@ohhwells/bridge 0.1.68 → 0.1.69-next.207
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 +2227 -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 +2219 -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,58 @@ 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
|
+
const parent = sections[0].parentElement;
|
|
8183
|
+
if (!parent) return;
|
|
8184
|
+
const anchor = sections[sections.length - 1].nextSibling;
|
|
8185
|
+
ordered.forEach((el) => parent.insertBefore(el, anchor));
|
|
8186
|
+
}
|
|
7596
8187
|
function getPageSectionOrderEntries(raw, currentPath) {
|
|
7597
8188
|
if (!raw) return [];
|
|
7598
8189
|
try {
|
|
@@ -7630,6 +8221,7 @@ function initSectionInstancesFromContent(content, currentPath) {
|
|
|
7630
8221
|
rekeySectionSubtree(clone, entry.instanceId);
|
|
7631
8222
|
original.insertAdjacentElement("afterend", clone);
|
|
7632
8223
|
}
|
|
8224
|
+
applyPersistedOrder(entries);
|
|
7633
8225
|
}
|
|
7634
8226
|
|
|
7635
8227
|
// src/OhhwellsBridge.tsx
|
|
@@ -10174,8 +10766,13 @@ var GLYPH_SELECTOR = "svg, img";
|
|
|
10174
10766
|
function referenceBox(slot) {
|
|
10175
10767
|
const row = slot.closest("[data-ohw-socials-row]") ?? slot.closest("a")?.parentElement ?? null;
|
|
10176
10768
|
const neighbour = row ? Array.from(row.querySelectorAll('[data-ohw-editable="icon"]')).find((el) => el !== slot) : null;
|
|
10177
|
-
|
|
10178
|
-
|
|
10769
|
+
if (neighbour) {
|
|
10770
|
+
const box2 = neighbour.querySelector(GLYPH_SELECTOR)?.getBoundingClientRect();
|
|
10771
|
+
if (box2?.width && box2.height) return box2;
|
|
10772
|
+
}
|
|
10773
|
+
const own = slot.getBoundingClientRect();
|
|
10774
|
+
if (own.width && own.height) return own;
|
|
10775
|
+
const box = slot.querySelector(GLYPH_SELECTOR)?.getBoundingClientRect() ?? null;
|
|
10179
10776
|
return box?.width && box.height ? box : null;
|
|
10180
10777
|
}
|
|
10181
10778
|
function iconMarkupSizedFor(slot, markup) {
|
|
@@ -10254,7 +10851,8 @@ function findSocialsRow(el) {
|
|
|
10254
10851
|
}
|
|
10255
10852
|
function isSocialsRow(el) {
|
|
10256
10853
|
const anchors = Array.from(el.querySelectorAll("a"));
|
|
10257
|
-
|
|
10854
|
+
if (!anchors.length || !anchors.some((anchor) => isSocialItem(anchor))) return false;
|
|
10855
|
+
return findSocialsRow(anchors[0]) === el;
|
|
10258
10856
|
}
|
|
10259
10857
|
var MAX_SOCIAL_ITEMS_PER_ROW = 7;
|
|
10260
10858
|
function canAddSocialItem(row) {
|
|
@@ -10292,6 +10890,7 @@ function markSocialsRows(root = document) {
|
|
|
10292
10890
|
});
|
|
10293
10891
|
listSocialsRows(root).forEach((row) => {
|
|
10294
10892
|
row.setAttribute(SOCIALS_ROW_ATTR, "");
|
|
10893
|
+
allowRowToWrap(row);
|
|
10295
10894
|
const items = listSocialItems(row);
|
|
10296
10895
|
const firstUnit = items[0] ? socialRowUnit(items[0], row) : null;
|
|
10297
10896
|
if (firstUnit) rowTemplates.set(rowKeyOf(row), firstUnit.outerHTML);
|
|
@@ -10586,7 +11185,29 @@ function applySocialsDisplayToRow(row, display) {
|
|
|
10586
11185
|
const icon = item.querySelector(ICON_SELECTOR);
|
|
10587
11186
|
if (label) label.style.display = display.text ? "" : "none";
|
|
10588
11187
|
if (icon) icon.style.display = display.icon ? "" : "none";
|
|
11188
|
+
layOutIconAndLabel(item, Boolean(display.text && display.icon));
|
|
10589
11189
|
});
|
|
11190
|
+
allowRowToWrap(row);
|
|
11191
|
+
}
|
|
11192
|
+
function layOutIconAndLabel(item, on) {
|
|
11193
|
+
const hasBoth = Boolean(item.querySelector(ICON_SELECTOR)) && Boolean(socialLabelElement(item));
|
|
11194
|
+
if (!hasBoth) {
|
|
11195
|
+
item.style.display = "";
|
|
11196
|
+
item.style.alignItems = "";
|
|
11197
|
+
item.style.gap = "";
|
|
11198
|
+
item.style.whiteSpace = "";
|
|
11199
|
+
item.style.flex = "";
|
|
11200
|
+
return;
|
|
11201
|
+
}
|
|
11202
|
+
item.style.display = on ? "inline-flex" : "";
|
|
11203
|
+
item.style.alignItems = on ? "center" : "";
|
|
11204
|
+
item.style.gap = on ? "8px" : "";
|
|
11205
|
+
item.style.whiteSpace = on ? "nowrap" : "";
|
|
11206
|
+
item.style.flex = on ? "0 0 auto" : "";
|
|
11207
|
+
}
|
|
11208
|
+
function allowRowToWrap(row) {
|
|
11209
|
+
const display = row.ownerDocument.defaultView?.getComputedStyle(row).display ?? "";
|
|
11210
|
+
if (display === "flex" || display === "inline-flex") row.style.flexWrap = "wrap";
|
|
10590
11211
|
}
|
|
10591
11212
|
function applySocialsDisplayFromContent(content, root = document) {
|
|
10592
11213
|
const stored = parseSocialsDisplay(content[SOCIALS_DISPLAY_KEY]);
|
|
@@ -11796,6 +12417,7 @@ function readLogoSizeState(content, placement) {
|
|
|
11796
12417
|
function getLogoElement(el) {
|
|
11797
12418
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
11798
12419
|
if (marked) return marked;
|
|
12420
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
11799
12421
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
11800
12422
|
if (!root) return null;
|
|
11801
12423
|
const anchor = el.closest("a");
|
|
@@ -12675,101 +13297,428 @@ function useNavItemDrag({
|
|
|
12675
13297
|
};
|
|
12676
13298
|
}
|
|
12677
13299
|
|
|
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
|
-
}
|
|
13300
|
+
// src/useSectionDrag.ts
|
|
13301
|
+
import { useCallback as useCallback7, useEffect as useEffect11, useRef as useRef9, useState as useState10 } from "react";
|
|
12728
13302
|
|
|
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];
|
|
13303
|
+
// src/lib/section-dnd.ts
|
|
13304
|
+
function isFooterSection(el) {
|
|
13305
|
+
return el.dataset.ohwSection === "footer";
|
|
12742
13306
|
}
|
|
12743
|
-
function
|
|
12744
|
-
|
|
12745
|
-
|
|
13307
|
+
function buildSectionDropSlots(draggedInstanceId) {
|
|
13308
|
+
const sections = topLevelSections().filter(
|
|
13309
|
+
(el) => instanceIdOf(el) !== draggedInstanceId && !isFooterSection(el)
|
|
12746
13310
|
);
|
|
13311
|
+
const slots = [];
|
|
13312
|
+
if (sections.length === 0) return slots;
|
|
13313
|
+
const left = 0;
|
|
13314
|
+
const width = document.documentElement.clientWidth;
|
|
13315
|
+
for (let i = 0; i <= sections.length; i++) {
|
|
13316
|
+
let y;
|
|
13317
|
+
if (i === 0) {
|
|
13318
|
+
y = sections[0].getBoundingClientRect().top;
|
|
13319
|
+
} else if (i === sections.length) {
|
|
13320
|
+
y = sections[sections.length - 1].getBoundingClientRect().bottom;
|
|
13321
|
+
} else {
|
|
13322
|
+
const prev = sections[i - 1].getBoundingClientRect();
|
|
13323
|
+
const next = sections[i].getBoundingClientRect();
|
|
13324
|
+
y = (prev.bottom + next.top) / 2;
|
|
13325
|
+
}
|
|
13326
|
+
slots.push({ insertIndex: i, y, left, width });
|
|
13327
|
+
}
|
|
13328
|
+
return slots;
|
|
12747
13329
|
}
|
|
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 [];
|
|
13330
|
+
function hitTestSectionDropSlot(y, slots) {
|
|
13331
|
+
let best = null;
|
|
13332
|
+
for (const slot of slots) {
|
|
13333
|
+
const dist = Math.abs(y - slot.y);
|
|
13334
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
12759
13335
|
}
|
|
13336
|
+
return best?.slot ?? null;
|
|
12760
13337
|
}
|
|
12761
|
-
|
|
12762
|
-
|
|
12763
|
-
|
|
12764
|
-
|
|
12765
|
-
|
|
12766
|
-
|
|
12767
|
-
|
|
12768
|
-
|
|
12769
|
-
|
|
13338
|
+
|
|
13339
|
+
// src/useSectionDrag.ts
|
|
13340
|
+
var PRESS_THRESHOLD = 10;
|
|
13341
|
+
var EDGE_ZONE = 60;
|
|
13342
|
+
var MAX_AUTO_SCROLL_SPEED = 18;
|
|
13343
|
+
var SECTION_DRAG_EXCLUDED_SELECTOR = [
|
|
13344
|
+
"[data-ohw-toolbar]",
|
|
13345
|
+
"[data-ohw-edit-chrome]",
|
|
13346
|
+
"[data-ohw-item-interaction]",
|
|
13347
|
+
"[data-ohw-drag-handle-container]",
|
|
13348
|
+
'[data-slot="drag-handle"]',
|
|
13349
|
+
"[data-ohw-item-toolbar-anchor]",
|
|
13350
|
+
"[data-ohw-item-drag-surface]",
|
|
13351
|
+
"[data-ohw-more-menu]",
|
|
13352
|
+
'[data-slot="dropdown-menu-content"]',
|
|
13353
|
+
'[data-slot="dropdown-menu-item"]',
|
|
13354
|
+
"[data-ohw-state-toggle]",
|
|
13355
|
+
"[data-ohw-max-badge]",
|
|
13356
|
+
"[data-ohw-floating-panel]",
|
|
13357
|
+
"[data-ohw-section-picker]",
|
|
13358
|
+
"[data-ohw-link-popover-root]",
|
|
13359
|
+
"[data-ohw-link-modal-root]",
|
|
13360
|
+
"[data-ohw-link-page-dropdown]",
|
|
13361
|
+
'[data-slot="popover-content"]',
|
|
13362
|
+
'[data-slot="dialog-content"]',
|
|
13363
|
+
'[data-slot="dialog-overlay"]',
|
|
13364
|
+
"[data-ohw-ai-review]",
|
|
13365
|
+
"[data-ohw-editable]",
|
|
13366
|
+
"[data-ohw-editable-state]",
|
|
13367
|
+
"[contenteditable]",
|
|
13368
|
+
"[data-ohw-href-key]",
|
|
13369
|
+
"[data-ohw-footer-col]",
|
|
13370
|
+
"[data-ohw-social-label]",
|
|
13371
|
+
"a",
|
|
13372
|
+
"button",
|
|
13373
|
+
'[role="button"]',
|
|
13374
|
+
'[data-ohw-role="navbar-button"]',
|
|
13375
|
+
'[data-ohw-role="button"]',
|
|
13376
|
+
"[data-ohw-carousel]",
|
|
13377
|
+
"[data-ohw-carousel-value]",
|
|
13378
|
+
"[data-ohw-carousel-slide]",
|
|
13379
|
+
"[data-ohw-carousel-overlay]",
|
|
13380
|
+
"[data-ohw-media-chrome]",
|
|
13381
|
+
"[data-ohw-media-overlay]",
|
|
13382
|
+
"[data-ohw-media-skeleton]"
|
|
13383
|
+
].join(", ");
|
|
13384
|
+
function visibleClip(ps) {
|
|
13385
|
+
if (!ps) return null;
|
|
13386
|
+
const top = Math.max(0, ps.headerH - ps.iframeOffsetTop);
|
|
13387
|
+
const bottom = Math.min(window.innerHeight, ps.headerH + ps.canvasH - ps.iframeOffsetTop);
|
|
13388
|
+
return { top, bottom: Math.max(top, bottom) };
|
|
12770
13389
|
}
|
|
12771
|
-
function
|
|
12772
|
-
|
|
13390
|
+
function useSectionDrag({
|
|
13391
|
+
isEditMode,
|
|
13392
|
+
editContentRef,
|
|
13393
|
+
postToParentRef,
|
|
13394
|
+
parentScrollRef,
|
|
13395
|
+
navDragRef,
|
|
13396
|
+
footerDragRef,
|
|
13397
|
+
suppressNextClickRef,
|
|
13398
|
+
suppressClickUntilRef
|
|
13399
|
+
}) {
|
|
13400
|
+
const sectionDragRef = useRef9(null);
|
|
13401
|
+
const [sectionDropSlots, setSectionDropSlots] = useState10([]);
|
|
13402
|
+
const [activeSectionDropIndex, setActiveSectionDropIndex] = useState10(null);
|
|
13403
|
+
const [isSectionDragging, setIsSectionDragging] = useState10(false);
|
|
13404
|
+
const sectionPointerDragRef = useRef9(null);
|
|
13405
|
+
const autoScrollRafRef = useRef9(null);
|
|
13406
|
+
const autoScrollDeltaRef = useRef9(0);
|
|
13407
|
+
const stopAutoScroll = useCallback7(() => {
|
|
13408
|
+
if (autoScrollRafRef.current != null) {
|
|
13409
|
+
cancelAnimationFrame(autoScrollRafRef.current);
|
|
13410
|
+
autoScrollRafRef.current = null;
|
|
13411
|
+
}
|
|
13412
|
+
autoScrollDeltaRef.current = 0;
|
|
13413
|
+
}, []);
|
|
13414
|
+
const tickAutoScroll = useCallback7(() => {
|
|
13415
|
+
if (!sectionDragRef.current) {
|
|
13416
|
+
stopAutoScroll();
|
|
13417
|
+
return;
|
|
13418
|
+
}
|
|
13419
|
+
if (autoScrollDeltaRef.current !== 0) {
|
|
13420
|
+
postToParentRef.current({ type: "ow:request-scroll", deltaY: autoScrollDeltaRef.current });
|
|
13421
|
+
}
|
|
13422
|
+
autoScrollRafRef.current = requestAnimationFrame(tickAutoScroll);
|
|
13423
|
+
}, [postToParentRef, stopAutoScroll]);
|
|
13424
|
+
const updateAutoScroll = useCallback7(
|
|
13425
|
+
(clientY) => {
|
|
13426
|
+
const clip = visibleClip(parentScrollRef.current);
|
|
13427
|
+
let delta = 0;
|
|
13428
|
+
if (clip) {
|
|
13429
|
+
const distTop = clientY - clip.top;
|
|
13430
|
+
const distBottom = clip.bottom - clientY;
|
|
13431
|
+
if (distTop >= 0 && distTop < EDGE_ZONE) {
|
|
13432
|
+
delta = -MAX_AUTO_SCROLL_SPEED * (1 - distTop / EDGE_ZONE);
|
|
13433
|
+
} else if (distBottom >= 0 && distBottom < EDGE_ZONE) {
|
|
13434
|
+
delta = MAX_AUTO_SCROLL_SPEED * (1 - distBottom / EDGE_ZONE);
|
|
13435
|
+
}
|
|
13436
|
+
}
|
|
13437
|
+
autoScrollDeltaRef.current = delta;
|
|
13438
|
+
if (delta !== 0 && autoScrollRafRef.current == null) {
|
|
13439
|
+
autoScrollRafRef.current = requestAnimationFrame(tickAutoScroll);
|
|
13440
|
+
} else if (delta === 0) {
|
|
13441
|
+
stopAutoScroll();
|
|
13442
|
+
}
|
|
13443
|
+
},
|
|
13444
|
+
[parentScrollRef, stopAutoScroll, tickAutoScroll]
|
|
13445
|
+
);
|
|
13446
|
+
const clearSectionDragVisuals = useCallback7(() => {
|
|
13447
|
+
sectionDragRef.current?.draggedEl.removeAttribute("data-ohw-section-dragging");
|
|
13448
|
+
sectionDragRef.current = null;
|
|
13449
|
+
setSectionDropSlots([]);
|
|
13450
|
+
setActiveSectionDropIndex(null);
|
|
13451
|
+
setIsSectionDragging(false);
|
|
13452
|
+
stopAutoScroll();
|
|
13453
|
+
document.documentElement.removeAttribute("data-ohw-section-dragging-root");
|
|
13454
|
+
unlockItemDragInteraction();
|
|
13455
|
+
}, [stopAutoScroll]);
|
|
13456
|
+
const refreshSectionDragVisuals = useCallback7(
|
|
13457
|
+
(session, clientX, clientY) => {
|
|
13458
|
+
session.lastClientX = clientX;
|
|
13459
|
+
session.lastClientY = clientY;
|
|
13460
|
+
const slots = buildSectionDropSlots(session.instanceId);
|
|
13461
|
+
const activeSlot = hitTestSectionDropSlot(clientY, slots);
|
|
13462
|
+
session.activeSlot = activeSlot;
|
|
13463
|
+
setSectionDropSlots(slots);
|
|
13464
|
+
const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
13465
|
+
setActiveSectionDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
13466
|
+
updateAutoScroll(clientY);
|
|
13467
|
+
},
|
|
13468
|
+
[updateAutoScroll]
|
|
13469
|
+
);
|
|
13470
|
+
const beginSectionDrag = useCallback7(
|
|
13471
|
+
(session) => {
|
|
13472
|
+
sectionDragRef.current = session;
|
|
13473
|
+
setIsSectionDragging(true);
|
|
13474
|
+
lockItemDuringDrag();
|
|
13475
|
+
document.documentElement.setAttribute("data-ohw-section-dragging-root", "");
|
|
13476
|
+
session.draggedEl.setAttribute("data-ohw-section-dragging", "");
|
|
13477
|
+
refreshSectionDragVisuals(session, session.lastClientX, session.lastClientY);
|
|
13478
|
+
},
|
|
13479
|
+
[refreshSectionDragVisuals]
|
|
13480
|
+
);
|
|
13481
|
+
const commitSectionDrag = useCallback7(() => {
|
|
13482
|
+
const session = sectionDragRef.current;
|
|
13483
|
+
if (!session) {
|
|
13484
|
+
clearSectionDragVisuals();
|
|
13485
|
+
return;
|
|
13486
|
+
}
|
|
13487
|
+
const slot = session.activeSlot ?? hitTestSectionDropSlot(session.lastClientY, buildSectionDropSlots(session.instanceId));
|
|
13488
|
+
const entries = slot ? planSectionMove(session.instanceId, slot.insertIndex, window.location.pathname) : null;
|
|
13489
|
+
if (!entries) {
|
|
13490
|
+
clearSectionDragVisuals();
|
|
13491
|
+
return;
|
|
13492
|
+
}
|
|
13493
|
+
const orderJson = JSON.stringify(entries);
|
|
13494
|
+
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
13495
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
13496
|
+
applyPersistedOrder(entries);
|
|
13497
|
+
clearSectionDragVisuals();
|
|
13498
|
+
requestAnimationFrame(() => {
|
|
13499
|
+
if (editContentRef.current[SECTION_ORDER_KEY] === orderJson) {
|
|
13500
|
+
applyPersistedOrder(entries);
|
|
13501
|
+
}
|
|
13502
|
+
requestAnimationFrame(() => {
|
|
13503
|
+
window.dispatchEvent(new Event("resize"));
|
|
13504
|
+
});
|
|
13505
|
+
});
|
|
13506
|
+
}, [clearSectionDragVisuals, editContentRef, postToParentRef]);
|
|
13507
|
+
const startSectionPressDrag = useCallback7(
|
|
13508
|
+
(el, clientX, clientY, pointerId) => {
|
|
13509
|
+
if (navDragRef.current || footerDragRef.current || sectionDragRef.current) return false;
|
|
13510
|
+
const instanceId = instanceIdOf(el);
|
|
13511
|
+
if (!instanceId) return false;
|
|
13512
|
+
sectionPointerDragRef.current = {
|
|
13513
|
+
el,
|
|
13514
|
+
instanceId,
|
|
13515
|
+
startX: clientX,
|
|
13516
|
+
startY: clientY,
|
|
13517
|
+
pointerId,
|
|
13518
|
+
started: false
|
|
13519
|
+
};
|
|
13520
|
+
return true;
|
|
13521
|
+
},
|
|
13522
|
+
[footerDragRef, navDragRef]
|
|
13523
|
+
);
|
|
13524
|
+
useEffect11(() => {
|
|
13525
|
+
if (!isEditMode) return;
|
|
13526
|
+
const onPointerDown = (e) => {
|
|
13527
|
+
if (e.button !== 0) return;
|
|
13528
|
+
if (navDragRef.current || footerDragRef.current || sectionDragRef.current) return;
|
|
13529
|
+
if (sectionPointerDragRef.current) return;
|
|
13530
|
+
const target = e.target;
|
|
13531
|
+
if (!(target instanceof HTMLElement)) return;
|
|
13532
|
+
if (target.closest(SECTION_DRAG_EXCLUDED_SELECTOR)) return;
|
|
13533
|
+
const sectionEl = target.closest("[data-ohw-section]");
|
|
13534
|
+
if (!sectionEl || isChromeSection(sectionEl) || sectionEl.dataset.ohwSection === "footer") return;
|
|
13535
|
+
if (!topLevelSections().includes(sectionEl)) return;
|
|
13536
|
+
startSectionPressDrag(sectionEl, e.clientX, e.clientY, e.pointerId);
|
|
13537
|
+
};
|
|
13538
|
+
const onPointerMove = (e) => {
|
|
13539
|
+
const pending = sectionPointerDragRef.current;
|
|
13540
|
+
if (!pending) return;
|
|
13541
|
+
if (pending.started) {
|
|
13542
|
+
e.preventDefault();
|
|
13543
|
+
clearTextSelection();
|
|
13544
|
+
const session = sectionDragRef.current;
|
|
13545
|
+
if (!session) return;
|
|
13546
|
+
refreshSectionDragVisuals(session, e.clientX, e.clientY);
|
|
13547
|
+
return;
|
|
13548
|
+
}
|
|
13549
|
+
const dx = e.clientX - pending.startX;
|
|
13550
|
+
const dy = e.clientY - pending.startY;
|
|
13551
|
+
if (dx * dx + dy * dy < PRESS_THRESHOLD * PRESS_THRESHOLD) return;
|
|
13552
|
+
e.preventDefault();
|
|
13553
|
+
pending.started = true;
|
|
13554
|
+
armItemPressDrag();
|
|
13555
|
+
clearTextSelection();
|
|
13556
|
+
try {
|
|
13557
|
+
document.body.setPointerCapture(pending.pointerId);
|
|
13558
|
+
} catch {
|
|
13559
|
+
}
|
|
13560
|
+
beginSectionDrag({
|
|
13561
|
+
instanceId: pending.instanceId,
|
|
13562
|
+
draggedEl: pending.el,
|
|
13563
|
+
lastClientX: e.clientX,
|
|
13564
|
+
lastClientY: e.clientY,
|
|
13565
|
+
activeSlot: null
|
|
13566
|
+
});
|
|
13567
|
+
};
|
|
13568
|
+
const endPointerDrag = (e) => {
|
|
13569
|
+
const pending = sectionPointerDragRef.current;
|
|
13570
|
+
sectionPointerDragRef.current = null;
|
|
13571
|
+
try {
|
|
13572
|
+
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
13573
|
+
document.body.releasePointerCapture(e.pointerId);
|
|
13574
|
+
}
|
|
13575
|
+
} catch {
|
|
13576
|
+
}
|
|
13577
|
+
if (!pending) return;
|
|
13578
|
+
if (!pending.started) {
|
|
13579
|
+
unlockItemDragInteraction();
|
|
13580
|
+
return;
|
|
13581
|
+
}
|
|
13582
|
+
suppressNextClickRef.current = true;
|
|
13583
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
13584
|
+
commitSectionDrag();
|
|
13585
|
+
};
|
|
13586
|
+
const onKeyDown = (e) => {
|
|
13587
|
+
if (e.key !== "Escape") return;
|
|
13588
|
+
if (!sectionDragRef.current && !sectionPointerDragRef.current) return;
|
|
13589
|
+
sectionPointerDragRef.current = null;
|
|
13590
|
+
clearSectionDragVisuals();
|
|
13591
|
+
};
|
|
13592
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
13593
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
13594
|
+
document.addEventListener("pointerup", endPointerDrag, true);
|
|
13595
|
+
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
13596
|
+
document.addEventListener("keydown", onKeyDown, true);
|
|
13597
|
+
return () => {
|
|
13598
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
13599
|
+
document.removeEventListener("pointermove", onPointerMove, true);
|
|
13600
|
+
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
13601
|
+
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
13602
|
+
document.removeEventListener("keydown", onKeyDown, true);
|
|
13603
|
+
unlockItemDragInteraction();
|
|
13604
|
+
stopAutoScroll();
|
|
13605
|
+
};
|
|
13606
|
+
}, [
|
|
13607
|
+
beginSectionDrag,
|
|
13608
|
+
clearSectionDragVisuals,
|
|
13609
|
+
commitSectionDrag,
|
|
13610
|
+
footerDragRef,
|
|
13611
|
+
isEditMode,
|
|
13612
|
+
navDragRef,
|
|
13613
|
+
refreshSectionDragVisuals,
|
|
13614
|
+
startSectionPressDrag,
|
|
13615
|
+
stopAutoScroll,
|
|
13616
|
+
suppressClickUntilRef,
|
|
13617
|
+
suppressNextClickRef
|
|
13618
|
+
]);
|
|
13619
|
+
return {
|
|
13620
|
+
sectionDragRef,
|
|
13621
|
+
sectionDropSlots,
|
|
13622
|
+
activeSectionDropIndex,
|
|
13623
|
+
isSectionDragging
|
|
13624
|
+
};
|
|
13625
|
+
}
|
|
13626
|
+
|
|
13627
|
+
// src/ui/footer-container-chrome.tsx
|
|
13628
|
+
import { Plus as Plus2 } from "lucide-react";
|
|
13629
|
+
import { jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
13630
|
+
function FooterContainerChrome({
|
|
13631
|
+
rect,
|
|
13632
|
+
onAdd,
|
|
13633
|
+
addDisabled = false
|
|
13634
|
+
}) {
|
|
13635
|
+
const chromeGap = 6;
|
|
13636
|
+
const buttonMargin = 7;
|
|
13637
|
+
return /* @__PURE__ */ jsx29(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsx29(
|
|
13638
|
+
"div",
|
|
13639
|
+
{
|
|
13640
|
+
"data-ohw-footer-container-chrome": "",
|
|
13641
|
+
"data-ohw-bridge": "",
|
|
13642
|
+
className: "pointer-events-none fixed z-[2147483647]",
|
|
13643
|
+
style: {
|
|
13644
|
+
top: rect.top - chromeGap,
|
|
13645
|
+
left: rect.left - chromeGap,
|
|
13646
|
+
width: rect.width + chromeGap * 2,
|
|
13647
|
+
height: rect.height + chromeGap * 2
|
|
13648
|
+
},
|
|
13649
|
+
children: /* @__PURE__ */ jsxs19(Tooltip, { children: [
|
|
13650
|
+
/* @__PURE__ */ jsx29(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx29(
|
|
13651
|
+
"button",
|
|
13652
|
+
{
|
|
13653
|
+
type: "button",
|
|
13654
|
+
"data-ohw-footer-add-button": "",
|
|
13655
|
+
disabled: addDisabled,
|
|
13656
|
+
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",
|
|
13657
|
+
style: { top: chromeGap - buttonMargin },
|
|
13658
|
+
"aria-label": "Add item",
|
|
13659
|
+
onMouseDown: (e) => {
|
|
13660
|
+
e.preventDefault();
|
|
13661
|
+
e.stopPropagation();
|
|
13662
|
+
},
|
|
13663
|
+
onClick: (e) => {
|
|
13664
|
+
e.preventDefault();
|
|
13665
|
+
e.stopPropagation();
|
|
13666
|
+
if (addDisabled) return;
|
|
13667
|
+
onAdd();
|
|
13668
|
+
},
|
|
13669
|
+
children: /* @__PURE__ */ jsx29(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
13670
|
+
}
|
|
13671
|
+
) }),
|
|
13672
|
+
/* @__PURE__ */ jsx29(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
|
|
13673
|
+
] })
|
|
13674
|
+
}
|
|
13675
|
+
) });
|
|
13676
|
+
}
|
|
13677
|
+
|
|
13678
|
+
// src/lib/carousel.ts
|
|
13679
|
+
import { useEffect as useEffect12, useState as useState11 } from "react";
|
|
13680
|
+
var CAROUSEL_ATTR = "data-ohw-carousel";
|
|
13681
|
+
var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
|
|
13682
|
+
var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
|
|
13683
|
+
var CAROUSEL_EVENT = "ohw:carousel-change";
|
|
13684
|
+
function listCarouselKeys() {
|
|
13685
|
+
const keys = /* @__PURE__ */ new Set();
|
|
13686
|
+
document.querySelectorAll(`[${CAROUSEL_ATTR}]`).forEach((el) => {
|
|
13687
|
+
const key = el.getAttribute("data-ohw-key");
|
|
13688
|
+
if (key) keys.add(key);
|
|
13689
|
+
});
|
|
13690
|
+
return [...keys];
|
|
13691
|
+
}
|
|
13692
|
+
function containersForKey(key) {
|
|
13693
|
+
return Array.from(
|
|
13694
|
+
document.querySelectorAll(`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`)
|
|
13695
|
+
);
|
|
13696
|
+
}
|
|
13697
|
+
function isCarouselKey(key) {
|
|
13698
|
+
return containersForKey(key).length > 0;
|
|
13699
|
+
}
|
|
13700
|
+
function parseSlides(raw) {
|
|
13701
|
+
if (!raw) return [];
|
|
13702
|
+
try {
|
|
13703
|
+
const parsed = JSON.parse(raw);
|
|
13704
|
+
if (!Array.isArray(parsed)) return [];
|
|
13705
|
+
return parsed.filter((s) => Boolean(s) && typeof s === "object").map((s) => ({ src: String(s.src ?? ""), alt: String(s.alt ?? "") }));
|
|
13706
|
+
} catch {
|
|
13707
|
+
return [];
|
|
13708
|
+
}
|
|
13709
|
+
}
|
|
13710
|
+
function readCarouselValue(key) {
|
|
13711
|
+
const container = containersForKey(key)[0];
|
|
13712
|
+
if (!container) return [];
|
|
13713
|
+
const fromAttr = parseSlides(container.getAttribute(CAROUSEL_VALUE_ATTR));
|
|
13714
|
+
if (fromAttr.length > 0) return fromAttr;
|
|
13715
|
+
return Array.from(container.querySelectorAll(`[${CAROUSEL_SLIDE_ATTR}]`)).filter((slide) => slide.closest(`[${CAROUSEL_ATTR}]`) === container).sort((a, b) => slideIndex(a) - slideIndex(b)).map((slide) => {
|
|
13716
|
+
const img = slide instanceof HTMLImageElement ? slide : slide.querySelector("img");
|
|
13717
|
+
return { src: img?.src ?? "", alt: img?.alt ?? "" };
|
|
13718
|
+
});
|
|
13719
|
+
}
|
|
13720
|
+
function slideIndex(el) {
|
|
13721
|
+
const raw = el.getAttribute(CAROUSEL_SLIDE_ATTR);
|
|
12773
13722
|
const n = raw ? parseInt(raw, 10) : NaN;
|
|
12774
13723
|
return Number.isFinite(n) ? n : 0;
|
|
12775
13724
|
}
|
|
@@ -12789,8 +13738,8 @@ function applyCarouselNode(key, val) {
|
|
|
12789
13738
|
return true;
|
|
12790
13739
|
}
|
|
12791
13740
|
function useOhwCarousel(key, initial) {
|
|
12792
|
-
const [images, setImages] =
|
|
12793
|
-
|
|
13741
|
+
const [images, setImages] = useState11(initial);
|
|
13742
|
+
useEffect12(() => {
|
|
12794
13743
|
const el = document.querySelector(
|
|
12795
13744
|
`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
|
|
12796
13745
|
);
|
|
@@ -12868,7 +13817,7 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
12868
13817
|
nodes.push({ key, type: "link", text: href });
|
|
12869
13818
|
}
|
|
12870
13819
|
if (extraContent) {
|
|
12871
|
-
for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY]) {
|
|
13820
|
+
for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY, SECTION_ORDER_KEY]) {
|
|
12872
13821
|
const text = extraContent[key];
|
|
12873
13822
|
if (typeof text === "string" && text.length > 0) {
|
|
12874
13823
|
nodes.push({ key, type: "meta", text });
|
|
@@ -12905,6 +13854,18 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
12905
13854
|
}
|
|
12906
13855
|
if (extraContent && !isScoped) {
|
|
12907
13856
|
applyNavFooterDeleteOverrides(byKey, extraContent);
|
|
13857
|
+
for (const key of LOGO_IMAGE_KEYS) {
|
|
13858
|
+
if (!(key in extraContent)) continue;
|
|
13859
|
+
byKey.set(key, { key, type: "image", text: extraContent[key] ?? "" });
|
|
13860
|
+
}
|
|
13861
|
+
for (const key of [LOGO_PLACEHOLDER_KEY, LOGO_ALT_KEY]) {
|
|
13862
|
+
if (!(key in extraContent)) continue;
|
|
13863
|
+
byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
|
|
13864
|
+
}
|
|
13865
|
+
for (const key of LOGO_SIZE_KEYS) {
|
|
13866
|
+
if (!(key in extraContent)) continue;
|
|
13867
|
+
byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
|
|
13868
|
+
}
|
|
12908
13869
|
}
|
|
12909
13870
|
return Array.from(byKey.values());
|
|
12910
13871
|
}
|
|
@@ -13309,6 +14270,7 @@ function fadeInImageElement(img, onReady) {
|
|
|
13309
14270
|
function applyEditableImageSrc(img, url) {
|
|
13310
14271
|
img.removeAttribute("srcset");
|
|
13311
14272
|
img.removeAttribute("sizes");
|
|
14273
|
+
if (img.loading === "lazy") img.loading = "eager";
|
|
13312
14274
|
img.src = url;
|
|
13313
14275
|
}
|
|
13314
14276
|
function fadeInBgImage(el, url, onReady) {
|
|
@@ -13373,21 +14335,10 @@ function parseSchedulingInsertAfter(insertAfter) {
|
|
|
13373
14335
|
insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
|
|
13374
14336
|
};
|
|
13375
14337
|
}
|
|
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;
|
|
14338
|
+
function resolveEntryAnchor(entry) {
|
|
14339
|
+
if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
|
|
14340
|
+
const parsed = parseSchedulingInsertAfter(entry.insertAfter);
|
|
14341
|
+
return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
|
|
13391
14342
|
}
|
|
13392
14343
|
function schedulingMountDepth(insertAfter) {
|
|
13393
14344
|
if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
|
|
@@ -13404,8 +14355,7 @@ function getPageSchedulingEntries(raw) {
|
|
|
13404
14355
|
}
|
|
13405
14356
|
}
|
|
13406
14357
|
function isSchedulingWidgetMissing(entry) {
|
|
13407
|
-
|
|
13408
|
-
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
|
|
14358
|
+
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
|
|
13409
14359
|
}
|
|
13410
14360
|
function hasMissingSchedulingWidgets(entries) {
|
|
13411
14361
|
return entries.some(isSchedulingWidgetMissing);
|
|
@@ -13435,16 +14385,17 @@ function initSectionsFromContent(content, removeExisting = false) {
|
|
|
13435
14385
|
} catch {
|
|
13436
14386
|
}
|
|
13437
14387
|
}
|
|
13438
|
-
function mountSchedulingWidget(
|
|
13439
|
-
const
|
|
13440
|
-
const sectionId = schedulingSectionId(
|
|
14388
|
+
function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
|
|
14389
|
+
const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
|
|
14390
|
+
const sectionId = schedulingSectionId(widgetId);
|
|
13441
14391
|
if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
|
|
13442
|
-
const
|
|
13443
|
-
if (!
|
|
14392
|
+
const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
|
|
14393
|
+
if (!anchorEl) return false;
|
|
14394
|
+
const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
13444
14395
|
const container = document.createElement("div");
|
|
13445
14396
|
container.dataset.ohwSectionContainer = "scheduling";
|
|
13446
|
-
if (
|
|
13447
|
-
const beforeAnchor = document.querySelector(`[data-ohw-section="${
|
|
14397
|
+
if (beforeId) {
|
|
14398
|
+
const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
|
|
13448
14399
|
const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
|
|
13449
14400
|
if (!beforePoint) return false;
|
|
13450
14401
|
beforePoint.insertAdjacentElement("beforebegin", container);
|
|
@@ -13455,19 +14406,25 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
13455
14406
|
}
|
|
13456
14407
|
tail.insertAdjacentElement("afterend", container);
|
|
13457
14408
|
}
|
|
13458
|
-
|
|
13459
|
-
|
|
13460
|
-
|
|
13461
|
-
|
|
13462
|
-
|
|
13463
|
-
|
|
13464
|
-
|
|
13465
|
-
|
|
13466
|
-
|
|
13467
|
-
|
|
13468
|
-
|
|
13469
|
-
|
|
13470
|
-
|
|
14409
|
+
try {
|
|
14410
|
+
const root = createRoot2(container);
|
|
14411
|
+
flushSync2(() => {
|
|
14412
|
+
root.render(
|
|
14413
|
+
/* @__PURE__ */ jsx33(
|
|
14414
|
+
SchedulingWidget,
|
|
14415
|
+
{
|
|
14416
|
+
notifyOnConnect,
|
|
14417
|
+
initialScheduleId: scheduleId,
|
|
14418
|
+
insertAfter: widgetId
|
|
14419
|
+
}
|
|
14420
|
+
)
|
|
14421
|
+
);
|
|
14422
|
+
});
|
|
14423
|
+
} catch (err) {
|
|
14424
|
+
console.error("[ow:scheduling] render threw", err);
|
|
14425
|
+
container.remove();
|
|
14426
|
+
return false;
|
|
14427
|
+
}
|
|
13471
14428
|
const tracker = getSectionsTracker();
|
|
13472
14429
|
let sections = [];
|
|
13473
14430
|
try {
|
|
@@ -13475,10 +14432,12 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
13475
14432
|
} catch {
|
|
13476
14433
|
}
|
|
13477
14434
|
const inEditor = typeof window !== "undefined" && window.self !== window.top;
|
|
13478
|
-
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter ===
|
|
14435
|
+
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
|
|
13479
14436
|
sections.push({
|
|
13480
14437
|
type: "scheduling",
|
|
13481
|
-
insertAfter:
|
|
14438
|
+
insertAfter: widgetId,
|
|
14439
|
+
anchorId,
|
|
14440
|
+
beforeId: beforeId ?? null,
|
|
13482
14441
|
pagePath: window.location.pathname,
|
|
13483
14442
|
...scheduleId ? { scheduleId } : {}
|
|
13484
14443
|
});
|
|
@@ -13492,7 +14451,8 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
13492
14451
|
for (let i = pending.length - 1; i >= 0; i--) {
|
|
13493
14452
|
const entry = pending[i];
|
|
13494
14453
|
const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
|
|
13495
|
-
|
|
14454
|
+
const { anchorId, beforeId } = resolveEntryAnchor(entry);
|
|
14455
|
+
if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
|
|
13496
14456
|
pending.splice(i, 1);
|
|
13497
14457
|
}
|
|
13498
14458
|
}
|
|
@@ -13640,6 +14600,13 @@ function isInsideLinkEditor(target) {
|
|
|
13640
14600
|
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
14601
|
);
|
|
13642
14602
|
}
|
|
14603
|
+
function isInsideFloatingPanel(target) {
|
|
14604
|
+
return Boolean(target.closest("[data-ohw-floating-panel]"));
|
|
14605
|
+
}
|
|
14606
|
+
function isPointOverFloatingPanel(clientX, clientY) {
|
|
14607
|
+
const el = document.elementFromPoint(clientX, clientY);
|
|
14608
|
+
return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
|
|
14609
|
+
}
|
|
13643
14610
|
function getHrefKeyFromElement(el) {
|
|
13644
14611
|
if (!el) return null;
|
|
13645
14612
|
const anchor = el.closest("[data-ohw-href-key]");
|
|
@@ -13885,7 +14852,7 @@ function getNavigationSelectionParent(el) {
|
|
|
13885
14852
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
13886
14853
|
return getFooterLinksContainer();
|
|
13887
14854
|
}
|
|
13888
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
14855
|
+
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
14856
|
return getNavigationRoot(el);
|
|
13890
14857
|
}
|
|
13891
14858
|
return null;
|
|
@@ -14478,6 +15445,45 @@ function StateToggle({
|
|
|
14478
15445
|
);
|
|
14479
15446
|
}
|
|
14480
15447
|
var contentCache = /* @__PURE__ */ new Map();
|
|
15448
|
+
var fetchedContentPaths = /* @__PURE__ */ new Set();
|
|
15449
|
+
var OHW_LOADER_STYLE = {
|
|
15450
|
+
position: "fixed",
|
|
15451
|
+
inset: 0,
|
|
15452
|
+
background: "#fff",
|
|
15453
|
+
zIndex: 2147483646,
|
|
15454
|
+
display: "flex",
|
|
15455
|
+
alignItems: "center",
|
|
15456
|
+
justifyContent: "center"
|
|
15457
|
+
};
|
|
15458
|
+
function OhwLoaderSpinner() {
|
|
15459
|
+
return /* @__PURE__ */ jsxs20("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", "aria-hidden": true, children: [
|
|
15460
|
+
/* @__PURE__ */ jsx33("circle", { cx: "14", cy: "14", r: "11", stroke: "#E7E5E4", strokeWidth: "3" }),
|
|
15461
|
+
/* @__PURE__ */ jsx33(
|
|
15462
|
+
"circle",
|
|
15463
|
+
{
|
|
15464
|
+
cx: "14",
|
|
15465
|
+
cy: "14",
|
|
15466
|
+
r: "11",
|
|
15467
|
+
stroke: "#1C1917",
|
|
15468
|
+
strokeWidth: "3",
|
|
15469
|
+
strokeDasharray: "17 52",
|
|
15470
|
+
strokeLinecap: "round",
|
|
15471
|
+
children: /* @__PURE__ */ jsx33(
|
|
15472
|
+
"animateTransform",
|
|
15473
|
+
{
|
|
15474
|
+
attributeName: "transform",
|
|
15475
|
+
type: "rotate",
|
|
15476
|
+
from: "0 14 14",
|
|
15477
|
+
to: "360 14 14",
|
|
15478
|
+
dur: "0.7s",
|
|
15479
|
+
repeatCount: "indefinite"
|
|
15480
|
+
}
|
|
15481
|
+
)
|
|
15482
|
+
}
|
|
15483
|
+
)
|
|
15484
|
+
] });
|
|
15485
|
+
}
|
|
15486
|
+
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
15487
|
function resolveSubdomain(subdomainFromQuery) {
|
|
14482
15488
|
if (subdomainFromQuery) return subdomainFromQuery;
|
|
14483
15489
|
if (typeof window !== "undefined") {
|
|
@@ -14500,8 +15506,8 @@ function OhhwellsBridge() {
|
|
|
14500
15506
|
const router = useRouter3();
|
|
14501
15507
|
const searchParams = useSearchParams();
|
|
14502
15508
|
const isEditMode = isEditSessionActive();
|
|
14503
|
-
const [bridgeRoot, setBridgeRoot] =
|
|
14504
|
-
|
|
15509
|
+
const [bridgeRoot, setBridgeRoot] = useState12(null);
|
|
15510
|
+
useEffect13(() => {
|
|
14505
15511
|
const figtreeFontId = "ohw-figtree-font";
|
|
14506
15512
|
if (!document.getElementById(figtreeFontId)) {
|
|
14507
15513
|
const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
|
|
@@ -14530,86 +15536,150 @@ function OhhwellsBridge() {
|
|
|
14530
15536
|
const subdomain = resolveSubdomain(subdomainFromQuery);
|
|
14531
15537
|
useLinkHrefGuardian(pathname, subdomain, isEditMode);
|
|
14532
15538
|
useSavedLinkNavigation(isEditMode);
|
|
14533
|
-
const postToParent2 =
|
|
15539
|
+
const postToParent2 = useCallback8((data) => {
|
|
14534
15540
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
14535
15541
|
window.parent.postMessage(data, "*");
|
|
14536
15542
|
}
|
|
14537
15543
|
}, []);
|
|
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 =
|
|
15544
|
+
const [fetchState, setFetchState] = useState12("idle");
|
|
15545
|
+
const autoSaveTimers = useRef10(/* @__PURE__ */ new Map());
|
|
15546
|
+
const activeElRef = useRef10(null);
|
|
15547
|
+
const pointerHeldRef = useRef10(false);
|
|
15548
|
+
const selectedElRef = useRef10(null);
|
|
15549
|
+
const selectedHrefKeyRef = useRef10(null);
|
|
15550
|
+
const selectedFooterColAttrRef = useRef10(null);
|
|
15551
|
+
const originalContentRef = useRef10(null);
|
|
15552
|
+
const activeStateElRef = useRef10(null);
|
|
15553
|
+
const parentScrollRef = useRef10(null);
|
|
15554
|
+
const visibleViewportRef = useRef10(null);
|
|
15555
|
+
const [dialogPortalContainer, setDialogPortalContainer] = useState12(null);
|
|
15556
|
+
const attachVisibleViewport = useCallback8((node) => {
|
|
14551
15557
|
visibleViewportRef.current = node;
|
|
14552
15558
|
setDialogPortalContainer(node);
|
|
14553
15559
|
if (node) applyVisibleViewport(node, parentScrollRef.current);
|
|
14554
15560
|
}, []);
|
|
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
|
-
|
|
15561
|
+
const toolbarElRef = useRef10(null);
|
|
15562
|
+
const glowElRef = useRef10(null);
|
|
15563
|
+
const hoveredImageRef = useRef10(null);
|
|
15564
|
+
const hoveredImageHasTextOverlapRef = useRef10(false);
|
|
15565
|
+
const dragOverElRef = useRef10(null);
|
|
15566
|
+
const [mediaHover, setMediaHover] = useState12(null);
|
|
15567
|
+
const [selectedMedia, setSelectedMedia] = useState12(null);
|
|
15568
|
+
const selectedMediaElRef = useRef10(null);
|
|
15569
|
+
const clearMediaSelection = useCallback8(() => {
|
|
15570
|
+
const prev = selectedMediaElRef.current;
|
|
15571
|
+
selectedMediaElRef.current = null;
|
|
15572
|
+
setSelectedMedia(null);
|
|
15573
|
+
const sectionEl = prev?.closest("[data-ohw-section]") ?? null;
|
|
15574
|
+
if (sectionEl) {
|
|
15575
|
+
postToParentRef.current({
|
|
15576
|
+
type: "ow:section-selected",
|
|
15577
|
+
sectionId: sectionEl.dataset.ohwSection ?? null,
|
|
15578
|
+
sectionLabel: sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? ""),
|
|
15579
|
+
key: null
|
|
15580
|
+
});
|
|
15581
|
+
}
|
|
15582
|
+
}, []);
|
|
15583
|
+
const clearMediaSelectionRef = useRef10(clearMediaSelection);
|
|
15584
|
+
clearMediaSelectionRef.current = clearMediaSelection;
|
|
15585
|
+
const selectMediaElement = useCallback8((el) => {
|
|
15586
|
+
const r2 = el.getBoundingClientRect();
|
|
15587
|
+
const video = el.dataset.ohwEditable === "video" ? el.querySelector("video") : null;
|
|
15588
|
+
selectedMediaElRef.current = el;
|
|
15589
|
+
setSelectedMedia({
|
|
15590
|
+
key: el.dataset.ohwKey ?? "",
|
|
15591
|
+
rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
|
|
15592
|
+
elementType: el.dataset.ohwEditable ?? "image",
|
|
15593
|
+
hasTextOverlap: false,
|
|
15594
|
+
isDragOver: false,
|
|
15595
|
+
...video ? { videoAutoplay: video.autoplay, videoMuted: video.muted } : {}
|
|
15596
|
+
});
|
|
15597
|
+
const sectionEl = el.closest("[data-ohw-section]");
|
|
15598
|
+
aiSectionApiRef.current?.selectFromElement(el, { report: false });
|
|
15599
|
+
postToParentRef.current({
|
|
15600
|
+
type: "ow:section-selected",
|
|
15601
|
+
sectionId: sectionEl?.dataset.ohwSection ?? null,
|
|
15602
|
+
sectionLabel: sectionEl ? sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? "") : null,
|
|
15603
|
+
key: el.dataset.ohwKey ?? null,
|
|
15604
|
+
// Display name for the pill — the raw key prettifies into fragments ("Img"); the
|
|
15605
|
+
// bridge knows what the node IS, so it names it.
|
|
15606
|
+
keyLabel: el.dataset.ohwEditable === "video" ? "Video" : el.dataset.ohwEditable === "bg-image" ? "Background" : "Image"
|
|
15607
|
+
});
|
|
15608
|
+
}, []);
|
|
15609
|
+
const selectMediaElementRef = useRef10(selectMediaElement);
|
|
15610
|
+
selectMediaElementRef.current = selectMediaElement;
|
|
15611
|
+
useEffect13(() => {
|
|
15612
|
+
if (!selectedMedia) return;
|
|
15613
|
+
const update = () => {
|
|
15614
|
+
const el = selectedMediaElRef.current;
|
|
15615
|
+
if (!el || !el.isConnected) {
|
|
15616
|
+
clearMediaSelection();
|
|
15617
|
+
return;
|
|
15618
|
+
}
|
|
15619
|
+
const r2 = el.getBoundingClientRect();
|
|
15620
|
+
setSelectedMedia(
|
|
15621
|
+
(prev) => prev ? { ...prev, rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height } } : prev
|
|
15622
|
+
);
|
|
15623
|
+
};
|
|
15624
|
+
window.addEventListener("scroll", update, true);
|
|
15625
|
+
window.addEventListener("resize", update);
|
|
15626
|
+
return () => {
|
|
15627
|
+
window.removeEventListener("scroll", update, true);
|
|
15628
|
+
window.removeEventListener("resize", update);
|
|
15629
|
+
};
|
|
15630
|
+
}, [selectedMedia !== null]);
|
|
15631
|
+
const [carouselHover, setCarouselHover] = useState12(null);
|
|
15632
|
+
const [uploadingRects, setUploadingRects] = useState12({});
|
|
15633
|
+
const hoveredGapRef = useRef10(null);
|
|
15634
|
+
const imageUnhoverTimerRef = useRef10(null);
|
|
15635
|
+
const imageShowTimerRef = useRef10(null);
|
|
15636
|
+
const editStylesRef = useRef10(null);
|
|
15637
|
+
const activateRef = useRef10(() => {
|
|
15638
|
+
});
|
|
15639
|
+
const deactivateRef = useRef10(() => {
|
|
15640
|
+
});
|
|
15641
|
+
const selectRef = useRef10(() => {
|
|
15642
|
+
});
|
|
15643
|
+
const selectFrameRef = useRef10(() => {
|
|
15644
|
+
});
|
|
15645
|
+
const selectLogoRef = useRef10(() => {
|
|
15646
|
+
});
|
|
15647
|
+
const openLogoSizePanelRef = useRef10(() => {
|
|
15648
|
+
});
|
|
15649
|
+
const deselectRef = useRef10(() => {
|
|
15650
|
+
});
|
|
15651
|
+
const closeFloatingPanelOnlyRef = useRef10(() => {
|
|
15652
|
+
});
|
|
15653
|
+
const reselectNavigationItemRef = useRef10(() => {
|
|
15654
|
+
});
|
|
15655
|
+
const commitNavigationTextEditRef = useRef10(() => {
|
|
15656
|
+
});
|
|
15657
|
+
const handleDeleteSelectedRef = useRef10(() => false);
|
|
15658
|
+
const runPendingDeleteUndoRef = useRef10(() => false);
|
|
15659
|
+
const isFooterFrameSelectionRef = useRef10(false);
|
|
15660
|
+
const refreshActiveCommandsRef = useRef10(() => {
|
|
15661
|
+
});
|
|
15662
|
+
const postToParentRef = useRef10(postToParent2);
|
|
15663
|
+
postToParentRef.current = postToParent2;
|
|
15664
|
+
const aiSectionApiRef = useRef10(null);
|
|
15665
|
+
const sectionsLoadedRef = useRef10(false);
|
|
15666
|
+
const pendingScheduleConfigRequests = useRef10([]);
|
|
15667
|
+
const [toolbarRect, setToolbarRect] = useState12(null);
|
|
15668
|
+
const [formPickRect, setFormPickRect] = useState12(null);
|
|
15669
|
+
const formPickElRef = useRef10(null);
|
|
15670
|
+
const [formViewState, setFormViewStateUi] = useState12("default");
|
|
15671
|
+
const [formPickCount, setFormPickCount] = useState12(null);
|
|
15672
|
+
const [formHoverRect, setFormHoverRect] = useState12(null);
|
|
15673
|
+
const formHoverElRef = useRef10(null);
|
|
15674
|
+
const [fieldPickRect, setFieldPickRect] = useState12(null);
|
|
15675
|
+
const fieldPickElRef = useRef10(null);
|
|
15676
|
+
const [fieldPickState, setFieldPickState] = useState12(null);
|
|
15677
|
+
const [fieldTypePickerOpen, setFieldTypePickerOpen] = useState12(false);
|
|
15678
|
+
const clearFormPick = useCallback8(() => {
|
|
15679
|
+
const form = formPickElRef.current;
|
|
15680
|
+
const editing = fieldPickElRef.current;
|
|
15681
|
+
if (commitPlaceholderEdit(editing) && editing) {
|
|
15682
|
+
const owner = editing.closest('[data-ohw-editable="form"]');
|
|
14613
15683
|
if (owner) persistFieldsRef.current(owner);
|
|
14614
15684
|
}
|
|
14615
15685
|
if (form) {
|
|
@@ -14625,7 +15695,7 @@ function OhhwellsBridge() {
|
|
|
14625
15695
|
formPickElRef.current = null;
|
|
14626
15696
|
setFormPickRect(null);
|
|
14627
15697
|
}, []);
|
|
14628
|
-
const clearFieldPick =
|
|
15698
|
+
const clearFieldPick = useCallback8(() => {
|
|
14629
15699
|
const wrapper = fieldPickElRef.current;
|
|
14630
15700
|
if (commitPlaceholderEdit(wrapper) && wrapper) {
|
|
14631
15701
|
const form = wrapper.closest('[data-ohw-editable="form"]');
|
|
@@ -14635,9 +15705,9 @@ function OhhwellsBridge() {
|
|
|
14635
15705
|
setFieldPickRect(null);
|
|
14636
15706
|
setFieldPickState(null);
|
|
14637
15707
|
}, []);
|
|
14638
|
-
const persistFieldsRef =
|
|
15708
|
+
const persistFieldsRef = useRef10(() => {
|
|
14639
15709
|
});
|
|
14640
|
-
const persistFields =
|
|
15710
|
+
const persistFields = useCallback8(
|
|
14641
15711
|
(form) => {
|
|
14642
15712
|
const key = formKeyOf(form);
|
|
14643
15713
|
if (!key) return;
|
|
@@ -14648,7 +15718,7 @@ function OhhwellsBridge() {
|
|
|
14648
15718
|
[]
|
|
14649
15719
|
);
|
|
14650
15720
|
persistFieldsRef.current = persistFields;
|
|
14651
|
-
const selectField =
|
|
15721
|
+
const selectField = useCallback8((wrapper) => {
|
|
14652
15722
|
if (fieldPickElRef.current && fieldPickElRef.current !== wrapper) {
|
|
14653
15723
|
commitPlaceholderEdit(fieldPickElRef.current);
|
|
14654
15724
|
}
|
|
@@ -14661,7 +15731,7 @@ function OhhwellsBridge() {
|
|
|
14661
15731
|
setFieldPickState({ type: fieldTypeOf(wrapper), required: isFieldRequired(wrapper) });
|
|
14662
15732
|
setFieldTypePickerOpen(false);
|
|
14663
15733
|
}, []);
|
|
14664
|
-
const withSelectedField =
|
|
15734
|
+
const withSelectedField = useCallback8(
|
|
14665
15735
|
(run) => {
|
|
14666
15736
|
const wrapper = fieldPickElRef.current;
|
|
14667
15737
|
const form = formPickElRef.current;
|
|
@@ -14674,28 +15744,28 @@ function OhhwellsBridge() {
|
|
|
14674
15744
|
},
|
|
14675
15745
|
[persistFields]
|
|
14676
15746
|
);
|
|
14677
|
-
const handleFieldTypeChange =
|
|
15747
|
+
const handleFieldTypeChange = useCallback8(
|
|
14678
15748
|
(type) => withSelectedField((_form, wrapper) => {
|
|
14679
15749
|
applyFieldType(wrapper, type);
|
|
14680
15750
|
selectField(wrapper);
|
|
14681
15751
|
}),
|
|
14682
15752
|
[selectField, withSelectedField]
|
|
14683
15753
|
);
|
|
14684
|
-
const handleFieldRequiredToggle =
|
|
15754
|
+
const handleFieldRequiredToggle = useCallback8(
|
|
14685
15755
|
() => withSelectedField((_form, wrapper) => {
|
|
14686
15756
|
setFieldRequired(wrapper, !isFieldRequired(wrapper));
|
|
14687
15757
|
selectField(wrapper);
|
|
14688
15758
|
}),
|
|
14689
15759
|
[selectField, withSelectedField]
|
|
14690
15760
|
);
|
|
14691
|
-
const handleFieldDuplicate =
|
|
15761
|
+
const handleFieldDuplicate = useCallback8(
|
|
14692
15762
|
() => withSelectedField((form, wrapper) => {
|
|
14693
15763
|
const copy = duplicateField(form, wrapper);
|
|
14694
15764
|
selectField(copy);
|
|
14695
15765
|
}),
|
|
14696
15766
|
[selectField, withSelectedField]
|
|
14697
15767
|
);
|
|
14698
|
-
const handleFieldDelete =
|
|
15768
|
+
const handleFieldDelete = useCallback8(
|
|
14699
15769
|
() => withSelectedField((_form, wrapper) => {
|
|
14700
15770
|
removeField(wrapper);
|
|
14701
15771
|
clearFieldPick();
|
|
@@ -14703,7 +15773,7 @@ function OhhwellsBridge() {
|
|
|
14703
15773
|
}),
|
|
14704
15774
|
[clearFieldPick, withSelectedField]
|
|
14705
15775
|
);
|
|
14706
|
-
const handleAddField =
|
|
15776
|
+
const handleAddField = useCallback8(
|
|
14707
15777
|
(type) => {
|
|
14708
15778
|
const form = formPickElRef.current;
|
|
14709
15779
|
if (!form) return;
|
|
@@ -14719,8 +15789,8 @@ function OhhwellsBridge() {
|
|
|
14719
15789
|
},
|
|
14720
15790
|
[persistFields, selectField]
|
|
14721
15791
|
);
|
|
14722
|
-
const fieldDragRef =
|
|
14723
|
-
const buildFieldDropSlots =
|
|
15792
|
+
const fieldDragRef = useRef10(null);
|
|
15793
|
+
const buildFieldDropSlots = useCallback8((form, draggedKey) => {
|
|
14724
15794
|
const others = listFieldWrappers(form).filter((el) => fieldKeyOf(el) !== draggedKey);
|
|
14725
15795
|
const slots = others.map((el) => {
|
|
14726
15796
|
const rect = el.getBoundingClientRect();
|
|
@@ -14733,7 +15803,7 @@ function OhhwellsBridge() {
|
|
|
14733
15803
|
}
|
|
14734
15804
|
return slots;
|
|
14735
15805
|
}, []);
|
|
14736
|
-
const handleFieldDragStart =
|
|
15806
|
+
const handleFieldDragStart = useCallback8(() => {
|
|
14737
15807
|
const wrapper = fieldPickElRef.current;
|
|
14738
15808
|
const form = formPickElRef.current;
|
|
14739
15809
|
if (!wrapper || !form) return;
|
|
@@ -14742,18 +15812,18 @@ function OhhwellsBridge() {
|
|
|
14742
15812
|
setFieldDragging(true);
|
|
14743
15813
|
setFieldDropSlots(buildFieldDropSlots(form, key));
|
|
14744
15814
|
}, [buildFieldDropSlots]);
|
|
14745
|
-
const handleFieldDragEnd =
|
|
15815
|
+
const handleFieldDragEnd = useCallback8(() => {
|
|
14746
15816
|
fieldDragRef.current = null;
|
|
14747
15817
|
setFieldDropIndex(null);
|
|
14748
15818
|
setFieldDropSlots([]);
|
|
14749
15819
|
setFieldDragging(false);
|
|
14750
15820
|
}, []);
|
|
14751
|
-
const [fieldDropIndex, setFieldDropIndex] =
|
|
14752
|
-
const [fieldDropSlots, setFieldDropSlots] =
|
|
14753
|
-
const [fieldDragging, setFieldDragging] =
|
|
14754
|
-
const clearFormPickRef =
|
|
15821
|
+
const [fieldDropIndex, setFieldDropIndex] = useState12(null);
|
|
15822
|
+
const [fieldDropSlots, setFieldDropSlots] = useState12([]);
|
|
15823
|
+
const [fieldDragging, setFieldDragging] = useState12(false);
|
|
15824
|
+
const clearFormPickRef = useRef10(clearFormPick);
|
|
14755
15825
|
clearFormPickRef.current = clearFormPick;
|
|
14756
|
-
|
|
15826
|
+
useEffect13(() => {
|
|
14757
15827
|
const el = fieldPickElRef.current;
|
|
14758
15828
|
if (!el || fieldPickRect === null) return;
|
|
14759
15829
|
const observer = new ResizeObserver(() => {
|
|
@@ -14762,7 +15832,7 @@ function OhhwellsBridge() {
|
|
|
14762
15832
|
observer.observe(el);
|
|
14763
15833
|
return () => observer.disconnect();
|
|
14764
15834
|
}, [fieldPickRect !== null, fieldPickState]);
|
|
14765
|
-
|
|
15835
|
+
useEffect13(() => {
|
|
14766
15836
|
const el = formPickElRef.current;
|
|
14767
15837
|
if (!el || formPickRect === null) return;
|
|
14768
15838
|
const observer = new ResizeObserver(() => {
|
|
@@ -14771,25 +15841,25 @@ function OhhwellsBridge() {
|
|
|
14771
15841
|
observer.observe(el);
|
|
14772
15842
|
return () => observer.disconnect();
|
|
14773
15843
|
}, [formPickRect !== null, formViewState]);
|
|
14774
|
-
const [toolbarVariant, setToolbarVariant] =
|
|
14775
|
-
const toolbarVariantRef =
|
|
15844
|
+
const [toolbarVariant, setToolbarVariant] = useState12("none");
|
|
15845
|
+
const toolbarVariantRef = useRef10("none");
|
|
14776
15846
|
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
|
-
|
|
15847
|
+
const [selectedIsCta, setSelectedIsCta] = useState12(false);
|
|
15848
|
+
const [selectedIsSocial, setSelectedIsSocial] = useState12(false);
|
|
15849
|
+
const [selectedIsSocialsRow, setSelectedIsSocialsRow] = useState12(false);
|
|
15850
|
+
const [reorderHrefKey, setReorderHrefKey] = useState12(null);
|
|
15851
|
+
const [reorderDragDisabled, setReorderDragDisabled] = useState12(false);
|
|
15852
|
+
const [toggleState, setToggleState] = useState12(null);
|
|
15853
|
+
const [maxBadge, setMaxBadge] = useState12(null);
|
|
15854
|
+
const [activeCommands, setActiveCommands] = useState12(/* @__PURE__ */ new Set());
|
|
15855
|
+
const [sectionGap, setSectionGap] = useState12(null);
|
|
15856
|
+
const [toolbarShowEditLink, setToolbarShowEditLink] = useState12(false);
|
|
15857
|
+
const hoveredNavContainerRef = useRef10(null);
|
|
15858
|
+
const [hoveredNavContainerRect, setHoveredNavContainerRect] = useState12(null);
|
|
15859
|
+
const hoveredItemElRef = useRef10(null);
|
|
15860
|
+
const [hoveredItemRect, setHoveredItemRect] = useState12(null);
|
|
15861
|
+
const [hoveredTextRect, setHoveredTextRect] = useState12(null);
|
|
15862
|
+
useEffect13(() => {
|
|
14793
15863
|
const sync = () => {
|
|
14794
15864
|
const el = document.querySelector(
|
|
14795
15865
|
'[data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key]):not([data-ohw-editable="form"] *)'
|
|
@@ -14810,43 +15880,56 @@ function OhhwellsBridge() {
|
|
|
14810
15880
|
});
|
|
14811
15881
|
return () => observer.disconnect();
|
|
14812
15882
|
}, []);
|
|
14813
|
-
const siblingHintElRef =
|
|
14814
|
-
const [siblingHintRect, setSiblingHintRect] =
|
|
14815
|
-
const [siblingHintRects, setSiblingHintRects] =
|
|
14816
|
-
const [isItemDragging, setIsItemDragging] =
|
|
14817
|
-
const [isFooterFrameSelection, setIsFooterFrameSelection] =
|
|
15883
|
+
const siblingHintElRef = useRef10(null);
|
|
15884
|
+
const [siblingHintRect, setSiblingHintRect] = useState12(null);
|
|
15885
|
+
const [siblingHintRects, setSiblingHintRects] = useState12([]);
|
|
15886
|
+
const [isItemDragging, setIsItemDragging] = useState12(false);
|
|
15887
|
+
const [isFooterFrameSelection, setIsFooterFrameSelection] = useState12(false);
|
|
14818
15888
|
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
|
|
15889
|
+
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = useState12(null);
|
|
15890
|
+
const [footerHeadingVisible, setFooterHeadingVisible] = useState12(null);
|
|
15891
|
+
const footerDragRef = useRef10(null);
|
|
15892
|
+
const [footerDropSlots, setFooterDropSlots] = useState12([]);
|
|
15893
|
+
const [activeFooterDropIndex, setActiveFooterDropIndex] = useState12(null);
|
|
15894
|
+
const [draggedItemRect, setDraggedItemRect] = useState12(null);
|
|
15895
|
+
const footerPointerDragRef = useRef10(null);
|
|
15896
|
+
const suppressNextClickRef = useRef10(false);
|
|
15897
|
+
const suppressClickUntilRef = useRef10(0);
|
|
15898
|
+
const [linkPopover, setLinkPopover] = useState12(null);
|
|
15899
|
+
const linkPopoverSessionRef = useRef10(null);
|
|
15900
|
+
const addNavAfterAnchorRef = useRef10(null);
|
|
15901
|
+
const editContentRef = useRef10({});
|
|
15902
|
+
const aiSectionsRef = useRef10("");
|
|
15903
|
+
const brandKitRef = useRef10("");
|
|
15904
|
+
const stylesRef = useRef10("");
|
|
15905
|
+
const pendingDeleteUndoRef = useRef10(null);
|
|
15906
|
+
const [floatingPanel, setFloatingPanel] = useState12(null);
|
|
15907
|
+
const floatingPanelOpenRef = useRef10(false);
|
|
15908
|
+
const setFloatingPanelRef = useRef10(setFloatingPanel);
|
|
15909
|
+
const [floatingPanelPos, setFloatingPanelPos] = useState12(null);
|
|
15910
|
+
const [logoSizeDraft, setLogoSizeDraft] = useState12(null);
|
|
15911
|
+
const [editorViewport, setEditorViewport] = useState12("desktop");
|
|
15912
|
+
const [parentScrollSnap, setParentScrollSnap] = useState12(null);
|
|
15913
|
+
const [sitePages, setSitePages] = useState12([]);
|
|
15914
|
+
const [sectionsByPath, setSectionsByPath] = useState12({});
|
|
15915
|
+
const sectionsPrefetchGenRef = useRef10(0);
|
|
15916
|
+
const setLinkPopoverRef = useRef10(setLinkPopover);
|
|
15917
|
+
const linkPopoverPanelRef = useRef10(null);
|
|
15918
|
+
const linkPopoverOpenRef = useRef10(false);
|
|
15919
|
+
const linkPopoverGraceUntilRef = useRef10(0);
|
|
14848
15920
|
setLinkPopoverRef.current = setLinkPopover;
|
|
15921
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
14849
15922
|
linkPopoverSessionRef.current = linkPopover;
|
|
15923
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
15924
|
+
useEffect13(() => {
|
|
15925
|
+
const syncViewport = () => {
|
|
15926
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
15927
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
15928
|
+
};
|
|
15929
|
+
syncViewport();
|
|
15930
|
+
window.addEventListener("resize", syncViewport);
|
|
15931
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
15932
|
+
}, []);
|
|
14850
15933
|
const {
|
|
14851
15934
|
navDragRef,
|
|
14852
15935
|
navDropSlots,
|
|
@@ -14879,10 +15962,20 @@ function OhhwellsBridge() {
|
|
|
14879
15962
|
getNavigationItemAnchor,
|
|
14880
15963
|
isDragHandleDisabled
|
|
14881
15964
|
});
|
|
15965
|
+
const { sectionDropSlots, activeSectionDropIndex, isSectionDragging } = useSectionDrag({
|
|
15966
|
+
isEditMode,
|
|
15967
|
+
editContentRef,
|
|
15968
|
+
postToParentRef,
|
|
15969
|
+
parentScrollRef,
|
|
15970
|
+
navDragRef,
|
|
15971
|
+
footerDragRef,
|
|
15972
|
+
suppressNextClickRef,
|
|
15973
|
+
suppressClickUntilRef
|
|
15974
|
+
});
|
|
14882
15975
|
const bumpLinkPopoverGrace = () => {
|
|
14883
15976
|
linkPopoverGraceUntilRef.current = Date.now() + 350;
|
|
14884
15977
|
};
|
|
14885
|
-
const runSectionsPrefetch =
|
|
15978
|
+
const runSectionsPrefetch = useCallback8((pages) => {
|
|
14886
15979
|
if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
|
|
14887
15980
|
const gen = ++sectionsPrefetchGenRef.current;
|
|
14888
15981
|
const paths = pages.map((p) => p.path);
|
|
@@ -14901,9 +15994,9 @@ function OhhwellsBridge() {
|
|
|
14901
15994
|
);
|
|
14902
15995
|
});
|
|
14903
15996
|
}, [isEditMode, pathname]);
|
|
14904
|
-
const runSectionsPrefetchRef =
|
|
15997
|
+
const runSectionsPrefetchRef = useRef10(runSectionsPrefetch);
|
|
14905
15998
|
runSectionsPrefetchRef.current = runSectionsPrefetch;
|
|
14906
|
-
|
|
15999
|
+
useEffect13(() => {
|
|
14907
16000
|
if (!linkPopover) {
|
|
14908
16001
|
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
14909
16002
|
return;
|
|
@@ -14931,7 +16024,7 @@ function OhhwellsBridge() {
|
|
|
14931
16024
|
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
14932
16025
|
};
|
|
14933
16026
|
}, [linkPopover, postToParent2]);
|
|
14934
|
-
|
|
16027
|
+
useEffect13(() => {
|
|
14935
16028
|
if (!isEditMode) return;
|
|
14936
16029
|
const useFixtures = shouldUseDevFixtures();
|
|
14937
16030
|
if (useFixtures) {
|
|
@@ -14955,14 +16048,14 @@ function OhhwellsBridge() {
|
|
|
14955
16048
|
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
14956
16049
|
return () => window.removeEventListener("message", onSitePages);
|
|
14957
16050
|
}, [isEditMode, postToParent2]);
|
|
14958
|
-
|
|
16051
|
+
useEffect13(() => {
|
|
14959
16052
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
14960
16053
|
void loadAllSectionsManifest().then((manifest) => {
|
|
14961
16054
|
if (Object.keys(manifest).length === 0) return;
|
|
14962
16055
|
setSectionsByPath((prev) => ({ ...manifest, ...prev }));
|
|
14963
16056
|
});
|
|
14964
16057
|
}, [isEditMode]);
|
|
14965
|
-
|
|
16058
|
+
useEffect13(() => {
|
|
14966
16059
|
const update = () => {
|
|
14967
16060
|
const el = activeElRef.current ?? selectedElRef.current;
|
|
14968
16061
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
@@ -14986,10 +16079,10 @@ function OhhwellsBridge() {
|
|
|
14986
16079
|
vvp.removeEventListener("resize", update);
|
|
14987
16080
|
};
|
|
14988
16081
|
}, []);
|
|
14989
|
-
const refreshStateRules =
|
|
16082
|
+
const refreshStateRules = useCallback8(() => {
|
|
14990
16083
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
14991
16084
|
}, []);
|
|
14992
|
-
const processConfigRequest =
|
|
16085
|
+
const processConfigRequest = useCallback8((insertAfterVal) => {
|
|
14993
16086
|
const tracker = getSectionsTracker();
|
|
14994
16087
|
let entries = [];
|
|
14995
16088
|
try {
|
|
@@ -15012,7 +16105,7 @@ function OhhwellsBridge() {
|
|
|
15012
16105
|
}
|
|
15013
16106
|
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
|
|
15014
16107
|
}, [isEditMode]);
|
|
15015
|
-
const deactivate =
|
|
16108
|
+
const deactivate = useCallback8(() => {
|
|
15016
16109
|
const el = activeElRef.current;
|
|
15017
16110
|
if (!el) return;
|
|
15018
16111
|
const isFormBlock = el.dataset.ohwEditable === "form";
|
|
@@ -15053,12 +16146,12 @@ function OhhwellsBridge() {
|
|
|
15053
16146
|
setToolbarShowEditLink(false);
|
|
15054
16147
|
postToParent2({ type: "ow:exit-edit" });
|
|
15055
16148
|
}, [postToParent2]);
|
|
15056
|
-
const clearSelectedAttr =
|
|
16149
|
+
const clearSelectedAttr = useCallback8(() => {
|
|
15057
16150
|
document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
|
|
15058
16151
|
el.removeAttribute("data-ohw-selected");
|
|
15059
16152
|
});
|
|
15060
16153
|
}, []);
|
|
15061
|
-
const deselect =
|
|
16154
|
+
const deselect = useCallback8(() => {
|
|
15062
16155
|
clearSelectedAttr();
|
|
15063
16156
|
selectedElRef.current = null;
|
|
15064
16157
|
selectedHrefKeyRef.current = null;
|
|
@@ -15087,11 +16180,12 @@ function OhhwellsBridge() {
|
|
|
15087
16180
|
setToolbarVariant("none");
|
|
15088
16181
|
}
|
|
15089
16182
|
}, [clearSelectedAttr]);
|
|
15090
|
-
const markSelected =
|
|
16183
|
+
const markSelected = useCallback8((el) => {
|
|
15091
16184
|
clearSelectedAttr();
|
|
16185
|
+
el.removeAttribute("data-ohw-hovered");
|
|
15092
16186
|
el.setAttribute("data-ohw-selected", "");
|
|
15093
16187
|
}, [clearSelectedAttr]);
|
|
15094
|
-
const resolveHrefKeyElement =
|
|
16188
|
+
const resolveHrefKeyElement = useCallback8((hrefKey) => {
|
|
15095
16189
|
if (isFooterHrefKey(hrefKey)) {
|
|
15096
16190
|
return document.querySelector(
|
|
15097
16191
|
`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
@@ -15106,7 +16200,7 @@ function OhhwellsBridge() {
|
|
|
15106
16200
|
`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
15107
16201
|
);
|
|
15108
16202
|
}, []);
|
|
15109
|
-
const resyncSelectedNavigationItem =
|
|
16203
|
+
const resyncSelectedNavigationItem = useCallback8(() => {
|
|
15110
16204
|
const hrefKey = selectedHrefKeyRef.current;
|
|
15111
16205
|
if (hrefKey) {
|
|
15112
16206
|
const link = resolveHrefKeyElement(hrefKey);
|
|
@@ -15144,7 +16238,7 @@ function OhhwellsBridge() {
|
|
|
15144
16238
|
);
|
|
15145
16239
|
}
|
|
15146
16240
|
}, [resolveHrefKeyElement]);
|
|
15147
|
-
const reselectNavigationItem =
|
|
16241
|
+
const reselectNavigationItem = useCallback8((navAnchor) => {
|
|
15148
16242
|
selectedElRef.current = navAnchor;
|
|
15149
16243
|
selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
|
|
15150
16244
|
selectedFooterColAttrRef.current = null;
|
|
@@ -15175,7 +16269,7 @@ function OhhwellsBridge() {
|
|
|
15175
16269
|
setToolbarShowEditLink(false);
|
|
15176
16270
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
15177
16271
|
}, [markSelected]);
|
|
15178
|
-
const commitNavigationTextEdit =
|
|
16272
|
+
const commitNavigationTextEdit = useCallback8((navAnchor) => {
|
|
15179
16273
|
const el = activeElRef.current;
|
|
15180
16274
|
if (!el) return;
|
|
15181
16275
|
const key = el.dataset.ohwKey;
|
|
@@ -15208,7 +16302,7 @@ function OhhwellsBridge() {
|
|
|
15208
16302
|
postToParent2({ type: "ow:exit-edit" });
|
|
15209
16303
|
reselectNavigationItem(navAnchor);
|
|
15210
16304
|
}, [postToParent2, reselectNavigationItem]);
|
|
15211
|
-
const handleAddTopLevelNavItem =
|
|
16305
|
+
const handleAddTopLevelNavItem = useCallback8(() => {
|
|
15212
16306
|
const items = listNavbarRootItems();
|
|
15213
16307
|
addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
|
|
15214
16308
|
deselectRef.current();
|
|
@@ -15220,7 +16314,7 @@ function OhhwellsBridge() {
|
|
|
15220
16314
|
intent: "add-nav"
|
|
15221
16315
|
});
|
|
15222
16316
|
}, []);
|
|
15223
|
-
const maybeWarnNavLinkDropdownConflict =
|
|
16317
|
+
const maybeWarnNavLinkDropdownConflict = useCallback8(
|
|
15224
16318
|
(anchor) => {
|
|
15225
16319
|
if (!isNavbarHrefKey(anchor.getAttribute("data-ohw-href-key"))) return;
|
|
15226
16320
|
if (!navDropdownsOpenOnClick()) return;
|
|
@@ -15233,7 +16327,7 @@ function OhhwellsBridge() {
|
|
|
15233
16327
|
},
|
|
15234
16328
|
[postToParent2]
|
|
15235
16329
|
);
|
|
15236
|
-
const handleNavDropdownOpenChange =
|
|
16330
|
+
const handleNavDropdownOpenChange = useCallback8((open) => {
|
|
15237
16331
|
const selected = selectedElRef.current;
|
|
15238
16332
|
if (!selected || !isNavigationItem2(selected)) return;
|
|
15239
16333
|
setNavGroupForceOpen(selected, open);
|
|
@@ -15245,7 +16339,7 @@ function OhhwellsBridge() {
|
|
|
15245
16339
|
}
|
|
15246
16340
|
});
|
|
15247
16341
|
}, []);
|
|
15248
|
-
const handleFooterHeadingVisibleChange =
|
|
16342
|
+
const handleFooterHeadingVisibleChange = useCallback8(
|
|
15249
16343
|
(visible) => {
|
|
15250
16344
|
const selected = selectedElRef.current;
|
|
15251
16345
|
if (!selected || !isFooterFrameSelectionRef.current) return;
|
|
@@ -15269,7 +16363,7 @@ function OhhwellsBridge() {
|
|
|
15269
16363
|
},
|
|
15270
16364
|
[postToParent2]
|
|
15271
16365
|
);
|
|
15272
|
-
const enterEditOnNewItem =
|
|
16366
|
+
const enterEditOnNewItem = useCallback8((anchor) => {
|
|
15273
16367
|
const label = anchor.querySelector('[data-ohw-editable="text"]');
|
|
15274
16368
|
if (!label) {
|
|
15275
16369
|
selectRef.current(anchor);
|
|
@@ -15278,7 +16372,7 @@ function OhhwellsBridge() {
|
|
|
15278
16372
|
setNavGroupForceOpen(anchor, true);
|
|
15279
16373
|
activateRef.current(label);
|
|
15280
16374
|
}, []);
|
|
15281
|
-
const handleAddChildItem =
|
|
16375
|
+
const handleAddChildItem = useCallback8(() => {
|
|
15282
16376
|
const selected = selectedElRef.current;
|
|
15283
16377
|
if (!selected) return;
|
|
15284
16378
|
const socialsRow = isSocialsRow(selected) ? selected : findSocialsRow(selected);
|
|
@@ -15390,7 +16484,7 @@ function OhhwellsBridge() {
|
|
|
15390
16484
|
enterEditOnNewItem(result.anchor);
|
|
15391
16485
|
});
|
|
15392
16486
|
}, [enterEditOnNewItem, isFooterFrameSelection, maybeWarnNavLinkDropdownConflict, postToParent2]);
|
|
15393
|
-
const handleAddFooterColumn =
|
|
16487
|
+
const handleAddFooterColumn = useCallback8(() => {
|
|
15394
16488
|
if (!canAddFooterColumn()) {
|
|
15395
16489
|
postToParent2({
|
|
15396
16490
|
type: "ow:toast",
|
|
@@ -15411,7 +16505,7 @@ function OhhwellsBridge() {
|
|
|
15411
16505
|
selectRef.current(result.firstLink);
|
|
15412
16506
|
});
|
|
15413
16507
|
}, [postToParent2]);
|
|
15414
|
-
const clearFooterDragVisuals =
|
|
16508
|
+
const clearFooterDragVisuals = useCallback8(() => {
|
|
15415
16509
|
footerDragRef.current = null;
|
|
15416
16510
|
setSiblingHintRects([]);
|
|
15417
16511
|
setFooterDropSlots([]);
|
|
@@ -15420,7 +16514,7 @@ function OhhwellsBridge() {
|
|
|
15420
16514
|
setIsItemDragging(false);
|
|
15421
16515
|
unlockFooterDragInteraction();
|
|
15422
16516
|
}, []);
|
|
15423
|
-
const refreshFooterDragVisuals =
|
|
16517
|
+
const refreshFooterDragVisuals = useCallback8((session, activeSlot, clientX, clientY) => {
|
|
15424
16518
|
const dragged = session.draggedEl;
|
|
15425
16519
|
setDraggedItemRect(dragged.getBoundingClientRect());
|
|
15426
16520
|
if (typeof clientX === "number" && typeof clientY === "number") {
|
|
@@ -15452,13 +16546,13 @@ function OhhwellsBridge() {
|
|
|
15452
16546
|
const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
15453
16547
|
setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
15454
16548
|
}, []);
|
|
15455
|
-
const refreshFooterDragVisualsRef =
|
|
16549
|
+
const refreshFooterDragVisualsRef = useRef10(refreshFooterDragVisuals);
|
|
15456
16550
|
refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
|
|
15457
|
-
const commitFooterDragRef =
|
|
16551
|
+
const commitFooterDragRef = useRef10(() => {
|
|
15458
16552
|
});
|
|
15459
|
-
const beginFooterDragRef =
|
|
16553
|
+
const beginFooterDragRef = useRef10(() => {
|
|
15460
16554
|
});
|
|
15461
|
-
const beginFooterDrag =
|
|
16555
|
+
const beginFooterDrag = useCallback8(
|
|
15462
16556
|
(session) => {
|
|
15463
16557
|
const rect = session.draggedEl.getBoundingClientRect();
|
|
15464
16558
|
session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
|
|
@@ -15478,7 +16572,7 @@ function OhhwellsBridge() {
|
|
|
15478
16572
|
[refreshFooterDragVisuals]
|
|
15479
16573
|
);
|
|
15480
16574
|
beginFooterDragRef.current = beginFooterDrag;
|
|
15481
|
-
const commitFooterDrag =
|
|
16575
|
+
const commitFooterDrag = useCallback8(
|
|
15482
16576
|
(clientX, clientY) => {
|
|
15483
16577
|
const session = footerDragRef.current;
|
|
15484
16578
|
if (!session) {
|
|
@@ -15606,7 +16700,7 @@ function OhhwellsBridge() {
|
|
|
15606
16700
|
[clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
|
|
15607
16701
|
);
|
|
15608
16702
|
commitFooterDragRef.current = commitFooterDrag;
|
|
15609
|
-
const startFooterLinkDrag =
|
|
16703
|
+
const startFooterLinkDrag = useCallback8(
|
|
15610
16704
|
(anchor, clientX, clientY, wasSelected) => {
|
|
15611
16705
|
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
15612
16706
|
if (!hrefKey) return false;
|
|
@@ -15642,7 +16736,7 @@ function OhhwellsBridge() {
|
|
|
15642
16736
|
},
|
|
15643
16737
|
[beginFooterDrag]
|
|
15644
16738
|
);
|
|
15645
|
-
const startFooterColumnDrag =
|
|
16739
|
+
const startFooterColumnDrag = useCallback8(
|
|
15646
16740
|
(columnEl, clientX, clientY, wasSelected) => {
|
|
15647
16741
|
const columns = listFooterColumns();
|
|
15648
16742
|
const idx = columns.indexOf(columnEl);
|
|
@@ -15662,7 +16756,7 @@ function OhhwellsBridge() {
|
|
|
15662
16756
|
},
|
|
15663
16757
|
[beginFooterDrag]
|
|
15664
16758
|
);
|
|
15665
|
-
const handleItemDragStart =
|
|
16759
|
+
const handleItemDragStart = useCallback8(
|
|
15666
16760
|
(e) => {
|
|
15667
16761
|
const selected = selectedElRef.current;
|
|
15668
16762
|
if (!selected) {
|
|
@@ -15682,7 +16776,7 @@ function OhhwellsBridge() {
|
|
|
15682
16776
|
},
|
|
15683
16777
|
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
|
|
15684
16778
|
);
|
|
15685
|
-
const handleItemDragEnd =
|
|
16779
|
+
const handleItemDragEnd = useCallback8(
|
|
15686
16780
|
(e) => {
|
|
15687
16781
|
if (footerDragRef.current) {
|
|
15688
16782
|
const x = e?.clientX;
|
|
@@ -15708,7 +16802,7 @@ function OhhwellsBridge() {
|
|
|
15708
16802
|
},
|
|
15709
16803
|
[commitFooterDrag, commitNavDrag, navDragRef]
|
|
15710
16804
|
);
|
|
15711
|
-
const handleItemChromePointerDown =
|
|
16805
|
+
const handleItemChromePointerDown = useCallback8((e) => {
|
|
15712
16806
|
if (e.button !== 0) return;
|
|
15713
16807
|
const selected = selectedElRef.current;
|
|
15714
16808
|
if (!selected) return;
|
|
@@ -15739,7 +16833,7 @@ function OhhwellsBridge() {
|
|
|
15739
16833
|
}
|
|
15740
16834
|
if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
|
|
15741
16835
|
}, [armNavPressFromChrome]);
|
|
15742
|
-
const handleItemChromeClick =
|
|
16836
|
+
const handleItemChromeClick = useCallback8((clientX, clientY) => {
|
|
15743
16837
|
if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
|
|
15744
16838
|
suppressNextClickRef.current = false;
|
|
15745
16839
|
return;
|
|
@@ -15752,7 +16846,7 @@ function OhhwellsBridge() {
|
|
|
15752
16846
|
}, []);
|
|
15753
16847
|
reselectNavigationItemRef.current = reselectNavigationItem;
|
|
15754
16848
|
commitNavigationTextEditRef.current = commitNavigationTextEdit;
|
|
15755
|
-
const select =
|
|
16849
|
+
const select = useCallback8((anchor) => {
|
|
15756
16850
|
if (!isNavigationItem2(anchor)) return;
|
|
15757
16851
|
if (activeElRef.current) deactivate();
|
|
15758
16852
|
aiSectionApiRef.current?.selectFromElement(anchor);
|
|
@@ -15795,7 +16889,7 @@ function OhhwellsBridge() {
|
|
|
15795
16889
|
setFloatingPanel(null);
|
|
15796
16890
|
setLogoSizeDraft(null);
|
|
15797
16891
|
}, [deactivate, markSelected]);
|
|
15798
|
-
const selectFrame =
|
|
16892
|
+
const selectFrame = useCallback8((el) => {
|
|
15799
16893
|
if (!isNavigationContainer(el)) return;
|
|
15800
16894
|
if (activeElRef.current) deactivate();
|
|
15801
16895
|
aiSectionApiRef.current?.selectFromElement(el);
|
|
@@ -15846,7 +16940,7 @@ function OhhwellsBridge() {
|
|
|
15846
16940
|
setFloatingPanel(null);
|
|
15847
16941
|
setLogoSizeDraft(null);
|
|
15848
16942
|
}, [deactivate, markSelected, postToParent2]);
|
|
15849
|
-
const selectLogo =
|
|
16943
|
+
const selectLogo = useCallback8(
|
|
15850
16944
|
(logoEl) => {
|
|
15851
16945
|
if (activeElRef.current) deactivate();
|
|
15852
16946
|
selectedElRef.current = logoEl;
|
|
@@ -15875,7 +16969,7 @@ function OhhwellsBridge() {
|
|
|
15875
16969
|
},
|
|
15876
16970
|
[deactivate, markSelected]
|
|
15877
16971
|
);
|
|
15878
|
-
const openLogoSizePanel =
|
|
16972
|
+
const openLogoSizePanel = useCallback8((logoEl) => {
|
|
15879
16973
|
const placement = getLogoPlacement(logoEl);
|
|
15880
16974
|
const draft = readLogoSizeState(editContentRef.current, placement);
|
|
15881
16975
|
setLogoSizeDraft(draft);
|
|
@@ -15888,7 +16982,7 @@ function OhhwellsBridge() {
|
|
|
15888
16982
|
placement
|
|
15889
16983
|
});
|
|
15890
16984
|
}, []);
|
|
15891
|
-
const openSocialsDisplayPanel =
|
|
16985
|
+
const openSocialsDisplayPanel = useCallback8((row) => {
|
|
15892
16986
|
setParentScrollSnap(parentScrollRef.current);
|
|
15893
16987
|
setFloatingPanel({
|
|
15894
16988
|
key: "socials-display",
|
|
@@ -15898,7 +16992,7 @@ function OhhwellsBridge() {
|
|
|
15898
16992
|
row
|
|
15899
16993
|
});
|
|
15900
16994
|
}, []);
|
|
15901
|
-
const changeSocialsDisplay =
|
|
16995
|
+
const changeSocialsDisplay = useCallback8(
|
|
15902
16996
|
(row, next) => {
|
|
15903
16997
|
if (next.icon) {
|
|
15904
16998
|
const missing = socialsMissingIcons(row);
|
|
@@ -15921,17 +17015,17 @@ function OhhwellsBridge() {
|
|
|
15921
17015
|
},
|
|
15922
17016
|
[]
|
|
15923
17017
|
);
|
|
15924
|
-
const closeFloatingPanelOnly =
|
|
17018
|
+
const closeFloatingPanelOnly = useCallback8(() => {
|
|
15925
17019
|
setFloatingPanel(null);
|
|
15926
17020
|
setLogoSizeDraft(null);
|
|
15927
17021
|
}, []);
|
|
15928
17022
|
closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
|
|
15929
|
-
const closeFloatingPanelAndDeselect =
|
|
17023
|
+
const closeFloatingPanelAndDeselect = useCallback8(() => {
|
|
15930
17024
|
setFloatingPanel(null);
|
|
15931
17025
|
setLogoSizeDraft(null);
|
|
15932
17026
|
deselectRef.current();
|
|
15933
17027
|
}, []);
|
|
15934
|
-
|
|
17028
|
+
useEffect13(() => {
|
|
15935
17029
|
const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
|
|
15936
17030
|
if (!session || !logoSizeDraft) {
|
|
15937
17031
|
postToParentRef.current({ type: "ow:logo-size-panel", open: false });
|
|
@@ -15950,7 +17044,7 @@ function OhhwellsBridge() {
|
|
|
15950
17044
|
max: LOGO_SIZE_MAX
|
|
15951
17045
|
});
|
|
15952
17046
|
}, [floatingPanel, logoSizeDraft, editorViewport]);
|
|
15953
|
-
const persistLogoSizeDraft =
|
|
17047
|
+
const persistLogoSizeDraft = useCallback8(
|
|
15954
17048
|
(placement, draft) => {
|
|
15955
17049
|
const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
|
|
15956
17050
|
const mobileKey = LOGO_SIZE_MOBILE_KEYS[placement];
|
|
@@ -15990,7 +17084,7 @@ function OhhwellsBridge() {
|
|
|
15990
17084
|
},
|
|
15991
17085
|
[postToParent2]
|
|
15992
17086
|
);
|
|
15993
|
-
const activate =
|
|
17087
|
+
const activate = useCallback8((el, options) => {
|
|
15994
17088
|
if (activeElRef.current === el) return;
|
|
15995
17089
|
if (isIconEditable(el)) return;
|
|
15996
17090
|
if (el.hasAttribute("data-ohw-social-label")) return;
|
|
@@ -16074,8 +17168,8 @@ function OhhwellsBridge() {
|
|
|
16074
17168
|
openLogoSizePanelRef.current = openLogoSizePanel;
|
|
16075
17169
|
deselectRef.current = deselect;
|
|
16076
17170
|
closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
|
|
16077
|
-
const lastSiteWideScopeRef =
|
|
16078
|
-
|
|
17171
|
+
const lastSiteWideScopeRef = useRef10(null);
|
|
17172
|
+
useEffect13(() => {
|
|
16079
17173
|
if (!isEditMode) {
|
|
16080
17174
|
if (lastSiteWideScopeRef.current !== false) {
|
|
16081
17175
|
lastSiteWideScopeRef.current = false;
|
|
@@ -16108,15 +17202,27 @@ function OhhwellsBridge() {
|
|
|
16108
17202
|
}
|
|
16109
17203
|
const applyContent = (content) => {
|
|
16110
17204
|
const imageLoads = [];
|
|
17205
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
17206
|
+
brandKitRef.current = content[BRAND_KIT_KEY];
|
|
17207
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
17208
|
+
}
|
|
16111
17209
|
if (typeof content[AI_SECTIONS_KEY] === "string") {
|
|
16112
17210
|
aiSectionsRef.current = content[AI_SECTIONS_KEY];
|
|
16113
17211
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
16114
17212
|
}
|
|
17213
|
+
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
17214
|
+
stylesRef.current = content[STYLE_STORE_KEY];
|
|
17215
|
+
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
17216
|
+
}
|
|
17217
|
+
applyBrandChrome(content);
|
|
16115
17218
|
for (const [key, val] of Object.entries(content)) {
|
|
16116
17219
|
if (key === "__ohw_sections") continue;
|
|
16117
17220
|
if (key === AI_SECTIONS_KEY) continue;
|
|
16118
17221
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
16119
17222
|
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
17223
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
17224
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
17225
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
16120
17226
|
if (applyVideoSettingNode(key, val)) continue;
|
|
16121
17227
|
if (applyCarouselNode(key, val)) continue;
|
|
16122
17228
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -16174,7 +17280,9 @@ function OhhwellsBridge() {
|
|
|
16174
17280
|
let cancelled = false;
|
|
16175
17281
|
setFetchState("loading");
|
|
16176
17282
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
16177
|
-
|
|
17283
|
+
const initialPath = pathname;
|
|
17284
|
+
fetchedContentPaths.add(`${subdomain}::${initialPath}`);
|
|
17285
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
16178
17286
|
if (cancelled) return;
|
|
16179
17287
|
const content = data?.content ?? {};
|
|
16180
17288
|
contentCache.set(subdomain, content);
|
|
@@ -16187,7 +17295,7 @@ function OhhwellsBridge() {
|
|
|
16187
17295
|
cancelled = true;
|
|
16188
17296
|
};
|
|
16189
17297
|
}, [subdomain, isEditMode]);
|
|
16190
|
-
|
|
17298
|
+
useEffect13(() => {
|
|
16191
17299
|
if (!isEditMode) return;
|
|
16192
17300
|
const resolveIndex = (form, clientY) => {
|
|
16193
17301
|
const wrappers = listFieldWrappers(form).filter((el) => fieldKeyOf(el) !== fieldDragRef.current?.key);
|
|
@@ -16228,7 +17336,7 @@ function OhhwellsBridge() {
|
|
|
16228
17336
|
window.removeEventListener("drop", onDrop, true);
|
|
16229
17337
|
};
|
|
16230
17338
|
}, [buildFieldDropSlots, isEditMode, persistFields, selectField]);
|
|
16231
|
-
|
|
17339
|
+
useEffect13(() => {
|
|
16232
17340
|
if (!isEditMode) return;
|
|
16233
17341
|
const mark = () => document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
16234
17342
|
markFormFields(form);
|
|
@@ -16240,7 +17348,7 @@ function OhhwellsBridge() {
|
|
|
16240
17348
|
});
|
|
16241
17349
|
return () => observer.disconnect();
|
|
16242
17350
|
}, [isEditMode, fetchState, pathname]);
|
|
16243
|
-
|
|
17351
|
+
useEffect13(() => {
|
|
16244
17352
|
if (!isEditMode) return;
|
|
16245
17353
|
let saveTimer = null;
|
|
16246
17354
|
const onInput = (e) => {
|
|
@@ -16262,14 +17370,14 @@ function OhhwellsBridge() {
|
|
|
16262
17370
|
document.addEventListener("input", onInput, true);
|
|
16263
17371
|
return () => document.removeEventListener("input", onInput, true);
|
|
16264
17372
|
}, [isEditMode, persistFields]);
|
|
16265
|
-
|
|
17373
|
+
useEffect13(() => {
|
|
16266
17374
|
if (isEditMode || fetchState !== "done") return;
|
|
16267
17375
|
const content = contentCache.get(subdomain) ?? {};
|
|
16268
17376
|
document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
16269
17377
|
reconcileFieldsFromContent(form, content);
|
|
16270
17378
|
});
|
|
16271
17379
|
}, [isEditMode, fetchState, subdomain]);
|
|
16272
|
-
|
|
17380
|
+
useEffect13(() => {
|
|
16273
17381
|
if (!isEditMode) return;
|
|
16274
17382
|
const swallow = (e) => {
|
|
16275
17383
|
const target = e.target;
|
|
@@ -16278,12 +17386,12 @@ function OhhwellsBridge() {
|
|
|
16278
17386
|
document.addEventListener("submit", swallow, true);
|
|
16279
17387
|
return () => document.removeEventListener("submit", swallow, true);
|
|
16280
17388
|
}, [isEditMode]);
|
|
16281
|
-
|
|
17389
|
+
useEffect13(() => {
|
|
16282
17390
|
if (isEditMode || fetchState !== "done") return;
|
|
16283
17391
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
16284
17392
|
bindPublishedForms(apiUrl, subdomain, contentCache.get(subdomain) ?? {});
|
|
16285
17393
|
}, [isEditMode, fetchState, subdomain]);
|
|
16286
|
-
|
|
17394
|
+
useEffect13(() => {
|
|
16287
17395
|
if (!subdomain || isEditMode) return;
|
|
16288
17396
|
let debounceTimer = null;
|
|
16289
17397
|
let observer = null;
|
|
@@ -16294,10 +17402,21 @@ function OhhwellsBridge() {
|
|
|
16294
17402
|
initSectionInstancesFromContent(content, window.location.pathname);
|
|
16295
17403
|
observer?.disconnect();
|
|
16296
17404
|
try {
|
|
17405
|
+
applyBrandChrome(content);
|
|
17406
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
17407
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
17408
|
+
}
|
|
17409
|
+
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
17410
|
+
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
17411
|
+
}
|
|
16297
17412
|
for (const [key, val] of Object.entries(content)) {
|
|
16298
17413
|
if (key === "__ohw_sections") continue;
|
|
16299
17414
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
16300
17415
|
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
17416
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
17417
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
17418
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
17419
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
16301
17420
|
if (applyVideoSettingNode(key, val)) continue;
|
|
16302
17421
|
if (applyCarouselNode(key, val)) continue;
|
|
16303
17422
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -16340,6 +17459,17 @@ function OhhwellsBridge() {
|
|
|
16340
17459
|
debounceTimer = setTimeout(applyFromCache, 150);
|
|
16341
17460
|
};
|
|
16342
17461
|
applyFromCache();
|
|
17462
|
+
const pathCacheKey = `${subdomain}::${pathname}`;
|
|
17463
|
+
if (!fetchedContentPaths.has(pathCacheKey)) {
|
|
17464
|
+
fetchedContentPaths.add(pathCacheKey);
|
|
17465
|
+
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
17466
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
17467
|
+
if (!data?.content) return;
|
|
17468
|
+
contentCache.set(subdomain, data.content);
|
|
17469
|
+
applyFromCache();
|
|
17470
|
+
}).catch(() => {
|
|
17471
|
+
});
|
|
17472
|
+
}
|
|
16343
17473
|
observer = new MutationObserver(scheduleApply);
|
|
16344
17474
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
16345
17475
|
return () => {
|
|
@@ -16353,10 +17483,10 @@ function OhhwellsBridge() {
|
|
|
16353
17483
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
16354
17484
|
el.style.display = visible ? "flex" : "none";
|
|
16355
17485
|
}, [subdomain, fetchState]);
|
|
16356
|
-
|
|
17486
|
+
useEffect13(() => {
|
|
16357
17487
|
postToParent2({ type: "ow:navigation", path: pathname });
|
|
16358
17488
|
}, [pathname, postToParent2]);
|
|
16359
|
-
|
|
17489
|
+
useEffect13(() => {
|
|
16360
17490
|
if (!isEditMode) return;
|
|
16361
17491
|
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
16362
17492
|
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
@@ -16364,7 +17494,7 @@ function OhhwellsBridge() {
|
|
|
16364
17494
|
deselectRef.current();
|
|
16365
17495
|
deactivateRef.current();
|
|
16366
17496
|
}, [pathname, isEditMode]);
|
|
16367
|
-
|
|
17497
|
+
useEffect13(() => {
|
|
16368
17498
|
const contentForNav = () => {
|
|
16369
17499
|
if (isEditMode) return editContentRef.current;
|
|
16370
17500
|
if (!subdomain) return {};
|
|
@@ -16431,31 +17561,36 @@ function OhhwellsBridge() {
|
|
|
16431
17561
|
observer?.disconnect();
|
|
16432
17562
|
};
|
|
16433
17563
|
}, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
|
|
16434
|
-
|
|
17564
|
+
useEffect13(() => {
|
|
16435
17565
|
if (!isEditMode) return;
|
|
17566
|
+
let lastPosted = 0;
|
|
16436
17567
|
const measure = () => {
|
|
16437
17568
|
const h = document.body.scrollHeight;
|
|
16438
|
-
if (h > 50
|
|
17569
|
+
if (h > 50 && Math.abs(h - lastPosted) > 1) {
|
|
17570
|
+
lastPosted = h;
|
|
17571
|
+
postToParent2({ type: "ow:height", height: h });
|
|
17572
|
+
}
|
|
17573
|
+
};
|
|
17574
|
+
let raf = null;
|
|
17575
|
+
const schedule = () => {
|
|
17576
|
+
if (raf != null) return;
|
|
17577
|
+
raf = requestAnimationFrame(() => {
|
|
17578
|
+
raf = null;
|
|
17579
|
+
measure();
|
|
17580
|
+
});
|
|
16439
17581
|
};
|
|
16440
17582
|
const t1 = setTimeout(measure, 50);
|
|
16441
17583
|
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);
|
|
17584
|
+
const ro = new ResizeObserver(schedule);
|
|
17585
|
+
ro.observe(document.body);
|
|
16451
17586
|
return () => {
|
|
16452
17587
|
clearTimeout(t1);
|
|
16453
17588
|
clearTimeout(t2);
|
|
16454
|
-
if (
|
|
16455
|
-
|
|
17589
|
+
if (raf != null) cancelAnimationFrame(raf);
|
|
17590
|
+
ro.disconnect();
|
|
16456
17591
|
};
|
|
16457
17592
|
}, [pathname, isEditMode, postToParent2]);
|
|
16458
|
-
|
|
17593
|
+
useEffect13(() => {
|
|
16459
17594
|
if (!subdomainFromQuery || isEditMode) return;
|
|
16460
17595
|
const handleClick = (e) => {
|
|
16461
17596
|
const anchor = e.target.closest("a");
|
|
@@ -16471,7 +17606,7 @@ function OhhwellsBridge() {
|
|
|
16471
17606
|
document.addEventListener("click", handleClick, true);
|
|
16472
17607
|
return () => document.removeEventListener("click", handleClick, true);
|
|
16473
17608
|
}, [subdomainFromQuery, isEditMode, router]);
|
|
16474
|
-
|
|
17609
|
+
useEffect13(() => {
|
|
16475
17610
|
if (!isEditMode) {
|
|
16476
17611
|
editStylesRef.current?.base.remove();
|
|
16477
17612
|
editStylesRef.current?.forceHover.remove();
|
|
@@ -16633,16 +17768,21 @@ function OhhwellsBridge() {
|
|
|
16633
17768
|
return;
|
|
16634
17769
|
}
|
|
16635
17770
|
const target = e.target;
|
|
17771
|
+
if (target.closest("[data-ohw-ai-review]")) return;
|
|
16636
17772
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
16637
17773
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
16638
17774
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
16639
17775
|
if (isInsideLinkEditor(target)) return;
|
|
17776
|
+
if (isInsideFloatingPanel(target)) return;
|
|
16640
17777
|
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
16641
17778
|
if (target.closest(
|
|
16642
17779
|
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
16643
17780
|
)) {
|
|
16644
17781
|
return;
|
|
16645
17782
|
}
|
|
17783
|
+
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
17784
|
+
clearMediaSelectionRef.current();
|
|
17785
|
+
}
|
|
16646
17786
|
{
|
|
16647
17787
|
const formEl = getFormElement(target);
|
|
16648
17788
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -16790,8 +17930,11 @@ function OhhwellsBridge() {
|
|
|
16790
17930
|
if (isMediaEditable(editable) && !buttonOnMedia) {
|
|
16791
17931
|
e.preventDefault();
|
|
16792
17932
|
e.stopPropagation();
|
|
16793
|
-
|
|
16794
|
-
|
|
17933
|
+
if (selectedMediaElRef.current === editable) {
|
|
17934
|
+
postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "", elementType: editable.dataset.ohwEditable ?? "image" });
|
|
17935
|
+
} else {
|
|
17936
|
+
selectMediaElementRef.current(editable);
|
|
17937
|
+
}
|
|
16795
17938
|
return;
|
|
16796
17939
|
}
|
|
16797
17940
|
const hrefLookupTarget = buttonOnMedia ? clickedButton : editable;
|
|
@@ -16910,10 +18053,12 @@ function OhhwellsBridge() {
|
|
|
16910
18053
|
};
|
|
16911
18054
|
const handleDblClick = (e) => {
|
|
16912
18055
|
const target = e.target;
|
|
18056
|
+
if (target.closest("[data-ohw-ai-review]")) return;
|
|
16913
18057
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
16914
18058
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
16915
18059
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
16916
18060
|
if (isInsideLinkEditor(target)) return;
|
|
18061
|
+
if (isInsideFloatingPanel(target)) return;
|
|
16917
18062
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
16918
18063
|
return;
|
|
16919
18064
|
}
|
|
@@ -16954,11 +18099,14 @@ function OhhwellsBridge() {
|
|
|
16954
18099
|
setSiblingHintRects([]);
|
|
16955
18100
|
return;
|
|
16956
18101
|
}
|
|
16957
|
-
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || target.
|
|
18102
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || isInsideFloatingPanel(target) || isPointOverFloatingPanel(e.clientX, e.clientY)) {
|
|
16958
18103
|
hoveredItemElRef.current = null;
|
|
16959
18104
|
setHoveredItemRect(null);
|
|
16960
18105
|
hoveredNavContainerRef.current = null;
|
|
16961
18106
|
setHoveredNavContainerRect(null);
|
|
18107
|
+
siblingHintElRef.current = null;
|
|
18108
|
+
setSiblingHintRect(null);
|
|
18109
|
+
setSiblingHintRects([]);
|
|
16962
18110
|
return;
|
|
16963
18111
|
}
|
|
16964
18112
|
{
|
|
@@ -16976,6 +18124,16 @@ function OhhwellsBridge() {
|
|
|
16976
18124
|
return;
|
|
16977
18125
|
}
|
|
16978
18126
|
}
|
|
18127
|
+
if (allowNavContainerHover) {
|
|
18128
|
+
const socialsRow = isSocialsRow(target) ? target : null;
|
|
18129
|
+
if (socialsRow && !getSocialItem(target) && selected2 !== socialsRow) {
|
|
18130
|
+
hoveredNavContainerRef.current = socialsRow;
|
|
18131
|
+
setHoveredNavContainerRect(socialsRow.getBoundingClientRect());
|
|
18132
|
+
hoveredItemElRef.current = null;
|
|
18133
|
+
setHoveredItemRect(null);
|
|
18134
|
+
return;
|
|
18135
|
+
}
|
|
18136
|
+
}
|
|
16979
18137
|
if (allowFooterLinksHover) {
|
|
16980
18138
|
const navContainer = target.closest("[data-ohw-nav-container]");
|
|
16981
18139
|
if (!navContainer) {
|
|
@@ -17061,13 +18219,12 @@ function OhhwellsBridge() {
|
|
|
17061
18219
|
clearHrefKeyHover(hoverTarget);
|
|
17062
18220
|
hoveredItemElRef.current = hoverTarget;
|
|
17063
18221
|
setHoveredItemRect(hoverTarget.getBoundingClientRect());
|
|
17064
|
-
} else if (!isInsideNavigationItem(editable)) {
|
|
18222
|
+
} else if (!isInsideNavigationItem(editable) && hoverTarget !== selectedElRef.current) {
|
|
17065
18223
|
hoverTarget.setAttribute("data-ohw-hovered", "");
|
|
17066
18224
|
if (editable.closest("footer") || editable.closest('[data-ohw-section="footer"]')) {
|
|
17067
18225
|
hoveredNavContainerRef.current = null;
|
|
17068
18226
|
setHoveredNavContainerRect(null);
|
|
17069
18227
|
hoveredItemElRef.current = editable;
|
|
17070
|
-
setHoveredItemRect(editable.getBoundingClientRect());
|
|
17071
18228
|
}
|
|
17072
18229
|
}
|
|
17073
18230
|
}
|
|
@@ -17364,7 +18521,7 @@ function OhhwellsBridge() {
|
|
|
17364
18521
|
}
|
|
17365
18522
|
};
|
|
17366
18523
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
17367
|
-
if (linkPopoverOpenRef.current) {
|
|
18524
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
17368
18525
|
if (hoveredImageRef.current) {
|
|
17369
18526
|
hoveredImageRef.current = null;
|
|
17370
18527
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -17623,7 +18780,7 @@ function OhhwellsBridge() {
|
|
|
17623
18780
|
}
|
|
17624
18781
|
};
|
|
17625
18782
|
const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
|
|
17626
|
-
if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
|
|
18783
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || document.documentElement.hasAttribute("data-ohw-section-picking")) {
|
|
17627
18784
|
if (activeStateElRef.current) {
|
|
17628
18785
|
activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
|
|
17629
18786
|
activeStateElRef.current = null;
|
|
@@ -17660,6 +18817,35 @@ function OhhwellsBridge() {
|
|
|
17660
18817
|
}
|
|
17661
18818
|
}
|
|
17662
18819
|
};
|
|
18820
|
+
const probeSocialsRowAt = (clientX, clientY, fromParentViewport = false) => {
|
|
18821
|
+
const wasSocialsRow = Boolean(hoveredNavContainerRef.current?.hasAttribute(SOCIALS_ROW_ATTR));
|
|
18822
|
+
const clear = () => {
|
|
18823
|
+
if (!wasSocialsRow) return false;
|
|
18824
|
+
hoveredNavContainerRef.current = null;
|
|
18825
|
+
setHoveredNavContainerRect(null);
|
|
18826
|
+
return false;
|
|
18827
|
+
};
|
|
18828
|
+
if (linkPopoverOpenRef.current || toolbarVariantRef.current === "select-frame") return clear();
|
|
18829
|
+
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
18830
|
+
const SLACK = 6;
|
|
18831
|
+
for (const row of Array.from(document.querySelectorAll(`[${SOCIALS_ROW_ATTR}]`))) {
|
|
18832
|
+
const rect = row.getBoundingClientRect();
|
|
18833
|
+
const inside = x >= rect.left - SLACK && x <= rect.right + SLACK && y >= rect.top - SLACK && y <= rect.bottom + SLACK;
|
|
18834
|
+
if (!inside) continue;
|
|
18835
|
+
if (selectedElRef.current === row) return clear();
|
|
18836
|
+
const overItem = listSocialItems(row).some((item) => {
|
|
18837
|
+
const box = item.getBoundingClientRect();
|
|
18838
|
+
return x >= box.left && x <= box.right && y >= box.top && y <= box.bottom;
|
|
18839
|
+
});
|
|
18840
|
+
if (overItem) return clear();
|
|
18841
|
+
hoveredNavContainerRef.current = row;
|
|
18842
|
+
setHoveredNavContainerRect(rect);
|
|
18843
|
+
hoveredItemElRef.current = null;
|
|
18844
|
+
setHoveredItemRect(null);
|
|
18845
|
+
return true;
|
|
18846
|
+
}
|
|
18847
|
+
return clear();
|
|
18848
|
+
};
|
|
17663
18849
|
const probeSectionGapAt = (clientX, clientY, fromParentViewport = false) => {
|
|
17664
18850
|
if (linkPopoverOpenRef.current) {
|
|
17665
18851
|
if (hoveredGapRef.current) {
|
|
@@ -17669,7 +18855,9 @@ function OhhwellsBridge() {
|
|
|
17669
18855
|
return;
|
|
17670
18856
|
}
|
|
17671
18857
|
const { y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
17672
|
-
const sections = Array.from(document.querySelectorAll("[data-ohw-section]")).
|
|
18858
|
+
const sections = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
18859
|
+
(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
|
|
18860
|
+
).sort((a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top);
|
|
17673
18861
|
const ZONE = 20;
|
|
17674
18862
|
for (let i = 0; i < sections.length; i++) {
|
|
17675
18863
|
const a = sections[i];
|
|
@@ -17698,8 +18886,7 @@ function OhhwellsBridge() {
|
|
|
17698
18886
|
};
|
|
17699
18887
|
const handleMouseMove = (e) => {
|
|
17700
18888
|
const { clientX, clientY } = e;
|
|
17701
|
-
if (
|
|
17702
|
-
if (isOverEditorChrome(clientX, clientY)) {
|
|
18889
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || isOverEditorChrome(clientX, clientY)) {
|
|
17703
18890
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
17704
18891
|
formHoverElRef.current = null;
|
|
17705
18892
|
setFormHoverRect(null);
|
|
@@ -17707,8 +18894,15 @@ function OhhwellsBridge() {
|
|
|
17707
18894
|
setHoveredItemRect(null);
|
|
17708
18895
|
hoveredNavContainerRef.current = null;
|
|
17709
18896
|
setHoveredNavContainerRect(null);
|
|
18897
|
+
siblingHintElRef.current = null;
|
|
18898
|
+
setSiblingHintRect(null);
|
|
18899
|
+
setSiblingHintRects([]);
|
|
18900
|
+
dismissImageHover();
|
|
18901
|
+
clearImageHover();
|
|
18902
|
+
setSectionGap(null);
|
|
17710
18903
|
return;
|
|
17711
18904
|
}
|
|
18905
|
+
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
17712
18906
|
probeSectionGapAt(clientX, clientY);
|
|
17713
18907
|
probeImageAt(clientX, clientY);
|
|
17714
18908
|
probeHoverCardsAt(clientX, clientY);
|
|
@@ -17717,7 +18911,12 @@ function OhhwellsBridge() {
|
|
|
17717
18911
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
17718
18912
|
const { clientX, clientY } = e.data;
|
|
17719
18913
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
17720
|
-
if (
|
|
18914
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
18915
|
+
dismissImageHover();
|
|
18916
|
+
clearImageHover();
|
|
18917
|
+
return;
|
|
18918
|
+
}
|
|
18919
|
+
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
17721
18920
|
probeSectionGapAt(clientX, clientY);
|
|
17722
18921
|
probeImageAt(clientX, clientY);
|
|
17723
18922
|
probeHoverCardsAt(clientX, clientY);
|
|
@@ -17963,10 +19162,19 @@ function OhhwellsBridge() {
|
|
|
17963
19162
|
if (e.data?.type !== "ow:hydrate") return;
|
|
17964
19163
|
const content = e.data.content;
|
|
17965
19164
|
if (!content) return;
|
|
19165
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
19166
|
+
brandKitRef.current = content[BRAND_KIT_KEY];
|
|
19167
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
19168
|
+
}
|
|
17966
19169
|
if (typeof content[AI_SECTIONS_KEY] === "string") {
|
|
17967
19170
|
aiSectionsRef.current = content[AI_SECTIONS_KEY];
|
|
17968
19171
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
17969
19172
|
}
|
|
19173
|
+
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
19174
|
+
stylesRef.current = content[STYLE_STORE_KEY];
|
|
19175
|
+
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
19176
|
+
}
|
|
19177
|
+
applyBrandChrome(content);
|
|
17970
19178
|
let sectionsJson = null;
|
|
17971
19179
|
for (const [key, val] of Object.entries(content)) {
|
|
17972
19180
|
if (key === "__ohw_sections") {
|
|
@@ -17976,6 +19184,9 @@ function OhhwellsBridge() {
|
|
|
17976
19184
|
if (key === AI_SECTIONS_KEY) continue;
|
|
17977
19185
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
17978
19186
|
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
19187
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
19188
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
19189
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
17979
19190
|
if (applyVideoSettingNode(key, val)) continue;
|
|
17980
19191
|
if (applyCarouselNode(key, val)) continue;
|
|
17981
19192
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -17989,6 +19200,8 @@ function OhhwellsBridge() {
|
|
|
17989
19200
|
if (video && video.src !== val) applyVideoSrc(video, val);
|
|
17990
19201
|
} else if (el.dataset.ohwEditable === "link") {
|
|
17991
19202
|
applyLinkHref(el, val);
|
|
19203
|
+
} else if (el.dataset.ohwEditable === "icon") {
|
|
19204
|
+
applyIconMarkup(el, val);
|
|
17992
19205
|
} else {
|
|
17993
19206
|
el.innerHTML = val;
|
|
17994
19207
|
}
|
|
@@ -18072,12 +19285,21 @@ function OhhwellsBridge() {
|
|
|
18072
19285
|
nodes: collectEditableNodes(editContentRef.current)
|
|
18073
19286
|
});
|
|
18074
19287
|
};
|
|
19288
|
+
const clearInteractionChrome = () => {
|
|
19289
|
+
deactivateRef.current();
|
|
19290
|
+
deselectRef.current();
|
|
19291
|
+
clearMediaSelectionRef.current();
|
|
19292
|
+
};
|
|
18075
19293
|
const handleAiApplyTree = (e) => {
|
|
18076
19294
|
if (e.data?.type !== "ow:ai-apply-tree") return;
|
|
18077
19295
|
const payload = e.data.payload;
|
|
18078
19296
|
if (!payload || typeof payload.id !== "string" || !isRenderableTree(payload.tree)) return;
|
|
19297
|
+
clearInteractionChrome();
|
|
18079
19298
|
const previous = aiSectionsRef.current;
|
|
18080
|
-
const nextState = applyTreeToState(parseAiSectionsState(previous),
|
|
19299
|
+
const nextState = applyTreeToState(parseAiSectionsState(previous), {
|
|
19300
|
+
...payload,
|
|
19301
|
+
path: payload.path ?? window.location.pathname
|
|
19302
|
+
});
|
|
18081
19303
|
const nextValue = serializeAiSectionsState(nextState);
|
|
18082
19304
|
aiSectionsRef.current = nextValue;
|
|
18083
19305
|
applyAiSectionsToDom(nextState);
|
|
@@ -18097,6 +19319,7 @@ function OhhwellsBridge() {
|
|
|
18097
19319
|
if (!sectionId || sectionId === "navbar" || sectionId === "footer") return;
|
|
18098
19320
|
const exists = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
|
|
18099
19321
|
if (!exists) return;
|
|
19322
|
+
clearInteractionChrome();
|
|
18100
19323
|
const previous = aiSectionsRef.current;
|
|
18101
19324
|
const nextState = deleteSectionFromState(parseAiSectionsState(previous), sectionId);
|
|
18102
19325
|
const nextValue = serializeAiSectionsState(nextState);
|
|
@@ -18112,14 +19335,58 @@ function OhhwellsBridge() {
|
|
|
18112
19335
|
const handleAiSetSections = (e) => {
|
|
18113
19336
|
if (e.data?.type !== "ow:ai-set-sections") return;
|
|
18114
19337
|
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
19338
|
+
clearInteractionChrome();
|
|
18115
19339
|
aiSectionsRef.current = value;
|
|
18116
19340
|
applyAiSectionsToDom(parseAiSectionsState(value));
|
|
19341
|
+
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
18117
19342
|
const restoredHeight = document.documentElement.scrollHeight;
|
|
18118
19343
|
if (restoredHeight > 50) postToParentRef.current({ type: "ow:height", height: restoredHeight });
|
|
18119
19344
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: value }] });
|
|
18120
19345
|
postAiSectionsChanged();
|
|
18121
19346
|
};
|
|
18122
19347
|
window.addEventListener("message", handleAiSetSections);
|
|
19348
|
+
const handleMoveSection = (e) => {
|
|
19349
|
+
if (e.data?.type !== "ow:move-section") return;
|
|
19350
|
+
const instanceId = typeof e.data.instanceId === "string" ? e.data.instanceId : "";
|
|
19351
|
+
const direction = e.data.direction === "up" || e.data.direction === "down" ? e.data.direction : null;
|
|
19352
|
+
if (!instanceId || !direction) return;
|
|
19353
|
+
const entries = moveSectionInstance(instanceId, direction, window.location.pathname);
|
|
19354
|
+
if (!entries) return;
|
|
19355
|
+
const orderJson = JSON.stringify(entries);
|
|
19356
|
+
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
19357
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
19358
|
+
window.dispatchEvent(new Event("resize"));
|
|
19359
|
+
};
|
|
19360
|
+
window.addEventListener("message", handleMoveSection);
|
|
19361
|
+
const handleAiSetBrand = (e) => {
|
|
19362
|
+
if (e.data?.type !== "ow:ai-set-brand") return;
|
|
19363
|
+
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
19364
|
+
const previous = brandKitRef.current;
|
|
19365
|
+
brandKitRef.current = value;
|
|
19366
|
+
applyBrandToDom(parseBrandKit(value));
|
|
19367
|
+
if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
|
|
19368
|
+
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
19369
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
|
|
19370
|
+
postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
|
|
19371
|
+
};
|
|
19372
|
+
window.addEventListener("message", handleAiSetBrand);
|
|
19373
|
+
const handleAiSetStyles = (e) => {
|
|
19374
|
+
if (e.data?.type !== "ow:ai-set-styles") return;
|
|
19375
|
+
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
19376
|
+
const previous = stylesRef.current;
|
|
19377
|
+
stylesRef.current = value;
|
|
19378
|
+
applyStylesToDom(parseStyleStore(value));
|
|
19379
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
|
|
19380
|
+
postToParentRef.current({ type: "ow:ai-styles-applied", previous, value });
|
|
19381
|
+
};
|
|
19382
|
+
window.addEventListener("message", handleAiSetStyles);
|
|
19383
|
+
const handleGetBrand = (e) => {
|
|
19384
|
+
if (e.data?.type !== "ow:get-brand") return;
|
|
19385
|
+
const template = deriveTemplateBrand();
|
|
19386
|
+
const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
|
|
19387
|
+
postToParentRef.current({ type: "ow:brand-value", value });
|
|
19388
|
+
};
|
|
19389
|
+
window.addEventListener("message", handleGetBrand);
|
|
18123
19390
|
const handlePanelDragging = (e) => {
|
|
18124
19391
|
if (e.data?.type !== "ow:panel-dragging") return;
|
|
18125
19392
|
if (e.data.dragging) document.documentElement.setAttribute("data-ohw-panel-dragging", "");
|
|
@@ -18135,8 +19402,15 @@ function OhhwellsBridge() {
|
|
|
18135
19402
|
closeLinkPopoverRef.current();
|
|
18136
19403
|
return;
|
|
18137
19404
|
}
|
|
19405
|
+
if (floatingPanelOpenRef.current) {
|
|
19406
|
+
setFloatingPanelRef.current(null);
|
|
19407
|
+
deselectRef.current();
|
|
19408
|
+
deactivateRef.current();
|
|
19409
|
+
return;
|
|
19410
|
+
}
|
|
18138
19411
|
deselectRef.current();
|
|
18139
19412
|
deactivateRef.current();
|
|
19413
|
+
clearMediaSelectionRef.current();
|
|
18140
19414
|
};
|
|
18141
19415
|
window.addEventListener("message", handleDeactivate);
|
|
18142
19416
|
const handleToastAction = (e) => {
|
|
@@ -18222,6 +19496,10 @@ function OhhwellsBridge() {
|
|
|
18222
19496
|
const handleKeyDown = (e) => {
|
|
18223
19497
|
if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
|
|
18224
19498
|
if (e.key === "Escape" && document.querySelector("[data-ohw-more-menu]")) return;
|
|
19499
|
+
if (e.key === "Escape" && selectedMediaElRef.current) {
|
|
19500
|
+
clearMediaSelectionRef.current();
|
|
19501
|
+
return;
|
|
19502
|
+
}
|
|
18225
19503
|
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
|
|
18226
19504
|
e.preventDefault();
|
|
18227
19505
|
selectAllTextInEditable(activeElRef.current);
|
|
@@ -18381,6 +19659,12 @@ function OhhwellsBridge() {
|
|
|
18381
19659
|
if (aiSectionsRef.current) {
|
|
18382
19660
|
nodes.push({ key: AI_SECTIONS_KEY, type: "sections", text: aiSectionsRef.current });
|
|
18383
19661
|
}
|
|
19662
|
+
if (stylesRef.current) {
|
|
19663
|
+
nodes.push({ key: STYLE_STORE_KEY, type: "styles", text: stylesRef.current });
|
|
19664
|
+
}
|
|
19665
|
+
if (brandKitRef.current) {
|
|
19666
|
+
nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
|
|
19667
|
+
}
|
|
18384
19668
|
document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
18385
19669
|
const formKey = formKeyOf(form);
|
|
18386
19670
|
if (!formKey) return;
|
|
@@ -18398,8 +19682,12 @@ function OhhwellsBridge() {
|
|
|
18398
19682
|
if (inserted) {
|
|
18399
19683
|
const tracker = getSectionsTracker();
|
|
18400
19684
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
|
|
18401
|
-
const
|
|
18402
|
-
|
|
19685
|
+
const reportHeight = () => {
|
|
19686
|
+
const h = document.body.scrollHeight;
|
|
19687
|
+
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
19688
|
+
};
|
|
19689
|
+
reportHeight();
|
|
19690
|
+
setTimeout(reportHeight, 500);
|
|
18403
19691
|
}
|
|
18404
19692
|
};
|
|
18405
19693
|
const handleSwitchSchedule = (e) => {
|
|
@@ -18786,19 +20074,23 @@ function OhhwellsBridge() {
|
|
|
18786
20074
|
window.removeEventListener("message", handleAiApplyTree);
|
|
18787
20075
|
window.removeEventListener("message", handleAiDeleteSection);
|
|
18788
20076
|
window.removeEventListener("message", handleAiSetSections);
|
|
20077
|
+
window.removeEventListener("message", handleMoveSection);
|
|
20078
|
+
window.removeEventListener("message", handleAiSetBrand);
|
|
20079
|
+
window.removeEventListener("message", handleAiSetStyles);
|
|
20080
|
+
window.removeEventListener("message", handleGetBrand);
|
|
18789
20081
|
window.removeEventListener("message", handlePanelDragging);
|
|
18790
20082
|
window.removeEventListener("message", handleDeactivate);
|
|
18791
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
18792
20083
|
window.removeEventListener("message", handleToastAction);
|
|
18793
20084
|
window.removeEventListener("message", handleFormCount);
|
|
18794
20085
|
window.removeEventListener("message", handleUiEscape);
|
|
20086
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
18795
20087
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
18796
20088
|
autoSaveTimers.current.clear();
|
|
18797
20089
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
18798
20090
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
18799
20091
|
};
|
|
18800
20092
|
}, [isEditMode, refreshStateRules]);
|
|
18801
|
-
|
|
20093
|
+
useEffect13(() => {
|
|
18802
20094
|
if (!isEditMode) return;
|
|
18803
20095
|
const THRESHOLD = 10;
|
|
18804
20096
|
const resolveWasSelected = (el) => {
|
|
@@ -18954,7 +20246,7 @@ function OhhwellsBridge() {
|
|
|
18954
20246
|
unlockFooterDragInteraction();
|
|
18955
20247
|
};
|
|
18956
20248
|
}, [isEditMode]);
|
|
18957
|
-
|
|
20249
|
+
useEffect13(() => {
|
|
18958
20250
|
const handler = (e) => {
|
|
18959
20251
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
18960
20252
|
const insertAfterVal = e.data.insertAfter;
|
|
@@ -18970,7 +20262,7 @@ function OhhwellsBridge() {
|
|
|
18970
20262
|
window.addEventListener("message", handler);
|
|
18971
20263
|
return () => window.removeEventListener("message", handler);
|
|
18972
20264
|
}, [processConfigRequest]);
|
|
18973
|
-
|
|
20265
|
+
useEffect13(() => {
|
|
18974
20266
|
if (!isEditMode) return;
|
|
18975
20267
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|
|
18976
20268
|
el.removeAttribute("data-ohw-active-state");
|
|
@@ -18994,7 +20286,7 @@ function OhhwellsBridge() {
|
|
|
18994
20286
|
postToParent2({
|
|
18995
20287
|
type: "ow:ready",
|
|
18996
20288
|
version: "1",
|
|
18997
|
-
bridgeVersion: "0.1.
|
|
20289
|
+
bridgeVersion: "0.1.69",
|
|
18998
20290
|
path: pathname,
|
|
18999
20291
|
nodes: collectEditableNodes(editContentRef.current),
|
|
19000
20292
|
sections
|
|
@@ -19006,13 +20298,13 @@ function OhhwellsBridge() {
|
|
|
19006
20298
|
clearTimeout(timer);
|
|
19007
20299
|
};
|
|
19008
20300
|
}, [pathname, isEditMode, refreshStateRules, postToParent2]);
|
|
19009
|
-
|
|
20301
|
+
useEffect13(() => {
|
|
19010
20302
|
scrollToHashSectionWhenReady();
|
|
19011
20303
|
const onHashChange = () => scrollToHashSectionWhenReady();
|
|
19012
20304
|
window.addEventListener("hashchange", onHashChange);
|
|
19013
20305
|
return () => window.removeEventListener("hashchange", onHashChange);
|
|
19014
20306
|
}, [pathname]);
|
|
19015
|
-
const handleCommand =
|
|
20307
|
+
const handleCommand = useCallback8((cmd) => {
|
|
19016
20308
|
const el = activeElRef.current;
|
|
19017
20309
|
const selBefore = window.getSelection();
|
|
19018
20310
|
let savedOffsets = null;
|
|
@@ -19048,7 +20340,7 @@ function OhhwellsBridge() {
|
|
|
19048
20340
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
19049
20341
|
refreshActiveCommandsRef.current();
|
|
19050
20342
|
}, []);
|
|
19051
|
-
|
|
20343
|
+
useEffect13(() => {
|
|
19052
20344
|
const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
|
|
19053
20345
|
if (!session || !logoSizeDraft) return;
|
|
19054
20346
|
const onPanelAction = (e) => {
|
|
@@ -19086,7 +20378,7 @@ function OhhwellsBridge() {
|
|
|
19086
20378
|
window.addEventListener("message", onPanelAction);
|
|
19087
20379
|
return () => window.removeEventListener("message", onPanelAction);
|
|
19088
20380
|
}, [floatingPanel, logoSizeDraft, editorViewport, persistLogoSizeDraft, closeFloatingPanelAndDeselect]);
|
|
19089
|
-
const handleStateChange =
|
|
20381
|
+
const handleStateChange = useCallback8((state) => {
|
|
19090
20382
|
if (!activeStateElRef.current) return;
|
|
19091
20383
|
const el = activeStateElRef.current;
|
|
19092
20384
|
if (state === "Default") {
|
|
@@ -19099,7 +20391,7 @@ function OhhwellsBridge() {
|
|
|
19099
20391
|
}
|
|
19100
20392
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
19101
20393
|
}, [deactivate]);
|
|
19102
|
-
const reselectAfterLinkPopover =
|
|
20394
|
+
const reselectAfterLinkPopover = useCallback8(
|
|
19103
20395
|
(hrefKey) => {
|
|
19104
20396
|
requestAnimationFrame(() => {
|
|
19105
20397
|
const el = resolveHrefKeyElement(hrefKey);
|
|
@@ -19108,7 +20400,7 @@ function OhhwellsBridge() {
|
|
|
19108
20400
|
},
|
|
19109
20401
|
[resolveHrefKeyElement]
|
|
19110
20402
|
);
|
|
19111
|
-
const closeLinkPopover =
|
|
20403
|
+
const closeLinkPopover = useCallback8(() => {
|
|
19112
20404
|
const session = linkPopoverSessionRef.current;
|
|
19113
20405
|
addNavAfterAnchorRef.current = null;
|
|
19114
20406
|
setLinkPopover(null);
|
|
@@ -19116,9 +20408,9 @@ function OhhwellsBridge() {
|
|
|
19116
20408
|
reselectAfterLinkPopover(session.key);
|
|
19117
20409
|
}
|
|
19118
20410
|
}, [reselectAfterLinkPopover]);
|
|
19119
|
-
const closeLinkPopoverRef =
|
|
20411
|
+
const closeLinkPopoverRef = useRef10(closeLinkPopover);
|
|
19120
20412
|
closeLinkPopoverRef.current = closeLinkPopover;
|
|
19121
|
-
const openLinkPopoverForActive =
|
|
20413
|
+
const openLinkPopoverForActive = useCallback8(() => {
|
|
19122
20414
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
19123
20415
|
if (!hrefCtx) return;
|
|
19124
20416
|
bumpLinkPopoverGrace();
|
|
@@ -19129,7 +20421,7 @@ function OhhwellsBridge() {
|
|
|
19129
20421
|
});
|
|
19130
20422
|
deactivate();
|
|
19131
20423
|
}, [deactivate]);
|
|
19132
|
-
const openLinkPopoverForSelected =
|
|
20424
|
+
const openLinkPopoverForSelected = useCallback8(() => {
|
|
19133
20425
|
const anchor = selectedElRef.current;
|
|
19134
20426
|
if (!anchor) return;
|
|
19135
20427
|
const key = anchor.getAttribute("data-ohw-href-key");
|
|
@@ -19146,7 +20438,7 @@ function OhhwellsBridge() {
|
|
|
19146
20438
|
});
|
|
19147
20439
|
deselect();
|
|
19148
20440
|
}, [deselect]);
|
|
19149
|
-
const handleSelectParent =
|
|
20441
|
+
const handleSelectParent = useCallback8(() => {
|
|
19150
20442
|
const selected = selectedElRef.current;
|
|
19151
20443
|
if (!selected) return;
|
|
19152
20444
|
if (toolbarVariantRef.current === "select-frame") {
|
|
@@ -19173,7 +20465,7 @@ function OhhwellsBridge() {
|
|
|
19173
20465
|
}
|
|
19174
20466
|
deselectRef.current();
|
|
19175
20467
|
}, []);
|
|
19176
|
-
const handleDuplicateSelected =
|
|
20468
|
+
const handleDuplicateSelected = useCallback8(() => {
|
|
19177
20469
|
const selected = selectedElRef.current;
|
|
19178
20470
|
if (!selected || !isNavigationItem2(selected)) return;
|
|
19179
20471
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
@@ -19289,7 +20581,7 @@ function OhhwellsBridge() {
|
|
|
19289
20581
|
});
|
|
19290
20582
|
}
|
|
19291
20583
|
}, [postToParent2]);
|
|
19292
|
-
const runPendingDeleteUndo =
|
|
20584
|
+
const runPendingDeleteUndo = useCallback8(() => {
|
|
19293
20585
|
const pending = pendingDeleteUndoRef.current;
|
|
19294
20586
|
if (!pending) return false;
|
|
19295
20587
|
pendingDeleteUndoRef.current = null;
|
|
@@ -19297,7 +20589,7 @@ function OhhwellsBridge() {
|
|
|
19297
20589
|
enforceLinkHrefs();
|
|
19298
20590
|
return true;
|
|
19299
20591
|
}, []);
|
|
19300
|
-
const handleDeleteSelected =
|
|
20592
|
+
const handleDeleteSelected = useCallback8(() => {
|
|
19301
20593
|
const selected = selectedElRef.current;
|
|
19302
20594
|
if (!selected) return false;
|
|
19303
20595
|
return deleteSelectedNavFooterItem({
|
|
@@ -19318,7 +20610,7 @@ function OhhwellsBridge() {
|
|
|
19318
20610
|
}, [postToParent2]);
|
|
19319
20611
|
handleDeleteSelectedRef.current = handleDeleteSelected;
|
|
19320
20612
|
runPendingDeleteUndoRef.current = runPendingDeleteUndo;
|
|
19321
|
-
const handleLinkPopoverSubmit =
|
|
20613
|
+
const handleLinkPopoverSubmit = useCallback8(
|
|
19322
20614
|
(target) => {
|
|
19323
20615
|
const session = linkPopoverSessionRef.current;
|
|
19324
20616
|
if (!session) return;
|
|
@@ -19384,19 +20676,30 @@ function OhhwellsBridge() {
|
|
|
19384
20676
|
const showEditLink = toolbarShowEditLink;
|
|
19385
20677
|
const currentSections = sectionsByPath[pathname] ?? [];
|
|
19386
20678
|
linkPopoverOpenRef.current = linkPopover !== null;
|
|
19387
|
-
const
|
|
20679
|
+
const handleMediaSelect = useCallback8((key) => {
|
|
20680
|
+
const el = hoveredImageRef.current?.dataset.ohwKey === key ? hoveredImageRef.current : Array.from(document.querySelectorAll(MEDIA_SELECTOR)).find(
|
|
20681
|
+
(m) => (m.dataset.ohwKey ?? "") === key
|
|
20682
|
+
) ?? null;
|
|
20683
|
+
if (!el) return;
|
|
20684
|
+
selectMediaElementRef.current(el);
|
|
20685
|
+
}, []);
|
|
20686
|
+
const handleMediaReplace = useCallback8(
|
|
19388
20687
|
(key) => {
|
|
19389
|
-
postToParent2({
|
|
20688
|
+
postToParent2({
|
|
20689
|
+
type: "ow:image-pick",
|
|
20690
|
+
key,
|
|
20691
|
+
elementType: mediaHover?.elementType ?? selectedMedia?.elementType ?? "image"
|
|
20692
|
+
});
|
|
19390
20693
|
},
|
|
19391
|
-
[postToParent2, mediaHover?.elementType]
|
|
20694
|
+
[postToParent2, mediaHover?.elementType, selectedMedia?.elementType]
|
|
19392
20695
|
);
|
|
19393
|
-
const handleEditCarousel =
|
|
20696
|
+
const handleEditCarousel = useCallback8(
|
|
19394
20697
|
(key) => {
|
|
19395
20698
|
postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
|
|
19396
20699
|
},
|
|
19397
20700
|
[postToParent2]
|
|
19398
20701
|
);
|
|
19399
|
-
const handleMediaFadeOutComplete =
|
|
20702
|
+
const handleMediaFadeOutComplete = useCallback8((key) => {
|
|
19400
20703
|
setUploadingRects((prev) => {
|
|
19401
20704
|
if (!(key in prev)) return prev;
|
|
19402
20705
|
const next = { ...prev };
|
|
@@ -19404,7 +20707,7 @@ function OhhwellsBridge() {
|
|
|
19404
20707
|
return next;
|
|
19405
20708
|
});
|
|
19406
20709
|
}, []);
|
|
19407
|
-
const handleVideoSettingsChange =
|
|
20710
|
+
const handleVideoSettingsChange = useCallback8(
|
|
19408
20711
|
(key, settings) => {
|
|
19409
20712
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
19410
20713
|
const video = getVideoEl2(el);
|
|
@@ -19426,420 +20729,506 @@ function OhhwellsBridge() {
|
|
|
19426
20729
|
},
|
|
19427
20730
|
[postToParent2]
|
|
19428
20731
|
);
|
|
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
|
|
20732
|
+
return /* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
20733
|
+
/* @__PURE__ */ jsx33("div", { id: "ohw-loader", suppressHydrationWarning: true, style: { ...OHW_LOADER_STYLE, display: "none" }, children: /* @__PURE__ */ jsx33(OhwLoaderSpinner, {}) }),
|
|
20734
|
+
/* @__PURE__ */ jsx33("script", { suppressHydrationWarning: true, dangerouslySetInnerHTML: { __html: OHW_LOADER_PREHYDRATE_SCRIPT } }),
|
|
20735
|
+
bridgeRoot ? createPortal2(
|
|
20736
|
+
/* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
20737
|
+
/* @__PURE__ */ jsx33("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
20738
|
+
isEditMode && /* @__PURE__ */ jsx33(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
|
|
20739
|
+
isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
20740
|
+
"div",
|
|
20741
|
+
{
|
|
20742
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
20743
|
+
style: { left: slot.left, top: slot.y, width: slot.width, height: 3, transform: "translateY(-50%)" },
|
|
20744
|
+
children: /* @__PURE__ */ jsx33(
|
|
20745
|
+
DropIndicator,
|
|
20746
|
+
{
|
|
20747
|
+
direction: "horizontal",
|
|
20748
|
+
state: activeSectionDropIndex === i ? "dragActive" : "dragIdle",
|
|
20749
|
+
className: "!h-full !w-full"
|
|
20750
|
+
}
|
|
20751
|
+
)
|
|
19466
20752
|
},
|
|
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
|
|
20753
|
+
`section-drop-${slot.insertIndex}-${i}`
|
|
20754
|
+
)),
|
|
20755
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx33(
|
|
20756
|
+
MediaOverlay,
|
|
20757
|
+
{
|
|
20758
|
+
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
20759
|
+
isUploading: true,
|
|
20760
|
+
fadingOut,
|
|
20761
|
+
onFadeOutComplete: handleMediaFadeOutComplete,
|
|
20762
|
+
onReplace: handleMediaReplace
|
|
19487
20763
|
},
|
|
19488
|
-
|
|
19489
|
-
|
|
19490
|
-
|
|
19491
|
-
|
|
19492
|
-
|
|
19493
|
-
|
|
19494
|
-
|
|
19495
|
-
|
|
19496
|
-
|
|
19497
|
-
|
|
19498
|
-
|
|
19499
|
-
|
|
19500
|
-
|
|
19501
|
-
|
|
19502
|
-
|
|
19503
|
-
|
|
19504
|
-
|
|
19505
|
-
|
|
19506
|
-
|
|
19507
|
-
|
|
19508
|
-
|
|
19509
|
-
|
|
19510
|
-
|
|
20764
|
+
`uploading-${key}`
|
|
20765
|
+
)),
|
|
20766
|
+
mediaHover && !(mediaHover.key in uploadingRects) && mediaHover.key !== selectedMedia?.key && /* @__PURE__ */ jsx33(
|
|
20767
|
+
MediaOverlay,
|
|
20768
|
+
{
|
|
20769
|
+
hover: mediaHover,
|
|
20770
|
+
isUploading: false,
|
|
20771
|
+
onReplace: handleMediaReplace,
|
|
20772
|
+
onSelect: handleMediaSelect,
|
|
20773
|
+
onVideoSettingsChange: handleVideoSettingsChange
|
|
20774
|
+
}
|
|
20775
|
+
),
|
|
20776
|
+
selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */ jsx33(
|
|
20777
|
+
MediaOverlay,
|
|
20778
|
+
{
|
|
20779
|
+
hover: selectedMedia,
|
|
20780
|
+
selected: true,
|
|
20781
|
+
hovered: mediaHover?.key === selectedMedia.key,
|
|
20782
|
+
isUploading: false,
|
|
20783
|
+
onReplace: handleMediaReplace,
|
|
20784
|
+
onSelect: handleMediaSelect,
|
|
20785
|
+
onVideoSettingsChange: handleVideoSettingsChange
|
|
20786
|
+
}
|
|
20787
|
+
),
|
|
20788
|
+
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
|
|
20789
|
+
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
20790
|
+
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
20791
|
+
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
20792
|
+
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
20793
|
+
"div",
|
|
20794
|
+
{
|
|
20795
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
20796
|
+
style: {
|
|
20797
|
+
left: slot.left,
|
|
20798
|
+
top: slot.top,
|
|
20799
|
+
width: slot.width,
|
|
20800
|
+
height: slot.height
|
|
20801
|
+
},
|
|
20802
|
+
children: /* @__PURE__ */ jsx33(
|
|
20803
|
+
DropIndicator,
|
|
20804
|
+
{
|
|
20805
|
+
direction: slot.direction,
|
|
20806
|
+
state: activeFooterDropIndex === i ? "dragActive" : "dragIdle",
|
|
20807
|
+
className: "!h-full !w-full"
|
|
20808
|
+
}
|
|
20809
|
+
)
|
|
20810
|
+
},
|
|
20811
|
+
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
20812
|
+
)),
|
|
20813
|
+
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
20814
|
+
"div",
|
|
20815
|
+
{
|
|
20816
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
20817
|
+
style: {
|
|
20818
|
+
left: slot.left,
|
|
20819
|
+
top: slot.top,
|
|
20820
|
+
width: slot.width,
|
|
20821
|
+
height: slot.height
|
|
20822
|
+
},
|
|
20823
|
+
children: /* @__PURE__ */ jsx33(
|
|
20824
|
+
DropIndicator,
|
|
20825
|
+
{
|
|
20826
|
+
direction: slot.direction,
|
|
20827
|
+
state: activeNavDropIndex === i ? "dragActive" : "dragIdle",
|
|
20828
|
+
className: "!h-full !w-full"
|
|
20829
|
+
}
|
|
20830
|
+
)
|
|
20831
|
+
},
|
|
20832
|
+
`nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
|
|
20833
|
+
)),
|
|
20834
|
+
hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
20835
|
+
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
20836
|
+
hoveredTextRect && !hoveredNavContainerRect && !hoveredItemRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
|
|
20837
|
+
formPickRect && !isItemDragging && /* @__PURE__ */ jsx33(
|
|
20838
|
+
ItemInteractionLayer,
|
|
20839
|
+
{
|
|
20840
|
+
rect: formPickRect,
|
|
20841
|
+
state: "active-top",
|
|
20842
|
+
itemDragSurface: false,
|
|
20843
|
+
toolbarAlign: "left",
|
|
20844
|
+
chromeGap: 24,
|
|
20845
|
+
toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ jsxs20(
|
|
20846
|
+
"div",
|
|
20847
|
+
{
|
|
20848
|
+
"data-ohw-form-toolbar": "",
|
|
20849
|
+
className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
|
|
20850
|
+
children: [
|
|
20851
|
+
/* @__PURE__ */ jsx33(
|
|
20852
|
+
"button",
|
|
20853
|
+
{
|
|
20854
|
+
type: "button",
|
|
20855
|
+
"aria-label": "Add field",
|
|
20856
|
+
className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
|
|
20857
|
+
onClick: () => setFieldTypePickerOpen((open) => !open),
|
|
20858
|
+
"data-ohw-add-field": "",
|
|
20859
|
+
children: /* @__PURE__ */ jsx33(Plus4, { size: 15, "aria-hidden": true })
|
|
20860
|
+
}
|
|
20861
|
+
),
|
|
20862
|
+
/* @__PURE__ */ jsx33("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
20863
|
+
/* @__PURE__ */ jsxs20(
|
|
20864
|
+
"button",
|
|
20865
|
+
{
|
|
20866
|
+
type: "button",
|
|
20867
|
+
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",
|
|
20868
|
+
onClick: () => {
|
|
20869
|
+
const form = formPickElRef.current;
|
|
20870
|
+
if (!form) return;
|
|
20871
|
+
postToParent2({
|
|
20872
|
+
type: "ow:form-pick",
|
|
20873
|
+
formKey: formKeyOf(form),
|
|
20874
|
+
hasLongText: formHasLongText(form)
|
|
20875
|
+
});
|
|
20876
|
+
},
|
|
20877
|
+
children: [
|
|
20878
|
+
/* @__PURE__ */ jsx33(Settings, { size: 14, "aria-hidden": true }),
|
|
20879
|
+
"Form settings",
|
|
20880
|
+
formPickCount ? (
|
|
20881
|
+
// Counter pill, per the design — not a text suffix.
|
|
20882
|
+
/* @__PURE__ */ jsx33(
|
|
20883
|
+
"span",
|
|
20884
|
+
{
|
|
20885
|
+
"data-ohw-form-count": "",
|
|
20886
|
+
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",
|
|
20887
|
+
children: formPickCount
|
|
20888
|
+
}
|
|
20889
|
+
)
|
|
20890
|
+
) : null
|
|
20891
|
+
]
|
|
20892
|
+
}
|
|
20893
|
+
),
|
|
20894
|
+
/* @__PURE__ */ jsx33("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
20895
|
+
/* @__PURE__ */ jsx33("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ jsx33(
|
|
20896
|
+
"button",
|
|
20897
|
+
{
|
|
20898
|
+
type: "button",
|
|
20899
|
+
"aria-pressed": formViewState === state,
|
|
20900
|
+
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"),
|
|
20901
|
+
onClick: () => {
|
|
20902
|
+
const form = formPickElRef.current;
|
|
20903
|
+
const key = form ? formKeyOf(form) : null;
|
|
20904
|
+
if (!form || !key) return;
|
|
20905
|
+
const initial = successInitialFor(form, key, editContentRef.current);
|
|
20906
|
+
setFormViewState(form, key, state, initial);
|
|
20907
|
+
setFormViewStateUi(state);
|
|
20908
|
+
setFormPickRect(form.getBoundingClientRect());
|
|
20909
|
+
if (state === "success") {
|
|
20910
|
+
const successEl = form.querySelector(`[${SUCCESS_TEXT_ATTR}]`);
|
|
20911
|
+
if (successEl) requestAnimationFrame(() => activateRef.current(successEl));
|
|
20912
|
+
} else {
|
|
20913
|
+
deactivateRef.current();
|
|
20914
|
+
}
|
|
20915
|
+
},
|
|
20916
|
+
children: state
|
|
20917
|
+
},
|
|
20918
|
+
state
|
|
20919
|
+
)) })
|
|
20920
|
+
]
|
|
20921
|
+
}
|
|
20922
|
+
)
|
|
20923
|
+
}
|
|
20924
|
+
),
|
|
20925
|
+
formHoverRect && !isItemDragging && /* @__PURE__ */ jsx33(
|
|
20926
|
+
ItemInteractionLayer,
|
|
20927
|
+
{
|
|
20928
|
+
rect: formHoverRect,
|
|
20929
|
+
state: "hover",
|
|
20930
|
+
chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
|
|
20931
|
+
}
|
|
20932
|
+
),
|
|
20933
|
+
fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ jsx33(
|
|
20934
|
+
ItemInteractionLayer,
|
|
20935
|
+
{
|
|
20936
|
+
rect: fieldPickRect,
|
|
20937
|
+
state: fieldDragging ? "dragging" : "active-top",
|
|
20938
|
+
itemDragSurface: false,
|
|
20939
|
+
toolbarAlign: "left",
|
|
20940
|
+
chromeGap: 10,
|
|
20941
|
+
showHandle: true,
|
|
20942
|
+
dragHandleLabel: "Reorder field",
|
|
20943
|
+
onDragHandleDragStart: handleFieldDragStart,
|
|
20944
|
+
onDragHandleDragEnd: handleFieldDragEnd,
|
|
20945
|
+
toolbar: /* @__PURE__ */ jsx33(
|
|
20946
|
+
FormFieldToolbar,
|
|
20947
|
+
{
|
|
20948
|
+
type: fieldPickState.type,
|
|
20949
|
+
required: fieldPickState.required,
|
|
20950
|
+
onTypeChange: handleFieldTypeChange,
|
|
20951
|
+
onRequiredToggle: handleFieldRequiredToggle,
|
|
20952
|
+
onDuplicate: handleFieldDuplicate,
|
|
20953
|
+
onDelete: handleFieldDelete
|
|
20954
|
+
}
|
|
20955
|
+
)
|
|
20956
|
+
}
|
|
20957
|
+
),
|
|
20958
|
+
fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
20959
|
+
"div",
|
|
20960
|
+
{
|
|
20961
|
+
className: "pointer-events-none fixed z-[2147483644]",
|
|
20962
|
+
style: { top: slot.top, left: slot.left, width: slot.width },
|
|
20963
|
+
children: /* @__PURE__ */ jsx33(
|
|
20964
|
+
DropIndicator,
|
|
20965
|
+
{
|
|
20966
|
+
direction: "horizontal",
|
|
20967
|
+
state: fieldDropIndex === i ? "dragActive" : "dragIdle",
|
|
20968
|
+
className: "!w-full"
|
|
20969
|
+
}
|
|
20970
|
+
)
|
|
20971
|
+
},
|
|
20972
|
+
`field-drop-${i}`
|
|
20973
|
+
)) : null,
|
|
20974
|
+
fieldTypePickerOpen && formPickRect ? (() => {
|
|
20975
|
+
const toolbar = document.querySelector("[data-ohw-form-toolbar]")?.getBoundingClientRect();
|
|
20976
|
+
return /* @__PURE__ */ jsx33(
|
|
19511
20977
|
"div",
|
|
19512
20978
|
{
|
|
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
|
-
]
|
|
20979
|
+
className: "pointer-events-none fixed z-[2147483645]",
|
|
20980
|
+
style: {
|
|
20981
|
+
top: toolbar ? toolbar.bottom + 6 : formPickRect.top + 16,
|
|
20982
|
+
left: toolbar ? toolbar.left : formPickRect.left + 24
|
|
20983
|
+
},
|
|
20984
|
+
children: /* @__PURE__ */ jsx33(FieldTypePicker, { onPick: handleAddField })
|
|
19586
20985
|
}
|
|
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
|
-
|
|
20986
|
+
);
|
|
20987
|
+
})() : null,
|
|
20988
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ jsx33(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
|
|
20989
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx33(
|
|
20990
|
+
FooterContainerChrome,
|
|
20991
|
+
{
|
|
20992
|
+
rect: toolbarRect,
|
|
20993
|
+
onAdd: handleAddFooterColumn,
|
|
20994
|
+
addDisabled: !canAddFooterColumn()
|
|
20995
|
+
}
|
|
20996
|
+
),
|
|
20997
|
+
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ jsx33(
|
|
20998
|
+
ItemInteractionLayer,
|
|
20999
|
+
{
|
|
21000
|
+
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
|
|
21001
|
+
toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
|
|
21002
|
+
elRef: glowElRef,
|
|
21003
|
+
state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanelRect(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
21004
|
+
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
|
|
21005
|
+
dragDisabled: reorderDragDisabled,
|
|
21006
|
+
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
21007
|
+
onDragHandleDragStart: handleItemDragStart,
|
|
21008
|
+
onDragHandleDragEnd: handleItemDragEnd,
|
|
21009
|
+
onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
|
|
21010
|
+
onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
|
|
21011
|
+
itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
|
|
21012
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ jsx33(
|
|
21013
|
+
ItemActionToolbar,
|
|
21014
|
+
{
|
|
21015
|
+
onEditLink: openLinkPopoverForSelected,
|
|
21016
|
+
onStyle: () => {
|
|
21017
|
+
const row = selectedElRef.current;
|
|
21018
|
+
if (!row) return;
|
|
21019
|
+
if (floatingPanel?.kind === "socials-display") closeFloatingPanelOnly();
|
|
21020
|
+
else openSocialsDisplayPanel(row);
|
|
21021
|
+
},
|
|
21022
|
+
showStyle: selectedIsSocialsRow,
|
|
21023
|
+
styleActive: floatingPanel?.kind === "socials-display",
|
|
21024
|
+
onAddItem: handleAddChildItem,
|
|
21025
|
+
onSelectParent: handleSelectParent,
|
|
21026
|
+
onDuplicate: handleDuplicateSelected,
|
|
21027
|
+
onDelete: handleDeleteSelected,
|
|
21028
|
+
addItemDisabled: isFooterFrameSelection && isFooterAddItemDisabled(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
21029
|
+
const row = isSocialsRow(selectedElRef.current) ? selectedElRef.current : findSocialsRow(selectedElRef.current);
|
|
21030
|
+
return row ? !canAddSocialItem(row) : false;
|
|
21031
|
+
})(),
|
|
21032
|
+
editLinkDisabled: false,
|
|
21033
|
+
moreDisabled: false,
|
|
21034
|
+
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow,
|
|
21035
|
+
showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
|
|
21036
|
+
showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
|
|
21037
|
+
selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
|
|
21038
|
+
),
|
|
21039
|
+
showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
|
|
21040
|
+
dropdownOpen: navDropdownPreviewOpen,
|
|
21041
|
+
onDropdownOpenChange: handleNavDropdownOpenChange,
|
|
21042
|
+
headingVisible: footerHeadingVisible,
|
|
21043
|
+
onHeadingVisibleChange: handleFooterHeadingVisibleChange
|
|
21044
|
+
}
|
|
21045
|
+
) : void 0
|
|
21046
|
+
}
|
|
21047
|
+
),
|
|
21048
|
+
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
21049
|
+
/* @__PURE__ */ jsx33(
|
|
21050
|
+
EditGlowChrome,
|
|
19612
21051
|
{
|
|
19613
|
-
|
|
19614
|
-
|
|
19615
|
-
|
|
19616
|
-
|
|
19617
|
-
|
|
19618
|
-
onDelete: handleFieldDelete
|
|
21052
|
+
rect: toolbarRect,
|
|
21053
|
+
elRef: glowElRef,
|
|
21054
|
+
reorderHrefKey,
|
|
21055
|
+
dragDisabled: reorderDragDisabled,
|
|
21056
|
+
hideHandle: isItemDragging
|
|
19619
21057
|
}
|
|
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,
|
|
21058
|
+
),
|
|
21059
|
+
/* @__PURE__ */ jsx33(
|
|
21060
|
+
FloatingToolbar,
|
|
19630
21061
|
{
|
|
19631
|
-
|
|
19632
|
-
|
|
19633
|
-
|
|
21062
|
+
rect: toolbarRect,
|
|
21063
|
+
parentScroll: parentScrollRef.current,
|
|
21064
|
+
elRef: toolbarElRef,
|
|
21065
|
+
onCommand: handleCommand,
|
|
21066
|
+
activeCommands,
|
|
21067
|
+
showEditLink,
|
|
21068
|
+
onEditLink: openLinkPopoverForActive
|
|
19634
21069
|
}
|
|
19635
21070
|
)
|
|
19636
|
-
},
|
|
19637
|
-
|
|
19638
|
-
)) : null,
|
|
19639
|
-
fieldTypePickerOpen && formPickRect ? (() => {
|
|
19640
|
-
const toolbar = document.querySelector("[data-ohw-form-toolbar]")?.getBoundingClientRect();
|
|
19641
|
-
return /* @__PURE__ */ jsx33(
|
|
21071
|
+
] }),
|
|
21072
|
+
maxBadge && /* @__PURE__ */ jsxs20(
|
|
19642
21073
|
"div",
|
|
19643
21074
|
{
|
|
19644
|
-
|
|
21075
|
+
"data-ohw-max-badge": "",
|
|
19645
21076
|
style: {
|
|
19646
|
-
|
|
19647
|
-
|
|
21077
|
+
position: "fixed",
|
|
21078
|
+
top: maxBadge.rect.bottom + 4,
|
|
21079
|
+
left: maxBadge.rect.right,
|
|
21080
|
+
transform: "translateX(-100%)",
|
|
21081
|
+
zIndex: 2147483647,
|
|
21082
|
+
background: maxBadge.current > maxBadge.max ? "#FEF2F2" : "#F5F5F4",
|
|
21083
|
+
color: maxBadge.current > maxBadge.max ? "#DC2626" : "#78716C",
|
|
21084
|
+
border: `1px solid ${maxBadge.current > maxBadge.max ? "#FECACA" : "#E7E5E4"}`,
|
|
21085
|
+
borderRadius: 4,
|
|
21086
|
+
padding: "2px 6px",
|
|
21087
|
+
fontSize: 11,
|
|
21088
|
+
fontWeight: 500,
|
|
21089
|
+
pointerEvents: "none"
|
|
19648
21090
|
},
|
|
19649
|
-
children:
|
|
21091
|
+
children: [
|
|
21092
|
+
maxBadge.current,
|
|
21093
|
+
"/",
|
|
21094
|
+
maxBadge.max
|
|
21095
|
+
]
|
|
19650
21096
|
}
|
|
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,
|
|
21097
|
+
),
|
|
21098
|
+
toggleState && !linkPopover && /* @__PURE__ */ jsx33(
|
|
21099
|
+
StateToggle,
|
|
19716
21100
|
{
|
|
19717
|
-
rect:
|
|
19718
|
-
|
|
19719
|
-
|
|
19720
|
-
|
|
19721
|
-
hideHandle: isItemDragging
|
|
21101
|
+
rect: toggleState.rect,
|
|
21102
|
+
activeState: toggleState.activeState,
|
|
21103
|
+
states: toggleState.states,
|
|
21104
|
+
onStateChange: handleStateChange
|
|
19722
21105
|
}
|
|
19723
21106
|
),
|
|
19724
|
-
/* @__PURE__ */
|
|
19725
|
-
|
|
21107
|
+
sectionGap && !linkPopover && /* @__PURE__ */ jsxs20(
|
|
21108
|
+
"div",
|
|
19726
21109
|
{
|
|
19727
|
-
|
|
19728
|
-
|
|
19729
|
-
|
|
19730
|
-
|
|
19731
|
-
|
|
19732
|
-
|
|
19733
|
-
|
|
21110
|
+
"data-ohw-section-insert-line": "",
|
|
21111
|
+
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
21112
|
+
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
21113
|
+
children: [
|
|
21114
|
+
/* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
21115
|
+
/* @__PURE__ */ jsx33(
|
|
21116
|
+
Badge,
|
|
21117
|
+
{
|
|
21118
|
+
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",
|
|
21119
|
+
onClick: () => {
|
|
21120
|
+
window.parent.postMessage(
|
|
21121
|
+
{
|
|
21122
|
+
type: "ow:add-section",
|
|
21123
|
+
insertAfter: sectionGap.insertAfter,
|
|
21124
|
+
insertBefore: sectionGap.insertBefore
|
|
21125
|
+
},
|
|
21126
|
+
"*"
|
|
21127
|
+
);
|
|
21128
|
+
},
|
|
21129
|
+
children: "Add Section"
|
|
21130
|
+
}
|
|
21131
|
+
),
|
|
21132
|
+
/* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
21133
|
+
]
|
|
19734
21134
|
}
|
|
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"
|
|
21135
|
+
),
|
|
21136
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx33(
|
|
21137
|
+
LinkPopover,
|
|
21138
|
+
{
|
|
21139
|
+
panelRef: linkPopoverPanelRef,
|
|
21140
|
+
portalContainer: dialogPortalContainer,
|
|
21141
|
+
open: true,
|
|
21142
|
+
mode: linkPopover.mode ?? "edit",
|
|
21143
|
+
pages: sitePages,
|
|
21144
|
+
sections: currentSections,
|
|
21145
|
+
sectionsByPath,
|
|
21146
|
+
initialTarget: linkPopover.target,
|
|
21147
|
+
existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [],
|
|
21148
|
+
onClose: closeLinkPopover,
|
|
21149
|
+
onSubmit: handleLinkPopoverSubmit
|
|
19755
21150
|
},
|
|
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,
|
|
21151
|
+
linkPopover.key
|
|
21152
|
+
) : null,
|
|
21153
|
+
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ jsx33(
|
|
21154
|
+
FloatingPanel,
|
|
21155
|
+
{
|
|
21156
|
+
open: true,
|
|
21157
|
+
title: floatingPanel.title,
|
|
21158
|
+
context: floatingPanel.context,
|
|
21159
|
+
position: floatingPanelPos,
|
|
21160
|
+
onPositionChange: setFloatingPanelPos,
|
|
21161
|
+
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
21162
|
+
onClose: closeFloatingPanelOnly,
|
|
21163
|
+
children: /* @__PURE__ */ jsx33(
|
|
21164
|
+
SocialsDisplayPanel,
|
|
19782
21165
|
{
|
|
19783
|
-
|
|
19784
|
-
|
|
19785
|
-
|
|
19786
|
-
|
|
19787
|
-
|
|
19788
|
-
insertAfter: sectionGap.insertAfter,
|
|
19789
|
-
insertBefore: sectionGap.insertBefore
|
|
19790
|
-
},
|
|
19791
|
-
"*"
|
|
19792
|
-
);
|
|
19793
|
-
},
|
|
19794
|
-
children: "Add Section"
|
|
21166
|
+
display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
|
|
21167
|
+
onChange: (next) => {
|
|
21168
|
+
changeSocialsDisplay(floatingPanel.row, next);
|
|
21169
|
+
setFloatingPanel({ ...floatingPanel });
|
|
21170
|
+
}
|
|
19795
21171
|
}
|
|
19796
|
-
)
|
|
19797
|
-
|
|
19798
|
-
|
|
19799
|
-
|
|
19800
|
-
|
|
19801
|
-
|
|
19802
|
-
|
|
19803
|
-
|
|
19804
|
-
|
|
19805
|
-
|
|
19806
|
-
|
|
19807
|
-
|
|
19808
|
-
|
|
19809
|
-
|
|
19810
|
-
|
|
19811
|
-
|
|
19812
|
-
|
|
19813
|
-
|
|
19814
|
-
|
|
21172
|
+
)
|
|
21173
|
+
}
|
|
21174
|
+
) : null
|
|
21175
|
+
] }),
|
|
21176
|
+
bridgeRoot
|
|
21177
|
+
) : null
|
|
21178
|
+
] });
|
|
21179
|
+
}
|
|
21180
|
+
|
|
21181
|
+
// src/ui/EmptySection.tsx
|
|
21182
|
+
import Link3 from "next/link";
|
|
21183
|
+
import { Fragment as Fragment9, jsx as jsx34, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
21184
|
+
function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
|
|
21185
|
+
return /* @__PURE__ */ jsxs21(Fragment9, { children: [
|
|
21186
|
+
/* @__PURE__ */ jsx34(
|
|
21187
|
+
"p",
|
|
21188
|
+
{
|
|
21189
|
+
style: {
|
|
21190
|
+
fontFamily: "var(--brand-font-body)",
|
|
21191
|
+
fontSize: "0.75rem",
|
|
21192
|
+
fontWeight: 500,
|
|
21193
|
+
letterSpacing: "0.15em",
|
|
21194
|
+
textTransform: "uppercase",
|
|
21195
|
+
color: "var(--brand-accent)",
|
|
21196
|
+
marginBottom: "1.5rem"
|
|
19815
21197
|
},
|
|
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
|
-
|
|
21198
|
+
children: /* @__PURE__ */ jsx34(Link3, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ jsx34("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
|
|
21199
|
+
}
|
|
21200
|
+
),
|
|
21201
|
+
/* @__PURE__ */ jsx34(
|
|
21202
|
+
"h1",
|
|
21203
|
+
{
|
|
21204
|
+
style: {
|
|
21205
|
+
fontFamily: "var(--brand-font-heading)",
|
|
21206
|
+
fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
|
|
21207
|
+
lineHeight: 1.1,
|
|
21208
|
+
letterSpacing: "-0.025em",
|
|
21209
|
+
color: "var(--brand-text)",
|
|
21210
|
+
marginBottom: "1rem"
|
|
21211
|
+
},
|
|
21212
|
+
...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
|
|
21213
|
+
children: title
|
|
21214
|
+
}
|
|
21215
|
+
),
|
|
21216
|
+
/* @__PURE__ */ jsx34(
|
|
21217
|
+
"p",
|
|
21218
|
+
{
|
|
21219
|
+
style: {
|
|
21220
|
+
fontFamily: "var(--brand-font-body)",
|
|
21221
|
+
fontSize: "1rem",
|
|
21222
|
+
lineHeight: 1.7,
|
|
21223
|
+
fontWeight: 300,
|
|
21224
|
+
color: "var(--brand-text-muted)",
|
|
21225
|
+
maxWidth: "340px"
|
|
21226
|
+
},
|
|
21227
|
+
...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
|
|
21228
|
+
children: "This page doesn't have any content yet."
|
|
21229
|
+
}
|
|
21230
|
+
)
|
|
21231
|
+
] });
|
|
19843
21232
|
}
|
|
19844
21233
|
export {
|
|
19845
21234
|
AI_DEFAULT_BRAND,
|
|
@@ -19857,6 +21246,7 @@ export {
|
|
|
19857
21246
|
DropdownMenuItem,
|
|
19858
21247
|
DropdownMenuSeparator,
|
|
19859
21248
|
DropdownMenuTrigger,
|
|
21249
|
+
EmptySection,
|
|
19860
21250
|
ItemActionToolbar,
|
|
19861
21251
|
ItemInteractionLayer,
|
|
19862
21252
|
LinkEditorPanel,
|