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