@ohhwells/bridge 0.1.54 → 0.1.55-next.160
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 +2642 -388
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -3
- package/dist/index.d.ts +18 -3
- package/dist/index.js +2644 -385
- 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 +108 -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_react16 = __toESM(require("react"), 1);
|
|
78
79
|
var import_client2 = require("react-dom/client");
|
|
79
80
|
var import_react_dom3 = require("react-dom");
|
|
80
81
|
|
|
@@ -191,6 +192,129 @@ function deleteSectionFromState(state, sectionId) {
|
|
|
191
192
|
return { ...state, v: 1, sections: state.sections, removed: [...removed, sectionId] };
|
|
192
193
|
}
|
|
193
194
|
|
|
195
|
+
// src/lib/brand-chrome.ts
|
|
196
|
+
var BRAND_NAME_KEY = "__ohw_brand_name";
|
|
197
|
+
var BRAND_TITLE_KEY = "__ohw_site_title";
|
|
198
|
+
var BRAND_FAVICON_LETTER_KEY = "__ohw_favicon_letter";
|
|
199
|
+
var BRAND_CHROME_KEYS = /* @__PURE__ */ new Set([
|
|
200
|
+
BRAND_NAME_KEY,
|
|
201
|
+
BRAND_TITLE_KEY,
|
|
202
|
+
BRAND_FAVICON_LETTER_KEY
|
|
203
|
+
]);
|
|
204
|
+
function upsertMeta(selector, attr, token, value) {
|
|
205
|
+
let el = document.head.querySelector(selector);
|
|
206
|
+
if (!el) {
|
|
207
|
+
el = document.createElement("meta");
|
|
208
|
+
el.setAttribute(attr, token);
|
|
209
|
+
document.head.appendChild(el);
|
|
210
|
+
}
|
|
211
|
+
if (el.getAttribute("content") !== value) el.setAttribute("content", value);
|
|
212
|
+
}
|
|
213
|
+
function escapeXml(value) {
|
|
214
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
215
|
+
}
|
|
216
|
+
function applyLetterFavicon(letter) {
|
|
217
|
+
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>`;
|
|
218
|
+
const href = `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
|
219
|
+
let link = document.head.querySelector('link[rel="icon"]');
|
|
220
|
+
if (!link) {
|
|
221
|
+
link = document.createElement("link");
|
|
222
|
+
link.rel = "icon";
|
|
223
|
+
document.head.appendChild(link);
|
|
224
|
+
}
|
|
225
|
+
link.type = "image/svg+xml";
|
|
226
|
+
if (link.href !== href) link.href = href;
|
|
227
|
+
}
|
|
228
|
+
function applyBrandChrome(content) {
|
|
229
|
+
const name = content[BRAND_NAME_KEY];
|
|
230
|
+
if (typeof name === "string" && name.length > 0) {
|
|
231
|
+
document.querySelectorAll("[data-ohw-wordmark]").forEach((el) => {
|
|
232
|
+
if (el.textContent !== name) el.textContent = name;
|
|
233
|
+
if (el.getAttribute("title") !== name) el.setAttribute("title", name);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
const title = content[BRAND_TITLE_KEY];
|
|
237
|
+
if (typeof title === "string" && title.length > 0) {
|
|
238
|
+
if (document.title !== title) document.title = title;
|
|
239
|
+
upsertMeta('meta[property="og:title"]', "property", "og:title", title);
|
|
240
|
+
upsertMeta('meta[name="twitter:title"]', "name", "twitter:title", title);
|
|
241
|
+
}
|
|
242
|
+
const letter = content[BRAND_FAVICON_LETTER_KEY];
|
|
243
|
+
if (typeof letter === "string" && letter.length > 0) {
|
|
244
|
+
applyLetterFavicon(letter);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// src/lib/brand-kit.ts
|
|
249
|
+
var BRAND_KIT_KEY = "__ohw_brand";
|
|
250
|
+
var BRAND_VAR_PREFIX = "--ohw-brand-";
|
|
251
|
+
var BRAND_VAR_NAMES = ["primary", "accent", "light", "dark", "surface", "border", "muted"].map(
|
|
252
|
+
(role) => `${BRAND_VAR_PREFIX}${role}`
|
|
253
|
+
);
|
|
254
|
+
var FONT_VARS = { heading: ["--font-heading", "--font-display"], body: ["--font-body"] };
|
|
255
|
+
var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
|
|
256
|
+
function brandColorVars(kit) {
|
|
257
|
+
const { dark, primary, accent, light } = kit.palette;
|
|
258
|
+
const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
|
|
259
|
+
return {
|
|
260
|
+
[`${BRAND_VAR_PREFIX}primary`]: primary,
|
|
261
|
+
[`${BRAND_VAR_PREFIX}accent`]: accent,
|
|
262
|
+
[`${BRAND_VAR_PREFIX}light`]: light,
|
|
263
|
+
[`${BRAND_VAR_PREFIX}dark`]: dark,
|
|
264
|
+
[`${BRAND_VAR_PREFIX}surface`]: mix(light, 95, dark),
|
|
265
|
+
[`${BRAND_VAR_PREFIX}border`]: mix(light, 85, dark),
|
|
266
|
+
[`${BRAND_VAR_PREFIX}muted`]: mix(dark, 62, light)
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
function parseBrandKit(raw) {
|
|
270
|
+
if (!raw) return null;
|
|
271
|
+
try {
|
|
272
|
+
const parsed = JSON.parse(raw);
|
|
273
|
+
const p = parsed?.palette;
|
|
274
|
+
const f = parsed?.fonts;
|
|
275
|
+
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") {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
return {
|
|
279
|
+
palette: { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light },
|
|
280
|
+
fonts: { heading: f.heading, body: f.body }
|
|
281
|
+
};
|
|
282
|
+
} catch {
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
function familyOf(stack) {
|
|
287
|
+
const first = stack.split(",")[0]?.trim() ?? "";
|
|
288
|
+
return first.replace(/^['"]|['"]$/g, "");
|
|
289
|
+
}
|
|
290
|
+
function loadBrandFonts(families) {
|
|
291
|
+
const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
|
|
292
|
+
if (unique.length === 0) return;
|
|
293
|
+
const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
|
|
294
|
+
const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
|
|
295
|
+
let link = document.getElementById(BRAND_FONT_LINK_ID);
|
|
296
|
+
if (!link) {
|
|
297
|
+
link = document.createElement("link");
|
|
298
|
+
link.id = BRAND_FONT_LINK_ID;
|
|
299
|
+
link.rel = "stylesheet";
|
|
300
|
+
document.head.appendChild(link);
|
|
301
|
+
}
|
|
302
|
+
if (link.href !== href) link.href = href;
|
|
303
|
+
}
|
|
304
|
+
function applyBrandToDom(kit) {
|
|
305
|
+
const root = document.documentElement;
|
|
306
|
+
if (!kit) {
|
|
307
|
+
for (const name of BRAND_VAR_NAMES) root.style.removeProperty(name);
|
|
308
|
+
for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
|
|
309
|
+
document.getElementById(BRAND_FONT_LINK_ID)?.remove();
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
for (const [name, value] of Object.entries(brandColorVars(kit))) root.style.setProperty(name, value);
|
|
313
|
+
for (const name of FONT_VARS.heading) root.style.setProperty(name, kit.fonts.heading);
|
|
314
|
+
for (const name of FONT_VARS.body) root.style.setProperty(name, kit.fonts.body);
|
|
315
|
+
loadBrandFonts([familyOf(kit.fonts.heading), familyOf(kit.fonts.body)]);
|
|
316
|
+
}
|
|
317
|
+
|
|
194
318
|
// src/ui/ai-tree/aiSectionsManager.tsx
|
|
195
319
|
var import_react_dom = require("react-dom");
|
|
196
320
|
var import_client = require("react-dom/client");
|
|
@@ -223,6 +347,17 @@ var FEATURE_LINE_CSS = [
|
|
|
223
347
|
function textAttrs(ctx, path) {
|
|
224
348
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
225
349
|
}
|
|
350
|
+
var AI_RESPONSIVE_CSS = [
|
|
351
|
+
"@media (max-width: 960px) {",
|
|
352
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
|
|
353
|
+
' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
|
|
354
|
+
"}",
|
|
355
|
+
"@media (max-width: 640px) {",
|
|
356
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
357
|
+
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
358
|
+
" [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
359
|
+
"}"
|
|
360
|
+
].join("\n");
|
|
226
361
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
227
362
|
function MediaBox({
|
|
228
363
|
refValue,
|
|
@@ -235,13 +370,17 @@ function MediaBox({
|
|
|
235
370
|
const url = refValue ? ctx.resolveMedia(refValue) : null;
|
|
236
371
|
const isIcon = /^(lucide|simple):/.test(refValue);
|
|
237
372
|
const aspectRatio = aspect && /^\d+:\d+$/.test(aspect) ? aspect.replace(":", " / ") : void 0;
|
|
238
|
-
const editAttrs = ctx.keyFor && editPath
|
|
373
|
+
const editAttrs = ctx.keyFor && editPath ? {
|
|
374
|
+
"data-ohw-key": ctx.keyFor(editPath),
|
|
375
|
+
"data-ohw-editable": isIcon ? "icon" : "image"
|
|
376
|
+
} : {};
|
|
239
377
|
if (isIcon) {
|
|
240
378
|
const Icon = refValue.startsWith("lucide:") ? lucideByName(refValue.slice(7)) : null;
|
|
241
379
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
242
380
|
"span",
|
|
243
381
|
{
|
|
244
382
|
"data-ai-icon": refValue,
|
|
383
|
+
...editAttrs,
|
|
245
384
|
style: {
|
|
246
385
|
display: "inline-flex",
|
|
247
386
|
width: 48,
|
|
@@ -961,6 +1100,7 @@ function Carousel({ items, itemsPerRow, ctx }) {
|
|
|
961
1100
|
children: pageGroups.map((group, p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
962
1101
|
"div",
|
|
963
1102
|
{
|
|
1103
|
+
"data-ai-grid": String(itemsPerRow),
|
|
964
1104
|
style: {
|
|
965
1105
|
flex: "0 0 100%",
|
|
966
1106
|
display: "grid",
|
|
@@ -1064,6 +1204,7 @@ function CollectionBlock({ node, ctx, path }) {
|
|
|
1064
1204
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1065
1205
|
"div",
|
|
1066
1206
|
{
|
|
1207
|
+
"data-ai-grid": String(itemsPerRow),
|
|
1067
1208
|
style: {
|
|
1068
1209
|
display: "grid",
|
|
1069
1210
|
gridTemplateColumns: `repeat(${itemsPerRow}, 1fr)`,
|
|
@@ -1227,6 +1368,7 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1227
1368
|
{
|
|
1228
1369
|
"data-ai-section": tree.tag ?? "",
|
|
1229
1370
|
...bgAttrs,
|
|
1371
|
+
"data-ai-responsive": "",
|
|
1230
1372
|
style: {
|
|
1231
1373
|
position: "relative",
|
|
1232
1374
|
padding: `${pad}px 0`,
|
|
@@ -1236,10 +1378,12 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1236
1378
|
backgroundPosition: "center"
|
|
1237
1379
|
},
|
|
1238
1380
|
children: [
|
|
1381
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
|
|
1239
1382
|
isOverlay && backgroundUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
1240
1383
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1241
1384
|
"div",
|
|
1242
1385
|
{
|
|
1386
|
+
"data-ai-section-inner": "",
|
|
1243
1387
|
style: {
|
|
1244
1388
|
position: "relative",
|
|
1245
1389
|
maxWidth: AI_TREE_TOKENS.sectionMaxWidth,
|
|
@@ -1250,6 +1394,7 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1250
1394
|
children: tree.rows.map((row, r2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1251
1395
|
"div",
|
|
1252
1396
|
{
|
|
1397
|
+
"data-ai-columns": "",
|
|
1253
1398
|
style: {
|
|
1254
1399
|
display: "grid",
|
|
1255
1400
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
@@ -1273,17 +1418,34 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
|
1273
1418
|
var CONTAINER_ATTR = "data-ohw-ai-generated";
|
|
1274
1419
|
var REPLACED_ATTR = "data-ohw-ai-replaced-by";
|
|
1275
1420
|
var REMOVED_ATTR = "data-ohw-ai-removed";
|
|
1421
|
+
function readRootVar(name) {
|
|
1422
|
+
if (typeof document === "undefined") return "";
|
|
1423
|
+
return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
|
|
1424
|
+
}
|
|
1425
|
+
function deriveBrandOverride() {
|
|
1426
|
+
const dark = readRootVar("--ohw-brand-dark");
|
|
1427
|
+
const primary = readRootVar("--ohw-brand-primary");
|
|
1428
|
+
const light = readRootVar("--ohw-brand-light");
|
|
1429
|
+
if (!dark || !primary || !light) return null;
|
|
1430
|
+
const accent = readRootVar("--ohw-brand-accent");
|
|
1431
|
+
const heading = readRootVar("--font-heading") || readRootVar("--font-display");
|
|
1432
|
+
const body = readRootVar("--font-body");
|
|
1433
|
+
return {
|
|
1434
|
+
palette: { dark, primary, accent: accent || dark, light },
|
|
1435
|
+
fonts: {
|
|
1436
|
+
heading: heading || AI_DEFAULT_BRAND.fonts.heading,
|
|
1437
|
+
body: body || AI_DEFAULT_BRAND.fonts.body
|
|
1438
|
+
}
|
|
1439
|
+
};
|
|
1440
|
+
}
|
|
1276
1441
|
function deriveTemplateBrand() {
|
|
1277
|
-
|
|
1278
|
-
const
|
|
1279
|
-
const
|
|
1280
|
-
const dark = read("--color-dark");
|
|
1281
|
-
const primary = read("--color-primary");
|
|
1282
|
-
const light = read("--color-light");
|
|
1442
|
+
const dark = readRootVar("--color-dark");
|
|
1443
|
+
const primary = readRootVar("--color-primary");
|
|
1444
|
+
const light = readRootVar("--color-light");
|
|
1283
1445
|
if (!dark || !primary || !light) return null;
|
|
1284
|
-
const accent =
|
|
1285
|
-
const heading =
|
|
1286
|
-
const body =
|
|
1446
|
+
const accent = readRootVar("--color-accent");
|
|
1447
|
+
const heading = readRootVar("--font-heading") || readRootVar("--font-display");
|
|
1448
|
+
const body = readRootVar("--font-body");
|
|
1287
1449
|
return {
|
|
1288
1450
|
palette: { dark, primary, accent: accent || dark, light },
|
|
1289
1451
|
fonts: {
|
|
@@ -1375,7 +1537,9 @@ function syncReplacedOriginals(state) {
|
|
|
1375
1537
|
}
|
|
1376
1538
|
function applyAiSectionsToDom(state, options) {
|
|
1377
1539
|
if (typeof document === "undefined") return;
|
|
1540
|
+
const brandOverride = deriveBrandOverride();
|
|
1378
1541
|
const templateBrand = deriveTemplateBrand();
|
|
1542
|
+
const brandKey = brandOverride ? JSON.stringify(brandOverride) : "";
|
|
1379
1543
|
const activeIds = new Set(state.sections.map((entry) => entry.id));
|
|
1380
1544
|
for (const [id, section] of mounted) {
|
|
1381
1545
|
if (!activeIds.has(id)) {
|
|
@@ -1385,7 +1549,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1385
1549
|
}
|
|
1386
1550
|
}
|
|
1387
1551
|
for (const entry of state.sections) {
|
|
1388
|
-
const serialized = JSON.stringify(entry);
|
|
1552
|
+
const serialized = JSON.stringify(entry) + brandKey;
|
|
1389
1553
|
const existing = mounted.get(entry.id);
|
|
1390
1554
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
1391
1555
|
continue;
|
|
@@ -1409,7 +1573,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1409
1573
|
AiTreeRenderer,
|
|
1410
1574
|
{
|
|
1411
1575
|
tree: entry.tree,
|
|
1412
|
-
brand: entry.brand ?? options?.brand ?? templateBrand ?? void 0,
|
|
1576
|
+
brand: brandOverride ?? entry.brand ?? options?.brand ?? templateBrand ?? void 0,
|
|
1413
1577
|
resolveMedia,
|
|
1414
1578
|
editKeyPrefix: `ai.${entry.id}`
|
|
1415
1579
|
}
|
|
@@ -2026,7 +2190,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
2026
2190
|
const autoId = (0, import_react5.useId)();
|
|
2027
2191
|
const insertAfter = insertAfterProp ?? autoId;
|
|
2028
2192
|
const [schedule, setSchedule] = (0, import_react5.useState)(null);
|
|
2029
|
-
const [loading, setLoading] = (0, import_react5.useState)(
|
|
2193
|
+
const [loading, setLoading] = (0, import_react5.useState)(initialScheduleId !== null);
|
|
2030
2194
|
const [inEditor, setInEditor] = (0, import_react5.useState)(false);
|
|
2031
2195
|
const [isHovered, setIsHovered] = (0, import_react5.useState)(false);
|
|
2032
2196
|
const [modalState, setModalState] = (0, import_react5.useState)(null);
|
|
@@ -2200,8 +2364,10 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
2200
2364
|
"*"
|
|
2201
2365
|
);
|
|
2202
2366
|
};
|
|
2203
|
-
if (!inEditor && !loading && !schedule) return null;
|
|
2204
2367
|
const sectionId = `scheduling-${insertAfter}`;
|
|
2368
|
+
if (!inEditor && !loading && !schedule) {
|
|
2369
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("section", { "data-ohw-section": sectionId, "data-ohw-scheduling-anchor": insertAfter, style: { display: "none" } });
|
|
2370
|
+
}
|
|
2205
2371
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2206
2372
|
"section",
|
|
2207
2373
|
{
|
|
@@ -5935,6 +6101,7 @@ function ToolbarActionTooltip({
|
|
|
5935
6101
|
function ItemActionToolbar({
|
|
5936
6102
|
onEditLink,
|
|
5937
6103
|
onAddItem,
|
|
6104
|
+
onStyle,
|
|
5938
6105
|
onSelectParent,
|
|
5939
6106
|
onDuplicate,
|
|
5940
6107
|
onDelete,
|
|
@@ -5946,6 +6113,8 @@ function ItemActionToolbar({
|
|
|
5946
6113
|
deleteDisabled = false,
|
|
5947
6114
|
showEditLink = true,
|
|
5948
6115
|
showAddItem = true,
|
|
6116
|
+
showStyle = false,
|
|
6117
|
+
styleActive = false,
|
|
5949
6118
|
showMore = true,
|
|
5950
6119
|
tooltipSide = "bottom",
|
|
5951
6120
|
dropdownOpen = null,
|
|
@@ -6019,6 +6188,22 @@ function ItemActionToolbar({
|
|
|
6019
6188
|
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.Link, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
6020
6189
|
}
|
|
6021
6190
|
) : null,
|
|
6191
|
+
showStyle ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
6192
|
+
ToolbarActionTooltip,
|
|
6193
|
+
{
|
|
6194
|
+
label: "Style",
|
|
6195
|
+
side: tooltipSide,
|
|
6196
|
+
buttonProps: {
|
|
6197
|
+
active: styleActive,
|
|
6198
|
+
onMouseDown: (e) => {
|
|
6199
|
+
e.preventDefault();
|
|
6200
|
+
e.stopPropagation();
|
|
6201
|
+
onStyle?.();
|
|
6202
|
+
}
|
|
6203
|
+
},
|
|
6204
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.Brush, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
6205
|
+
}
|
|
6206
|
+
) : null,
|
|
6022
6207
|
showAddItem ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
6023
6208
|
ToolbarActionTooltip,
|
|
6024
6209
|
{
|
|
@@ -6136,6 +6321,7 @@ var FOCUS_RING = `0 0 0 4px color-mix(in srgb, ${PRIMARY} 12%, transparent)`;
|
|
|
6136
6321
|
var DRAG_SHADOW = "0px 4px 6px -1px rgba(0, 0, 0, 0.1), 0px 2px 4px -2px rgba(0, 0, 0, 0.1)";
|
|
6137
6322
|
var TOOLBAR_EDGE_MARGIN = 4;
|
|
6138
6323
|
var SELECTION_CHROME_GAP = 4;
|
|
6324
|
+
var HOVER_CHROME_GAP = 2;
|
|
6139
6325
|
var TOOLBAR_STROKE_GAP = 4;
|
|
6140
6326
|
function getChromeZIndex(state) {
|
|
6141
6327
|
switch (state) {
|
|
@@ -6291,10 +6477,11 @@ function ItemInteractionLayer({
|
|
|
6291
6477
|
onItemPointerDown,
|
|
6292
6478
|
onItemClick,
|
|
6293
6479
|
itemDragSurface = true,
|
|
6294
|
-
chromeGap
|
|
6480
|
+
chromeGap,
|
|
6295
6481
|
className
|
|
6296
6482
|
}) {
|
|
6297
6483
|
if (state === "default") return null;
|
|
6484
|
+
const gap = chromeGap ?? (state === "hover" ? HOVER_CHROME_GAP : SELECTION_CHROME_GAP);
|
|
6298
6485
|
const isActive = state === "active-top" || state === "active-bottom";
|
|
6299
6486
|
const isDragging = state === "dragging";
|
|
6300
6487
|
const showToolbar = isActive && toolbar;
|
|
@@ -6310,10 +6497,10 @@ function ItemInteractionLayer({
|
|
|
6310
6497
|
className: cn("pointer-events-none", className),
|
|
6311
6498
|
style: {
|
|
6312
6499
|
position: "fixed",
|
|
6313
|
-
top: rect.top -
|
|
6314
|
-
left: rect.left -
|
|
6315
|
-
width: rect.width +
|
|
6316
|
-
height: rect.height +
|
|
6500
|
+
top: rect.top - gap,
|
|
6501
|
+
left: rect.left - gap,
|
|
6502
|
+
width: rect.width + gap * 2,
|
|
6503
|
+
height: rect.height + gap * 2,
|
|
6317
6504
|
zIndex: getChromeZIndex(state)
|
|
6318
6505
|
},
|
|
6319
6506
|
children: [
|
|
@@ -9525,9 +9712,453 @@ function deleteNavbarItem(sourceAnchor) {
|
|
|
9525
9712
|
};
|
|
9526
9713
|
}
|
|
9527
9714
|
|
|
9715
|
+
// src/lib/icon-markup.ts
|
|
9716
|
+
var GLYPH_SELECTOR = "svg, img";
|
|
9717
|
+
function referenceBox(slot) {
|
|
9718
|
+
const row = slot.closest("[data-ohw-socials-row]") ?? slot.closest("a")?.parentElement ?? null;
|
|
9719
|
+
const neighbour = row ? Array.from(row.querySelectorAll('[data-ohw-editable="icon"]')).find((el) => el !== slot) : null;
|
|
9720
|
+
const source = (neighbour ?? slot).querySelector(GLYPH_SELECTOR);
|
|
9721
|
+
const box = source?.getBoundingClientRect() ?? null;
|
|
9722
|
+
return box?.width && box.height ? box : null;
|
|
9723
|
+
}
|
|
9724
|
+
function iconMarkupSizedFor(slot, markup) {
|
|
9725
|
+
const box = referenceBox(slot);
|
|
9726
|
+
if (!box) return markup;
|
|
9727
|
+
const holder = document.createElement("div");
|
|
9728
|
+
holder.innerHTML = markup;
|
|
9729
|
+
const glyph = holder.querySelector(GLYPH_SELECTOR);
|
|
9730
|
+
if (!glyph) return markup;
|
|
9731
|
+
glyph.style.width = `${Math.round(box.width)}px`;
|
|
9732
|
+
glyph.style.height = `${Math.round(box.height)}px`;
|
|
9733
|
+
return holder.innerHTML;
|
|
9734
|
+
}
|
|
9735
|
+
function applyIconMarkup(slot, markup) {
|
|
9736
|
+
if (!markup) return;
|
|
9737
|
+
const coloured = iconMarkupInheritingColour(markup);
|
|
9738
|
+
const sized = iconMarkupSizedFor(slot, coloured);
|
|
9739
|
+
if (slot.innerHTML !== sized) slot.innerHTML = sized;
|
|
9740
|
+
if (sized === coloured) {
|
|
9741
|
+
requestAnimationFrame(() => {
|
|
9742
|
+
if (!slot.isConnected) return;
|
|
9743
|
+
const resized = iconMarkupSizedFor(slot, coloured);
|
|
9744
|
+
if (resized !== coloured && slot.innerHTML !== resized) slot.innerHTML = resized;
|
|
9745
|
+
});
|
|
9746
|
+
}
|
|
9747
|
+
}
|
|
9748
|
+
function detectIconStyle(el) {
|
|
9749
|
+
const row = el.closest("[data-ohw-socials-row]");
|
|
9750
|
+
const glyphs = Array.from((row ?? el).querySelectorAll("svg"));
|
|
9751
|
+
const outlined = glyphs.some((svg) => {
|
|
9752
|
+
return Array.from(svg.querySelectorAll("*")).some((node) => {
|
|
9753
|
+
return node.getAttribute("stroke") !== null && node.getAttribute("stroke") !== "none";
|
|
9754
|
+
});
|
|
9755
|
+
});
|
|
9756
|
+
return outlined ? "outline" : "fill";
|
|
9757
|
+
}
|
|
9758
|
+
function iconMarkupInheritingColour(markup) {
|
|
9759
|
+
const holder = document.createElement("div");
|
|
9760
|
+
holder.innerHTML = markup;
|
|
9761
|
+
holder.querySelectorAll("svg *").forEach((node) => {
|
|
9762
|
+
if (node.getAttribute("fill") && node.getAttribute("fill") !== "none") {
|
|
9763
|
+
node.setAttribute("fill", "currentColor");
|
|
9764
|
+
}
|
|
9765
|
+
if (node.getAttribute("stroke") && node.getAttribute("stroke") !== "none") {
|
|
9766
|
+
node.setAttribute("stroke", "currentColor");
|
|
9767
|
+
}
|
|
9768
|
+
});
|
|
9769
|
+
return holder.innerHTML;
|
|
9770
|
+
}
|
|
9771
|
+
|
|
9772
|
+
// src/lib/socials-items.ts
|
|
9773
|
+
var ICON_SELECTOR = '[data-ohw-editable="icon"]';
|
|
9774
|
+
var SOCIAL_KEY_RE = /(^|-)social(s)?(-|$)/i;
|
|
9775
|
+
var SOCIALS_ROW_ATTR = "data-ohw-socials-row";
|
|
9776
|
+
var SOCIALS_ITEM_ATTR = "data-ohw-social-item";
|
|
9777
|
+
function isSocialItem(el) {
|
|
9778
|
+
if (!el) return false;
|
|
9779
|
+
const anchor = el instanceof HTMLAnchorElement ? el : el.closest("a");
|
|
9780
|
+
if (!anchor) return false;
|
|
9781
|
+
if (SOCIAL_KEY_RE.test(anchor.getAttribute("data-ohw-href-key") ?? "")) return true;
|
|
9782
|
+
return anchor.querySelectorAll(ICON_SELECTOR).length === 1;
|
|
9783
|
+
}
|
|
9784
|
+
function getSocialItem(el) {
|
|
9785
|
+
const anchor = el.closest("a");
|
|
9786
|
+
return isSocialItem(anchor) ? anchor : null;
|
|
9787
|
+
}
|
|
9788
|
+
function findSocialsRow(el) {
|
|
9789
|
+
const item = getSocialItem(el);
|
|
9790
|
+
if (!item) return null;
|
|
9791
|
+
const wrapper = item.parentElement;
|
|
9792
|
+
const row = wrapper && wrapper.querySelectorAll("a").length === 1 && wrapper.matches("li, div, span") ? wrapper.parentElement : wrapper;
|
|
9793
|
+
if (!row) return null;
|
|
9794
|
+
const anchors = Array.from(row.querySelectorAll("a"));
|
|
9795
|
+
if (!anchors.length || !anchors.every((anchor) => isSocialItem(anchor))) return null;
|
|
9796
|
+
return row;
|
|
9797
|
+
}
|
|
9798
|
+
function isSocialsRow(el) {
|
|
9799
|
+
const anchors = Array.from(el.querySelectorAll("a"));
|
|
9800
|
+
return anchors.length > 0 && anchors.every((anchor) => isSocialItem(anchor));
|
|
9801
|
+
}
|
|
9802
|
+
function listSocialItems(row) {
|
|
9803
|
+
return Array.from(row.children).map((child) => {
|
|
9804
|
+
if (!(child instanceof HTMLElement)) return null;
|
|
9805
|
+
const anchor = child.matches("a") ? child : child.querySelector("a");
|
|
9806
|
+
return isSocialItem(anchor) ? anchor : null;
|
|
9807
|
+
}).filter((item) => item !== null);
|
|
9808
|
+
}
|
|
9809
|
+
function socialRowUnit(item) {
|
|
9810
|
+
const row = findSocialsRow(item);
|
|
9811
|
+
let node = item;
|
|
9812
|
+
while (node.parentElement && node.parentElement !== row) {
|
|
9813
|
+
node = node.parentElement;
|
|
9814
|
+
}
|
|
9815
|
+
return node;
|
|
9816
|
+
}
|
|
9817
|
+
function listSocialsRows(root = document) {
|
|
9818
|
+
const rows = /* @__PURE__ */ new Set();
|
|
9819
|
+
root.querySelectorAll(`${ICON_SELECTOR}, a[data-ohw-href-key]`).forEach((el) => {
|
|
9820
|
+
const row = findSocialsRow(el);
|
|
9821
|
+
if (row) rows.add(row);
|
|
9822
|
+
});
|
|
9823
|
+
root.querySelectorAll(`[${SOCIALS_ROW_ATTR}]`).forEach((row) => rows.add(row));
|
|
9824
|
+
return Array.from(rows);
|
|
9825
|
+
}
|
|
9826
|
+
var rowTemplates = /* @__PURE__ */ new Map();
|
|
9827
|
+
function markSocialsRows(root = document) {
|
|
9828
|
+
root.querySelectorAll(`[${SOCIALS_ITEM_ATTR}]`).forEach((item) => {
|
|
9829
|
+
item.removeAttribute(SOCIALS_ITEM_ATTR);
|
|
9830
|
+
});
|
|
9831
|
+
listSocialsRows(root).forEach((row) => {
|
|
9832
|
+
row.setAttribute(SOCIALS_ROW_ATTR, "");
|
|
9833
|
+
const items = listSocialItems(row);
|
|
9834
|
+
if (items[0]) rowTemplates.set(rowKeyOf(row), socialRowUnit(items[0]).outerHTML);
|
|
9835
|
+
items.forEach((item, index) => {
|
|
9836
|
+
item.setAttribute(SOCIALS_ITEM_ATTR, String(index));
|
|
9837
|
+
const iconKey = socialIconKey(item);
|
|
9838
|
+
if (iconKey) ensureLabelSlot(item, iconKey);
|
|
9839
|
+
});
|
|
9840
|
+
});
|
|
9841
|
+
}
|
|
9842
|
+
var SOCIALS_LABEL_ATTR = "data-ohw-social-label";
|
|
9843
|
+
function ensureLabelSlot(item, iconKey) {
|
|
9844
|
+
if (socialLabelElement(item)) return;
|
|
9845
|
+
const label = document.createElement("span");
|
|
9846
|
+
label.setAttribute("data-ohw-key", `${iconKey}-label`);
|
|
9847
|
+
label.setAttribute("data-ohw-editable", "text");
|
|
9848
|
+
label.setAttribute(SOCIALS_LABEL_ATTR, "");
|
|
9849
|
+
label.style.display = "none";
|
|
9850
|
+
label.textContent = item.getAttribute("aria-label") ?? "";
|
|
9851
|
+
item.appendChild(label);
|
|
9852
|
+
}
|
|
9853
|
+
function socialLabelElement(item) {
|
|
9854
|
+
return item.querySelector(
|
|
9855
|
+
`[${SOCIALS_LABEL_ATTR}], [data-ohw-editable="text"], [data-ohw-editable="plain"]`
|
|
9856
|
+
);
|
|
9857
|
+
}
|
|
9858
|
+
function socialLabelKey(iconKey) {
|
|
9859
|
+
return `${iconKey}-label`;
|
|
9860
|
+
}
|
|
9861
|
+
function applyStoredValues(item, content) {
|
|
9862
|
+
const hrefKey = socialHrefKey(item);
|
|
9863
|
+
const iconKey = socialIconKey(item);
|
|
9864
|
+
if (hrefKey && content[hrefKey] !== void 0) item.setAttribute("href", content[hrefKey]);
|
|
9865
|
+
if (iconKey) {
|
|
9866
|
+
const glyph = item.querySelector(ICON_SELECTOR);
|
|
9867
|
+
if (glyph && content[iconKey]) applyIconMarkup(glyph, content[iconKey]);
|
|
9868
|
+
const label = item.querySelector(`[${SOCIALS_LABEL_ATTR}]`);
|
|
9869
|
+
label?.setAttribute("data-ohw-key", socialLabelKey(iconKey));
|
|
9870
|
+
const stored = content[socialLabelKey(iconKey)];
|
|
9871
|
+
if (label && stored) label.textContent = stored;
|
|
9872
|
+
}
|
|
9873
|
+
}
|
|
9874
|
+
function socialPlatformKey(iconKey) {
|
|
9875
|
+
return `${iconKey}-platform`;
|
|
9876
|
+
}
|
|
9877
|
+
function socialHrefKey(item) {
|
|
9878
|
+
return item.getAttribute("data-ohw-href-key");
|
|
9879
|
+
}
|
|
9880
|
+
function socialIconKey(item) {
|
|
9881
|
+
return item.querySelector(ICON_SELECTOR)?.dataset.ohwKey ?? null;
|
|
9882
|
+
}
|
|
9883
|
+
var SOCIALS_ORDER_KEY = "__ohw_socials_order";
|
|
9884
|
+
function fromMarkup(markup) {
|
|
9885
|
+
const holder = document.createElement("div");
|
|
9886
|
+
holder.innerHTML = markup;
|
|
9887
|
+
return holder.firstElementChild instanceof HTMLElement ? holder.firstElementChild : null;
|
|
9888
|
+
}
|
|
9889
|
+
var rowKeys = /* @__PURE__ */ new WeakMap();
|
|
9890
|
+
function rowKeyOf(row) {
|
|
9891
|
+
const first = listSocialItems(row)[0];
|
|
9892
|
+
const itemKey = first ? socialIconKey(first) ?? socialHrefKey(first)?.replace(/-href$/, "") : null;
|
|
9893
|
+
const derived = itemKey?.replace(/-[^-]+$/, "") || null;
|
|
9894
|
+
if (derived) rowKeys.set(row, derived);
|
|
9895
|
+
return derived ?? rowKeys.get(row) ?? "social";
|
|
9896
|
+
}
|
|
9897
|
+
function getSocialsOrderFromDom(root = document) {
|
|
9898
|
+
const order = {};
|
|
9899
|
+
listSocialsRows(root).forEach((row) => {
|
|
9900
|
+
order[rowKeyOf(row)] = listSocialItems(row).map((item) => socialHrefKey(item)).filter((key) => Boolean(key));
|
|
9901
|
+
});
|
|
9902
|
+
return order;
|
|
9903
|
+
}
|
|
9904
|
+
function hasStoredValue(content, hrefKey) {
|
|
9905
|
+
const iconKey = hrefKey.replace(/-href$/, "");
|
|
9906
|
+
return Boolean(content[hrefKey]) || Boolean(content[iconKey]);
|
|
9907
|
+
}
|
|
9908
|
+
function parseSocialsOrder(raw) {
|
|
9909
|
+
if (!raw) return null;
|
|
9910
|
+
try {
|
|
9911
|
+
const parsed = JSON.parse(raw);
|
|
9912
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
9913
|
+
} catch {
|
|
9914
|
+
return null;
|
|
9915
|
+
}
|
|
9916
|
+
}
|
|
9917
|
+
function nextSocialIndex(row, rowKey, content) {
|
|
9918
|
+
const used = listSocialItems(row).map((item) => socialHrefKey(item)).concat(Object.keys(content)).map((key) => key?.match(new RegExp(`^${rowKey}-(\\d+)`))?.[1]).map((digits) => digits === void 0 ? -1 : Number(digits));
|
|
9919
|
+
return Math.max(-1, ...used) + 1;
|
|
9920
|
+
}
|
|
9921
|
+
function insertSocialItem(row, after, content = {}) {
|
|
9922
|
+
const rowKey = rowKeyOf(row);
|
|
9923
|
+
const template = listSocialItems(row)[0];
|
|
9924
|
+
const remembered = rowTemplates.get(rowKey);
|
|
9925
|
+
if (!template && !remembered) return null;
|
|
9926
|
+
const index = nextSocialIndex(row, rowKey, content);
|
|
9927
|
+
const iconKey = `${rowKey}-${index}`;
|
|
9928
|
+
const hrefKey = `${iconKey}-href`;
|
|
9929
|
+
const templateUnit = template ? socialRowUnit(template) : null;
|
|
9930
|
+
const unit = templateUnit ? templateUnit.cloneNode(true) : fromMarkup(remembered);
|
|
9931
|
+
const item = unit && (unit.matches("a") ? unit : unit.querySelector("a"));
|
|
9932
|
+
if (!unit || !item) return null;
|
|
9933
|
+
item.setAttribute("data-ohw-href-key", hrefKey);
|
|
9934
|
+
item.setAttribute("href", "");
|
|
9935
|
+
item.removeAttribute("aria-label");
|
|
9936
|
+
item.querySelectorAll("[data-ohw-hovered], [data-ohw-selected]").forEach((el) => {
|
|
9937
|
+
el.removeAttribute("data-ohw-hovered");
|
|
9938
|
+
el.removeAttribute("data-ohw-selected");
|
|
9939
|
+
});
|
|
9940
|
+
const icon = item.querySelector(ICON_SELECTOR);
|
|
9941
|
+
icon?.setAttribute("data-ohw-key", iconKey);
|
|
9942
|
+
item.querySelector(`[${SOCIALS_LABEL_ATTR}]`)?.remove();
|
|
9943
|
+
const afterUnit = after ? socialRowUnit(after) : null;
|
|
9944
|
+
if (afterUnit && afterUnit.parentElement === row) afterUnit.insertAdjacentElement("afterend", unit);
|
|
9945
|
+
else row.appendChild(unit);
|
|
9946
|
+
markSocialsRows(row.ownerDocument);
|
|
9947
|
+
return { item, hrefKey, iconKey, order: getSocialsOrderFromDom(row.ownerDocument) };
|
|
9948
|
+
}
|
|
9949
|
+
function duplicateSocialItem(item, content) {
|
|
9950
|
+
const row = findSocialsRow(item);
|
|
9951
|
+
const created = row ? insertSocialItem(row, item, content) : null;
|
|
9952
|
+
if (!created) return null;
|
|
9953
|
+
const sourceHref = socialHrefKey(item);
|
|
9954
|
+
const sourceIcon = socialIconKey(item);
|
|
9955
|
+
const link = created.item;
|
|
9956
|
+
if (sourceHref) link.setAttribute("href", item.getAttribute("href") ?? "");
|
|
9957
|
+
const glyph = item.querySelector(ICON_SELECTOR)?.innerHTML;
|
|
9958
|
+
if (glyph) {
|
|
9959
|
+
const slot = link.querySelector(ICON_SELECTOR);
|
|
9960
|
+
if (slot) slot.innerHTML = glyph;
|
|
9961
|
+
}
|
|
9962
|
+
return {
|
|
9963
|
+
...created,
|
|
9964
|
+
copiedFrom: { href: sourceHref, icon: sourceIcon }
|
|
9965
|
+
};
|
|
9966
|
+
}
|
|
9967
|
+
function removeSocialItem(item, content) {
|
|
9968
|
+
const row = findSocialsRow(item);
|
|
9969
|
+
if (!row) return null;
|
|
9970
|
+
const hrefKey = socialHrefKey(item);
|
|
9971
|
+
const iconKey = socialIconKey(item);
|
|
9972
|
+
const removedKeys = [hrefKey, iconKey].filter((key) => Boolean(key));
|
|
9973
|
+
if (!removedKeys.length) return null;
|
|
9974
|
+
const previousOrder = getSocialsOrderFromDom(row.ownerDocument);
|
|
9975
|
+
const previousContent = Object.fromEntries(
|
|
9976
|
+
removedKeys.filter((key) => key in content).map((key) => [key, content[key]])
|
|
9977
|
+
);
|
|
9978
|
+
const unit = socialRowUnit(item);
|
|
9979
|
+
const nextSibling = unit.nextElementSibling;
|
|
9980
|
+
unit.remove();
|
|
9981
|
+
markSocialsRows(row.ownerDocument);
|
|
9982
|
+
return {
|
|
9983
|
+
removedKeys,
|
|
9984
|
+
previousContent,
|
|
9985
|
+
order: getSocialsOrderFromDom(row.ownerDocument),
|
|
9986
|
+
previousOrder,
|
|
9987
|
+
undo: () => {
|
|
9988
|
+
if (nextSibling) nextSibling.before(unit);
|
|
9989
|
+
else row.appendChild(unit);
|
|
9990
|
+
markSocialsRows(row.ownerDocument);
|
|
9991
|
+
}
|
|
9992
|
+
};
|
|
9993
|
+
}
|
|
9994
|
+
function applySocialsOrder(order, root = document) {
|
|
9995
|
+
listSocialsRows(root).forEach((row) => {
|
|
9996
|
+
const wanted = order[rowKeyOf(row)];
|
|
9997
|
+
if (!wanted) return;
|
|
9998
|
+
const byKey = new Map(listSocialItems(row).map((item) => [socialHrefKey(item), item]));
|
|
9999
|
+
wanted.forEach((key) => {
|
|
10000
|
+
const item = byKey.get(key);
|
|
10001
|
+
if (item) row.appendChild(socialRowUnit(item));
|
|
10002
|
+
});
|
|
10003
|
+
});
|
|
10004
|
+
markSocialsRows(root);
|
|
10005
|
+
}
|
|
10006
|
+
function reconcileSocialsFromContent(content, root = document) {
|
|
10007
|
+
markSocialsRows(root);
|
|
10008
|
+
const stored = parseSocialsOrder(content[SOCIALS_ORDER_KEY]);
|
|
10009
|
+
if (!stored) return;
|
|
10010
|
+
listSocialsRows(root).forEach((row) => {
|
|
10011
|
+
const wanted = stored[rowKeyOf(row)];
|
|
10012
|
+
if (!wanted) return;
|
|
10013
|
+
if (!wanted.length) return;
|
|
10014
|
+
wanted.forEach((key) => {
|
|
10015
|
+
if (listSocialItems(row).some((item) => socialHrefKey(item) === key)) return;
|
|
10016
|
+
if (!hasStoredValue(content, key)) return;
|
|
10017
|
+
const created = insertSocialItem(row, null, content);
|
|
10018
|
+
if (created) {
|
|
10019
|
+
created.item.setAttribute("data-ohw-href-key", key);
|
|
10020
|
+
created.item.querySelector(ICON_SELECTOR)?.setAttribute("data-ohw-key", key.replace(/-href$/, ""));
|
|
10021
|
+
applyStoredValues(created.item, content);
|
|
10022
|
+
}
|
|
10023
|
+
});
|
|
10024
|
+
const present = listSocialItems(row);
|
|
10025
|
+
const surviving = present.filter((item) => {
|
|
10026
|
+
const key = socialHrefKey(item);
|
|
10027
|
+
return !key || wanted.includes(key);
|
|
10028
|
+
});
|
|
10029
|
+
if (surviving.length) {
|
|
10030
|
+
present.forEach((item) => {
|
|
10031
|
+
if (!surviving.includes(item)) socialRowUnit(item).remove();
|
|
10032
|
+
});
|
|
10033
|
+
}
|
|
10034
|
+
});
|
|
10035
|
+
applySocialsOrder(stored, root);
|
|
10036
|
+
}
|
|
10037
|
+
var DROP_BAR_THICKNESS = 3;
|
|
10038
|
+
var DROP_BAR_GAP = 8;
|
|
10039
|
+
function buildSocialDropSlots(row) {
|
|
10040
|
+
const items = listSocialItems(row);
|
|
10041
|
+
if (!items.length) return [];
|
|
10042
|
+
const rects = items.map((item) => item.getBoundingClientRect());
|
|
10043
|
+
return items.concat(items[items.length - 1]).map((_, index) => {
|
|
10044
|
+
const previous = rects[index - 1];
|
|
10045
|
+
const next = rects[index];
|
|
10046
|
+
const centre = previous && next ? (previous.right + next.left) / 2 : next ? next.left - DROP_BAR_GAP : previous.right + DROP_BAR_GAP;
|
|
10047
|
+
const rect = next ?? previous;
|
|
10048
|
+
return {
|
|
10049
|
+
insertIndex: index,
|
|
10050
|
+
columnIndex: -1,
|
|
10051
|
+
left: centre - DROP_BAR_THICKNESS / 2,
|
|
10052
|
+
top: rect.top,
|
|
10053
|
+
width: DROP_BAR_THICKNESS,
|
|
10054
|
+
height: rect.height,
|
|
10055
|
+
direction: "vertical"
|
|
10056
|
+
};
|
|
10057
|
+
});
|
|
10058
|
+
}
|
|
10059
|
+
function findSocialByHrefKey(hrefKey, root = document) {
|
|
10060
|
+
const el = root.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`);
|
|
10061
|
+
return el ? getSocialItem(el) : null;
|
|
10062
|
+
}
|
|
10063
|
+
function buildSocialDropSlotsForKey(hrefKey, root = document) {
|
|
10064
|
+
const item = findSocialByHrefKey(hrefKey, root);
|
|
10065
|
+
const row = item ? findSocialsRow(item) : null;
|
|
10066
|
+
return row ? buildSocialDropSlots(row) : [];
|
|
10067
|
+
}
|
|
10068
|
+
function hitTestSocialDropSlot(clientX, clientY, draggedHrefKey, root = document) {
|
|
10069
|
+
const distanceTo = (slot) => {
|
|
10070
|
+
const dx = clientX - (slot.left + slot.width / 2);
|
|
10071
|
+
const dy = clientY < slot.top ? slot.top - clientY : Math.max(0, clientY - (slot.top + slot.height));
|
|
10072
|
+
return Math.hypot(dx, dy);
|
|
10073
|
+
};
|
|
10074
|
+
const slots = buildSocialDropSlotsForKey(draggedHrefKey, root);
|
|
10075
|
+
return slots.reduce((best, slot) => {
|
|
10076
|
+
return !best || distanceTo(slot) < distanceTo(best) ? slot : best;
|
|
10077
|
+
}, null);
|
|
10078
|
+
}
|
|
10079
|
+
function planSocialMove(hrefKey, insertIndex, root = document) {
|
|
10080
|
+
const item = findSocialByHrefKey(hrefKey, root);
|
|
10081
|
+
const row = item ? findSocialsRow(item) : null;
|
|
10082
|
+
if (!row) return null;
|
|
10083
|
+
const order = getSocialsOrderFromDom(root);
|
|
10084
|
+
const key = rowKeyOf(row);
|
|
10085
|
+
const current = order[key];
|
|
10086
|
+
if (!current) return null;
|
|
10087
|
+
const from = current.indexOf(hrefKey);
|
|
10088
|
+
if (from < 0) return null;
|
|
10089
|
+
const next = current.filter((_, index) => index !== from);
|
|
10090
|
+
next.splice(insertIndex > from ? insertIndex - 1 : insertIndex, 0, hrefKey);
|
|
10091
|
+
return { ...order, [key]: next };
|
|
10092
|
+
}
|
|
10093
|
+
var SOCIALS_DISPLAY_KEY = "__ohw_socials_display";
|
|
10094
|
+
function readSocialsDisplay(row) {
|
|
10095
|
+
const items = listSocialItems(row);
|
|
10096
|
+
const visible = (el) => Boolean(el) && el.style.display !== "none" && el.getAttribute("data-ohw-hidden") === null;
|
|
10097
|
+
return {
|
|
10098
|
+
text: items.some((item) => visible(socialLabelElement(item))),
|
|
10099
|
+
icon: items.some((item) => visible(item.querySelector(ICON_SELECTOR)))
|
|
10100
|
+
};
|
|
10101
|
+
}
|
|
10102
|
+
function parseSocialsDisplay(raw) {
|
|
10103
|
+
if (!raw) return null;
|
|
10104
|
+
try {
|
|
10105
|
+
const parsed = JSON.parse(raw);
|
|
10106
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
10107
|
+
} catch {
|
|
10108
|
+
return null;
|
|
10109
|
+
}
|
|
10110
|
+
}
|
|
10111
|
+
function socialsDisplayFor(row, content) {
|
|
10112
|
+
return parseSocialsDisplay(content[SOCIALS_DISPLAY_KEY])?.[rowKeyOf(row)] ?? readSocialsDisplay(row);
|
|
10113
|
+
}
|
|
10114
|
+
function socialsDisplayWith(row, display, content) {
|
|
10115
|
+
return { ...parseSocialsDisplay(content[SOCIALS_DISPLAY_KEY]) ?? {}, [rowKeyOf(row)]: display };
|
|
10116
|
+
}
|
|
10117
|
+
function applySocialsDisplayToRow(row, display) {
|
|
10118
|
+
listSocialItems(row).forEach((item) => {
|
|
10119
|
+
const label = socialLabelElement(item);
|
|
10120
|
+
const icon = item.querySelector(ICON_SELECTOR);
|
|
10121
|
+
if (label) label.style.display = display.text ? "" : "none";
|
|
10122
|
+
if (icon) icon.style.display = display.icon ? "" : "none";
|
|
10123
|
+
});
|
|
10124
|
+
}
|
|
10125
|
+
function applySocialsDisplayFromContent(content, root = document) {
|
|
10126
|
+
const stored = parseSocialsDisplay(content[SOCIALS_DISPLAY_KEY]);
|
|
10127
|
+
if (!stored) return;
|
|
10128
|
+
listSocialsRows(root).forEach((row) => {
|
|
10129
|
+
const display = stored[rowKeyOf(row)];
|
|
10130
|
+
if (!display) return;
|
|
10131
|
+
if (display.icon) {
|
|
10132
|
+
listSocialItems(row).forEach((item) => {
|
|
10133
|
+
const iconKey = ensureIconSlot(item);
|
|
10134
|
+
const slot = item.querySelector(ICON_SELECTOR);
|
|
10135
|
+
if (iconKey && slot && content[iconKey]) applyIconMarkup(slot, content[iconKey]);
|
|
10136
|
+
});
|
|
10137
|
+
}
|
|
10138
|
+
applySocialsDisplayToRow(row, display);
|
|
10139
|
+
});
|
|
10140
|
+
}
|
|
10141
|
+
function socialsMissingIcons(row) {
|
|
10142
|
+
return listSocialItems(row).filter((item) => !item.querySelector(ICON_SELECTOR)).map((item) => ({ hrefKey: socialHrefKey(item) ?? "", url: item.getAttribute("href") ?? "" })).filter((entry) => Boolean(entry.hrefKey));
|
|
10143
|
+
}
|
|
10144
|
+
function ensureIconSlot(item) {
|
|
10145
|
+
const existing = item.querySelector(ICON_SELECTOR);
|
|
10146
|
+
if (existing) return existing.dataset.ohwKey ?? null;
|
|
10147
|
+
const hrefKey = socialHrefKey(item);
|
|
10148
|
+
if (!hrefKey) return null;
|
|
10149
|
+
const iconKey = hrefKey.replace(/-href$/, "");
|
|
10150
|
+
const slot = document.createElement("span");
|
|
10151
|
+
slot.setAttribute("data-ohw-key", iconKey);
|
|
10152
|
+
slot.setAttribute("data-ohw-editable", "icon");
|
|
10153
|
+
slot.style.display = "inline-flex";
|
|
10154
|
+
item.prepend(slot);
|
|
10155
|
+
return iconKey;
|
|
10156
|
+
}
|
|
10157
|
+
|
|
9528
10158
|
// src/lib/footer-items.ts
|
|
9529
10159
|
var FOOTER_ORDER_KEY = "__ohw_footer_order";
|
|
9530
10160
|
var MAX_FOOTER_COLUMNS = 18;
|
|
10161
|
+
var MAX_FOOTER_ITEMS_PER_COLUMN = 7;
|
|
9531
10162
|
var FOOTER_HREF_RE = /^footer-(\d+)-(\d+)-href$/;
|
|
9532
10163
|
function parseFooterHrefKey(key) {
|
|
9533
10164
|
if (!key) return null;
|
|
@@ -9745,6 +10376,13 @@ function getNextFooterColumnIndex() {
|
|
|
9745
10376
|
function canAddFooterColumn() {
|
|
9746
10377
|
return listFooterColumns().length < MAX_FOOTER_COLUMNS;
|
|
9747
10378
|
}
|
|
10379
|
+
function canAddFooterItem(column) {
|
|
10380
|
+
return listFooterLinksInColumn(column).length < MAX_FOOTER_ITEMS_PER_COLUMN;
|
|
10381
|
+
}
|
|
10382
|
+
function resolveFooterColumnForAdd(selected) {
|
|
10383
|
+
if (selected.hasAttribute("data-ohw-footer-col")) return selected;
|
|
10384
|
+
return selected.closest("[data-ohw-footer-col]") ?? (listFooterColumns().includes(selected) ? selected : null);
|
|
10385
|
+
}
|
|
9748
10386
|
function buildFooterHeading(colIndex, text) {
|
|
9749
10387
|
const heading = document.createElement("p");
|
|
9750
10388
|
heading.setAttribute("data-ohw-editable", "text");
|
|
@@ -10369,6 +11007,329 @@ function deleteFooterColumn(column) {
|
|
|
10369
11007
|
};
|
|
10370
11008
|
}
|
|
10371
11009
|
|
|
11010
|
+
// src/lib/logo-identity.ts
|
|
11011
|
+
var LOGO_TEXT_KEYS = ["nav-logo-text", "footer-logo-text", "logo-text"];
|
|
11012
|
+
var LOGO_IMAGE_KEYS = ["nav-logo-image", "footer-logo", "footer-logo-image"];
|
|
11013
|
+
var LOGO_HREF_KEYS = ["nav-logo-href", "footer-logo-href", "logo-href"];
|
|
11014
|
+
var LOGO_PLACEHOLDER_KEY = "logo-is-placeholder";
|
|
11015
|
+
var LOGO_ALT_KEY = "logo-alt";
|
|
11016
|
+
var LOGO_IMAGE_URL_KEY = "nav-logo-image";
|
|
11017
|
+
var PLACEHOLDER_BUSINESS_NAME = "Business name";
|
|
11018
|
+
function resolveLogoDisplayText(text) {
|
|
11019
|
+
const trimmed = (text ?? "").trim();
|
|
11020
|
+
return trimmed || PLACEHOLDER_BUSINESS_NAME;
|
|
11021
|
+
}
|
|
11022
|
+
function isFooterLogoRoot(root) {
|
|
11023
|
+
return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
|
|
11024
|
+
}
|
|
11025
|
+
function imageKeyForRoot(root) {
|
|
11026
|
+
return isFooterLogoRoot(root) ? "footer-logo" : "nav-logo-image";
|
|
11027
|
+
}
|
|
11028
|
+
function textKeyForRoot(root) {
|
|
11029
|
+
return isFooterLogoRoot(root) ? "footer-logo-text" : "nav-logo-text";
|
|
11030
|
+
}
|
|
11031
|
+
function ensureLogoHrefKey(root) {
|
|
11032
|
+
if (!(root instanceof HTMLAnchorElement)) return;
|
|
11033
|
+
if (root.hasAttribute("data-ohw-href-key")) return;
|
|
11034
|
+
root.setAttribute("data-ohw-href-key", isFooterLogoRoot(root) ? "footer-logo-href" : "nav-logo-href");
|
|
11035
|
+
}
|
|
11036
|
+
function applyLogoIdentity(text, isPlaceholder) {
|
|
11037
|
+
const display = resolveLogoDisplayText(text);
|
|
11038
|
+
const placeholder = isPlaceholder || !text.trim() || display === PLACEHOLDER_BUSINESS_NAME;
|
|
11039
|
+
for (const key of LOGO_TEXT_KEYS) {
|
|
11040
|
+
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
11041
|
+
if (el.textContent !== display) el.textContent = display;
|
|
11042
|
+
});
|
|
11043
|
+
}
|
|
11044
|
+
for (const key of LOGO_IMAGE_KEYS) {
|
|
11045
|
+
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
11046
|
+
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
11047
|
+
if (img) img.alt = display;
|
|
11048
|
+
});
|
|
11049
|
+
}
|
|
11050
|
+
document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((el) => {
|
|
11051
|
+
if (placeholder) el.setAttribute("data-ohw-placeholder", "");
|
|
11052
|
+
else el.removeAttribute("data-ohw-placeholder");
|
|
11053
|
+
});
|
|
11054
|
+
return display;
|
|
11055
|
+
}
|
|
11056
|
+
function applyLogoImage(url, alt) {
|
|
11057
|
+
const displayAlt = resolveLogoDisplayText(alt);
|
|
11058
|
+
document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
|
|
11059
|
+
ensureLogoHrefKey(root);
|
|
11060
|
+
const imageKey = imageKeyForRoot(root);
|
|
11061
|
+
const textKey = textKeyForRoot(root);
|
|
11062
|
+
let img = root.querySelector(`img[data-ohw-key="${imageKey}"]`) ?? (root.querySelector(`[data-ohw-key="${imageKey}"]`) instanceof HTMLImageElement ? root.querySelector(`[data-ohw-key="${imageKey}"]`) : null) ?? root.querySelector("img");
|
|
11063
|
+
let textEl = root.querySelector(`[data-ohw-key="${textKey}"]`) ?? root.querySelector('[data-ohw-key="logo-text"]');
|
|
11064
|
+
if (url) {
|
|
11065
|
+
if (!img) {
|
|
11066
|
+
img = document.createElement("img");
|
|
11067
|
+
img.setAttribute("data-ohw-editable", "image");
|
|
11068
|
+
img.setAttribute("data-ohw-key", imageKey);
|
|
11069
|
+
img.alt = displayAlt;
|
|
11070
|
+
img.style.height = "";
|
|
11071
|
+
img.style.maxHeight = "none";
|
|
11072
|
+
img.style.width = "auto";
|
|
11073
|
+
img.style.display = "block";
|
|
11074
|
+
img.style.objectFit = "contain";
|
|
11075
|
+
root.insertBefore(img, root.firstChild);
|
|
11076
|
+
} else {
|
|
11077
|
+
img.setAttribute("data-ohw-editable", "image");
|
|
11078
|
+
img.setAttribute("data-ohw-key", imageKey);
|
|
11079
|
+
}
|
|
11080
|
+
img.removeAttribute("srcset");
|
|
11081
|
+
img.removeAttribute("sizes");
|
|
11082
|
+
img.src = url;
|
|
11083
|
+
img.alt = displayAlt;
|
|
11084
|
+
img.style.display = "block";
|
|
11085
|
+
if (textEl) textEl.style.display = "none";
|
|
11086
|
+
root.removeAttribute("data-ohw-placeholder");
|
|
11087
|
+
return;
|
|
11088
|
+
}
|
|
11089
|
+
if (img) {
|
|
11090
|
+
img.removeAttribute("src");
|
|
11091
|
+
img.removeAttribute("srcset");
|
|
11092
|
+
img.removeAttribute("sizes");
|
|
11093
|
+
img.alt = displayAlt;
|
|
11094
|
+
img.style.display = "none";
|
|
11095
|
+
}
|
|
11096
|
+
if (!textEl) {
|
|
11097
|
+
textEl = document.createElement("span");
|
|
11098
|
+
textEl.setAttribute("data-ohw-editable", "plain");
|
|
11099
|
+
textEl.setAttribute("data-ohw-key", textKey);
|
|
11100
|
+
root.appendChild(textEl);
|
|
11101
|
+
}
|
|
11102
|
+
textEl.style.display = "";
|
|
11103
|
+
if (textEl.textContent !== displayAlt) textEl.textContent = displayAlt;
|
|
11104
|
+
if (!displayAlt.trim() || displayAlt === PLACEHOLDER_BUSINESS_NAME) {
|
|
11105
|
+
root.setAttribute("data-ohw-placeholder", "");
|
|
11106
|
+
} else {
|
|
11107
|
+
root.removeAttribute("data-ohw-placeholder");
|
|
11108
|
+
}
|
|
11109
|
+
});
|
|
11110
|
+
}
|
|
11111
|
+
function applyLogoHref(href) {
|
|
11112
|
+
const target = href.trim() || "/";
|
|
11113
|
+
document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
|
|
11114
|
+
ensureLogoHrefKey(root);
|
|
11115
|
+
if (root instanceof HTMLAnchorElement) {
|
|
11116
|
+
root.setAttribute("href", target);
|
|
11117
|
+
}
|
|
11118
|
+
});
|
|
11119
|
+
for (const key of LOGO_HREF_KEYS) setStoredLinkHref(key, target);
|
|
11120
|
+
}
|
|
11121
|
+
function readLogoIdentityFromDom() {
|
|
11122
|
+
let imageUrl = null;
|
|
11123
|
+
for (const key of LOGO_IMAGE_KEYS) {
|
|
11124
|
+
const el = document.querySelector(`[data-ohw-key="${key}"]`);
|
|
11125
|
+
const img = el instanceof HTMLImageElement ? el : el?.querySelector("img");
|
|
11126
|
+
const attrSrc = img?.getAttribute("src")?.trim() ?? "";
|
|
11127
|
+
if (attrSrc && !attrSrc.startsWith("data:") && img && img.style.display !== "none") {
|
|
11128
|
+
imageUrl = img.currentSrc || img.src;
|
|
11129
|
+
break;
|
|
11130
|
+
}
|
|
11131
|
+
}
|
|
11132
|
+
let text = PLACEHOLDER_BUSINESS_NAME;
|
|
11133
|
+
let isPlaceholder = true;
|
|
11134
|
+
for (const key of LOGO_TEXT_KEYS) {
|
|
11135
|
+
const el = document.querySelector(`[data-ohw-key="${key}"]`);
|
|
11136
|
+
if (el?.textContent?.trim()) {
|
|
11137
|
+
text = el.textContent.trim();
|
|
11138
|
+
const logoRoot2 = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
11139
|
+
isPlaceholder = logoRoot2?.hasAttribute("data-ohw-placeholder") === true || text === PLACEHOLDER_BUSINESS_NAME;
|
|
11140
|
+
break;
|
|
11141
|
+
}
|
|
11142
|
+
}
|
|
11143
|
+
if (imageUrl) {
|
|
11144
|
+
const logoImg = document.querySelector(
|
|
11145
|
+
'[data-ohw-key="nav-logo-image"], [data-ohw-key="footer-logo"]'
|
|
11146
|
+
);
|
|
11147
|
+
const alt = logoImg?.alt?.trim() || text;
|
|
11148
|
+
isPlaceholder = false;
|
|
11149
|
+
const hrefEl = document.querySelector(
|
|
11150
|
+
'a[data-ohw-role="logo"], a[data-ohw-logo], [data-ohw-role="logo"]'
|
|
11151
|
+
);
|
|
11152
|
+
const href2 = (hrefEl instanceof HTMLAnchorElement ? hrefEl.getAttribute("href") : null) || hrefEl?.closest("a")?.getAttribute("href") || "/";
|
|
11153
|
+
return { text, isPlaceholder, imageUrl, href: href2, alt };
|
|
11154
|
+
}
|
|
11155
|
+
const logoRoot = document.querySelector('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
11156
|
+
const href = (logoRoot instanceof HTMLAnchorElement ? logoRoot.getAttribute("href") : null) || logoRoot?.closest("a")?.getAttribute("href") || "/";
|
|
11157
|
+
return { text, isPlaceholder, imageUrl: null, href, alt: text };
|
|
11158
|
+
}
|
|
11159
|
+
function applyLogoFromContent(content) {
|
|
11160
|
+
const hasLogoIdentity = LOGO_PLACEHOLDER_KEY in content || LOGO_TEXT_KEYS.some((key) => key in content) || LOGO_IMAGE_KEYS.some((key) => key in content) || LOGO_ALT_KEY in content || LOGO_HREF_KEYS.some((key) => key in content);
|
|
11161
|
+
if (!hasLogoIdentity) return false;
|
|
11162
|
+
const logoText = content[LOGO_TEXT_KEYS[0]] ?? content[LOGO_TEXT_KEYS[1]] ?? readLogoIdentityFromDom().text;
|
|
11163
|
+
const logoAlt = content[LOGO_ALT_KEY] ?? logoText;
|
|
11164
|
+
const rawLogoImage = content[LOGO_IMAGE_URL_KEY] ?? content["footer-logo"] ?? content["footer-logo-image"] ?? null;
|
|
11165
|
+
const logoImageUrl = typeof rawLogoImage === "string" && rawLogoImage.trim() ? rawLogoImage.trim() : null;
|
|
11166
|
+
const imageExplicitlyCleared = LOGO_IMAGE_KEYS.some((key) => key in content) && !logoImageUrl;
|
|
11167
|
+
const logoIsPlaceholder = LOGO_PLACEHOLDER_KEY in content ? content[LOGO_PLACEHOLDER_KEY] !== "false" : !logoImageUrl && (!logoText.trim() || logoText === PLACEHOLDER_BUSINESS_NAME);
|
|
11168
|
+
if (logoImageUrl) {
|
|
11169
|
+
applyLogoImage(logoImageUrl, logoAlt);
|
|
11170
|
+
} else {
|
|
11171
|
+
if (imageExplicitlyCleared) applyLogoImage(null, logoAlt);
|
|
11172
|
+
applyLogoIdentity(logoText, logoIsPlaceholder);
|
|
11173
|
+
}
|
|
11174
|
+
const logoHref = content["nav-logo-href"] ?? content["footer-logo-href"] ?? content["logo-href"];
|
|
11175
|
+
if (typeof logoHref === "string" && logoHref.trim()) {
|
|
11176
|
+
applyLogoHref(logoHref);
|
|
11177
|
+
}
|
|
11178
|
+
return true;
|
|
11179
|
+
}
|
|
11180
|
+
|
|
11181
|
+
// src/lib/logo-size.ts
|
|
11182
|
+
var LOGO_SIZE_DEFAULTS = {
|
|
11183
|
+
navbar: 28,
|
|
11184
|
+
footer: 32
|
|
11185
|
+
};
|
|
11186
|
+
var LOGO_SIZE_MIN = 16;
|
|
11187
|
+
var LOGO_SIZE_MAX = 80;
|
|
11188
|
+
var LOGO_SIZE_DESKTOP_KEYS = {
|
|
11189
|
+
navbar: "nav-logo-size",
|
|
11190
|
+
footer: "footer-logo-size"
|
|
11191
|
+
};
|
|
11192
|
+
var LOGO_SIZE_MOBILE_KEYS = {
|
|
11193
|
+
navbar: "nav-logo-size-mobile",
|
|
11194
|
+
footer: "footer-logo-size-mobile"
|
|
11195
|
+
};
|
|
11196
|
+
var LOGO_SIZE_KEYS = [
|
|
11197
|
+
LOGO_SIZE_DESKTOP_KEYS.navbar,
|
|
11198
|
+
LOGO_SIZE_DESKTOP_KEYS.footer,
|
|
11199
|
+
LOGO_SIZE_MOBILE_KEYS.navbar,
|
|
11200
|
+
LOGO_SIZE_MOBILE_KEYS.footer
|
|
11201
|
+
];
|
|
11202
|
+
function isFooterLogoRoot2(root) {
|
|
11203
|
+
return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
|
|
11204
|
+
}
|
|
11205
|
+
function getLogoPlacement(root) {
|
|
11206
|
+
return isFooterLogoRoot2(root) ? "footer" : "navbar";
|
|
11207
|
+
}
|
|
11208
|
+
function parseLogoSizePx(raw, fallback) {
|
|
11209
|
+
if (raw == null || raw === "") return fallback;
|
|
11210
|
+
const n = Number.parseFloat(raw);
|
|
11211
|
+
if (!Number.isFinite(n)) return fallback;
|
|
11212
|
+
return Math.min(LOGO_SIZE_MAX, Math.max(LOGO_SIZE_MIN, Math.round(n)));
|
|
11213
|
+
}
|
|
11214
|
+
function isMobileLogoSizeFollowing(content, placement) {
|
|
11215
|
+
const raw = content[LOGO_SIZE_MOBILE_KEYS[placement]];
|
|
11216
|
+
return raw == null || raw.trim() === "";
|
|
11217
|
+
}
|
|
11218
|
+
function resolveDesktopLogoSize(content, placement) {
|
|
11219
|
+
return parseLogoSizePx(content[LOGO_SIZE_DESKTOP_KEYS[placement]], LOGO_SIZE_DEFAULTS[placement]);
|
|
11220
|
+
}
|
|
11221
|
+
function resolveMobileLogoSize(content, placement) {
|
|
11222
|
+
if (isMobileLogoSizeFollowing(content, placement)) {
|
|
11223
|
+
return resolveDesktopLogoSize(content, placement);
|
|
11224
|
+
}
|
|
11225
|
+
return parseLogoSizePx(
|
|
11226
|
+
content[LOGO_SIZE_MOBILE_KEYS[placement]],
|
|
11227
|
+
resolveDesktopLogoSize(content, placement)
|
|
11228
|
+
);
|
|
11229
|
+
}
|
|
11230
|
+
function setRootSizeVars(root, desktopPx, mobilePx, following) {
|
|
11231
|
+
root.style.setProperty("--ohw-logo-size", `${desktopPx}px`);
|
|
11232
|
+
if (following) {
|
|
11233
|
+
root.style.removeProperty("--ohw-logo-size-mobile");
|
|
11234
|
+
} else {
|
|
11235
|
+
root.style.setProperty("--ohw-logo-size-mobile", `${mobilePx}px`);
|
|
11236
|
+
}
|
|
11237
|
+
root.querySelectorAll("img").forEach((img) => {
|
|
11238
|
+
img.style.height = "";
|
|
11239
|
+
img.style.maxHeight = "none";
|
|
11240
|
+
img.style.width = "auto";
|
|
11241
|
+
img.style.objectFit = "contain";
|
|
11242
|
+
});
|
|
11243
|
+
}
|
|
11244
|
+
function applyLogoSizes(content) {
|
|
11245
|
+
document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
|
|
11246
|
+
const placement = getLogoPlacement(root);
|
|
11247
|
+
const desktop = resolveDesktopLogoSize(content, placement);
|
|
11248
|
+
const following = isMobileLogoSizeFollowing(content, placement);
|
|
11249
|
+
const mobile = following ? desktop : resolveMobileLogoSize(content, placement);
|
|
11250
|
+
setRootSizeVars(root, desktop, mobile, following);
|
|
11251
|
+
});
|
|
11252
|
+
}
|
|
11253
|
+
function applyLogoSizeToPlacement(placement, desktopPx, mobilePx, following) {
|
|
11254
|
+
document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
|
|
11255
|
+
if (getLogoPlacement(root) !== placement) return;
|
|
11256
|
+
setRootSizeVars(root, desktopPx, mobilePx, following);
|
|
11257
|
+
});
|
|
11258
|
+
}
|
|
11259
|
+
function logoHasUploadedImage(logoEl) {
|
|
11260
|
+
if (logoEl.hasAttribute("data-ohw-placeholder")) return false;
|
|
11261
|
+
const img = logoEl.querySelector('img[data-ohw-key="nav-logo-image"], img[data-ohw-key="footer-logo"], img[data-ohw-key="footer-logo-image"]') ?? logoEl.querySelector("img");
|
|
11262
|
+
if (!img) return false;
|
|
11263
|
+
const src = img.getAttribute("src")?.trim() ?? "";
|
|
11264
|
+
if (!src || src.startsWith("data:")) return false;
|
|
11265
|
+
if (img.style.display === "none") return false;
|
|
11266
|
+
return true;
|
|
11267
|
+
}
|
|
11268
|
+
function getLogoInteractionRect(logoEl) {
|
|
11269
|
+
if (logoHasUploadedImage(logoEl)) {
|
|
11270
|
+
const img = logoEl.querySelector('img[data-ohw-key="nav-logo-image"], img[data-ohw-key="footer-logo"], img[data-ohw-key="footer-logo-image"]') ?? logoEl.querySelector("img");
|
|
11271
|
+
if (img) {
|
|
11272
|
+
const r2 = img.getBoundingClientRect();
|
|
11273
|
+
if (r2.width > 0 && r2.height > 0) return r2;
|
|
11274
|
+
}
|
|
11275
|
+
}
|
|
11276
|
+
const text = logoEl.querySelector(
|
|
11277
|
+
'[data-ohw-key="nav-logo-text"], [data-ohw-key="footer-logo-text"]'
|
|
11278
|
+
);
|
|
11279
|
+
if (text) {
|
|
11280
|
+
const style = window.getComputedStyle(text);
|
|
11281
|
+
if (style.display !== "none" && style.visibility !== "hidden") {
|
|
11282
|
+
const r2 = text.getBoundingClientRect();
|
|
11283
|
+
if (r2.width > 0 && r2.height > 0) return r2;
|
|
11284
|
+
}
|
|
11285
|
+
}
|
|
11286
|
+
return logoEl.getBoundingClientRect();
|
|
11287
|
+
}
|
|
11288
|
+
function readLogoSizeState(content, placement) {
|
|
11289
|
+
const desktopPx = resolveDesktopLogoSize(content, placement);
|
|
11290
|
+
const mobileFollowing = isMobileLogoSizeFollowing(content, placement);
|
|
11291
|
+
const mobilePx = mobileFollowing ? desktopPx : resolveMobileLogoSize(content, placement);
|
|
11292
|
+
return { desktopPx, mobilePx, mobileFollowing };
|
|
11293
|
+
}
|
|
11294
|
+
|
|
11295
|
+
// src/lib/site-wide-scope.ts
|
|
11296
|
+
function getLogoElement(el) {
|
|
11297
|
+
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
11298
|
+
if (marked) return marked;
|
|
11299
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
11300
|
+
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
11301
|
+
if (!root) return null;
|
|
11302
|
+
const anchor = el.closest("a");
|
|
11303
|
+
if (anchor && root.contains(anchor) && !anchor.hasAttribute("data-ohw-href-key") && !anchor.closest("[data-ohw-nav-container]") && Boolean(anchor.querySelector("img") || anchor.matches("img"))) {
|
|
11304
|
+
return anchor;
|
|
11305
|
+
}
|
|
11306
|
+
const img = el.matches("img") ? el : null;
|
|
11307
|
+
if (img && !img.closest("[data-ohw-href-key]") && !img.closest("[data-ohw-nav-container]") && (img.closest("footer") || img.closest("nav, [data-ohw-nav-root]"))) {
|
|
11308
|
+
return img;
|
|
11309
|
+
}
|
|
11310
|
+
return null;
|
|
11311
|
+
}
|
|
11312
|
+
function isInFooter(el) {
|
|
11313
|
+
if (!el) return false;
|
|
11314
|
+
return Boolean(el.closest("footer") || el.closest('[data-ohw-section="footer"]'));
|
|
11315
|
+
}
|
|
11316
|
+
function isSiteWideElement(el) {
|
|
11317
|
+
if (!el) return false;
|
|
11318
|
+
if (getLogoElement(el)) return true;
|
|
11319
|
+
if (isInFooter(el)) return true;
|
|
11320
|
+
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-root")) {
|
|
11321
|
+
return true;
|
|
11322
|
+
}
|
|
11323
|
+
if (el.hasAttribute("data-ohw-href-key") && el.closest("nav, [data-ohw-nav-root], [data-ohw-nav-drawer], aside")) {
|
|
11324
|
+
return true;
|
|
11325
|
+
}
|
|
11326
|
+
if (el.closest('[data-ohw-role="navbar-button"]')) return true;
|
|
11327
|
+
return false;
|
|
11328
|
+
}
|
|
11329
|
+
function isSiteWideScopeActive(args) {
|
|
11330
|
+
return isSiteWideElement(args.selected) || isSiteWideElement(args.hoveredItem) || isSiteWideElement(args.hoveredNavContainer) || isSiteWideElement(args.active);
|
|
11331
|
+
}
|
|
11332
|
+
|
|
10372
11333
|
// src/lib/add-footer-column.ts
|
|
10373
11334
|
function buildFooterColumnEditContentPatch(result) {
|
|
10374
11335
|
return {
|
|
@@ -10401,35 +11362,398 @@ function addFooterColumnWithPersist({
|
|
|
10401
11362
|
return result;
|
|
10402
11363
|
}
|
|
10403
11364
|
|
|
10404
|
-
// src/
|
|
10405
|
-
|
|
10406
|
-
|
|
10407
|
-
|
|
10408
|
-
|
|
11365
|
+
// src/ui/FloatingPanel.tsx
|
|
11366
|
+
var import_react13 = require("react");
|
|
11367
|
+
var import_lucide_react13 = require("lucide-react");
|
|
11368
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
11369
|
+
var PANEL_WIDTH = 256;
|
|
11370
|
+
var EDGE_MARGIN = 16;
|
|
11371
|
+
function getVisibleClip(parentScroll) {
|
|
11372
|
+
const left = 0;
|
|
11373
|
+
const right = window.innerWidth;
|
|
11374
|
+
if (!parentScroll) {
|
|
11375
|
+
return { top: 0, bottom: window.innerHeight, left, right };
|
|
10409
11376
|
}
|
|
11377
|
+
const { iframeOffsetTop, headerH: visibleCanvasTop, canvasH } = parentScroll;
|
|
11378
|
+
const top = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
11379
|
+
const bottom = Math.min(window.innerHeight, visibleCanvasTop + canvasH - iframeOffsetTop);
|
|
11380
|
+
return { top, bottom: Math.max(top, bottom), left, right };
|
|
10410
11381
|
}
|
|
10411
|
-
function
|
|
10412
|
-
const
|
|
10413
|
-
|
|
10414
|
-
|
|
10415
|
-
|
|
10416
|
-
|
|
10417
|
-
|
|
10418
|
-
|
|
10419
|
-
|
|
10420
|
-
document.documentElement.setAttribute("data-ohw-item-dragging", "");
|
|
10421
|
-
clearTextSelection();
|
|
11382
|
+
function defaultFloatingPanelPosition(parentScroll, panelHeight = 280) {
|
|
11383
|
+
const clip = getVisibleClip(parentScroll);
|
|
11384
|
+
return {
|
|
11385
|
+
x: Math.max(EDGE_MARGIN, clip.right - PANEL_WIDTH - EDGE_MARGIN),
|
|
11386
|
+
y: Math.min(
|
|
11387
|
+
Math.max(clip.top + EDGE_MARGIN, EDGE_MARGIN),
|
|
11388
|
+
Math.max(clip.top + EDGE_MARGIN, clip.bottom - panelHeight - EDGE_MARGIN)
|
|
11389
|
+
)
|
|
11390
|
+
};
|
|
10422
11391
|
}
|
|
10423
|
-
function
|
|
10424
|
-
const
|
|
10425
|
-
|
|
10426
|
-
|
|
10427
|
-
|
|
11392
|
+
function clampPosition(pos, parentScroll, panelW, panelH) {
|
|
11393
|
+
const clip = getVisibleClip(parentScroll);
|
|
11394
|
+
const maxX = Math.max(clip.left + EDGE_MARGIN, clip.right - panelW - EDGE_MARGIN);
|
|
11395
|
+
const maxY = Math.max(clip.top + EDGE_MARGIN, clip.bottom - panelH - EDGE_MARGIN);
|
|
11396
|
+
return {
|
|
11397
|
+
x: Math.min(Math.max(pos.x, clip.left + EDGE_MARGIN), maxX),
|
|
11398
|
+
y: Math.min(Math.max(pos.y, clip.top + EDGE_MARGIN), maxY)
|
|
11399
|
+
};
|
|
10428
11400
|
}
|
|
10429
|
-
|
|
10430
|
-
|
|
10431
|
-
|
|
10432
|
-
|
|
11401
|
+
function FloatingPanel({
|
|
11402
|
+
open,
|
|
11403
|
+
title,
|
|
11404
|
+
context,
|
|
11405
|
+
icon,
|
|
11406
|
+
onClose,
|
|
11407
|
+
children,
|
|
11408
|
+
position,
|
|
11409
|
+
onPositionChange,
|
|
11410
|
+
parentScroll = null,
|
|
11411
|
+
className,
|
|
11412
|
+
bodyClassName
|
|
11413
|
+
}) {
|
|
11414
|
+
const panelRef = (0, import_react13.useRef)(null);
|
|
11415
|
+
const [measured, setMeasured] = (0, import_react13.useState)({ w: PANEL_WIDTH, h: 280 });
|
|
11416
|
+
const dragRef = (0, import_react13.useRef)(null);
|
|
11417
|
+
const resolved = position ?? defaultFloatingPanelPosition(parentScroll, measured.h);
|
|
11418
|
+
const clamped = clampPosition(resolved, parentScroll, measured.w, measured.h);
|
|
11419
|
+
(0, import_react13.useLayoutEffect)(() => {
|
|
11420
|
+
if (!open || !panelRef.current) return;
|
|
11421
|
+
const el = panelRef.current;
|
|
11422
|
+
const next = { w: el.offsetWidth || PANEL_WIDTH, h: el.offsetHeight || 280 };
|
|
11423
|
+
setMeasured((prev) => prev.w === next.w && prev.h === next.h ? prev : next);
|
|
11424
|
+
}, [open, children, title, context]);
|
|
11425
|
+
(0, import_react13.useEffect)(() => {
|
|
11426
|
+
if (!open || !position || !onPositionChange) return;
|
|
11427
|
+
const next = clampPosition(position, parentScroll, measured.w, measured.h);
|
|
11428
|
+
if (next.x !== position.x || next.y !== position.y) onPositionChange(next);
|
|
11429
|
+
}, [open, parentScroll, measured.w, measured.h, position, onPositionChange]);
|
|
11430
|
+
const onHeaderPointerDown = (0, import_react13.useCallback)(
|
|
11431
|
+
(e) => {
|
|
11432
|
+
if (e.button !== 0) return;
|
|
11433
|
+
if (e.target.closest("[data-ohw-floating-panel-close]")) return;
|
|
11434
|
+
e.preventDefault();
|
|
11435
|
+
e.stopPropagation();
|
|
11436
|
+
const el = e.currentTarget;
|
|
11437
|
+
el.setPointerCapture(e.pointerId);
|
|
11438
|
+
document.documentElement.setAttribute("data-ohw-panel-dragging", "");
|
|
11439
|
+
dragRef.current = {
|
|
11440
|
+
pointerId: e.pointerId,
|
|
11441
|
+
startX: e.clientX,
|
|
11442
|
+
startY: e.clientY,
|
|
11443
|
+
originX: clamped.x,
|
|
11444
|
+
originY: clamped.y
|
|
11445
|
+
};
|
|
11446
|
+
},
|
|
11447
|
+
[clamped.x, clamped.y]
|
|
11448
|
+
);
|
|
11449
|
+
const onHeaderPointerMove = (0, import_react13.useCallback)(
|
|
11450
|
+
(e) => {
|
|
11451
|
+
const drag = dragRef.current;
|
|
11452
|
+
if (!drag || drag.pointerId !== e.pointerId) return;
|
|
11453
|
+
e.preventDefault();
|
|
11454
|
+
const next = clampPosition(
|
|
11455
|
+
{
|
|
11456
|
+
x: drag.originX + (e.clientX - drag.startX),
|
|
11457
|
+
y: drag.originY + (e.clientY - drag.startY)
|
|
11458
|
+
},
|
|
11459
|
+
parentScroll,
|
|
11460
|
+
measured.w,
|
|
11461
|
+
measured.h
|
|
11462
|
+
);
|
|
11463
|
+
onPositionChange?.(next);
|
|
11464
|
+
},
|
|
11465
|
+
[measured.h, measured.w, onPositionChange, parentScroll]
|
|
11466
|
+
);
|
|
11467
|
+
const endDrag = (0, import_react13.useCallback)((e) => {
|
|
11468
|
+
const drag = dragRef.current;
|
|
11469
|
+
if (!drag || drag.pointerId !== e.pointerId) return;
|
|
11470
|
+
dragRef.current = null;
|
|
11471
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
11472
|
+
try {
|
|
11473
|
+
e.currentTarget.releasePointerCapture(e.pointerId);
|
|
11474
|
+
} catch {
|
|
11475
|
+
}
|
|
11476
|
+
}, []);
|
|
11477
|
+
(0, import_react13.useEffect)(() => {
|
|
11478
|
+
if (open) return;
|
|
11479
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
11480
|
+
}, [open]);
|
|
11481
|
+
(0, import_react13.useEffect)(() => () => document.documentElement.removeAttribute("data-ohw-panel-dragging"), []);
|
|
11482
|
+
if (!open) return null;
|
|
11483
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
11484
|
+
"div",
|
|
11485
|
+
{
|
|
11486
|
+
ref: panelRef,
|
|
11487
|
+
"data-ohw-floating-panel": "",
|
|
11488
|
+
role: "dialog",
|
|
11489
|
+
"aria-label": title,
|
|
11490
|
+
className: cn(
|
|
11491
|
+
// Above MediaOverlay / item chrome (2147483646); link-modal content shares this tier.
|
|
11492
|
+
"fixed z-[2147483647] flex w-64 flex-col overflow-hidden rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
11493
|
+
className
|
|
11494
|
+
),
|
|
11495
|
+
style: { left: clamped.x, top: clamped.y },
|
|
11496
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
11497
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
11498
|
+
onClick: (e) => e.stopPropagation(),
|
|
11499
|
+
children: [
|
|
11500
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
11501
|
+
"div",
|
|
11502
|
+
{
|
|
11503
|
+
"data-ohw-floating-panel-header": "",
|
|
11504
|
+
className: "relative flex cursor-grab items-start gap-2 border-b border-border py-5 pl-5 pr-11 active:cursor-grabbing",
|
|
11505
|
+
onPointerDown: onHeaderPointerDown,
|
|
11506
|
+
onPointerMove: onHeaderPointerMove,
|
|
11507
|
+
onPointerUp: endDrag,
|
|
11508
|
+
onPointerCancel: endDrag,
|
|
11509
|
+
children: [
|
|
11510
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col gap-1.5", children: [
|
|
11511
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
11512
|
+
icon ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "shrink-0 text-foreground", children: icon }) : null,
|
|
11513
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "min-w-0 flex-1 text-lg font-semibold leading-7 text-foreground", children: title })
|
|
11514
|
+
] }),
|
|
11515
|
+
context ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "w-full text-sm leading-5 text-muted-foreground", children: context }) : null
|
|
11516
|
+
] }),
|
|
11517
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
11518
|
+
"button",
|
|
11519
|
+
{
|
|
11520
|
+
type: "button",
|
|
11521
|
+
"data-ohw-floating-panel-close": "",
|
|
11522
|
+
"aria-label": "Close",
|
|
11523
|
+
className: "absolute right-2.5 top-2.5 rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
11524
|
+
onClick: (e) => {
|
|
11525
|
+
e.stopPropagation();
|
|
11526
|
+
onClose();
|
|
11527
|
+
},
|
|
11528
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
11529
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.X, { size: 16, "aria-hidden": true })
|
|
11530
|
+
}
|
|
11531
|
+
)
|
|
11532
|
+
]
|
|
11533
|
+
}
|
|
11534
|
+
),
|
|
11535
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
11536
|
+
"div",
|
|
11537
|
+
{
|
|
11538
|
+
"data-ohw-floating-panel-body": "",
|
|
11539
|
+
className: cn("flex w-full flex-col gap-4 p-5", bodyClassName),
|
|
11540
|
+
children
|
|
11541
|
+
}
|
|
11542
|
+
)
|
|
11543
|
+
]
|
|
11544
|
+
}
|
|
11545
|
+
);
|
|
11546
|
+
}
|
|
11547
|
+
|
|
11548
|
+
// src/ui/logo-size-panel.tsx
|
|
11549
|
+
var import_lucide_react14 = require("lucide-react");
|
|
11550
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
11551
|
+
function SizeSlider({
|
|
11552
|
+
value,
|
|
11553
|
+
onChange
|
|
11554
|
+
}) {
|
|
11555
|
+
const pct = (value - LOGO_SIZE_MIN) / (LOGO_SIZE_MAX - LOGO_SIZE_MIN) * 100;
|
|
11556
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex w-full flex-col gap-3", children: [
|
|
11557
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex w-full items-center gap-2 text-sm font-medium leading-5", children: [
|
|
11558
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "min-w-0 flex-1 text-foreground", children: "Size" }),
|
|
11559
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "shrink-0 whitespace-nowrap text-muted-foreground", children: [
|
|
11560
|
+
value,
|
|
11561
|
+
" px"
|
|
11562
|
+
] })
|
|
11563
|
+
] }),
|
|
11564
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "relative h-2 w-full rounded-full bg-primary-50", children: [
|
|
11565
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
11566
|
+
"div",
|
|
11567
|
+
{
|
|
11568
|
+
className: "absolute inset-y-0 left-0 rounded-full bg-primary",
|
|
11569
|
+
style: { width: `${pct}%` }
|
|
11570
|
+
}
|
|
11571
|
+
),
|
|
11572
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
11573
|
+
"input",
|
|
11574
|
+
{
|
|
11575
|
+
type: "range",
|
|
11576
|
+
min: LOGO_SIZE_MIN,
|
|
11577
|
+
max: LOGO_SIZE_MAX,
|
|
11578
|
+
step: 1,
|
|
11579
|
+
value,
|
|
11580
|
+
"aria-label": "Logo size",
|
|
11581
|
+
className: cn(
|
|
11582
|
+
"absolute inset-0 h-full w-full cursor-pointer appearance-none bg-transparent",
|
|
11583
|
+
"[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:size-5",
|
|
11584
|
+
"[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2",
|
|
11585
|
+
"[&::-webkit-slider-thumb]:border-primary [&::-webkit-slider-thumb]:bg-background",
|
|
11586
|
+
"[&::-moz-range-thumb]:size-5 [&::-moz-range-thumb]:rounded-full",
|
|
11587
|
+
"[&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-primary",
|
|
11588
|
+
"[&::-moz-range-thumb]:bg-background"
|
|
11589
|
+
),
|
|
11590
|
+
onChange: (e) => onChange(Number(e.target.value))
|
|
11591
|
+
}
|
|
11592
|
+
)
|
|
11593
|
+
] })
|
|
11594
|
+
] });
|
|
11595
|
+
}
|
|
11596
|
+
function LogoSizePanel({
|
|
11597
|
+
viewport,
|
|
11598
|
+
sizePx,
|
|
11599
|
+
mobileFollowing = true,
|
|
11600
|
+
onSizeChange,
|
|
11601
|
+
onCustomizeMobile,
|
|
11602
|
+
onResetMobile,
|
|
11603
|
+
onUpdateEverywhere,
|
|
11604
|
+
className
|
|
11605
|
+
}) {
|
|
11606
|
+
const showFollowing = viewport === "mobile" && mobileFollowing;
|
|
11607
|
+
const showMobileSlider = viewport === "mobile" && !mobileFollowing;
|
|
11608
|
+
const showDesktopSlider = viewport === "desktop";
|
|
11609
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: cn("flex w-full flex-col gap-4", className), children: [
|
|
11610
|
+
showFollowing ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
|
|
11611
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-start gap-1", children: [
|
|
11612
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react14.Link, { size: 16, className: "mt-0.5 shrink-0 text-foreground", "aria-hidden": true }),
|
|
11613
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-sm font-semibold leading-5 text-foreground", children: "Following desktop size" })
|
|
11614
|
+
] }),
|
|
11615
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-sm leading-5 text-muted-foreground", children: "Mobile uses the desktop size until you customize it. Change the desktop size and it follows automatically." }),
|
|
11616
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
11617
|
+
Button,
|
|
11618
|
+
{
|
|
11619
|
+
type: "button",
|
|
11620
|
+
variant: "outline",
|
|
11621
|
+
size: "sm",
|
|
11622
|
+
className: "h-9 w-full min-w-0 cursor-pointer",
|
|
11623
|
+
onClick: onCustomizeMobile,
|
|
11624
|
+
children: "Customize for mobile"
|
|
11625
|
+
}
|
|
11626
|
+
)
|
|
11627
|
+
] }) : null,
|
|
11628
|
+
showDesktopSlider || showMobileSlider ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SizeSlider, { value: sizePx, onChange: onSizeChange }) : null,
|
|
11629
|
+
showMobileSlider ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
11630
|
+
Button,
|
|
11631
|
+
{
|
|
11632
|
+
type: "button",
|
|
11633
|
+
variant: "outline",
|
|
11634
|
+
size: "sm",
|
|
11635
|
+
className: "h-9 w-full min-w-0 cursor-pointer",
|
|
11636
|
+
onClick: onResetMobile,
|
|
11637
|
+
children: "Reset to desktop size"
|
|
11638
|
+
}
|
|
11639
|
+
) : null,
|
|
11640
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "h-px w-full bg-border", role: "separator" }),
|
|
11641
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
11642
|
+
Button,
|
|
11643
|
+
{
|
|
11644
|
+
type: "button",
|
|
11645
|
+
variant: "outline",
|
|
11646
|
+
size: "sm",
|
|
11647
|
+
className: "h-9 w-full min-w-0 cursor-pointer gap-1",
|
|
11648
|
+
onClick: onUpdateEverywhere,
|
|
11649
|
+
children: [
|
|
11650
|
+
"Update logo everywhere",
|
|
11651
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react14.ArrowUpRight, { size: 16, "aria-hidden": true })
|
|
11652
|
+
]
|
|
11653
|
+
}
|
|
11654
|
+
),
|
|
11655
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-sm leading-5 text-muted-foreground", children: "Matches the right version to your background." })
|
|
11656
|
+
] });
|
|
11657
|
+
}
|
|
11658
|
+
|
|
11659
|
+
// src/ui/socials-display-panel.tsx
|
|
11660
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
11661
|
+
function DisplaySwitch({
|
|
11662
|
+
label,
|
|
11663
|
+
checked,
|
|
11664
|
+
disabled,
|
|
11665
|
+
onChange
|
|
11666
|
+
}) {
|
|
11667
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
|
|
11668
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
11669
|
+
"span",
|
|
11670
|
+
{
|
|
11671
|
+
className: cn(
|
|
11672
|
+
"min-w-0 flex-1 text-sm font-medium leading-5",
|
|
11673
|
+
disabled ? "text-muted-foreground" : "text-foreground"
|
|
11674
|
+
),
|
|
11675
|
+
children: label
|
|
11676
|
+
}
|
|
11677
|
+
),
|
|
11678
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
11679
|
+
"button",
|
|
11680
|
+
{
|
|
11681
|
+
type: "button",
|
|
11682
|
+
role: "switch",
|
|
11683
|
+
"aria-checked": checked,
|
|
11684
|
+
"aria-label": label,
|
|
11685
|
+
disabled,
|
|
11686
|
+
onClick: () => onChange(!checked),
|
|
11687
|
+
className: cn(
|
|
11688
|
+
"relative h-5 w-9 shrink-0 rounded-full transition-colors",
|
|
11689
|
+
checked ? "bg-primary" : "bg-primary-50",
|
|
11690
|
+
disabled ? "cursor-default opacity-50" : "cursor-pointer"
|
|
11691
|
+
),
|
|
11692
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
11693
|
+
"span",
|
|
11694
|
+
{
|
|
11695
|
+
className: cn(
|
|
11696
|
+
"absolute top-0.5 h-4 w-4 rounded-full bg-white transition-all",
|
|
11697
|
+
checked ? "left-[1.125rem]" : "left-0.5"
|
|
11698
|
+
)
|
|
11699
|
+
}
|
|
11700
|
+
)
|
|
11701
|
+
}
|
|
11702
|
+
)
|
|
11703
|
+
] });
|
|
11704
|
+
}
|
|
11705
|
+
function SocialsDisplayPanel({ display, onChange, className }) {
|
|
11706
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: cn("flex w-full flex-col gap-3", className), children: [
|
|
11707
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
11708
|
+
DisplaySwitch,
|
|
11709
|
+
{
|
|
11710
|
+
label: "Text",
|
|
11711
|
+
checked: display.text,
|
|
11712
|
+
disabled: display.text && !display.icon,
|
|
11713
|
+
onChange: (text) => onChange({ ...display, text })
|
|
11714
|
+
}
|
|
11715
|
+
),
|
|
11716
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
11717
|
+
DisplaySwitch,
|
|
11718
|
+
{
|
|
11719
|
+
label: "Icon",
|
|
11720
|
+
checked: display.icon,
|
|
11721
|
+
disabled: display.icon && !display.text,
|
|
11722
|
+
onChange: (icon) => onChange({ ...display, icon })
|
|
11723
|
+
}
|
|
11724
|
+
)
|
|
11725
|
+
] });
|
|
11726
|
+
}
|
|
11727
|
+
|
|
11728
|
+
// src/lib/item-drag-interaction.ts
|
|
11729
|
+
function disableNativeHrefDrag(el) {
|
|
11730
|
+
if (el.draggable) el.draggable = false;
|
|
11731
|
+
if (el.getAttribute("draggable") !== "false") {
|
|
11732
|
+
el.setAttribute("draggable", "false");
|
|
11733
|
+
}
|
|
11734
|
+
}
|
|
11735
|
+
function clearTextSelection() {
|
|
11736
|
+
const sel = window.getSelection();
|
|
11737
|
+
if (sel && !sel.isCollapsed) sel.removeAllRanges();
|
|
11738
|
+
}
|
|
11739
|
+
function armItemPressDrag() {
|
|
11740
|
+
document.documentElement.setAttribute("data-ohw-footer-press-drag", "");
|
|
11741
|
+
}
|
|
11742
|
+
function lockItemDuringDrag() {
|
|
11743
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
11744
|
+
document.documentElement.setAttribute("data-ohw-item-dragging", "");
|
|
11745
|
+
clearTextSelection();
|
|
11746
|
+
}
|
|
11747
|
+
function unlockItemDragInteraction() {
|
|
11748
|
+
const wasDragging = document.documentElement.hasAttribute("data-ohw-item-dragging");
|
|
11749
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
11750
|
+
document.documentElement.removeAttribute("data-ohw-item-dragging");
|
|
11751
|
+
if (wasDragging) clearTextSelection();
|
|
11752
|
+
}
|
|
11753
|
+
var armFooterPressDrag = armItemPressDrag;
|
|
11754
|
+
var lockFooterDuringDrag = lockItemDuringDrag;
|
|
11755
|
+
var unlockFooterDragInteraction = unlockItemDragInteraction;
|
|
11756
|
+
|
|
10433
11757
|
// src/lib/nav-dnd.ts
|
|
10434
11758
|
function listReorderableNavItems() {
|
|
10435
11759
|
return listNavbarItems().filter((el) => {
|
|
@@ -10599,7 +11923,7 @@ function hitTestNavDropSlot(clientX, clientY, draggedHrefKey) {
|
|
|
10599
11923
|
}
|
|
10600
11924
|
|
|
10601
11925
|
// src/useNavItemDrag.ts
|
|
10602
|
-
var
|
|
11926
|
+
var import_react14 = require("react");
|
|
10603
11927
|
function useNavItemDrag({
|
|
10604
11928
|
isEditMode,
|
|
10605
11929
|
editContentRef,
|
|
@@ -10623,11 +11947,11 @@ function useNavItemDrag({
|
|
|
10623
11947
|
getNavigationItemAnchor: getNavigationItemAnchor2,
|
|
10624
11948
|
isDragHandleDisabled: isDragHandleDisabled2
|
|
10625
11949
|
}) {
|
|
10626
|
-
const navDragRef = (0,
|
|
10627
|
-
const [navDropSlots, setNavDropSlots] = (0,
|
|
10628
|
-
const [activeNavDropIndex, setActiveNavDropIndex] = (0,
|
|
10629
|
-
const navPointerDragRef = (0,
|
|
10630
|
-
const clearNavDragVisuals = (0,
|
|
11950
|
+
const navDragRef = (0, import_react14.useRef)(null);
|
|
11951
|
+
const [navDropSlots, setNavDropSlots] = (0, import_react14.useState)([]);
|
|
11952
|
+
const [activeNavDropIndex, setActiveNavDropIndex] = (0, import_react14.useState)(null);
|
|
11953
|
+
const navPointerDragRef = (0, import_react14.useRef)(null);
|
|
11954
|
+
const clearNavDragVisuals = (0, import_react14.useCallback)(() => {
|
|
10631
11955
|
const session = navDragRef.current;
|
|
10632
11956
|
const keepOpenEl = session?.draggedEl?.closest("[data-ohw-nav-children]") != null ? session.draggedEl : null;
|
|
10633
11957
|
navDragRef.current = null;
|
|
@@ -10644,7 +11968,7 @@ function useNavItemDrag({
|
|
|
10644
11968
|
document.documentElement.removeAttribute("data-ohw-nav-dragging-root");
|
|
10645
11969
|
unlockItemDragInteraction();
|
|
10646
11970
|
}, [setDraggedItemRect, setIsItemDragging, setSiblingHintRects]);
|
|
10647
|
-
const refreshNavDragVisuals = (0,
|
|
11971
|
+
const refreshNavDragVisuals = (0, import_react14.useCallback)(
|
|
10648
11972
|
(session, activeSlot, clientX, clientY) => {
|
|
10649
11973
|
setDraggedItemRect(session.draggedEl.getBoundingClientRect());
|
|
10650
11974
|
if (typeof clientX === "number" && typeof clientY === "number") {
|
|
@@ -10662,13 +11986,13 @@ function useNavItemDrag({
|
|
|
10662
11986
|
},
|
|
10663
11987
|
[setDraggedItemRect, setSiblingHintRects]
|
|
10664
11988
|
);
|
|
10665
|
-
const refreshNavDragVisualsRef = (0,
|
|
11989
|
+
const refreshNavDragVisualsRef = (0, import_react14.useRef)(refreshNavDragVisuals);
|
|
10666
11990
|
refreshNavDragVisualsRef.current = refreshNavDragVisuals;
|
|
10667
|
-
const commitNavDragRef = (0,
|
|
11991
|
+
const commitNavDragRef = (0, import_react14.useRef)(() => {
|
|
10668
11992
|
});
|
|
10669
|
-
const beginNavDragRef = (0,
|
|
11993
|
+
const beginNavDragRef = (0, import_react14.useRef)(() => {
|
|
10670
11994
|
});
|
|
10671
|
-
const beginNavDrag = (0,
|
|
11995
|
+
const beginNavDrag = (0, import_react14.useCallback)(
|
|
10672
11996
|
(session) => {
|
|
10673
11997
|
const rect = session.draggedEl.getBoundingClientRect();
|
|
10674
11998
|
session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
|
|
@@ -10702,7 +12026,7 @@ function useNavItemDrag({
|
|
|
10702
12026
|
]
|
|
10703
12027
|
);
|
|
10704
12028
|
beginNavDragRef.current = beginNavDrag;
|
|
10705
|
-
const commitNavDrag = (0,
|
|
12029
|
+
const commitNavDrag = (0, import_react14.useCallback)(
|
|
10706
12030
|
(clientX, clientY) => {
|
|
10707
12031
|
const session = navDragRef.current;
|
|
10708
12032
|
if (!session) {
|
|
@@ -10763,7 +12087,7 @@ function useNavItemDrag({
|
|
|
10763
12087
|
[clearNavDragVisuals, deselectRef, editContentRef, postToParentRef, selectRef]
|
|
10764
12088
|
);
|
|
10765
12089
|
commitNavDragRef.current = commitNavDrag;
|
|
10766
|
-
const startNavLinkDrag = (0,
|
|
12090
|
+
const startNavLinkDrag = (0, import_react14.useCallback)(
|
|
10767
12091
|
(anchor, clientX, clientY, wasSelected) => {
|
|
10768
12092
|
if (footerDragRef.current) return false;
|
|
10769
12093
|
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
@@ -10781,7 +12105,7 @@ function useNavItemDrag({
|
|
|
10781
12105
|
},
|
|
10782
12106
|
[beginNavDrag, footerDragRef, isDragHandleDisabled2, isCtaButton]
|
|
10783
12107
|
);
|
|
10784
|
-
const onNavDragOver = (0,
|
|
12108
|
+
const onNavDragOver = (0, import_react14.useCallback)(
|
|
10785
12109
|
(e) => {
|
|
10786
12110
|
const session = navDragRef.current;
|
|
10787
12111
|
if (!session) return false;
|
|
@@ -10793,7 +12117,7 @@ function useNavItemDrag({
|
|
|
10793
12117
|
},
|
|
10794
12118
|
[]
|
|
10795
12119
|
);
|
|
10796
|
-
(0,
|
|
12120
|
+
(0, import_react14.useEffect)(() => {
|
|
10797
12121
|
if (!isEditMode) return;
|
|
10798
12122
|
const THRESHOLD = 10;
|
|
10799
12123
|
const resolveWasSelected = (el) => {
|
|
@@ -10918,7 +12242,7 @@ function useNavItemDrag({
|
|
|
10918
12242
|
setLinkPopover,
|
|
10919
12243
|
suppressNextClickRef
|
|
10920
12244
|
]);
|
|
10921
|
-
const armNavPressFromChrome = (0,
|
|
12245
|
+
const armNavPressFromChrome = (0, import_react14.useCallback)(
|
|
10922
12246
|
(selected, clientX, clientY, pointerId) => {
|
|
10923
12247
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
10924
12248
|
if (!hrefKey || !isNavbarHrefKey(hrefKey)) return false;
|
|
@@ -10949,8 +12273,8 @@ function useNavItemDrag({
|
|
|
10949
12273
|
}
|
|
10950
12274
|
|
|
10951
12275
|
// src/ui/footer-container-chrome.tsx
|
|
10952
|
-
var
|
|
10953
|
-
var
|
|
12276
|
+
var import_lucide_react15 = require("lucide-react");
|
|
12277
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
10954
12278
|
function FooterContainerChrome({
|
|
10955
12279
|
rect,
|
|
10956
12280
|
onAdd,
|
|
@@ -10958,7 +12282,7 @@ function FooterContainerChrome({
|
|
|
10958
12282
|
}) {
|
|
10959
12283
|
const chromeGap = 6;
|
|
10960
12284
|
const buttonMargin = 7;
|
|
10961
|
-
return /* @__PURE__ */ (0,
|
|
12285
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
10962
12286
|
"div",
|
|
10963
12287
|
{
|
|
10964
12288
|
"data-ohw-footer-container-chrome": "",
|
|
@@ -10970,8 +12294,8 @@ function FooterContainerChrome({
|
|
|
10970
12294
|
width: rect.width + chromeGap * 2,
|
|
10971
12295
|
height: rect.height + chromeGap * 2
|
|
10972
12296
|
},
|
|
10973
|
-
children: /* @__PURE__ */ (0,
|
|
10974
|
-
/* @__PURE__ */ (0,
|
|
12297
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(Tooltip, { children: [
|
|
12298
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
10975
12299
|
"button",
|
|
10976
12300
|
{
|
|
10977
12301
|
type: "button",
|
|
@@ -10990,17 +12314,17 @@ function FooterContainerChrome({
|
|
|
10990
12314
|
if (addDisabled) return;
|
|
10991
12315
|
onAdd();
|
|
10992
12316
|
},
|
|
10993
|
-
children: /* @__PURE__ */ (0,
|
|
12317
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
10994
12318
|
}
|
|
10995
12319
|
) }),
|
|
10996
|
-
/* @__PURE__ */ (0,
|
|
12320
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
|
|
10997
12321
|
] })
|
|
10998
12322
|
}
|
|
10999
12323
|
) });
|
|
11000
12324
|
}
|
|
11001
12325
|
|
|
11002
12326
|
// src/lib/carousel.ts
|
|
11003
|
-
var
|
|
12327
|
+
var import_react15 = require("react");
|
|
11004
12328
|
var CAROUSEL_ATTR = "data-ohw-carousel";
|
|
11005
12329
|
var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
|
|
11006
12330
|
var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
|
|
@@ -11062,8 +12386,8 @@ function applyCarouselNode(key, val) {
|
|
|
11062
12386
|
return true;
|
|
11063
12387
|
}
|
|
11064
12388
|
function useOhwCarousel(key, initial) {
|
|
11065
|
-
const [images, setImages] = (0,
|
|
11066
|
-
(0,
|
|
12389
|
+
const [images, setImages] = (0, import_react15.useState)(initial);
|
|
12390
|
+
(0, import_react15.useEffect)(() => {
|
|
11067
12391
|
const el = document.querySelector(
|
|
11068
12392
|
`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
|
|
11069
12393
|
);
|
|
@@ -11176,6 +12500,18 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
11176
12500
|
}
|
|
11177
12501
|
if (extraContent && !isScoped) {
|
|
11178
12502
|
applyNavFooterDeleteOverrides(byKey, extraContent);
|
|
12503
|
+
for (const key of LOGO_IMAGE_KEYS) {
|
|
12504
|
+
if (!(key in extraContent)) continue;
|
|
12505
|
+
byKey.set(key, { key, type: "image", text: extraContent[key] ?? "" });
|
|
12506
|
+
}
|
|
12507
|
+
for (const key of [LOGO_PLACEHOLDER_KEY, LOGO_ALT_KEY]) {
|
|
12508
|
+
if (!(key in extraContent)) continue;
|
|
12509
|
+
byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
|
|
12510
|
+
}
|
|
12511
|
+
for (const key of LOGO_SIZE_KEYS) {
|
|
12512
|
+
if (!(key in extraContent)) continue;
|
|
12513
|
+
byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
|
|
12514
|
+
}
|
|
11179
12515
|
}
|
|
11180
12516
|
return Array.from(byKey.values());
|
|
11181
12517
|
}
|
|
@@ -11278,7 +12614,7 @@ function isNavbarLinksContainer(el) {
|
|
|
11278
12614
|
function isNavigationItem(el) {
|
|
11279
12615
|
const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
|
|
11280
12616
|
if (!anchor) return false;
|
|
11281
|
-
return Boolean(anchor.querySelector('[data-ohw-editable="text"]'));
|
|
12617
|
+
return Boolean(anchor.querySelector('[data-ohw-editable="text"]')) || Boolean(getSocialItem(anchor));
|
|
11282
12618
|
}
|
|
11283
12619
|
function findFooterItemGroup(item) {
|
|
11284
12620
|
const explicit = item.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
|
|
@@ -11299,8 +12635,9 @@ function isInferredFooterGroup(el) {
|
|
|
11299
12635
|
const footer = el.closest("footer");
|
|
11300
12636
|
if (!footer || el === footer) return false;
|
|
11301
12637
|
if (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column")) return true;
|
|
12638
|
+
if (isSocialsRow(el)) return false;
|
|
11302
12639
|
const count = Array.from(el.querySelectorAll("[data-ohw-href-key]")).filter(
|
|
11303
|
-
isNavigationItem
|
|
12640
|
+
(item) => isNavigationItem(item) && !getSocialItem(item)
|
|
11304
12641
|
).length;
|
|
11305
12642
|
return count >= 2;
|
|
11306
12643
|
}
|
|
@@ -11344,7 +12681,8 @@ function deleteSelectedNavFooterItem(deps) {
|
|
|
11344
12681
|
if (key.endsWith("-href")) applyLinkByKey2(key, text);
|
|
11345
12682
|
else {
|
|
11346
12683
|
document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`).forEach((el) => {
|
|
11347
|
-
el.
|
|
12684
|
+
if (el.getAttribute("data-ohw-editable") === "icon") applyIconMarkup(el, text);
|
|
12685
|
+
else el.textContent = text;
|
|
11348
12686
|
});
|
|
11349
12687
|
}
|
|
11350
12688
|
}
|
|
@@ -11406,6 +12744,21 @@ function deleteSelectedNavFooterItem(deps) {
|
|
|
11406
12744
|
});
|
|
11407
12745
|
return true;
|
|
11408
12746
|
}
|
|
12747
|
+
const social = getSocialItem(selected);
|
|
12748
|
+
if (social) {
|
|
12749
|
+
const result = removeSocialItem(social, getEditContent());
|
|
12750
|
+
if (!result) return false;
|
|
12751
|
+
finishDelete({
|
|
12752
|
+
toastTitle: "Social deleted",
|
|
12753
|
+
removedKeys: result.removedKeys,
|
|
12754
|
+
previousContent: result.previousContent,
|
|
12755
|
+
orderKey: SOCIALS_ORDER_KEY,
|
|
12756
|
+
orderJson: JSON.stringify(result.order),
|
|
12757
|
+
previousOrderJson: JSON.stringify(result.previousOrder),
|
|
12758
|
+
undoDom: result.undo
|
|
12759
|
+
});
|
|
12760
|
+
return true;
|
|
12761
|
+
}
|
|
11409
12762
|
if (isFooterHrefKey(hrefKey)) {
|
|
11410
12763
|
const result = deleteFooterItem(selected);
|
|
11411
12764
|
if (!result) return false;
|
|
@@ -11424,14 +12777,14 @@ function deleteSelectedNavFooterItem(deps) {
|
|
|
11424
12777
|
}
|
|
11425
12778
|
|
|
11426
12779
|
// src/ui/navbar-container-chrome.tsx
|
|
11427
|
-
var
|
|
11428
|
-
var
|
|
12780
|
+
var import_lucide_react16 = require("lucide-react");
|
|
12781
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
11429
12782
|
function NavbarContainerChrome({
|
|
11430
12783
|
rect,
|
|
11431
12784
|
onAdd
|
|
11432
12785
|
}) {
|
|
11433
12786
|
const chromeGap = 6;
|
|
11434
|
-
return /* @__PURE__ */ (0,
|
|
12787
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
11435
12788
|
"div",
|
|
11436
12789
|
{
|
|
11437
12790
|
"data-ohw-navbar-container-chrome": "",
|
|
@@ -11443,7 +12796,7 @@ function NavbarContainerChrome({
|
|
|
11443
12796
|
width: rect.width + chromeGap * 2,
|
|
11444
12797
|
height: rect.height + chromeGap * 2
|
|
11445
12798
|
},
|
|
11446
|
-
children: /* @__PURE__ */ (0,
|
|
12799
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
11447
12800
|
"button",
|
|
11448
12801
|
{
|
|
11449
12802
|
type: "button",
|
|
@@ -11460,7 +12813,7 @@ function NavbarContainerChrome({
|
|
|
11460
12813
|
e.stopPropagation();
|
|
11461
12814
|
onAdd();
|
|
11462
12815
|
},
|
|
11463
|
-
children: /* @__PURE__ */ (0,
|
|
12816
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react16.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
11464
12817
|
}
|
|
11465
12818
|
)
|
|
11466
12819
|
}
|
|
@@ -11469,7 +12822,7 @@ function NavbarContainerChrome({
|
|
|
11469
12822
|
|
|
11470
12823
|
// src/ui/drop-indicator.tsx
|
|
11471
12824
|
var React10 = __toESM(require("react"), 1);
|
|
11472
|
-
var
|
|
12825
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
11473
12826
|
var dropIndicatorVariants = cva(
|
|
11474
12827
|
"ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
|
|
11475
12828
|
{
|
|
@@ -11493,7 +12846,7 @@ var dropIndicatorVariants = cva(
|
|
|
11493
12846
|
);
|
|
11494
12847
|
var DropIndicator = React10.forwardRef(
|
|
11495
12848
|
({ className, direction, state, ...props }, ref) => {
|
|
11496
|
-
return /* @__PURE__ */ (0,
|
|
12849
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
11497
12850
|
"div",
|
|
11498
12851
|
{
|
|
11499
12852
|
ref,
|
|
@@ -11510,7 +12863,7 @@ var DropIndicator = React10.forwardRef(
|
|
|
11510
12863
|
DropIndicator.displayName = "DropIndicator";
|
|
11511
12864
|
|
|
11512
12865
|
// src/ui/badge.tsx
|
|
11513
|
-
var
|
|
12866
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
11514
12867
|
var badgeVariants = cva(
|
|
11515
12868
|
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
11516
12869
|
{
|
|
@@ -11528,12 +12881,12 @@ var badgeVariants = cva(
|
|
|
11528
12881
|
}
|
|
11529
12882
|
);
|
|
11530
12883
|
function Badge({ className, variant, ...props }) {
|
|
11531
|
-
return /* @__PURE__ */ (0,
|
|
12884
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
11532
12885
|
}
|
|
11533
12886
|
|
|
11534
12887
|
// src/OhhwellsBridge.tsx
|
|
11535
|
-
var
|
|
11536
|
-
var
|
|
12888
|
+
var import_lucide_react17 = require("lucide-react");
|
|
12889
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
11537
12890
|
var PRIMARY3 = "#0885FE";
|
|
11538
12891
|
var IMAGE_FADE_MS = 300;
|
|
11539
12892
|
function runOpacityFade(el, onDone) {
|
|
@@ -11627,21 +12980,10 @@ function parseSchedulingInsertAfter(insertAfter) {
|
|
|
11627
12980
|
insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
|
|
11628
12981
|
};
|
|
11629
12982
|
}
|
|
11630
|
-
function
|
|
11631
|
-
|
|
11632
|
-
const
|
|
11633
|
-
|
|
11634
|
-
return { effectiveInsertAfter, insertBefore };
|
|
11635
|
-
}
|
|
11636
|
-
function getSchedulingMountPoint(insertAfter) {
|
|
11637
|
-
const { anchor } = parseSchedulingInsertAfter(insertAfter);
|
|
11638
|
-
let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
|
|
11639
|
-
if (!anchorEl && anchor === "scheduling") {
|
|
11640
|
-
const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
|
|
11641
|
-
anchorEl = widgets.at(-1) ?? null;
|
|
11642
|
-
}
|
|
11643
|
-
if (!anchorEl) return null;
|
|
11644
|
-
return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
12983
|
+
function resolveEntryAnchor(entry) {
|
|
12984
|
+
if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
|
|
12985
|
+
const parsed = parseSchedulingInsertAfter(entry.insertAfter);
|
|
12986
|
+
return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
|
|
11645
12987
|
}
|
|
11646
12988
|
function schedulingMountDepth(insertAfter) {
|
|
11647
12989
|
if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
|
|
@@ -11658,8 +13000,7 @@ function getPageSchedulingEntries(raw) {
|
|
|
11658
13000
|
}
|
|
11659
13001
|
}
|
|
11660
13002
|
function isSchedulingWidgetMissing(entry) {
|
|
11661
|
-
|
|
11662
|
-
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
|
|
13003
|
+
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
|
|
11663
13004
|
}
|
|
11664
13005
|
function hasMissingSchedulingWidgets(entries) {
|
|
11665
13006
|
return entries.some(isSchedulingWidgetMissing);
|
|
@@ -11689,16 +13030,17 @@ function initSectionsFromContent(content, removeExisting = false) {
|
|
|
11689
13030
|
} catch {
|
|
11690
13031
|
}
|
|
11691
13032
|
}
|
|
11692
|
-
function mountSchedulingWidget(
|
|
11693
|
-
const
|
|
11694
|
-
const sectionId = schedulingSectionId(
|
|
13033
|
+
function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
|
|
13034
|
+
const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
|
|
13035
|
+
const sectionId = schedulingSectionId(widgetId);
|
|
11695
13036
|
if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
|
|
11696
|
-
const
|
|
11697
|
-
if (!
|
|
13037
|
+
const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
|
|
13038
|
+
if (!anchorEl) return false;
|
|
13039
|
+
const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
11698
13040
|
const container = document.createElement("div");
|
|
11699
13041
|
container.dataset.ohwSectionContainer = "scheduling";
|
|
11700
|
-
if (
|
|
11701
|
-
const beforeAnchor = document.querySelector(`[data-ohw-section="${
|
|
13042
|
+
if (beforeId) {
|
|
13043
|
+
const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
|
|
11702
13044
|
const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
|
|
11703
13045
|
if (!beforePoint) return false;
|
|
11704
13046
|
beforePoint.insertAdjacentElement("beforebegin", container);
|
|
@@ -11709,19 +13051,25 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
11709
13051
|
}
|
|
11710
13052
|
tail.insertAdjacentElement("afterend", container);
|
|
11711
13053
|
}
|
|
11712
|
-
|
|
11713
|
-
|
|
11714
|
-
|
|
11715
|
-
|
|
11716
|
-
|
|
11717
|
-
|
|
11718
|
-
|
|
11719
|
-
|
|
11720
|
-
|
|
11721
|
-
|
|
11722
|
-
|
|
11723
|
-
|
|
11724
|
-
|
|
13054
|
+
try {
|
|
13055
|
+
const root = (0, import_client2.createRoot)(container);
|
|
13056
|
+
(0, import_react_dom3.flushSync)(() => {
|
|
13057
|
+
root.render(
|
|
13058
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
13059
|
+
SchedulingWidget,
|
|
13060
|
+
{
|
|
13061
|
+
notifyOnConnect,
|
|
13062
|
+
initialScheduleId: scheduleId,
|
|
13063
|
+
insertAfter: widgetId
|
|
13064
|
+
}
|
|
13065
|
+
)
|
|
13066
|
+
);
|
|
13067
|
+
});
|
|
13068
|
+
} catch (err) {
|
|
13069
|
+
console.error("[ow:scheduling] render threw", err);
|
|
13070
|
+
container.remove();
|
|
13071
|
+
return false;
|
|
13072
|
+
}
|
|
11725
13073
|
const tracker = getSectionsTracker();
|
|
11726
13074
|
let sections = [];
|
|
11727
13075
|
try {
|
|
@@ -11729,10 +13077,12 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
11729
13077
|
} catch {
|
|
11730
13078
|
}
|
|
11731
13079
|
const inEditor = typeof window !== "undefined" && window.self !== window.top;
|
|
11732
|
-
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter ===
|
|
13080
|
+
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
|
|
11733
13081
|
sections.push({
|
|
11734
13082
|
type: "scheduling",
|
|
11735
|
-
insertAfter:
|
|
13083
|
+
insertAfter: widgetId,
|
|
13084
|
+
anchorId,
|
|
13085
|
+
beforeId: beforeId ?? null,
|
|
11736
13086
|
pagePath: window.location.pathname,
|
|
11737
13087
|
...scheduleId ? { scheduleId } : {}
|
|
11738
13088
|
});
|
|
@@ -11746,7 +13096,8 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
11746
13096
|
for (let i = pending.length - 1; i >= 0; i--) {
|
|
11747
13097
|
const entry = pending[i];
|
|
11748
13098
|
const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
|
|
11749
|
-
|
|
13099
|
+
const { anchorId, beforeId } = resolveEntryAnchor(entry);
|
|
13100
|
+
if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
|
|
11750
13101
|
pending.splice(i, 1);
|
|
11751
13102
|
}
|
|
11752
13103
|
}
|
|
@@ -11760,6 +13111,17 @@ function applyLinkHref(el, val) {
|
|
|
11760
13111
|
const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
|
|
11761
13112
|
if (anchor) anchor.setAttribute("href", val);
|
|
11762
13113
|
}
|
|
13114
|
+
function currentIconRef(el) {
|
|
13115
|
+
const uploaded = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
13116
|
+
if (uploaded?.getAttribute("src")) {
|
|
13117
|
+
return uploaded.getAttribute("src") ?? "";
|
|
13118
|
+
}
|
|
13119
|
+
const svg = el instanceof SVGElement ? el : el.querySelector("svg");
|
|
13120
|
+
const named = Array.from(svg?.classList ?? []).find(
|
|
13121
|
+
(c) => c.startsWith("lucide-") && c !== "lucide-icon"
|
|
13122
|
+
);
|
|
13123
|
+
return named ? `lucide:${named.slice("lucide-".length)}` : "";
|
|
13124
|
+
}
|
|
11763
13125
|
function getEditMeasureEl(editable) {
|
|
11764
13126
|
return editable.closest("[data-ohw-href-key]") ?? editable;
|
|
11765
13127
|
}
|
|
@@ -11804,8 +13166,11 @@ function isMediaEditable(el) {
|
|
|
11804
13166
|
const t = el.dataset.ohwEditable;
|
|
11805
13167
|
return t === "image" || t === "bg-image" || t === "video";
|
|
11806
13168
|
}
|
|
13169
|
+
function isIconEditable(el) {
|
|
13170
|
+
return el.dataset.ohwEditable === "icon";
|
|
13171
|
+
}
|
|
11807
13172
|
var MEDIA_SELECTOR = '[data-ohw-editable="image"], [data-ohw-editable="bg-image"], [data-ohw-editable="video"]';
|
|
11808
|
-
var NON_MEDIA_SELECTOR = '[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"])';
|
|
13173
|
+
var NON_MEDIA_SELECTOR = '[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"]):not([data-ohw-editable="icon"])';
|
|
11809
13174
|
function getVideoEl2(el) {
|
|
11810
13175
|
return el instanceof HTMLVideoElement ? el : el.querySelector("video");
|
|
11811
13176
|
}
|
|
@@ -11876,6 +13241,13 @@ function isInsideLinkEditor(target) {
|
|
|
11876
13241
|
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"]')
|
|
11877
13242
|
);
|
|
11878
13243
|
}
|
|
13244
|
+
function isInsideFloatingPanel(target) {
|
|
13245
|
+
return Boolean(target.closest("[data-ohw-floating-panel]"));
|
|
13246
|
+
}
|
|
13247
|
+
function isPointOverFloatingPanel(clientX, clientY) {
|
|
13248
|
+
const el = document.elementFromPoint(clientX, clientY);
|
|
13249
|
+
return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
|
|
13250
|
+
}
|
|
11879
13251
|
function getHrefKeyFromElement(el) {
|
|
11880
13252
|
if (!el) return null;
|
|
11881
13253
|
const anchor = el.closest("[data-ohw-href-key]");
|
|
@@ -11923,13 +13295,29 @@ function isNavItemPointerTarget(el) {
|
|
|
11923
13295
|
function getNavigationItemAnchor(el) {
|
|
11924
13296
|
const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
|
|
11925
13297
|
if (!anchor) return null;
|
|
11926
|
-
if (!anchor.querySelector('[data-ohw-editable="text"]')) return null;
|
|
13298
|
+
if (!anchor.querySelector('[data-ohw-editable="text"]') && !getSocialItem(anchor)) return null;
|
|
11927
13299
|
if (!isNavItemPointerTarget(anchor)) return null;
|
|
11928
13300
|
return anchor;
|
|
11929
13301
|
}
|
|
11930
13302
|
function isNavigationItem2(el) {
|
|
11931
13303
|
return getNavigationItemAnchor(el) !== null;
|
|
11932
13304
|
}
|
|
13305
|
+
function requestSocialDialog(anchor, post, content) {
|
|
13306
|
+
const item = getSocialItem(anchor);
|
|
13307
|
+
if (!item) return false;
|
|
13308
|
+
const iconKey = item.querySelector('[data-ohw-editable="icon"]')?.dataset.ohwKey ?? "";
|
|
13309
|
+
post({
|
|
13310
|
+
type: "ow:social-pick",
|
|
13311
|
+
hrefKey: item.getAttribute("data-ohw-href-key") ?? "",
|
|
13312
|
+
iconKey,
|
|
13313
|
+
url: getLinkHref4(item),
|
|
13314
|
+
iconStyle: detectIconStyle(item),
|
|
13315
|
+
// What was chosen last time. Guessing from the address instead reads as "Website" for anything
|
|
13316
|
+
// unrecognised, and for an item with no address at all — so a deliberate choice looked lost.
|
|
13317
|
+
platformId: content[socialPlatformKey(iconKey)] ?? ""
|
|
13318
|
+
});
|
|
13319
|
+
return true;
|
|
13320
|
+
}
|
|
11933
13321
|
function listNavigationItems() {
|
|
11934
13322
|
return Array.from(
|
|
11935
13323
|
document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
|
|
@@ -11964,7 +13352,7 @@ function getNavigationRoot(el) {
|
|
|
11964
13352
|
return el.closest("nav, footer, aside");
|
|
11965
13353
|
}
|
|
11966
13354
|
function countFooterNavItems(el) {
|
|
11967
|
-
return Array.from(el.querySelectorAll("[data-ohw-href-key]")).filter(isNavigationItem2).length;
|
|
13355
|
+
return Array.from(el.querySelectorAll("[data-ohw-href-key]")).filter((item) => isNavigationItem2(item) && !getSocialItem(item)).length;
|
|
11968
13356
|
}
|
|
11969
13357
|
function findFooterItemGroup2(item) {
|
|
11970
13358
|
const explicit = item.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
|
|
@@ -11985,10 +13373,11 @@ function isInferredFooterGroup2(el) {
|
|
|
11985
13373
|
const footer = el.closest("footer");
|
|
11986
13374
|
if (!footer || el === footer) return false;
|
|
11987
13375
|
if (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column")) return true;
|
|
13376
|
+
if (isSocialsRow(el)) return false;
|
|
11988
13377
|
return countFooterNavItems(el) >= 2;
|
|
11989
13378
|
}
|
|
11990
13379
|
function isNavigationContainer(el) {
|
|
11991
|
-
return el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el) || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isNavigationRoot(el) || isInferredFooterGroup2(el);
|
|
13380
|
+
return el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el) || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isNavigationRoot(el) || isSocialsRow(el) || isInferredFooterGroup2(el);
|
|
11992
13381
|
}
|
|
11993
13382
|
function isNavbarLinksContainer2(el) {
|
|
11994
13383
|
return el.hasAttribute("data-ohw-nav-container");
|
|
@@ -11996,6 +13385,11 @@ function isNavbarLinksContainer2(el) {
|
|
|
11996
13385
|
function getFooterColumn(el) {
|
|
11997
13386
|
return el.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
|
|
11998
13387
|
}
|
|
13388
|
+
function isFooterAddItemDisabled(selected) {
|
|
13389
|
+
if (!selected) return false;
|
|
13390
|
+
const column = resolveFooterColumnForAdd(selected);
|
|
13391
|
+
return column ? !canAddFooterItem(column) : false;
|
|
13392
|
+
}
|
|
11999
13393
|
function resolveFooterColumnSelectionTarget(target, clientX, clientY) {
|
|
12000
13394
|
if (getNavigationItemAnchor(target)) return null;
|
|
12001
13395
|
const column = getFooterColumn(target);
|
|
@@ -12071,6 +13465,8 @@ function resolveNavContainerSelectionTarget(target, clientX, clientY) {
|
|
|
12071
13465
|
return null;
|
|
12072
13466
|
}
|
|
12073
13467
|
function getNavigationSelectionParent(el) {
|
|
13468
|
+
const socialsRow = findSocialsRow(el);
|
|
13469
|
+
if (socialsRow) return socialsRow;
|
|
12074
13470
|
if (isNavigationItem2(el)) {
|
|
12075
13471
|
const childrenRoot = el.closest("[data-ohw-nav-children]");
|
|
12076
13472
|
if (childrenRoot) {
|
|
@@ -12089,13 +13485,17 @@ function getNavigationSelectionParent(el) {
|
|
|
12089
13485
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
12090
13486
|
return getFooterLinksContainer();
|
|
12091
13487
|
}
|
|
12092
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
13488
|
+
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)) {
|
|
12093
13489
|
return getNavigationRoot(el);
|
|
12094
13490
|
}
|
|
12095
13491
|
return null;
|
|
12096
13492
|
}
|
|
12097
13493
|
function collectNavigationItemSiblingHintRects(selected) {
|
|
12098
13494
|
if (!isNavigationItem2(selected)) return [];
|
|
13495
|
+
const socialsRow = findSocialsRow(selected);
|
|
13496
|
+
if (socialsRow) {
|
|
13497
|
+
return listSocialItems(socialsRow).filter((item) => item !== selected).map((item) => item.getBoundingClientRect());
|
|
13498
|
+
}
|
|
12099
13499
|
const footerColumn = getFooterColumn(selected);
|
|
12100
13500
|
if (footerColumn) {
|
|
12101
13501
|
return listFooterLinksInColumn(footerColumn).filter((link) => link !== selected).map((link) => link.getBoundingClientRect());
|
|
@@ -12303,6 +13703,9 @@ var ICONS = {
|
|
|
12303
13703
|
var SELECTION_CHROME_GAP2 = 4;
|
|
12304
13704
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
12305
13705
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
13706
|
+
var HOVER_STROKE_WIDTH = 1.5;
|
|
13707
|
+
var TEXT_HOVER_SIDE_PAD = 4;
|
|
13708
|
+
var CHROME_PRIMARY = `var(--ohw-primary, ${PRIMARY3})`;
|
|
12306
13709
|
var TOOLBAR_GROUPS = [
|
|
12307
13710
|
[
|
|
12308
13711
|
{ cmd: "bold", title: "Bold" },
|
|
@@ -12328,7 +13731,7 @@ function EditGlowChrome({
|
|
|
12328
13731
|
hideHandle = false
|
|
12329
13732
|
}) {
|
|
12330
13733
|
const GAP = SELECTION_CHROME_GAP2;
|
|
12331
|
-
return /* @__PURE__ */ (0,
|
|
13734
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
12332
13735
|
"div",
|
|
12333
13736
|
{
|
|
12334
13737
|
ref: elRef,
|
|
@@ -12343,7 +13746,7 @@ function EditGlowChrome({
|
|
|
12343
13746
|
zIndex: 2147483646
|
|
12344
13747
|
},
|
|
12345
13748
|
children: [
|
|
12346
|
-
/* @__PURE__ */ (0,
|
|
13749
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
12347
13750
|
"div",
|
|
12348
13751
|
{
|
|
12349
13752
|
style: {
|
|
@@ -12356,7 +13759,7 @@ function EditGlowChrome({
|
|
|
12356
13759
|
}
|
|
12357
13760
|
}
|
|
12358
13761
|
),
|
|
12359
|
-
reorderHrefKey && !hideHandle && /* @__PURE__ */ (0,
|
|
13762
|
+
reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
12360
13763
|
"div",
|
|
12361
13764
|
{
|
|
12362
13765
|
"data-ohw-drag-handle-container": "",
|
|
@@ -12368,7 +13771,7 @@ function EditGlowChrome({
|
|
|
12368
13771
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
12369
13772
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
12370
13773
|
},
|
|
12371
|
-
children: /* @__PURE__ */ (0,
|
|
13774
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
12372
13775
|
DragHandle,
|
|
12373
13776
|
{
|
|
12374
13777
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -12551,9 +13954,9 @@ function FloatingToolbar({
|
|
|
12551
13954
|
showEditLink,
|
|
12552
13955
|
onEditLink
|
|
12553
13956
|
}) {
|
|
12554
|
-
const localRef =
|
|
12555
|
-
const [measuredW, setMeasuredW] =
|
|
12556
|
-
const setRefs =
|
|
13957
|
+
const localRef = import_react16.default.useRef(null);
|
|
13958
|
+
const [measuredW, setMeasuredW] = import_react16.default.useState(330);
|
|
13959
|
+
const setRefs = import_react16.default.useCallback(
|
|
12557
13960
|
(node) => {
|
|
12558
13961
|
localRef.current = node;
|
|
12559
13962
|
if (typeof elRef === "function") elRef(node);
|
|
@@ -12565,7 +13968,7 @@ function FloatingToolbar({
|
|
|
12565
13968
|
},
|
|
12566
13969
|
[elRef]
|
|
12567
13970
|
);
|
|
12568
|
-
|
|
13971
|
+
import_react16.default.useLayoutEffect(() => {
|
|
12569
13972
|
const node = localRef.current;
|
|
12570
13973
|
if (!node) return;
|
|
12571
13974
|
const update = () => {
|
|
@@ -12578,7 +13981,7 @@ function FloatingToolbar({
|
|
|
12578
13981
|
return () => ro.disconnect();
|
|
12579
13982
|
}, [showEditLink, activeCommands]);
|
|
12580
13983
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
|
|
12581
|
-
return /* @__PURE__ */ (0,
|
|
13984
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
12582
13985
|
"div",
|
|
12583
13986
|
{
|
|
12584
13987
|
ref: setRefs,
|
|
@@ -12590,12 +13993,12 @@ function FloatingToolbar({
|
|
|
12590
13993
|
zIndex: 2147483647,
|
|
12591
13994
|
pointerEvents: "auto"
|
|
12592
13995
|
},
|
|
12593
|
-
children: /* @__PURE__ */ (0,
|
|
12594
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0,
|
|
12595
|
-
gi > 0 && /* @__PURE__ */ (0,
|
|
13996
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(CustomToolbar, { children: [
|
|
13997
|
+
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_react16.default.Fragment, { children: [
|
|
13998
|
+
gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CustomToolbarDivider, {}),
|
|
12596
13999
|
btns.map((btn) => {
|
|
12597
14000
|
const isActive = activeCommands.has(btn.cmd);
|
|
12598
|
-
return /* @__PURE__ */ (0,
|
|
14001
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
12599
14002
|
CustomToolbarButton,
|
|
12600
14003
|
{
|
|
12601
14004
|
title: btn.title,
|
|
@@ -12604,7 +14007,7 @@ function FloatingToolbar({
|
|
|
12604
14007
|
e.preventDefault();
|
|
12605
14008
|
onCommand(btn.cmd);
|
|
12606
14009
|
},
|
|
12607
|
-
children: /* @__PURE__ */ (0,
|
|
14010
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
12608
14011
|
"svg",
|
|
12609
14012
|
{
|
|
12610
14013
|
width: "16",
|
|
@@ -12625,7 +14028,7 @@ function FloatingToolbar({
|
|
|
12625
14028
|
);
|
|
12626
14029
|
})
|
|
12627
14030
|
] }, gi)),
|
|
12628
|
-
showEditLink ? /* @__PURE__ */ (0,
|
|
14031
|
+
showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
12629
14032
|
CustomToolbarButton,
|
|
12630
14033
|
{
|
|
12631
14034
|
type: "button",
|
|
@@ -12639,7 +14042,7 @@ function FloatingToolbar({
|
|
|
12639
14042
|
e.preventDefault();
|
|
12640
14043
|
e.stopPropagation();
|
|
12641
14044
|
},
|
|
12642
|
-
children: /* @__PURE__ */ (0,
|
|
14045
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Link, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
12643
14046
|
}
|
|
12644
14047
|
) : null
|
|
12645
14048
|
] })
|
|
@@ -12656,7 +14059,7 @@ function StateToggle({
|
|
|
12656
14059
|
states,
|
|
12657
14060
|
onStateChange
|
|
12658
14061
|
}) {
|
|
12659
|
-
return /* @__PURE__ */ (0,
|
|
14062
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
12660
14063
|
ToggleGroup,
|
|
12661
14064
|
{
|
|
12662
14065
|
"data-ohw-state-toggle": "",
|
|
@@ -12670,11 +14073,12 @@ function StateToggle({
|
|
|
12670
14073
|
left: rect.right - 8,
|
|
12671
14074
|
transform: "translateX(-100%)"
|
|
12672
14075
|
},
|
|
12673
|
-
children: states.map((state) => /* @__PURE__ */ (0,
|
|
14076
|
+
children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
12674
14077
|
}
|
|
12675
14078
|
);
|
|
12676
14079
|
}
|
|
12677
14080
|
var contentCache = /* @__PURE__ */ new Map();
|
|
14081
|
+
var fetchedContentPaths = /* @__PURE__ */ new Set();
|
|
12678
14082
|
function resolveSubdomain(subdomainFromQuery) {
|
|
12679
14083
|
if (subdomainFromQuery) return subdomainFromQuery;
|
|
12680
14084
|
if (typeof window !== "undefined") {
|
|
@@ -12697,8 +14101,8 @@ function OhhwellsBridge() {
|
|
|
12697
14101
|
const router = (0, import_navigation3.useRouter)();
|
|
12698
14102
|
const searchParams = (0, import_navigation3.useSearchParams)();
|
|
12699
14103
|
const isEditMode = isEditSessionActive();
|
|
12700
|
-
const [bridgeRoot, setBridgeRoot] = (0,
|
|
12701
|
-
(0,
|
|
14104
|
+
const [bridgeRoot, setBridgeRoot] = (0, import_react16.useState)(null);
|
|
14105
|
+
(0, import_react16.useEffect)(() => {
|
|
12702
14106
|
const figtreeFontId = "ohw-figtree-font";
|
|
12703
14107
|
if (!document.getElementById(figtreeFontId)) {
|
|
12704
14108
|
const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
|
|
@@ -12727,110 +14131,159 @@ function OhhwellsBridge() {
|
|
|
12727
14131
|
const subdomain = resolveSubdomain(subdomainFromQuery);
|
|
12728
14132
|
useLinkHrefGuardian(pathname, subdomain, isEditMode);
|
|
12729
14133
|
useSavedLinkNavigation(isEditMode);
|
|
12730
|
-
const postToParent2 = (0,
|
|
14134
|
+
const postToParent2 = (0, import_react16.useCallback)((data) => {
|
|
12731
14135
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
12732
14136
|
window.parent.postMessage(data, "*");
|
|
12733
14137
|
}
|
|
12734
14138
|
}, []);
|
|
12735
|
-
const [fetchState, setFetchState] = (0,
|
|
12736
|
-
const autoSaveTimers = (0,
|
|
12737
|
-
const activeElRef = (0,
|
|
12738
|
-
const pointerHeldRef = (0,
|
|
12739
|
-
const selectedElRef = (0,
|
|
12740
|
-
const selectedHrefKeyRef = (0,
|
|
12741
|
-
const selectedFooterColAttrRef = (0,
|
|
12742
|
-
const originalContentRef = (0,
|
|
12743
|
-
const activeStateElRef = (0,
|
|
12744
|
-
const parentScrollRef = (0,
|
|
12745
|
-
const visibleViewportRef = (0,
|
|
12746
|
-
const [dialogPortalContainer, setDialogPortalContainer] = (0,
|
|
12747
|
-
const attachVisibleViewport = (0,
|
|
14139
|
+
const [fetchState, setFetchState] = (0, import_react16.useState)("idle");
|
|
14140
|
+
const autoSaveTimers = (0, import_react16.useRef)(/* @__PURE__ */ new Map());
|
|
14141
|
+
const activeElRef = (0, import_react16.useRef)(null);
|
|
14142
|
+
const pointerHeldRef = (0, import_react16.useRef)(false);
|
|
14143
|
+
const selectedElRef = (0, import_react16.useRef)(null);
|
|
14144
|
+
const selectedHrefKeyRef = (0, import_react16.useRef)(null);
|
|
14145
|
+
const selectedFooterColAttrRef = (0, import_react16.useRef)(null);
|
|
14146
|
+
const originalContentRef = (0, import_react16.useRef)(null);
|
|
14147
|
+
const activeStateElRef = (0, import_react16.useRef)(null);
|
|
14148
|
+
const parentScrollRef = (0, import_react16.useRef)(null);
|
|
14149
|
+
const visibleViewportRef = (0, import_react16.useRef)(null);
|
|
14150
|
+
const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react16.useState)(null);
|
|
14151
|
+
const attachVisibleViewport = (0, import_react16.useCallback)((node) => {
|
|
12748
14152
|
visibleViewportRef.current = node;
|
|
12749
14153
|
setDialogPortalContainer(node);
|
|
12750
14154
|
if (node) applyVisibleViewport(node, parentScrollRef.current);
|
|
12751
14155
|
}, []);
|
|
12752
|
-
const toolbarElRef = (0,
|
|
12753
|
-
const glowElRef = (0,
|
|
12754
|
-
const hoveredImageRef = (0,
|
|
12755
|
-
const hoveredImageHasTextOverlapRef = (0,
|
|
12756
|
-
const dragOverElRef = (0,
|
|
12757
|
-
const [mediaHover, setMediaHover] = (0,
|
|
12758
|
-
const [carouselHover, setCarouselHover] = (0,
|
|
12759
|
-
const [uploadingRects, setUploadingRects] = (0,
|
|
12760
|
-
const hoveredGapRef = (0,
|
|
12761
|
-
const imageUnhoverTimerRef = (0,
|
|
12762
|
-
const imageShowTimerRef = (0,
|
|
12763
|
-
const editStylesRef = (0,
|
|
12764
|
-
const activateRef = (0,
|
|
14156
|
+
const toolbarElRef = (0, import_react16.useRef)(null);
|
|
14157
|
+
const glowElRef = (0, import_react16.useRef)(null);
|
|
14158
|
+
const hoveredImageRef = (0, import_react16.useRef)(null);
|
|
14159
|
+
const hoveredImageHasTextOverlapRef = (0, import_react16.useRef)(false);
|
|
14160
|
+
const dragOverElRef = (0, import_react16.useRef)(null);
|
|
14161
|
+
const [mediaHover, setMediaHover] = (0, import_react16.useState)(null);
|
|
14162
|
+
const [carouselHover, setCarouselHover] = (0, import_react16.useState)(null);
|
|
14163
|
+
const [uploadingRects, setUploadingRects] = (0, import_react16.useState)({});
|
|
14164
|
+
const hoveredGapRef = (0, import_react16.useRef)(null);
|
|
14165
|
+
const imageUnhoverTimerRef = (0, import_react16.useRef)(null);
|
|
14166
|
+
const imageShowTimerRef = (0, import_react16.useRef)(null);
|
|
14167
|
+
const editStylesRef = (0, import_react16.useRef)(null);
|
|
14168
|
+
const activateRef = (0, import_react16.useRef)(() => {
|
|
14169
|
+
});
|
|
14170
|
+
const deactivateRef = (0, import_react16.useRef)(() => {
|
|
14171
|
+
});
|
|
14172
|
+
const selectRef = (0, import_react16.useRef)(() => {
|
|
12765
14173
|
});
|
|
12766
|
-
const
|
|
14174
|
+
const selectFrameRef = (0, import_react16.useRef)(() => {
|
|
12767
14175
|
});
|
|
12768
|
-
const
|
|
14176
|
+
const selectLogoRef = (0, import_react16.useRef)(() => {
|
|
12769
14177
|
});
|
|
12770
|
-
const
|
|
14178
|
+
const openLogoSizePanelRef = (0, import_react16.useRef)(() => {
|
|
12771
14179
|
});
|
|
12772
|
-
const deselectRef = (0,
|
|
14180
|
+
const deselectRef = (0, import_react16.useRef)(() => {
|
|
12773
14181
|
});
|
|
12774
|
-
const
|
|
14182
|
+
const closeFloatingPanelOnlyRef = (0, import_react16.useRef)(() => {
|
|
12775
14183
|
});
|
|
12776
|
-
const
|
|
14184
|
+
const reselectNavigationItemRef = (0, import_react16.useRef)(() => {
|
|
12777
14185
|
});
|
|
12778
|
-
const
|
|
12779
|
-
const runPendingDeleteUndoRef = (0, import_react15.useRef)(() => false);
|
|
12780
|
-
const isFooterFrameSelectionRef = (0, import_react15.useRef)(false);
|
|
12781
|
-
const refreshActiveCommandsRef = (0, import_react15.useRef)(() => {
|
|
14186
|
+
const commitNavigationTextEditRef = (0, import_react16.useRef)(() => {
|
|
12782
14187
|
});
|
|
12783
|
-
const
|
|
14188
|
+
const handleDeleteSelectedRef = (0, import_react16.useRef)(() => false);
|
|
14189
|
+
const runPendingDeleteUndoRef = (0, import_react16.useRef)(() => false);
|
|
14190
|
+
const isFooterFrameSelectionRef = (0, import_react16.useRef)(false);
|
|
14191
|
+
const refreshActiveCommandsRef = (0, import_react16.useRef)(() => {
|
|
14192
|
+
});
|
|
14193
|
+
const postToParentRef = (0, import_react16.useRef)(postToParent2);
|
|
12784
14194
|
postToParentRef.current = postToParent2;
|
|
12785
|
-
const aiSectionApiRef = (0,
|
|
12786
|
-
const sectionsLoadedRef = (0,
|
|
12787
|
-
const pendingScheduleConfigRequests = (0,
|
|
12788
|
-
const [toolbarRect, setToolbarRect] = (0,
|
|
12789
|
-
const [toolbarVariant, setToolbarVariant] = (0,
|
|
12790
|
-
const toolbarVariantRef = (0,
|
|
14195
|
+
const aiSectionApiRef = (0, import_react16.useRef)(null);
|
|
14196
|
+
const sectionsLoadedRef = (0, import_react16.useRef)(false);
|
|
14197
|
+
const pendingScheduleConfigRequests = (0, import_react16.useRef)([]);
|
|
14198
|
+
const [toolbarRect, setToolbarRect] = (0, import_react16.useState)(null);
|
|
14199
|
+
const [toolbarVariant, setToolbarVariant] = (0, import_react16.useState)("none");
|
|
14200
|
+
const toolbarVariantRef = (0, import_react16.useRef)("none");
|
|
12791
14201
|
toolbarVariantRef.current = toolbarVariant;
|
|
12792
|
-
const [selectedIsCta, setSelectedIsCta] = (0,
|
|
12793
|
-
const [
|
|
12794
|
-
const [
|
|
12795
|
-
const [
|
|
12796
|
-
const [
|
|
12797
|
-
const [
|
|
12798
|
-
const [
|
|
12799
|
-
const [
|
|
12800
|
-
const
|
|
12801
|
-
const [
|
|
12802
|
-
const
|
|
12803
|
-
const [
|
|
12804
|
-
const
|
|
12805
|
-
const [
|
|
12806
|
-
const [
|
|
12807
|
-
|
|
12808
|
-
|
|
14202
|
+
const [selectedIsCta, setSelectedIsCta] = (0, import_react16.useState)(false);
|
|
14203
|
+
const [selectedIsSocial, setSelectedIsSocial] = (0, import_react16.useState)(false);
|
|
14204
|
+
const [selectedIsSocialsRow, setSelectedIsSocialsRow] = (0, import_react16.useState)(false);
|
|
14205
|
+
const [reorderHrefKey, setReorderHrefKey] = (0, import_react16.useState)(null);
|
|
14206
|
+
const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react16.useState)(false);
|
|
14207
|
+
const [toggleState, setToggleState] = (0, import_react16.useState)(null);
|
|
14208
|
+
const [maxBadge, setMaxBadge] = (0, import_react16.useState)(null);
|
|
14209
|
+
const [activeCommands, setActiveCommands] = (0, import_react16.useState)(/* @__PURE__ */ new Set());
|
|
14210
|
+
const [sectionGap, setSectionGap] = (0, import_react16.useState)(null);
|
|
14211
|
+
const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react16.useState)(false);
|
|
14212
|
+
const hoveredNavContainerRef = (0, import_react16.useRef)(null);
|
|
14213
|
+
const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react16.useState)(null);
|
|
14214
|
+
const hoveredItemElRef = (0, import_react16.useRef)(null);
|
|
14215
|
+
const [hoveredItemRect, setHoveredItemRect] = (0, import_react16.useState)(null);
|
|
14216
|
+
const [hoveredTextRect, setHoveredTextRect] = (0, import_react16.useState)(null);
|
|
14217
|
+
(0, import_react16.useEffect)(() => {
|
|
14218
|
+
const sync = () => {
|
|
14219
|
+
const el = document.querySelector(
|
|
14220
|
+
"[data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key])"
|
|
14221
|
+
);
|
|
14222
|
+
const target = el && !el.closest("[data-ohw-href-key]") ? el : null;
|
|
14223
|
+
if (!target) {
|
|
14224
|
+
setHoveredTextRect(null);
|
|
14225
|
+
return;
|
|
14226
|
+
}
|
|
14227
|
+
const r2 = target.getBoundingClientRect();
|
|
14228
|
+
setHoveredTextRect(new DOMRect(r2.x - TEXT_HOVER_SIDE_PAD, r2.y, r2.width + TEXT_HOVER_SIDE_PAD * 2, r2.height));
|
|
14229
|
+
};
|
|
14230
|
+
const observer = new MutationObserver(sync);
|
|
14231
|
+
observer.observe(document.documentElement, {
|
|
14232
|
+
attributes: true,
|
|
14233
|
+
attributeFilter: ["data-ohw-hovered"],
|
|
14234
|
+
subtree: true
|
|
14235
|
+
});
|
|
14236
|
+
return () => observer.disconnect();
|
|
14237
|
+
}, []);
|
|
14238
|
+
const siblingHintElRef = (0, import_react16.useRef)(null);
|
|
14239
|
+
const [siblingHintRect, setSiblingHintRect] = (0, import_react16.useState)(null);
|
|
14240
|
+
const [siblingHintRects, setSiblingHintRects] = (0, import_react16.useState)([]);
|
|
14241
|
+
const [isItemDragging, setIsItemDragging] = (0, import_react16.useState)(false);
|
|
14242
|
+
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react16.useState)(false);
|
|
12809
14243
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
12810
|
-
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0,
|
|
12811
|
-
const [footerHeadingVisible, setFooterHeadingVisible] = (0,
|
|
12812
|
-
const footerDragRef = (0,
|
|
12813
|
-
const [footerDropSlots, setFooterDropSlots] = (0,
|
|
12814
|
-
const [activeFooterDropIndex, setActiveFooterDropIndex] = (0,
|
|
12815
|
-
const [draggedItemRect, setDraggedItemRect] = (0,
|
|
12816
|
-
const footerPointerDragRef = (0,
|
|
12817
|
-
const suppressNextClickRef = (0,
|
|
12818
|
-
const suppressClickUntilRef = (0,
|
|
12819
|
-
const [linkPopover, setLinkPopover] = (0,
|
|
12820
|
-
const linkPopoverSessionRef = (0,
|
|
12821
|
-
const addNavAfterAnchorRef = (0,
|
|
12822
|
-
const editContentRef = (0,
|
|
12823
|
-
const aiSectionsRef = (0,
|
|
12824
|
-
const
|
|
12825
|
-
const
|
|
12826
|
-
const [
|
|
12827
|
-
const
|
|
12828
|
-
const
|
|
12829
|
-
const
|
|
12830
|
-
const
|
|
12831
|
-
const
|
|
14244
|
+
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react16.useState)(null);
|
|
14245
|
+
const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react16.useState)(null);
|
|
14246
|
+
const footerDragRef = (0, import_react16.useRef)(null);
|
|
14247
|
+
const [footerDropSlots, setFooterDropSlots] = (0, import_react16.useState)([]);
|
|
14248
|
+
const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react16.useState)(null);
|
|
14249
|
+
const [draggedItemRect, setDraggedItemRect] = (0, import_react16.useState)(null);
|
|
14250
|
+
const footerPointerDragRef = (0, import_react16.useRef)(null);
|
|
14251
|
+
const suppressNextClickRef = (0, import_react16.useRef)(false);
|
|
14252
|
+
const suppressClickUntilRef = (0, import_react16.useRef)(0);
|
|
14253
|
+
const [linkPopover, setLinkPopover] = (0, import_react16.useState)(null);
|
|
14254
|
+
const linkPopoverSessionRef = (0, import_react16.useRef)(null);
|
|
14255
|
+
const addNavAfterAnchorRef = (0, import_react16.useRef)(null);
|
|
14256
|
+
const editContentRef = (0, import_react16.useRef)({});
|
|
14257
|
+
const aiSectionsRef = (0, import_react16.useRef)("");
|
|
14258
|
+
const brandKitRef = (0, import_react16.useRef)("");
|
|
14259
|
+
const pendingDeleteUndoRef = (0, import_react16.useRef)(null);
|
|
14260
|
+
const [floatingPanel, setFloatingPanel] = (0, import_react16.useState)(null);
|
|
14261
|
+
const floatingPanelOpenRef = (0, import_react16.useRef)(false);
|
|
14262
|
+
const setFloatingPanelRef = (0, import_react16.useRef)(setFloatingPanel);
|
|
14263
|
+
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react16.useState)(null);
|
|
14264
|
+
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react16.useState)(null);
|
|
14265
|
+
const [editorViewport, setEditorViewport] = (0, import_react16.useState)("desktop");
|
|
14266
|
+
const [parentScrollSnap, setParentScrollSnap] = (0, import_react16.useState)(null);
|
|
14267
|
+
const [sitePages, setSitePages] = (0, import_react16.useState)([]);
|
|
14268
|
+
const [sectionsByPath, setSectionsByPath] = (0, import_react16.useState)({});
|
|
14269
|
+
const sectionsPrefetchGenRef = (0, import_react16.useRef)(0);
|
|
14270
|
+
const setLinkPopoverRef = (0, import_react16.useRef)(setLinkPopover);
|
|
14271
|
+
const linkPopoverPanelRef = (0, import_react16.useRef)(null);
|
|
14272
|
+
const linkPopoverOpenRef = (0, import_react16.useRef)(false);
|
|
14273
|
+
const linkPopoverGraceUntilRef = (0, import_react16.useRef)(0);
|
|
12832
14274
|
setLinkPopoverRef.current = setLinkPopover;
|
|
14275
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
12833
14276
|
linkPopoverSessionRef.current = linkPopover;
|
|
14277
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
14278
|
+
(0, import_react16.useEffect)(() => {
|
|
14279
|
+
const syncViewport = () => {
|
|
14280
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
14281
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
14282
|
+
};
|
|
14283
|
+
syncViewport();
|
|
14284
|
+
window.addEventListener("resize", syncViewport);
|
|
14285
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
14286
|
+
}, []);
|
|
12834
14287
|
const {
|
|
12835
14288
|
navDragRef,
|
|
12836
14289
|
navDropSlots,
|
|
@@ -12866,7 +14319,7 @@ function OhhwellsBridge() {
|
|
|
12866
14319
|
const bumpLinkPopoverGrace = () => {
|
|
12867
14320
|
linkPopoverGraceUntilRef.current = Date.now() + 350;
|
|
12868
14321
|
};
|
|
12869
|
-
const runSectionsPrefetch = (0,
|
|
14322
|
+
const runSectionsPrefetch = (0, import_react16.useCallback)((pages) => {
|
|
12870
14323
|
if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
|
|
12871
14324
|
const gen = ++sectionsPrefetchGenRef.current;
|
|
12872
14325
|
const paths = pages.map((p) => p.path);
|
|
@@ -12885,9 +14338,9 @@ function OhhwellsBridge() {
|
|
|
12885
14338
|
);
|
|
12886
14339
|
});
|
|
12887
14340
|
}, [isEditMode, pathname]);
|
|
12888
|
-
const runSectionsPrefetchRef = (0,
|
|
14341
|
+
const runSectionsPrefetchRef = (0, import_react16.useRef)(runSectionsPrefetch);
|
|
12889
14342
|
runSectionsPrefetchRef.current = runSectionsPrefetch;
|
|
12890
|
-
(0,
|
|
14343
|
+
(0, import_react16.useEffect)(() => {
|
|
12891
14344
|
if (!linkPopover) {
|
|
12892
14345
|
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
12893
14346
|
return;
|
|
@@ -12915,7 +14368,7 @@ function OhhwellsBridge() {
|
|
|
12915
14368
|
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
12916
14369
|
};
|
|
12917
14370
|
}, [linkPopover, postToParent2]);
|
|
12918
|
-
(0,
|
|
14371
|
+
(0, import_react16.useEffect)(() => {
|
|
12919
14372
|
if (!isEditMode) return;
|
|
12920
14373
|
const useFixtures = shouldUseDevFixtures();
|
|
12921
14374
|
if (useFixtures) {
|
|
@@ -12939,14 +14392,14 @@ function OhhwellsBridge() {
|
|
|
12939
14392
|
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
12940
14393
|
return () => window.removeEventListener("message", onSitePages);
|
|
12941
14394
|
}, [isEditMode, postToParent2]);
|
|
12942
|
-
(0,
|
|
14395
|
+
(0, import_react16.useEffect)(() => {
|
|
12943
14396
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
12944
14397
|
void loadAllSectionsManifest().then((manifest) => {
|
|
12945
14398
|
if (Object.keys(manifest).length === 0) return;
|
|
12946
14399
|
setSectionsByPath((prev) => ({ ...manifest, ...prev }));
|
|
12947
14400
|
});
|
|
12948
14401
|
}, [isEditMode]);
|
|
12949
|
-
(0,
|
|
14402
|
+
(0, import_react16.useEffect)(() => {
|
|
12950
14403
|
const update = () => {
|
|
12951
14404
|
const el = activeElRef.current ?? selectedElRef.current;
|
|
12952
14405
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
@@ -12970,10 +14423,10 @@ function OhhwellsBridge() {
|
|
|
12970
14423
|
vvp.removeEventListener("resize", update);
|
|
12971
14424
|
};
|
|
12972
14425
|
}, []);
|
|
12973
|
-
const refreshStateRules = (0,
|
|
14426
|
+
const refreshStateRules = (0, import_react16.useCallback)(() => {
|
|
12974
14427
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
12975
14428
|
}, []);
|
|
12976
|
-
const processConfigRequest = (0,
|
|
14429
|
+
const processConfigRequest = (0, import_react16.useCallback)((insertAfterVal) => {
|
|
12977
14430
|
const tracker = getSectionsTracker();
|
|
12978
14431
|
let entries = [];
|
|
12979
14432
|
try {
|
|
@@ -12996,7 +14449,7 @@ function OhhwellsBridge() {
|
|
|
12996
14449
|
}
|
|
12997
14450
|
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
|
|
12998
14451
|
}, [isEditMode]);
|
|
12999
|
-
const deactivate = (0,
|
|
14452
|
+
const deactivate = (0, import_react16.useCallback)(() => {
|
|
13000
14453
|
const el = activeElRef.current;
|
|
13001
14454
|
if (!el) return;
|
|
13002
14455
|
const key = el.dataset.ohwKey;
|
|
@@ -13029,17 +14482,19 @@ function OhhwellsBridge() {
|
|
|
13029
14482
|
setToolbarShowEditLink(false);
|
|
13030
14483
|
postToParent2({ type: "ow:exit-edit" });
|
|
13031
14484
|
}, [postToParent2]);
|
|
13032
|
-
const clearSelectedAttr = (0,
|
|
14485
|
+
const clearSelectedAttr = (0, import_react16.useCallback)(() => {
|
|
13033
14486
|
document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
|
|
13034
14487
|
el.removeAttribute("data-ohw-selected");
|
|
13035
14488
|
});
|
|
13036
14489
|
}, []);
|
|
13037
|
-
const deselect = (0,
|
|
14490
|
+
const deselect = (0, import_react16.useCallback)(() => {
|
|
13038
14491
|
clearSelectedAttr();
|
|
13039
14492
|
selectedElRef.current = null;
|
|
13040
14493
|
selectedHrefKeyRef.current = null;
|
|
13041
14494
|
selectedFooterColAttrRef.current = null;
|
|
13042
14495
|
setSelectedIsCta(false);
|
|
14496
|
+
setSelectedIsSocial(false);
|
|
14497
|
+
setSelectedIsSocialsRow(false);
|
|
13043
14498
|
setReorderHrefKey(null);
|
|
13044
14499
|
setReorderDragDisabled(false);
|
|
13045
14500
|
setIsFooterFrameSelection(false);
|
|
@@ -13051,17 +14506,21 @@ function OhhwellsBridge() {
|
|
|
13051
14506
|
setIsItemDragging(false);
|
|
13052
14507
|
hoveredNavContainerRef.current = null;
|
|
13053
14508
|
setHoveredNavContainerRect(null);
|
|
14509
|
+
hoveredItemElRef.current = null;
|
|
14510
|
+
setHoveredItemRect(null);
|
|
14511
|
+
setFloatingPanel(null);
|
|
14512
|
+
setLogoSizeDraft(null);
|
|
13054
14513
|
if (!activeElRef.current) {
|
|
13055
14514
|
setNavGroupForceOpen(null, false);
|
|
13056
14515
|
setToolbarRect(null);
|
|
13057
14516
|
setToolbarVariant("none");
|
|
13058
14517
|
}
|
|
13059
14518
|
}, [clearSelectedAttr]);
|
|
13060
|
-
const markSelected = (0,
|
|
14519
|
+
const markSelected = (0, import_react16.useCallback)((el) => {
|
|
13061
14520
|
clearSelectedAttr();
|
|
13062
14521
|
el.setAttribute("data-ohw-selected", "");
|
|
13063
14522
|
}, [clearSelectedAttr]);
|
|
13064
|
-
const resolveHrefKeyElement = (0,
|
|
14523
|
+
const resolveHrefKeyElement = (0, import_react16.useCallback)((hrefKey) => {
|
|
13065
14524
|
if (isFooterHrefKey(hrefKey)) {
|
|
13066
14525
|
return document.querySelector(
|
|
13067
14526
|
`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
@@ -13076,7 +14535,7 @@ function OhhwellsBridge() {
|
|
|
13076
14535
|
`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
13077
14536
|
);
|
|
13078
14537
|
}, []);
|
|
13079
|
-
const resyncSelectedNavigationItem = (0,
|
|
14538
|
+
const resyncSelectedNavigationItem = (0, import_react16.useCallback)(() => {
|
|
13080
14539
|
const hrefKey = selectedHrefKeyRef.current;
|
|
13081
14540
|
if (hrefKey) {
|
|
13082
14541
|
const link = resolveHrefKeyElement(hrefKey);
|
|
@@ -13114,12 +14573,14 @@ function OhhwellsBridge() {
|
|
|
13114
14573
|
);
|
|
13115
14574
|
}
|
|
13116
14575
|
}, [resolveHrefKeyElement]);
|
|
13117
|
-
const reselectNavigationItem = (0,
|
|
14576
|
+
const reselectNavigationItem = (0, import_react16.useCallback)((navAnchor) => {
|
|
13118
14577
|
selectedElRef.current = navAnchor;
|
|
13119
14578
|
selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
|
|
13120
14579
|
selectedFooterColAttrRef.current = null;
|
|
13121
14580
|
markSelected(navAnchor);
|
|
13122
14581
|
setSelectedIsCta(isCtaButton(navAnchor));
|
|
14582
|
+
setSelectedIsSocial(Boolean(getSocialItem(navAnchor)));
|
|
14583
|
+
setSelectedIsSocialsRow(false);
|
|
13123
14584
|
const isDropdownTrigger = !isNestedNavChild(navAnchor) && (navItemHasDropdownChildren(navAnchor) || navItemOwnsDropdownPanel(navAnchor));
|
|
13124
14585
|
if (isNestedNavChild(navAnchor)) {
|
|
13125
14586
|
setNavGroupForceOpen(navAnchor, true);
|
|
@@ -13143,7 +14604,7 @@ function OhhwellsBridge() {
|
|
|
13143
14604
|
setToolbarShowEditLink(false);
|
|
13144
14605
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
13145
14606
|
}, [markSelected]);
|
|
13146
|
-
const commitNavigationTextEdit = (0,
|
|
14607
|
+
const commitNavigationTextEdit = (0, import_react16.useCallback)((navAnchor) => {
|
|
13147
14608
|
const el = activeElRef.current;
|
|
13148
14609
|
if (!el) return;
|
|
13149
14610
|
const key = el.dataset.ohwKey;
|
|
@@ -13170,7 +14631,7 @@ function OhhwellsBridge() {
|
|
|
13170
14631
|
postToParent2({ type: "ow:exit-edit" });
|
|
13171
14632
|
reselectNavigationItem(navAnchor);
|
|
13172
14633
|
}, [postToParent2, reselectNavigationItem]);
|
|
13173
|
-
const handleAddTopLevelNavItem = (0,
|
|
14634
|
+
const handleAddTopLevelNavItem = (0, import_react16.useCallback)(() => {
|
|
13174
14635
|
const items = listNavbarRootItems();
|
|
13175
14636
|
addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
|
|
13176
14637
|
deselectRef.current();
|
|
@@ -13182,7 +14643,7 @@ function OhhwellsBridge() {
|
|
|
13182
14643
|
intent: "add-nav"
|
|
13183
14644
|
});
|
|
13184
14645
|
}, []);
|
|
13185
|
-
const maybeWarnNavLinkDropdownConflict = (0,
|
|
14646
|
+
const maybeWarnNavLinkDropdownConflict = (0, import_react16.useCallback)(
|
|
13186
14647
|
(anchor) => {
|
|
13187
14648
|
if (!isNavbarHrefKey(anchor.getAttribute("data-ohw-href-key"))) return;
|
|
13188
14649
|
if (!navDropdownsOpenOnClick()) return;
|
|
@@ -13195,7 +14656,7 @@ function OhhwellsBridge() {
|
|
|
13195
14656
|
},
|
|
13196
14657
|
[postToParent2]
|
|
13197
14658
|
);
|
|
13198
|
-
const handleNavDropdownOpenChange = (0,
|
|
14659
|
+
const handleNavDropdownOpenChange = (0, import_react16.useCallback)((open) => {
|
|
13199
14660
|
const selected = selectedElRef.current;
|
|
13200
14661
|
if (!selected || !isNavigationItem2(selected)) return;
|
|
13201
14662
|
setNavGroupForceOpen(selected, open);
|
|
@@ -13207,7 +14668,7 @@ function OhhwellsBridge() {
|
|
|
13207
14668
|
}
|
|
13208
14669
|
});
|
|
13209
14670
|
}, []);
|
|
13210
|
-
const handleFooterHeadingVisibleChange = (0,
|
|
14671
|
+
const handleFooterHeadingVisibleChange = (0, import_react16.useCallback)(
|
|
13211
14672
|
(visible) => {
|
|
13212
14673
|
const selected = selectedElRef.current;
|
|
13213
14674
|
if (!selected || !isFooterFrameSelectionRef.current) return;
|
|
@@ -13231,7 +14692,7 @@ function OhhwellsBridge() {
|
|
|
13231
14692
|
},
|
|
13232
14693
|
[postToParent2]
|
|
13233
14694
|
);
|
|
13234
|
-
const enterEditOnNewItem = (0,
|
|
14695
|
+
const enterEditOnNewItem = (0, import_react16.useCallback)((anchor) => {
|
|
13235
14696
|
const label = anchor.querySelector('[data-ohw-editable="text"]');
|
|
13236
14697
|
if (!label) {
|
|
13237
14698
|
selectRef.current(anchor);
|
|
@@ -13240,14 +14701,42 @@ function OhhwellsBridge() {
|
|
|
13240
14701
|
setNavGroupForceOpen(anchor, true);
|
|
13241
14702
|
activateRef.current(label);
|
|
13242
14703
|
}, []);
|
|
13243
|
-
const handleAddChildItem = (0,
|
|
14704
|
+
const handleAddChildItem = (0, import_react16.useCallback)(() => {
|
|
13244
14705
|
const selected = selectedElRef.current;
|
|
13245
14706
|
if (!selected) return;
|
|
14707
|
+
const socialsRow = isSocialsRow(selected) ? selected : findSocialsRow(selected);
|
|
14708
|
+
if (socialsRow) {
|
|
14709
|
+
const after = getSocialItem(selected);
|
|
14710
|
+
const result2 = insertSocialItem(socialsRow, after, editContentRef.current);
|
|
14711
|
+
if (!result2) return;
|
|
14712
|
+
const orderJson = JSON.stringify(result2.order);
|
|
14713
|
+
applySocialsDisplayToRow(socialsRow, socialsDisplayFor(socialsRow, editContentRef.current));
|
|
14714
|
+
editContentRef.current = { ...editContentRef.current, [SOCIALS_ORDER_KEY]: orderJson };
|
|
14715
|
+
postToParent2({ type: "ow:change", nodes: [{ key: SOCIALS_ORDER_KEY, text: orderJson }] });
|
|
14716
|
+
postToParentRef.current({
|
|
14717
|
+
type: "ow:social-pick",
|
|
14718
|
+
hrefKey: result2.hrefKey,
|
|
14719
|
+
iconKey: result2.iconKey,
|
|
14720
|
+
url: "",
|
|
14721
|
+
iconStyle: detectIconStyle(result2.item),
|
|
14722
|
+
platformId: "",
|
|
14723
|
+
// Lets the editor undo the insert if the dialog is dismissed: an item that was never given
|
|
14724
|
+
// an address should not survive a Cancel.
|
|
14725
|
+
isNew: true
|
|
14726
|
+
});
|
|
14727
|
+
return;
|
|
14728
|
+
}
|
|
13246
14729
|
if (toolbarVariantRef.current === "select-frame" && isFooterFrameSelection) {
|
|
13247
|
-
|
|
13248
|
-
}
|
|
13249
|
-
const column = (selected.hasAttribute("data-ohw-footer-col") ? selected : null) ?? selected.closest("[data-ohw-footer-col]") ?? (listFooterColumns().includes(selected) ? selected : null);
|
|
14730
|
+
const column = resolveFooterColumnForAdd(selected);
|
|
13250
14731
|
if (!column) return;
|
|
14732
|
+
if (!canAddFooterItem(column)) {
|
|
14733
|
+
postToParent2({
|
|
14734
|
+
type: "ow:toast",
|
|
14735
|
+
title: `Maximum ${MAX_FOOTER_ITEMS_PER_COLUMN} items per column`,
|
|
14736
|
+
toastType: "error"
|
|
14737
|
+
});
|
|
14738
|
+
return;
|
|
14739
|
+
}
|
|
13251
14740
|
const result2 = insertFooterItem(column, "/", "New link", null);
|
|
13252
14741
|
applyLinkByKey(result2.hrefKey, result2.href);
|
|
13253
14742
|
document.querySelectorAll(`[data-ohw-key="${result2.labelKey}"]`).forEach((el) => {
|
|
@@ -13316,7 +14805,7 @@ function OhhwellsBridge() {
|
|
|
13316
14805
|
enterEditOnNewItem(result.anchor);
|
|
13317
14806
|
});
|
|
13318
14807
|
}, [enterEditOnNewItem, isFooterFrameSelection, maybeWarnNavLinkDropdownConflict, postToParent2]);
|
|
13319
|
-
const handleAddFooterColumn = (0,
|
|
14808
|
+
const handleAddFooterColumn = (0, import_react16.useCallback)(() => {
|
|
13320
14809
|
if (!canAddFooterColumn()) {
|
|
13321
14810
|
postToParent2({
|
|
13322
14811
|
type: "ow:toast",
|
|
@@ -13337,7 +14826,7 @@ function OhhwellsBridge() {
|
|
|
13337
14826
|
selectRef.current(result.firstLink);
|
|
13338
14827
|
});
|
|
13339
14828
|
}, [postToParent2]);
|
|
13340
|
-
const clearFooterDragVisuals = (0,
|
|
14829
|
+
const clearFooterDragVisuals = (0, import_react16.useCallback)(() => {
|
|
13341
14830
|
footerDragRef.current = null;
|
|
13342
14831
|
setSiblingHintRects([]);
|
|
13343
14832
|
setFooterDropSlots([]);
|
|
@@ -13346,7 +14835,7 @@ function OhhwellsBridge() {
|
|
|
13346
14835
|
setIsItemDragging(false);
|
|
13347
14836
|
unlockFooterDragInteraction();
|
|
13348
14837
|
}, []);
|
|
13349
|
-
const refreshFooterDragVisuals = (0,
|
|
14838
|
+
const refreshFooterDragVisuals = (0, import_react16.useCallback)((session, activeSlot, clientX, clientY) => {
|
|
13350
14839
|
const dragged = session.draggedEl;
|
|
13351
14840
|
setDraggedItemRect(dragged.getBoundingClientRect());
|
|
13352
14841
|
if (typeof clientX === "number" && typeof clientY === "number") {
|
|
@@ -13355,6 +14844,13 @@ function OhhwellsBridge() {
|
|
|
13355
14844
|
}
|
|
13356
14845
|
session.activeSlot = activeSlot;
|
|
13357
14846
|
setSiblingHintRects([]);
|
|
14847
|
+
if (session.kind === "social") {
|
|
14848
|
+
const slots2 = session.hrefKey ? buildSocialDropSlotsForKey(session.hrefKey) : [];
|
|
14849
|
+
setFooterDropSlots(slots2);
|
|
14850
|
+
const activeIdx2 = activeSlot ? slots2.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
14851
|
+
setActiveFooterDropIndex(activeIdx2 >= 0 ? activeIdx2 : null);
|
|
14852
|
+
return;
|
|
14853
|
+
}
|
|
13358
14854
|
if (session.kind === "link") {
|
|
13359
14855
|
const columns = listFooterColumns();
|
|
13360
14856
|
const slots2 = [];
|
|
@@ -13371,13 +14867,13 @@ function OhhwellsBridge() {
|
|
|
13371
14867
|
const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
13372
14868
|
setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
13373
14869
|
}, []);
|
|
13374
|
-
const refreshFooterDragVisualsRef = (0,
|
|
14870
|
+
const refreshFooterDragVisualsRef = (0, import_react16.useRef)(refreshFooterDragVisuals);
|
|
13375
14871
|
refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
|
|
13376
|
-
const commitFooterDragRef = (0,
|
|
14872
|
+
const commitFooterDragRef = (0, import_react16.useRef)(() => {
|
|
13377
14873
|
});
|
|
13378
|
-
const beginFooterDragRef = (0,
|
|
14874
|
+
const beginFooterDragRef = (0, import_react16.useRef)(() => {
|
|
13379
14875
|
});
|
|
13380
|
-
const beginFooterDrag = (0,
|
|
14876
|
+
const beginFooterDrag = (0, import_react16.useCallback)(
|
|
13381
14877
|
(session) => {
|
|
13382
14878
|
const rect = session.draggedEl.getBoundingClientRect();
|
|
13383
14879
|
session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
|
|
@@ -13391,13 +14887,13 @@ function OhhwellsBridge() {
|
|
|
13391
14887
|
if (session.wasSelected && selectedElRef.current === session.draggedEl) {
|
|
13392
14888
|
setToolbarRect(rect);
|
|
13393
14889
|
}
|
|
13394
|
-
const initialSlot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
14890
|
+
const initialSlot = session.kind === "social" && session.hrefKey ? hitTestSocialDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
13395
14891
|
refreshFooterDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
|
|
13396
14892
|
},
|
|
13397
14893
|
[refreshFooterDragVisuals]
|
|
13398
14894
|
);
|
|
13399
14895
|
beginFooterDragRef.current = beginFooterDrag;
|
|
13400
|
-
const commitFooterDrag = (0,
|
|
14896
|
+
const commitFooterDrag = (0, import_react16.useCallback)(
|
|
13401
14897
|
(clientX, clientY) => {
|
|
13402
14898
|
const session = footerDragRef.current;
|
|
13403
14899
|
if (!session) {
|
|
@@ -13407,8 +14903,11 @@ function OhhwellsBridge() {
|
|
|
13407
14903
|
const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
|
|
13408
14904
|
const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
|
|
13409
14905
|
let nextOrder = null;
|
|
13410
|
-
|
|
13411
|
-
|
|
14906
|
+
let nextSocialsOrder = null;
|
|
14907
|
+
const slot = session.activeSlot ?? (session.kind === "social" && session.hrefKey ? hitTestSocialDropSlot(x, y, session.hrefKey) : session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(x, y, session.hrefKey) : session.kind === "column" ? hitTestColumnDropSlot(x, y) : null);
|
|
14908
|
+
if (session.kind === "social" && session.hrefKey && slot) {
|
|
14909
|
+
nextSocialsOrder = planSocialMove(session.hrefKey, slot.insertIndex);
|
|
14910
|
+
} else if (session.kind === "link" && session.hrefKey && slot) {
|
|
13412
14911
|
nextOrder = planFooterLinkMove(session.hrefKey, slot.columnIndex, slot.insertIndex);
|
|
13413
14912
|
} else if (session.kind === "column" && slot) {
|
|
13414
14913
|
nextOrder = planFooterColumnMove(session.sourceColumnIndex, slot.insertIndex);
|
|
@@ -13466,6 +14965,27 @@ function OhhwellsBridge() {
|
|
|
13466
14965
|
}
|
|
13467
14966
|
deselectRef.current();
|
|
13468
14967
|
};
|
|
14968
|
+
if (nextSocialsOrder) {
|
|
14969
|
+
const orderJson = JSON.stringify(nextSocialsOrder);
|
|
14970
|
+
editContentRef.current = { ...editContentRef.current, [SOCIALS_ORDER_KEY]: orderJson };
|
|
14971
|
+
applySocialsOrder(nextSocialsOrder);
|
|
14972
|
+
postToParentRef.current({
|
|
14973
|
+
type: "ow:change",
|
|
14974
|
+
nodes: [{ key: SOCIALS_ORDER_KEY, text: orderJson }]
|
|
14975
|
+
});
|
|
14976
|
+
applySelectionAfterDrop();
|
|
14977
|
+
clearFooterDragVisuals();
|
|
14978
|
+
const reapply = nextSocialsOrder;
|
|
14979
|
+
requestAnimationFrame(() => {
|
|
14980
|
+
if (editContentRef.current[SOCIALS_ORDER_KEY] === orderJson) applySocialsOrder(reapply);
|
|
14981
|
+
applySelectionAfterDrop();
|
|
14982
|
+
requestAnimationFrame(() => {
|
|
14983
|
+
if (editContentRef.current[SOCIALS_ORDER_KEY] === orderJson) applySocialsOrder(reapply);
|
|
14984
|
+
resyncSelectedNavigationItem();
|
|
14985
|
+
});
|
|
14986
|
+
});
|
|
14987
|
+
return;
|
|
14988
|
+
}
|
|
13469
14989
|
if (nextOrder) {
|
|
13470
14990
|
const orderJson = JSON.stringify(nextOrder);
|
|
13471
14991
|
editContentRef.current = {
|
|
@@ -13501,10 +15021,25 @@ function OhhwellsBridge() {
|
|
|
13501
15021
|
[clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
|
|
13502
15022
|
);
|
|
13503
15023
|
commitFooterDragRef.current = commitFooterDrag;
|
|
13504
|
-
const startFooterLinkDrag = (0,
|
|
15024
|
+
const startFooterLinkDrag = (0, import_react16.useCallback)(
|
|
13505
15025
|
(anchor, clientX, clientY, wasSelected) => {
|
|
13506
15026
|
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
13507
|
-
if (!hrefKey
|
|
15027
|
+
if (!hrefKey) return false;
|
|
15028
|
+
if (getSocialItem(anchor)) {
|
|
15029
|
+
beginFooterDrag({
|
|
15030
|
+
kind: "social",
|
|
15031
|
+
hrefKey,
|
|
15032
|
+
columnEl: null,
|
|
15033
|
+
sourceColumnIndex: 0,
|
|
15034
|
+
wasSelected,
|
|
15035
|
+
draggedEl: anchor,
|
|
15036
|
+
lastClientX: clientX,
|
|
15037
|
+
lastClientY: clientY,
|
|
15038
|
+
activeSlot: null
|
|
15039
|
+
});
|
|
15040
|
+
return true;
|
|
15041
|
+
}
|
|
15042
|
+
if (!isFooterHrefKey(hrefKey)) return false;
|
|
13508
15043
|
const column = findFooterColumnForLink(anchor);
|
|
13509
15044
|
const columns = listFooterColumns();
|
|
13510
15045
|
beginFooterDrag({
|
|
@@ -13522,7 +15057,7 @@ function OhhwellsBridge() {
|
|
|
13522
15057
|
},
|
|
13523
15058
|
[beginFooterDrag]
|
|
13524
15059
|
);
|
|
13525
|
-
const startFooterColumnDrag = (0,
|
|
15060
|
+
const startFooterColumnDrag = (0, import_react16.useCallback)(
|
|
13526
15061
|
(columnEl, clientX, clientY, wasSelected) => {
|
|
13527
15062
|
const columns = listFooterColumns();
|
|
13528
15063
|
const idx = columns.indexOf(columnEl);
|
|
@@ -13542,7 +15077,7 @@ function OhhwellsBridge() {
|
|
|
13542
15077
|
},
|
|
13543
15078
|
[beginFooterDrag]
|
|
13544
15079
|
);
|
|
13545
|
-
const handleItemDragStart = (0,
|
|
15080
|
+
const handleItemDragStart = (0, import_react16.useCallback)(
|
|
13546
15081
|
(e) => {
|
|
13547
15082
|
const selected = selectedElRef.current;
|
|
13548
15083
|
if (!selected) {
|
|
@@ -13562,7 +15097,7 @@ function OhhwellsBridge() {
|
|
|
13562
15097
|
},
|
|
13563
15098
|
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
|
|
13564
15099
|
);
|
|
13565
|
-
const handleItemDragEnd = (0,
|
|
15100
|
+
const handleItemDragEnd = (0, import_react16.useCallback)(
|
|
13566
15101
|
(e) => {
|
|
13567
15102
|
if (footerDragRef.current) {
|
|
13568
15103
|
const x = e?.clientX;
|
|
@@ -13588,7 +15123,7 @@ function OhhwellsBridge() {
|
|
|
13588
15123
|
},
|
|
13589
15124
|
[commitFooterDrag, commitNavDrag, navDragRef]
|
|
13590
15125
|
);
|
|
13591
|
-
const handleItemChromePointerDown = (0,
|
|
15126
|
+
const handleItemChromePointerDown = (0, import_react16.useCallback)((e) => {
|
|
13592
15127
|
if (e.button !== 0) return;
|
|
13593
15128
|
const selected = selectedElRef.current;
|
|
13594
15129
|
if (!selected) return;
|
|
@@ -13619,7 +15154,7 @@ function OhhwellsBridge() {
|
|
|
13619
15154
|
}
|
|
13620
15155
|
if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
|
|
13621
15156
|
}, [armNavPressFromChrome]);
|
|
13622
|
-
const handleItemChromeClick = (0,
|
|
15157
|
+
const handleItemChromeClick = (0, import_react16.useCallback)((clientX, clientY) => {
|
|
13623
15158
|
if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
|
|
13624
15159
|
suppressNextClickRef.current = false;
|
|
13625
15160
|
return;
|
|
@@ -13632,7 +15167,7 @@ function OhhwellsBridge() {
|
|
|
13632
15167
|
}, []);
|
|
13633
15168
|
reselectNavigationItemRef.current = reselectNavigationItem;
|
|
13634
15169
|
commitNavigationTextEditRef.current = commitNavigationTextEdit;
|
|
13635
|
-
const select = (0,
|
|
15170
|
+
const select = (0, import_react16.useCallback)((anchor) => {
|
|
13636
15171
|
if (!isNavigationItem2(anchor)) return;
|
|
13637
15172
|
if (activeElRef.current) deactivate();
|
|
13638
15173
|
aiSectionApiRef.current?.selectFromElement(anchor);
|
|
@@ -13641,6 +15176,8 @@ function OhhwellsBridge() {
|
|
|
13641
15176
|
selectedFooterColAttrRef.current = null;
|
|
13642
15177
|
markSelected(anchor);
|
|
13643
15178
|
setSelectedIsCta(isCtaButton(anchor));
|
|
15179
|
+
setSelectedIsSocial(Boolean(getSocialItem(anchor)));
|
|
15180
|
+
setSelectedIsSocialsRow(false);
|
|
13644
15181
|
clearHrefKeyHover(anchor);
|
|
13645
15182
|
const isDropdownTrigger = !isNestedNavChild(anchor) && (navItemHasDropdownChildren(anchor) || navItemOwnsDropdownPanel(anchor));
|
|
13646
15183
|
if (isNestedNavChild(anchor)) {
|
|
@@ -13670,8 +15207,10 @@ function OhhwellsBridge() {
|
|
|
13670
15207
|
setToolbarRect(anchor.getBoundingClientRect());
|
|
13671
15208
|
setToolbarShowEditLink(false);
|
|
13672
15209
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
15210
|
+
setFloatingPanel(null);
|
|
15211
|
+
setLogoSizeDraft(null);
|
|
13673
15212
|
}, [deactivate, markSelected]);
|
|
13674
|
-
const selectFrame = (0,
|
|
15213
|
+
const selectFrame = (0, import_react16.useCallback)((el) => {
|
|
13675
15214
|
if (!isNavigationContainer(el)) return;
|
|
13676
15215
|
if (activeElRef.current) deactivate();
|
|
13677
15216
|
aiSectionApiRef.current?.selectFromElement(el);
|
|
@@ -13681,6 +15220,8 @@ function OhhwellsBridge() {
|
|
|
13681
15220
|
selectedFooterColAttrRef.current = isFooterColumn ? el.getAttribute("data-ohw-footer-col") ?? String(listFooterColumns().indexOf(el)) : null;
|
|
13682
15221
|
markSelected(el);
|
|
13683
15222
|
setSelectedIsCta(false);
|
|
15223
|
+
setSelectedIsSocial(false);
|
|
15224
|
+
setSelectedIsSocialsRow(isSocialsRow(el));
|
|
13684
15225
|
clearHrefKeyHover(el);
|
|
13685
15226
|
setNavGroupForceOpen(null, false);
|
|
13686
15227
|
hoveredNavContainerRef.current = null;
|
|
@@ -13709,22 +15250,153 @@ function OhhwellsBridge() {
|
|
|
13709
15250
|
nodes: [{ key: ensured.headingKey, text: ensured.text }]
|
|
13710
15251
|
});
|
|
13711
15252
|
}
|
|
13712
|
-
setFooterHeadingVisible(isFooterColumnHeadingVisible(el));
|
|
13713
|
-
} else {
|
|
13714
|
-
setFooterHeadingVisible(null);
|
|
13715
|
-
}
|
|
13716
|
-
setToolbarVariant("select-frame");
|
|
13717
|
-
setToolbarRect(el.getBoundingClientRect());
|
|
13718
|
-
setToolbarShowEditLink(false);
|
|
13719
|
-
setActiveCommands(/* @__PURE__ */ new Set());
|
|
13720
|
-
|
|
13721
|
-
|
|
15253
|
+
setFooterHeadingVisible(isFooterColumnHeadingVisible(el));
|
|
15254
|
+
} else {
|
|
15255
|
+
setFooterHeadingVisible(null);
|
|
15256
|
+
}
|
|
15257
|
+
setToolbarVariant("select-frame");
|
|
15258
|
+
setToolbarRect(el.getBoundingClientRect());
|
|
15259
|
+
setToolbarShowEditLink(false);
|
|
15260
|
+
setActiveCommands(/* @__PURE__ */ new Set());
|
|
15261
|
+
setFloatingPanel(null);
|
|
15262
|
+
setLogoSizeDraft(null);
|
|
15263
|
+
}, [deactivate, markSelected, postToParent2]);
|
|
15264
|
+
const selectLogo = (0, import_react16.useCallback)(
|
|
15265
|
+
(logoEl) => {
|
|
15266
|
+
if (activeElRef.current) deactivate();
|
|
15267
|
+
selectedElRef.current = logoEl;
|
|
15268
|
+
selectedHrefKeyRef.current = null;
|
|
15269
|
+
selectedFooterColAttrRef.current = null;
|
|
15270
|
+
markSelected(logoEl);
|
|
15271
|
+
setSelectedIsCta(false);
|
|
15272
|
+
setSelectedIsSocial(false);
|
|
15273
|
+
setSelectedIsSocialsRow(false);
|
|
15274
|
+
setSelectedIsSocialsRow(false);
|
|
15275
|
+
clearHrefKeyHover(logoEl);
|
|
15276
|
+
hoveredNavContainerRef.current = null;
|
|
15277
|
+
setHoveredNavContainerRect(null);
|
|
15278
|
+
setHoveredItemRect(null);
|
|
15279
|
+
hoveredItemElRef.current = null;
|
|
15280
|
+
siblingHintElRef.current = null;
|
|
15281
|
+
setSiblingHintRect(null);
|
|
15282
|
+
setSiblingHintRects([]);
|
|
15283
|
+
setIsItemDragging(false);
|
|
15284
|
+
setReorderHrefKey(null);
|
|
15285
|
+
setReorderDragDisabled(false);
|
|
15286
|
+
setIsFooterFrameSelection(false);
|
|
15287
|
+
setToolbarVariant("logo");
|
|
15288
|
+
setToolbarRect(getLogoInteractionRect(logoEl));
|
|
15289
|
+
setToolbarShowEditLink(false);
|
|
15290
|
+
setActiveCommands(/* @__PURE__ */ new Set());
|
|
15291
|
+
},
|
|
15292
|
+
[deactivate, markSelected]
|
|
15293
|
+
);
|
|
15294
|
+
const openLogoSizePanel = (0, import_react16.useCallback)((logoEl) => {
|
|
15295
|
+
const placement = getLogoPlacement(logoEl);
|
|
15296
|
+
const draft = readLogoSizeState(editContentRef.current, placement);
|
|
15297
|
+
setLogoSizeDraft(draft);
|
|
15298
|
+
setParentScrollSnap(parentScrollRef.current);
|
|
15299
|
+
setFloatingPanel({
|
|
15300
|
+
key: `logo-size:${placement}`,
|
|
15301
|
+
title: "Logo",
|
|
15302
|
+
context: placement === "navbar" ? "Navbar" : "Footer",
|
|
15303
|
+
kind: "logo-size",
|
|
15304
|
+
placement
|
|
15305
|
+
});
|
|
15306
|
+
}, []);
|
|
15307
|
+
const openSocialsDisplayPanel = (0, import_react16.useCallback)((row) => {
|
|
15308
|
+
setParentScrollSnap(parentScrollRef.current);
|
|
15309
|
+
setFloatingPanel({
|
|
15310
|
+
key: "socials-display",
|
|
15311
|
+
title: "Style",
|
|
15312
|
+
context: "Socials \xB7 Footer",
|
|
15313
|
+
kind: "socials-display",
|
|
15314
|
+
row
|
|
15315
|
+
});
|
|
15316
|
+
}, []);
|
|
15317
|
+
const changeSocialsDisplay = (0, import_react16.useCallback)(
|
|
15318
|
+
(row, next) => {
|
|
15319
|
+
if (next.icon) {
|
|
15320
|
+
const missing = socialsMissingIcons(row);
|
|
15321
|
+
listSocialItems(row).forEach((item) => ensureIconSlot(item));
|
|
15322
|
+
if (missing.length) {
|
|
15323
|
+
postToParentRef.current({ type: "ow:social-icons-needed", items: missing });
|
|
15324
|
+
}
|
|
15325
|
+
}
|
|
15326
|
+
applySocialsDisplayToRow(row, next);
|
|
15327
|
+
requestAnimationFrame(() => {
|
|
15328
|
+
if (selectedElRef.current === row && row.isConnected) setToolbarRect(row.getBoundingClientRect());
|
|
15329
|
+
});
|
|
15330
|
+
const displayJson = JSON.stringify(socialsDisplayWith(row, next, editContentRef.current));
|
|
15331
|
+
editContentRef.current = { ...editContentRef.current, [SOCIALS_DISPLAY_KEY]: displayJson };
|
|
15332
|
+
postToParentRef.current({
|
|
15333
|
+
type: "ow:change",
|
|
15334
|
+
nodes: [{ key: SOCIALS_DISPLAY_KEY, text: displayJson }],
|
|
15335
|
+
flush: true
|
|
15336
|
+
});
|
|
15337
|
+
},
|
|
15338
|
+
[]
|
|
15339
|
+
);
|
|
15340
|
+
const closeFloatingPanelOnly = (0, import_react16.useCallback)(() => {
|
|
15341
|
+
setFloatingPanel(null);
|
|
15342
|
+
setLogoSizeDraft(null);
|
|
15343
|
+
}, []);
|
|
15344
|
+
const closeFloatingPanelAndDeselect = (0, import_react16.useCallback)(() => {
|
|
15345
|
+
setFloatingPanel(null);
|
|
15346
|
+
setLogoSizeDraft(null);
|
|
15347
|
+
deselectRef.current();
|
|
15348
|
+
}, []);
|
|
15349
|
+
const persistLogoSizeDraft = (0, import_react16.useCallback)(
|
|
15350
|
+
(placement, draft) => {
|
|
15351
|
+
const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
|
|
15352
|
+
const mobileKey = LOGO_SIZE_MOBILE_KEYS[placement];
|
|
15353
|
+
const nodes = [
|
|
15354
|
+
{ key: desktopKey, text: String(draft.desktopPx) }
|
|
15355
|
+
];
|
|
15356
|
+
if (draft.mobileFollowing) {
|
|
15357
|
+
nodes.push({ key: mobileKey, text: "" });
|
|
15358
|
+
} else {
|
|
15359
|
+
nodes.push({ key: mobileKey, text: String(draft.mobilePx) });
|
|
15360
|
+
}
|
|
15361
|
+
editContentRef.current = {
|
|
15362
|
+
...editContentRef.current,
|
|
15363
|
+
[desktopKey]: String(draft.desktopPx),
|
|
15364
|
+
[mobileKey]: draft.mobileFollowing ? "" : String(draft.mobilePx)
|
|
15365
|
+
};
|
|
15366
|
+
applyLogoSizeToPlacement(
|
|
15367
|
+
placement,
|
|
15368
|
+
draft.desktopPx,
|
|
15369
|
+
draft.mobileFollowing ? draft.desktopPx : draft.mobilePx,
|
|
15370
|
+
draft.mobileFollowing
|
|
15371
|
+
);
|
|
15372
|
+
postToParent2({ type: "ow:change", nodes });
|
|
15373
|
+
requestAnimationFrame(() => {
|
|
15374
|
+
const selected = selectedElRef.current;
|
|
15375
|
+
if (!selected || toolbarVariantRef.current !== "logo") return;
|
|
15376
|
+
const rect = getLogoInteractionRect(selected);
|
|
15377
|
+
setToolbarRect(rect);
|
|
15378
|
+
if (glowElRef.current) {
|
|
15379
|
+
const GAP = SELECTION_CHROME_GAP2;
|
|
15380
|
+
glowElRef.current.style.top = `${rect.top - GAP}px`;
|
|
15381
|
+
glowElRef.current.style.left = `${rect.left - GAP}px`;
|
|
15382
|
+
glowElRef.current.style.width = `${rect.width + GAP * 2}px`;
|
|
15383
|
+
glowElRef.current.style.height = `${rect.height + GAP * 2}px`;
|
|
15384
|
+
}
|
|
15385
|
+
});
|
|
15386
|
+
},
|
|
15387
|
+
[postToParent2]
|
|
15388
|
+
);
|
|
15389
|
+
const activate = (0, import_react16.useCallback)((el, options) => {
|
|
13722
15390
|
if (activeElRef.current === el) return;
|
|
15391
|
+
if (isIconEditable(el)) return;
|
|
15392
|
+
if (el.hasAttribute("data-ohw-social-label")) return;
|
|
13723
15393
|
clearSelectedAttr();
|
|
13724
15394
|
selectedElRef.current = null;
|
|
13725
15395
|
selectedHrefKeyRef.current = null;
|
|
13726
15396
|
selectedFooterColAttrRef.current = null;
|
|
13727
15397
|
setSelectedIsCta(false);
|
|
15398
|
+
setSelectedIsSocial(false);
|
|
15399
|
+
setSelectedIsSocialsRow(false);
|
|
13728
15400
|
deactivate();
|
|
13729
15401
|
if (hoveredImageRef.current) {
|
|
13730
15402
|
hoveredImageRef.current = null;
|
|
@@ -13794,8 +15466,38 @@ function OhhwellsBridge() {
|
|
|
13794
15466
|
deactivateRef.current = deactivate;
|
|
13795
15467
|
selectRef.current = select;
|
|
13796
15468
|
selectFrameRef.current = selectFrame;
|
|
15469
|
+
selectLogoRef.current = selectLogo;
|
|
15470
|
+
openLogoSizePanelRef.current = openLogoSizePanel;
|
|
13797
15471
|
deselectRef.current = deselect;
|
|
13798
|
-
|
|
15472
|
+
closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
|
|
15473
|
+
const lastSiteWideScopeRef = (0, import_react16.useRef)(null);
|
|
15474
|
+
(0, import_react16.useEffect)(() => {
|
|
15475
|
+
if (!isEditMode) {
|
|
15476
|
+
if (lastSiteWideScopeRef.current !== false) {
|
|
15477
|
+
lastSiteWideScopeRef.current = false;
|
|
15478
|
+
postToParent2({ type: "ow:site-wide-scope", active: false });
|
|
15479
|
+
}
|
|
15480
|
+
return;
|
|
15481
|
+
}
|
|
15482
|
+
const active = isSiteWideScopeActive({
|
|
15483
|
+
selected: selectedElRef.current,
|
|
15484
|
+
hoveredItem: hoveredItemElRef.current,
|
|
15485
|
+
hoveredNavContainer: hoveredNavContainerRef.current,
|
|
15486
|
+
active: activeElRef.current
|
|
15487
|
+
});
|
|
15488
|
+
if (lastSiteWideScopeRef.current === active) return;
|
|
15489
|
+
lastSiteWideScopeRef.current = active;
|
|
15490
|
+
postToParent2({ type: "ow:site-wide-scope", active });
|
|
15491
|
+
}, [
|
|
15492
|
+
isEditMode,
|
|
15493
|
+
hoveredItemRect,
|
|
15494
|
+
hoveredNavContainerRect,
|
|
15495
|
+
toolbarVariant,
|
|
15496
|
+
toolbarRect,
|
|
15497
|
+
isFooterFrameSelection,
|
|
15498
|
+
postToParent2
|
|
15499
|
+
]);
|
|
15500
|
+
(0, import_react16.useLayoutEffect)(() => {
|
|
13799
15501
|
if (!subdomain || isEditMode) {
|
|
13800
15502
|
setFetchState("done");
|
|
13801
15503
|
return;
|
|
@@ -13806,9 +15508,18 @@ function OhhwellsBridge() {
|
|
|
13806
15508
|
aiSectionsRef.current = content[AI_SECTIONS_KEY];
|
|
13807
15509
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
13808
15510
|
}
|
|
15511
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
15512
|
+
brandKitRef.current = content[BRAND_KIT_KEY];
|
|
15513
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
15514
|
+
}
|
|
15515
|
+
applyBrandChrome(content);
|
|
13809
15516
|
for (const [key, val] of Object.entries(content)) {
|
|
13810
15517
|
if (key === "__ohw_sections") continue;
|
|
13811
15518
|
if (key === AI_SECTIONS_KEY) continue;
|
|
15519
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
15520
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
15521
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
15522
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
13812
15523
|
if (applyVideoSettingNode(key, val)) continue;
|
|
13813
15524
|
if (applyCarouselNode(key, val)) continue;
|
|
13814
15525
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -13835,14 +15546,20 @@ function OhhwellsBridge() {
|
|
|
13835
15546
|
}
|
|
13836
15547
|
} else if (el.dataset.ohwEditable === "link") {
|
|
13837
15548
|
applyLinkHref(el, val);
|
|
15549
|
+
} else if (el.dataset.ohwEditable === "icon") {
|
|
15550
|
+
applyIconMarkup(el, val);
|
|
13838
15551
|
} else if (el.innerHTML !== val) {
|
|
13839
15552
|
el.innerHTML = val;
|
|
13840
15553
|
}
|
|
13841
15554
|
});
|
|
13842
15555
|
applyLinkByKey(key, val);
|
|
13843
15556
|
}
|
|
15557
|
+
applyLogoFromContent(content);
|
|
15558
|
+
applyLogoSizes(content);
|
|
13844
15559
|
reconcileNavbarItemsFromContent(content);
|
|
13845
15560
|
reconcileFooterOrderFromContent(content);
|
|
15561
|
+
reconcileSocialsFromContent(content);
|
|
15562
|
+
applySocialsDisplayFromContent(content);
|
|
13846
15563
|
enforceLinkHrefs();
|
|
13847
15564
|
initSectionsFromContent(content, true);
|
|
13848
15565
|
sectionsLoadedRef.current = true;
|
|
@@ -13858,7 +15575,9 @@ function OhhwellsBridge() {
|
|
|
13858
15575
|
let cancelled = false;
|
|
13859
15576
|
setFetchState("loading");
|
|
13860
15577
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
13861
|
-
|
|
15578
|
+
const initialPath = pathname;
|
|
15579
|
+
fetchedContentPaths.add(`${subdomain}::${initialPath}`);
|
|
15580
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
13862
15581
|
if (cancelled) return;
|
|
13863
15582
|
const content = data?.content ?? {};
|
|
13864
15583
|
contentCache.set(subdomain, content);
|
|
@@ -13871,7 +15590,7 @@ function OhhwellsBridge() {
|
|
|
13871
15590
|
cancelled = true;
|
|
13872
15591
|
};
|
|
13873
15592
|
}, [subdomain, isEditMode]);
|
|
13874
|
-
(0,
|
|
15593
|
+
(0, import_react16.useEffect)(() => {
|
|
13875
15594
|
if (!subdomain || isEditMode) return;
|
|
13876
15595
|
let debounceTimer = null;
|
|
13877
15596
|
let observer = null;
|
|
@@ -13881,8 +15600,16 @@ function OhhwellsBridge() {
|
|
|
13881
15600
|
retryMissingSchedulingMounts(getPageSchedulingEntries(content["__ohw_sections"]), false);
|
|
13882
15601
|
observer?.disconnect();
|
|
13883
15602
|
try {
|
|
15603
|
+
applyBrandChrome(content);
|
|
15604
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
15605
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
15606
|
+
}
|
|
13884
15607
|
for (const [key, val] of Object.entries(content)) {
|
|
13885
15608
|
if (key === "__ohw_sections") continue;
|
|
15609
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
15610
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
15611
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
15612
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
13886
15613
|
if (applyVideoSettingNode(key, val)) continue;
|
|
13887
15614
|
if (applyCarouselNode(key, val)) continue;
|
|
13888
15615
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -13903,8 +15630,11 @@ function OhhwellsBridge() {
|
|
|
13903
15630
|
});
|
|
13904
15631
|
applyLinkByKey(key, val);
|
|
13905
15632
|
}
|
|
15633
|
+
applyLogoFromContent(content);
|
|
13906
15634
|
reconcileNavbarItemsFromContent(content);
|
|
13907
15635
|
reconcileFooterOrderFromContent(content);
|
|
15636
|
+
reconcileSocialsFromContent(content);
|
|
15637
|
+
applySocialsDisplayFromContent(content);
|
|
13908
15638
|
} finally {
|
|
13909
15639
|
observer?.observe(document.body, { childList: true, subtree: true });
|
|
13910
15640
|
}
|
|
@@ -13915,6 +15645,17 @@ function OhhwellsBridge() {
|
|
|
13915
15645
|
debounceTimer = setTimeout(applyFromCache, 150);
|
|
13916
15646
|
};
|
|
13917
15647
|
applyFromCache();
|
|
15648
|
+
const pathCacheKey = `${subdomain}::${pathname}`;
|
|
15649
|
+
if (!fetchedContentPaths.has(pathCacheKey)) {
|
|
15650
|
+
fetchedContentPaths.add(pathCacheKey);
|
|
15651
|
+
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
15652
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
15653
|
+
if (!data?.content) return;
|
|
15654
|
+
contentCache.set(subdomain, data.content);
|
|
15655
|
+
applyFromCache();
|
|
15656
|
+
}).catch(() => {
|
|
15657
|
+
});
|
|
15658
|
+
}
|
|
13918
15659
|
observer = new MutationObserver(scheduleApply);
|
|
13919
15660
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
13920
15661
|
return () => {
|
|
@@ -13922,16 +15663,16 @@ function OhhwellsBridge() {
|
|
|
13922
15663
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
13923
15664
|
};
|
|
13924
15665
|
}, [subdomain, isEditMode, pathname]);
|
|
13925
|
-
(0,
|
|
15666
|
+
(0, import_react16.useLayoutEffect)(() => {
|
|
13926
15667
|
const el = document.getElementById("ohw-loader");
|
|
13927
15668
|
if (!el) return;
|
|
13928
15669
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
13929
15670
|
el.style.display = visible ? "flex" : "none";
|
|
13930
15671
|
}, [subdomain, fetchState]);
|
|
13931
|
-
(0,
|
|
15672
|
+
(0, import_react16.useEffect)(() => {
|
|
13932
15673
|
postToParent2({ type: "ow:navigation", path: pathname });
|
|
13933
15674
|
}, [pathname, postToParent2]);
|
|
13934
|
-
(0,
|
|
15675
|
+
(0, import_react16.useEffect)(() => {
|
|
13935
15676
|
if (!isEditMode) return;
|
|
13936
15677
|
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
13937
15678
|
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
@@ -13939,7 +15680,7 @@ function OhhwellsBridge() {
|
|
|
13939
15680
|
deselectRef.current();
|
|
13940
15681
|
deactivateRef.current();
|
|
13941
15682
|
}, [pathname, isEditMode]);
|
|
13942
|
-
(0,
|
|
15683
|
+
(0, import_react16.useEffect)(() => {
|
|
13943
15684
|
const contentForNav = () => {
|
|
13944
15685
|
if (isEditMode) return editContentRef.current;
|
|
13945
15686
|
if (!subdomain) return {};
|
|
@@ -13971,8 +15712,10 @@ function OhhwellsBridge() {
|
|
|
13971
15712
|
const content = contentForNav();
|
|
13972
15713
|
reconcileNavbarItemsFromContent(content);
|
|
13973
15714
|
reconcileFooterOrderFromContent(content);
|
|
15715
|
+
reconcileSocialsFromContent(content);
|
|
15716
|
+
applySocialsDisplayFromContent(content);
|
|
13974
15717
|
document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
|
|
13975
|
-
if (isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
15718
|
+
if (isFooterHrefKey(el.getAttribute("data-ohw-href-key")) || getSocialItem(el)) {
|
|
13976
15719
|
disableNativeHrefDrag(el);
|
|
13977
15720
|
}
|
|
13978
15721
|
});
|
|
@@ -14004,31 +15747,36 @@ function OhhwellsBridge() {
|
|
|
14004
15747
|
observer?.disconnect();
|
|
14005
15748
|
};
|
|
14006
15749
|
}, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
|
|
14007
|
-
(0,
|
|
15750
|
+
(0, import_react16.useEffect)(() => {
|
|
14008
15751
|
if (!isEditMode) return;
|
|
15752
|
+
let lastPosted = 0;
|
|
14009
15753
|
const measure = () => {
|
|
14010
15754
|
const h = document.body.scrollHeight;
|
|
14011
|
-
if (h > 50
|
|
15755
|
+
if (h > 50 && Math.abs(h - lastPosted) > 1) {
|
|
15756
|
+
lastPosted = h;
|
|
15757
|
+
postToParent2({ type: "ow:height", height: h });
|
|
15758
|
+
}
|
|
15759
|
+
};
|
|
15760
|
+
let raf = null;
|
|
15761
|
+
const schedule = () => {
|
|
15762
|
+
if (raf != null) return;
|
|
15763
|
+
raf = requestAnimationFrame(() => {
|
|
15764
|
+
raf = null;
|
|
15765
|
+
measure();
|
|
15766
|
+
});
|
|
14012
15767
|
};
|
|
14013
15768
|
const t1 = setTimeout(measure, 50);
|
|
14014
15769
|
const t2 = setTimeout(measure, 500);
|
|
14015
|
-
|
|
14016
|
-
|
|
14017
|
-
const handleResize = () => {
|
|
14018
|
-
if (window.innerWidth === lastWidth) return;
|
|
14019
|
-
lastWidth = window.innerWidth;
|
|
14020
|
-
if (resizeTimer) clearTimeout(resizeTimer);
|
|
14021
|
-
resizeTimer = setTimeout(measure, 150);
|
|
14022
|
-
};
|
|
14023
|
-
window.addEventListener("resize", handleResize);
|
|
15770
|
+
const ro = new ResizeObserver(schedule);
|
|
15771
|
+
ro.observe(document.body);
|
|
14024
15772
|
return () => {
|
|
14025
15773
|
clearTimeout(t1);
|
|
14026
15774
|
clearTimeout(t2);
|
|
14027
|
-
if (
|
|
14028
|
-
|
|
15775
|
+
if (raf != null) cancelAnimationFrame(raf);
|
|
15776
|
+
ro.disconnect();
|
|
14029
15777
|
};
|
|
14030
15778
|
}, [pathname, isEditMode, postToParent2]);
|
|
14031
|
-
(0,
|
|
15779
|
+
(0, import_react16.useEffect)(() => {
|
|
14032
15780
|
if (!subdomainFromQuery || isEditMode) return;
|
|
14033
15781
|
const handleClick = (e) => {
|
|
14034
15782
|
const anchor = e.target.closest("a");
|
|
@@ -14044,7 +15792,7 @@ function OhhwellsBridge() {
|
|
|
14044
15792
|
document.addEventListener("click", handleClick, true);
|
|
14045
15793
|
return () => document.removeEventListener("click", handleClick, true);
|
|
14046
15794
|
}, [subdomainFromQuery, isEditMode, router]);
|
|
14047
|
-
(0,
|
|
15795
|
+
(0, import_react16.useEffect)(() => {
|
|
14048
15796
|
if (!isEditMode) {
|
|
14049
15797
|
editStylesRef.current?.base.remove();
|
|
14050
15798
|
editStylesRef.current?.forceHover.remove();
|
|
@@ -14095,9 +15843,12 @@ function OhhwellsBridge() {
|
|
|
14095
15843
|
[data-ohw-editable="video"], [data-ohw-editable="video"] *,
|
|
14096
15844
|
[data-ohw-editable="bg-image"], [data-ohw-editable="bg-image"] * { cursor: pointer !important; }
|
|
14097
15845
|
[data-ohw-editable="link"], [data-ohw-editable="link"] * { cursor: pointer !important; }
|
|
15846
|
+
/* Text hover chrome is drawn by the overlay (see hoveredTextRect) \u2014 the CSS outline
|
|
15847
|
+
that used to draw it dashes denser than the overlay border, so identical specs
|
|
15848
|
+
still read as two different frames (OHH-695). The attribute stays: hover paths
|
|
15849
|
+
and suppression rules key off it. */
|
|
14098
15850
|
[data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key]) {
|
|
14099
|
-
outline:
|
|
14100
|
-
outline-offset: 4px;
|
|
15851
|
+
outline: none !important;
|
|
14101
15852
|
}
|
|
14102
15853
|
[data-ohw-href-key] [data-ohw-hovered],
|
|
14103
15854
|
[data-ohw-href-key][data-ohw-hovered],
|
|
@@ -14150,8 +15901,11 @@ function OhhwellsBridge() {
|
|
|
14150
15901
|
stateViews.textContent = `
|
|
14151
15902
|
[data-ohw-state-view]:not([data-ohw-state-view="default"]) { display: none; }
|
|
14152
15903
|
[data-ohw-state-view="default"] [data-ohw-editable] { pointer-events: auto !important; }
|
|
14153
|
-
[data-ohw-state-hovered] { outline:
|
|
15904
|
+
[data-ohw-state-hovered] { outline: ${HOVER_STROKE_WIDTH}px dashed ${CHROME_PRIMARY} !important; outline-offset: ${HOVER_CHROME_GAP}px; }
|
|
14154
15905
|
[data-ohw-state-hovered]:has([data-ohw-hovered]) { outline: none !important; }
|
|
15906
|
+
/* :has() only sees descendants \u2014 when the card itself is the hovered text, the overlay
|
|
15907
|
+
already frames it, and the card outline doubled it (OHH-695). */
|
|
15908
|
+
[data-ohw-state-hovered][data-ohw-hovered] { outline: none !important; }
|
|
14155
15909
|
`;
|
|
14156
15910
|
document.head.appendChild(base);
|
|
14157
15911
|
document.head.appendChild(forceHover);
|
|
@@ -14173,6 +15927,7 @@ function OhhwellsBridge() {
|
|
|
14173
15927
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
14174
15928
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
14175
15929
|
if (isInsideLinkEditor(target)) return;
|
|
15930
|
+
if (isInsideFloatingPanel(target)) return;
|
|
14176
15931
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
14177
15932
|
const beneath = document.elementsFromPoint(e.clientX, e.clientY).find(
|
|
14178
15933
|
(el) => el instanceof HTMLElement && !el.closest("[data-ohw-bridge-root]") && el.closest("[data-ohw-section]") != null
|
|
@@ -14236,6 +15991,21 @@ function OhhwellsBridge() {
|
|
|
14236
15991
|
return;
|
|
14237
15992
|
}
|
|
14238
15993
|
}
|
|
15994
|
+
const logoEl = getLogoElement(target);
|
|
15995
|
+
if (logoEl) {
|
|
15996
|
+
e.preventDefault();
|
|
15997
|
+
e.stopPropagation();
|
|
15998
|
+
if (!logoHasUploadedImage(logoEl)) {
|
|
15999
|
+
deselectRef.current();
|
|
16000
|
+
deactivateRef.current();
|
|
16001
|
+
const identity = readLogoIdentityFromDom();
|
|
16002
|
+
postToParentRef.current({ type: "ow:open-logo-settings", ...identity });
|
|
16003
|
+
return;
|
|
16004
|
+
}
|
|
16005
|
+
selectLogoRef.current(logoEl);
|
|
16006
|
+
openLogoSizePanelRef.current(logoEl);
|
|
16007
|
+
return;
|
|
16008
|
+
}
|
|
14239
16009
|
const editable = target.closest("[data-ohw-editable]");
|
|
14240
16010
|
if (editable) {
|
|
14241
16011
|
if (editable.dataset.ohwEditable === "link") {
|
|
@@ -14252,6 +16022,17 @@ function OhhwellsBridge() {
|
|
|
14252
16022
|
});
|
|
14253
16023
|
return;
|
|
14254
16024
|
}
|
|
16025
|
+
if (isIconEditable(editable) && !getSocialItem(editable)) {
|
|
16026
|
+
e.preventDefault();
|
|
16027
|
+
e.stopPropagation();
|
|
16028
|
+
aiSectionApiRef.current?.selectFromElement(editable);
|
|
16029
|
+
postToParentRef.current({
|
|
16030
|
+
type: "ow:icon-pick",
|
|
16031
|
+
key: editable.dataset.ohwKey ?? "",
|
|
16032
|
+
current: currentIconRef(editable)
|
|
16033
|
+
});
|
|
16034
|
+
return;
|
|
16035
|
+
}
|
|
14255
16036
|
if (isMediaEditable(editable)) {
|
|
14256
16037
|
e.preventDefault();
|
|
14257
16038
|
e.stopPropagation();
|
|
@@ -14266,6 +16047,7 @@ function OhhwellsBridge() {
|
|
|
14266
16047
|
e.stopPropagation();
|
|
14267
16048
|
if (selectedElRef.current === navAnchor) {
|
|
14268
16049
|
if (e.detail >= 2) return;
|
|
16050
|
+
if (requestSocialDialog(navAnchor, postToParentRef.current, editContentRef.current)) return;
|
|
14269
16051
|
activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
|
|
14270
16052
|
return;
|
|
14271
16053
|
}
|
|
@@ -14282,6 +16064,7 @@ function OhhwellsBridge() {
|
|
|
14282
16064
|
e.preventDefault();
|
|
14283
16065
|
e.stopPropagation();
|
|
14284
16066
|
if (selectedElRef.current === hrefAnchor) {
|
|
16067
|
+
if (requestSocialDialog(hrefAnchor, postToParentRef.current, editContentRef.current)) return;
|
|
14285
16068
|
const textEditable = hrefAnchor.querySelector('[data-ohw-editable="text"]') ?? hrefAnchor.querySelector("[data-ohw-editable]");
|
|
14286
16069
|
if (textEditable) {
|
|
14287
16070
|
activateRef.current(textEditable, {
|
|
@@ -14320,6 +16103,13 @@ function OhhwellsBridge() {
|
|
|
14320
16103
|
selectFrameRef.current(navContainerToSelect);
|
|
14321
16104
|
return;
|
|
14322
16105
|
}
|
|
16106
|
+
const socialsRowToSelect = isSocialsRow(target) ? target : null;
|
|
16107
|
+
if (socialsRowToSelect && !getSocialItem(target)) {
|
|
16108
|
+
e.preventDefault();
|
|
16109
|
+
e.stopPropagation();
|
|
16110
|
+
selectFrameRef.current(socialsRowToSelect);
|
|
16111
|
+
return;
|
|
16112
|
+
}
|
|
14323
16113
|
const footerColumnToSelect = resolveFooterColumnSelectionTarget(target, e.clientX, e.clientY);
|
|
14324
16114
|
if (footerColumnToSelect) {
|
|
14325
16115
|
e.preventDefault();
|
|
@@ -14368,9 +16158,11 @@ function OhhwellsBridge() {
|
|
|
14368
16158
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
14369
16159
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
14370
16160
|
if (isInsideLinkEditor(target)) return;
|
|
16161
|
+
if (isInsideFloatingPanel(target)) return;
|
|
14371
16162
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
14372
16163
|
return;
|
|
14373
16164
|
}
|
|
16165
|
+
if (getSocialItem(target)) return;
|
|
14374
16166
|
const navLabel = getNavigationLabelEditable(target);
|
|
14375
16167
|
const editable = navLabel?.editable ?? target.closest('[data-ohw-editable="text"], [data-ohw-editable="plain"]');
|
|
14376
16168
|
if (!editable || isMediaEditable(editable) || editable.dataset.ohwEditable === "link") return;
|
|
@@ -14394,6 +16186,16 @@ function OhhwellsBridge() {
|
|
|
14394
16186
|
setHoveredNavContainerRect(null);
|
|
14395
16187
|
return;
|
|
14396
16188
|
}
|
|
16189
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || isInsideFloatingPanel(target) || isPointOverFloatingPanel(e.clientX, e.clientY)) {
|
|
16190
|
+
hoveredItemElRef.current = null;
|
|
16191
|
+
setHoveredItemRect(null);
|
|
16192
|
+
hoveredNavContainerRef.current = null;
|
|
16193
|
+
setHoveredNavContainerRect(null);
|
|
16194
|
+
siblingHintElRef.current = null;
|
|
16195
|
+
setSiblingHintRect(null);
|
|
16196
|
+
setSiblingHintRects([]);
|
|
16197
|
+
return;
|
|
16198
|
+
}
|
|
14397
16199
|
{
|
|
14398
16200
|
const selected2 = selectedElRef.current;
|
|
14399
16201
|
const selectedIsFooterColumn = Boolean(selected2) && !isFooterLinksContainer(selected2) && (selected2.hasAttribute("data-ohw-footer-col") || selected2.hasAttribute("data-ohw-footer-column") || Boolean(selected2.closest("footer") && isInferredFooterGroup2(selected2)));
|
|
@@ -14401,7 +16203,7 @@ function OhhwellsBridge() {
|
|
|
14401
16203
|
const allowFooterLinksHover = toolbarVariantRef.current !== "select-frame" || selectedIsFooterColumn;
|
|
14402
16204
|
if (allowNavContainerHover) {
|
|
14403
16205
|
const navContainer = target.closest("[data-ohw-nav-container]");
|
|
14404
|
-
if (navContainer && !getNavigationItemAnchor(target)) {
|
|
16206
|
+
if (navContainer && !getNavigationItemAnchor(target) && !getLogoElement(target)) {
|
|
14405
16207
|
hoveredNavContainerRef.current = navContainer;
|
|
14406
16208
|
setHoveredNavContainerRect(navContainer.getBoundingClientRect());
|
|
14407
16209
|
hoveredItemElRef.current = null;
|
|
@@ -14430,6 +16232,15 @@ function OhhwellsBridge() {
|
|
|
14430
16232
|
setHoveredNavContainerRect(null);
|
|
14431
16233
|
}
|
|
14432
16234
|
}
|
|
16235
|
+
const logoEl = getLogoElement(target);
|
|
16236
|
+
if (logoEl) {
|
|
16237
|
+
hoveredNavContainerRef.current = null;
|
|
16238
|
+
setHoveredNavContainerRect(null);
|
|
16239
|
+
if (selectedElRef.current === logoEl) return;
|
|
16240
|
+
hoveredItemElRef.current = logoEl;
|
|
16241
|
+
setHoveredItemRect(getLogoInteractionRect(logoEl));
|
|
16242
|
+
return;
|
|
16243
|
+
}
|
|
14433
16244
|
const navAnchor = getNavigationItemAnchor(target);
|
|
14434
16245
|
if (navAnchor) {
|
|
14435
16246
|
hoveredNavContainerRef.current = null;
|
|
@@ -14455,6 +16266,11 @@ function OhhwellsBridge() {
|
|
|
14455
16266
|
const selected = selectedElRef.current;
|
|
14456
16267
|
if (selected && (selected === editable || selected.contains(editable))) return;
|
|
14457
16268
|
if (!isMediaEditable(editable) && !editable.hasAttribute("contenteditable")) {
|
|
16269
|
+
if (isIconEditable(editable) && !getSocialItem(editable)) {
|
|
16270
|
+
hoveredItemElRef.current = editable;
|
|
16271
|
+
setHoveredItemRect(editable.getBoundingClientRect());
|
|
16272
|
+
return;
|
|
16273
|
+
}
|
|
14458
16274
|
const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
|
|
14459
16275
|
if (hoverTarget.hasAttribute("data-ohw-href-key")) {
|
|
14460
16276
|
clearHrefKeyHover(hoverTarget);
|
|
@@ -14462,6 +16278,11 @@ function OhhwellsBridge() {
|
|
|
14462
16278
|
setHoveredItemRect(hoverTarget.getBoundingClientRect());
|
|
14463
16279
|
} else if (!isInsideNavigationItem(editable)) {
|
|
14464
16280
|
hoverTarget.setAttribute("data-ohw-hovered", "");
|
|
16281
|
+
if (editable.closest("footer") || editable.closest('[data-ohw-section="footer"]')) {
|
|
16282
|
+
hoveredNavContainerRef.current = null;
|
|
16283
|
+
setHoveredNavContainerRect(null);
|
|
16284
|
+
hoveredItemElRef.current = editable;
|
|
16285
|
+
}
|
|
14465
16286
|
}
|
|
14466
16287
|
}
|
|
14467
16288
|
};
|
|
@@ -14497,11 +16318,30 @@ function OhhwellsBridge() {
|
|
|
14497
16318
|
}
|
|
14498
16319
|
return;
|
|
14499
16320
|
}
|
|
16321
|
+
const logoEl = getLogoElement(target);
|
|
16322
|
+
if (logoEl) {
|
|
16323
|
+
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
16324
|
+
if (related2 && (logoEl === related2 || logoEl.contains(related2) || related2.closest?.('[data-ohw-role="logo"], [data-ohw-logo]'))) {
|
|
16325
|
+
return;
|
|
16326
|
+
}
|
|
16327
|
+
if (hoveredItemElRef.current === logoEl) {
|
|
16328
|
+
hoveredItemElRef.current = null;
|
|
16329
|
+
setHoveredItemRect(null);
|
|
16330
|
+
}
|
|
16331
|
+
return;
|
|
16332
|
+
}
|
|
14500
16333
|
const editable = target.closest("[data-ohw-editable]");
|
|
14501
16334
|
if (!editable) return;
|
|
14502
16335
|
const related = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
14503
16336
|
if (related?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
|
|
14504
16337
|
if (!isMediaEditable(editable)) {
|
|
16338
|
+
if (isIconEditable(editable) && !getSocialItem(editable) && hoveredItemElRef.current === editable) {
|
|
16339
|
+
if (!related?.closest("[data-ohw-item-interaction]")) {
|
|
16340
|
+
hoveredItemElRef.current = null;
|
|
16341
|
+
setHoveredItemRect(null);
|
|
16342
|
+
}
|
|
16343
|
+
return;
|
|
16344
|
+
}
|
|
14505
16345
|
const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
|
|
14506
16346
|
if (hoverTarget.hasAttribute("data-ohw-href-key")) {
|
|
14507
16347
|
if (!related?.closest("[data-ohw-href-key]")) {
|
|
@@ -14510,6 +16350,13 @@ function OhhwellsBridge() {
|
|
|
14510
16350
|
}
|
|
14511
16351
|
} else {
|
|
14512
16352
|
hoverTarget.removeAttribute("data-ohw-hovered");
|
|
16353
|
+
if (hoveredItemElRef.current === editable) {
|
|
16354
|
+
const stillOnEditable = related instanceof Element && related.closest("[data-ohw-editable]") === editable;
|
|
16355
|
+
if (!stillOnEditable) {
|
|
16356
|
+
hoveredItemElRef.current = null;
|
|
16357
|
+
setHoveredItemRect(null);
|
|
16358
|
+
}
|
|
16359
|
+
}
|
|
14513
16360
|
}
|
|
14514
16361
|
}
|
|
14515
16362
|
};
|
|
@@ -14626,6 +16473,26 @@ function OhhwellsBridge() {
|
|
|
14626
16473
|
hoveredNavContainerRef.current = null;
|
|
14627
16474
|
setHoveredNavContainerRect(null);
|
|
14628
16475
|
}
|
|
16476
|
+
const logoCandidates = [
|
|
16477
|
+
...document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]'),
|
|
16478
|
+
...document.querySelectorAll("nav a:not([data-ohw-href-key]), [data-ohw-nav-root] a:not([data-ohw-href-key])"),
|
|
16479
|
+
...document.querySelectorAll("footer img")
|
|
16480
|
+
];
|
|
16481
|
+
const seenLogos = /* @__PURE__ */ new Set();
|
|
16482
|
+
for (const candidate of logoCandidates) {
|
|
16483
|
+
const logo = getLogoElement(candidate);
|
|
16484
|
+
if (!logo || seenLogos.has(logo)) continue;
|
|
16485
|
+
seenLogos.add(logo);
|
|
16486
|
+
const r2 = logo.getBoundingClientRect();
|
|
16487
|
+
if (x < r2.left || x > r2.right || y < r2.top || y > r2.bottom) continue;
|
|
16488
|
+
hoveredNavContainerRef.current = null;
|
|
16489
|
+
setHoveredNavContainerRect(null);
|
|
16490
|
+
if (selectedElRef.current !== logo) {
|
|
16491
|
+
hoveredItemElRef.current = logo;
|
|
16492
|
+
setHoveredItemRect(getLogoInteractionRect(logo));
|
|
16493
|
+
}
|
|
16494
|
+
return;
|
|
16495
|
+
}
|
|
14629
16496
|
const navContainers = Array.from(
|
|
14630
16497
|
document.querySelectorAll("[data-ohw-nav-container]")
|
|
14631
16498
|
);
|
|
@@ -14711,7 +16578,7 @@ function OhhwellsBridge() {
|
|
|
14711
16578
|
}
|
|
14712
16579
|
};
|
|
14713
16580
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
14714
|
-
if (linkPopoverOpenRef.current) {
|
|
16581
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
14715
16582
|
if (hoveredImageRef.current) {
|
|
14716
16583
|
hoveredImageRef.current = null;
|
|
14717
16584
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -14965,7 +16832,7 @@ function OhhwellsBridge() {
|
|
|
14965
16832
|
}
|
|
14966
16833
|
};
|
|
14967
16834
|
const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
|
|
14968
|
-
if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
|
|
16835
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || document.documentElement.hasAttribute("data-ohw-section-picking")) {
|
|
14969
16836
|
if (activeStateElRef.current) {
|
|
14970
16837
|
activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
|
|
14971
16838
|
activeStateElRef.current = null;
|
|
@@ -15033,6 +16900,19 @@ function OhhwellsBridge() {
|
|
|
15033
16900
|
};
|
|
15034
16901
|
const handleMouseMove = (e) => {
|
|
15035
16902
|
const { clientX, clientY } = e;
|
|
16903
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
16904
|
+
hoveredItemElRef.current = null;
|
|
16905
|
+
setHoveredItemRect(null);
|
|
16906
|
+
hoveredNavContainerRef.current = null;
|
|
16907
|
+
setHoveredNavContainerRect(null);
|
|
16908
|
+
siblingHintElRef.current = null;
|
|
16909
|
+
setSiblingHintRect(null);
|
|
16910
|
+
setSiblingHintRects([]);
|
|
16911
|
+
dismissImageHover();
|
|
16912
|
+
clearImageHover();
|
|
16913
|
+
setSectionGap(null);
|
|
16914
|
+
return;
|
|
16915
|
+
}
|
|
15036
16916
|
probeSectionGapAt(clientX, clientY);
|
|
15037
16917
|
probeImageAt(clientX, clientY);
|
|
15038
16918
|
probeHoverCardsAt(clientX, clientY);
|
|
@@ -15041,6 +16921,11 @@ function OhhwellsBridge() {
|
|
|
15041
16921
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
15042
16922
|
const { clientX, clientY } = e.data;
|
|
15043
16923
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
16924
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
16925
|
+
dismissImageHover();
|
|
16926
|
+
clearImageHover();
|
|
16927
|
+
return;
|
|
16928
|
+
}
|
|
15044
16929
|
probeSectionGapAt(clientX, clientY);
|
|
15045
16930
|
probeImageAt(clientX, clientY);
|
|
15046
16931
|
probeHoverCardsAt(clientX, clientY);
|
|
@@ -15050,7 +16935,7 @@ function OhhwellsBridge() {
|
|
|
15050
16935
|
if (footerSession) {
|
|
15051
16936
|
e.preventDefault();
|
|
15052
16937
|
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
15053
|
-
const slot = footerSession.kind === "link" && footerSession.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, footerSession.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
16938
|
+
const slot = footerSession.kind === "social" && footerSession.hrefKey ? hitTestSocialDropSlot(e.clientX, e.clientY, footerSession.hrefKey) : footerSession.kind === "link" && footerSession.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, footerSession.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
15054
16939
|
refreshFooterDragVisualsRef.current(footerSession, slot, e.clientX, e.clientY);
|
|
15055
16940
|
return;
|
|
15056
16941
|
}
|
|
@@ -15102,6 +16987,62 @@ function OhhwellsBridge() {
|
|
|
15102
16987
|
resumeAnimTracks();
|
|
15103
16988
|
clearImageHover();
|
|
15104
16989
|
};
|
|
16990
|
+
const handleSocialCancel = (e) => {
|
|
16991
|
+
if (e.data?.type !== "ow:social-cancel") return;
|
|
16992
|
+
const { hrefKey } = e.data;
|
|
16993
|
+
const item = hrefKey ? findSocialByHrefKey(hrefKey) : null;
|
|
16994
|
+
if (!item) return;
|
|
16995
|
+
const removed = removeSocialItem(item, editContentRef.current);
|
|
16996
|
+
if (!removed) return;
|
|
16997
|
+
const orderJson = JSON.stringify(removed.order);
|
|
16998
|
+
editContentRef.current = { ...editContentRef.current, [SOCIALS_ORDER_KEY]: orderJson };
|
|
16999
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: SOCIALS_ORDER_KEY, text: orderJson }] });
|
|
17000
|
+
deselectRef.current();
|
|
17001
|
+
};
|
|
17002
|
+
const handleSocialUpdate = (e) => {
|
|
17003
|
+
if (e.data?.type !== "ow:social-update") return;
|
|
17004
|
+
const updates = Array.isArray(e.data.items) ? e.data.items : [e.data];
|
|
17005
|
+
const nodes = [];
|
|
17006
|
+
for (const { hrefKey, iconKey, url, iconMarkup, platformId, label } of updates) {
|
|
17007
|
+
if (hrefKey) {
|
|
17008
|
+
document.querySelectorAll(`[data-ohw-href-key="${hrefKey}"]`).forEach((el) => applyLinkHref(el, url));
|
|
17009
|
+
nodes.push({ key: hrefKey, text: url });
|
|
17010
|
+
}
|
|
17011
|
+
if (iconKey && typeof iconMarkup === "string" && iconMarkup) {
|
|
17012
|
+
document.querySelectorAll(`[data-ohw-key="${iconKey}"][data-ohw-editable="icon"]`).forEach((el) => {
|
|
17013
|
+
applyIconMarkup(el, iconMarkup);
|
|
17014
|
+
});
|
|
17015
|
+
nodes.push({ key: iconKey, text: iconMarkup });
|
|
17016
|
+
}
|
|
17017
|
+
if (iconKey && platformId) nodes.push({ key: socialPlatformKey(iconKey), text: platformId });
|
|
17018
|
+
if (iconKey && label) {
|
|
17019
|
+
const labelKey = socialLabelKey(iconKey);
|
|
17020
|
+
document.querySelectorAll(`[data-ohw-key="${labelKey}"]`).forEach((el) => {
|
|
17021
|
+
el.textContent = label;
|
|
17022
|
+
});
|
|
17023
|
+
nodes.push({ key: labelKey, text: label });
|
|
17024
|
+
}
|
|
17025
|
+
}
|
|
17026
|
+
if (!nodes.length) return;
|
|
17027
|
+
editContentRef.current = {
|
|
17028
|
+
...editContentRef.current,
|
|
17029
|
+
...Object.fromEntries(nodes.map((node) => [node.key, node.text]))
|
|
17030
|
+
};
|
|
17031
|
+
postToParentRef.current({ type: "ow:change", nodes, flush: true });
|
|
17032
|
+
};
|
|
17033
|
+
const handleIconMarkup = (e) => {
|
|
17034
|
+
if (e.data?.type !== "ow:icon-markup") return;
|
|
17035
|
+
const { key, markup } = e.data;
|
|
17036
|
+
if (!key || typeof markup !== "string") return;
|
|
17037
|
+
const targets = document.querySelectorAll(
|
|
17038
|
+
`[data-ohw-key="${key}"][data-ohw-editable="icon"]`
|
|
17039
|
+
);
|
|
17040
|
+
if (!targets.length) return;
|
|
17041
|
+
targets.forEach((el) => {
|
|
17042
|
+
applyIconMarkup(el, markup);
|
|
17043
|
+
});
|
|
17044
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key, text: markup }], flush: true });
|
|
17045
|
+
};
|
|
15105
17046
|
const handleImageUrl = (e) => {
|
|
15106
17047
|
if (e.data?.type !== "ow:image-url") return;
|
|
15107
17048
|
const { key, url } = e.data;
|
|
@@ -15234,6 +17175,11 @@ function OhhwellsBridge() {
|
|
|
15234
17175
|
aiSectionsRef.current = content[AI_SECTIONS_KEY];
|
|
15235
17176
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
15236
17177
|
}
|
|
17178
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
17179
|
+
brandKitRef.current = content[BRAND_KIT_KEY];
|
|
17180
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
17181
|
+
}
|
|
17182
|
+
applyBrandChrome(content);
|
|
15237
17183
|
let sectionsJson = null;
|
|
15238
17184
|
for (const [key, val] of Object.entries(content)) {
|
|
15239
17185
|
if (key === "__ohw_sections") {
|
|
@@ -15241,6 +17187,10 @@ function OhhwellsBridge() {
|
|
|
15241
17187
|
continue;
|
|
15242
17188
|
}
|
|
15243
17189
|
if (key === AI_SECTIONS_KEY) continue;
|
|
17190
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
17191
|
+
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
17192
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
17193
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
15244
17194
|
if (applyVideoSettingNode(key, val)) continue;
|
|
15245
17195
|
if (applyCarouselNode(key, val)) continue;
|
|
15246
17196
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -15260,6 +17210,8 @@ function OhhwellsBridge() {
|
|
|
15260
17210
|
});
|
|
15261
17211
|
applyLinkByKey(key, val);
|
|
15262
17212
|
}
|
|
17213
|
+
applyLogoFromContent(content);
|
|
17214
|
+
applyLogoSizes(content);
|
|
15263
17215
|
if (sectionsJson) {
|
|
15264
17216
|
initSectionsFromContent({ __ohw_sections: sectionsJson }, true);
|
|
15265
17217
|
sectionsLoadedRef.current = true;
|
|
@@ -15274,6 +17226,58 @@ function OhhwellsBridge() {
|
|
|
15274
17226
|
if (hydratedHeight > 50) postToParentRef.current({ type: "ow:height", height: hydratedHeight });
|
|
15275
17227
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
15276
17228
|
};
|
|
17229
|
+
const handleUpdateLogoIdentity = (e) => {
|
|
17230
|
+
if (e.data?.type !== "ow:update-logo-identity") return;
|
|
17231
|
+
const rawText = typeof e.data.text === "string" ? e.data.text : "";
|
|
17232
|
+
const alt = typeof e.data.alt === "string" ? e.data.alt : rawText;
|
|
17233
|
+
const href = typeof e.data.href === "string" ? e.data.href : void 0;
|
|
17234
|
+
const imageProvided = "image" in e.data;
|
|
17235
|
+
const imageUrl = imageProvided && typeof e.data.image === "string" && e.data.image.trim() ? e.data.image.trim() : imageProvided ? null : void 0;
|
|
17236
|
+
let isPlaceholder = e.data.isPlaceholder !== false;
|
|
17237
|
+
if (imageUrl) isPlaceholder = false;
|
|
17238
|
+
else if (imageProvided && imageUrl === null) {
|
|
17239
|
+
isPlaceholder = e.data.isPlaceholder === true || !rawText.trim() || resolveLogoDisplayText(rawText) === PLACEHOLDER_BUSINESS_NAME;
|
|
17240
|
+
}
|
|
17241
|
+
const display = applyLogoIdentity(rawText, isPlaceholder);
|
|
17242
|
+
const displayAlt = resolveLogoDisplayText(alt || display);
|
|
17243
|
+
if (imageUrl !== void 0) {
|
|
17244
|
+
applyLogoImage(imageUrl, displayAlt);
|
|
17245
|
+
} else {
|
|
17246
|
+
for (const key of LOGO_IMAGE_KEYS) {
|
|
17247
|
+
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
17248
|
+
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
17249
|
+
if (img) img.alt = displayAlt;
|
|
17250
|
+
});
|
|
17251
|
+
}
|
|
17252
|
+
}
|
|
17253
|
+
if (href !== void 0) {
|
|
17254
|
+
applyLogoHref(href);
|
|
17255
|
+
applyLinkByKey("nav-logo-href", href);
|
|
17256
|
+
applyLinkByKey("footer-logo-href", href);
|
|
17257
|
+
applyLinkByKey("logo-href", href);
|
|
17258
|
+
}
|
|
17259
|
+
const nodes = [
|
|
17260
|
+
...LOGO_TEXT_KEYS.map((key) => ({ key, text: display })),
|
|
17261
|
+
{ key: LOGO_PLACEHOLDER_KEY, text: isPlaceholder ? "true" : "false" },
|
|
17262
|
+
{ key: LOGO_ALT_KEY, text: displayAlt }
|
|
17263
|
+
];
|
|
17264
|
+
if (imageUrl !== void 0) {
|
|
17265
|
+
if (imageUrl) {
|
|
17266
|
+
for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: imageUrl });
|
|
17267
|
+
} else {
|
|
17268
|
+
for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: "" });
|
|
17269
|
+
}
|
|
17270
|
+
}
|
|
17271
|
+
if (href !== void 0) {
|
|
17272
|
+
for (const key of LOGO_HREF_KEYS) nodes.push({ key, text: href.trim() || "/" });
|
|
17273
|
+
}
|
|
17274
|
+
editContentRef.current = {
|
|
17275
|
+
...editContentRef.current,
|
|
17276
|
+
...Object.fromEntries(nodes.map(({ key, text }) => [key, text]))
|
|
17277
|
+
};
|
|
17278
|
+
applyLogoSizes(editContentRef.current);
|
|
17279
|
+
postToParentRef.current({ type: "ow:change", nodes });
|
|
17280
|
+
};
|
|
15277
17281
|
window.addEventListener("message", handleHydrate);
|
|
15278
17282
|
const postAiSectionsChanged = () => {
|
|
15279
17283
|
postToParentRef.current({
|
|
@@ -15330,6 +17334,17 @@ function OhhwellsBridge() {
|
|
|
15330
17334
|
postAiSectionsChanged();
|
|
15331
17335
|
};
|
|
15332
17336
|
window.addEventListener("message", handleAiSetSections);
|
|
17337
|
+
const handleAiSetBrand = (e) => {
|
|
17338
|
+
if (e.data?.type !== "ow:ai-set-brand") return;
|
|
17339
|
+
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
17340
|
+
const previous = brandKitRef.current;
|
|
17341
|
+
brandKitRef.current = value;
|
|
17342
|
+
applyBrandToDom(parseBrandKit(value));
|
|
17343
|
+
if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
|
|
17344
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
|
|
17345
|
+
postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
|
|
17346
|
+
};
|
|
17347
|
+
window.addEventListener("message", handleAiSetBrand);
|
|
15333
17348
|
const handleDeactivate = (e) => {
|
|
15334
17349
|
if (e.data?.type !== "ow:deactivate") return;
|
|
15335
17350
|
if (Date.now() < linkPopoverGraceUntilRef.current) return;
|
|
@@ -15338,6 +17353,12 @@ function OhhwellsBridge() {
|
|
|
15338
17353
|
closeLinkPopoverRef.current();
|
|
15339
17354
|
return;
|
|
15340
17355
|
}
|
|
17356
|
+
if (floatingPanelOpenRef.current) {
|
|
17357
|
+
setFloatingPanelRef.current(null);
|
|
17358
|
+
deselectRef.current();
|
|
17359
|
+
deactivateRef.current();
|
|
17360
|
+
return;
|
|
17361
|
+
}
|
|
15341
17362
|
deselectRef.current();
|
|
15342
17363
|
deactivateRef.current();
|
|
15343
17364
|
};
|
|
@@ -15357,6 +17378,10 @@ function OhhwellsBridge() {
|
|
|
15357
17378
|
closeLinkPopoverRef.current();
|
|
15358
17379
|
return;
|
|
15359
17380
|
}
|
|
17381
|
+
if (floatingPanelOpenRef.current) {
|
|
17382
|
+
closeFloatingPanelOnlyRef.current();
|
|
17383
|
+
return;
|
|
17384
|
+
}
|
|
15360
17385
|
if (activeElRef.current) {
|
|
15361
17386
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
15362
17387
|
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
@@ -15387,6 +17412,10 @@ function OhhwellsBridge() {
|
|
|
15387
17412
|
return;
|
|
15388
17413
|
}
|
|
15389
17414
|
if (selectedElRef.current) {
|
|
17415
|
+
if (toolbarVariantRef.current === "logo") {
|
|
17416
|
+
deselectRef.current();
|
|
17417
|
+
return;
|
|
17418
|
+
}
|
|
15390
17419
|
if (toolbarVariantRef.current === "select-frame") {
|
|
15391
17420
|
const parent2 = getNavigationSelectionParent(selectedElRef.current);
|
|
15392
17421
|
if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
|
|
@@ -15420,7 +17449,16 @@ function OhhwellsBridge() {
|
|
|
15420
17449
|
closeLinkPopoverRef.current();
|
|
15421
17450
|
return;
|
|
15422
17451
|
}
|
|
17452
|
+
if (e.key === "Escape" && floatingPanelOpenRef.current) {
|
|
17453
|
+
e.preventDefault();
|
|
17454
|
+
closeFloatingPanelOnlyRef.current();
|
|
17455
|
+
return;
|
|
17456
|
+
}
|
|
15423
17457
|
if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
|
|
17458
|
+
if (toolbarVariantRef.current === "logo") {
|
|
17459
|
+
deselectRef.current();
|
|
17460
|
+
return;
|
|
17461
|
+
}
|
|
15424
17462
|
if (toolbarVariantRef.current === "select-frame") {
|
|
15425
17463
|
const parent2 = getNavigationSelectionParent(selectedElRef.current);
|
|
15426
17464
|
if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
|
|
@@ -15498,7 +17536,8 @@ function OhhwellsBridge() {
|
|
|
15498
17536
|
const handleScroll = () => {
|
|
15499
17537
|
const focusEl = activeElRef.current ?? selectedElRef.current;
|
|
15500
17538
|
if (focusEl) {
|
|
15501
|
-
const
|
|
17539
|
+
const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : toolbarVariantRef.current === "logo" ? null : focusEl;
|
|
17540
|
+
const r2 = measureEl ? measureEl.getBoundingClientRect() : toolbarVariantRef.current === "logo" ? getLogoInteractionRect(focusEl) : focusEl.getBoundingClientRect();
|
|
15502
17541
|
applyToolbarPos(r2);
|
|
15503
17542
|
setToolbarRect(r2);
|
|
15504
17543
|
setMaxBadge((prev) => prev && activeElRef.current ? { ...prev, rect: r2 } : prev);
|
|
@@ -15508,7 +17547,9 @@ function OhhwellsBridge() {
|
|
|
15508
17547
|
setToggleState((prev) => prev ? { ...prev, rect } : null);
|
|
15509
17548
|
}
|
|
15510
17549
|
if (hoveredItemElRef.current) {
|
|
15511
|
-
|
|
17550
|
+
const hoverEl = hoveredItemElRef.current;
|
|
17551
|
+
const logo = getLogoElement(hoverEl);
|
|
17552
|
+
setHoveredItemRect(logo ? getLogoInteractionRect(logo) : hoverEl.getBoundingClientRect());
|
|
15512
17553
|
}
|
|
15513
17554
|
if (hoveredNavContainerRef.current) {
|
|
15514
17555
|
setHoveredNavContainerRect(hoveredNavContainerRef.current.getBoundingClientRect());
|
|
@@ -15528,7 +17569,7 @@ function OhhwellsBridge() {
|
|
|
15528
17569
|
}
|
|
15529
17570
|
if (footerDragRef.current) {
|
|
15530
17571
|
const session = footerDragRef.current;
|
|
15531
|
-
const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
17572
|
+
const slot = session.kind === "social" && session.hrefKey ? hitTestSocialDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
15532
17573
|
refreshFooterDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
|
|
15533
17574
|
}
|
|
15534
17575
|
if (navDragRef.current) {
|
|
@@ -15552,6 +17593,9 @@ function OhhwellsBridge() {
|
|
|
15552
17593
|
if (aiSectionsRef.current) {
|
|
15553
17594
|
nodes.push({ key: AI_SECTIONS_KEY, type: "sections", text: aiSectionsRef.current });
|
|
15554
17595
|
}
|
|
17596
|
+
if (brandKitRef.current) {
|
|
17597
|
+
nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
|
|
17598
|
+
}
|
|
15555
17599
|
postToParentRef.current({ type: "ow:save-result", nodes });
|
|
15556
17600
|
};
|
|
15557
17601
|
const handleInsertSection = (e) => {
|
|
@@ -15562,8 +17606,12 @@ function OhhwellsBridge() {
|
|
|
15562
17606
|
if (inserted) {
|
|
15563
17607
|
const tracker = getSectionsTracker();
|
|
15564
17608
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
|
|
15565
|
-
const
|
|
15566
|
-
|
|
17609
|
+
const reportHeight = () => {
|
|
17610
|
+
const h = document.body.scrollHeight;
|
|
17611
|
+
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
17612
|
+
};
|
|
17613
|
+
reportHeight();
|
|
17614
|
+
setTimeout(reportHeight, 500);
|
|
15567
17615
|
}
|
|
15568
17616
|
};
|
|
15569
17617
|
const handleSwitchSchedule = (e) => {
|
|
@@ -15756,13 +17804,17 @@ function OhhwellsBridge() {
|
|
|
15756
17804
|
if (e.data?.type !== "ow:parent-scroll") return;
|
|
15757
17805
|
const { iframeOffsetTop, headerH, canvasH } = e.data;
|
|
15758
17806
|
parentScrollRef.current = { iframeOffsetTop, headerH, canvasH };
|
|
17807
|
+
if (floatingPanelOpenRef.current) {
|
|
17808
|
+
setParentScrollSnap({ iframeOffsetTop, headerH, canvasH });
|
|
17809
|
+
}
|
|
15759
17810
|
if (visibleViewportRef.current) {
|
|
15760
17811
|
applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
|
|
15761
17812
|
}
|
|
15762
17813
|
const focusEl = activeElRef.current ?? selectedElRef.current;
|
|
15763
17814
|
if (focusEl) {
|
|
15764
|
-
const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : focusEl;
|
|
15765
|
-
|
|
17815
|
+
const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : toolbarVariantRef.current === "logo" ? null : focusEl;
|
|
17816
|
+
const r2 = measureEl ? measureEl.getBoundingClientRect() : toolbarVariantRef.current === "logo" ? getLogoInteractionRect(focusEl) : focusEl.getBoundingClientRect();
|
|
17817
|
+
applyToolbarPos(r2);
|
|
15766
17818
|
}
|
|
15767
17819
|
};
|
|
15768
17820
|
const handleClickAt = (e) => {
|
|
@@ -15787,6 +17839,25 @@ function OhhwellsBridge() {
|
|
|
15787
17839
|
postToParentRef.current({ type: "ow:image-pick", key: stateCardImage.dataset.ohwKey ?? "", elementType: stateCardImage.dataset.ohwEditable ?? "image" });
|
|
15788
17840
|
return;
|
|
15789
17841
|
}
|
|
17842
|
+
const logoAtPoint = Array.from(
|
|
17843
|
+
document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]')
|
|
17844
|
+
).map((el) => getLogoElement(el)).find((logo) => {
|
|
17845
|
+
if (!logo) return false;
|
|
17846
|
+
const r2 = logo.getBoundingClientRect();
|
|
17847
|
+
return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
|
|
17848
|
+
});
|
|
17849
|
+
if (logoAtPoint) {
|
|
17850
|
+
if (!logoHasUploadedImage(logoAtPoint)) {
|
|
17851
|
+
deselectRef.current();
|
|
17852
|
+
deactivateRef.current();
|
|
17853
|
+
const identity = readLogoIdentityFromDom();
|
|
17854
|
+
postToParentRef.current({ type: "ow:open-logo-settings", ...identity });
|
|
17855
|
+
return;
|
|
17856
|
+
}
|
|
17857
|
+
selectLogoRef.current(logoAtPoint);
|
|
17858
|
+
openLogoSizePanelRef.current(logoAtPoint);
|
|
17859
|
+
return;
|
|
17860
|
+
}
|
|
15790
17861
|
const textEditable = Array.from(
|
|
15791
17862
|
document.querySelectorAll(NON_MEDIA_SELECTOR)
|
|
15792
17863
|
).find((el) => {
|
|
@@ -15848,6 +17919,9 @@ function OhhwellsBridge() {
|
|
|
15848
17919
|
window.addEventListener("message", handleClearSchedulingWidget);
|
|
15849
17920
|
window.addEventListener("message", handleRemoveSchedulingSection);
|
|
15850
17921
|
window.addEventListener("message", handleCollectSection);
|
|
17922
|
+
window.addEventListener("message", handleSocialCancel);
|
|
17923
|
+
window.addEventListener("message", handleSocialUpdate);
|
|
17924
|
+
window.addEventListener("message", handleIconMarkup);
|
|
15851
17925
|
window.addEventListener("message", handleImageUrl);
|
|
15852
17926
|
window.addEventListener("message", handleImageUploading);
|
|
15853
17927
|
window.addEventListener("message", handleCarouselChange);
|
|
@@ -15855,6 +17929,14 @@ function OhhwellsBridge() {
|
|
|
15855
17929
|
window.addEventListener("message", handleParentScroll);
|
|
15856
17930
|
window.addEventListener("message", handlePointerSync);
|
|
15857
17931
|
window.addEventListener("message", handleClickAt);
|
|
17932
|
+
window.addEventListener("message", handleUpdateLogoIdentity);
|
|
17933
|
+
const handleViewMode = (e) => {
|
|
17934
|
+
if (e.data?.type !== "ow:view-mode") return;
|
|
17935
|
+
const mode = e.data.mode === "Mobile" || e.data.mode === "mobile" ? "mobile" : "desktop";
|
|
17936
|
+
setEditorViewport(mode);
|
|
17937
|
+
applyLogoSizes(editContentRef.current);
|
|
17938
|
+
};
|
|
17939
|
+
window.addEventListener("message", handleViewMode);
|
|
15858
17940
|
const handleViewportResize = () => {
|
|
15859
17941
|
if (visibleViewportRef.current) {
|
|
15860
17942
|
applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
|
|
@@ -15899,6 +17981,9 @@ function OhhwellsBridge() {
|
|
|
15899
17981
|
window.removeEventListener("message", handleClearSchedulingWidget);
|
|
15900
17982
|
window.removeEventListener("message", handleRemoveSchedulingSection);
|
|
15901
17983
|
window.removeEventListener("message", handleCollectSection);
|
|
17984
|
+
window.removeEventListener("message", handleSocialCancel);
|
|
17985
|
+
window.removeEventListener("message", handleSocialUpdate);
|
|
17986
|
+
window.removeEventListener("message", handleIconMarkup);
|
|
15902
17987
|
window.removeEventListener("message", handleImageUrl);
|
|
15903
17988
|
window.removeEventListener("message", handleImageUploading);
|
|
15904
17989
|
window.removeEventListener("message", handleCarouselChange);
|
|
@@ -15907,10 +17992,13 @@ function OhhwellsBridge() {
|
|
|
15907
17992
|
window.removeEventListener("resize", handleViewportResize);
|
|
15908
17993
|
window.removeEventListener("message", handlePointerSync);
|
|
15909
17994
|
window.removeEventListener("message", handleClickAt);
|
|
17995
|
+
window.removeEventListener("message", handleUpdateLogoIdentity);
|
|
17996
|
+
window.removeEventListener("message", handleViewMode);
|
|
15910
17997
|
window.removeEventListener("message", handleHydrate);
|
|
15911
17998
|
window.removeEventListener("message", handleAiApplyTree);
|
|
15912
17999
|
window.removeEventListener("message", handleAiDeleteSection);
|
|
15913
18000
|
window.removeEventListener("message", handleAiSetSections);
|
|
18001
|
+
window.removeEventListener("message", handleAiSetBrand);
|
|
15914
18002
|
window.removeEventListener("message", handleDeactivate);
|
|
15915
18003
|
window.removeEventListener("message", handleToastAction);
|
|
15916
18004
|
window.removeEventListener("message", handleUiEscape);
|
|
@@ -15920,7 +18008,7 @@ function OhhwellsBridge() {
|
|
|
15920
18008
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
15921
18009
|
};
|
|
15922
18010
|
}, [isEditMode, refreshStateRules]);
|
|
15923
|
-
(0,
|
|
18011
|
+
(0, import_react16.useEffect)(() => {
|
|
15924
18012
|
if (!isEditMode) return;
|
|
15925
18013
|
const THRESHOLD = 10;
|
|
15926
18014
|
const resolveWasSelected = (el) => {
|
|
@@ -15936,13 +18024,13 @@ function OhhwellsBridge() {
|
|
|
15936
18024
|
if (footerDragRef.current) return;
|
|
15937
18025
|
const target = e.target;
|
|
15938
18026
|
if (!target) return;
|
|
15939
|
-
if (target.closest('[data-ohw-drag-handle-container], [data-slot="drag-handle"], [data-ohw-toolbar], [data-ohw-item-toolbar-anchor], [data-ohw-link-popover-root]')) {
|
|
18027
|
+
if (target.closest('[data-ohw-drag-handle-container], [data-slot="drag-handle"], [data-ohw-toolbar], [data-ohw-item-toolbar-anchor], [data-ohw-link-popover-root], [data-ohw-floating-panel]')) {
|
|
15940
18028
|
return;
|
|
15941
18029
|
}
|
|
15942
18030
|
if (target.closest("[data-ohw-item-drag-surface]")) return;
|
|
15943
|
-
const anchor = getNavigationItemAnchor(target);
|
|
18031
|
+
const anchor = getNavigationItemAnchor(target) ?? (document.elementsFromPoint(e.clientX, e.clientY).map((el) => el instanceof HTMLElement ? getNavigationItemAnchor(el) : null).find((found) => found !== null) ?? null);
|
|
15944
18032
|
const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
15945
|
-
if (anchor && isFooterHrefKey(hrefKey)) {
|
|
18033
|
+
if (anchor && (isFooterHrefKey(hrefKey) || getSocialItem(anchor))) {
|
|
15946
18034
|
footerPointerDragRef.current = {
|
|
15947
18035
|
el: anchor,
|
|
15948
18036
|
kind: "link",
|
|
@@ -15975,7 +18063,7 @@ function OhhwellsBridge() {
|
|
|
15975
18063
|
clearTextSelection();
|
|
15976
18064
|
const session = footerDragRef.current;
|
|
15977
18065
|
if (!session) return;
|
|
15978
|
-
const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, session.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
18066
|
+
const slot = session.kind === "social" && session.hrefKey ? hitTestSocialDropSlot(e.clientX, e.clientY, session.hrefKey) : session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, session.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
15979
18067
|
refreshFooterDragVisualsRef.current(session, slot, e.clientX, e.clientY);
|
|
15980
18068
|
return;
|
|
15981
18069
|
}
|
|
@@ -16002,7 +18090,7 @@ function OhhwellsBridge() {
|
|
|
16002
18090
|
const column = findFooterColumnForLink(pending.el);
|
|
16003
18091
|
const columns2 = listFooterColumns();
|
|
16004
18092
|
beginFooterDragRef.current({
|
|
16005
|
-
kind: "link",
|
|
18093
|
+
kind: getSocialItem(pending.el) ? "social" : "link",
|
|
16006
18094
|
hrefKey: key,
|
|
16007
18095
|
columnEl: column,
|
|
16008
18096
|
sourceColumnIndex: column ? columns2.indexOf(column) : 0,
|
|
@@ -16074,7 +18162,7 @@ function OhhwellsBridge() {
|
|
|
16074
18162
|
unlockFooterDragInteraction();
|
|
16075
18163
|
};
|
|
16076
18164
|
}, [isEditMode]);
|
|
16077
|
-
(0,
|
|
18165
|
+
(0, import_react16.useEffect)(() => {
|
|
16078
18166
|
const handler = (e) => {
|
|
16079
18167
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
16080
18168
|
const insertAfterVal = e.data.insertAfter;
|
|
@@ -16090,7 +18178,7 @@ function OhhwellsBridge() {
|
|
|
16090
18178
|
window.addEventListener("message", handler);
|
|
16091
18179
|
return () => window.removeEventListener("message", handler);
|
|
16092
18180
|
}, [processConfigRequest]);
|
|
16093
|
-
(0,
|
|
18181
|
+
(0, import_react16.useEffect)(() => {
|
|
16094
18182
|
if (!isEditMode) return;
|
|
16095
18183
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|
|
16096
18184
|
el.removeAttribute("data-ohw-active-state");
|
|
@@ -16114,7 +18202,7 @@ function OhhwellsBridge() {
|
|
|
16114
18202
|
postToParent2({
|
|
16115
18203
|
type: "ow:ready",
|
|
16116
18204
|
version: "1",
|
|
16117
|
-
bridgeVersion: "0.1.
|
|
18205
|
+
bridgeVersion: "0.1.55",
|
|
16118
18206
|
path: pathname,
|
|
16119
18207
|
nodes: collectEditableNodes(editContentRef.current),
|
|
16120
18208
|
sections
|
|
@@ -16126,13 +18214,13 @@ function OhhwellsBridge() {
|
|
|
16126
18214
|
clearTimeout(timer);
|
|
16127
18215
|
};
|
|
16128
18216
|
}, [pathname, isEditMode, refreshStateRules, postToParent2]);
|
|
16129
|
-
(0,
|
|
18217
|
+
(0, import_react16.useEffect)(() => {
|
|
16130
18218
|
scrollToHashSectionWhenReady();
|
|
16131
18219
|
const onHashChange = () => scrollToHashSectionWhenReady();
|
|
16132
18220
|
window.addEventListener("hashchange", onHashChange);
|
|
16133
18221
|
return () => window.removeEventListener("hashchange", onHashChange);
|
|
16134
18222
|
}, [pathname]);
|
|
16135
|
-
const handleCommand = (0,
|
|
18223
|
+
const handleCommand = (0, import_react16.useCallback)((cmd) => {
|
|
16136
18224
|
const el = activeElRef.current;
|
|
16137
18225
|
const selBefore = window.getSelection();
|
|
16138
18226
|
let savedOffsets = null;
|
|
@@ -16168,7 +18256,7 @@ function OhhwellsBridge() {
|
|
|
16168
18256
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
16169
18257
|
refreshActiveCommandsRef.current();
|
|
16170
18258
|
}, []);
|
|
16171
|
-
const handleStateChange = (0,
|
|
18259
|
+
const handleStateChange = (0, import_react16.useCallback)((state) => {
|
|
16172
18260
|
if (!activeStateElRef.current) return;
|
|
16173
18261
|
const el = activeStateElRef.current;
|
|
16174
18262
|
if (state === "Default") {
|
|
@@ -16181,7 +18269,7 @@ function OhhwellsBridge() {
|
|
|
16181
18269
|
}
|
|
16182
18270
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
16183
18271
|
}, [deactivate]);
|
|
16184
|
-
const reselectAfterLinkPopover = (0,
|
|
18272
|
+
const reselectAfterLinkPopover = (0, import_react16.useCallback)(
|
|
16185
18273
|
(hrefKey) => {
|
|
16186
18274
|
requestAnimationFrame(() => {
|
|
16187
18275
|
const el = resolveHrefKeyElement(hrefKey);
|
|
@@ -16190,7 +18278,7 @@ function OhhwellsBridge() {
|
|
|
16190
18278
|
},
|
|
16191
18279
|
[resolveHrefKeyElement]
|
|
16192
18280
|
);
|
|
16193
|
-
const closeLinkPopover = (0,
|
|
18281
|
+
const closeLinkPopover = (0, import_react16.useCallback)(() => {
|
|
16194
18282
|
const session = linkPopoverSessionRef.current;
|
|
16195
18283
|
addNavAfterAnchorRef.current = null;
|
|
16196
18284
|
setLinkPopover(null);
|
|
@@ -16198,9 +18286,9 @@ function OhhwellsBridge() {
|
|
|
16198
18286
|
reselectAfterLinkPopover(session.key);
|
|
16199
18287
|
}
|
|
16200
18288
|
}, [reselectAfterLinkPopover]);
|
|
16201
|
-
const closeLinkPopoverRef = (0,
|
|
18289
|
+
const closeLinkPopoverRef = (0, import_react16.useRef)(closeLinkPopover);
|
|
16202
18290
|
closeLinkPopoverRef.current = closeLinkPopover;
|
|
16203
|
-
const openLinkPopoverForActive = (0,
|
|
18291
|
+
const openLinkPopoverForActive = (0, import_react16.useCallback)(() => {
|
|
16204
18292
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
16205
18293
|
if (!hrefCtx) return;
|
|
16206
18294
|
bumpLinkPopoverGrace();
|
|
@@ -16211,11 +18299,15 @@ function OhhwellsBridge() {
|
|
|
16211
18299
|
});
|
|
16212
18300
|
deactivate();
|
|
16213
18301
|
}, [deactivate]);
|
|
16214
|
-
const openLinkPopoverForSelected = (0,
|
|
18302
|
+
const openLinkPopoverForSelected = (0, import_react16.useCallback)(() => {
|
|
16215
18303
|
const anchor = selectedElRef.current;
|
|
16216
18304
|
if (!anchor) return;
|
|
16217
18305
|
const key = anchor.getAttribute("data-ohw-href-key");
|
|
16218
18306
|
if (!key) return;
|
|
18307
|
+
if (requestSocialDialog(anchor, postToParentRef.current, editContentRef.current)) {
|
|
18308
|
+
deselect();
|
|
18309
|
+
return;
|
|
18310
|
+
}
|
|
16219
18311
|
bumpLinkPopoverGrace();
|
|
16220
18312
|
setLinkPopover({
|
|
16221
18313
|
key,
|
|
@@ -16224,7 +18316,7 @@ function OhhwellsBridge() {
|
|
|
16224
18316
|
});
|
|
16225
18317
|
deselect();
|
|
16226
18318
|
}, [deselect]);
|
|
16227
|
-
const handleSelectParent = (0,
|
|
18319
|
+
const handleSelectParent = (0, import_react16.useCallback)(() => {
|
|
16228
18320
|
const selected = selectedElRef.current;
|
|
16229
18321
|
if (!selected) return;
|
|
16230
18322
|
if (toolbarVariantRef.current === "select-frame") {
|
|
@@ -16251,11 +18343,37 @@ function OhhwellsBridge() {
|
|
|
16251
18343
|
}
|
|
16252
18344
|
deselectRef.current();
|
|
16253
18345
|
}, []);
|
|
16254
|
-
const handleDuplicateSelected = (0,
|
|
18346
|
+
const handleDuplicateSelected = (0, import_react16.useCallback)(() => {
|
|
16255
18347
|
const selected = selectedElRef.current;
|
|
16256
18348
|
if (!selected || !isNavigationItem2(selected)) return;
|
|
16257
18349
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
16258
18350
|
if (!hrefKey) return;
|
|
18351
|
+
const social = getSocialItem(selected);
|
|
18352
|
+
if (social) {
|
|
18353
|
+
const result = duplicateSocialItem(social, editContentRef.current);
|
|
18354
|
+
if (!result) return;
|
|
18355
|
+
const orderJson = JSON.stringify(result.order);
|
|
18356
|
+
const carried = [
|
|
18357
|
+
{ from: result.copiedFrom?.href, to: result.hrefKey },
|
|
18358
|
+
{ from: result.copiedFrom?.icon, to: result.iconKey },
|
|
18359
|
+
{ from: result.copiedFrom?.icon ? socialPlatformKey(result.copiedFrom.icon) : null, to: socialPlatformKey(result.iconKey) }
|
|
18360
|
+
];
|
|
18361
|
+
const nodes = [{ key: SOCIALS_ORDER_KEY, text: orderJson }];
|
|
18362
|
+
for (const { from, to } of carried) {
|
|
18363
|
+
const value = from ? editContentRef.current[from] : void 0;
|
|
18364
|
+
if (value) nodes.push({ key: to, text: value });
|
|
18365
|
+
}
|
|
18366
|
+
editContentRef.current = {
|
|
18367
|
+
...editContentRef.current,
|
|
18368
|
+
...Object.fromEntries(nodes.map((node) => [node.key, node.text]))
|
|
18369
|
+
};
|
|
18370
|
+
postToParent2({ type: "ow:change", nodes });
|
|
18371
|
+
enforceLinkHrefs();
|
|
18372
|
+
const copyRow = findSocialsRow(result.item);
|
|
18373
|
+
if (copyRow) applySocialsDisplayToRow(copyRow, socialsDisplayFor(copyRow, editContentRef.current));
|
|
18374
|
+
requestAnimationFrame(() => selectRef.current(result.item));
|
|
18375
|
+
return;
|
|
18376
|
+
}
|
|
16259
18377
|
if (isNavbarHrefKey(hrefKey)) {
|
|
16260
18378
|
const result = duplicateNavbarItem(selected);
|
|
16261
18379
|
if (!result) return;
|
|
@@ -16341,7 +18459,7 @@ function OhhwellsBridge() {
|
|
|
16341
18459
|
});
|
|
16342
18460
|
}
|
|
16343
18461
|
}, [postToParent2]);
|
|
16344
|
-
const runPendingDeleteUndo = (0,
|
|
18462
|
+
const runPendingDeleteUndo = (0, import_react16.useCallback)(() => {
|
|
16345
18463
|
const pending = pendingDeleteUndoRef.current;
|
|
16346
18464
|
if (!pending) return false;
|
|
16347
18465
|
pendingDeleteUndoRef.current = null;
|
|
@@ -16349,7 +18467,7 @@ function OhhwellsBridge() {
|
|
|
16349
18467
|
enforceLinkHrefs();
|
|
16350
18468
|
return true;
|
|
16351
18469
|
}, []);
|
|
16352
|
-
const handleDeleteSelected = (0,
|
|
18470
|
+
const handleDeleteSelected = (0, import_react16.useCallback)(() => {
|
|
16353
18471
|
const selected = selectedElRef.current;
|
|
16354
18472
|
if (!selected) return false;
|
|
16355
18473
|
return deleteSelectedNavFooterItem({
|
|
@@ -16370,7 +18488,7 @@ function OhhwellsBridge() {
|
|
|
16370
18488
|
}, [postToParent2]);
|
|
16371
18489
|
handleDeleteSelectedRef.current = handleDeleteSelected;
|
|
16372
18490
|
runPendingDeleteUndoRef.current = runPendingDeleteUndo;
|
|
16373
|
-
const handleLinkPopoverSubmit = (0,
|
|
18491
|
+
const handleLinkPopoverSubmit = (0, import_react16.useCallback)(
|
|
16374
18492
|
(target) => {
|
|
16375
18493
|
const session = linkPopoverSessionRef.current;
|
|
16376
18494
|
if (!session) return;
|
|
@@ -16436,19 +18554,19 @@ function OhhwellsBridge() {
|
|
|
16436
18554
|
const showEditLink = toolbarShowEditLink;
|
|
16437
18555
|
const currentSections = sectionsByPath[pathname] ?? [];
|
|
16438
18556
|
linkPopoverOpenRef.current = linkPopover !== null;
|
|
16439
|
-
const handleMediaReplace = (0,
|
|
18557
|
+
const handleMediaReplace = (0, import_react16.useCallback)(
|
|
16440
18558
|
(key) => {
|
|
16441
18559
|
postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
|
|
16442
18560
|
},
|
|
16443
18561
|
[postToParent2, mediaHover?.elementType]
|
|
16444
18562
|
);
|
|
16445
|
-
const handleEditCarousel = (0,
|
|
18563
|
+
const handleEditCarousel = (0, import_react16.useCallback)(
|
|
16446
18564
|
(key) => {
|
|
16447
18565
|
postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
|
|
16448
18566
|
},
|
|
16449
18567
|
[postToParent2]
|
|
16450
18568
|
);
|
|
16451
|
-
const handleMediaFadeOutComplete = (0,
|
|
18569
|
+
const handleMediaFadeOutComplete = (0, import_react16.useCallback)((key) => {
|
|
16452
18570
|
setUploadingRects((prev) => {
|
|
16453
18571
|
if (!(key in prev)) return prev;
|
|
16454
18572
|
const next = { ...prev };
|
|
@@ -16456,7 +18574,7 @@ function OhhwellsBridge() {
|
|
|
16456
18574
|
return next;
|
|
16457
18575
|
});
|
|
16458
18576
|
}, []);
|
|
16459
|
-
const handleVideoSettingsChange = (0,
|
|
18577
|
+
const handleVideoSettingsChange = (0, import_react16.useCallback)(
|
|
16460
18578
|
(key, settings) => {
|
|
16461
18579
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
16462
18580
|
const video = getVideoEl2(el);
|
|
@@ -16479,10 +18597,10 @@ function OhhwellsBridge() {
|
|
|
16479
18597
|
[postToParent2]
|
|
16480
18598
|
);
|
|
16481
18599
|
return bridgeRoot ? (0, import_react_dom4.createPortal)(
|
|
16482
|
-
/* @__PURE__ */ (0,
|
|
16483
|
-
/* @__PURE__ */ (0,
|
|
16484
|
-
isEditMode && /* @__PURE__ */ (0,
|
|
16485
|
-
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0,
|
|
18600
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
|
|
18601
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
18602
|
+
isEditMode && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
|
|
18603
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
16486
18604
|
MediaOverlay,
|
|
16487
18605
|
{
|
|
16488
18606
|
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
@@ -16493,7 +18611,7 @@ function OhhwellsBridge() {
|
|
|
16493
18611
|
},
|
|
16494
18612
|
`uploading-${key}`
|
|
16495
18613
|
)),
|
|
16496
|
-
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0,
|
|
18614
|
+
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
16497
18615
|
MediaOverlay,
|
|
16498
18616
|
{
|
|
16499
18617
|
hover: mediaHover,
|
|
@@ -16502,11 +18620,11 @@ function OhhwellsBridge() {
|
|
|
16502
18620
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
16503
18621
|
}
|
|
16504
18622
|
),
|
|
16505
|
-
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0,
|
|
16506
|
-
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0,
|
|
16507
|
-
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0,
|
|
16508
|
-
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0,
|
|
16509
|
-
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0,
|
|
18623
|
+
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
|
|
18624
|
+
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
18625
|
+
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
18626
|
+
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
18627
|
+
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
16510
18628
|
"div",
|
|
16511
18629
|
{
|
|
16512
18630
|
className: "pointer-events-none fixed z-2147483646",
|
|
@@ -16516,7 +18634,7 @@ function OhhwellsBridge() {
|
|
|
16516
18634
|
width: slot.width,
|
|
16517
18635
|
height: slot.height
|
|
16518
18636
|
},
|
|
16519
|
-
children: /* @__PURE__ */ (0,
|
|
18637
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
16520
18638
|
DropIndicator,
|
|
16521
18639
|
{
|
|
16522
18640
|
direction: slot.direction,
|
|
@@ -16527,7 +18645,7 @@ function OhhwellsBridge() {
|
|
|
16527
18645
|
},
|
|
16528
18646
|
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
16529
18647
|
)),
|
|
16530
|
-
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0,
|
|
18648
|
+
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
16531
18649
|
"div",
|
|
16532
18650
|
{
|
|
16533
18651
|
className: "pointer-events-none fixed z-2147483646",
|
|
@@ -16537,7 +18655,7 @@ function OhhwellsBridge() {
|
|
|
16537
18655
|
width: slot.width,
|
|
16538
18656
|
height: slot.height
|
|
16539
18657
|
},
|
|
16540
|
-
children: /* @__PURE__ */ (0,
|
|
18658
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
16541
18659
|
DropIndicator,
|
|
16542
18660
|
{
|
|
16543
18661
|
direction: slot.direction,
|
|
@@ -16548,10 +18666,11 @@ function OhhwellsBridge() {
|
|
|
16548
18666
|
},
|
|
16549
18667
|
`nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
|
|
16550
18668
|
)),
|
|
16551
|
-
hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0,
|
|
16552
|
-
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0,
|
|
16553
|
-
|
|
16554
|
-
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current &&
|
|
18669
|
+
hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
18670
|
+
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
18671
|
+
hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
|
|
18672
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
|
|
18673
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
16555
18674
|
FooterContainerChrome,
|
|
16556
18675
|
{
|
|
16557
18676
|
rect: toolbarRect,
|
|
@@ -16559,7 +18678,7 @@ function OhhwellsBridge() {
|
|
|
16559
18678
|
addDisabled: !canAddFooterColumn()
|
|
16560
18679
|
}
|
|
16561
18680
|
),
|
|
16562
|
-
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0,
|
|
18681
|
+
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
16563
18682
|
ItemInteractionLayer,
|
|
16564
18683
|
{
|
|
16565
18684
|
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
|
|
@@ -16571,26 +18690,34 @@ function OhhwellsBridge() {
|
|
|
16571
18690
|
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
16572
18691
|
onDragHandleDragStart: handleItemDragStart,
|
|
16573
18692
|
onDragHandleDragEnd: handleItemDragEnd,
|
|
16574
|
-
onItemPointerDown: handleItemChromePointerDown,
|
|
16575
|
-
onItemClick: handleItemChromeClick,
|
|
16576
|
-
itemDragSurface: !isFooterFrameSelection,
|
|
16577
|
-
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && isFooterFrameSelection && !isItemDragging ? /* @__PURE__ */ (0,
|
|
18693
|
+
onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
|
|
18694
|
+
onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
|
|
18695
|
+
itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
|
|
18696
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
16578
18697
|
ItemActionToolbar,
|
|
16579
18698
|
{
|
|
16580
18699
|
onEditLink: openLinkPopoverForSelected,
|
|
18700
|
+
onStyle: () => {
|
|
18701
|
+
const row = selectedElRef.current;
|
|
18702
|
+
if (!row) return;
|
|
18703
|
+
if (floatingPanel?.kind === "socials-display") closeFloatingPanelOnly();
|
|
18704
|
+
else openSocialsDisplayPanel(row);
|
|
18705
|
+
},
|
|
18706
|
+
showStyle: selectedIsSocialsRow,
|
|
18707
|
+
styleActive: floatingPanel?.kind === "socials-display",
|
|
16581
18708
|
onAddItem: handleAddChildItem,
|
|
16582
18709
|
onSelectParent: handleSelectParent,
|
|
16583
18710
|
onDuplicate: handleDuplicateSelected,
|
|
16584
18711
|
onDelete: handleDeleteSelected,
|
|
16585
|
-
addItemDisabled:
|
|
18712
|
+
addItemDisabled: isFooterFrameSelection && isFooterAddItemDisabled(selectedElRef.current),
|
|
16586
18713
|
editLinkDisabled: false,
|
|
16587
18714
|
moreDisabled: false,
|
|
16588
|
-
duplicateDisabled: isFooterFrameSelection,
|
|
16589
|
-
showEditLink: !isFooterFrameSelection && navDropdownPreviewOpen === null,
|
|
16590
|
-
showAddItem: isFooterFrameSelection || !selectedIsCta && Boolean(
|
|
18715
|
+
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow,
|
|
18716
|
+
showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
|
|
18717
|
+
showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
|
|
16591
18718
|
selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
|
|
16592
18719
|
),
|
|
16593
|
-
showMore: !selectedIsCta || isFooterFrameSelection,
|
|
18720
|
+
showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
|
|
16594
18721
|
dropdownOpen: navDropdownPreviewOpen,
|
|
16595
18722
|
onDropdownOpenChange: handleNavDropdownOpenChange,
|
|
16596
18723
|
headingVisible: footerHeadingVisible,
|
|
@@ -16599,8 +18726,8 @@ function OhhwellsBridge() {
|
|
|
16599
18726
|
) : void 0
|
|
16600
18727
|
}
|
|
16601
18728
|
),
|
|
16602
|
-
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0,
|
|
16603
|
-
/* @__PURE__ */ (0,
|
|
18729
|
+
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
|
|
18730
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
16604
18731
|
EditGlowChrome,
|
|
16605
18732
|
{
|
|
16606
18733
|
rect: toolbarRect,
|
|
@@ -16610,7 +18737,7 @@ function OhhwellsBridge() {
|
|
|
16610
18737
|
hideHandle: isItemDragging
|
|
16611
18738
|
}
|
|
16612
18739
|
),
|
|
16613
|
-
/* @__PURE__ */ (0,
|
|
18740
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
16614
18741
|
FloatingToolbar,
|
|
16615
18742
|
{
|
|
16616
18743
|
rect: toolbarRect,
|
|
@@ -16623,7 +18750,7 @@ function OhhwellsBridge() {
|
|
|
16623
18750
|
}
|
|
16624
18751
|
)
|
|
16625
18752
|
] }),
|
|
16626
|
-
maxBadge && /* @__PURE__ */ (0,
|
|
18753
|
+
maxBadge && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
16627
18754
|
"div",
|
|
16628
18755
|
{
|
|
16629
18756
|
"data-ohw-max-badge": "",
|
|
@@ -16649,7 +18776,7 @@ function OhhwellsBridge() {
|
|
|
16649
18776
|
]
|
|
16650
18777
|
}
|
|
16651
18778
|
),
|
|
16652
|
-
toggleState && !linkPopover && /* @__PURE__ */ (0,
|
|
18779
|
+
toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
16653
18780
|
StateToggle,
|
|
16654
18781
|
{
|
|
16655
18782
|
rect: toggleState.rect,
|
|
@@ -16658,15 +18785,15 @@ function OhhwellsBridge() {
|
|
|
16658
18785
|
onStateChange: handleStateChange
|
|
16659
18786
|
}
|
|
16660
18787
|
),
|
|
16661
|
-
sectionGap && !linkPopover && /* @__PURE__ */ (0,
|
|
18788
|
+
sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
16662
18789
|
"div",
|
|
16663
18790
|
{
|
|
16664
18791
|
"data-ohw-section-insert-line": "",
|
|
16665
18792
|
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
16666
18793
|
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
16667
18794
|
children: [
|
|
16668
|
-
/* @__PURE__ */ (0,
|
|
16669
|
-
/* @__PURE__ */ (0,
|
|
18795
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
18796
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
16670
18797
|
Badge,
|
|
16671
18798
|
{
|
|
16672
18799
|
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",
|
|
@@ -16683,11 +18810,11 @@ function OhhwellsBridge() {
|
|
|
16683
18810
|
children: "Add Section"
|
|
16684
18811
|
}
|
|
16685
18812
|
),
|
|
16686
|
-
/* @__PURE__ */ (0,
|
|
18813
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
16687
18814
|
]
|
|
16688
18815
|
}
|
|
16689
18816
|
),
|
|
16690
|
-
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0,
|
|
18817
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
16691
18818
|
LinkPopover,
|
|
16692
18819
|
{
|
|
16693
18820
|
panelRef: linkPopoverPanelRef,
|
|
@@ -16703,11 +18830,137 @@ function OhhwellsBridge() {
|
|
|
16703
18830
|
onSubmit: handleLinkPopoverSubmit
|
|
16704
18831
|
},
|
|
16705
18832
|
linkPopover.key
|
|
18833
|
+
) : null,
|
|
18834
|
+
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
18835
|
+
FloatingPanel,
|
|
18836
|
+
{
|
|
18837
|
+
open: true,
|
|
18838
|
+
title: floatingPanel.title,
|
|
18839
|
+
context: floatingPanel.context,
|
|
18840
|
+
position: floatingPanelPos,
|
|
18841
|
+
onPositionChange: setFloatingPanelPos,
|
|
18842
|
+
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
18843
|
+
onClose: closeFloatingPanelOnly,
|
|
18844
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
18845
|
+
SocialsDisplayPanel,
|
|
18846
|
+
{
|
|
18847
|
+
display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
|
|
18848
|
+
onChange: (next) => {
|
|
18849
|
+
changeSocialsDisplay(floatingPanel.row, next);
|
|
18850
|
+
setFloatingPanel({ ...floatingPanel });
|
|
18851
|
+
}
|
|
18852
|
+
}
|
|
18853
|
+
)
|
|
18854
|
+
}
|
|
18855
|
+
) : null,
|
|
18856
|
+
floatingPanel && floatingPanel.kind === "logo-size" && logoSizeDraft ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
18857
|
+
FloatingPanel,
|
|
18858
|
+
{
|
|
18859
|
+
open: true,
|
|
18860
|
+
title: floatingPanel.title,
|
|
18861
|
+
context: floatingPanel.context,
|
|
18862
|
+
position: floatingPanelPos,
|
|
18863
|
+
onPositionChange: setFloatingPanelPos,
|
|
18864
|
+
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
18865
|
+
onClose: closeFloatingPanelAndDeselect,
|
|
18866
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
18867
|
+
LogoSizePanel,
|
|
18868
|
+
{
|
|
18869
|
+
viewport: editorViewport,
|
|
18870
|
+
sizePx: editorViewport === "mobile" && !logoSizeDraft.mobileFollowing ? logoSizeDraft.mobilePx : logoSizeDraft.desktopPx,
|
|
18871
|
+
mobileFollowing: logoSizeDraft.mobileFollowing,
|
|
18872
|
+
onSizeChange: (px) => {
|
|
18873
|
+
const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px, mobileFollowing: false } : {
|
|
18874
|
+
...logoSizeDraft,
|
|
18875
|
+
desktopPx: px,
|
|
18876
|
+
mobilePx: logoSizeDraft.mobileFollowing ? px : logoSizeDraft.mobilePx
|
|
18877
|
+
};
|
|
18878
|
+
setLogoSizeDraft(next);
|
|
18879
|
+
persistLogoSizeDraft(floatingPanel.placement, next);
|
|
18880
|
+
},
|
|
18881
|
+
onCustomizeMobile: () => {
|
|
18882
|
+
const next = {
|
|
18883
|
+
...logoSizeDraft,
|
|
18884
|
+
mobileFollowing: false,
|
|
18885
|
+
mobilePx: logoSizeDraft.desktopPx
|
|
18886
|
+
};
|
|
18887
|
+
setLogoSizeDraft(next);
|
|
18888
|
+
persistLogoSizeDraft(floatingPanel.placement, next);
|
|
18889
|
+
},
|
|
18890
|
+
onResetMobile: () => {
|
|
18891
|
+
const next = {
|
|
18892
|
+
...logoSizeDraft,
|
|
18893
|
+
mobileFollowing: true,
|
|
18894
|
+
mobilePx: logoSizeDraft.desktopPx
|
|
18895
|
+
};
|
|
18896
|
+
setLogoSizeDraft(next);
|
|
18897
|
+
persistLogoSizeDraft(floatingPanel.placement, next);
|
|
18898
|
+
},
|
|
18899
|
+
onUpdateEverywhere: () => {
|
|
18900
|
+
const identity = readLogoIdentityFromDom();
|
|
18901
|
+
postToParent2({ type: "ow:open-logo-settings", ...identity });
|
|
18902
|
+
}
|
|
18903
|
+
}
|
|
18904
|
+
)
|
|
18905
|
+
}
|
|
16706
18906
|
) : null
|
|
16707
18907
|
] }),
|
|
16708
18908
|
bridgeRoot
|
|
16709
18909
|
) : null;
|
|
16710
18910
|
}
|
|
18911
|
+
|
|
18912
|
+
// src/ui/EmptySection.tsx
|
|
18913
|
+
var import_link = __toESM(require("next/link"), 1);
|
|
18914
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
18915
|
+
function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
|
|
18916
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
|
|
18917
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
18918
|
+
"p",
|
|
18919
|
+
{
|
|
18920
|
+
style: {
|
|
18921
|
+
fontFamily: "var(--brand-font-body)",
|
|
18922
|
+
fontSize: "0.75rem",
|
|
18923
|
+
fontWeight: 500,
|
|
18924
|
+
letterSpacing: "0.15em",
|
|
18925
|
+
textTransform: "uppercase",
|
|
18926
|
+
color: "var(--brand-accent)",
|
|
18927
|
+
marginBottom: "1.5rem"
|
|
18928
|
+
},
|
|
18929
|
+
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" }) })
|
|
18930
|
+
}
|
|
18931
|
+
),
|
|
18932
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
18933
|
+
"h1",
|
|
18934
|
+
{
|
|
18935
|
+
style: {
|
|
18936
|
+
fontFamily: "var(--brand-font-heading)",
|
|
18937
|
+
fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
|
|
18938
|
+
lineHeight: 1.1,
|
|
18939
|
+
letterSpacing: "-0.025em",
|
|
18940
|
+
color: "var(--brand-text)",
|
|
18941
|
+
marginBottom: "1rem"
|
|
18942
|
+
},
|
|
18943
|
+
...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
|
|
18944
|
+
children: title
|
|
18945
|
+
}
|
|
18946
|
+
),
|
|
18947
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
18948
|
+
"p",
|
|
18949
|
+
{
|
|
18950
|
+
style: {
|
|
18951
|
+
fontFamily: "var(--brand-font-body)",
|
|
18952
|
+
fontSize: "1rem",
|
|
18953
|
+
lineHeight: 1.7,
|
|
18954
|
+
fontWeight: 300,
|
|
18955
|
+
color: "var(--brand-text-muted)",
|
|
18956
|
+
maxWidth: "340px"
|
|
18957
|
+
},
|
|
18958
|
+
...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
|
|
18959
|
+
children: "This page doesn't have any content yet."
|
|
18960
|
+
}
|
|
18961
|
+
)
|
|
18962
|
+
] });
|
|
18963
|
+
}
|
|
16711
18964
|
// Annotate the CommonJS export names for ESM import in node:
|
|
16712
18965
|
0 && (module.exports = {
|
|
16713
18966
|
AI_DEFAULT_BRAND,
|
|
@@ -16725,6 +18978,7 @@ function OhhwellsBridge() {
|
|
|
16725
18978
|
DropdownMenuItem,
|
|
16726
18979
|
DropdownMenuSeparator,
|
|
16727
18980
|
DropdownMenuTrigger,
|
|
18981
|
+
EmptySection,
|
|
16728
18982
|
ItemActionToolbar,
|
|
16729
18983
|
ItemInteractionLayer,
|
|
16730
18984
|
LinkEditorPanel,
|