@ohhwells/bridge 0.1.57 → 0.1.59-next.170
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 +1437 -177
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +1434 -175
- 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 +58 -0
- package/package.json +6 -1
package/dist/index.js
CHANGED
|
@@ -118,6 +118,129 @@ function deleteSectionFromState(state, sectionId) {
|
|
|
118
118
|
return { ...state, v: 1, sections: state.sections, removed: [...removed, sectionId] };
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
+
// src/lib/brand-chrome.ts
|
|
122
|
+
var BRAND_NAME_KEY = "__ohw_brand_name";
|
|
123
|
+
var BRAND_TITLE_KEY = "__ohw_site_title";
|
|
124
|
+
var BRAND_FAVICON_LETTER_KEY = "__ohw_favicon_letter";
|
|
125
|
+
var BRAND_CHROME_KEYS = /* @__PURE__ */ new Set([
|
|
126
|
+
BRAND_NAME_KEY,
|
|
127
|
+
BRAND_TITLE_KEY,
|
|
128
|
+
BRAND_FAVICON_LETTER_KEY
|
|
129
|
+
]);
|
|
130
|
+
function upsertMeta(selector, attr, token, value) {
|
|
131
|
+
let el = document.head.querySelector(selector);
|
|
132
|
+
if (!el) {
|
|
133
|
+
el = document.createElement("meta");
|
|
134
|
+
el.setAttribute(attr, token);
|
|
135
|
+
document.head.appendChild(el);
|
|
136
|
+
}
|
|
137
|
+
if (el.getAttribute("content") !== value) el.setAttribute("content", value);
|
|
138
|
+
}
|
|
139
|
+
function escapeXml(value) {
|
|
140
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
141
|
+
}
|
|
142
|
+
function applyLetterFavicon(letter) {
|
|
143
|
+
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>`;
|
|
144
|
+
const href = `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
|
145
|
+
let link = document.head.querySelector('link[rel="icon"]');
|
|
146
|
+
if (!link) {
|
|
147
|
+
link = document.createElement("link");
|
|
148
|
+
link.rel = "icon";
|
|
149
|
+
document.head.appendChild(link);
|
|
150
|
+
}
|
|
151
|
+
link.type = "image/svg+xml";
|
|
152
|
+
if (link.href !== href) link.href = href;
|
|
153
|
+
}
|
|
154
|
+
function applyBrandChrome(content) {
|
|
155
|
+
const name = content[BRAND_NAME_KEY];
|
|
156
|
+
if (typeof name === "string" && name.length > 0) {
|
|
157
|
+
document.querySelectorAll("[data-ohw-wordmark]").forEach((el) => {
|
|
158
|
+
if (el.textContent !== name) el.textContent = name;
|
|
159
|
+
if (el.getAttribute("title") !== name) el.setAttribute("title", name);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
const title = content[BRAND_TITLE_KEY];
|
|
163
|
+
if (typeof title === "string" && title.length > 0) {
|
|
164
|
+
if (document.title !== title) document.title = title;
|
|
165
|
+
upsertMeta('meta[property="og:title"]', "property", "og:title", title);
|
|
166
|
+
upsertMeta('meta[name="twitter:title"]', "name", "twitter:title", title);
|
|
167
|
+
}
|
|
168
|
+
const letter = content[BRAND_FAVICON_LETTER_KEY];
|
|
169
|
+
if (typeof letter === "string" && letter.length > 0) {
|
|
170
|
+
applyLetterFavicon(letter);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// src/lib/brand-kit.ts
|
|
175
|
+
var BRAND_KIT_KEY = "__ohw_brand";
|
|
176
|
+
var BRAND_VAR_PREFIX = "--ohw-brand-";
|
|
177
|
+
var BRAND_VAR_NAMES = ["primary", "accent", "light", "dark", "surface", "border", "muted"].map(
|
|
178
|
+
(role) => `${BRAND_VAR_PREFIX}${role}`
|
|
179
|
+
);
|
|
180
|
+
var FONT_VARS = { heading: ["--font-heading", "--font-display"], body: ["--font-body"] };
|
|
181
|
+
var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
|
|
182
|
+
function brandColorVars(kit) {
|
|
183
|
+
const { dark, primary, accent, light } = kit.palette;
|
|
184
|
+
const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
|
|
185
|
+
return {
|
|
186
|
+
[`${BRAND_VAR_PREFIX}primary`]: primary,
|
|
187
|
+
[`${BRAND_VAR_PREFIX}accent`]: accent,
|
|
188
|
+
[`${BRAND_VAR_PREFIX}light`]: light,
|
|
189
|
+
[`${BRAND_VAR_PREFIX}dark`]: dark,
|
|
190
|
+
[`${BRAND_VAR_PREFIX}surface`]: mix(light, 95, dark),
|
|
191
|
+
[`${BRAND_VAR_PREFIX}border`]: mix(light, 85, dark),
|
|
192
|
+
[`${BRAND_VAR_PREFIX}muted`]: mix(dark, 62, light)
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function parseBrandKit(raw) {
|
|
196
|
+
if (!raw) return null;
|
|
197
|
+
try {
|
|
198
|
+
const parsed = JSON.parse(raw);
|
|
199
|
+
const p = parsed?.palette;
|
|
200
|
+
const f = parsed?.fonts;
|
|
201
|
+
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") {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
palette: { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light },
|
|
206
|
+
fonts: { heading: f.heading, body: f.body }
|
|
207
|
+
};
|
|
208
|
+
} catch {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
function familyOf(stack) {
|
|
213
|
+
const first = stack.split(",")[0]?.trim() ?? "";
|
|
214
|
+
return first.replace(/^['"]|['"]$/g, "");
|
|
215
|
+
}
|
|
216
|
+
function loadBrandFonts(families) {
|
|
217
|
+
const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
|
|
218
|
+
if (unique.length === 0) return;
|
|
219
|
+
const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
|
|
220
|
+
const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
|
|
221
|
+
let link = document.getElementById(BRAND_FONT_LINK_ID);
|
|
222
|
+
if (!link) {
|
|
223
|
+
link = document.createElement("link");
|
|
224
|
+
link.id = BRAND_FONT_LINK_ID;
|
|
225
|
+
link.rel = "stylesheet";
|
|
226
|
+
document.head.appendChild(link);
|
|
227
|
+
}
|
|
228
|
+
if (link.href !== href) link.href = href;
|
|
229
|
+
}
|
|
230
|
+
function applyBrandToDom(kit) {
|
|
231
|
+
const root = document.documentElement;
|
|
232
|
+
if (!kit) {
|
|
233
|
+
for (const name of BRAND_VAR_NAMES) root.style.removeProperty(name);
|
|
234
|
+
for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
|
|
235
|
+
document.getElementById(BRAND_FONT_LINK_ID)?.remove();
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
for (const [name, value] of Object.entries(brandColorVars(kit))) root.style.setProperty(name, value);
|
|
239
|
+
for (const name of FONT_VARS.heading) root.style.setProperty(name, kit.fonts.heading);
|
|
240
|
+
for (const name of FONT_VARS.body) root.style.setProperty(name, kit.fonts.body);
|
|
241
|
+
loadBrandFonts([familyOf(kit.fonts.heading), familyOf(kit.fonts.body)]);
|
|
242
|
+
}
|
|
243
|
+
|
|
121
244
|
// src/ui/ai-tree/aiSectionsManager.tsx
|
|
122
245
|
import { flushSync } from "react-dom";
|
|
123
246
|
import { createRoot } from "react-dom/client";
|
|
@@ -150,6 +273,17 @@ var FEATURE_LINE_CSS = [
|
|
|
150
273
|
function textAttrs(ctx, path) {
|
|
151
274
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
152
275
|
}
|
|
276
|
+
var AI_RESPONSIVE_CSS = [
|
|
277
|
+
"@media (max-width: 960px) {",
|
|
278
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
|
|
279
|
+
' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
|
|
280
|
+
"}",
|
|
281
|
+
"@media (max-width: 640px) {",
|
|
282
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
283
|
+
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
284
|
+
" [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
285
|
+
"}"
|
|
286
|
+
].join("\n");
|
|
153
287
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
154
288
|
function MediaBox({
|
|
155
289
|
refValue,
|
|
@@ -892,6 +1026,7 @@ function Carousel({ items, itemsPerRow, ctx }) {
|
|
|
892
1026
|
children: pageGroups.map((group, p) => /* @__PURE__ */ jsx(
|
|
893
1027
|
"div",
|
|
894
1028
|
{
|
|
1029
|
+
"data-ai-grid": String(itemsPerRow),
|
|
895
1030
|
style: {
|
|
896
1031
|
flex: "0 0 100%",
|
|
897
1032
|
display: "grid",
|
|
@@ -995,6 +1130,7 @@ function CollectionBlock({ node, ctx, path }) {
|
|
|
995
1130
|
return /* @__PURE__ */ jsx(
|
|
996
1131
|
"div",
|
|
997
1132
|
{
|
|
1133
|
+
"data-ai-grid": String(itemsPerRow),
|
|
998
1134
|
style: {
|
|
999
1135
|
display: "grid",
|
|
1000
1136
|
gridTemplateColumns: `repeat(${itemsPerRow}, 1fr)`,
|
|
@@ -1158,6 +1294,7 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1158
1294
|
{
|
|
1159
1295
|
"data-ai-section": tree.tag ?? "",
|
|
1160
1296
|
...bgAttrs,
|
|
1297
|
+
"data-ai-responsive": "",
|
|
1161
1298
|
style: {
|
|
1162
1299
|
position: "relative",
|
|
1163
1300
|
padding: `${pad}px 0`,
|
|
@@ -1167,10 +1304,12 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1167
1304
|
backgroundPosition: "center"
|
|
1168
1305
|
},
|
|
1169
1306
|
children: [
|
|
1307
|
+
/* @__PURE__ */ jsx("style", { children: AI_RESPONSIVE_CSS }),
|
|
1170
1308
|
isOverlay && backgroundUrl && /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
1171
1309
|
/* @__PURE__ */ jsx(
|
|
1172
1310
|
"div",
|
|
1173
1311
|
{
|
|
1312
|
+
"data-ai-section-inner": "",
|
|
1174
1313
|
style: {
|
|
1175
1314
|
position: "relative",
|
|
1176
1315
|
maxWidth: AI_TREE_TOKENS.sectionMaxWidth,
|
|
@@ -1181,6 +1320,7 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1181
1320
|
children: tree.rows.map((row, r2) => /* @__PURE__ */ jsx(
|
|
1182
1321
|
"div",
|
|
1183
1322
|
{
|
|
1323
|
+
"data-ai-columns": "",
|
|
1184
1324
|
style: {
|
|
1185
1325
|
display: "grid",
|
|
1186
1326
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
@@ -1204,17 +1344,34 @@ import { jsx as jsx2 } from "react/jsx-runtime";
|
|
|
1204
1344
|
var CONTAINER_ATTR = "data-ohw-ai-generated";
|
|
1205
1345
|
var REPLACED_ATTR = "data-ohw-ai-replaced-by";
|
|
1206
1346
|
var REMOVED_ATTR = "data-ohw-ai-removed";
|
|
1347
|
+
function readRootVar(name) {
|
|
1348
|
+
if (typeof document === "undefined") return "";
|
|
1349
|
+
return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
|
|
1350
|
+
}
|
|
1351
|
+
function deriveBrandOverride() {
|
|
1352
|
+
const dark = readRootVar("--ohw-brand-dark");
|
|
1353
|
+
const primary = readRootVar("--ohw-brand-primary");
|
|
1354
|
+
const light = readRootVar("--ohw-brand-light");
|
|
1355
|
+
if (!dark || !primary || !light) return null;
|
|
1356
|
+
const accent = readRootVar("--ohw-brand-accent");
|
|
1357
|
+
const heading = readRootVar("--font-heading") || readRootVar("--font-display");
|
|
1358
|
+
const body = readRootVar("--font-body");
|
|
1359
|
+
return {
|
|
1360
|
+
palette: { dark, primary, accent: accent || dark, light },
|
|
1361
|
+
fonts: {
|
|
1362
|
+
heading: heading || AI_DEFAULT_BRAND.fonts.heading,
|
|
1363
|
+
body: body || AI_DEFAULT_BRAND.fonts.body
|
|
1364
|
+
}
|
|
1365
|
+
};
|
|
1366
|
+
}
|
|
1207
1367
|
function deriveTemplateBrand() {
|
|
1208
|
-
|
|
1209
|
-
const
|
|
1210
|
-
const
|
|
1211
|
-
const dark = read("--color-dark");
|
|
1212
|
-
const primary = read("--color-primary");
|
|
1213
|
-
const light = read("--color-light");
|
|
1368
|
+
const dark = readRootVar("--color-dark");
|
|
1369
|
+
const primary = readRootVar("--color-primary");
|
|
1370
|
+
const light = readRootVar("--color-light");
|
|
1214
1371
|
if (!dark || !primary || !light) return null;
|
|
1215
|
-
const accent =
|
|
1216
|
-
const heading =
|
|
1217
|
-
const body =
|
|
1372
|
+
const accent = readRootVar("--color-accent");
|
|
1373
|
+
const heading = readRootVar("--font-heading") || readRootVar("--font-display");
|
|
1374
|
+
const body = readRootVar("--font-body");
|
|
1218
1375
|
return {
|
|
1219
1376
|
palette: { dark, primary, accent: accent || dark, light },
|
|
1220
1377
|
fonts: {
|
|
@@ -1306,7 +1463,9 @@ function syncReplacedOriginals(state) {
|
|
|
1306
1463
|
}
|
|
1307
1464
|
function applyAiSectionsToDom(state, options) {
|
|
1308
1465
|
if (typeof document === "undefined") return;
|
|
1466
|
+
const brandOverride = deriveBrandOverride();
|
|
1309
1467
|
const templateBrand = deriveTemplateBrand();
|
|
1468
|
+
const brandKey = brandOverride ? JSON.stringify(brandOverride) : "";
|
|
1310
1469
|
const activeIds = new Set(state.sections.map((entry) => entry.id));
|
|
1311
1470
|
for (const [id, section] of mounted) {
|
|
1312
1471
|
if (!activeIds.has(id)) {
|
|
@@ -1316,7 +1475,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1316
1475
|
}
|
|
1317
1476
|
}
|
|
1318
1477
|
for (const entry of state.sections) {
|
|
1319
|
-
const serialized = JSON.stringify(entry);
|
|
1478
|
+
const serialized = JSON.stringify(entry) + brandKey;
|
|
1320
1479
|
const existing = mounted.get(entry.id);
|
|
1321
1480
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
1322
1481
|
continue;
|
|
@@ -1330,6 +1489,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1330
1489
|
mounted.delete(entry.id);
|
|
1331
1490
|
}
|
|
1332
1491
|
container.setAttribute("data-ohw-section", entry.id);
|
|
1492
|
+
container.setAttribute("data-ohw-instance", entry.id);
|
|
1333
1493
|
container.setAttribute("data-ohw-section-label", entry.label);
|
|
1334
1494
|
placeContainer(container, entry);
|
|
1335
1495
|
const root = mounted.get(entry.id)?.root ?? createRoot(container);
|
|
@@ -1340,7 +1500,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1340
1500
|
AiTreeRenderer,
|
|
1341
1501
|
{
|
|
1342
1502
|
tree: entry.tree,
|
|
1343
|
-
brand: entry.brand ?? options?.brand ?? templateBrand ?? void 0,
|
|
1503
|
+
brand: brandOverride ?? entry.brand ?? options?.brand ?? templateBrand ?? void 0,
|
|
1344
1504
|
resolveMedia,
|
|
1345
1505
|
editKeyPrefix: `ai.${entry.id}`
|
|
1346
1506
|
}
|
|
@@ -1957,7 +2117,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
1957
2117
|
const autoId = useId();
|
|
1958
2118
|
const insertAfter = insertAfterProp ?? autoId;
|
|
1959
2119
|
const [schedule, setSchedule] = useState2(null);
|
|
1960
|
-
const [loading, setLoading] = useState2(
|
|
2120
|
+
const [loading, setLoading] = useState2(initialScheduleId !== null);
|
|
1961
2121
|
const [inEditor, setInEditor] = useState2(false);
|
|
1962
2122
|
const [isHovered, setIsHovered] = useState2(false);
|
|
1963
2123
|
const [modalState, setModalState] = useState2(null);
|
|
@@ -2131,8 +2291,10 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
2131
2291
|
"*"
|
|
2132
2292
|
);
|
|
2133
2293
|
};
|
|
2134
|
-
if (!inEditor && !loading && !schedule) return null;
|
|
2135
2294
|
const sectionId = `scheduling-${insertAfter}`;
|
|
2295
|
+
if (!inEditor && !loading && !schedule) {
|
|
2296
|
+
return /* @__PURE__ */ jsx4("section", { "data-ohw-section": sectionId, "data-ohw-scheduling-anchor": insertAfter, style: { display: "none" } });
|
|
2297
|
+
}
|
|
2136
2298
|
return /* @__PURE__ */ jsxs3(
|
|
2137
2299
|
"section",
|
|
2138
2300
|
{
|
|
@@ -6086,6 +6248,7 @@ var FOCUS_RING = `0 0 0 4px color-mix(in srgb, ${PRIMARY} 12%, transparent)`;
|
|
|
6086
6248
|
var DRAG_SHADOW = "0px 4px 6px -1px rgba(0, 0, 0, 0.1), 0px 2px 4px -2px rgba(0, 0, 0, 0.1)";
|
|
6087
6249
|
var TOOLBAR_EDGE_MARGIN = 4;
|
|
6088
6250
|
var SELECTION_CHROME_GAP = 4;
|
|
6251
|
+
var HOVER_CHROME_GAP = 2;
|
|
6089
6252
|
var TOOLBAR_STROKE_GAP = 4;
|
|
6090
6253
|
function getChromeZIndex(state) {
|
|
6091
6254
|
switch (state) {
|
|
@@ -6241,10 +6404,11 @@ function ItemInteractionLayer({
|
|
|
6241
6404
|
onItemPointerDown,
|
|
6242
6405
|
onItemClick,
|
|
6243
6406
|
itemDragSurface = true,
|
|
6244
|
-
chromeGap
|
|
6407
|
+
chromeGap,
|
|
6245
6408
|
className
|
|
6246
6409
|
}) {
|
|
6247
6410
|
if (state === "default") return null;
|
|
6411
|
+
const gap = chromeGap ?? (state === "hover" ? HOVER_CHROME_GAP : SELECTION_CHROME_GAP);
|
|
6248
6412
|
const isActive = state === "active-top" || state === "active-bottom";
|
|
6249
6413
|
const isDragging = state === "dragging";
|
|
6250
6414
|
const showToolbar = isActive && toolbar;
|
|
@@ -6260,10 +6424,10 @@ function ItemInteractionLayer({
|
|
|
6260
6424
|
className: cn("pointer-events-none", className),
|
|
6261
6425
|
style: {
|
|
6262
6426
|
position: "fixed",
|
|
6263
|
-
top: rect.top -
|
|
6264
|
-
left: rect.left -
|
|
6265
|
-
width: rect.width +
|
|
6266
|
-
height: rect.height +
|
|
6427
|
+
top: rect.top - gap,
|
|
6428
|
+
left: rect.left - gap,
|
|
6429
|
+
width: rect.width + gap * 2,
|
|
6430
|
+
height: rect.height + gap * 2,
|
|
6267
6431
|
zIndex: getChromeZIndex(state)
|
|
6268
6432
|
},
|
|
6269
6433
|
children: [
|
|
@@ -6649,8 +6813,12 @@ function parseSectionsFromHtml(html) {
|
|
|
6649
6813
|
|
|
6650
6814
|
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
6651
6815
|
import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
6652
|
-
function
|
|
6653
|
-
const
|
|
6816
|
+
function findSectionElement(instanceId) {
|
|
6817
|
+
const escaped = CSS.escape(instanceId);
|
|
6818
|
+
return document.querySelector(`[data-ohw-instance="${escaped}"]`) ?? document.querySelector(`[data-ohw-section="${escaped}"]:not([data-ohw-instance])`);
|
|
6819
|
+
}
|
|
6820
|
+
function readRect(instanceId) {
|
|
6821
|
+
const el = findSectionElement(instanceId);
|
|
6654
6822
|
if (!el) return null;
|
|
6655
6823
|
const r2 = el.getBoundingClientRect();
|
|
6656
6824
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
@@ -6673,7 +6841,7 @@ function useLiveSectionRect(sectionId) {
|
|
|
6673
6841
|
const opts = { capture: true, passive: true };
|
|
6674
6842
|
window.addEventListener("scroll", update, opts);
|
|
6675
6843
|
window.addEventListener("resize", update);
|
|
6676
|
-
const el =
|
|
6844
|
+
const el = findSectionElement(sectionId);
|
|
6677
6845
|
const ro = el ? new ResizeObserver(update) : null;
|
|
6678
6846
|
if (el && ro) ro.observe(el);
|
|
6679
6847
|
const interval = setInterval(update, 500);
|
|
@@ -6686,6 +6854,14 @@ function useLiveSectionRect(sectionId) {
|
|
|
6686
6854
|
}, [sectionId]);
|
|
6687
6855
|
return rect;
|
|
6688
6856
|
}
|
|
6857
|
+
function computeSectionBoundaryFlags(instanceId) {
|
|
6858
|
+
const topLevel = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
6859
|
+
(el) => !el.parentElement?.closest("[data-ohw-section]")
|
|
6860
|
+
);
|
|
6861
|
+
const index = topLevel.findIndex((el) => (el.dataset.ohwInstance ?? el.dataset.ohwSection) === instanceId);
|
|
6862
|
+
if (index === -1) return { isFirst: true, isLast: true };
|
|
6863
|
+
return { isFirst: index === 0, isLast: index === topLevel.length - 1 };
|
|
6864
|
+
}
|
|
6689
6865
|
var PRIMARY2 = "#0885FE";
|
|
6690
6866
|
function edgeAwareRadius(rect) {
|
|
6691
6867
|
const container = window.innerWidth <= 480 ? 16 : 24;
|
|
@@ -6767,7 +6943,7 @@ function AiSectionOverlay({
|
|
|
6767
6943
|
(el) => {
|
|
6768
6944
|
postToParent2({
|
|
6769
6945
|
type: "ow:section-selected",
|
|
6770
|
-
sectionId: el
|
|
6946
|
+
sectionId: el ? el.dataset.ohwInstance ?? el.dataset.ohwSection ?? null : null,
|
|
6771
6947
|
sectionLabel: el ? el.dataset.ohwSectionLabel ?? titleCaseSectionId(el.dataset.ohwSection ?? "") : null
|
|
6772
6948
|
});
|
|
6773
6949
|
},
|
|
@@ -6776,7 +6952,7 @@ function AiSectionOverlay({
|
|
|
6776
6952
|
const selectFromElement = useCallback2(
|
|
6777
6953
|
(el, options) => {
|
|
6778
6954
|
const sectionEl = el?.closest("[data-ohw-section]") ?? null;
|
|
6779
|
-
const id = sectionEl
|
|
6955
|
+
const id = sectionEl ? sectionEl.dataset.ohwInstance ?? sectionEl.dataset.ohwSection ?? null : null;
|
|
6780
6956
|
if (id === selectedIdRef.current) return;
|
|
6781
6957
|
setSelectedId(id);
|
|
6782
6958
|
if (options?.report !== false) report(sectionEl);
|
|
@@ -6819,7 +6995,7 @@ function AiSectionOverlay({
|
|
|
6819
6995
|
setReviewId(found ? sectionId : null);
|
|
6820
6996
|
postToParent2({ type: "ow:ai-review-started", sectionId, found });
|
|
6821
6997
|
if (found) {
|
|
6822
|
-
document.querySelector(`[data-ohw-
|
|
6998
|
+
document.querySelector(`[data-ohw-instance="${CSS.escape(sectionId)}"]`)?.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
6823
6999
|
}
|
|
6824
7000
|
}
|
|
6825
7001
|
};
|
|
@@ -6838,7 +7014,7 @@ function AiSectionOverlay({
|
|
|
6838
7014
|
return;
|
|
6839
7015
|
}
|
|
6840
7016
|
const sec = t.closest("[data-ohw-section]");
|
|
6841
|
-
setHoveredId(sec
|
|
7017
|
+
setHoveredId(sec ? sec.dataset.ohwInstance ?? sec.dataset.ohwSection ?? null : null);
|
|
6842
7018
|
};
|
|
6843
7019
|
const onLeave = () => setHoveredId(null);
|
|
6844
7020
|
document.addEventListener("mousemove", onMove, { passive: true });
|
|
@@ -6870,9 +7046,29 @@ function AiSectionOverlay({
|
|
|
6870
7046
|
},
|
|
6871
7047
|
[postToParent2]
|
|
6872
7048
|
);
|
|
6873
|
-
const
|
|
7049
|
+
const activeSelectionId = reviewId ? null : selectedId;
|
|
7050
|
+
const selectionRect = useLiveSectionRect(activeSelectionId);
|
|
6874
7051
|
const reviewRect = useLiveSectionRect(reviewId);
|
|
6875
7052
|
const hoverRect = useLiveSectionRect(reviewId || hoveredId === selectedId ? null : hoveredId);
|
|
7053
|
+
useEffect4(() => {
|
|
7054
|
+
if (!activeSelectionId || !selectionRect) {
|
|
7055
|
+
postToParent2({ type: "ow:section-rect", instanceId: null, rect: null });
|
|
7056
|
+
return;
|
|
7057
|
+
}
|
|
7058
|
+
const { isFirst, isLast } = computeSectionBoundaryFlags(activeSelectionId);
|
|
7059
|
+
postToParent2({
|
|
7060
|
+
type: "ow:section-rect",
|
|
7061
|
+
instanceId: activeSelectionId,
|
|
7062
|
+
rect: {
|
|
7063
|
+
top: selectionRect.top + window.scrollY,
|
|
7064
|
+
left: selectionRect.left + window.scrollX,
|
|
7065
|
+
width: selectionRect.width,
|
|
7066
|
+
height: selectionRect.height
|
|
7067
|
+
},
|
|
7068
|
+
isFirst,
|
|
7069
|
+
isLast
|
|
7070
|
+
});
|
|
7071
|
+
}, [activeSelectionId, selectionRect, postToParent2]);
|
|
6876
7072
|
return /* @__PURE__ */ jsxs8(Fragment5, { children: [
|
|
6877
7073
|
hoverRect && /* @__PURE__ */ jsx16(
|
|
6878
7074
|
"div",
|
|
@@ -6923,7 +7119,10 @@ function AiSectionOverlay({
|
|
|
6923
7119
|
border: `2px solid ${PRIMARY2}`,
|
|
6924
7120
|
borderRadius: edgeAwareRadius(reviewRect),
|
|
6925
7121
|
zIndex: 2147483200,
|
|
6926
|
-
// The veil itself: swallows clicks so the section stays locked until decided.
|
|
7122
|
+
// The veil itself: swallows clicks so the section stays locked until decided. This
|
|
7123
|
+
// stopPropagation only guards the bubble phase; the bridge's capture-phase click
|
|
7124
|
+
// handlers additionally bail on `[data-ohw-ai-review]`, without which a click on
|
|
7125
|
+
// Accept/Discard resolves to the media beneath and opens the file picker.
|
|
6927
7126
|
background: "rgba(8, 133, 254, 0.04)",
|
|
6928
7127
|
pointerEvents: "auto",
|
|
6929
7128
|
cursor: "default"
|
|
@@ -7035,7 +7234,14 @@ function findClosestButtonLike(target) {
|
|
|
7035
7234
|
function findButtonAtPoint(x, y, media) {
|
|
7036
7235
|
const hits = Array.from(
|
|
7037
7236
|
document.querySelectorAll(BUTTON_LIKE_SELECTOR)
|
|
7038
|
-
).filter(
|
|
7237
|
+
).filter(
|
|
7238
|
+
(el) => containsPoint(el, x, y) && !(media && el.contains(media)) && // Bridge-injected chrome (e.g. MediaOverlay's own "Replace image" button) is never a
|
|
7239
|
+
// site button. Without this, once the media overlay renders its button lands right
|
|
7240
|
+
// under the cursor, gets detected as "a button on the media", and dismisses the very
|
|
7241
|
+
// overlay it belongs to — which removes the button, so the next hit-test finds nothing
|
|
7242
|
+
// and the overlay reappears. Flip-flops every tick: the "Replace image" button flashes.
|
|
7243
|
+
!el.closest("[data-ohw-bridge]")
|
|
7244
|
+
);
|
|
7039
7245
|
if (hits.length === 0) return null;
|
|
7040
7246
|
return hits.reduce((best, el) => best.contains(el) ? el : best);
|
|
7041
7247
|
}
|
|
@@ -9610,6 +9816,10 @@ function isSocialsRow(el) {
|
|
|
9610
9816
|
const anchors = Array.from(el.querySelectorAll("a"));
|
|
9611
9817
|
return anchors.length > 0 && anchors.every((anchor) => isSocialItem(anchor));
|
|
9612
9818
|
}
|
|
9819
|
+
var MAX_SOCIAL_ITEMS_PER_ROW = 7;
|
|
9820
|
+
function canAddSocialItem(row) {
|
|
9821
|
+
return listSocialItems(row).length < MAX_SOCIAL_ITEMS_PER_ROW;
|
|
9822
|
+
}
|
|
9613
9823
|
function listSocialItems(row) {
|
|
9614
9824
|
return Array.from(row.children).map((child) => {
|
|
9615
9825
|
if (!(child instanceof HTMLElement)) return null;
|
|
@@ -9969,6 +10179,7 @@ function ensureIconSlot(item) {
|
|
|
9969
10179
|
// src/lib/footer-items.ts
|
|
9970
10180
|
var FOOTER_ORDER_KEY = "__ohw_footer_order";
|
|
9971
10181
|
var MAX_FOOTER_COLUMNS = 18;
|
|
10182
|
+
var MAX_FOOTER_ITEMS_PER_COLUMN = 7;
|
|
9972
10183
|
var FOOTER_HREF_RE = /^footer-(\d+)-(\d+)-href$/;
|
|
9973
10184
|
function parseFooterHrefKey(key) {
|
|
9974
10185
|
if (!key) return null;
|
|
@@ -10186,6 +10397,13 @@ function getNextFooterColumnIndex() {
|
|
|
10186
10397
|
function canAddFooterColumn() {
|
|
10187
10398
|
return listFooterColumns().length < MAX_FOOTER_COLUMNS;
|
|
10188
10399
|
}
|
|
10400
|
+
function canAddFooterItem(column) {
|
|
10401
|
+
return listFooterLinksInColumn(column).length < MAX_FOOTER_ITEMS_PER_COLUMN;
|
|
10402
|
+
}
|
|
10403
|
+
function resolveFooterColumnForAdd(selected) {
|
|
10404
|
+
if (selected.hasAttribute("data-ohw-footer-col")) return selected;
|
|
10405
|
+
return selected.closest("[data-ohw-footer-col]") ?? (listFooterColumns().includes(selected) ? selected : null);
|
|
10406
|
+
}
|
|
10189
10407
|
function buildFooterHeading(colIndex, text) {
|
|
10190
10408
|
const heading = document.createElement("p");
|
|
10191
10409
|
heading.setAttribute("data-ohw-editable", "text");
|
|
@@ -10810,6 +11028,329 @@ function deleteFooterColumn(column) {
|
|
|
10810
11028
|
};
|
|
10811
11029
|
}
|
|
10812
11030
|
|
|
11031
|
+
// src/lib/logo-identity.ts
|
|
11032
|
+
var LOGO_TEXT_KEYS = ["nav-logo-text", "footer-logo-text", "logo-text"];
|
|
11033
|
+
var LOGO_IMAGE_KEYS = ["nav-logo-image", "footer-logo", "footer-logo-image"];
|
|
11034
|
+
var LOGO_HREF_KEYS = ["nav-logo-href", "footer-logo-href", "logo-href"];
|
|
11035
|
+
var LOGO_PLACEHOLDER_KEY = "logo-is-placeholder";
|
|
11036
|
+
var LOGO_ALT_KEY = "logo-alt";
|
|
11037
|
+
var LOGO_IMAGE_URL_KEY = "nav-logo-image";
|
|
11038
|
+
var PLACEHOLDER_BUSINESS_NAME = "Business name";
|
|
11039
|
+
function resolveLogoDisplayText(text) {
|
|
11040
|
+
const trimmed = (text ?? "").trim();
|
|
11041
|
+
return trimmed || PLACEHOLDER_BUSINESS_NAME;
|
|
11042
|
+
}
|
|
11043
|
+
function isFooterLogoRoot(root) {
|
|
11044
|
+
return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
|
|
11045
|
+
}
|
|
11046
|
+
function imageKeyForRoot(root) {
|
|
11047
|
+
return isFooterLogoRoot(root) ? "footer-logo" : "nav-logo-image";
|
|
11048
|
+
}
|
|
11049
|
+
function textKeyForRoot(root) {
|
|
11050
|
+
return isFooterLogoRoot(root) ? "footer-logo-text" : "nav-logo-text";
|
|
11051
|
+
}
|
|
11052
|
+
function ensureLogoHrefKey(root) {
|
|
11053
|
+
if (!(root instanceof HTMLAnchorElement)) return;
|
|
11054
|
+
if (root.hasAttribute("data-ohw-href-key")) return;
|
|
11055
|
+
root.setAttribute("data-ohw-href-key", isFooterLogoRoot(root) ? "footer-logo-href" : "nav-logo-href");
|
|
11056
|
+
}
|
|
11057
|
+
function applyLogoIdentity(text, isPlaceholder) {
|
|
11058
|
+
const display = resolveLogoDisplayText(text);
|
|
11059
|
+
const placeholder = isPlaceholder || !text.trim() || display === PLACEHOLDER_BUSINESS_NAME;
|
|
11060
|
+
for (const key of LOGO_TEXT_KEYS) {
|
|
11061
|
+
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
11062
|
+
if (el.textContent !== display) el.textContent = display;
|
|
11063
|
+
});
|
|
11064
|
+
}
|
|
11065
|
+
for (const key of LOGO_IMAGE_KEYS) {
|
|
11066
|
+
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
11067
|
+
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
11068
|
+
if (img) img.alt = display;
|
|
11069
|
+
});
|
|
11070
|
+
}
|
|
11071
|
+
document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((el) => {
|
|
11072
|
+
if (placeholder) el.setAttribute("data-ohw-placeholder", "");
|
|
11073
|
+
else el.removeAttribute("data-ohw-placeholder");
|
|
11074
|
+
});
|
|
11075
|
+
return display;
|
|
11076
|
+
}
|
|
11077
|
+
function applyLogoImage(url, alt) {
|
|
11078
|
+
const displayAlt = resolveLogoDisplayText(alt);
|
|
11079
|
+
document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
|
|
11080
|
+
ensureLogoHrefKey(root);
|
|
11081
|
+
const imageKey = imageKeyForRoot(root);
|
|
11082
|
+
const textKey = textKeyForRoot(root);
|
|
11083
|
+
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");
|
|
11084
|
+
let textEl = root.querySelector(`[data-ohw-key="${textKey}"]`) ?? root.querySelector('[data-ohw-key="logo-text"]');
|
|
11085
|
+
if (url) {
|
|
11086
|
+
if (!img) {
|
|
11087
|
+
img = document.createElement("img");
|
|
11088
|
+
img.setAttribute("data-ohw-editable", "image");
|
|
11089
|
+
img.setAttribute("data-ohw-key", imageKey);
|
|
11090
|
+
img.alt = displayAlt;
|
|
11091
|
+
img.style.height = "";
|
|
11092
|
+
img.style.maxHeight = "none";
|
|
11093
|
+
img.style.width = "auto";
|
|
11094
|
+
img.style.display = "block";
|
|
11095
|
+
img.style.objectFit = "contain";
|
|
11096
|
+
root.insertBefore(img, root.firstChild);
|
|
11097
|
+
} else {
|
|
11098
|
+
img.setAttribute("data-ohw-editable", "image");
|
|
11099
|
+
img.setAttribute("data-ohw-key", imageKey);
|
|
11100
|
+
}
|
|
11101
|
+
img.removeAttribute("srcset");
|
|
11102
|
+
img.removeAttribute("sizes");
|
|
11103
|
+
img.src = url;
|
|
11104
|
+
img.alt = displayAlt;
|
|
11105
|
+
img.style.display = "block";
|
|
11106
|
+
if (textEl) textEl.style.display = "none";
|
|
11107
|
+
root.removeAttribute("data-ohw-placeholder");
|
|
11108
|
+
return;
|
|
11109
|
+
}
|
|
11110
|
+
if (img) {
|
|
11111
|
+
img.removeAttribute("src");
|
|
11112
|
+
img.removeAttribute("srcset");
|
|
11113
|
+
img.removeAttribute("sizes");
|
|
11114
|
+
img.alt = displayAlt;
|
|
11115
|
+
img.style.display = "none";
|
|
11116
|
+
}
|
|
11117
|
+
if (!textEl) {
|
|
11118
|
+
textEl = document.createElement("span");
|
|
11119
|
+
textEl.setAttribute("data-ohw-editable", "plain");
|
|
11120
|
+
textEl.setAttribute("data-ohw-key", textKey);
|
|
11121
|
+
root.appendChild(textEl);
|
|
11122
|
+
}
|
|
11123
|
+
textEl.style.display = "";
|
|
11124
|
+
if (textEl.textContent !== displayAlt) textEl.textContent = displayAlt;
|
|
11125
|
+
if (!displayAlt.trim() || displayAlt === PLACEHOLDER_BUSINESS_NAME) {
|
|
11126
|
+
root.setAttribute("data-ohw-placeholder", "");
|
|
11127
|
+
} else {
|
|
11128
|
+
root.removeAttribute("data-ohw-placeholder");
|
|
11129
|
+
}
|
|
11130
|
+
});
|
|
11131
|
+
}
|
|
11132
|
+
function applyLogoHref(href) {
|
|
11133
|
+
const target = href.trim() || "/";
|
|
11134
|
+
document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
|
|
11135
|
+
ensureLogoHrefKey(root);
|
|
11136
|
+
if (root instanceof HTMLAnchorElement) {
|
|
11137
|
+
root.setAttribute("href", target);
|
|
11138
|
+
}
|
|
11139
|
+
});
|
|
11140
|
+
for (const key of LOGO_HREF_KEYS) setStoredLinkHref(key, target);
|
|
11141
|
+
}
|
|
11142
|
+
function readLogoIdentityFromDom() {
|
|
11143
|
+
let imageUrl = null;
|
|
11144
|
+
for (const key of LOGO_IMAGE_KEYS) {
|
|
11145
|
+
const el = document.querySelector(`[data-ohw-key="${key}"]`);
|
|
11146
|
+
const img = el instanceof HTMLImageElement ? el : el?.querySelector("img");
|
|
11147
|
+
const attrSrc = img?.getAttribute("src")?.trim() ?? "";
|
|
11148
|
+
if (attrSrc && !attrSrc.startsWith("data:") && img && img.style.display !== "none") {
|
|
11149
|
+
imageUrl = img.currentSrc || img.src;
|
|
11150
|
+
break;
|
|
11151
|
+
}
|
|
11152
|
+
}
|
|
11153
|
+
let text = PLACEHOLDER_BUSINESS_NAME;
|
|
11154
|
+
let isPlaceholder = true;
|
|
11155
|
+
for (const key of LOGO_TEXT_KEYS) {
|
|
11156
|
+
const el = document.querySelector(`[data-ohw-key="${key}"]`);
|
|
11157
|
+
if (el?.textContent?.trim()) {
|
|
11158
|
+
text = el.textContent.trim();
|
|
11159
|
+
const logoRoot2 = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
11160
|
+
isPlaceholder = logoRoot2?.hasAttribute("data-ohw-placeholder") === true || text === PLACEHOLDER_BUSINESS_NAME;
|
|
11161
|
+
break;
|
|
11162
|
+
}
|
|
11163
|
+
}
|
|
11164
|
+
if (imageUrl) {
|
|
11165
|
+
const logoImg = document.querySelector(
|
|
11166
|
+
'[data-ohw-key="nav-logo-image"], [data-ohw-key="footer-logo"]'
|
|
11167
|
+
);
|
|
11168
|
+
const alt = logoImg?.alt?.trim() || text;
|
|
11169
|
+
isPlaceholder = false;
|
|
11170
|
+
const hrefEl = document.querySelector(
|
|
11171
|
+
'a[data-ohw-role="logo"], a[data-ohw-logo], [data-ohw-role="logo"]'
|
|
11172
|
+
);
|
|
11173
|
+
const href2 = (hrefEl instanceof HTMLAnchorElement ? hrefEl.getAttribute("href") : null) || hrefEl?.closest("a")?.getAttribute("href") || "/";
|
|
11174
|
+
return { text, isPlaceholder, imageUrl, href: href2, alt };
|
|
11175
|
+
}
|
|
11176
|
+
const logoRoot = document.querySelector('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
11177
|
+
const href = (logoRoot instanceof HTMLAnchorElement ? logoRoot.getAttribute("href") : null) || logoRoot?.closest("a")?.getAttribute("href") || "/";
|
|
11178
|
+
return { text, isPlaceholder, imageUrl: null, href, alt: text };
|
|
11179
|
+
}
|
|
11180
|
+
function applyLogoFromContent(content) {
|
|
11181
|
+
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);
|
|
11182
|
+
if (!hasLogoIdentity) return false;
|
|
11183
|
+
const logoText = content[LOGO_TEXT_KEYS[0]] ?? content[LOGO_TEXT_KEYS[1]] ?? readLogoIdentityFromDom().text;
|
|
11184
|
+
const logoAlt = content[LOGO_ALT_KEY] ?? logoText;
|
|
11185
|
+
const rawLogoImage = content[LOGO_IMAGE_URL_KEY] ?? content["footer-logo"] ?? content["footer-logo-image"] ?? null;
|
|
11186
|
+
const logoImageUrl = typeof rawLogoImage === "string" && rawLogoImage.trim() ? rawLogoImage.trim() : null;
|
|
11187
|
+
const imageExplicitlyCleared = LOGO_IMAGE_KEYS.some((key) => key in content) && !logoImageUrl;
|
|
11188
|
+
const logoIsPlaceholder = LOGO_PLACEHOLDER_KEY in content ? content[LOGO_PLACEHOLDER_KEY] !== "false" : !logoImageUrl && (!logoText.trim() || logoText === PLACEHOLDER_BUSINESS_NAME);
|
|
11189
|
+
if (logoImageUrl) {
|
|
11190
|
+
applyLogoImage(logoImageUrl, logoAlt);
|
|
11191
|
+
} else {
|
|
11192
|
+
if (imageExplicitlyCleared) applyLogoImage(null, logoAlt);
|
|
11193
|
+
applyLogoIdentity(logoText, logoIsPlaceholder);
|
|
11194
|
+
}
|
|
11195
|
+
const logoHref = content["nav-logo-href"] ?? content["footer-logo-href"] ?? content["logo-href"];
|
|
11196
|
+
if (typeof logoHref === "string" && logoHref.trim()) {
|
|
11197
|
+
applyLogoHref(logoHref);
|
|
11198
|
+
}
|
|
11199
|
+
return true;
|
|
11200
|
+
}
|
|
11201
|
+
|
|
11202
|
+
// src/lib/logo-size.ts
|
|
11203
|
+
var LOGO_SIZE_DEFAULTS = {
|
|
11204
|
+
navbar: 28,
|
|
11205
|
+
footer: 32
|
|
11206
|
+
};
|
|
11207
|
+
var LOGO_SIZE_MIN = 16;
|
|
11208
|
+
var LOGO_SIZE_MAX = 80;
|
|
11209
|
+
var LOGO_SIZE_DESKTOP_KEYS = {
|
|
11210
|
+
navbar: "nav-logo-size",
|
|
11211
|
+
footer: "footer-logo-size"
|
|
11212
|
+
};
|
|
11213
|
+
var LOGO_SIZE_MOBILE_KEYS = {
|
|
11214
|
+
navbar: "nav-logo-size-mobile",
|
|
11215
|
+
footer: "footer-logo-size-mobile"
|
|
11216
|
+
};
|
|
11217
|
+
var LOGO_SIZE_KEYS = [
|
|
11218
|
+
LOGO_SIZE_DESKTOP_KEYS.navbar,
|
|
11219
|
+
LOGO_SIZE_DESKTOP_KEYS.footer,
|
|
11220
|
+
LOGO_SIZE_MOBILE_KEYS.navbar,
|
|
11221
|
+
LOGO_SIZE_MOBILE_KEYS.footer
|
|
11222
|
+
];
|
|
11223
|
+
function isFooterLogoRoot2(root) {
|
|
11224
|
+
return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
|
|
11225
|
+
}
|
|
11226
|
+
function getLogoPlacement(root) {
|
|
11227
|
+
return isFooterLogoRoot2(root) ? "footer" : "navbar";
|
|
11228
|
+
}
|
|
11229
|
+
function parseLogoSizePx(raw, fallback) {
|
|
11230
|
+
if (raw == null || raw === "") return fallback;
|
|
11231
|
+
const n = Number.parseFloat(raw);
|
|
11232
|
+
if (!Number.isFinite(n)) return fallback;
|
|
11233
|
+
return Math.min(LOGO_SIZE_MAX, Math.max(LOGO_SIZE_MIN, Math.round(n)));
|
|
11234
|
+
}
|
|
11235
|
+
function isMobileLogoSizeFollowing(content, placement) {
|
|
11236
|
+
const raw = content[LOGO_SIZE_MOBILE_KEYS[placement]];
|
|
11237
|
+
return raw == null || raw.trim() === "";
|
|
11238
|
+
}
|
|
11239
|
+
function resolveDesktopLogoSize(content, placement) {
|
|
11240
|
+
return parseLogoSizePx(content[LOGO_SIZE_DESKTOP_KEYS[placement]], LOGO_SIZE_DEFAULTS[placement]);
|
|
11241
|
+
}
|
|
11242
|
+
function resolveMobileLogoSize(content, placement) {
|
|
11243
|
+
if (isMobileLogoSizeFollowing(content, placement)) {
|
|
11244
|
+
return resolveDesktopLogoSize(content, placement);
|
|
11245
|
+
}
|
|
11246
|
+
return parseLogoSizePx(
|
|
11247
|
+
content[LOGO_SIZE_MOBILE_KEYS[placement]],
|
|
11248
|
+
resolveDesktopLogoSize(content, placement)
|
|
11249
|
+
);
|
|
11250
|
+
}
|
|
11251
|
+
function setRootSizeVars(root, desktopPx, mobilePx, following) {
|
|
11252
|
+
root.style.setProperty("--ohw-logo-size", `${desktopPx}px`);
|
|
11253
|
+
if (following) {
|
|
11254
|
+
root.style.removeProperty("--ohw-logo-size-mobile");
|
|
11255
|
+
} else {
|
|
11256
|
+
root.style.setProperty("--ohw-logo-size-mobile", `${mobilePx}px`);
|
|
11257
|
+
}
|
|
11258
|
+
root.querySelectorAll("img").forEach((img) => {
|
|
11259
|
+
img.style.height = "";
|
|
11260
|
+
img.style.maxHeight = "none";
|
|
11261
|
+
img.style.width = "auto";
|
|
11262
|
+
img.style.objectFit = "contain";
|
|
11263
|
+
});
|
|
11264
|
+
}
|
|
11265
|
+
function applyLogoSizes(content) {
|
|
11266
|
+
document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
|
|
11267
|
+
const placement = getLogoPlacement(root);
|
|
11268
|
+
const desktop = resolveDesktopLogoSize(content, placement);
|
|
11269
|
+
const following = isMobileLogoSizeFollowing(content, placement);
|
|
11270
|
+
const mobile = following ? desktop : resolveMobileLogoSize(content, placement);
|
|
11271
|
+
setRootSizeVars(root, desktop, mobile, following);
|
|
11272
|
+
});
|
|
11273
|
+
}
|
|
11274
|
+
function applyLogoSizeToPlacement(placement, desktopPx, mobilePx, following) {
|
|
11275
|
+
document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
|
|
11276
|
+
if (getLogoPlacement(root) !== placement) return;
|
|
11277
|
+
setRootSizeVars(root, desktopPx, mobilePx, following);
|
|
11278
|
+
});
|
|
11279
|
+
}
|
|
11280
|
+
function logoHasUploadedImage(logoEl) {
|
|
11281
|
+
if (logoEl.hasAttribute("data-ohw-placeholder")) return false;
|
|
11282
|
+
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");
|
|
11283
|
+
if (!img) return false;
|
|
11284
|
+
const src = img.getAttribute("src")?.trim() ?? "";
|
|
11285
|
+
if (!src || src.startsWith("data:")) return false;
|
|
11286
|
+
if (img.style.display === "none") return false;
|
|
11287
|
+
return true;
|
|
11288
|
+
}
|
|
11289
|
+
function getLogoInteractionRect(logoEl) {
|
|
11290
|
+
if (logoHasUploadedImage(logoEl)) {
|
|
11291
|
+
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");
|
|
11292
|
+
if (img) {
|
|
11293
|
+
const r2 = img.getBoundingClientRect();
|
|
11294
|
+
if (r2.width > 0 && r2.height > 0) return r2;
|
|
11295
|
+
}
|
|
11296
|
+
}
|
|
11297
|
+
const text = logoEl.querySelector(
|
|
11298
|
+
'[data-ohw-key="nav-logo-text"], [data-ohw-key="footer-logo-text"]'
|
|
11299
|
+
);
|
|
11300
|
+
if (text) {
|
|
11301
|
+
const style = window.getComputedStyle(text);
|
|
11302
|
+
if (style.display !== "none" && style.visibility !== "hidden") {
|
|
11303
|
+
const r2 = text.getBoundingClientRect();
|
|
11304
|
+
if (r2.width > 0 && r2.height > 0) return r2;
|
|
11305
|
+
}
|
|
11306
|
+
}
|
|
11307
|
+
return logoEl.getBoundingClientRect();
|
|
11308
|
+
}
|
|
11309
|
+
function readLogoSizeState(content, placement) {
|
|
11310
|
+
const desktopPx = resolveDesktopLogoSize(content, placement);
|
|
11311
|
+
const mobileFollowing = isMobileLogoSizeFollowing(content, placement);
|
|
11312
|
+
const mobilePx = mobileFollowing ? desktopPx : resolveMobileLogoSize(content, placement);
|
|
11313
|
+
return { desktopPx, mobilePx, mobileFollowing };
|
|
11314
|
+
}
|
|
11315
|
+
|
|
11316
|
+
// src/lib/site-wide-scope.ts
|
|
11317
|
+
function getLogoElement(el) {
|
|
11318
|
+
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
11319
|
+
if (marked) return marked;
|
|
11320
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
11321
|
+
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
11322
|
+
if (!root) return null;
|
|
11323
|
+
const anchor = el.closest("a");
|
|
11324
|
+
if (anchor && root.contains(anchor) && !anchor.hasAttribute("data-ohw-href-key") && !anchor.closest("[data-ohw-nav-container]") && Boolean(anchor.querySelector("img") || anchor.matches("img"))) {
|
|
11325
|
+
return anchor;
|
|
11326
|
+
}
|
|
11327
|
+
const img = el.matches("img") ? el : null;
|
|
11328
|
+
if (img && !img.closest("[data-ohw-href-key]") && !img.closest("[data-ohw-nav-container]") && (img.closest("footer") || img.closest("nav, [data-ohw-nav-root]"))) {
|
|
11329
|
+
return img;
|
|
11330
|
+
}
|
|
11331
|
+
return null;
|
|
11332
|
+
}
|
|
11333
|
+
function isInFooter(el) {
|
|
11334
|
+
if (!el) return false;
|
|
11335
|
+
return Boolean(el.closest("footer") || el.closest('[data-ohw-section="footer"]'));
|
|
11336
|
+
}
|
|
11337
|
+
function isSiteWideElement(el) {
|
|
11338
|
+
if (!el) return false;
|
|
11339
|
+
if (getLogoElement(el)) return true;
|
|
11340
|
+
if (isInFooter(el)) return true;
|
|
11341
|
+
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-root")) {
|
|
11342
|
+
return true;
|
|
11343
|
+
}
|
|
11344
|
+
if (el.hasAttribute("data-ohw-href-key") && el.closest("nav, [data-ohw-nav-root], [data-ohw-nav-drawer], aside")) {
|
|
11345
|
+
return true;
|
|
11346
|
+
}
|
|
11347
|
+
if (el.closest('[data-ohw-role="navbar-button"]')) return true;
|
|
11348
|
+
return false;
|
|
11349
|
+
}
|
|
11350
|
+
function isSiteWideScopeActive(args) {
|
|
11351
|
+
return isSiteWideElement(args.selected) || isSiteWideElement(args.hoveredItem) || isSiteWideElement(args.hoveredNavContainer) || isSiteWideElement(args.active);
|
|
11352
|
+
}
|
|
11353
|
+
|
|
10813
11354
|
// src/lib/add-footer-column.ts
|
|
10814
11355
|
function buildFooterColumnEditContentPatch(result) {
|
|
10815
11356
|
return {
|
|
@@ -10921,6 +11462,7 @@ function FloatingPanel({
|
|
|
10921
11462
|
e.stopPropagation();
|
|
10922
11463
|
const el = e.currentTarget;
|
|
10923
11464
|
el.setPointerCapture(e.pointerId);
|
|
11465
|
+
document.documentElement.setAttribute("data-ohw-panel-dragging", "");
|
|
10924
11466
|
dragRef.current = {
|
|
10925
11467
|
pointerId: e.pointerId,
|
|
10926
11468
|
startX: e.clientX,
|
|
@@ -10953,11 +11495,17 @@ function FloatingPanel({
|
|
|
10953
11495
|
const drag = dragRef.current;
|
|
10954
11496
|
if (!drag || drag.pointerId !== e.pointerId) return;
|
|
10955
11497
|
dragRef.current = null;
|
|
11498
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
10956
11499
|
try {
|
|
10957
11500
|
e.currentTarget.releasePointerCapture(e.pointerId);
|
|
10958
11501
|
} catch {
|
|
10959
11502
|
}
|
|
10960
11503
|
}, []);
|
|
11504
|
+
useEffect9(() => {
|
|
11505
|
+
if (open) return;
|
|
11506
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
11507
|
+
}, [open]);
|
|
11508
|
+
useEffect9(() => () => document.documentElement.removeAttribute("data-ohw-panel-dragging"), []);
|
|
10961
11509
|
if (!open) return null;
|
|
10962
11510
|
return /* @__PURE__ */ jsxs16(
|
|
10963
11511
|
"div",
|
|
@@ -11024,16 +11572,127 @@ function FloatingPanel({
|
|
|
11024
11572
|
);
|
|
11025
11573
|
}
|
|
11026
11574
|
|
|
11027
|
-
// src/ui/
|
|
11575
|
+
// src/ui/logo-size-panel.tsx
|
|
11576
|
+
import { ArrowUpRight, Link as Link2 } from "lucide-react";
|
|
11028
11577
|
import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
11578
|
+
function SizeSlider({
|
|
11579
|
+
value,
|
|
11580
|
+
onChange
|
|
11581
|
+
}) {
|
|
11582
|
+
const pct = (value - LOGO_SIZE_MIN) / (LOGO_SIZE_MAX - LOGO_SIZE_MIN) * 100;
|
|
11583
|
+
return /* @__PURE__ */ jsxs17("div", { className: "flex w-full flex-col gap-3", children: [
|
|
11584
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex w-full items-center gap-2 text-sm font-medium leading-5", children: [
|
|
11585
|
+
/* @__PURE__ */ jsx27("span", { className: "min-w-0 flex-1 text-foreground", children: "Size" }),
|
|
11586
|
+
/* @__PURE__ */ jsxs17("span", { className: "shrink-0 whitespace-nowrap text-muted-foreground", children: [
|
|
11587
|
+
value,
|
|
11588
|
+
" px"
|
|
11589
|
+
] })
|
|
11590
|
+
] }),
|
|
11591
|
+
/* @__PURE__ */ jsxs17("div", { className: "relative h-2 w-full rounded-full bg-primary-50", children: [
|
|
11592
|
+
/* @__PURE__ */ jsx27(
|
|
11593
|
+
"div",
|
|
11594
|
+
{
|
|
11595
|
+
className: "absolute inset-y-0 left-0 rounded-full bg-primary",
|
|
11596
|
+
style: { width: `${pct}%` }
|
|
11597
|
+
}
|
|
11598
|
+
),
|
|
11599
|
+
/* @__PURE__ */ jsx27(
|
|
11600
|
+
"input",
|
|
11601
|
+
{
|
|
11602
|
+
type: "range",
|
|
11603
|
+
min: LOGO_SIZE_MIN,
|
|
11604
|
+
max: LOGO_SIZE_MAX,
|
|
11605
|
+
step: 1,
|
|
11606
|
+
value,
|
|
11607
|
+
"aria-label": "Logo size",
|
|
11608
|
+
className: cn(
|
|
11609
|
+
"absolute inset-0 h-full w-full cursor-pointer appearance-none bg-transparent",
|
|
11610
|
+
"[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:size-5",
|
|
11611
|
+
"[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2",
|
|
11612
|
+
"[&::-webkit-slider-thumb]:border-primary [&::-webkit-slider-thumb]:bg-background",
|
|
11613
|
+
"[&::-moz-range-thumb]:size-5 [&::-moz-range-thumb]:rounded-full",
|
|
11614
|
+
"[&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-primary",
|
|
11615
|
+
"[&::-moz-range-thumb]:bg-background"
|
|
11616
|
+
),
|
|
11617
|
+
onChange: (e) => onChange(Number(e.target.value))
|
|
11618
|
+
}
|
|
11619
|
+
)
|
|
11620
|
+
] })
|
|
11621
|
+
] });
|
|
11622
|
+
}
|
|
11623
|
+
function LogoSizePanel({
|
|
11624
|
+
viewport,
|
|
11625
|
+
sizePx,
|
|
11626
|
+
mobileFollowing = true,
|
|
11627
|
+
onSizeChange,
|
|
11628
|
+
onCustomizeMobile,
|
|
11629
|
+
onResetMobile,
|
|
11630
|
+
onUpdateEverywhere,
|
|
11631
|
+
className
|
|
11632
|
+
}) {
|
|
11633
|
+
const showFollowing = viewport === "mobile" && mobileFollowing;
|
|
11634
|
+
const showMobileSlider = viewport === "mobile" && !mobileFollowing;
|
|
11635
|
+
const showDesktopSlider = viewport === "desktop";
|
|
11636
|
+
return /* @__PURE__ */ jsxs17("div", { className: cn("flex w-full flex-col gap-4", className), children: [
|
|
11637
|
+
showFollowing ? /* @__PURE__ */ jsxs17("div", { className: "flex w-full flex-col gap-2", children: [
|
|
11638
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex items-start gap-1", children: [
|
|
11639
|
+
/* @__PURE__ */ jsx27(Link2, { size: 16, className: "mt-0.5 shrink-0 text-foreground", "aria-hidden": true }),
|
|
11640
|
+
/* @__PURE__ */ jsx27("p", { className: "text-sm font-semibold leading-5 text-foreground", children: "Following desktop size" })
|
|
11641
|
+
] }),
|
|
11642
|
+
/* @__PURE__ */ jsx27("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." }),
|
|
11643
|
+
/* @__PURE__ */ jsx27(
|
|
11644
|
+
Button,
|
|
11645
|
+
{
|
|
11646
|
+
type: "button",
|
|
11647
|
+
variant: "outline",
|
|
11648
|
+
size: "sm",
|
|
11649
|
+
className: "h-9 w-full min-w-0 cursor-pointer",
|
|
11650
|
+
onClick: onCustomizeMobile,
|
|
11651
|
+
children: "Customize for mobile"
|
|
11652
|
+
}
|
|
11653
|
+
)
|
|
11654
|
+
] }) : null,
|
|
11655
|
+
showDesktopSlider || showMobileSlider ? /* @__PURE__ */ jsx27(SizeSlider, { value: sizePx, onChange: onSizeChange }) : null,
|
|
11656
|
+
showMobileSlider ? /* @__PURE__ */ jsx27(
|
|
11657
|
+
Button,
|
|
11658
|
+
{
|
|
11659
|
+
type: "button",
|
|
11660
|
+
variant: "outline",
|
|
11661
|
+
size: "sm",
|
|
11662
|
+
className: "h-9 w-full min-w-0 cursor-pointer",
|
|
11663
|
+
onClick: onResetMobile,
|
|
11664
|
+
children: "Reset to desktop size"
|
|
11665
|
+
}
|
|
11666
|
+
) : null,
|
|
11667
|
+
/* @__PURE__ */ jsx27("div", { className: "h-px w-full bg-border", role: "separator" }),
|
|
11668
|
+
/* @__PURE__ */ jsxs17(
|
|
11669
|
+
Button,
|
|
11670
|
+
{
|
|
11671
|
+
type: "button",
|
|
11672
|
+
variant: "outline",
|
|
11673
|
+
size: "sm",
|
|
11674
|
+
className: "h-9 w-full min-w-0 cursor-pointer gap-1",
|
|
11675
|
+
onClick: onUpdateEverywhere,
|
|
11676
|
+
children: [
|
|
11677
|
+
"Update logo everywhere",
|
|
11678
|
+
/* @__PURE__ */ jsx27(ArrowUpRight, { size: 16, "aria-hidden": true })
|
|
11679
|
+
]
|
|
11680
|
+
}
|
|
11681
|
+
),
|
|
11682
|
+
/* @__PURE__ */ jsx27("p", { className: "text-sm leading-5 text-muted-foreground", children: "Matches the right version to your background." })
|
|
11683
|
+
] });
|
|
11684
|
+
}
|
|
11685
|
+
|
|
11686
|
+
// src/ui/socials-display-panel.tsx
|
|
11687
|
+
import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
11029
11688
|
function DisplaySwitch({
|
|
11030
11689
|
label,
|
|
11031
11690
|
checked,
|
|
11032
11691
|
disabled,
|
|
11033
11692
|
onChange
|
|
11034
11693
|
}) {
|
|
11035
|
-
return /* @__PURE__ */
|
|
11036
|
-
/* @__PURE__ */
|
|
11694
|
+
return /* @__PURE__ */ jsxs18("div", { className: "flex w-full items-center gap-2", children: [
|
|
11695
|
+
/* @__PURE__ */ jsx28(
|
|
11037
11696
|
"span",
|
|
11038
11697
|
{
|
|
11039
11698
|
className: cn(
|
|
@@ -11043,7 +11702,7 @@ function DisplaySwitch({
|
|
|
11043
11702
|
children: label
|
|
11044
11703
|
}
|
|
11045
11704
|
),
|
|
11046
|
-
/* @__PURE__ */
|
|
11705
|
+
/* @__PURE__ */ jsx28(
|
|
11047
11706
|
"button",
|
|
11048
11707
|
{
|
|
11049
11708
|
type: "button",
|
|
@@ -11057,7 +11716,7 @@ function DisplaySwitch({
|
|
|
11057
11716
|
checked ? "bg-primary" : "bg-primary-50",
|
|
11058
11717
|
disabled ? "cursor-default opacity-50" : "cursor-pointer"
|
|
11059
11718
|
),
|
|
11060
|
-
children: /* @__PURE__ */
|
|
11719
|
+
children: /* @__PURE__ */ jsx28(
|
|
11061
11720
|
"span",
|
|
11062
11721
|
{
|
|
11063
11722
|
className: cn(
|
|
@@ -11071,8 +11730,8 @@ function DisplaySwitch({
|
|
|
11071
11730
|
] });
|
|
11072
11731
|
}
|
|
11073
11732
|
function SocialsDisplayPanel({ display, onChange, className }) {
|
|
11074
|
-
return /* @__PURE__ */
|
|
11075
|
-
/* @__PURE__ */
|
|
11733
|
+
return /* @__PURE__ */ jsxs18("div", { className: cn("flex w-full flex-col gap-3", className), children: [
|
|
11734
|
+
/* @__PURE__ */ jsx28(
|
|
11076
11735
|
DisplaySwitch,
|
|
11077
11736
|
{
|
|
11078
11737
|
label: "Text",
|
|
@@ -11081,7 +11740,7 @@ function SocialsDisplayPanel({ display, onChange, className }) {
|
|
|
11081
11740
|
onChange: (text) => onChange({ ...display, text })
|
|
11082
11741
|
}
|
|
11083
11742
|
),
|
|
11084
|
-
/* @__PURE__ */
|
|
11743
|
+
/* @__PURE__ */ jsx28(
|
|
11085
11744
|
DisplaySwitch,
|
|
11086
11745
|
{
|
|
11087
11746
|
label: "Icon",
|
|
@@ -11642,7 +12301,7 @@ function useNavItemDrag({
|
|
|
11642
12301
|
|
|
11643
12302
|
// src/ui/footer-container-chrome.tsx
|
|
11644
12303
|
import { Plus as Plus2 } from "lucide-react";
|
|
11645
|
-
import { jsx as
|
|
12304
|
+
import { jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
11646
12305
|
function FooterContainerChrome({
|
|
11647
12306
|
rect,
|
|
11648
12307
|
onAdd,
|
|
@@ -11650,7 +12309,7 @@ function FooterContainerChrome({
|
|
|
11650
12309
|
}) {
|
|
11651
12310
|
const chromeGap = 6;
|
|
11652
12311
|
const buttonMargin = 7;
|
|
11653
|
-
return /* @__PURE__ */
|
|
12312
|
+
return /* @__PURE__ */ jsx29(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsx29(
|
|
11654
12313
|
"div",
|
|
11655
12314
|
{
|
|
11656
12315
|
"data-ohw-footer-container-chrome": "",
|
|
@@ -11662,8 +12321,8 @@ function FooterContainerChrome({
|
|
|
11662
12321
|
width: rect.width + chromeGap * 2,
|
|
11663
12322
|
height: rect.height + chromeGap * 2
|
|
11664
12323
|
},
|
|
11665
|
-
children: /* @__PURE__ */
|
|
11666
|
-
/* @__PURE__ */
|
|
12324
|
+
children: /* @__PURE__ */ jsxs19(Tooltip, { children: [
|
|
12325
|
+
/* @__PURE__ */ jsx29(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx29(
|
|
11667
12326
|
"button",
|
|
11668
12327
|
{
|
|
11669
12328
|
type: "button",
|
|
@@ -11682,10 +12341,10 @@ function FooterContainerChrome({
|
|
|
11682
12341
|
if (addDisabled) return;
|
|
11683
12342
|
onAdd();
|
|
11684
12343
|
},
|
|
11685
|
-
children: /* @__PURE__ */
|
|
12344
|
+
children: /* @__PURE__ */ jsx29(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
11686
12345
|
}
|
|
11687
12346
|
) }),
|
|
11688
|
-
/* @__PURE__ */
|
|
12347
|
+
/* @__PURE__ */ jsx29(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
|
|
11689
12348
|
] })
|
|
11690
12349
|
}
|
|
11691
12350
|
) });
|
|
@@ -11868,6 +12527,18 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
11868
12527
|
}
|
|
11869
12528
|
if (extraContent && !isScoped) {
|
|
11870
12529
|
applyNavFooterDeleteOverrides(byKey, extraContent);
|
|
12530
|
+
for (const key of LOGO_IMAGE_KEYS) {
|
|
12531
|
+
if (!(key in extraContent)) continue;
|
|
12532
|
+
byKey.set(key, { key, type: "image", text: extraContent[key] ?? "" });
|
|
12533
|
+
}
|
|
12534
|
+
for (const key of [LOGO_PLACEHOLDER_KEY, LOGO_ALT_KEY]) {
|
|
12535
|
+
if (!(key in extraContent)) continue;
|
|
12536
|
+
byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
|
|
12537
|
+
}
|
|
12538
|
+
for (const key of LOGO_SIZE_KEYS) {
|
|
12539
|
+
if (!(key in extraContent)) continue;
|
|
12540
|
+
byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
|
|
12541
|
+
}
|
|
11871
12542
|
}
|
|
11872
12543
|
return Array.from(byKey.values());
|
|
11873
12544
|
}
|
|
@@ -12134,13 +12805,13 @@ function deleteSelectedNavFooterItem(deps) {
|
|
|
12134
12805
|
|
|
12135
12806
|
// src/ui/navbar-container-chrome.tsx
|
|
12136
12807
|
import { Plus as Plus3 } from "lucide-react";
|
|
12137
|
-
import { jsx as
|
|
12808
|
+
import { jsx as jsx30 } from "react/jsx-runtime";
|
|
12138
12809
|
function NavbarContainerChrome({
|
|
12139
12810
|
rect,
|
|
12140
12811
|
onAdd
|
|
12141
12812
|
}) {
|
|
12142
12813
|
const chromeGap = 6;
|
|
12143
|
-
return /* @__PURE__ */
|
|
12814
|
+
return /* @__PURE__ */ jsx30(
|
|
12144
12815
|
"div",
|
|
12145
12816
|
{
|
|
12146
12817
|
"data-ohw-navbar-container-chrome": "",
|
|
@@ -12152,7 +12823,7 @@ function NavbarContainerChrome({
|
|
|
12152
12823
|
width: rect.width + chromeGap * 2,
|
|
12153
12824
|
height: rect.height + chromeGap * 2
|
|
12154
12825
|
},
|
|
12155
|
-
children: /* @__PURE__ */
|
|
12826
|
+
children: /* @__PURE__ */ jsx30(
|
|
12156
12827
|
"button",
|
|
12157
12828
|
{
|
|
12158
12829
|
type: "button",
|
|
@@ -12169,7 +12840,7 @@ function NavbarContainerChrome({
|
|
|
12169
12840
|
e.stopPropagation();
|
|
12170
12841
|
onAdd();
|
|
12171
12842
|
},
|
|
12172
|
-
children: /* @__PURE__ */
|
|
12843
|
+
children: /* @__PURE__ */ jsx30(Plus3, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
12173
12844
|
}
|
|
12174
12845
|
)
|
|
12175
12846
|
}
|
|
@@ -12178,7 +12849,7 @@ function NavbarContainerChrome({
|
|
|
12178
12849
|
|
|
12179
12850
|
// src/ui/drop-indicator.tsx
|
|
12180
12851
|
import * as React10 from "react";
|
|
12181
|
-
import { jsx as
|
|
12852
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
12182
12853
|
var dropIndicatorVariants = cva(
|
|
12183
12854
|
"ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
|
|
12184
12855
|
{
|
|
@@ -12202,7 +12873,7 @@ var dropIndicatorVariants = cva(
|
|
|
12202
12873
|
);
|
|
12203
12874
|
var DropIndicator = React10.forwardRef(
|
|
12204
12875
|
({ className, direction, state, ...props }, ref) => {
|
|
12205
|
-
return /* @__PURE__ */
|
|
12876
|
+
return /* @__PURE__ */ jsx31(
|
|
12206
12877
|
"div",
|
|
12207
12878
|
{
|
|
12208
12879
|
ref,
|
|
@@ -12219,7 +12890,7 @@ var DropIndicator = React10.forwardRef(
|
|
|
12219
12890
|
DropIndicator.displayName = "DropIndicator";
|
|
12220
12891
|
|
|
12221
12892
|
// src/ui/badge.tsx
|
|
12222
|
-
import { jsx as
|
|
12893
|
+
import { jsx as jsx32 } from "react/jsx-runtime";
|
|
12223
12894
|
var badgeVariants = cva(
|
|
12224
12895
|
"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",
|
|
12225
12896
|
{
|
|
@@ -12237,12 +12908,12 @@ var badgeVariants = cva(
|
|
|
12237
12908
|
}
|
|
12238
12909
|
);
|
|
12239
12910
|
function Badge({ className, variant, ...props }) {
|
|
12240
|
-
return /* @__PURE__ */
|
|
12911
|
+
return /* @__PURE__ */ jsx32("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
12241
12912
|
}
|
|
12242
12913
|
|
|
12243
12914
|
// src/OhhwellsBridge.tsx
|
|
12244
|
-
import { Link as
|
|
12245
|
-
import { Fragment as Fragment8, jsx as
|
|
12915
|
+
import { Link as Link3 } from "lucide-react";
|
|
12916
|
+
import { Fragment as Fragment8, jsx as jsx33, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
12246
12917
|
var PRIMARY3 = "#0885FE";
|
|
12247
12918
|
var IMAGE_FADE_MS = 300;
|
|
12248
12919
|
function runOpacityFade(el, onDone) {
|
|
@@ -12336,21 +13007,10 @@ function parseSchedulingInsertAfter(insertAfter) {
|
|
|
12336
13007
|
insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
|
|
12337
13008
|
};
|
|
12338
13009
|
}
|
|
12339
|
-
function
|
|
12340
|
-
|
|
12341
|
-
const
|
|
12342
|
-
|
|
12343
|
-
return { effectiveInsertAfter, insertBefore };
|
|
12344
|
-
}
|
|
12345
|
-
function getSchedulingMountPoint(insertAfter) {
|
|
12346
|
-
const { anchor } = parseSchedulingInsertAfter(insertAfter);
|
|
12347
|
-
let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
|
|
12348
|
-
if (!anchorEl && anchor === "scheduling") {
|
|
12349
|
-
const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
|
|
12350
|
-
anchorEl = widgets.at(-1) ?? null;
|
|
12351
|
-
}
|
|
12352
|
-
if (!anchorEl) return null;
|
|
12353
|
-
return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
13010
|
+
function resolveEntryAnchor(entry) {
|
|
13011
|
+
if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
|
|
13012
|
+
const parsed = parseSchedulingInsertAfter(entry.insertAfter);
|
|
13013
|
+
return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
|
|
12354
13014
|
}
|
|
12355
13015
|
function schedulingMountDepth(insertAfter) {
|
|
12356
13016
|
if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
|
|
@@ -12367,8 +13027,7 @@ function getPageSchedulingEntries(raw) {
|
|
|
12367
13027
|
}
|
|
12368
13028
|
}
|
|
12369
13029
|
function isSchedulingWidgetMissing(entry) {
|
|
12370
|
-
|
|
12371
|
-
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
|
|
13030
|
+
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
|
|
12372
13031
|
}
|
|
12373
13032
|
function hasMissingSchedulingWidgets(entries) {
|
|
12374
13033
|
return entries.some(isSchedulingWidgetMissing);
|
|
@@ -12398,16 +13057,17 @@ function initSectionsFromContent(content, removeExisting = false) {
|
|
|
12398
13057
|
} catch {
|
|
12399
13058
|
}
|
|
12400
13059
|
}
|
|
12401
|
-
function mountSchedulingWidget(
|
|
12402
|
-
const
|
|
12403
|
-
const sectionId = schedulingSectionId(
|
|
13060
|
+
function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
|
|
13061
|
+
const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
|
|
13062
|
+
const sectionId = schedulingSectionId(widgetId);
|
|
12404
13063
|
if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
|
|
12405
|
-
const
|
|
12406
|
-
if (!
|
|
13064
|
+
const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
|
|
13065
|
+
if (!anchorEl) return false;
|
|
13066
|
+
const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
12407
13067
|
const container = document.createElement("div");
|
|
12408
13068
|
container.dataset.ohwSectionContainer = "scheduling";
|
|
12409
|
-
if (
|
|
12410
|
-
const beforeAnchor = document.querySelector(`[data-ohw-section="${
|
|
13069
|
+
if (beforeId) {
|
|
13070
|
+
const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
|
|
12411
13071
|
const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
|
|
12412
13072
|
if (!beforePoint) return false;
|
|
12413
13073
|
beforePoint.insertAdjacentElement("beforebegin", container);
|
|
@@ -12418,19 +13078,25 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
12418
13078
|
}
|
|
12419
13079
|
tail.insertAdjacentElement("afterend", container);
|
|
12420
13080
|
}
|
|
12421
|
-
|
|
12422
|
-
|
|
12423
|
-
|
|
12424
|
-
|
|
12425
|
-
|
|
12426
|
-
|
|
12427
|
-
|
|
12428
|
-
|
|
12429
|
-
|
|
12430
|
-
|
|
12431
|
-
|
|
12432
|
-
|
|
12433
|
-
|
|
13081
|
+
try {
|
|
13082
|
+
const root = createRoot2(container);
|
|
13083
|
+
flushSync2(() => {
|
|
13084
|
+
root.render(
|
|
13085
|
+
/* @__PURE__ */ jsx33(
|
|
13086
|
+
SchedulingWidget,
|
|
13087
|
+
{
|
|
13088
|
+
notifyOnConnect,
|
|
13089
|
+
initialScheduleId: scheduleId,
|
|
13090
|
+
insertAfter: widgetId
|
|
13091
|
+
}
|
|
13092
|
+
)
|
|
13093
|
+
);
|
|
13094
|
+
});
|
|
13095
|
+
} catch (err) {
|
|
13096
|
+
console.error("[ow:scheduling] render threw", err);
|
|
13097
|
+
container.remove();
|
|
13098
|
+
return false;
|
|
13099
|
+
}
|
|
12434
13100
|
const tracker = getSectionsTracker();
|
|
12435
13101
|
let sections = [];
|
|
12436
13102
|
try {
|
|
@@ -12438,10 +13104,12 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
12438
13104
|
} catch {
|
|
12439
13105
|
}
|
|
12440
13106
|
const inEditor = typeof window !== "undefined" && window.self !== window.top;
|
|
12441
|
-
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter ===
|
|
13107
|
+
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
|
|
12442
13108
|
sections.push({
|
|
12443
13109
|
type: "scheduling",
|
|
12444
|
-
insertAfter:
|
|
13110
|
+
insertAfter: widgetId,
|
|
13111
|
+
anchorId,
|
|
13112
|
+
beforeId: beforeId ?? null,
|
|
12445
13113
|
pagePath: window.location.pathname,
|
|
12446
13114
|
...scheduleId ? { scheduleId } : {}
|
|
12447
13115
|
});
|
|
@@ -12455,7 +13123,8 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
12455
13123
|
for (let i = pending.length - 1; i >= 0; i--) {
|
|
12456
13124
|
const entry = pending[i];
|
|
12457
13125
|
const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
|
|
12458
|
-
|
|
13126
|
+
const { anchorId, beforeId } = resolveEntryAnchor(entry);
|
|
13127
|
+
if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
|
|
12459
13128
|
pending.splice(i, 1);
|
|
12460
13129
|
}
|
|
12461
13130
|
}
|
|
@@ -12599,6 +13268,13 @@ function isInsideLinkEditor(target) {
|
|
|
12599
13268
|
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"]')
|
|
12600
13269
|
);
|
|
12601
13270
|
}
|
|
13271
|
+
function isInsideFloatingPanel(target) {
|
|
13272
|
+
return Boolean(target.closest("[data-ohw-floating-panel]"));
|
|
13273
|
+
}
|
|
13274
|
+
function isPointOverFloatingPanel(clientX, clientY) {
|
|
13275
|
+
const el = document.elementFromPoint(clientX, clientY);
|
|
13276
|
+
return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
|
|
13277
|
+
}
|
|
12602
13278
|
function getHrefKeyFromElement(el) {
|
|
12603
13279
|
if (!el) return null;
|
|
12604
13280
|
const anchor = el.closest("[data-ohw-href-key]");
|
|
@@ -12736,6 +13412,11 @@ function isNavbarLinksContainer2(el) {
|
|
|
12736
13412
|
function getFooterColumn(el) {
|
|
12737
13413
|
return el.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
|
|
12738
13414
|
}
|
|
13415
|
+
function isFooterAddItemDisabled(selected) {
|
|
13416
|
+
if (!selected) return false;
|
|
13417
|
+
const column = resolveFooterColumnForAdd(selected);
|
|
13418
|
+
return column ? !canAddFooterItem(column) : false;
|
|
13419
|
+
}
|
|
12739
13420
|
function resolveFooterColumnSelectionTarget(target, clientX, clientY) {
|
|
12740
13421
|
if (getNavigationItemAnchor(target)) return null;
|
|
12741
13422
|
const column = getFooterColumn(target);
|
|
@@ -12831,7 +13512,7 @@ function getNavigationSelectionParent(el) {
|
|
|
12831
13512
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
12832
13513
|
return getFooterLinksContainer();
|
|
12833
13514
|
}
|
|
12834
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
13515
|
+
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)) {
|
|
12835
13516
|
return getNavigationRoot(el);
|
|
12836
13517
|
}
|
|
12837
13518
|
return null;
|
|
@@ -13049,6 +13730,9 @@ var ICONS = {
|
|
|
13049
13730
|
var SELECTION_CHROME_GAP2 = 4;
|
|
13050
13731
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
13051
13732
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
13733
|
+
var HOVER_STROKE_WIDTH = 1.5;
|
|
13734
|
+
var TEXT_HOVER_SIDE_PAD = 4;
|
|
13735
|
+
var CHROME_PRIMARY = `var(--ohw-primary, ${PRIMARY3})`;
|
|
13052
13736
|
var TOOLBAR_GROUPS = [
|
|
13053
13737
|
[
|
|
13054
13738
|
{ cmd: "bold", title: "Bold" },
|
|
@@ -13074,7 +13758,7 @@ function EditGlowChrome({
|
|
|
13074
13758
|
hideHandle = false
|
|
13075
13759
|
}) {
|
|
13076
13760
|
const GAP = SELECTION_CHROME_GAP2;
|
|
13077
|
-
return /* @__PURE__ */
|
|
13761
|
+
return /* @__PURE__ */ jsxs20(
|
|
13078
13762
|
"div",
|
|
13079
13763
|
{
|
|
13080
13764
|
ref: elRef,
|
|
@@ -13089,7 +13773,7 @@ function EditGlowChrome({
|
|
|
13089
13773
|
zIndex: 2147483646
|
|
13090
13774
|
},
|
|
13091
13775
|
children: [
|
|
13092
|
-
/* @__PURE__ */
|
|
13776
|
+
/* @__PURE__ */ jsx33(
|
|
13093
13777
|
"div",
|
|
13094
13778
|
{
|
|
13095
13779
|
style: {
|
|
@@ -13102,7 +13786,7 @@ function EditGlowChrome({
|
|
|
13102
13786
|
}
|
|
13103
13787
|
}
|
|
13104
13788
|
),
|
|
13105
|
-
reorderHrefKey && !hideHandle && /* @__PURE__ */
|
|
13789
|
+
reorderHrefKey && !hideHandle && /* @__PURE__ */ jsx33(
|
|
13106
13790
|
"div",
|
|
13107
13791
|
{
|
|
13108
13792
|
"data-ohw-drag-handle-container": "",
|
|
@@ -13114,7 +13798,7 @@ function EditGlowChrome({
|
|
|
13114
13798
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
13115
13799
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
13116
13800
|
},
|
|
13117
|
-
children: /* @__PURE__ */
|
|
13801
|
+
children: /* @__PURE__ */ jsx33(
|
|
13118
13802
|
DragHandle,
|
|
13119
13803
|
{
|
|
13120
13804
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -13324,7 +14008,7 @@ function FloatingToolbar({
|
|
|
13324
14008
|
return () => ro.disconnect();
|
|
13325
14009
|
}, [showEditLink, activeCommands]);
|
|
13326
14010
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
|
|
13327
|
-
return /* @__PURE__ */
|
|
14011
|
+
return /* @__PURE__ */ jsx33(
|
|
13328
14012
|
"div",
|
|
13329
14013
|
{
|
|
13330
14014
|
ref: setRefs,
|
|
@@ -13336,12 +14020,12 @@ function FloatingToolbar({
|
|
|
13336
14020
|
zIndex: 2147483647,
|
|
13337
14021
|
pointerEvents: "auto"
|
|
13338
14022
|
},
|
|
13339
|
-
children: /* @__PURE__ */
|
|
13340
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */
|
|
13341
|
-
gi > 0 && /* @__PURE__ */
|
|
14023
|
+
children: /* @__PURE__ */ jsxs20(CustomToolbar, { children: [
|
|
14024
|
+
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs20(React11.Fragment, { children: [
|
|
14025
|
+
gi > 0 && /* @__PURE__ */ jsx33(CustomToolbarDivider, {}),
|
|
13342
14026
|
btns.map((btn) => {
|
|
13343
14027
|
const isActive = activeCommands.has(btn.cmd);
|
|
13344
|
-
return /* @__PURE__ */
|
|
14028
|
+
return /* @__PURE__ */ jsx33(
|
|
13345
14029
|
CustomToolbarButton,
|
|
13346
14030
|
{
|
|
13347
14031
|
title: btn.title,
|
|
@@ -13350,7 +14034,7 @@ function FloatingToolbar({
|
|
|
13350
14034
|
e.preventDefault();
|
|
13351
14035
|
onCommand(btn.cmd);
|
|
13352
14036
|
},
|
|
13353
|
-
children: /* @__PURE__ */
|
|
14037
|
+
children: /* @__PURE__ */ jsx33(
|
|
13354
14038
|
"svg",
|
|
13355
14039
|
{
|
|
13356
14040
|
width: "16",
|
|
@@ -13371,7 +14055,7 @@ function FloatingToolbar({
|
|
|
13371
14055
|
);
|
|
13372
14056
|
})
|
|
13373
14057
|
] }, gi)),
|
|
13374
|
-
showEditLink ? /* @__PURE__ */
|
|
14058
|
+
showEditLink ? /* @__PURE__ */ jsx33(
|
|
13375
14059
|
CustomToolbarButton,
|
|
13376
14060
|
{
|
|
13377
14061
|
type: "button",
|
|
@@ -13385,7 +14069,7 @@ function FloatingToolbar({
|
|
|
13385
14069
|
e.preventDefault();
|
|
13386
14070
|
e.stopPropagation();
|
|
13387
14071
|
},
|
|
13388
|
-
children: /* @__PURE__ */
|
|
14072
|
+
children: /* @__PURE__ */ jsx33(Link3, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
13389
14073
|
}
|
|
13390
14074
|
) : null
|
|
13391
14075
|
] })
|
|
@@ -13402,7 +14086,7 @@ function StateToggle({
|
|
|
13402
14086
|
states,
|
|
13403
14087
|
onStateChange
|
|
13404
14088
|
}) {
|
|
13405
|
-
return /* @__PURE__ */
|
|
14089
|
+
return /* @__PURE__ */ jsx33(
|
|
13406
14090
|
ToggleGroup,
|
|
13407
14091
|
{
|
|
13408
14092
|
"data-ohw-state-toggle": "",
|
|
@@ -13416,11 +14100,12 @@ function StateToggle({
|
|
|
13416
14100
|
left: rect.right - 8,
|
|
13417
14101
|
transform: "translateX(-100%)"
|
|
13418
14102
|
},
|
|
13419
|
-
children: states.map((state) => /* @__PURE__ */
|
|
14103
|
+
children: states.map((state) => /* @__PURE__ */ jsx33(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
13420
14104
|
}
|
|
13421
14105
|
);
|
|
13422
14106
|
}
|
|
13423
14107
|
var contentCache = /* @__PURE__ */ new Map();
|
|
14108
|
+
var fetchedContentPaths = /* @__PURE__ */ new Set();
|
|
13424
14109
|
function resolveSubdomain(subdomainFromQuery) {
|
|
13425
14110
|
if (subdomainFromQuery) return subdomainFromQuery;
|
|
13426
14111
|
if (typeof window !== "undefined") {
|
|
@@ -13515,8 +14200,14 @@ function OhhwellsBridge() {
|
|
|
13515
14200
|
});
|
|
13516
14201
|
const selectFrameRef = useRef9(() => {
|
|
13517
14202
|
});
|
|
14203
|
+
const selectLogoRef = useRef9(() => {
|
|
14204
|
+
});
|
|
14205
|
+
const openLogoSizePanelRef = useRef9(() => {
|
|
14206
|
+
});
|
|
13518
14207
|
const deselectRef = useRef9(() => {
|
|
13519
14208
|
});
|
|
14209
|
+
const closeFloatingPanelOnlyRef = useRef9(() => {
|
|
14210
|
+
});
|
|
13520
14211
|
const reselectNavigationItemRef = useRef9(() => {
|
|
13521
14212
|
});
|
|
13522
14213
|
const commitNavigationTextEditRef = useRef9(() => {
|
|
@@ -13549,15 +14240,34 @@ function OhhwellsBridge() {
|
|
|
13549
14240
|
const [hoveredNavContainerRect, setHoveredNavContainerRect] = useState11(null);
|
|
13550
14241
|
const hoveredItemElRef = useRef9(null);
|
|
13551
14242
|
const [hoveredItemRect, setHoveredItemRect] = useState11(null);
|
|
14243
|
+
const [hoveredTextRect, setHoveredTextRect] = useState11(null);
|
|
14244
|
+
useEffect12(() => {
|
|
14245
|
+
const sync = () => {
|
|
14246
|
+
const el = document.querySelector(
|
|
14247
|
+
"[data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key])"
|
|
14248
|
+
);
|
|
14249
|
+
const target = el && !el.closest("[data-ohw-href-key]") ? el : null;
|
|
14250
|
+
if (!target) {
|
|
14251
|
+
setHoveredTextRect(null);
|
|
14252
|
+
return;
|
|
14253
|
+
}
|
|
14254
|
+
const r2 = target.getBoundingClientRect();
|
|
14255
|
+
setHoveredTextRect(new DOMRect(r2.x - TEXT_HOVER_SIDE_PAD, r2.y, r2.width + TEXT_HOVER_SIDE_PAD * 2, r2.height));
|
|
14256
|
+
};
|
|
14257
|
+
const observer = new MutationObserver(sync);
|
|
14258
|
+
observer.observe(document.documentElement, {
|
|
14259
|
+
attributes: true,
|
|
14260
|
+
attributeFilter: ["data-ohw-hovered"],
|
|
14261
|
+
subtree: true
|
|
14262
|
+
});
|
|
14263
|
+
return () => observer.disconnect();
|
|
14264
|
+
}, []);
|
|
13552
14265
|
const siblingHintElRef = useRef9(null);
|
|
13553
14266
|
const [siblingHintRect, setSiblingHintRect] = useState11(null);
|
|
13554
14267
|
const [siblingHintRects, setSiblingHintRects] = useState11([]);
|
|
13555
14268
|
const [isItemDragging, setIsItemDragging] = useState11(false);
|
|
13556
14269
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = useState11(false);
|
|
13557
14270
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
13558
|
-
const [floatingPanel, setFloatingPanel] = useState11(null);
|
|
13559
|
-
const [floatingPanelPos, setFloatingPanelPos] = useState11(null);
|
|
13560
|
-
const [parentScrollSnap, setParentScrollSnap] = useState11(null);
|
|
13561
14271
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = useState11(null);
|
|
13562
14272
|
const [footerHeadingVisible, setFooterHeadingVisible] = useState11(null);
|
|
13563
14273
|
const footerDragRef = useRef9(null);
|
|
@@ -13572,7 +14282,15 @@ function OhhwellsBridge() {
|
|
|
13572
14282
|
const addNavAfterAnchorRef = useRef9(null);
|
|
13573
14283
|
const editContentRef = useRef9({});
|
|
13574
14284
|
const aiSectionsRef = useRef9("");
|
|
14285
|
+
const brandKitRef = useRef9("");
|
|
13575
14286
|
const pendingDeleteUndoRef = useRef9(null);
|
|
14287
|
+
const [floatingPanel, setFloatingPanel] = useState11(null);
|
|
14288
|
+
const floatingPanelOpenRef = useRef9(false);
|
|
14289
|
+
const setFloatingPanelRef = useRef9(setFloatingPanel);
|
|
14290
|
+
const [floatingPanelPos, setFloatingPanelPos] = useState11(null);
|
|
14291
|
+
const [logoSizeDraft, setLogoSizeDraft] = useState11(null);
|
|
14292
|
+
const [editorViewport, setEditorViewport] = useState11("desktop");
|
|
14293
|
+
const [parentScrollSnap, setParentScrollSnap] = useState11(null);
|
|
13576
14294
|
const [sitePages, setSitePages] = useState11([]);
|
|
13577
14295
|
const [sectionsByPath, setSectionsByPath] = useState11({});
|
|
13578
14296
|
const sectionsPrefetchGenRef = useRef9(0);
|
|
@@ -13581,7 +14299,18 @@ function OhhwellsBridge() {
|
|
|
13581
14299
|
const linkPopoverOpenRef = useRef9(false);
|
|
13582
14300
|
const linkPopoverGraceUntilRef = useRef9(0);
|
|
13583
14301
|
setLinkPopoverRef.current = setLinkPopover;
|
|
14302
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
13584
14303
|
linkPopoverSessionRef.current = linkPopover;
|
|
14304
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
14305
|
+
useEffect12(() => {
|
|
14306
|
+
const syncViewport = () => {
|
|
14307
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
14308
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
14309
|
+
};
|
|
14310
|
+
syncViewport();
|
|
14311
|
+
window.addEventListener("resize", syncViewport);
|
|
14312
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
14313
|
+
}, []);
|
|
13585
14314
|
const {
|
|
13586
14315
|
navDragRef,
|
|
13587
14316
|
navDropSlots,
|
|
@@ -13804,6 +14533,10 @@ function OhhwellsBridge() {
|
|
|
13804
14533
|
setIsItemDragging(false);
|
|
13805
14534
|
hoveredNavContainerRef.current = null;
|
|
13806
14535
|
setHoveredNavContainerRect(null);
|
|
14536
|
+
hoveredItemElRef.current = null;
|
|
14537
|
+
setHoveredItemRect(null);
|
|
14538
|
+
setFloatingPanel(null);
|
|
14539
|
+
setLogoSizeDraft(null);
|
|
13807
14540
|
if (!activeElRef.current) {
|
|
13808
14541
|
setNavGroupForceOpen(null, false);
|
|
13809
14542
|
setToolbarRect(null);
|
|
@@ -14000,6 +14733,14 @@ function OhhwellsBridge() {
|
|
|
14000
14733
|
if (!selected) return;
|
|
14001
14734
|
const socialsRow = isSocialsRow(selected) ? selected : findSocialsRow(selected);
|
|
14002
14735
|
if (socialsRow) {
|
|
14736
|
+
if (!canAddSocialItem(socialsRow)) {
|
|
14737
|
+
postToParent2({
|
|
14738
|
+
type: "ow:toast",
|
|
14739
|
+
title: `Maximum ${MAX_SOCIAL_ITEMS_PER_ROW} social icons`,
|
|
14740
|
+
toastType: "error"
|
|
14741
|
+
});
|
|
14742
|
+
return;
|
|
14743
|
+
}
|
|
14003
14744
|
const after = getSocialItem(selected);
|
|
14004
14745
|
const result2 = insertSocialItem(socialsRow, after, editContentRef.current);
|
|
14005
14746
|
if (!result2) return;
|
|
@@ -14021,10 +14762,16 @@ function OhhwellsBridge() {
|
|
|
14021
14762
|
return;
|
|
14022
14763
|
}
|
|
14023
14764
|
if (toolbarVariantRef.current === "select-frame" && isFooterFrameSelection) {
|
|
14024
|
-
|
|
14025
|
-
}
|
|
14026
|
-
const column = (selected.hasAttribute("data-ohw-footer-col") ? selected : null) ?? selected.closest("[data-ohw-footer-col]") ?? (listFooterColumns().includes(selected) ? selected : null);
|
|
14765
|
+
const column = resolveFooterColumnForAdd(selected);
|
|
14027
14766
|
if (!column) return;
|
|
14767
|
+
if (!canAddFooterItem(column)) {
|
|
14768
|
+
postToParent2({
|
|
14769
|
+
type: "ow:toast",
|
|
14770
|
+
title: `Maximum ${MAX_FOOTER_ITEMS_PER_COLUMN} items per column`,
|
|
14771
|
+
toastType: "error"
|
|
14772
|
+
});
|
|
14773
|
+
return;
|
|
14774
|
+
}
|
|
14028
14775
|
const result2 = insertFooterItem(column, "/", "New link", null);
|
|
14029
14776
|
applyLinkByKey(result2.hrefKey, result2.href);
|
|
14030
14777
|
document.querySelectorAll(`[data-ohw-key="${result2.labelKey}"]`).forEach((el) => {
|
|
@@ -14495,6 +15242,8 @@ function OhhwellsBridge() {
|
|
|
14495
15242
|
setToolbarRect(anchor.getBoundingClientRect());
|
|
14496
15243
|
setToolbarShowEditLink(false);
|
|
14497
15244
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
15245
|
+
setFloatingPanel(null);
|
|
15246
|
+
setLogoSizeDraft(null);
|
|
14498
15247
|
}, [deactivate, markSelected]);
|
|
14499
15248
|
const selectFrame = useCallback7((el) => {
|
|
14500
15249
|
if (!isNavigationContainer(el)) return;
|
|
@@ -14544,7 +15293,51 @@ function OhhwellsBridge() {
|
|
|
14544
15293
|
setToolbarRect(el.getBoundingClientRect());
|
|
14545
15294
|
setToolbarShowEditLink(false);
|
|
14546
15295
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
15296
|
+
setFloatingPanel(null);
|
|
15297
|
+
setLogoSizeDraft(null);
|
|
14547
15298
|
}, [deactivate, markSelected, postToParent2]);
|
|
15299
|
+
const selectLogo = useCallback7(
|
|
15300
|
+
(logoEl) => {
|
|
15301
|
+
if (activeElRef.current) deactivate();
|
|
15302
|
+
selectedElRef.current = logoEl;
|
|
15303
|
+
selectedHrefKeyRef.current = null;
|
|
15304
|
+
selectedFooterColAttrRef.current = null;
|
|
15305
|
+
markSelected(logoEl);
|
|
15306
|
+
setSelectedIsCta(false);
|
|
15307
|
+
setSelectedIsSocial(false);
|
|
15308
|
+
setSelectedIsSocialsRow(false);
|
|
15309
|
+
clearHrefKeyHover(logoEl);
|
|
15310
|
+
hoveredNavContainerRef.current = null;
|
|
15311
|
+
setHoveredNavContainerRect(null);
|
|
15312
|
+
setHoveredItemRect(null);
|
|
15313
|
+
hoveredItemElRef.current = null;
|
|
15314
|
+
siblingHintElRef.current = null;
|
|
15315
|
+
setSiblingHintRect(null);
|
|
15316
|
+
setSiblingHintRects([]);
|
|
15317
|
+
setIsItemDragging(false);
|
|
15318
|
+
setReorderHrefKey(null);
|
|
15319
|
+
setReorderDragDisabled(false);
|
|
15320
|
+
setIsFooterFrameSelection(false);
|
|
15321
|
+
setToolbarVariant("logo");
|
|
15322
|
+
setToolbarRect(getLogoInteractionRect(logoEl));
|
|
15323
|
+
setToolbarShowEditLink(false);
|
|
15324
|
+
setActiveCommands(/* @__PURE__ */ new Set());
|
|
15325
|
+
},
|
|
15326
|
+
[deactivate, markSelected]
|
|
15327
|
+
);
|
|
15328
|
+
const openLogoSizePanel = useCallback7((logoEl) => {
|
|
15329
|
+
const placement = getLogoPlacement(logoEl);
|
|
15330
|
+
const draft = readLogoSizeState(editContentRef.current, placement);
|
|
15331
|
+
setLogoSizeDraft(draft);
|
|
15332
|
+
setParentScrollSnap(parentScrollRef.current);
|
|
15333
|
+
setFloatingPanel({
|
|
15334
|
+
key: `logo-size:${placement}`,
|
|
15335
|
+
title: "Logo",
|
|
15336
|
+
context: placement === "navbar" ? "Navbar" : "Footer",
|
|
15337
|
+
kind: "logo-size",
|
|
15338
|
+
placement
|
|
15339
|
+
});
|
|
15340
|
+
}, []);
|
|
14548
15341
|
const openSocialsDisplayPanel = useCallback7((row) => {
|
|
14549
15342
|
setParentScrollSnap(parentScrollRef.current);
|
|
14550
15343
|
setFloatingPanel({
|
|
@@ -14580,11 +15373,53 @@ function OhhwellsBridge() {
|
|
|
14580
15373
|
);
|
|
14581
15374
|
const closeFloatingPanelOnly = useCallback7(() => {
|
|
14582
15375
|
setFloatingPanel(null);
|
|
15376
|
+
setLogoSizeDraft(null);
|
|
14583
15377
|
}, []);
|
|
14584
15378
|
const closeFloatingPanelAndDeselect = useCallback7(() => {
|
|
14585
15379
|
setFloatingPanel(null);
|
|
15380
|
+
setLogoSizeDraft(null);
|
|
14586
15381
|
deselectRef.current();
|
|
14587
15382
|
}, []);
|
|
15383
|
+
const persistLogoSizeDraft = useCallback7(
|
|
15384
|
+
(placement, draft) => {
|
|
15385
|
+
const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
|
|
15386
|
+
const mobileKey = LOGO_SIZE_MOBILE_KEYS[placement];
|
|
15387
|
+
const nodes = [
|
|
15388
|
+
{ key: desktopKey, text: String(draft.desktopPx) }
|
|
15389
|
+
];
|
|
15390
|
+
if (draft.mobileFollowing) {
|
|
15391
|
+
nodes.push({ key: mobileKey, text: "" });
|
|
15392
|
+
} else {
|
|
15393
|
+
nodes.push({ key: mobileKey, text: String(draft.mobilePx) });
|
|
15394
|
+
}
|
|
15395
|
+
editContentRef.current = {
|
|
15396
|
+
...editContentRef.current,
|
|
15397
|
+
[desktopKey]: String(draft.desktopPx),
|
|
15398
|
+
[mobileKey]: draft.mobileFollowing ? "" : String(draft.mobilePx)
|
|
15399
|
+
};
|
|
15400
|
+
applyLogoSizeToPlacement(
|
|
15401
|
+
placement,
|
|
15402
|
+
draft.desktopPx,
|
|
15403
|
+
draft.mobileFollowing ? draft.desktopPx : draft.mobilePx,
|
|
15404
|
+
draft.mobileFollowing
|
|
15405
|
+
);
|
|
15406
|
+
postToParent2({ type: "ow:change", nodes });
|
|
15407
|
+
requestAnimationFrame(() => {
|
|
15408
|
+
const selected = selectedElRef.current;
|
|
15409
|
+
if (!selected || toolbarVariantRef.current !== "logo") return;
|
|
15410
|
+
const rect = getLogoInteractionRect(selected);
|
|
15411
|
+
setToolbarRect(rect);
|
|
15412
|
+
if (glowElRef.current) {
|
|
15413
|
+
const GAP = SELECTION_CHROME_GAP2;
|
|
15414
|
+
glowElRef.current.style.top = `${rect.top - GAP}px`;
|
|
15415
|
+
glowElRef.current.style.left = `${rect.left - GAP}px`;
|
|
15416
|
+
glowElRef.current.style.width = `${rect.width + GAP * 2}px`;
|
|
15417
|
+
glowElRef.current.style.height = `${rect.height + GAP * 2}px`;
|
|
15418
|
+
}
|
|
15419
|
+
});
|
|
15420
|
+
},
|
|
15421
|
+
[postToParent2]
|
|
15422
|
+
);
|
|
14588
15423
|
const activate = useCallback7((el, options) => {
|
|
14589
15424
|
if (activeElRef.current === el) return;
|
|
14590
15425
|
if (isIconEditable(el)) return;
|
|
@@ -14665,7 +15500,37 @@ function OhhwellsBridge() {
|
|
|
14665
15500
|
deactivateRef.current = deactivate;
|
|
14666
15501
|
selectRef.current = select;
|
|
14667
15502
|
selectFrameRef.current = selectFrame;
|
|
15503
|
+
selectLogoRef.current = selectLogo;
|
|
15504
|
+
openLogoSizePanelRef.current = openLogoSizePanel;
|
|
14668
15505
|
deselectRef.current = deselect;
|
|
15506
|
+
closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
|
|
15507
|
+
const lastSiteWideScopeRef = useRef9(null);
|
|
15508
|
+
useEffect12(() => {
|
|
15509
|
+
if (!isEditMode) {
|
|
15510
|
+
if (lastSiteWideScopeRef.current !== false) {
|
|
15511
|
+
lastSiteWideScopeRef.current = false;
|
|
15512
|
+
postToParent2({ type: "ow:site-wide-scope", active: false });
|
|
15513
|
+
}
|
|
15514
|
+
return;
|
|
15515
|
+
}
|
|
15516
|
+
const active = isSiteWideScopeActive({
|
|
15517
|
+
selected: selectedElRef.current,
|
|
15518
|
+
hoveredItem: hoveredItemElRef.current,
|
|
15519
|
+
hoveredNavContainer: hoveredNavContainerRef.current,
|
|
15520
|
+
active: activeElRef.current
|
|
15521
|
+
});
|
|
15522
|
+
if (lastSiteWideScopeRef.current === active) return;
|
|
15523
|
+
lastSiteWideScopeRef.current = active;
|
|
15524
|
+
postToParent2({ type: "ow:site-wide-scope", active });
|
|
15525
|
+
}, [
|
|
15526
|
+
isEditMode,
|
|
15527
|
+
hoveredItemRect,
|
|
15528
|
+
hoveredNavContainerRect,
|
|
15529
|
+
toolbarVariant,
|
|
15530
|
+
toolbarRect,
|
|
15531
|
+
isFooterFrameSelection,
|
|
15532
|
+
postToParent2
|
|
15533
|
+
]);
|
|
14669
15534
|
useLayoutEffect4(() => {
|
|
14670
15535
|
if (!subdomain || isEditMode) {
|
|
14671
15536
|
setFetchState("done");
|
|
@@ -14677,9 +15542,18 @@ function OhhwellsBridge() {
|
|
|
14677
15542
|
aiSectionsRef.current = content[AI_SECTIONS_KEY];
|
|
14678
15543
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
14679
15544
|
}
|
|
15545
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
15546
|
+
brandKitRef.current = content[BRAND_KIT_KEY];
|
|
15547
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
15548
|
+
}
|
|
15549
|
+
applyBrandChrome(content);
|
|
14680
15550
|
for (const [key, val] of Object.entries(content)) {
|
|
14681
15551
|
if (key === "__ohw_sections") continue;
|
|
14682
15552
|
if (key === AI_SECTIONS_KEY) continue;
|
|
15553
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
15554
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
15555
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
15556
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
14683
15557
|
if (applyVideoSettingNode(key, val)) continue;
|
|
14684
15558
|
if (applyCarouselNode(key, val)) continue;
|
|
14685
15559
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -14714,6 +15588,8 @@ function OhhwellsBridge() {
|
|
|
14714
15588
|
});
|
|
14715
15589
|
applyLinkByKey(key, val);
|
|
14716
15590
|
}
|
|
15591
|
+
applyLogoFromContent(content);
|
|
15592
|
+
applyLogoSizes(content);
|
|
14717
15593
|
reconcileNavbarItemsFromContent(content);
|
|
14718
15594
|
reconcileFooterOrderFromContent(content);
|
|
14719
15595
|
reconcileSocialsFromContent(content);
|
|
@@ -14734,7 +15610,9 @@ function OhhwellsBridge() {
|
|
|
14734
15610
|
let cancelled = false;
|
|
14735
15611
|
setFetchState("loading");
|
|
14736
15612
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
14737
|
-
|
|
15613
|
+
const initialPath = pathname;
|
|
15614
|
+
fetchedContentPaths.add(`${subdomain}::${initialPath}`);
|
|
15615
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
14738
15616
|
if (cancelled) return;
|
|
14739
15617
|
const content = data?.content ?? {};
|
|
14740
15618
|
contentCache.set(subdomain, content);
|
|
@@ -14758,8 +15636,16 @@ function OhhwellsBridge() {
|
|
|
14758
15636
|
initSectionInstancesFromContent(content, window.location.pathname);
|
|
14759
15637
|
observer?.disconnect();
|
|
14760
15638
|
try {
|
|
15639
|
+
applyBrandChrome(content);
|
|
15640
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
15641
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
15642
|
+
}
|
|
14761
15643
|
for (const [key, val] of Object.entries(content)) {
|
|
14762
15644
|
if (key === "__ohw_sections") continue;
|
|
15645
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
15646
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
15647
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
15648
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
14763
15649
|
if (applyVideoSettingNode(key, val)) continue;
|
|
14764
15650
|
if (applyCarouselNode(key, val)) continue;
|
|
14765
15651
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -14780,6 +15666,7 @@ function OhhwellsBridge() {
|
|
|
14780
15666
|
});
|
|
14781
15667
|
applyLinkByKey(key, val);
|
|
14782
15668
|
}
|
|
15669
|
+
applyLogoFromContent(content);
|
|
14783
15670
|
reconcileNavbarItemsFromContent(content);
|
|
14784
15671
|
reconcileFooterOrderFromContent(content);
|
|
14785
15672
|
reconcileSocialsFromContent(content);
|
|
@@ -14794,6 +15681,17 @@ function OhhwellsBridge() {
|
|
|
14794
15681
|
debounceTimer = setTimeout(applyFromCache, 150);
|
|
14795
15682
|
};
|
|
14796
15683
|
applyFromCache();
|
|
15684
|
+
const pathCacheKey = `${subdomain}::${pathname}`;
|
|
15685
|
+
if (!fetchedContentPaths.has(pathCacheKey)) {
|
|
15686
|
+
fetchedContentPaths.add(pathCacheKey);
|
|
15687
|
+
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
15688
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
15689
|
+
if (!data?.content) return;
|
|
15690
|
+
contentCache.set(subdomain, data.content);
|
|
15691
|
+
applyFromCache();
|
|
15692
|
+
}).catch(() => {
|
|
15693
|
+
});
|
|
15694
|
+
}
|
|
14797
15695
|
observer = new MutationObserver(scheduleApply);
|
|
14798
15696
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
14799
15697
|
return () => {
|
|
@@ -14887,26 +15785,31 @@ function OhhwellsBridge() {
|
|
|
14887
15785
|
}, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
|
|
14888
15786
|
useEffect12(() => {
|
|
14889
15787
|
if (!isEditMode) return;
|
|
15788
|
+
let lastPosted = 0;
|
|
14890
15789
|
const measure = () => {
|
|
14891
15790
|
const h = document.body.scrollHeight;
|
|
14892
|
-
if (h > 50
|
|
15791
|
+
if (h > 50 && Math.abs(h - lastPosted) > 1) {
|
|
15792
|
+
lastPosted = h;
|
|
15793
|
+
postToParent2({ type: "ow:height", height: h });
|
|
15794
|
+
}
|
|
15795
|
+
};
|
|
15796
|
+
let raf = null;
|
|
15797
|
+
const schedule = () => {
|
|
15798
|
+
if (raf != null) return;
|
|
15799
|
+
raf = requestAnimationFrame(() => {
|
|
15800
|
+
raf = null;
|
|
15801
|
+
measure();
|
|
15802
|
+
});
|
|
14893
15803
|
};
|
|
14894
15804
|
const t1 = setTimeout(measure, 50);
|
|
14895
15805
|
const t2 = setTimeout(measure, 500);
|
|
14896
|
-
|
|
14897
|
-
|
|
14898
|
-
const handleResize = () => {
|
|
14899
|
-
if (window.innerWidth === lastWidth) return;
|
|
14900
|
-
lastWidth = window.innerWidth;
|
|
14901
|
-
if (resizeTimer) clearTimeout(resizeTimer);
|
|
14902
|
-
resizeTimer = setTimeout(measure, 150);
|
|
14903
|
-
};
|
|
14904
|
-
window.addEventListener("resize", handleResize);
|
|
15806
|
+
const ro = new ResizeObserver(schedule);
|
|
15807
|
+
ro.observe(document.body);
|
|
14905
15808
|
return () => {
|
|
14906
15809
|
clearTimeout(t1);
|
|
14907
15810
|
clearTimeout(t2);
|
|
14908
|
-
if (
|
|
14909
|
-
|
|
15811
|
+
if (raf != null) cancelAnimationFrame(raf);
|
|
15812
|
+
ro.disconnect();
|
|
14910
15813
|
};
|
|
14911
15814
|
}, [pathname, isEditMode, postToParent2]);
|
|
14912
15815
|
useEffect12(() => {
|
|
@@ -14976,9 +15879,12 @@ function OhhwellsBridge() {
|
|
|
14976
15879
|
[data-ohw-editable="video"], [data-ohw-editable="video"] *,
|
|
14977
15880
|
[data-ohw-editable="bg-image"], [data-ohw-editable="bg-image"] * { cursor: pointer !important; }
|
|
14978
15881
|
[data-ohw-editable="link"], [data-ohw-editable="link"] * { cursor: pointer !important; }
|
|
15882
|
+
/* Text hover chrome is drawn by the overlay (see hoveredTextRect) \u2014 the CSS outline
|
|
15883
|
+
that used to draw it dashes denser than the overlay border, so identical specs
|
|
15884
|
+
still read as two different frames (OHH-695). The attribute stays: hover paths
|
|
15885
|
+
and suppression rules key off it. */
|
|
14979
15886
|
[data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key]) {
|
|
14980
|
-
outline:
|
|
14981
|
-
outline-offset: 4px;
|
|
15887
|
+
outline: none !important;
|
|
14982
15888
|
}
|
|
14983
15889
|
[data-ohw-href-key] [data-ohw-hovered],
|
|
14984
15890
|
[data-ohw-href-key][data-ohw-hovered],
|
|
@@ -15031,8 +15937,11 @@ function OhhwellsBridge() {
|
|
|
15031
15937
|
stateViews.textContent = `
|
|
15032
15938
|
[data-ohw-state-view]:not([data-ohw-state-view="default"]) { display: none; }
|
|
15033
15939
|
[data-ohw-state-view="default"] [data-ohw-editable] { pointer-events: auto !important; }
|
|
15034
|
-
[data-ohw-state-hovered] { outline:
|
|
15940
|
+
[data-ohw-state-hovered] { outline: ${HOVER_STROKE_WIDTH}px dashed ${CHROME_PRIMARY} !important; outline-offset: ${HOVER_CHROME_GAP}px; }
|
|
15035
15941
|
[data-ohw-state-hovered]:has([data-ohw-hovered]) { outline: none !important; }
|
|
15942
|
+
/* :has() only sees descendants \u2014 when the card itself is the hovered text, the overlay
|
|
15943
|
+
already frames it, and the card outline doubled it (OHH-695). */
|
|
15944
|
+
[data-ohw-state-hovered][data-ohw-hovered] { outline: none !important; }
|
|
15036
15945
|
`;
|
|
15037
15946
|
document.head.appendChild(base);
|
|
15038
15947
|
document.head.appendChild(forceHover);
|
|
@@ -15050,10 +15959,12 @@ function OhhwellsBridge() {
|
|
|
15050
15959
|
return;
|
|
15051
15960
|
}
|
|
15052
15961
|
const target = e.target;
|
|
15962
|
+
if (target.closest("[data-ohw-ai-review]")) return;
|
|
15053
15963
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
15054
15964
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
15055
15965
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
15056
15966
|
if (isInsideLinkEditor(target)) return;
|
|
15967
|
+
if (isInsideFloatingPanel(target)) return;
|
|
15057
15968
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
15058
15969
|
const beneath = document.elementsFromPoint(e.clientX, e.clientY).find(
|
|
15059
15970
|
(el) => el instanceof HTMLElement && !el.closest("[data-ohw-bridge-root]") && el.closest("[data-ohw-section]") != null
|
|
@@ -15117,6 +16028,21 @@ function OhhwellsBridge() {
|
|
|
15117
16028
|
return;
|
|
15118
16029
|
}
|
|
15119
16030
|
}
|
|
16031
|
+
const logoEl = getLogoElement(target);
|
|
16032
|
+
if (logoEl) {
|
|
16033
|
+
e.preventDefault();
|
|
16034
|
+
e.stopPropagation();
|
|
16035
|
+
if (!logoHasUploadedImage(logoEl)) {
|
|
16036
|
+
deselectRef.current();
|
|
16037
|
+
deactivateRef.current();
|
|
16038
|
+
const identity = readLogoIdentityFromDom();
|
|
16039
|
+
postToParentRef.current({ type: "ow:open-logo-settings", ...identity });
|
|
16040
|
+
return;
|
|
16041
|
+
}
|
|
16042
|
+
selectLogoRef.current(logoEl);
|
|
16043
|
+
openLogoSizePanelRef.current(logoEl);
|
|
16044
|
+
return;
|
|
16045
|
+
}
|
|
15120
16046
|
const editable = target.closest("[data-ohw-editable]");
|
|
15121
16047
|
if (editable) {
|
|
15122
16048
|
if (editable.dataset.ohwEditable === "link") {
|
|
@@ -15269,10 +16195,12 @@ function OhhwellsBridge() {
|
|
|
15269
16195
|
};
|
|
15270
16196
|
const handleDblClick = (e) => {
|
|
15271
16197
|
const target = e.target;
|
|
16198
|
+
if (target.closest("[data-ohw-ai-review]")) return;
|
|
15272
16199
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
15273
16200
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
15274
16201
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
15275
16202
|
if (isInsideLinkEditor(target)) return;
|
|
16203
|
+
if (isInsideFloatingPanel(target)) return;
|
|
15276
16204
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
15277
16205
|
return;
|
|
15278
16206
|
}
|
|
@@ -15300,6 +16228,16 @@ function OhhwellsBridge() {
|
|
|
15300
16228
|
setHoveredNavContainerRect(null);
|
|
15301
16229
|
return;
|
|
15302
16230
|
}
|
|
16231
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || isInsideFloatingPanel(target) || isPointOverFloatingPanel(e.clientX, e.clientY)) {
|
|
16232
|
+
hoveredItemElRef.current = null;
|
|
16233
|
+
setHoveredItemRect(null);
|
|
16234
|
+
hoveredNavContainerRef.current = null;
|
|
16235
|
+
setHoveredNavContainerRect(null);
|
|
16236
|
+
siblingHintElRef.current = null;
|
|
16237
|
+
setSiblingHintRect(null);
|
|
16238
|
+
setSiblingHintRects([]);
|
|
16239
|
+
return;
|
|
16240
|
+
}
|
|
15303
16241
|
{
|
|
15304
16242
|
const selected2 = selectedElRef.current;
|
|
15305
16243
|
const selectedIsFooterColumn = Boolean(selected2) && !isFooterLinksContainer(selected2) && (selected2.hasAttribute("data-ohw-footer-col") || selected2.hasAttribute("data-ohw-footer-column") || Boolean(selected2.closest("footer") && isInferredFooterGroup2(selected2)));
|
|
@@ -15307,7 +16245,7 @@ function OhhwellsBridge() {
|
|
|
15307
16245
|
const allowFooterLinksHover = toolbarVariantRef.current !== "select-frame" || selectedIsFooterColumn;
|
|
15308
16246
|
if (allowNavContainerHover) {
|
|
15309
16247
|
const navContainer = target.closest("[data-ohw-nav-container]");
|
|
15310
|
-
if (navContainer && !getNavigationItemAnchor(target)) {
|
|
16248
|
+
if (navContainer && !getNavigationItemAnchor(target) && !getLogoElement(target)) {
|
|
15311
16249
|
hoveredNavContainerRef.current = navContainer;
|
|
15312
16250
|
setHoveredNavContainerRect(navContainer.getBoundingClientRect());
|
|
15313
16251
|
hoveredItemElRef.current = null;
|
|
@@ -15336,6 +16274,15 @@ function OhhwellsBridge() {
|
|
|
15336
16274
|
setHoveredNavContainerRect(null);
|
|
15337
16275
|
}
|
|
15338
16276
|
}
|
|
16277
|
+
const logoEl = getLogoElement(target);
|
|
16278
|
+
if (logoEl) {
|
|
16279
|
+
hoveredNavContainerRef.current = null;
|
|
16280
|
+
setHoveredNavContainerRect(null);
|
|
16281
|
+
if (selectedElRef.current === logoEl) return;
|
|
16282
|
+
hoveredItemElRef.current = logoEl;
|
|
16283
|
+
setHoveredItemRect(getLogoInteractionRect(logoEl));
|
|
16284
|
+
return;
|
|
16285
|
+
}
|
|
15339
16286
|
const navAnchor = getNavigationItemAnchor(target);
|
|
15340
16287
|
if (navAnchor) {
|
|
15341
16288
|
hoveredNavContainerRef.current = null;
|
|
@@ -15373,6 +16320,11 @@ function OhhwellsBridge() {
|
|
|
15373
16320
|
setHoveredItemRect(hoverTarget.getBoundingClientRect());
|
|
15374
16321
|
} else if (!isInsideNavigationItem(editable)) {
|
|
15375
16322
|
hoverTarget.setAttribute("data-ohw-hovered", "");
|
|
16323
|
+
if (editable.closest("footer") || editable.closest('[data-ohw-section="footer"]')) {
|
|
16324
|
+
hoveredNavContainerRef.current = null;
|
|
16325
|
+
setHoveredNavContainerRect(null);
|
|
16326
|
+
hoveredItemElRef.current = editable;
|
|
16327
|
+
}
|
|
15376
16328
|
}
|
|
15377
16329
|
}
|
|
15378
16330
|
};
|
|
@@ -15408,6 +16360,18 @@ function OhhwellsBridge() {
|
|
|
15408
16360
|
}
|
|
15409
16361
|
return;
|
|
15410
16362
|
}
|
|
16363
|
+
const logoEl = getLogoElement(target);
|
|
16364
|
+
if (logoEl) {
|
|
16365
|
+
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
16366
|
+
if (related2 && (logoEl === related2 || logoEl.contains(related2) || related2.closest?.('[data-ohw-role="logo"], [data-ohw-logo]'))) {
|
|
16367
|
+
return;
|
|
16368
|
+
}
|
|
16369
|
+
if (hoveredItemElRef.current === logoEl) {
|
|
16370
|
+
hoveredItemElRef.current = null;
|
|
16371
|
+
setHoveredItemRect(null);
|
|
16372
|
+
}
|
|
16373
|
+
return;
|
|
16374
|
+
}
|
|
15411
16375
|
const editable = target.closest("[data-ohw-editable]");
|
|
15412
16376
|
if (!editable) return;
|
|
15413
16377
|
const related = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
@@ -15428,6 +16392,13 @@ function OhhwellsBridge() {
|
|
|
15428
16392
|
}
|
|
15429
16393
|
} else {
|
|
15430
16394
|
hoverTarget.removeAttribute("data-ohw-hovered");
|
|
16395
|
+
if (hoveredItemElRef.current === editable) {
|
|
16396
|
+
const stillOnEditable = related instanceof Element && related.closest("[data-ohw-editable]") === editable;
|
|
16397
|
+
if (!stillOnEditable) {
|
|
16398
|
+
hoveredItemElRef.current = null;
|
|
16399
|
+
setHoveredItemRect(null);
|
|
16400
|
+
}
|
|
16401
|
+
}
|
|
15431
16402
|
}
|
|
15432
16403
|
}
|
|
15433
16404
|
};
|
|
@@ -15544,6 +16515,26 @@ function OhhwellsBridge() {
|
|
|
15544
16515
|
hoveredNavContainerRef.current = null;
|
|
15545
16516
|
setHoveredNavContainerRect(null);
|
|
15546
16517
|
}
|
|
16518
|
+
const logoCandidates = [
|
|
16519
|
+
...document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]'),
|
|
16520
|
+
...document.querySelectorAll("nav a:not([data-ohw-href-key]), [data-ohw-nav-root] a:not([data-ohw-href-key])"),
|
|
16521
|
+
...document.querySelectorAll("footer img")
|
|
16522
|
+
];
|
|
16523
|
+
const seenLogos = /* @__PURE__ */ new Set();
|
|
16524
|
+
for (const candidate of logoCandidates) {
|
|
16525
|
+
const logo = getLogoElement(candidate);
|
|
16526
|
+
if (!logo || seenLogos.has(logo)) continue;
|
|
16527
|
+
seenLogos.add(logo);
|
|
16528
|
+
const r2 = logo.getBoundingClientRect();
|
|
16529
|
+
if (x < r2.left || x > r2.right || y < r2.top || y > r2.bottom) continue;
|
|
16530
|
+
hoveredNavContainerRef.current = null;
|
|
16531
|
+
setHoveredNavContainerRect(null);
|
|
16532
|
+
if (selectedElRef.current !== logo) {
|
|
16533
|
+
hoveredItemElRef.current = logo;
|
|
16534
|
+
setHoveredItemRect(getLogoInteractionRect(logo));
|
|
16535
|
+
}
|
|
16536
|
+
return;
|
|
16537
|
+
}
|
|
15547
16538
|
const navContainers = Array.from(
|
|
15548
16539
|
document.querySelectorAll("[data-ohw-nav-container]")
|
|
15549
16540
|
);
|
|
@@ -15629,7 +16620,7 @@ function OhhwellsBridge() {
|
|
|
15629
16620
|
}
|
|
15630
16621
|
};
|
|
15631
16622
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
15632
|
-
if (linkPopoverOpenRef.current) {
|
|
16623
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
15633
16624
|
if (hoveredImageRef.current) {
|
|
15634
16625
|
hoveredImageRef.current = null;
|
|
15635
16626
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -15883,7 +16874,7 @@ function OhhwellsBridge() {
|
|
|
15883
16874
|
}
|
|
15884
16875
|
};
|
|
15885
16876
|
const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
|
|
15886
|
-
if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
|
|
16877
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || document.documentElement.hasAttribute("data-ohw-section-picking")) {
|
|
15887
16878
|
if (activeStateElRef.current) {
|
|
15888
16879
|
activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
|
|
15889
16880
|
activeStateElRef.current = null;
|
|
@@ -15951,6 +16942,19 @@ function OhhwellsBridge() {
|
|
|
15951
16942
|
};
|
|
15952
16943
|
const handleMouseMove = (e) => {
|
|
15953
16944
|
const { clientX, clientY } = e;
|
|
16945
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
16946
|
+
hoveredItemElRef.current = null;
|
|
16947
|
+
setHoveredItemRect(null);
|
|
16948
|
+
hoveredNavContainerRef.current = null;
|
|
16949
|
+
setHoveredNavContainerRect(null);
|
|
16950
|
+
siblingHintElRef.current = null;
|
|
16951
|
+
setSiblingHintRect(null);
|
|
16952
|
+
setSiblingHintRects([]);
|
|
16953
|
+
dismissImageHover();
|
|
16954
|
+
clearImageHover();
|
|
16955
|
+
setSectionGap(null);
|
|
16956
|
+
return;
|
|
16957
|
+
}
|
|
15954
16958
|
probeSectionGapAt(clientX, clientY);
|
|
15955
16959
|
probeImageAt(clientX, clientY);
|
|
15956
16960
|
probeHoverCardsAt(clientX, clientY);
|
|
@@ -15959,6 +16963,11 @@ function OhhwellsBridge() {
|
|
|
15959
16963
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
15960
16964
|
const { clientX, clientY } = e.data;
|
|
15961
16965
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
16966
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
16967
|
+
dismissImageHover();
|
|
16968
|
+
clearImageHover();
|
|
16969
|
+
return;
|
|
16970
|
+
}
|
|
15962
16971
|
probeSectionGapAt(clientX, clientY);
|
|
15963
16972
|
probeImageAt(clientX, clientY);
|
|
15964
16973
|
probeHoverCardsAt(clientX, clientY);
|
|
@@ -16208,6 +17217,11 @@ function OhhwellsBridge() {
|
|
|
16208
17217
|
aiSectionsRef.current = content[AI_SECTIONS_KEY];
|
|
16209
17218
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
16210
17219
|
}
|
|
17220
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
17221
|
+
brandKitRef.current = content[BRAND_KIT_KEY];
|
|
17222
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
17223
|
+
}
|
|
17224
|
+
applyBrandChrome(content);
|
|
16211
17225
|
let sectionsJson = null;
|
|
16212
17226
|
for (const [key, val] of Object.entries(content)) {
|
|
16213
17227
|
if (key === "__ohw_sections") {
|
|
@@ -16215,6 +17229,10 @@ function OhhwellsBridge() {
|
|
|
16215
17229
|
continue;
|
|
16216
17230
|
}
|
|
16217
17231
|
if (key === AI_SECTIONS_KEY) continue;
|
|
17232
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
17233
|
+
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
17234
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
17235
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
16218
17236
|
if (applyVideoSettingNode(key, val)) continue;
|
|
16219
17237
|
if (applyCarouselNode(key, val)) continue;
|
|
16220
17238
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -16234,6 +17252,8 @@ function OhhwellsBridge() {
|
|
|
16234
17252
|
});
|
|
16235
17253
|
applyLinkByKey(key, val);
|
|
16236
17254
|
}
|
|
17255
|
+
applyLogoFromContent(content);
|
|
17256
|
+
applyLogoSizes(content);
|
|
16237
17257
|
if (sectionsJson) {
|
|
16238
17258
|
initSectionsFromContent({ __ohw_sections: sectionsJson }, true);
|
|
16239
17259
|
sectionsLoadedRef.current = true;
|
|
@@ -16249,6 +17269,58 @@ function OhhwellsBridge() {
|
|
|
16249
17269
|
if (hydratedHeight > 50) postToParentRef.current({ type: "ow:height", height: hydratedHeight });
|
|
16250
17270
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
16251
17271
|
};
|
|
17272
|
+
const handleUpdateLogoIdentity = (e) => {
|
|
17273
|
+
if (e.data?.type !== "ow:update-logo-identity") return;
|
|
17274
|
+
const rawText = typeof e.data.text === "string" ? e.data.text : "";
|
|
17275
|
+
const alt = typeof e.data.alt === "string" ? e.data.alt : rawText;
|
|
17276
|
+
const href = typeof e.data.href === "string" ? e.data.href : void 0;
|
|
17277
|
+
const imageProvided = "image" in e.data;
|
|
17278
|
+
const imageUrl = imageProvided && typeof e.data.image === "string" && e.data.image.trim() ? e.data.image.trim() : imageProvided ? null : void 0;
|
|
17279
|
+
let isPlaceholder = e.data.isPlaceholder !== false;
|
|
17280
|
+
if (imageUrl) isPlaceholder = false;
|
|
17281
|
+
else if (imageProvided && imageUrl === null) {
|
|
17282
|
+
isPlaceholder = e.data.isPlaceholder === true || !rawText.trim() || resolveLogoDisplayText(rawText) === PLACEHOLDER_BUSINESS_NAME;
|
|
17283
|
+
}
|
|
17284
|
+
const display = applyLogoIdentity(rawText, isPlaceholder);
|
|
17285
|
+
const displayAlt = resolveLogoDisplayText(alt || display);
|
|
17286
|
+
if (imageUrl !== void 0) {
|
|
17287
|
+
applyLogoImage(imageUrl, displayAlt);
|
|
17288
|
+
} else {
|
|
17289
|
+
for (const key of LOGO_IMAGE_KEYS) {
|
|
17290
|
+
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
17291
|
+
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
17292
|
+
if (img) img.alt = displayAlt;
|
|
17293
|
+
});
|
|
17294
|
+
}
|
|
17295
|
+
}
|
|
17296
|
+
if (href !== void 0) {
|
|
17297
|
+
applyLogoHref(href);
|
|
17298
|
+
applyLinkByKey("nav-logo-href", href);
|
|
17299
|
+
applyLinkByKey("footer-logo-href", href);
|
|
17300
|
+
applyLinkByKey("logo-href", href);
|
|
17301
|
+
}
|
|
17302
|
+
const nodes = [
|
|
17303
|
+
...LOGO_TEXT_KEYS.map((key) => ({ key, text: display })),
|
|
17304
|
+
{ key: LOGO_PLACEHOLDER_KEY, text: isPlaceholder ? "true" : "false" },
|
|
17305
|
+
{ key: LOGO_ALT_KEY, text: displayAlt }
|
|
17306
|
+
];
|
|
17307
|
+
if (imageUrl !== void 0) {
|
|
17308
|
+
if (imageUrl) {
|
|
17309
|
+
for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: imageUrl });
|
|
17310
|
+
} else {
|
|
17311
|
+
for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: "" });
|
|
17312
|
+
}
|
|
17313
|
+
}
|
|
17314
|
+
if (href !== void 0) {
|
|
17315
|
+
for (const key of LOGO_HREF_KEYS) nodes.push({ key, text: href.trim() || "/" });
|
|
17316
|
+
}
|
|
17317
|
+
editContentRef.current = {
|
|
17318
|
+
...editContentRef.current,
|
|
17319
|
+
...Object.fromEntries(nodes.map(({ key, text }) => [key, text]))
|
|
17320
|
+
};
|
|
17321
|
+
applyLogoSizes(editContentRef.current);
|
|
17322
|
+
postToParentRef.current({ type: "ow:change", nodes });
|
|
17323
|
+
};
|
|
16252
17324
|
window.addEventListener("message", handleHydrate);
|
|
16253
17325
|
const postAiSectionsChanged = () => {
|
|
16254
17326
|
postToParentRef.current({
|
|
@@ -16305,6 +17377,17 @@ function OhhwellsBridge() {
|
|
|
16305
17377
|
postAiSectionsChanged();
|
|
16306
17378
|
};
|
|
16307
17379
|
window.addEventListener("message", handleAiSetSections);
|
|
17380
|
+
const handleAiSetBrand = (e) => {
|
|
17381
|
+
if (e.data?.type !== "ow:ai-set-brand") return;
|
|
17382
|
+
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
17383
|
+
const previous = brandKitRef.current;
|
|
17384
|
+
brandKitRef.current = value;
|
|
17385
|
+
applyBrandToDom(parseBrandKit(value));
|
|
17386
|
+
if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
|
|
17387
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
|
|
17388
|
+
postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
|
|
17389
|
+
};
|
|
17390
|
+
window.addEventListener("message", handleAiSetBrand);
|
|
16308
17391
|
const handleDeactivate = (e) => {
|
|
16309
17392
|
if (e.data?.type !== "ow:deactivate") return;
|
|
16310
17393
|
if (Date.now() < linkPopoverGraceUntilRef.current) return;
|
|
@@ -16313,6 +17396,12 @@ function OhhwellsBridge() {
|
|
|
16313
17396
|
closeLinkPopoverRef.current();
|
|
16314
17397
|
return;
|
|
16315
17398
|
}
|
|
17399
|
+
if (floatingPanelOpenRef.current) {
|
|
17400
|
+
setFloatingPanelRef.current(null);
|
|
17401
|
+
deselectRef.current();
|
|
17402
|
+
deactivateRef.current();
|
|
17403
|
+
return;
|
|
17404
|
+
}
|
|
16316
17405
|
deselectRef.current();
|
|
16317
17406
|
deactivateRef.current();
|
|
16318
17407
|
};
|
|
@@ -16332,6 +17421,10 @@ function OhhwellsBridge() {
|
|
|
16332
17421
|
closeLinkPopoverRef.current();
|
|
16333
17422
|
return;
|
|
16334
17423
|
}
|
|
17424
|
+
if (floatingPanelOpenRef.current) {
|
|
17425
|
+
closeFloatingPanelOnlyRef.current();
|
|
17426
|
+
return;
|
|
17427
|
+
}
|
|
16335
17428
|
if (activeElRef.current) {
|
|
16336
17429
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
16337
17430
|
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
@@ -16362,6 +17455,10 @@ function OhhwellsBridge() {
|
|
|
16362
17455
|
return;
|
|
16363
17456
|
}
|
|
16364
17457
|
if (selectedElRef.current) {
|
|
17458
|
+
if (toolbarVariantRef.current === "logo") {
|
|
17459
|
+
deselectRef.current();
|
|
17460
|
+
return;
|
|
17461
|
+
}
|
|
16365
17462
|
if (toolbarVariantRef.current === "select-frame") {
|
|
16366
17463
|
const parent2 = getNavigationSelectionParent(selectedElRef.current);
|
|
16367
17464
|
if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
|
|
@@ -16395,7 +17492,16 @@ function OhhwellsBridge() {
|
|
|
16395
17492
|
closeLinkPopoverRef.current();
|
|
16396
17493
|
return;
|
|
16397
17494
|
}
|
|
17495
|
+
if (e.key === "Escape" && floatingPanelOpenRef.current) {
|
|
17496
|
+
e.preventDefault();
|
|
17497
|
+
closeFloatingPanelOnlyRef.current();
|
|
17498
|
+
return;
|
|
17499
|
+
}
|
|
16398
17500
|
if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
|
|
17501
|
+
if (toolbarVariantRef.current === "logo") {
|
|
17502
|
+
deselectRef.current();
|
|
17503
|
+
return;
|
|
17504
|
+
}
|
|
16399
17505
|
if (toolbarVariantRef.current === "select-frame") {
|
|
16400
17506
|
const parent2 = getNavigationSelectionParent(selectedElRef.current);
|
|
16401
17507
|
if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
|
|
@@ -16473,7 +17579,8 @@ function OhhwellsBridge() {
|
|
|
16473
17579
|
const handleScroll = () => {
|
|
16474
17580
|
const focusEl = activeElRef.current ?? selectedElRef.current;
|
|
16475
17581
|
if (focusEl) {
|
|
16476
|
-
const
|
|
17582
|
+
const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : toolbarVariantRef.current === "logo" ? null : focusEl;
|
|
17583
|
+
const r2 = measureEl ? measureEl.getBoundingClientRect() : toolbarVariantRef.current === "logo" ? getLogoInteractionRect(focusEl) : focusEl.getBoundingClientRect();
|
|
16477
17584
|
applyToolbarPos(r2);
|
|
16478
17585
|
setToolbarRect(r2);
|
|
16479
17586
|
setMaxBadge((prev) => prev && activeElRef.current ? { ...prev, rect: r2 } : prev);
|
|
@@ -16483,7 +17590,9 @@ function OhhwellsBridge() {
|
|
|
16483
17590
|
setToggleState((prev) => prev ? { ...prev, rect } : null);
|
|
16484
17591
|
}
|
|
16485
17592
|
if (hoveredItemElRef.current) {
|
|
16486
|
-
|
|
17593
|
+
const hoverEl = hoveredItemElRef.current;
|
|
17594
|
+
const logo = getLogoElement(hoverEl);
|
|
17595
|
+
setHoveredItemRect(logo ? getLogoInteractionRect(logo) : hoverEl.getBoundingClientRect());
|
|
16487
17596
|
}
|
|
16488
17597
|
if (hoveredNavContainerRef.current) {
|
|
16489
17598
|
setHoveredNavContainerRect(hoveredNavContainerRef.current.getBoundingClientRect());
|
|
@@ -16527,6 +17636,9 @@ function OhhwellsBridge() {
|
|
|
16527
17636
|
if (aiSectionsRef.current) {
|
|
16528
17637
|
nodes.push({ key: AI_SECTIONS_KEY, type: "sections", text: aiSectionsRef.current });
|
|
16529
17638
|
}
|
|
17639
|
+
if (brandKitRef.current) {
|
|
17640
|
+
nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
|
|
17641
|
+
}
|
|
16530
17642
|
postToParentRef.current({ type: "ow:save-result", nodes });
|
|
16531
17643
|
};
|
|
16532
17644
|
const handleInsertSection = (e) => {
|
|
@@ -16537,8 +17649,12 @@ function OhhwellsBridge() {
|
|
|
16537
17649
|
if (inserted) {
|
|
16538
17650
|
const tracker = getSectionsTracker();
|
|
16539
17651
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
|
|
16540
|
-
const
|
|
16541
|
-
|
|
17652
|
+
const reportHeight = () => {
|
|
17653
|
+
const h = document.body.scrollHeight;
|
|
17654
|
+
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
17655
|
+
};
|
|
17656
|
+
reportHeight();
|
|
17657
|
+
setTimeout(reportHeight, 500);
|
|
16542
17658
|
}
|
|
16543
17659
|
};
|
|
16544
17660
|
const handleSwitchSchedule = (e) => {
|
|
@@ -16731,13 +17847,17 @@ function OhhwellsBridge() {
|
|
|
16731
17847
|
if (e.data?.type !== "ow:parent-scroll") return;
|
|
16732
17848
|
const { iframeOffsetTop, headerH, canvasH } = e.data;
|
|
16733
17849
|
parentScrollRef.current = { iframeOffsetTop, headerH, canvasH };
|
|
17850
|
+
if (floatingPanelOpenRef.current) {
|
|
17851
|
+
setParentScrollSnap({ iframeOffsetTop, headerH, canvasH });
|
|
17852
|
+
}
|
|
16734
17853
|
if (visibleViewportRef.current) {
|
|
16735
17854
|
applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
|
|
16736
17855
|
}
|
|
16737
17856
|
const focusEl = activeElRef.current ?? selectedElRef.current;
|
|
16738
17857
|
if (focusEl) {
|
|
16739
|
-
const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : focusEl;
|
|
16740
|
-
|
|
17858
|
+
const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : toolbarVariantRef.current === "logo" ? null : focusEl;
|
|
17859
|
+
const r2 = measureEl ? measureEl.getBoundingClientRect() : toolbarVariantRef.current === "logo" ? getLogoInteractionRect(focusEl) : focusEl.getBoundingClientRect();
|
|
17860
|
+
applyToolbarPos(r2);
|
|
16741
17861
|
}
|
|
16742
17862
|
};
|
|
16743
17863
|
const handleClickAt = (e) => {
|
|
@@ -16762,6 +17882,25 @@ function OhhwellsBridge() {
|
|
|
16762
17882
|
postToParentRef.current({ type: "ow:image-pick", key: stateCardImage.dataset.ohwKey ?? "", elementType: stateCardImage.dataset.ohwEditable ?? "image" });
|
|
16763
17883
|
return;
|
|
16764
17884
|
}
|
|
17885
|
+
const logoAtPoint = Array.from(
|
|
17886
|
+
document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]')
|
|
17887
|
+
).map((el) => getLogoElement(el)).find((logo) => {
|
|
17888
|
+
if (!logo) return false;
|
|
17889
|
+
const r2 = logo.getBoundingClientRect();
|
|
17890
|
+
return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
|
|
17891
|
+
});
|
|
17892
|
+
if (logoAtPoint) {
|
|
17893
|
+
if (!logoHasUploadedImage(logoAtPoint)) {
|
|
17894
|
+
deselectRef.current();
|
|
17895
|
+
deactivateRef.current();
|
|
17896
|
+
const identity = readLogoIdentityFromDom();
|
|
17897
|
+
postToParentRef.current({ type: "ow:open-logo-settings", ...identity });
|
|
17898
|
+
return;
|
|
17899
|
+
}
|
|
17900
|
+
selectLogoRef.current(logoAtPoint);
|
|
17901
|
+
openLogoSizePanelRef.current(logoAtPoint);
|
|
17902
|
+
return;
|
|
17903
|
+
}
|
|
16765
17904
|
const textEditable = Array.from(
|
|
16766
17905
|
document.querySelectorAll(NON_MEDIA_SELECTOR)
|
|
16767
17906
|
).find((el) => {
|
|
@@ -16833,6 +17972,14 @@ function OhhwellsBridge() {
|
|
|
16833
17972
|
window.addEventListener("message", handleParentScroll);
|
|
16834
17973
|
window.addEventListener("message", handlePointerSync);
|
|
16835
17974
|
window.addEventListener("message", handleClickAt);
|
|
17975
|
+
window.addEventListener("message", handleUpdateLogoIdentity);
|
|
17976
|
+
const handleViewMode = (e) => {
|
|
17977
|
+
if (e.data?.type !== "ow:view-mode") return;
|
|
17978
|
+
const mode = e.data.mode === "Mobile" || e.data.mode === "mobile" ? "mobile" : "desktop";
|
|
17979
|
+
setEditorViewport(mode);
|
|
17980
|
+
applyLogoSizes(editContentRef.current);
|
|
17981
|
+
};
|
|
17982
|
+
window.addEventListener("message", handleViewMode);
|
|
16836
17983
|
const handleViewportResize = () => {
|
|
16837
17984
|
if (visibleViewportRef.current) {
|
|
16838
17985
|
applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
|
|
@@ -16888,10 +18035,13 @@ function OhhwellsBridge() {
|
|
|
16888
18035
|
window.removeEventListener("resize", handleViewportResize);
|
|
16889
18036
|
window.removeEventListener("message", handlePointerSync);
|
|
16890
18037
|
window.removeEventListener("message", handleClickAt);
|
|
18038
|
+
window.removeEventListener("message", handleUpdateLogoIdentity);
|
|
18039
|
+
window.removeEventListener("message", handleViewMode);
|
|
16891
18040
|
window.removeEventListener("message", handleHydrate);
|
|
16892
18041
|
window.removeEventListener("message", handleAiApplyTree);
|
|
16893
18042
|
window.removeEventListener("message", handleAiDeleteSection);
|
|
16894
18043
|
window.removeEventListener("message", handleAiSetSections);
|
|
18044
|
+
window.removeEventListener("message", handleAiSetBrand);
|
|
16895
18045
|
window.removeEventListener("message", handleDeactivate);
|
|
16896
18046
|
window.removeEventListener("message", handleToastAction);
|
|
16897
18047
|
window.removeEventListener("message", handleUiEscape);
|
|
@@ -16917,7 +18067,7 @@ function OhhwellsBridge() {
|
|
|
16917
18067
|
if (footerDragRef.current) return;
|
|
16918
18068
|
const target = e.target;
|
|
16919
18069
|
if (!target) return;
|
|
16920
|
-
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]')) {
|
|
18070
|
+
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]')) {
|
|
16921
18071
|
return;
|
|
16922
18072
|
}
|
|
16923
18073
|
if (target.closest("[data-ohw-item-drag-surface]")) return;
|
|
@@ -17095,7 +18245,7 @@ function OhhwellsBridge() {
|
|
|
17095
18245
|
postToParent2({
|
|
17096
18246
|
type: "ow:ready",
|
|
17097
18247
|
version: "1",
|
|
17098
|
-
bridgeVersion: "0.1.
|
|
18248
|
+
bridgeVersion: "0.1.59",
|
|
17099
18249
|
path: pathname,
|
|
17100
18250
|
nodes: collectEditableNodes(editContentRef.current),
|
|
17101
18251
|
sections
|
|
@@ -17490,10 +18640,10 @@ function OhhwellsBridge() {
|
|
|
17490
18640
|
[postToParent2]
|
|
17491
18641
|
);
|
|
17492
18642
|
return bridgeRoot ? createPortal2(
|
|
17493
|
-
/* @__PURE__ */
|
|
17494
|
-
/* @__PURE__ */
|
|
17495
|
-
isEditMode && /* @__PURE__ */
|
|
17496
|
-
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */
|
|
18643
|
+
/* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
18644
|
+
/* @__PURE__ */ jsx33("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
18645
|
+
isEditMode && /* @__PURE__ */ jsx33(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
|
|
18646
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx33(
|
|
17497
18647
|
MediaOverlay,
|
|
17498
18648
|
{
|
|
17499
18649
|
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
@@ -17504,7 +18654,7 @@ function OhhwellsBridge() {
|
|
|
17504
18654
|
},
|
|
17505
18655
|
`uploading-${key}`
|
|
17506
18656
|
)),
|
|
17507
|
-
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */
|
|
18657
|
+
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx33(
|
|
17508
18658
|
MediaOverlay,
|
|
17509
18659
|
{
|
|
17510
18660
|
hover: mediaHover,
|
|
@@ -17513,11 +18663,11 @@ function OhhwellsBridge() {
|
|
|
17513
18663
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
17514
18664
|
}
|
|
17515
18665
|
),
|
|
17516
|
-
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */
|
|
17517
|
-
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */
|
|
17518
|
-
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */
|
|
17519
|
-
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */
|
|
17520
|
-
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */
|
|
18666
|
+
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
|
|
18667
|
+
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
18668
|
+
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
18669
|
+
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
18670
|
+
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
17521
18671
|
"div",
|
|
17522
18672
|
{
|
|
17523
18673
|
className: "pointer-events-none fixed z-2147483646",
|
|
@@ -17527,7 +18677,7 @@ function OhhwellsBridge() {
|
|
|
17527
18677
|
width: slot.width,
|
|
17528
18678
|
height: slot.height
|
|
17529
18679
|
},
|
|
17530
|
-
children: /* @__PURE__ */
|
|
18680
|
+
children: /* @__PURE__ */ jsx33(
|
|
17531
18681
|
DropIndicator,
|
|
17532
18682
|
{
|
|
17533
18683
|
direction: slot.direction,
|
|
@@ -17538,7 +18688,7 @@ function OhhwellsBridge() {
|
|
|
17538
18688
|
},
|
|
17539
18689
|
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
17540
18690
|
)),
|
|
17541
|
-
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */
|
|
18691
|
+
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
17542
18692
|
"div",
|
|
17543
18693
|
{
|
|
17544
18694
|
className: "pointer-events-none fixed z-2147483646",
|
|
@@ -17548,7 +18698,7 @@ function OhhwellsBridge() {
|
|
|
17548
18698
|
width: slot.width,
|
|
17549
18699
|
height: slot.height
|
|
17550
18700
|
},
|
|
17551
|
-
children: /* @__PURE__ */
|
|
18701
|
+
children: /* @__PURE__ */ jsx33(
|
|
17552
18702
|
DropIndicator,
|
|
17553
18703
|
{
|
|
17554
18704
|
direction: slot.direction,
|
|
@@ -17559,10 +18709,11 @@ function OhhwellsBridge() {
|
|
|
17559
18709
|
},
|
|
17560
18710
|
`nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
|
|
17561
18711
|
)),
|
|
17562
|
-
hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */
|
|
17563
|
-
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */
|
|
17564
|
-
|
|
17565
|
-
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current &&
|
|
18712
|
+
hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
18713
|
+
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
18714
|
+
hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
|
|
18715
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ jsx33(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
|
|
18716
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx33(
|
|
17566
18717
|
FooterContainerChrome,
|
|
17567
18718
|
{
|
|
17568
18719
|
rect: toolbarRect,
|
|
@@ -17570,7 +18721,7 @@ function OhhwellsBridge() {
|
|
|
17570
18721
|
addDisabled: !canAddFooterColumn()
|
|
17571
18722
|
}
|
|
17572
18723
|
),
|
|
17573
|
-
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */
|
|
18724
|
+
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ jsx33(
|
|
17574
18725
|
ItemInteractionLayer,
|
|
17575
18726
|
{
|
|
17576
18727
|
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
|
|
@@ -17582,10 +18733,10 @@ function OhhwellsBridge() {
|
|
|
17582
18733
|
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
17583
18734
|
onDragHandleDragStart: handleItemDragStart,
|
|
17584
18735
|
onDragHandleDragEnd: handleItemDragEnd,
|
|
17585
|
-
onItemPointerDown: handleItemChromePointerDown,
|
|
17586
|
-
onItemClick: handleItemChromeClick,
|
|
17587
|
-
itemDragSurface: !isFooterFrameSelection,
|
|
17588
|
-
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */
|
|
18736
|
+
onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
|
|
18737
|
+
onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
|
|
18738
|
+
itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
|
|
18739
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ jsx33(
|
|
17589
18740
|
ItemActionToolbar,
|
|
17590
18741
|
{
|
|
17591
18742
|
onEditLink: openLinkPopoverForSelected,
|
|
@@ -17601,7 +18752,10 @@ function OhhwellsBridge() {
|
|
|
17601
18752
|
onSelectParent: handleSelectParent,
|
|
17602
18753
|
onDuplicate: handleDuplicateSelected,
|
|
17603
18754
|
onDelete: handleDeleteSelected,
|
|
17604
|
-
addItemDisabled:
|
|
18755
|
+
addItemDisabled: isFooterFrameSelection && isFooterAddItemDisabled(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
18756
|
+
const row = isSocialsRow(selectedElRef.current) ? selectedElRef.current : findSocialsRow(selectedElRef.current);
|
|
18757
|
+
return row ? !canAddSocialItem(row) : false;
|
|
18758
|
+
})(),
|
|
17605
18759
|
editLinkDisabled: false,
|
|
17606
18760
|
moreDisabled: false,
|
|
17607
18761
|
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow,
|
|
@@ -17618,8 +18772,8 @@ function OhhwellsBridge() {
|
|
|
17618
18772
|
) : void 0
|
|
17619
18773
|
}
|
|
17620
18774
|
),
|
|
17621
|
-
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */
|
|
17622
|
-
/* @__PURE__ */
|
|
18775
|
+
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
18776
|
+
/* @__PURE__ */ jsx33(
|
|
17623
18777
|
EditGlowChrome,
|
|
17624
18778
|
{
|
|
17625
18779
|
rect: toolbarRect,
|
|
@@ -17629,7 +18783,7 @@ function OhhwellsBridge() {
|
|
|
17629
18783
|
hideHandle: isItemDragging
|
|
17630
18784
|
}
|
|
17631
18785
|
),
|
|
17632
|
-
/* @__PURE__ */
|
|
18786
|
+
/* @__PURE__ */ jsx33(
|
|
17633
18787
|
FloatingToolbar,
|
|
17634
18788
|
{
|
|
17635
18789
|
rect: toolbarRect,
|
|
@@ -17642,7 +18796,7 @@ function OhhwellsBridge() {
|
|
|
17642
18796
|
}
|
|
17643
18797
|
)
|
|
17644
18798
|
] }),
|
|
17645
|
-
maxBadge && /* @__PURE__ */
|
|
18799
|
+
maxBadge && /* @__PURE__ */ jsxs20(
|
|
17646
18800
|
"div",
|
|
17647
18801
|
{
|
|
17648
18802
|
"data-ohw-max-badge": "",
|
|
@@ -17668,7 +18822,7 @@ function OhhwellsBridge() {
|
|
|
17668
18822
|
]
|
|
17669
18823
|
}
|
|
17670
18824
|
),
|
|
17671
|
-
toggleState && !linkPopover && /* @__PURE__ */
|
|
18825
|
+
toggleState && !linkPopover && /* @__PURE__ */ jsx33(
|
|
17672
18826
|
StateToggle,
|
|
17673
18827
|
{
|
|
17674
18828
|
rect: toggleState.rect,
|
|
@@ -17677,15 +18831,15 @@ function OhhwellsBridge() {
|
|
|
17677
18831
|
onStateChange: handleStateChange
|
|
17678
18832
|
}
|
|
17679
18833
|
),
|
|
17680
|
-
sectionGap && !linkPopover && /* @__PURE__ */
|
|
18834
|
+
sectionGap && !linkPopover && /* @__PURE__ */ jsxs20(
|
|
17681
18835
|
"div",
|
|
17682
18836
|
{
|
|
17683
18837
|
"data-ohw-section-insert-line": "",
|
|
17684
18838
|
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
17685
18839
|
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
17686
18840
|
children: [
|
|
17687
|
-
/* @__PURE__ */
|
|
17688
|
-
/* @__PURE__ */
|
|
18841
|
+
/* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
18842
|
+
/* @__PURE__ */ jsx33(
|
|
17689
18843
|
Badge,
|
|
17690
18844
|
{
|
|
17691
18845
|
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",
|
|
@@ -17702,11 +18856,11 @@ function OhhwellsBridge() {
|
|
|
17702
18856
|
children: "Add Section"
|
|
17703
18857
|
}
|
|
17704
18858
|
),
|
|
17705
|
-
/* @__PURE__ */
|
|
18859
|
+
/* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
17706
18860
|
]
|
|
17707
18861
|
}
|
|
17708
18862
|
),
|
|
17709
|
-
linkPopover && dialogPortalContainer ? /* @__PURE__ */
|
|
18863
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx33(
|
|
17710
18864
|
LinkPopover,
|
|
17711
18865
|
{
|
|
17712
18866
|
panelRef: linkPopoverPanelRef,
|
|
@@ -17723,7 +18877,7 @@ function OhhwellsBridge() {
|
|
|
17723
18877
|
},
|
|
17724
18878
|
linkPopover.key
|
|
17725
18879
|
) : null,
|
|
17726
|
-
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */
|
|
18880
|
+
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ jsx33(
|
|
17727
18881
|
FloatingPanel,
|
|
17728
18882
|
{
|
|
17729
18883
|
open: true,
|
|
@@ -17733,7 +18887,7 @@ function OhhwellsBridge() {
|
|
|
17733
18887
|
onPositionChange: setFloatingPanelPos,
|
|
17734
18888
|
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
17735
18889
|
onClose: closeFloatingPanelOnly,
|
|
17736
|
-
children: /* @__PURE__ */
|
|
18890
|
+
children: /* @__PURE__ */ jsx33(
|
|
17737
18891
|
SocialsDisplayPanel,
|
|
17738
18892
|
{
|
|
17739
18893
|
display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
|
|
@@ -17744,11 +18898,115 @@ function OhhwellsBridge() {
|
|
|
17744
18898
|
}
|
|
17745
18899
|
)
|
|
17746
18900
|
}
|
|
18901
|
+
) : null,
|
|
18902
|
+
floatingPanel && floatingPanel.kind === "logo-size" && logoSizeDraft ? /* @__PURE__ */ jsx33(
|
|
18903
|
+
FloatingPanel,
|
|
18904
|
+
{
|
|
18905
|
+
open: true,
|
|
18906
|
+
title: floatingPanel.title,
|
|
18907
|
+
context: floatingPanel.context,
|
|
18908
|
+
position: floatingPanelPos,
|
|
18909
|
+
onPositionChange: setFloatingPanelPos,
|
|
18910
|
+
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
18911
|
+
onClose: closeFloatingPanelAndDeselect,
|
|
18912
|
+
children: /* @__PURE__ */ jsx33(
|
|
18913
|
+
LogoSizePanel,
|
|
18914
|
+
{
|
|
18915
|
+
viewport: editorViewport,
|
|
18916
|
+
sizePx: editorViewport === "mobile" && !logoSizeDraft.mobileFollowing ? logoSizeDraft.mobilePx : logoSizeDraft.desktopPx,
|
|
18917
|
+
mobileFollowing: logoSizeDraft.mobileFollowing,
|
|
18918
|
+
onSizeChange: (px) => {
|
|
18919
|
+
const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px, mobileFollowing: false } : {
|
|
18920
|
+
...logoSizeDraft,
|
|
18921
|
+
desktopPx: px,
|
|
18922
|
+
mobilePx: logoSizeDraft.mobileFollowing ? px : logoSizeDraft.mobilePx
|
|
18923
|
+
};
|
|
18924
|
+
setLogoSizeDraft(next);
|
|
18925
|
+
persistLogoSizeDraft(floatingPanel.placement, next);
|
|
18926
|
+
},
|
|
18927
|
+
onCustomizeMobile: () => {
|
|
18928
|
+
const next = {
|
|
18929
|
+
...logoSizeDraft,
|
|
18930
|
+
mobileFollowing: false,
|
|
18931
|
+
mobilePx: logoSizeDraft.desktopPx
|
|
18932
|
+
};
|
|
18933
|
+
setLogoSizeDraft(next);
|
|
18934
|
+
persistLogoSizeDraft(floatingPanel.placement, next);
|
|
18935
|
+
},
|
|
18936
|
+
onResetMobile: () => {
|
|
18937
|
+
const next = {
|
|
18938
|
+
...logoSizeDraft,
|
|
18939
|
+
mobileFollowing: true,
|
|
18940
|
+
mobilePx: logoSizeDraft.desktopPx
|
|
18941
|
+
};
|
|
18942
|
+
setLogoSizeDraft(next);
|
|
18943
|
+
persistLogoSizeDraft(floatingPanel.placement, next);
|
|
18944
|
+
},
|
|
18945
|
+
onUpdateEverywhere: () => {
|
|
18946
|
+
const identity = readLogoIdentityFromDom();
|
|
18947
|
+
postToParent2({ type: "ow:open-logo-settings", ...identity });
|
|
18948
|
+
}
|
|
18949
|
+
}
|
|
18950
|
+
)
|
|
18951
|
+
}
|
|
17747
18952
|
) : null
|
|
17748
18953
|
] }),
|
|
17749
18954
|
bridgeRoot
|
|
17750
18955
|
) : null;
|
|
17751
18956
|
}
|
|
18957
|
+
|
|
18958
|
+
// src/ui/EmptySection.tsx
|
|
18959
|
+
import Link4 from "next/link";
|
|
18960
|
+
import { Fragment as Fragment9, jsx as jsx34, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
18961
|
+
function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
|
|
18962
|
+
return /* @__PURE__ */ jsxs21(Fragment9, { children: [
|
|
18963
|
+
/* @__PURE__ */ jsx34(
|
|
18964
|
+
"p",
|
|
18965
|
+
{
|
|
18966
|
+
style: {
|
|
18967
|
+
fontFamily: "var(--brand-font-body)",
|
|
18968
|
+
fontSize: "0.75rem",
|
|
18969
|
+
fontWeight: 500,
|
|
18970
|
+
letterSpacing: "0.15em",
|
|
18971
|
+
textTransform: "uppercase",
|
|
18972
|
+
color: "var(--brand-accent)",
|
|
18973
|
+
marginBottom: "1.5rem"
|
|
18974
|
+
},
|
|
18975
|
+
children: /* @__PURE__ */ jsx34(Link4, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ jsx34("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
|
|
18976
|
+
}
|
|
18977
|
+
),
|
|
18978
|
+
/* @__PURE__ */ jsx34(
|
|
18979
|
+
"h1",
|
|
18980
|
+
{
|
|
18981
|
+
style: {
|
|
18982
|
+
fontFamily: "var(--brand-font-heading)",
|
|
18983
|
+
fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
|
|
18984
|
+
lineHeight: 1.1,
|
|
18985
|
+
letterSpacing: "-0.025em",
|
|
18986
|
+
color: "var(--brand-text)",
|
|
18987
|
+
marginBottom: "1rem"
|
|
18988
|
+
},
|
|
18989
|
+
...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
|
|
18990
|
+
children: title
|
|
18991
|
+
}
|
|
18992
|
+
),
|
|
18993
|
+
/* @__PURE__ */ jsx34(
|
|
18994
|
+
"p",
|
|
18995
|
+
{
|
|
18996
|
+
style: {
|
|
18997
|
+
fontFamily: "var(--brand-font-body)",
|
|
18998
|
+
fontSize: "1rem",
|
|
18999
|
+
lineHeight: 1.7,
|
|
19000
|
+
fontWeight: 300,
|
|
19001
|
+
color: "var(--brand-text-muted)",
|
|
19002
|
+
maxWidth: "340px"
|
|
19003
|
+
},
|
|
19004
|
+
...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
|
|
19005
|
+
children: "This page doesn't have any content yet."
|
|
19006
|
+
}
|
|
19007
|
+
)
|
|
19008
|
+
] });
|
|
19009
|
+
}
|
|
17752
19010
|
export {
|
|
17753
19011
|
AI_DEFAULT_BRAND,
|
|
17754
19012
|
AI_TREE_SCHEMA_VERSIONS,
|
|
@@ -17765,6 +19023,7 @@ export {
|
|
|
17765
19023
|
DropdownMenuItem,
|
|
17766
19024
|
DropdownMenuSeparator,
|
|
17767
19025
|
DropdownMenuTrigger,
|
|
19026
|
+
EmptySection,
|
|
17768
19027
|
ItemActionToolbar,
|
|
17769
19028
|
ItemInteractionLayer,
|
|
17770
19029
|
LinkEditorPanel,
|