@ohhwells/bridge 0.1.158 → 0.1.160-next.427
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/README.md +1 -1
- package/dist/index.cjs +1134 -722
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -1
- package/dist/index.d.ts +58 -1
- package/dist/index.js +1171 -743
- package/dist/index.js.map +1 -1
- package/dist/pages.cjs +9 -1
- package/dist/pages.cjs.map +1 -1
- package/dist/pages.d.cts +2 -0
- package/dist/pages.d.ts +2 -0
- package/dist/pages.js +9 -1
- package/dist/pages.js.map +1 -1
- package/dist/styles.css +116 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/OhhwellsBridge.tsx
|
|
4
|
-
import React12, { useCallback as useCallback12, useEffect as useEffect17, useLayoutEffect as
|
|
4
|
+
import React12, { useCallback as useCallback12, useEffect as useEffect17, useLayoutEffect as useLayoutEffect7, useRef as useRef14, useState as useState18 } from "react";
|
|
5
5
|
import { createRoot as createRoot3 } from "react-dom/client";
|
|
6
6
|
import { flushSync as flushSync3 } from "react-dom";
|
|
7
7
|
|
|
@@ -106,6 +106,56 @@ function isRenderableTree(value) {
|
|
|
106
106
|
return AI_TREE_SCHEMA_VERSIONS.includes(tree.schemaVersion) && tree.type === "section" && Array.isArray(tree.rows);
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
// src/lib/headline-size.ts
|
|
110
|
+
var HEADLINE_SIZE_MULTIPLIERS = {
|
|
111
|
+
xs: 0.7,
|
|
112
|
+
sm: 0.85,
|
|
113
|
+
base: 1,
|
|
114
|
+
lg: 1.2,
|
|
115
|
+
xl: 1.45,
|
|
116
|
+
"2xl": 1.75
|
|
117
|
+
};
|
|
118
|
+
var HEADLINE_SIZE_ATTR = "data-ohw-style-headlinesize";
|
|
119
|
+
var PREV_ATTR = "data-ohw-style-prev-fsmul";
|
|
120
|
+
var NODE_FONT_SIZE_ATTR = "data-ohw-style-prev-font-size";
|
|
121
|
+
function headingsIn(section) {
|
|
122
|
+
return Array.from(section.querySelectorAll("h1, h2, h3"));
|
|
123
|
+
}
|
|
124
|
+
function clearHeadlineSizes(root = document) {
|
|
125
|
+
for (const el of Array.from(root.querySelectorAll(`[${PREV_ATTR}]`))) {
|
|
126
|
+
const prev = el.getAttribute(PREV_ATTR) ?? "";
|
|
127
|
+
if (prev) el.style.setProperty("font-size", prev);
|
|
128
|
+
else el.style.removeProperty("font-size");
|
|
129
|
+
el.removeAttribute(PREV_ATTR);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function applyHeadlineSizes(root = document) {
|
|
133
|
+
clearHeadlineSizes(root);
|
|
134
|
+
for (const section of Array.from(
|
|
135
|
+
root.querySelectorAll(`[${HEADLINE_SIZE_ATTR}]`)
|
|
136
|
+
)) {
|
|
137
|
+
const multiplier = HEADLINE_SIZE_MULTIPLIERS[section.getAttribute(HEADLINE_SIZE_ATTR) ?? ""];
|
|
138
|
+
if (!multiplier || multiplier === 1) continue;
|
|
139
|
+
for (const heading of headingsIn(section)) {
|
|
140
|
+
if (heading.hasAttribute(NODE_FONT_SIZE_ATTR)) continue;
|
|
141
|
+
const base = Number.parseFloat(window.getComputedStyle(heading).fontSize);
|
|
142
|
+
if (!Number.isFinite(base) || base <= 0) continue;
|
|
143
|
+
heading.setAttribute(PREV_ATTR, heading.style.getPropertyValue("font-size"));
|
|
144
|
+
heading.style.setProperty("font-size", `${Math.round(base * multiplier * 100) / 100}px`, "important");
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
var resizeInstalled = false;
|
|
149
|
+
function installHeadlineSizeResize() {
|
|
150
|
+
if (resizeInstalled || typeof window === "undefined") return;
|
|
151
|
+
resizeInstalled = true;
|
|
152
|
+
let timer;
|
|
153
|
+
window.addEventListener("resize", () => {
|
|
154
|
+
if (timer) clearTimeout(timer);
|
|
155
|
+
timer = setTimeout(() => applyHeadlineSizes(), 120);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
109
159
|
// src/lib/sections.ts
|
|
110
160
|
var LINK_PICKER_EXCLUDED_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
111
161
|
function isChromeSection(el) {
|
|
@@ -5897,6 +5947,7 @@ var SECTION_ATTRS = {
|
|
|
5897
5947
|
sectionBackground: "data-ohw-style-bg",
|
|
5898
5948
|
textDistribution: "data-ohw-style-distribution",
|
|
5899
5949
|
headlineScale: "data-ohw-style-headline",
|
|
5950
|
+
headlineSize: HEADLINE_SIZE_ATTR,
|
|
5900
5951
|
imageAspect: "data-ohw-style-aspect",
|
|
5901
5952
|
spacing: "data-ohw-style-spacing",
|
|
5902
5953
|
verticalPadding: "data-ohw-style-vpadding",
|
|
@@ -5965,6 +6016,15 @@ function clearSectionAttrs(root) {
|
|
|
5965
6016
|
}
|
|
5966
6017
|
}
|
|
5967
6018
|
var ITEM_WROTE_ATTR = "data-ohw-style-item";
|
|
6019
|
+
function paintIcon(slot, color) {
|
|
6020
|
+
for (const el of [slot, ...Array.from(slot.querySelectorAll("svg, svg *"))]) {
|
|
6021
|
+
const styled = el;
|
|
6022
|
+
if (!styled.style) continue;
|
|
6023
|
+
saveInline(styled, "color");
|
|
6024
|
+
styled.style.setProperty("color", color, "important");
|
|
6025
|
+
styled.setAttribute(NODE_WROTE_ATTR, "");
|
|
6026
|
+
}
|
|
6027
|
+
}
|
|
5968
6028
|
function clearNodeProps(root) {
|
|
5969
6029
|
for (const el of Array.from(root.querySelectorAll(`[${NODE_WROTE_ATTR}]`))) {
|
|
5970
6030
|
const h = el;
|
|
@@ -6002,6 +6062,7 @@ function applyStylesToDom(store) {
|
|
|
6002
6062
|
ensureStyleSheet();
|
|
6003
6063
|
clearSectionAttrs(document);
|
|
6004
6064
|
clearNodeProps(document);
|
|
6065
|
+
clearHeadlineSizes(document);
|
|
6005
6066
|
loadStyleFonts(
|
|
6006
6067
|
store ? [
|
|
6007
6068
|
...Object.values(store.nodes).flatMap((n) => n.fontFamily ? [n.fontFamily] : []),
|
|
@@ -6075,9 +6136,13 @@ function applyStylesToDom(store) {
|
|
|
6075
6136
|
const nodes = document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`);
|
|
6076
6137
|
for (const el of Array.from(nodes)) {
|
|
6077
6138
|
if (override.color !== void 0) {
|
|
6078
|
-
|
|
6079
|
-
|
|
6080
|
-
|
|
6139
|
+
if (el.dataset.ohwEditable === "icon") {
|
|
6140
|
+
paintIcon(el, override.color);
|
|
6141
|
+
} else {
|
|
6142
|
+
saveInline(el, "color");
|
|
6143
|
+
el.style.setProperty("color", override.color, "important");
|
|
6144
|
+
el.setAttribute(NODE_WROTE_ATTR, "");
|
|
6145
|
+
}
|
|
6081
6146
|
}
|
|
6082
6147
|
if (override.fontFamily !== void 0) {
|
|
6083
6148
|
saveInline(el, "font-family");
|
|
@@ -6134,6 +6199,18 @@ function applyStylesToDom(store) {
|
|
|
6134
6199
|
}
|
|
6135
6200
|
}
|
|
6136
6201
|
}
|
|
6202
|
+
for (const [sectionId, override] of Object.entries(store.sections)) {
|
|
6203
|
+
if (override.iconColor === void 0) continue;
|
|
6204
|
+
const escaped = CSS.escape(sectionId);
|
|
6205
|
+
const byInstance = document.querySelectorAll(`[data-ohw-instance="${escaped}"]`);
|
|
6206
|
+
const sections = byInstance.length ? byInstance : document.querySelectorAll(`[data-ohw-section="${escaped}"]`);
|
|
6207
|
+
for (const marker of Array.from(sections)) {
|
|
6208
|
+
const icons = marker.querySelectorAll('[data-ohw-editable="icon"]');
|
|
6209
|
+
for (const el of Array.from(icons)) paintIcon(el, override.iconColor);
|
|
6210
|
+
}
|
|
6211
|
+
}
|
|
6212
|
+
applyHeadlineSizes(document);
|
|
6213
|
+
installHeadlineSizeResize();
|
|
6137
6214
|
}
|
|
6138
6215
|
|
|
6139
6216
|
// src/lib/ai-sections-store.ts
|
|
@@ -6173,17 +6250,21 @@ function resolveSectionTree(sectionId, aiSectionsRaw) {
|
|
|
6173
6250
|
return parseAiSectionsState(aiSectionsRaw).sections.find((entry) => entry.id === sectionId)?.tree;
|
|
6174
6251
|
}
|
|
6175
6252
|
function resolveSectionSettingsContext(sectionId, aiSectionsRaw, stylesRaw) {
|
|
6253
|
+
const styleOverride = parseStyleStore(stylesRaw)?.sections[sectionId];
|
|
6254
|
+
const headlineSize = styleOverride?.headlineSize;
|
|
6176
6255
|
const genSettings = parseAiSectionsState(aiSectionsRaw).sections.find(
|
|
6177
6256
|
(entry) => entry.id === sectionId
|
|
6178
6257
|
)?.tree.settings;
|
|
6179
|
-
if (genSettings)
|
|
6180
|
-
|
|
6181
|
-
|
|
6258
|
+
if (genSettings) {
|
|
6259
|
+
return { ...genSettings, ...headlineSize ? { headlineSize } : {} };
|
|
6260
|
+
}
|
|
6261
|
+
if (!styleOverride?.verticalPadding && !styleOverride?.minHeight && !styleOverride?.spacing && !headlineSize) {
|
|
6182
6262
|
return void 0;
|
|
6183
6263
|
}
|
|
6184
6264
|
return {
|
|
6185
|
-
verticalPadding: styleOverride
|
|
6186
|
-
minHeight: styleOverride
|
|
6265
|
+
verticalPadding: styleOverride?.verticalPadding ?? legacyVerticalPaddingAlias(styleOverride?.spacing),
|
|
6266
|
+
minHeight: styleOverride?.minHeight,
|
|
6267
|
+
...headlineSize ? { headlineSize } : {}
|
|
6187
6268
|
};
|
|
6188
6269
|
}
|
|
6189
6270
|
function applyTreeToState(state, payload) {
|
|
@@ -6568,6 +6649,21 @@ function pricingCardFeatureCount(tree, index) {
|
|
|
6568
6649
|
const target = findPricingCollection(tree)?.children?.[index];
|
|
6569
6650
|
return target ? pricingFeatureList(target).length : 0;
|
|
6570
6651
|
}
|
|
6652
|
+
function prevailingFeatureIcon(features) {
|
|
6653
|
+
const counts = /* @__PURE__ */ new Map();
|
|
6654
|
+
for (const row of features) {
|
|
6655
|
+
const key = `${row.icon ?? ""}|${row.iconColor ?? ""}`;
|
|
6656
|
+
const entry = counts.get(key) ?? { count: 0, ...row.icon ? { icon: row.icon } : {}, ...row.iconColor ? { iconColor: row.iconColor } : {} };
|
|
6657
|
+
entry.count += 1;
|
|
6658
|
+
counts.set(key, entry);
|
|
6659
|
+
}
|
|
6660
|
+
let best = null;
|
|
6661
|
+
for (const entry of counts.values()) {
|
|
6662
|
+
if (!best || entry.count > best.count) best = entry;
|
|
6663
|
+
}
|
|
6664
|
+
if (!best) return {};
|
|
6665
|
+
return { ...best.icon ? { icon: best.icon } : {}, ...best.iconColor ? { iconColor: best.iconColor } : {} };
|
|
6666
|
+
}
|
|
6571
6667
|
function addPricingCardFeature(tree, index, text) {
|
|
6572
6668
|
return withPricingCollection(tree, (collection) => {
|
|
6573
6669
|
const children = collection.children;
|
|
@@ -6576,7 +6672,7 @@ function addPricingCardFeature(tree, index, text) {
|
|
|
6576
6672
|
const features = pricingFeatureList(target);
|
|
6577
6673
|
if (features.length >= PRICING_FEATURES_MAX) return false;
|
|
6578
6674
|
target.slots = target.slots ?? {};
|
|
6579
|
-
target.slots.features = [...features, { text }];
|
|
6675
|
+
target.slots.features = [...features, { text, ...prevailingFeatureIcon(features) }];
|
|
6580
6676
|
return true;
|
|
6581
6677
|
});
|
|
6582
6678
|
}
|
|
@@ -7188,6 +7284,23 @@ function applyCustomCodeToHead(content) {
|
|
|
7188
7284
|
if (beforeNodes.length > 0) document.head.append(...beforeNodes);
|
|
7189
7285
|
}
|
|
7190
7286
|
|
|
7287
|
+
// src/lib/node-font-size.ts
|
|
7288
|
+
var TEXT_NODE_TYPES = /* @__PURE__ */ new Set(["text", "text/rich", "plain", "link"]);
|
|
7289
|
+
function escapeKey(key) {
|
|
7290
|
+
return typeof CSS !== "undefined" && typeof CSS.escape === "function" ? CSS.escape(key) : key.replace(/["\\]/g, "\\$&");
|
|
7291
|
+
}
|
|
7292
|
+
function measureNodeFontSize(key, type, root) {
|
|
7293
|
+
if (!TEXT_NODE_TYPES.has(type)) return void 0;
|
|
7294
|
+
const el = root.querySelector(`[data-ohw-editable][data-ohw-key="${escapeKey(key)}"]`);
|
|
7295
|
+
if (!el) return void 0;
|
|
7296
|
+
const size = Number.parseFloat(window.getComputedStyle(el).fontSize);
|
|
7297
|
+
return Number.isFinite(size) && size > 0 ? Math.round(size) : void 0;
|
|
7298
|
+
}
|
|
7299
|
+
function withNodeFontSize(node, root) {
|
|
7300
|
+
const fontSize = measureNodeFontSize(node.key, node.type, root);
|
|
7301
|
+
return fontSize === void 0 ? node : { ...node, fontSize };
|
|
7302
|
+
}
|
|
7303
|
+
|
|
7191
7304
|
// src/lib/selectNavContainer.ts
|
|
7192
7305
|
function isOnScreen(el) {
|
|
7193
7306
|
const rect = el.getBoundingClientRect();
|
|
@@ -7776,7 +7889,7 @@ var AI_MOBILE_CSS = [
|
|
|
7776
7889
|
// page's first section. Top only (bottom needs no nav clearance); ~96px approximates the
|
|
7777
7890
|
// template nav's own height (measured ~94px) — there's no shared `--ohw-header-h` var to read
|
|
7778
7891
|
// an exact figure from (no live measurement exists), so this is a safe approximation, not a
|
|
7779
|
-
// pixel-exact fit. Horizontal spacing already comes from `data-ai-
|
|
7892
|
+
// pixel-exact fit. Horizontal spacing already comes from `data-ai-section-inner`.
|
|
7780
7893
|
'[data-ai-overlay-clearance] [data-ai-overlap-layer="overlay"]{padding-top:96px}',
|
|
7781
7894
|
// A full-bleed carousel's height is pure arithmetic: it spans the whole window, so 16/9 turns
|
|
7782
7895
|
// window width straight into height. Measured at 16/9 it came out ~90% of the viewport at EVERY
|
|
@@ -7792,8 +7905,10 @@ var AI_MOBILE_CSS = [
|
|
|
7792
7905
|
"[data-ai-section]{overflow-x:hidden}",
|
|
7793
7906
|
// `:not([data-ai-full-bleed])`: this `!important` gutter beat the inline `padding: 0` that a
|
|
7794
7907
|
// full-bleed section's container sets, so a carousel/media hero that is edge-to-edge on desktop
|
|
7795
|
-
// still got a 20px band of section background down both sides on a phone.
|
|
7796
|
-
|
|
7908
|
+
// still got a 20px band of section background down both sides on a phone. The footer's own
|
|
7909
|
+
// container keeps the unguarded rule below — `data-ai-full-bleed` can never appear on it.
|
|
7910
|
+
"[data-ai-section-inner]:not([data-ai-full-bleed]){padding:0 20px !important}",
|
|
7911
|
+
"[data-ai-container]{padding:0 20px !important}",
|
|
7797
7912
|
"[data-ai-row]{display:flex !important;flex-direction:column !important;align-items:stretch !important}",
|
|
7798
7913
|
"[data-ai-cell]{width:100%;min-width:0}",
|
|
7799
7914
|
// The rule above turns every row into a COLUMN flex container on phones, which silently breaks
|
|
@@ -7998,6 +8113,31 @@ function pricingCardEmphasis(featured, ctx, hasBg) {
|
|
|
7998
8113
|
function textAttrs(ctx, path) {
|
|
7999
8114
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
8000
8115
|
}
|
|
8116
|
+
var AI_RESPONSIVE_CSS = [
|
|
8117
|
+
"@media (max-width: 960px) {",
|
|
8118
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
|
|
8119
|
+
' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
|
|
8120
|
+
"}",
|
|
8121
|
+
"@media (max-width: 640px) {",
|
|
8122
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
8123
|
+
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
8124
|
+
// Group containers flatten to a column on phones; span placements come along for free.
|
|
8125
|
+
// `:not([data-ai-group="overlap"])` for the same reason as the twin pair in AI_MOBILE_CSS — see
|
|
8126
|
+
// the comment there. This sheet's copy is the narrower selector, so without the exemption it
|
|
8127
|
+
// flattens an `overlap` hero below 640px even though the other rule stands down: measured a 390px
|
|
8128
|
+
// viewport with the heading/CTA in flow *under* the image, 219px of section background where the
|
|
8129
|
+
// layered text used to be.
|
|
8130
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) { display: flex !important; flex-direction: column !important; }',
|
|
8131
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) > * { grid-column: auto !important; }',
|
|
8132
|
+
// `:not([data-ai-full-bleed])` for the same reason as the twin rule in AI_MOBILE_CSS: this one
|
|
8133
|
+
// is narrower (0,2,0 vs 0,1,0) and also `!important`, so without the guard it wins outright and
|
|
8134
|
+
// a full-bleed hero gets its 20px side band back below 640px only — the one width where the
|
|
8135
|
+
// other rule had already been taught to stand down.
|
|
8136
|
+
" [data-ai-responsive] [data-ai-section-inner]:not([data-ai-full-bleed]) { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
8137
|
+
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
8138
|
+
" [data-ai-responsive] img { max-width: 100%; }",
|
|
8139
|
+
"}"
|
|
8140
|
+
].join("\n");
|
|
8001
8141
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
8002
8142
|
function MediaBox({
|
|
8003
8143
|
refValue,
|
|
@@ -8052,7 +8192,7 @@ function MediaBox({
|
|
|
8052
8192
|
position: fill ? "absolute" : void 0,
|
|
8053
8193
|
inset: fill ? 0 : void 0,
|
|
8054
8194
|
width: fill ? "100%" : fixedSize ? "auto" : "100%",
|
|
8055
|
-
height: fill ? "100%" : void 0,
|
|
8195
|
+
height: fill ? "100%" : fixedSize ? height : void 0,
|
|
8056
8196
|
aspectRatio: fill ? void 0 : aspectRatio,
|
|
8057
8197
|
minHeight: fill || fixedSize ? void 0 : height ?? (aspectRatio ? void 0 : 180),
|
|
8058
8198
|
borderRadius: radius,
|
|
@@ -9548,7 +9688,7 @@ function CollectionBlock({ node, ctx, path }) {
|
|
|
9548
9688
|
return /* @__PURE__ */ jsx(
|
|
9549
9689
|
"div",
|
|
9550
9690
|
{
|
|
9551
|
-
"data-ai-grid":
|
|
9691
|
+
"data-ai-grid": String(itemsPerRow),
|
|
9552
9692
|
"data-ohw-pricing-collection": isPricing ? "" : void 0,
|
|
9553
9693
|
style: {
|
|
9554
9694
|
display: "grid",
|
|
@@ -9850,7 +9990,7 @@ function renderNode(node, ctx, path, ambientAlign) {
|
|
|
9850
9990
|
},
|
|
9851
9991
|
children: [
|
|
9852
9992
|
i > 0 && ctx.heroOverlapFullBleed ? (
|
|
9853
|
-
// The section's `data-ai-
|
|
9993
|
+
// The section's `data-ai-section-inner` gave up its max-width/gutter so the base
|
|
9854
9994
|
// layer (this group's i===0 sibling) can span edge-to-edge — reintroduced here,
|
|
9855
9995
|
// scoped to just the overlay text, so a heading/copy/CTA stack doesn't stretch
|
|
9856
9996
|
// the full section width instead of reading at the usual content width.
|
|
@@ -10269,6 +10409,7 @@ function AiTreeRenderer({
|
|
|
10269
10409
|
...fillHeight ? { "data-ai-fill-height": "" } : {},
|
|
10270
10410
|
...needsOverlayClearance ? { "data-ai-overlay-clearance": "" } : {},
|
|
10271
10411
|
...bgAttrs,
|
|
10412
|
+
"data-ai-responsive": "",
|
|
10272
10413
|
style: {
|
|
10273
10414
|
position: "relative",
|
|
10274
10415
|
padding: `${padCss} 0`,
|
|
@@ -10282,12 +10423,13 @@ function AiTreeRenderer({
|
|
|
10282
10423
|
...fillHeight ? { display: "grid" } : {}
|
|
10283
10424
|
},
|
|
10284
10425
|
children: [
|
|
10285
|
-
|
|
10426
|
+
/* @__PURE__ */ jsx("style", { children: AI_RESPONSIVE_CSS }),
|
|
10286
10427
|
/* @__PURE__ */ jsx("style", { children: AI_MOBILE_CSS }),
|
|
10428
|
+
isOverlay && backgroundUrl && /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
10287
10429
|
/* @__PURE__ */ jsx(
|
|
10288
10430
|
"div",
|
|
10289
10431
|
{
|
|
10290
|
-
"data-ai-
|
|
10432
|
+
"data-ai-section-inner": "",
|
|
10291
10433
|
...fullBleedMedia ? { "data-ai-full-bleed": "" } : {},
|
|
10292
10434
|
style: {
|
|
10293
10435
|
position: "relative",
|
|
@@ -10304,7 +10446,7 @@ function AiTreeRenderer({
|
|
|
10304
10446
|
children: tree.rows.map((row, r2) => /* @__PURE__ */ jsx(
|
|
10305
10447
|
"div",
|
|
10306
10448
|
{
|
|
10307
|
-
"data-ai-
|
|
10449
|
+
"data-ai-columns": "",
|
|
10308
10450
|
style: {
|
|
10309
10451
|
display: "grid",
|
|
10310
10452
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
@@ -10966,9 +11108,10 @@ function applyAiSectionsToDom(state, options) {
|
|
|
10966
11108
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
10967
11109
|
continue;
|
|
10968
11110
|
}
|
|
10969
|
-
const isNewMount = !existing || !existing.container.isConnected;
|
|
10970
11111
|
let container = existing?.container;
|
|
11112
|
+
let isNewMount = false;
|
|
10971
11113
|
if (!container || !container.isConnected) {
|
|
11114
|
+
isNewMount = true;
|
|
10972
11115
|
existing?.root.unmount();
|
|
10973
11116
|
container?.remove();
|
|
10974
11117
|
container = document.createElement("div");
|
|
@@ -17127,7 +17270,7 @@ function apiBase() {
|
|
|
17127
17270
|
function bridgeVersion() {
|
|
17128
17271
|
try {
|
|
17129
17272
|
if (true) {
|
|
17130
|
-
return "0.1.
|
|
17273
|
+
return "0.1.160-next.427";
|
|
17131
17274
|
}
|
|
17132
17275
|
} catch {
|
|
17133
17276
|
}
|
|
@@ -17141,7 +17284,7 @@ function stampBridgeVersionOnDocument() {
|
|
|
17141
17284
|
return;
|
|
17142
17285
|
}
|
|
17143
17286
|
try {
|
|
17144
|
-
const v = true ? "0.1.
|
|
17287
|
+
const v = true ? "0.1.160-next.427" : "";
|
|
17145
17288
|
if (v) {
|
|
17146
17289
|
document.documentElement.setAttribute("data-ohw-bridge-version", v);
|
|
17147
17290
|
window.__OHW_BRIDGE_VERSION__ = v;
|
|
@@ -17819,6 +17962,7 @@ function MediaOverlay({
|
|
|
17819
17962
|
(prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
|
|
17820
17963
|
);
|
|
17821
17964
|
}, [isVideo]);
|
|
17965
|
+
const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
|
|
17822
17966
|
const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
|
|
17823
17967
|
const box = {
|
|
17824
17968
|
position: "fixed",
|
|
@@ -17917,11 +18061,10 @@ function MediaOverlay({
|
|
|
17917
18061
|
className: "flex items-center justify-center cursor-pointer",
|
|
17918
18062
|
style: {
|
|
17919
18063
|
...box,
|
|
17920
|
-
//
|
|
17921
|
-
//
|
|
17922
|
-
//
|
|
17923
|
-
|
|
17924
|
-
pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto",
|
|
18064
|
+
// Visual only. `pointer-events: auto` on this full-bleed rect covered the navbar
|
|
18065
|
+
// (hero bg includes the absolute TopNav) and swallowed CTA press-drag. Text overlay
|
|
18066
|
+
// and cueOnly also need clicks to fall through — Replace / video controls opt back in.
|
|
18067
|
+
pointerEvents: "none",
|
|
17925
18068
|
// Selected: a firm component ring with no wash, so the image reads as chosen rather
|
|
17926
18069
|
// than hovered. Hover keeps the existing tinted preview.
|
|
17927
18070
|
boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
|
|
@@ -17948,17 +18091,17 @@ function MediaOverlay({
|
|
|
17948
18091
|
},
|
|
17949
18092
|
children: [
|
|
17950
18093
|
isVideo ? /* @__PURE__ */ jsx17(Film, { size: 14 }) : /* @__PURE__ */ jsx17(ImageIcon, { size: 14 }),
|
|
17951
|
-
|
|
18094
|
+
replaceLabel
|
|
17952
18095
|
]
|
|
17953
18096
|
}
|
|
17954
18097
|
),
|
|
17955
|
-
replaceMode
|
|
18098
|
+
showChrome && replaceMode !== "none" && /* @__PURE__ */ jsxs8(
|
|
17956
18099
|
Button,
|
|
17957
18100
|
{
|
|
17958
18101
|
"data-ohw-media-overlay": "",
|
|
17959
18102
|
variant: "outline",
|
|
17960
18103
|
size: "sm",
|
|
17961
|
-
"aria-label":
|
|
18104
|
+
"aria-label": replaceLabel,
|
|
17962
18105
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
17963
18106
|
style: {
|
|
17964
18107
|
...OVERLAY_BUTTON_STYLE,
|
|
@@ -17981,7 +18124,7 @@ function MediaOverlay({
|
|
|
17981
18124
|
},
|
|
17982
18125
|
children: [
|
|
17983
18126
|
isVideo ? /* @__PURE__ */ jsx17(Film, { size: 14 }) : /* @__PURE__ */ jsx17(ImageIcon, { size: 14 }),
|
|
17984
|
-
replaceMode === "full" ?
|
|
18127
|
+
replaceMode === "full" ? replaceLabel : null
|
|
17985
18128
|
]
|
|
17986
18129
|
}
|
|
17987
18130
|
)
|
|
@@ -18050,6 +18193,89 @@ function CarouselOverlay({
|
|
|
18050
18193
|
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
18051
18194
|
import { useCallback as useCallback2, useEffect as useEffect5, useRef as useRef4, useState as useState7 } from "react";
|
|
18052
18195
|
import { Check, X } from "lucide-react";
|
|
18196
|
+
|
|
18197
|
+
// src/lib/ai-change-highlight.ts
|
|
18198
|
+
var STYLE_ID = "ohw-ai-changed-style";
|
|
18199
|
+
var MARK_ATTR = "data-ohw-ai-changed";
|
|
18200
|
+
var HIGHLIGHT_MS = 2200;
|
|
18201
|
+
var HIGHLIGHT_CSS = `
|
|
18202
|
+
@keyframes ohw-ai-changed-pulse {
|
|
18203
|
+
0% { outline-color: rgba(0, 120, 229, 0.95); box-shadow: 0 0 0 5px rgba(0, 120, 229, 0.20); }
|
|
18204
|
+
72% { outline-color: rgba(0, 120, 229, 0.95); box-shadow: 0 0 0 5px rgba(0, 120, 229, 0.12); }
|
|
18205
|
+
100% { outline-color: rgba(0, 120, 229, 0); box-shadow: 0 0 0 5px rgba(0, 120, 229, 0); }
|
|
18206
|
+
}
|
|
18207
|
+
[${MARK_ATTR}] {
|
|
18208
|
+
outline: 2px solid rgba(0, 120, 229, 0.95) !important;
|
|
18209
|
+
outline-offset: 3px !important;
|
|
18210
|
+
animation: ohw-ai-changed-pulse ${HIGHLIGHT_MS}ms ease-out forwards !important;
|
|
18211
|
+
}
|
|
18212
|
+
@media (prefers-reduced-motion: reduce) {
|
|
18213
|
+
[${MARK_ATTR}] { animation: none !important; }
|
|
18214
|
+
}
|
|
18215
|
+
`;
|
|
18216
|
+
function ensureStyleSheet2() {
|
|
18217
|
+
if (document.getElementById(STYLE_ID)) return;
|
|
18218
|
+
const el = document.createElement("style");
|
|
18219
|
+
el.id = STYLE_ID;
|
|
18220
|
+
el.textContent = HIGHLIGHT_CSS;
|
|
18221
|
+
document.head.appendChild(el);
|
|
18222
|
+
}
|
|
18223
|
+
function targetsFor(keys, item) {
|
|
18224
|
+
const out = /* @__PURE__ */ new Set();
|
|
18225
|
+
for (const key of keys) {
|
|
18226
|
+
if (!key) continue;
|
|
18227
|
+
for (const el of Array.from(
|
|
18228
|
+
document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`)
|
|
18229
|
+
)) {
|
|
18230
|
+
out.add(el);
|
|
18231
|
+
}
|
|
18232
|
+
}
|
|
18233
|
+
if (item) {
|
|
18234
|
+
const section = document.querySelector(`[data-ohw-instance="${CSS.escape(item.sectionId)}"]`) ?? document.querySelector(`[data-ohw-section="${CSS.escape(item.sectionId)}"]`);
|
|
18235
|
+
const stamp = `${item.group}:${item.index}`;
|
|
18236
|
+
const el = section?.querySelector(`[data-ohw-item="${CSS.escape(stamp)}"]`);
|
|
18237
|
+
if (el) out.add(el);
|
|
18238
|
+
}
|
|
18239
|
+
return [...out];
|
|
18240
|
+
}
|
|
18241
|
+
var clearTimer = null;
|
|
18242
|
+
function clearChangeHighlight() {
|
|
18243
|
+
if (clearTimer !== null) {
|
|
18244
|
+
clearTimeout(clearTimer);
|
|
18245
|
+
clearTimer = null;
|
|
18246
|
+
}
|
|
18247
|
+
for (const el of Array.from(document.querySelectorAll(`[${MARK_ATTR}]`))) {
|
|
18248
|
+
el.removeAttribute(MARK_ATTR);
|
|
18249
|
+
}
|
|
18250
|
+
}
|
|
18251
|
+
function highlightChangedElements(keys, item) {
|
|
18252
|
+
clearChangeHighlight();
|
|
18253
|
+
const targets = targetsFor(keys, item);
|
|
18254
|
+
if (targets.length === 0) return 0;
|
|
18255
|
+
ensureStyleSheet2();
|
|
18256
|
+
for (const el of targets) el.setAttribute(MARK_ATTR, "");
|
|
18257
|
+
const rect = targets[0].getBoundingClientRect();
|
|
18258
|
+
if (rect.bottom < 0 || rect.top > window.innerHeight) {
|
|
18259
|
+
targets[0].scrollIntoView({ behavior: "smooth", block: "center" });
|
|
18260
|
+
}
|
|
18261
|
+
clearTimer = setTimeout(clearChangeHighlight, HIGHLIGHT_MS);
|
|
18262
|
+
return targets.length;
|
|
18263
|
+
}
|
|
18264
|
+
function installAiChangeHighlight() {
|
|
18265
|
+
const onMessage = (e) => {
|
|
18266
|
+
const data = e.data;
|
|
18267
|
+
if (data?.type !== "ow:ai-highlight") return;
|
|
18268
|
+
const keys = Array.isArray(data.keys) ? data.keys.filter((k) => typeof k === "string") : [];
|
|
18269
|
+
const raw = data.item;
|
|
18270
|
+
const item = raw && typeof raw.sectionId === "string" && typeof raw.group === "string" && typeof raw.index === "number" ? { sectionId: raw.sectionId, group: raw.group, index: raw.index } : void 0;
|
|
18271
|
+
const found = highlightChangedElements(keys, item);
|
|
18272
|
+
window.parent?.postMessage({ type: "ow:ai-highlight-done", found }, "*");
|
|
18273
|
+
};
|
|
18274
|
+
window.addEventListener("message", onMessage);
|
|
18275
|
+
return () => window.removeEventListener("message", onMessage);
|
|
18276
|
+
}
|
|
18277
|
+
|
|
18278
|
+
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
18053
18279
|
import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
18054
18280
|
var findSectionElement = findByInstanceId;
|
|
18055
18281
|
function readRect(instanceId) {
|
|
@@ -18301,6 +18527,7 @@ function AiSectionOverlay({
|
|
|
18301
18527
|
window.addEventListener("message", onMessage);
|
|
18302
18528
|
return () => window.removeEventListener("message", onMessage);
|
|
18303
18529
|
}, [postToParent2]);
|
|
18530
|
+
useEffect5(() => installAiChangeHighlight(), []);
|
|
18304
18531
|
const [hoveredId, setHoveredId] = useState7(null);
|
|
18305
18532
|
useEffect5(() => {
|
|
18306
18533
|
const onMove = (e) => {
|
|
@@ -18490,8 +18717,24 @@ function AiSectionOverlay({
|
|
|
18490
18717
|
}
|
|
18491
18718
|
|
|
18492
18719
|
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
18493
|
-
import { useCallback as useCallback3, useEffect as useEffect6, useRef as useRef5, useState as useState8 } from "react";
|
|
18494
|
-
import {
|
|
18720
|
+
import { useCallback as useCallback3, useEffect as useEffect6, useLayoutEffect as useLayoutEffect4, useRef as useRef5, useState as useState8 } from "react";
|
|
18721
|
+
import {
|
|
18722
|
+
AlignCenter,
|
|
18723
|
+
AlignLeft,
|
|
18724
|
+
AlignRight,
|
|
18725
|
+
ArrowLeft as ArrowLeft2,
|
|
18726
|
+
ArrowRight as ArrowRight2,
|
|
18727
|
+
Check as Check2,
|
|
18728
|
+
ChevronDown as ChevronDown3,
|
|
18729
|
+
Image as ImageIcon2,
|
|
18730
|
+
ImageMinus,
|
|
18731
|
+
ImagePlus,
|
|
18732
|
+
Link as LinkIcon,
|
|
18733
|
+
Minus,
|
|
18734
|
+
Palette,
|
|
18735
|
+
Plus as Plus2,
|
|
18736
|
+
Star
|
|
18737
|
+
} from "lucide-react";
|
|
18495
18738
|
|
|
18496
18739
|
// src/lib/ai-media-strip-tree.ts
|
|
18497
18740
|
var MEDIA_STRIP_ITEM_MIN = 1;
|
|
@@ -18605,14 +18848,6 @@ function setMediaStripItemAsset(tree, index, assetId) {
|
|
|
18605
18848
|
return true;
|
|
18606
18849
|
});
|
|
18607
18850
|
}
|
|
18608
|
-
function setMediaStripItemAlt(tree, index, alt) {
|
|
18609
|
-
return withMediaStrip(tree, (block) => {
|
|
18610
|
-
const items = block.items;
|
|
18611
|
-
if (index < 0 || index >= items.length) return false;
|
|
18612
|
-
items[index] = { ...items[index], alt };
|
|
18613
|
-
return true;
|
|
18614
|
-
});
|
|
18615
|
-
}
|
|
18616
18851
|
function setMediaStripItemLink(tree, index, link) {
|
|
18617
18852
|
return withMediaStrip(tree, (block) => {
|
|
18618
18853
|
const items = block.items;
|
|
@@ -18630,11 +18865,117 @@ function setMediaStripItemLink(tree, index, link) {
|
|
|
18630
18865
|
});
|
|
18631
18866
|
}
|
|
18632
18867
|
|
|
18868
|
+
// src/ui/dialog.tsx
|
|
18869
|
+
import * as React9 from "react";
|
|
18870
|
+
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
18871
|
+
import { X as X2 } from "lucide-react";
|
|
18872
|
+
import { jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
18873
|
+
function Dialog2({
|
|
18874
|
+
...props
|
|
18875
|
+
}) {
|
|
18876
|
+
return /* @__PURE__ */ jsx20(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
|
|
18877
|
+
}
|
|
18878
|
+
function DialogPortal({
|
|
18879
|
+
...props
|
|
18880
|
+
}) {
|
|
18881
|
+
return /* @__PURE__ */ jsx20(DialogPrimitive.Portal, { ...props });
|
|
18882
|
+
}
|
|
18883
|
+
function DialogOverlay({
|
|
18884
|
+
className,
|
|
18885
|
+
...props
|
|
18886
|
+
}) {
|
|
18887
|
+
return /* @__PURE__ */ jsx20(
|
|
18888
|
+
DialogPrimitive.Overlay,
|
|
18889
|
+
{
|
|
18890
|
+
"data-slot": "dialog-overlay",
|
|
18891
|
+
"data-ohw-link-modal-root": "",
|
|
18892
|
+
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
18893
|
+
...props
|
|
18894
|
+
}
|
|
18895
|
+
);
|
|
18896
|
+
}
|
|
18897
|
+
var DialogContent = React9.forwardRef(
|
|
18898
|
+
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
18899
|
+
const positionMode = container ? "absolute" : "fixed";
|
|
18900
|
+
return /* @__PURE__ */ jsxs11(DialogPortal, { container: container ?? void 0, children: [
|
|
18901
|
+
/* @__PURE__ */ jsx20(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
18902
|
+
/* @__PURE__ */ jsxs11(
|
|
18903
|
+
DialogPrimitive.Content,
|
|
18904
|
+
{
|
|
18905
|
+
ref,
|
|
18906
|
+
"data-slot": "dialog-content",
|
|
18907
|
+
className: cn(
|
|
18908
|
+
positionMode,
|
|
18909
|
+
"left-1/2 top-1/2 z-[2147483647] flex w-full max-w-[448px] -translate-x-1/2 -translate-y-1/2 flex-col overflow-visible",
|
|
18910
|
+
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
18911
|
+
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
18912
|
+
className
|
|
18913
|
+
),
|
|
18914
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
18915
|
+
...props,
|
|
18916
|
+
children: [
|
|
18917
|
+
children,
|
|
18918
|
+
showCloseButton ? /* @__PURE__ */ jsx20(
|
|
18919
|
+
DialogPrimitive.Close,
|
|
18920
|
+
{
|
|
18921
|
+
type: "button",
|
|
18922
|
+
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
18923
|
+
"aria-label": "Close",
|
|
18924
|
+
children: /* @__PURE__ */ jsx20(X2, { size: 16, "aria-hidden": true })
|
|
18925
|
+
}
|
|
18926
|
+
) : null
|
|
18927
|
+
]
|
|
18928
|
+
}
|
|
18929
|
+
)
|
|
18930
|
+
] });
|
|
18931
|
+
}
|
|
18932
|
+
);
|
|
18933
|
+
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
18934
|
+
function DialogHeader({
|
|
18935
|
+
className,
|
|
18936
|
+
...props
|
|
18937
|
+
}) {
|
|
18938
|
+
return /* @__PURE__ */ jsx20("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
18939
|
+
}
|
|
18940
|
+
function DialogFooter({
|
|
18941
|
+
className,
|
|
18942
|
+
...props
|
|
18943
|
+
}) {
|
|
18944
|
+
return /* @__PURE__ */ jsx20(
|
|
18945
|
+
"div",
|
|
18946
|
+
{
|
|
18947
|
+
className: cn("flex items-center justify-end gap-2", className),
|
|
18948
|
+
...props
|
|
18949
|
+
}
|
|
18950
|
+
);
|
|
18951
|
+
}
|
|
18952
|
+
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx20(
|
|
18953
|
+
DialogPrimitive.Title,
|
|
18954
|
+
{
|
|
18955
|
+
ref,
|
|
18956
|
+
className: cn(
|
|
18957
|
+
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
18958
|
+
className
|
|
18959
|
+
),
|
|
18960
|
+
...props
|
|
18961
|
+
}
|
|
18962
|
+
));
|
|
18963
|
+
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
18964
|
+
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx20(
|
|
18965
|
+
DialogPrimitive.Description,
|
|
18966
|
+
{
|
|
18967
|
+
ref,
|
|
18968
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
18969
|
+
...props
|
|
18970
|
+
}
|
|
18971
|
+
));
|
|
18972
|
+
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
18973
|
+
var DialogClose = DialogPrimitive.Close;
|
|
18974
|
+
|
|
18633
18975
|
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
18634
|
-
import { Fragment as Fragment7, jsx as
|
|
18635
|
-
var PRIMARY3 = "#0885FE";
|
|
18636
|
-
var
|
|
18637
|
-
var OHW_BLUE_DARK = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY3}) 60%, #000000)`;
|
|
18976
|
+
import { Fragment as Fragment7, jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
18977
|
+
var PRIMARY3 = "var(--ohw-primary, #0885FE)";
|
|
18978
|
+
var CHROME_SELECTOR = "[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-link-modal-root], [data-ohw-section-picker], [data-ohw-ai-review], [data-ohw-more-menu]";
|
|
18638
18979
|
function findMediaStripItemElement(sectionId, index) {
|
|
18639
18980
|
const sectionEl = findByInstanceId(sectionId);
|
|
18640
18981
|
if (!sectionEl) return null;
|
|
@@ -18644,14 +18985,35 @@ function findMediaStripItemElement(sectionId, index) {
|
|
|
18644
18985
|
}
|
|
18645
18986
|
return null;
|
|
18646
18987
|
}
|
|
18647
|
-
function
|
|
18648
|
-
|
|
18988
|
+
function itemRefFromTarget(target) {
|
|
18989
|
+
if (!(target instanceof Element)) return null;
|
|
18990
|
+
if (target.closest(CHROME_SELECTOR)) return null;
|
|
18991
|
+
const itemEl = target.closest("[data-ohw-media-strip-item]");
|
|
18992
|
+
if (!itemEl) return null;
|
|
18993
|
+
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
18994
|
+
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
18995
|
+
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
18996
|
+
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
18997
|
+
if (!sectionId || Number.isNaN(index)) return null;
|
|
18998
|
+
return { sectionId, index };
|
|
18999
|
+
}
|
|
19000
|
+
function sameRef(a, b) {
|
|
19001
|
+
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
19002
|
+
}
|
|
19003
|
+
function rectOf(el) {
|
|
18649
19004
|
if (!el) return null;
|
|
18650
19005
|
const r2 = el.getBoundingClientRect();
|
|
18651
19006
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
18652
19007
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
18653
19008
|
}
|
|
18654
|
-
function
|
|
19009
|
+
function readRect2(ref) {
|
|
19010
|
+
return rectOf(ref && findMediaStripItemElement(ref.sectionId, ref.index));
|
|
19011
|
+
}
|
|
19012
|
+
function readStripRect(ref) {
|
|
19013
|
+
const item = ref && findMediaStripItemElement(ref.sectionId, ref.index);
|
|
19014
|
+
return rectOf(item?.closest("[data-ohw-media-strip]") ?? item);
|
|
19015
|
+
}
|
|
19016
|
+
function useLiveItemRect(ref, strip = false) {
|
|
18655
19017
|
const [rect, setRect] = useState8(null);
|
|
18656
19018
|
useEffect6(() => {
|
|
18657
19019
|
if (!ref) {
|
|
@@ -18659,7 +19021,7 @@ function useLiveItemRect(ref) {
|
|
|
18659
19021
|
return;
|
|
18660
19022
|
}
|
|
18661
19023
|
const update = () => {
|
|
18662
|
-
const next = readRect2(ref);
|
|
19024
|
+
const next = strip ? readStripRect(ref) : readRect2(ref);
|
|
18663
19025
|
setRect(
|
|
18664
19026
|
(prev) => prev && next && prev.top === next.top && prev.left === next.left && prev.width === next.width && prev.height === next.height ? prev : next
|
|
18665
19027
|
);
|
|
@@ -18674,9 +19036,49 @@ function useLiveItemRect(ref) {
|
|
|
18674
19036
|
window.removeEventListener("resize", update);
|
|
18675
19037
|
clearInterval(interval);
|
|
18676
19038
|
};
|
|
18677
|
-
}, [ref?.sectionId, ref?.index]);
|
|
19039
|
+
}, [ref?.sectionId, ref?.index, strip]);
|
|
18678
19040
|
return rect;
|
|
18679
19041
|
}
|
|
19042
|
+
var TOOLBAR_STRIP_GAP = 52;
|
|
19043
|
+
var TOOLBAR_STRIP_GAP_MOBILE = 42;
|
|
19044
|
+
var TOOLBAR_EDGE_MARGIN2 = 4;
|
|
19045
|
+
function StripToolbarSlot({ stripRect, children }) {
|
|
19046
|
+
const slotRef = useRef5(null);
|
|
19047
|
+
const [shift, setShift] = useState8(0);
|
|
19048
|
+
const centerX = stripRect.left + stripRect.width / 2;
|
|
19049
|
+
useLayoutEffect4(() => {
|
|
19050
|
+
const slot = slotRef.current;
|
|
19051
|
+
if (!slot) return;
|
|
19052
|
+
const clamp = () => {
|
|
19053
|
+
const w = slot.offsetWidth;
|
|
19054
|
+
if (w <= 0) return;
|
|
19055
|
+
const half = w / 2;
|
|
19056
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN2 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN2 - half));
|
|
19057
|
+
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
19058
|
+
};
|
|
19059
|
+
clamp();
|
|
19060
|
+
const ro = new ResizeObserver(clamp);
|
|
19061
|
+
ro.observe(slot);
|
|
19062
|
+
return () => ro.disconnect();
|
|
19063
|
+
}, [centerX, children]);
|
|
19064
|
+
const mobile = window.innerWidth <= 480;
|
|
19065
|
+
return /* @__PURE__ */ jsx21(
|
|
19066
|
+
"div",
|
|
19067
|
+
{
|
|
19068
|
+
ref: slotRef,
|
|
19069
|
+
"data-ohw-bridge": "",
|
|
19070
|
+
"data-ohw-item-interaction": "",
|
|
19071
|
+
className: "pointer-events-auto fixed",
|
|
19072
|
+
style: {
|
|
19073
|
+
top: stripRect.top - (mobile ? TOOLBAR_STRIP_GAP_MOBILE : TOOLBAR_STRIP_GAP),
|
|
19074
|
+
left: centerX + shift,
|
|
19075
|
+
transform: "translate(-50%, -100%)",
|
|
19076
|
+
zIndex: 2147483645
|
|
19077
|
+
},
|
|
19078
|
+
children
|
|
19079
|
+
}
|
|
19080
|
+
);
|
|
19081
|
+
}
|
|
18680
19082
|
function requestValidateTree(postToParent2, tree) {
|
|
18681
19083
|
return new Promise((resolve) => {
|
|
18682
19084
|
const id = `ai-validate-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
@@ -18713,116 +19115,72 @@ function requestAssetPick(postToParent2) {
|
|
|
18713
19115
|
postToParent2({ type: "ow:asset-pick", id });
|
|
18714
19116
|
});
|
|
18715
19117
|
}
|
|
18716
|
-
function
|
|
19118
|
+
function ToolbarAction({
|
|
18717
19119
|
label,
|
|
18718
19120
|
onClick,
|
|
18719
|
-
disabled,
|
|
18720
|
-
active
|
|
19121
|
+
disabled = false,
|
|
19122
|
+
active = false,
|
|
19123
|
+
children
|
|
18721
19124
|
}) {
|
|
18722
|
-
|
|
18723
|
-
|
|
18724
|
-
{
|
|
18725
|
-
|
|
18726
|
-
|
|
18727
|
-
disabled,
|
|
18728
|
-
style: {
|
|
18729
|
-
height: 28,
|
|
18730
|
-
padding: "0 10px",
|
|
18731
|
-
display: "inline-flex",
|
|
18732
|
-
alignItems: "center",
|
|
18733
|
-
gap: 4,
|
|
18734
|
-
borderRadius: 999,
|
|
18735
|
-
border: "none",
|
|
18736
|
-
cursor: disabled ? "default" : "pointer",
|
|
18737
|
-
background: active ? OHW_BLUE_DARK : "#ffffff",
|
|
18738
|
-
color: active ? "#ffffff" : OHW_BLUE_DARK,
|
|
18739
|
-
opacity: disabled ? 0.4 : 1,
|
|
18740
|
-
fontSize: 12,
|
|
18741
|
-
lineHeight: "16px",
|
|
18742
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18743
|
-
whiteSpace: "nowrap",
|
|
18744
|
-
flex: "0 0 auto"
|
|
18745
|
-
},
|
|
18746
|
-
children: label
|
|
18747
|
-
}
|
|
18748
|
-
);
|
|
19125
|
+
const button = /* @__PURE__ */ jsx21(CustomToolbarButton, { type: "button", "aria-label": label, disabled, active, onClick, className: "size-8", children });
|
|
19126
|
+
return /* @__PURE__ */ jsxs12(Tooltip, { children: [
|
|
19127
|
+
/* @__PURE__ */ jsx21(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ jsx21("span", { className: "inline-flex", children: button }) : button }),
|
|
19128
|
+
/* @__PURE__ */ jsx21(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
19129
|
+
] });
|
|
18749
19130
|
}
|
|
18750
|
-
function
|
|
18751
|
-
|
|
18752
|
-
|
|
18753
|
-
|
|
18754
|
-
|
|
18755
|
-
|
|
18756
|
-
|
|
18757
|
-
|
|
18758
|
-
|
|
18759
|
-
|
|
18760
|
-
|
|
18761
|
-
|
|
18762
|
-
|
|
18763
|
-
|
|
18764
|
-
|
|
18765
|
-
|
|
18766
|
-
|
|
18767
|
-
|
|
18768
|
-
|
|
18769
|
-
|
|
18770
|
-
|
|
18771
|
-
|
|
18772
|
-
|
|
18773
|
-
|
|
18774
|
-
|
|
18775
|
-
|
|
18776
|
-
|
|
18777
|
-
|
|
18778
|
-
|
|
18779
|
-
|
|
18780
|
-
|
|
18781
|
-
|
|
18782
|
-
|
|
18783
|
-
|
|
18784
|
-
|
|
18785
|
-
|
|
18786
|
-
|
|
18787
|
-
|
|
18788
|
-
|
|
18789
|
-
|
|
18790
|
-
|
|
18791
|
-
|
|
18792
|
-
|
|
18793
|
-
|
|
18794
|
-
if (e.key === "Escape") {
|
|
18795
|
-
setDraft(value);
|
|
18796
|
-
e.currentTarget.blur();
|
|
18797
|
-
}
|
|
18798
|
-
},
|
|
18799
|
-
placeholder: "Describe this image",
|
|
18800
|
-
"aria-label": "Image alt text",
|
|
18801
|
-
style: {
|
|
18802
|
-
flex: 1,
|
|
18803
|
-
minWidth: 0,
|
|
18804
|
-
border: "none",
|
|
18805
|
-
outline: "none",
|
|
18806
|
-
background: "transparent",
|
|
18807
|
-
fontSize: 12,
|
|
18808
|
-
lineHeight: "16px",
|
|
18809
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18810
|
-
color: "#1f2937"
|
|
18811
|
-
}
|
|
18812
|
-
}
|
|
18813
|
-
)
|
|
18814
|
-
]
|
|
18815
|
-
}
|
|
18816
|
-
);
|
|
19131
|
+
function ToolbarSeparator() {
|
|
19132
|
+
return /* @__PURE__ */ jsx21("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
19133
|
+
}
|
|
19134
|
+
function OptionMenu({
|
|
19135
|
+
label,
|
|
19136
|
+
value,
|
|
19137
|
+
options,
|
|
19138
|
+
onChange
|
|
19139
|
+
}) {
|
|
19140
|
+
const current = options.find((o) => o.value === value) ?? options[0];
|
|
19141
|
+
return /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19142
|
+
/* @__PURE__ */ jsx21("span", { className: "text-xs text-muted-foreground", children: label }),
|
|
19143
|
+
/* @__PURE__ */ jsxs12(DropdownMenu, { modal: false, children: [
|
|
19144
|
+
/* @__PURE__ */ jsx21(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs12(
|
|
19145
|
+
"button",
|
|
19146
|
+
{
|
|
19147
|
+
type: "button",
|
|
19148
|
+
"aria-label": label,
|
|
19149
|
+
className: "inline-flex h-8 min-w-[76px] items-center gap-[7px] rounded-[6px] bg-transparent px-2 text-[13px] font-medium text-foreground transition-colors hover:bg-muted data-[state=open]:bg-muted",
|
|
19150
|
+
children: [
|
|
19151
|
+
/* @__PURE__ */ jsx21("span", { className: "flex-1 text-left", children: current.label }),
|
|
19152
|
+
/* @__PURE__ */ jsx21(ChevronDown3, { size: 16, style: { pointerEvents: "none" } })
|
|
19153
|
+
]
|
|
19154
|
+
}
|
|
19155
|
+
) }),
|
|
19156
|
+
/* @__PURE__ */ jsx21(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[132px] min-w-[132px] p-1", children: options.map((option) => {
|
|
19157
|
+
const selected = option.value === value;
|
|
19158
|
+
return /* @__PURE__ */ jsxs12(
|
|
19159
|
+
DropdownMenuItem,
|
|
19160
|
+
{
|
|
19161
|
+
role: "menuitemradio",
|
|
19162
|
+
"aria-checked": selected,
|
|
19163
|
+
onSelect: () => onChange(option.value),
|
|
19164
|
+
className: cn("grid grid-cols-[1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
19165
|
+
children: [
|
|
19166
|
+
/* @__PURE__ */ jsx21("span", { children: option.label }),
|
|
19167
|
+
selected && /* @__PURE__ */ jsx21(Check2, { size: 16, className: "text-bridge-primary" })
|
|
19168
|
+
]
|
|
19169
|
+
},
|
|
19170
|
+
option.value
|
|
19171
|
+
);
|
|
19172
|
+
}) })
|
|
19173
|
+
] })
|
|
19174
|
+
] });
|
|
18817
19175
|
}
|
|
18818
19176
|
var VARIANTS = [
|
|
18819
19177
|
{ value: "logos", label: "Logos" },
|
|
18820
19178
|
{ value: "reel", label: "Reel" }
|
|
18821
19179
|
];
|
|
18822
19180
|
var ALIGNS = [
|
|
18823
|
-
{ value: "left", label: "
|
|
18824
|
-
{ value: "center", label: "
|
|
18825
|
-
{ value: "right", label: "
|
|
19181
|
+
{ value: "left", label: "Align left", Icon: AlignLeft },
|
|
19182
|
+
{ value: "center", label: "Align center", Icon: AlignCenter },
|
|
19183
|
+
{ value: "right", label: "Align right", Icon: AlignRight }
|
|
18826
19184
|
];
|
|
18827
19185
|
var HOVERS = [
|
|
18828
19186
|
{ value: "none", label: "None" },
|
|
@@ -18830,104 +19188,104 @@ var HOVERS = [
|
|
|
18830
19188
|
{ value: "zoom", label: "Zoom" },
|
|
18831
19189
|
{ value: "fade", label: "Fade" }
|
|
18832
19190
|
];
|
|
18833
|
-
var TREATMENTS = [
|
|
18834
|
-
{ value: "color", label: "Color" },
|
|
18835
|
-
{ value: "grayscale", label: "Grayscale" }
|
|
18836
|
-
];
|
|
18837
19191
|
var HTTP_URL_RE = /^https?:\/\/\S+$/i;
|
|
18838
|
-
function
|
|
18839
|
-
|
|
19192
|
+
function LinkModal({
|
|
19193
|
+
href,
|
|
19194
|
+
linkTarget,
|
|
19195
|
+
onClose,
|
|
19196
|
+
onSave
|
|
19197
|
+
}) {
|
|
19198
|
+
const [draft, setDraft] = useState8(href);
|
|
19199
|
+
const [newTab, setNewTab] = useState8(linkTarget !== "same-tab");
|
|
18840
19200
|
const [invalid, setInvalid] = useState8(false);
|
|
18841
|
-
|
|
18842
|
-
setDraft(value);
|
|
18843
|
-
setInvalid(false);
|
|
18844
|
-
}, [value]);
|
|
18845
|
-
const commit = () => {
|
|
19201
|
+
const save = () => {
|
|
18846
19202
|
const next = draft.trim();
|
|
18847
|
-
if (next
|
|
18848
|
-
|
|
18849
|
-
|
|
18850
|
-
onCommit(next);
|
|
18851
|
-
};
|
|
18852
|
-
return /* @__PURE__ */ jsxs11(
|
|
18853
|
-
"div",
|
|
18854
|
-
{
|
|
18855
|
-
style: {
|
|
18856
|
-
display: "flex",
|
|
18857
|
-
alignItems: "center",
|
|
18858
|
-
gap: 6,
|
|
18859
|
-
height: 28,
|
|
18860
|
-
padding: "0 12px",
|
|
18861
|
-
borderRadius: 999,
|
|
18862
|
-
background: "#ffffff",
|
|
18863
|
-
width: "100%",
|
|
18864
|
-
maxWidth: 260,
|
|
18865
|
-
boxSizing: "border-box",
|
|
18866
|
-
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
18867
|
-
},
|
|
18868
|
-
children: [
|
|
18869
|
-
/* @__PURE__ */ jsx20(
|
|
18870
|
-
"span",
|
|
18871
|
-
{
|
|
18872
|
-
style: {
|
|
18873
|
-
flex: "0 0 auto",
|
|
18874
|
-
color: OHW_BLUE_DARK,
|
|
18875
|
-
fontSize: 10,
|
|
18876
|
-
fontWeight: 700,
|
|
18877
|
-
textTransform: "uppercase",
|
|
18878
|
-
letterSpacing: 0.4
|
|
18879
|
-
},
|
|
18880
|
-
children: "Link"
|
|
18881
|
-
}
|
|
18882
|
-
),
|
|
18883
|
-
/* @__PURE__ */ jsx20(
|
|
18884
|
-
"input",
|
|
18885
|
-
{
|
|
18886
|
-
type: "text",
|
|
18887
|
-
inputMode: "url",
|
|
18888
|
-
value: draft,
|
|
18889
|
-
onChange: (e) => setDraft(e.target.value),
|
|
18890
|
-
onBlur: commit,
|
|
18891
|
-
onKeyDown: (e) => {
|
|
18892
|
-
if (e.key === "Enter") e.currentTarget.blur();
|
|
18893
|
-
if (e.key === "Escape") {
|
|
18894
|
-
setDraft(value);
|
|
18895
|
-
setInvalid(false);
|
|
18896
|
-
e.currentTarget.blur();
|
|
18897
|
-
}
|
|
18898
|
-
},
|
|
18899
|
-
placeholder: "https://example.com",
|
|
18900
|
-
"aria-label": "Image link URL",
|
|
18901
|
-
"aria-invalid": invalid,
|
|
18902
|
-
style: {
|
|
18903
|
-
flex: 1,
|
|
18904
|
-
minWidth: 0,
|
|
18905
|
-
border: "none",
|
|
18906
|
-
outline: "none",
|
|
18907
|
-
background: "transparent",
|
|
18908
|
-
fontSize: 12,
|
|
18909
|
-
lineHeight: "16px",
|
|
18910
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18911
|
-
color: "#1f2937"
|
|
18912
|
-
}
|
|
18913
|
-
}
|
|
18914
|
-
)
|
|
18915
|
-
]
|
|
19203
|
+
if (next && !HTTP_URL_RE.test(next)) {
|
|
19204
|
+
setInvalid(true);
|
|
19205
|
+
return;
|
|
18916
19206
|
}
|
|
18917
|
-
|
|
19207
|
+
onSave(next, newTab ? "new-tab" : "same-tab");
|
|
19208
|
+
onClose();
|
|
19209
|
+
};
|
|
19210
|
+
return /* @__PURE__ */ jsx21(Dialog2, { open: true, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxs12(DialogContent, { "data-ohw-link-modal-root": "", className: "max-w-[400px] gap-4 p-5", children: [
|
|
19211
|
+
/* @__PURE__ */ jsx21(DialogHeader, { children: /* @__PURE__ */ jsx21(DialogTitle, { className: "text-base", children: "Image link" }) }),
|
|
19212
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex flex-col gap-3", children: [
|
|
19213
|
+
/* @__PURE__ */ jsx21(
|
|
19214
|
+
"input",
|
|
19215
|
+
{
|
|
19216
|
+
autoFocus: true,
|
|
19217
|
+
type: "text",
|
|
19218
|
+
inputMode: "url",
|
|
19219
|
+
value: draft,
|
|
19220
|
+
onChange: (e) => {
|
|
19221
|
+
setDraft(e.target.value);
|
|
19222
|
+
setInvalid(false);
|
|
19223
|
+
},
|
|
19224
|
+
onKeyDown: (e) => {
|
|
19225
|
+
if (e.key === "Enter") save();
|
|
19226
|
+
},
|
|
19227
|
+
placeholder: "https://example.com",
|
|
19228
|
+
"aria-label": "Image link URL",
|
|
19229
|
+
"aria-invalid": invalid,
|
|
19230
|
+
className: cn(
|
|
19231
|
+
"h-9 w-full rounded-[6px] border border-border bg-background px-3 text-[13px] text-foreground outline-none placeholder:text-muted-foreground/70 focus:border-bridge-primary",
|
|
19232
|
+
invalid && "border-destructive focus:border-destructive"
|
|
19233
|
+
)
|
|
19234
|
+
}
|
|
19235
|
+
),
|
|
19236
|
+
invalid && /* @__PURE__ */ jsx21("p", { className: "text-xs text-destructive", children: "Enter a full URL starting with http:// or https://" }),
|
|
19237
|
+
/* @__PURE__ */ jsxs12("label", { className: "flex items-center gap-2 text-[13px] text-foreground", children: [
|
|
19238
|
+
/* @__PURE__ */ jsx21("input", { type: "checkbox", checked: newTab, onChange: (e) => setNewTab(e.target.checked) }),
|
|
19239
|
+
"Open in new tab"
|
|
19240
|
+
] })
|
|
19241
|
+
] }),
|
|
19242
|
+
/* @__PURE__ */ jsxs12(DialogFooter, { children: [
|
|
19243
|
+
href && /* @__PURE__ */ jsx21(
|
|
19244
|
+
"button",
|
|
19245
|
+
{
|
|
19246
|
+
type: "button",
|
|
19247
|
+
onClick: () => {
|
|
19248
|
+
onSave("", "new-tab");
|
|
19249
|
+
onClose();
|
|
19250
|
+
},
|
|
19251
|
+
className: "mr-auto rounded-[6px] px-3 py-2 text-[13px] font-medium text-destructive transition-colors hover:bg-muted",
|
|
19252
|
+
children: "Remove link"
|
|
19253
|
+
}
|
|
19254
|
+
),
|
|
19255
|
+
/* @__PURE__ */ jsx21(
|
|
19256
|
+
"button",
|
|
19257
|
+
{
|
|
19258
|
+
type: "button",
|
|
19259
|
+
onClick: onClose,
|
|
19260
|
+
className: "rounded-[6px] px-3 py-2 text-[13px] font-medium text-foreground transition-colors hover:bg-muted",
|
|
19261
|
+
children: "Cancel"
|
|
19262
|
+
}
|
|
19263
|
+
),
|
|
19264
|
+
/* @__PURE__ */ jsx21(
|
|
19265
|
+
"button",
|
|
19266
|
+
{
|
|
19267
|
+
type: "button",
|
|
19268
|
+
onClick: save,
|
|
19269
|
+
className: "rounded-[6px] bg-bridge-primary px-3 py-2 text-[13px] font-medium text-primary-foreground transition-opacity hover:opacity-90",
|
|
19270
|
+
children: "Save"
|
|
19271
|
+
}
|
|
19272
|
+
)
|
|
19273
|
+
] })
|
|
19274
|
+
] }) });
|
|
18918
19275
|
}
|
|
18919
19276
|
function MediaStripToolbar({
|
|
18920
19277
|
entry,
|
|
18921
19278
|
index,
|
|
18922
19279
|
pending,
|
|
18923
19280
|
error,
|
|
19281
|
+
itemEditOn,
|
|
19282
|
+
onToggleItemEdit,
|
|
18924
19283
|
onSetVariant,
|
|
18925
19284
|
onSetAlign,
|
|
18926
19285
|
onSetHover,
|
|
18927
19286
|
onSetTreatment,
|
|
18928
19287
|
onResize,
|
|
18929
|
-
|
|
18930
|
-
onSetLink,
|
|
19288
|
+
onOpenLink,
|
|
18931
19289
|
onAddItem,
|
|
18932
19290
|
onRemoveItem,
|
|
18933
19291
|
onChangeImage,
|
|
@@ -18936,81 +19294,102 @@ function MediaStripToolbar({
|
|
|
18936
19294
|
}) {
|
|
18937
19295
|
const items = mediaStripItems(entry.tree);
|
|
18938
19296
|
const itemCount = items.length;
|
|
18939
|
-
const currentAlt = items[index]?.alt ?? "";
|
|
18940
|
-
const currentHref = items[index]?.href ?? "";
|
|
18941
|
-
const currentTarget = items[index]?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
18942
19297
|
const slots = findMediaStripSlots(entry.tree);
|
|
18943
19298
|
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
18944
19299
|
const align = slots?.align === "left" || slots?.align === "right" ? slots.align : "center";
|
|
18945
19300
|
const hover = slots?.hover === "none" || slots?.hover === "lift" || slots?.hover === "zoom" || slots?.hover === "fade" ? slots.hover : "lift";
|
|
18946
19301
|
const treatment = slots?.treatment === "color" || slots?.treatment === "grayscale" ? slots.treatment : variant === "logos" ? "grayscale" : "color";
|
|
18947
19302
|
const sizeValue = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
18948
|
-
const
|
|
18949
|
-
const
|
|
18950
|
-
|
|
18951
|
-
gap: 6,
|
|
18952
|
-
flexWrap: "nowrap",
|
|
18953
|
-
justifyContent: "center",
|
|
18954
|
-
overflowX: "auto",
|
|
18955
|
-
WebkitOverflowScrolling: "touch",
|
|
18956
|
-
width: "100%",
|
|
18957
|
-
scrollbarWidth: "none"
|
|
18958
|
-
} : { display: "flex", gap: 6, flexWrap: "nowrap", justifyContent: "center" };
|
|
18959
|
-
return /* @__PURE__ */ jsxs11(
|
|
19303
|
+
const mobile = window.innerWidth <= 480;
|
|
19304
|
+
const gatedLabel = (label) => itemEditOn ? label : "Turn on the star to edit this image";
|
|
19305
|
+
return /* @__PURE__ */ jsx21(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs12(
|
|
18960
19306
|
"div",
|
|
18961
19307
|
{
|
|
18962
19308
|
"data-ohw-bridge": "",
|
|
18963
19309
|
"data-ohw-toolbar": "",
|
|
18964
19310
|
onMouseDown: (e) => e.stopPropagation(),
|
|
18965
|
-
|
|
18966
|
-
|
|
18967
|
-
flexDirection: "column",
|
|
18968
|
-
gap: 6,
|
|
18969
|
-
alignItems: "center",
|
|
18970
|
-
background: OHW_BLUE,
|
|
18971
|
-
padding: 8,
|
|
18972
|
-
borderRadius: 12,
|
|
18973
|
-
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
18974
|
-
pointerEvents: pending ? "none" : "auto",
|
|
18975
|
-
opacity: pending ? 0.6 : 1,
|
|
18976
|
-
maxWidth: isMobile ? "calc(100vw - 24px)" : "none"
|
|
18977
|
-
},
|
|
19311
|
+
className: cn("flex flex-col items-center gap-1.5 font-sans", pending && "pointer-events-none opacity-60"),
|
|
19312
|
+
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
18978
19313
|
children: [
|
|
18979
|
-
/* @__PURE__ */
|
|
18980
|
-
|
|
18981
|
-
|
|
18982
|
-
|
|
18983
|
-
|
|
18984
|
-
|
|
18985
|
-
|
|
18986
|
-
|
|
18987
|
-
|
|
18988
|
-
|
|
18989
|
-
|
|
18990
|
-
|
|
18991
|
-
|
|
18992
|
-
|
|
18993
|
-
|
|
18994
|
-
|
|
18995
|
-
|
|
18996
|
-
|
|
18997
|
-
|
|
18998
|
-
|
|
18999
|
-
|
|
19000
|
-
|
|
19001
|
-
|
|
19002
|
-
|
|
19003
|
-
|
|
19004
|
-
|
|
19005
|
-
|
|
19006
|
-
|
|
19007
|
-
|
|
19008
|
-
|
|
19009
|
-
|
|
19010
|
-
|
|
19314
|
+
/* @__PURE__ */ jsxs12(
|
|
19315
|
+
"div",
|
|
19316
|
+
{
|
|
19317
|
+
className: cn(
|
|
19318
|
+
"flex items-center gap-1 rounded-[10px] border border-border bg-background p-1 whitespace-nowrap",
|
|
19319
|
+
"shadow-[0px_10px_15px_-3px_rgba(0,0,0,0.1),0px_4px_6px_-4px_rgba(0,0,0,0.1)]",
|
|
19320
|
+
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
19321
|
+
),
|
|
19322
|
+
children: [
|
|
19323
|
+
/* @__PURE__ */ jsxs12(Tooltip, { children: [
|
|
19324
|
+
/* @__PURE__ */ jsx21(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx21(
|
|
19325
|
+
CustomToolbarButton,
|
|
19326
|
+
{
|
|
19327
|
+
type: "button",
|
|
19328
|
+
"aria-label": itemEditOn ? "Done editing this image" : "Edit this image",
|
|
19329
|
+
"aria-pressed": itemEditOn,
|
|
19330
|
+
onClick: onToggleItemEdit,
|
|
19331
|
+
className: "group size-8",
|
|
19332
|
+
children: /* @__PURE__ */ jsx21(
|
|
19333
|
+
Star,
|
|
19334
|
+
{
|
|
19335
|
+
size: 16,
|
|
19336
|
+
fill: "currentColor",
|
|
19337
|
+
strokeWidth: 0,
|
|
19338
|
+
className: cn(
|
|
19339
|
+
"transition-colors",
|
|
19340
|
+
itemEditOn ? "text-[#f59e0b] group-hover:text-[#d97706]" : "text-[#d6d3d1] group-hover:text-[#fbbf24]"
|
|
19341
|
+
),
|
|
19342
|
+
style: { pointerEvents: "none" }
|
|
19343
|
+
}
|
|
19344
|
+
)
|
|
19345
|
+
}
|
|
19346
|
+
) }),
|
|
19347
|
+
/* @__PURE__ */ jsx21(TooltipContent, { side: "bottom", sideOffset: 8, children: itemEditOn ? "Done editing this image" : "Edit this image" })
|
|
19348
|
+
] }),
|
|
19349
|
+
/* @__PURE__ */ jsx21(ToolbarSeparator, {}),
|
|
19350
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: gatedLabel("Change image"), onClick: onChangeImage, disabled: !itemEditOn, children: /* @__PURE__ */ jsx21(ImageIcon2, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19351
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: gatedLabel("Link"), onClick: onOpenLink, disabled: !itemEditOn, children: /* @__PURE__ */ jsx21(LinkIcon, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19352
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: gatedLabel("Move left"), onClick: onMoveLeft, disabled: !itemEditOn || index <= 0, children: /* @__PURE__ */ jsx21(ArrowLeft2, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19353
|
+
/* @__PURE__ */ jsx21(
|
|
19354
|
+
ToolbarAction,
|
|
19355
|
+
{
|
|
19356
|
+
label: gatedLabel("Move right"),
|
|
19357
|
+
onClick: onMoveRight,
|
|
19358
|
+
disabled: !itemEditOn || index >= itemCount - 1,
|
|
19359
|
+
children: /* @__PURE__ */ jsx21(ArrowRight2, { size: 16, style: { pointerEvents: "none" } })
|
|
19360
|
+
}
|
|
19361
|
+
),
|
|
19362
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: gatedLabel("Remove image"), onClick: onRemoveItem, disabled: !itemEditOn || itemCount <= 1, children: /* @__PURE__ */ jsx21(ImageMinus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19363
|
+
/* @__PURE__ */ jsx21(ToolbarSeparator, {}),
|
|
19364
|
+
/* @__PURE__ */ jsx21(OptionMenu, { label: "Layout", value: variant, options: VARIANTS, onChange: onSetVariant }),
|
|
19365
|
+
/* @__PURE__ */ jsx21(OptionMenu, { label: "Hover", value: hover, options: HOVERS, onChange: onSetHover }),
|
|
19366
|
+
/* @__PURE__ */ jsx21(
|
|
19367
|
+
ToolbarAction,
|
|
19368
|
+
{
|
|
19369
|
+
label: treatment === "grayscale" ? "Show in color" : "Show grayscale",
|
|
19370
|
+
active: treatment === "grayscale",
|
|
19371
|
+
onClick: () => onSetTreatment(treatment === "grayscale" ? "color" : "grayscale"),
|
|
19372
|
+
children: /* @__PURE__ */ jsx21(Palette, { size: 16, style: { pointerEvents: "none" } })
|
|
19373
|
+
}
|
|
19374
|
+
),
|
|
19375
|
+
/* @__PURE__ */ jsx21(ToolbarSeparator, {}),
|
|
19376
|
+
ALIGNS.map(({ value, label, Icon }) => /* @__PURE__ */ jsx21(ToolbarAction, { label, active: align === value, onClick: () => onSetAlign(value), children: /* @__PURE__ */ jsx21(Icon, { size: 16, style: { pointerEvents: "none" } }) }, value)),
|
|
19377
|
+
/* @__PURE__ */ jsx21(ToolbarSeparator, {}),
|
|
19378
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: "Smaller", onClick: () => onResize(-8), children: /* @__PURE__ */ jsx21(Minus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19379
|
+
/* @__PURE__ */ jsxs12("span", { className: "min-w-[40px] text-center text-xs tabular-nums text-muted-foreground", children: [
|
|
19380
|
+
sizeValue,
|
|
19381
|
+
"px"
|
|
19382
|
+
] }),
|
|
19383
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: "Larger", onClick: () => onResize(8), children: /* @__PURE__ */ jsx21(Plus2, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19384
|
+
/* @__PURE__ */ jsx21(ToolbarSeparator, {}),
|
|
19385
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: "Add image", onClick: onAddItem, children: /* @__PURE__ */ jsx21(ImagePlus, { size: 16, style: { pointerEvents: "none" } }) })
|
|
19386
|
+
]
|
|
19387
|
+
}
|
|
19388
|
+
),
|
|
19389
|
+
error && /* @__PURE__ */ jsx21("div", { className: "max-w-[260px] rounded-md bg-background px-2 py-1 text-center text-[11px] text-destructive shadow-sm", children: error })
|
|
19011
19390
|
]
|
|
19012
19391
|
}
|
|
19013
|
-
);
|
|
19392
|
+
) });
|
|
19014
19393
|
}
|
|
19015
19394
|
function findMediaStripSlots(tree) {
|
|
19016
19395
|
const stack = tree.rows.flatMap((row) => row.blocks);
|
|
@@ -19029,31 +19408,23 @@ function AiMediaStripOverlay({
|
|
|
19029
19408
|
}) {
|
|
19030
19409
|
const [hover, setHover] = useState8(null);
|
|
19031
19410
|
const [active, setActive] = useState8(null);
|
|
19411
|
+
const [itemEditOn, setItemEditOn] = useState8(false);
|
|
19412
|
+
const [linkOpen, setLinkOpen] = useState8(false);
|
|
19032
19413
|
const [pending, setPending] = useState8(false);
|
|
19033
19414
|
const [error, setError] = useState8(null);
|
|
19034
19415
|
const activeRef = useRef5(null);
|
|
19035
19416
|
activeRef.current = active;
|
|
19417
|
+
const linkOpenRef = useRef5(false);
|
|
19418
|
+
linkOpenRef.current = linkOpen;
|
|
19036
19419
|
useEffect6(() => {
|
|
19037
19420
|
const onMove = (e) => {
|
|
19421
|
+
const ref = itemRefFromTarget(e.target);
|
|
19038
19422
|
const t = e.target;
|
|
19039
|
-
|
|
19040
|
-
|
|
19041
|
-
|
|
19042
|
-
|
|
19043
|
-
|
|
19044
|
-
if (!itemEl) {
|
|
19045
|
-
setHover(null);
|
|
19046
|
-
return;
|
|
19047
|
-
}
|
|
19048
|
-
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
19049
|
-
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
19050
|
-
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
19051
|
-
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
19052
|
-
if (!sectionId || Number.isNaN(index)) {
|
|
19053
|
-
setHover(null);
|
|
19054
|
-
return;
|
|
19055
|
-
}
|
|
19056
|
-
setHover({ sectionId, index });
|
|
19423
|
+
const overEditable = Boolean(t?.closest?.("[data-ohw-editable]"));
|
|
19424
|
+
setHover((prev) => {
|
|
19425
|
+
const next = ref && !overEditable ? ref : null;
|
|
19426
|
+
return sameRef(prev, next) ? prev : next;
|
|
19427
|
+
});
|
|
19057
19428
|
};
|
|
19058
19429
|
const onLeave = () => setHover(null);
|
|
19059
19430
|
document.addEventListener("mousemove", onMove, { passive: true });
|
|
@@ -19065,23 +19436,25 @@ function AiMediaStripOverlay({
|
|
|
19065
19436
|
}, []);
|
|
19066
19437
|
useEffect6(() => {
|
|
19067
19438
|
const onClick = (e) => {
|
|
19068
|
-
const current = activeRef.current;
|
|
19069
|
-
if (!current) return;
|
|
19070
19439
|
const t = e.target;
|
|
19071
|
-
if (!(t instanceof
|
|
19072
|
-
if (t.closest(
|
|
19073
|
-
const
|
|
19074
|
-
if (
|
|
19075
|
-
|
|
19440
|
+
if (!(t instanceof Element)) return;
|
|
19441
|
+
if (t.closest(CHROME_SELECTOR)) return;
|
|
19442
|
+
const ref = itemRefFromTarget(t);
|
|
19443
|
+
if (sameRef(activeRef.current, ref)) return;
|
|
19444
|
+
if (ref) clearInteractionChromeRef.current();
|
|
19445
|
+
setItemEditOn(false);
|
|
19076
19446
|
setError(null);
|
|
19447
|
+
setActive(ref);
|
|
19077
19448
|
};
|
|
19078
19449
|
document.addEventListener("click", onClick, true);
|
|
19079
19450
|
return () => document.removeEventListener("click", onClick, true);
|
|
19080
|
-
}, []);
|
|
19451
|
+
}, [clearInteractionChromeRef]);
|
|
19081
19452
|
useEffect6(() => {
|
|
19082
19453
|
const onBlur = () => {
|
|
19083
19454
|
if (!activeRef.current) return;
|
|
19084
19455
|
setActive(null);
|
|
19456
|
+
setItemEditOn(false);
|
|
19457
|
+
setLinkOpen(false);
|
|
19085
19458
|
setError(null);
|
|
19086
19459
|
};
|
|
19087
19460
|
window.addEventListener("blur", onBlur);
|
|
@@ -19091,7 +19464,10 @@ function AiMediaStripOverlay({
|
|
|
19091
19464
|
const onKeyDown = (e) => {
|
|
19092
19465
|
if (e.key !== "Escape") return;
|
|
19093
19466
|
if (!activeRef.current) return;
|
|
19467
|
+
if (linkOpenRef.current) return;
|
|
19468
|
+
if (document.querySelector('[data-ohw-more-menu][data-state="open"]')) return;
|
|
19094
19469
|
setActive(null);
|
|
19470
|
+
setItemEditOn(false);
|
|
19095
19471
|
setError(null);
|
|
19096
19472
|
};
|
|
19097
19473
|
document.addEventListener("keydown", onKeyDown);
|
|
@@ -19125,137 +19501,133 @@ function AiMediaStripOverlay({
|
|
|
19125
19501
|
tree: nextTree,
|
|
19126
19502
|
label: entry.label,
|
|
19127
19503
|
media: extraMedia ? { ...entry.media, ...extraMedia } : entry.media,
|
|
19128
|
-
...entry.brand ? { brand: entry.brand } : {}
|
|
19504
|
+
...entry.brand ? { brand: entry.brand } : {},
|
|
19505
|
+
// The user is already looking at the strip they just edited — recentering the viewport
|
|
19506
|
+
// on every edit reads as the section jumping around.
|
|
19507
|
+
skipScrollIntoView: true
|
|
19129
19508
|
});
|
|
19130
19509
|
return true;
|
|
19131
19510
|
},
|
|
19132
19511
|
[findEntry, postToParent2, applyTreeLocalRef]
|
|
19133
19512
|
);
|
|
19134
19513
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
19135
|
-
const hoverHandleRect = useLiveItemRect(!active && hover ? hover : null);
|
|
19136
19514
|
const activeItemRect = useLiveItemRect(active);
|
|
19137
|
-
const
|
|
19138
|
-
const
|
|
19139
|
-
|
|
19140
|
-
|
|
19141
|
-
|
|
19142
|
-
|
|
19143
|
-
|
|
19144
|
-
|
|
19145
|
-
|
|
19146
|
-
|
|
19147
|
-
|
|
19148
|
-
|
|
19149
|
-
|
|
19150
|
-
|
|
19151
|
-
|
|
19152
|
-
|
|
19153
|
-
|
|
19154
|
-
|
|
19155
|
-
|
|
19156
|
-
|
|
19157
|
-
|
|
19158
|
-
|
|
19159
|
-
|
|
19160
|
-
|
|
19161
|
-
|
|
19162
|
-
|
|
19163
|
-
|
|
19164
|
-
|
|
19165
|
-
|
|
19166
|
-
|
|
19167
|
-
|
|
19168
|
-
|
|
19169
|
-
|
|
19170
|
-
|
|
19171
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */ jsx20(
|
|
19172
|
-
ItemInteractionLayer,
|
|
19173
|
-
{
|
|
19174
|
-
rect: activeItemRect,
|
|
19175
|
-
state: toolbarState,
|
|
19176
|
-
toolbar: /* @__PURE__ */ jsx20(
|
|
19177
|
-
MediaStripToolbar,
|
|
19178
|
-
{
|
|
19179
|
-
entry: activeEntry,
|
|
19180
|
-
index: active.index,
|
|
19181
|
-
pending,
|
|
19182
|
-
error,
|
|
19183
|
-
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
19184
|
-
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
19185
|
-
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
19186
|
-
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
19187
|
-
onResize: (delta) => {
|
|
19188
|
-
const slots = findMediaStripSlots(activeEntry.tree);
|
|
19189
|
-
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19190
|
-
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19191
|
-
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
19192
|
-
},
|
|
19193
|
-
onSetAlt: (alt) => {
|
|
19194
|
-
void runMutation(active.sectionId, (tree) => setMediaStripItemAlt(tree, active.index, alt));
|
|
19195
|
-
},
|
|
19196
|
-
onSetLink: (href, linkTarget) => {
|
|
19515
|
+
const activeStripRect = useLiveItemRect(active, true);
|
|
19516
|
+
const hoverRect = useLiveItemRect(hover && !sameRef(hover, active) ? hover : null);
|
|
19517
|
+
const activeItems = activeEntry ? mediaStripItems(activeEntry.tree) : [];
|
|
19518
|
+
const activeItem = active ? activeItems[active.index] : void 0;
|
|
19519
|
+
const activeHref = activeItem?.href ?? "";
|
|
19520
|
+
const activeTarget = activeItem?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
19521
|
+
return /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
19522
|
+
hoverRect && /* @__PURE__ */ jsx21(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
19523
|
+
activeItemRect && activeStripRect && active && activeEntry && /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
19524
|
+
/* @__PURE__ */ jsx21(ItemInteractionLayer, { rect: activeItemRect, state: "active-top" }),
|
|
19525
|
+
/* @__PURE__ */ jsx21(StripToolbarSlot, { stripRect: activeStripRect, children: /* @__PURE__ */ jsx21(
|
|
19526
|
+
MediaStripToolbar,
|
|
19527
|
+
{
|
|
19528
|
+
entry: activeEntry,
|
|
19529
|
+
index: active.index,
|
|
19530
|
+
pending,
|
|
19531
|
+
error,
|
|
19532
|
+
itemEditOn,
|
|
19533
|
+
onToggleItemEdit: () => setItemEditOn((on) => !on),
|
|
19534
|
+
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
19535
|
+
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
19536
|
+
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
19537
|
+
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
19538
|
+
onResize: (delta) => {
|
|
19539
|
+
const slots = findMediaStripSlots(activeEntry.tree);
|
|
19540
|
+
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19541
|
+
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19542
|
+
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
19543
|
+
},
|
|
19544
|
+
onOpenLink: () => setLinkOpen(true),
|
|
19545
|
+
onAddItem: () => {
|
|
19546
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
19547
|
+
if (!picked) return;
|
|
19548
|
+
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
19197
19549
|
void runMutation(
|
|
19198
19550
|
active.sectionId,
|
|
19199
|
-
(tree) =>
|
|
19200
|
-
|
|
19201
|
-
|
|
19202
|
-
|
|
19203
|
-
void requestAssetPick(postToParent2).then((picked) => {
|
|
19204
|
-
if (!picked) return;
|
|
19205
|
-
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
19206
|
-
void runMutation(
|
|
19207
|
-
active.sectionId,
|
|
19208
|
-
(tree) => addMediaStripItem(tree, item, active.index),
|
|
19209
|
-
{ [picked.assetId]: picked.url }
|
|
19210
|
-
).then((applied) => {
|
|
19211
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19212
|
-
});
|
|
19551
|
+
(tree) => addMediaStripItem(tree, item, active.index),
|
|
19552
|
+
{ [picked.assetId]: picked.url }
|
|
19553
|
+
).then((applied) => {
|
|
19554
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19213
19555
|
});
|
|
19214
|
-
}
|
|
19215
|
-
|
|
19216
|
-
|
|
19217
|
-
|
|
19218
|
-
|
|
19219
|
-
|
|
19220
|
-
|
|
19221
|
-
|
|
19222
|
-
|
|
19223
|
-
});
|
|
19224
|
-
},
|
|
19225
|
-
onRemoveItem: () => {
|
|
19226
|
-
void runMutation(active.sectionId, (tree) => removeMediaStripItem(tree, active.index)).then(
|
|
19227
|
-
(applied) => {
|
|
19228
|
-
if (applied) setActive(null);
|
|
19229
|
-
}
|
|
19230
|
-
);
|
|
19231
|
-
},
|
|
19232
|
-
onMoveLeft: () => {
|
|
19233
|
-
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
19234
|
-
(applied) => {
|
|
19235
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
19236
|
-
}
|
|
19237
|
-
);
|
|
19238
|
-
},
|
|
19239
|
-
onMoveRight: () => {
|
|
19240
|
-
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
19241
|
-
(applied) => {
|
|
19242
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19243
|
-
}
|
|
19556
|
+
});
|
|
19557
|
+
},
|
|
19558
|
+
onChangeImage: () => {
|
|
19559
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
19560
|
+
if (!picked) return;
|
|
19561
|
+
void runMutation(
|
|
19562
|
+
active.sectionId,
|
|
19563
|
+
(tree) => setMediaStripItemAsset(tree, active.index, picked.assetId),
|
|
19564
|
+
{ [picked.assetId]: picked.url }
|
|
19244
19565
|
);
|
|
19245
|
-
}
|
|
19566
|
+
});
|
|
19567
|
+
},
|
|
19568
|
+
onRemoveItem: () => {
|
|
19569
|
+
void runMutation(active.sectionId, (tree) => removeMediaStripItem(tree, active.index)).then(
|
|
19570
|
+
(applied) => {
|
|
19571
|
+
if (applied) setActive(null);
|
|
19572
|
+
}
|
|
19573
|
+
);
|
|
19574
|
+
},
|
|
19575
|
+
onMoveLeft: () => {
|
|
19576
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
19577
|
+
(applied) => {
|
|
19578
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
19579
|
+
}
|
|
19580
|
+
);
|
|
19581
|
+
},
|
|
19582
|
+
onMoveRight: () => {
|
|
19583
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
19584
|
+
(applied) => {
|
|
19585
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19586
|
+
}
|
|
19587
|
+
);
|
|
19246
19588
|
}
|
|
19247
|
-
|
|
19248
|
-
}
|
|
19249
|
-
|
|
19589
|
+
}
|
|
19590
|
+
) }),
|
|
19591
|
+
/* @__PURE__ */ jsx21(
|
|
19592
|
+
"div",
|
|
19593
|
+
{
|
|
19594
|
+
"data-ohw-bridge": "",
|
|
19595
|
+
"data-ohw-item-interaction": "",
|
|
19596
|
+
"aria-hidden": true,
|
|
19597
|
+
className: "pointer-events-none fixed rounded-[4px] px-[7px] py-[3px] font-sans text-[11px] font-medium leading-none text-primary-foreground whitespace-nowrap",
|
|
19598
|
+
style: {
|
|
19599
|
+
top: activeItemRect.top + activeItemRect.height + 10,
|
|
19600
|
+
left: activeItemRect.left - 5,
|
|
19601
|
+
background: PRIMARY3,
|
|
19602
|
+
zIndex: 2147483644
|
|
19603
|
+
},
|
|
19604
|
+
children: "Media item"
|
|
19605
|
+
}
|
|
19606
|
+
),
|
|
19607
|
+
linkOpen && /* @__PURE__ */ jsx21(
|
|
19608
|
+
LinkModal,
|
|
19609
|
+
{
|
|
19610
|
+
href: activeHref,
|
|
19611
|
+
linkTarget: activeTarget,
|
|
19612
|
+
onClose: () => setLinkOpen(false),
|
|
19613
|
+
onSave: (href, linkTarget) => {
|
|
19614
|
+
void runMutation(
|
|
19615
|
+
active.sectionId,
|
|
19616
|
+
(tree) => setMediaStripItemLink(tree, active.index, href ? { href, linkTarget } : {})
|
|
19617
|
+
);
|
|
19618
|
+
}
|
|
19619
|
+
}
|
|
19620
|
+
)
|
|
19621
|
+
] })
|
|
19250
19622
|
] });
|
|
19251
19623
|
}
|
|
19252
19624
|
|
|
19253
19625
|
// src/ui/ai-section/AiPricingCardOverlay.tsx
|
|
19254
|
-
import { useCallback as useCallback4, useEffect as useEffect7, useLayoutEffect as
|
|
19255
|
-
import { Check as
|
|
19256
|
-
import { Fragment as Fragment8, jsx as
|
|
19626
|
+
import { useCallback as useCallback4, useEffect as useEffect7, useLayoutEffect as useLayoutEffect5, useRef as useRef6, useState as useState9 } from "react";
|
|
19627
|
+
import { Check as Check3, ChevronDown as ChevronDown4, Minus as Minus2, Plus as Plus3, Star as Star2 } from "lucide-react";
|
|
19628
|
+
import { Fragment as Fragment8, jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
19257
19629
|
var PRIMARY4 = "var(--ohw-primary, #0885FE)";
|
|
19258
|
-
var
|
|
19630
|
+
var CHROME_SELECTOR2 = "[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-link-modal-root], [data-ohw-section-picker], [data-ohw-ai-review], [data-ohw-more-menu]";
|
|
19259
19631
|
function findPricingCardElement(sectionId, index) {
|
|
19260
19632
|
const sectionEl = findByInstanceId(sectionId);
|
|
19261
19633
|
if (!sectionEl) return null;
|
|
@@ -19267,7 +19639,7 @@ function findPricingCardElement(sectionId, index) {
|
|
|
19267
19639
|
}
|
|
19268
19640
|
function cardRefFromTarget(target) {
|
|
19269
19641
|
if (!(target instanceof Element)) return null;
|
|
19270
|
-
if (target.closest(
|
|
19642
|
+
if (target.closest(CHROME_SELECTOR2)) return null;
|
|
19271
19643
|
const cardEl = target.closest("[data-ohw-pricing-card]");
|
|
19272
19644
|
if (!cardEl) return null;
|
|
19273
19645
|
const sectionEl = cardEl.closest("[data-ohw-section]");
|
|
@@ -19277,21 +19649,21 @@ function cardRefFromTarget(target) {
|
|
|
19277
19649
|
if (!sectionId || Number.isNaN(index)) return null;
|
|
19278
19650
|
return { sectionId, index };
|
|
19279
19651
|
}
|
|
19280
|
-
function
|
|
19652
|
+
function sameRef2(a, b) {
|
|
19281
19653
|
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
19282
19654
|
}
|
|
19283
|
-
function
|
|
19655
|
+
function rectOf2(el) {
|
|
19284
19656
|
if (!el) return null;
|
|
19285
19657
|
const r2 = el.getBoundingClientRect();
|
|
19286
19658
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
19287
19659
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
19288
19660
|
}
|
|
19289
19661
|
function readRect3(ref) {
|
|
19290
|
-
return
|
|
19662
|
+
return rectOf2(ref && findPricingCardElement(ref.sectionId, ref.index));
|
|
19291
19663
|
}
|
|
19292
19664
|
function readGridRect(ref) {
|
|
19293
19665
|
const card = ref && findPricingCardElement(ref.sectionId, ref.index);
|
|
19294
|
-
return
|
|
19666
|
+
return rectOf2(card?.closest("[data-ohw-pricing-collection]") ?? card);
|
|
19295
19667
|
}
|
|
19296
19668
|
function useLiveCardRect(ref, grid = false) {
|
|
19297
19669
|
const [rect, setRect] = useState9(null);
|
|
@@ -19321,19 +19693,19 @@ function useLiveCardRect(ref, grid = false) {
|
|
|
19321
19693
|
}
|
|
19322
19694
|
var TOOLBAR_GRID_GAP = 52;
|
|
19323
19695
|
var TOOLBAR_GRID_GAP_MOBILE = 42;
|
|
19324
|
-
var
|
|
19696
|
+
var TOOLBAR_EDGE_MARGIN3 = 4;
|
|
19325
19697
|
function GridToolbarSlot({ gridRect, children }) {
|
|
19326
19698
|
const slotRef = useRef6(null);
|
|
19327
19699
|
const [shift, setShift] = useState9(0);
|
|
19328
19700
|
const centerX = gridRect.left + gridRect.width / 2;
|
|
19329
|
-
|
|
19701
|
+
useLayoutEffect5(() => {
|
|
19330
19702
|
const slot = slotRef.current;
|
|
19331
19703
|
if (!slot) return;
|
|
19332
19704
|
const clamp = () => {
|
|
19333
19705
|
const w = slot.offsetWidth;
|
|
19334
19706
|
if (w <= 0) return;
|
|
19335
19707
|
const half = w / 2;
|
|
19336
|
-
const clamped = Math.max(
|
|
19708
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN3 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN3 - half));
|
|
19337
19709
|
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
19338
19710
|
};
|
|
19339
19711
|
clamp();
|
|
@@ -19342,7 +19714,7 @@ function GridToolbarSlot({ gridRect, children }) {
|
|
|
19342
19714
|
return () => ro.disconnect();
|
|
19343
19715
|
}, [centerX, children]);
|
|
19344
19716
|
const mobile = window.innerWidth <= 480;
|
|
19345
|
-
return /* @__PURE__ */
|
|
19717
|
+
return /* @__PURE__ */ jsx22(
|
|
19346
19718
|
"div",
|
|
19347
19719
|
{
|
|
19348
19720
|
ref: slotRef,
|
|
@@ -19377,7 +19749,7 @@ function requestValidateTree2(postToParent2, tree) {
|
|
|
19377
19749
|
});
|
|
19378
19750
|
}
|
|
19379
19751
|
function StyleSwatch({ style }) {
|
|
19380
|
-
return /* @__PURE__ */
|
|
19752
|
+
return /* @__PURE__ */ jsx22(
|
|
19381
19753
|
"span",
|
|
19382
19754
|
{
|
|
19383
19755
|
"aria-hidden": true,
|
|
@@ -19391,35 +19763,35 @@ function StyleSwatch({ style }) {
|
|
|
19391
19763
|
);
|
|
19392
19764
|
}
|
|
19393
19765
|
function ButtonGlyph() {
|
|
19394
|
-
return /* @__PURE__ */
|
|
19395
|
-
/* @__PURE__ */
|
|
19396
|
-
/* @__PURE__ */
|
|
19766
|
+
return /* @__PURE__ */ jsxs13("svg", { width: "18", height: "12", viewBox: "0 0 18 12", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19767
|
+
/* @__PURE__ */ jsx22("rect", { x: "0.75", y: "0.75", width: "16.5", height: "10.5", rx: "3", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19768
|
+
/* @__PURE__ */ jsx22("path", { d: "M5.5 6H12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
|
|
19397
19769
|
] });
|
|
19398
19770
|
}
|
|
19399
19771
|
function FeatureGlyph({ mode }) {
|
|
19400
|
-
return /* @__PURE__ */
|
|
19401
|
-
/* @__PURE__ */
|
|
19402
|
-
/* @__PURE__ */
|
|
19403
|
-
/* @__PURE__ */
|
|
19404
|
-
/* @__PURE__ */
|
|
19405
|
-
/* @__PURE__ */
|
|
19406
|
-
mode === "add" && /* @__PURE__ */
|
|
19772
|
+
return /* @__PURE__ */ jsxs13("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19773
|
+
/* @__PURE__ */ jsx22("circle", { cx: "8", cy: "8", r: "7.25", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19774
|
+
/* @__PURE__ */ jsx22("path", { d: "M5 8.2L7.2 10.3L11 6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
19775
|
+
/* @__PURE__ */ jsx22("circle", { cx: "13.5", cy: "13.5", r: "4.25", fill: "var(--ohw-background, #ffffff)", stroke: "var(--ohw-background, #ffffff)", strokeWidth: "1" }),
|
|
19776
|
+
/* @__PURE__ */ jsx22("circle", { cx: "13.5", cy: "13.5", r: "3.75", fill: "var(--ohw-background, #ffffff)", stroke: PRIMARY4, strokeWidth: "1" }),
|
|
19777
|
+
/* @__PURE__ */ jsx22("path", { d: "M11.5 13.5H15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
19778
|
+
mode === "add" && /* @__PURE__ */ jsx22("path", { d: "M13.5 11.5V15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" })
|
|
19407
19779
|
] });
|
|
19408
19780
|
}
|
|
19409
|
-
function
|
|
19781
|
+
function ToolbarAction2({
|
|
19410
19782
|
label,
|
|
19411
19783
|
onClick,
|
|
19412
19784
|
disabled = false,
|
|
19413
19785
|
children
|
|
19414
19786
|
}) {
|
|
19415
|
-
const button = /* @__PURE__ */
|
|
19416
|
-
return /* @__PURE__ */
|
|
19417
|
-
/* @__PURE__ */
|
|
19418
|
-
/* @__PURE__ */
|
|
19787
|
+
const button = /* @__PURE__ */ jsx22(CustomToolbarButton, { type: "button", "aria-label": label, disabled, onClick, className: "size-8", children });
|
|
19788
|
+
return /* @__PURE__ */ jsxs13(Tooltip, { children: [
|
|
19789
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ jsx22("span", { className: "inline-flex", children: button }) : button }),
|
|
19790
|
+
/* @__PURE__ */ jsx22(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
19419
19791
|
] });
|
|
19420
19792
|
}
|
|
19421
|
-
function
|
|
19422
|
-
return /* @__PURE__ */
|
|
19793
|
+
function ToolbarSeparator2() {
|
|
19794
|
+
return /* @__PURE__ */ jsx22("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
19423
19795
|
}
|
|
19424
19796
|
function CardStyleMenu({
|
|
19425
19797
|
value,
|
|
@@ -19427,7 +19799,7 @@ function CardStyleMenu({
|
|
|
19427
19799
|
disabled = false
|
|
19428
19800
|
}) {
|
|
19429
19801
|
const current = PRICING_CARD_STYLES.find((s) => s.value === value) ?? PRICING_CARD_STYLES[0];
|
|
19430
|
-
const trigger = /* @__PURE__ */
|
|
19802
|
+
const trigger = /* @__PURE__ */ jsxs13(
|
|
19431
19803
|
"button",
|
|
19432
19804
|
{
|
|
19433
19805
|
type: "button",
|
|
@@ -19438,28 +19810,28 @@ function CardStyleMenu({
|
|
|
19438
19810
|
disabled && "cursor-not-allowed opacity-40 hover:bg-transparent"
|
|
19439
19811
|
),
|
|
19440
19812
|
children: [
|
|
19441
|
-
/* @__PURE__ */
|
|
19442
|
-
/* @__PURE__ */
|
|
19443
|
-
/* @__PURE__ */
|
|
19813
|
+
/* @__PURE__ */ jsx22(StyleSwatch, { style: current.value }),
|
|
19814
|
+
/* @__PURE__ */ jsx22("span", { className: "flex-1 text-left", children: current.label }),
|
|
19815
|
+
/* @__PURE__ */ jsx22(ChevronDown4, { size: 16, style: { pointerEvents: "none" } })
|
|
19444
19816
|
]
|
|
19445
19817
|
}
|
|
19446
19818
|
);
|
|
19447
19819
|
if (disabled) {
|
|
19448
|
-
return /* @__PURE__ */
|
|
19449
|
-
/* @__PURE__ */
|
|
19450
|
-
/* @__PURE__ */
|
|
19451
|
-
/* @__PURE__ */
|
|
19452
|
-
/* @__PURE__ */
|
|
19820
|
+
return /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19821
|
+
/* @__PURE__ */ jsx22("span", { className: "text-xs text-muted-foreground opacity-50", children: "Card style" }),
|
|
19822
|
+
/* @__PURE__ */ jsxs13(Tooltip, { children: [
|
|
19823
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx22("span", { className: "inline-flex", children: trigger }) }),
|
|
19824
|
+
/* @__PURE__ */ jsx22(TooltipContent, { side: "bottom", sideOffset: 8, children: "Mark as featured to edit card style" })
|
|
19453
19825
|
] })
|
|
19454
19826
|
] });
|
|
19455
19827
|
}
|
|
19456
|
-
return /* @__PURE__ */
|
|
19457
|
-
/* @__PURE__ */
|
|
19458
|
-
/* @__PURE__ */
|
|
19459
|
-
/* @__PURE__ */
|
|
19460
|
-
/* @__PURE__ */
|
|
19828
|
+
return /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19829
|
+
/* @__PURE__ */ jsx22("span", { className: "text-xs text-muted-foreground", children: "Card style" }),
|
|
19830
|
+
/* @__PURE__ */ jsxs13(DropdownMenu, { modal: false, children: [
|
|
19831
|
+
/* @__PURE__ */ jsx22(DropdownMenuTrigger, { asChild: true, children: trigger }),
|
|
19832
|
+
/* @__PURE__ */ jsx22(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[152px] min-w-[152px] p-1", children: PRICING_CARD_STYLES.map((style) => {
|
|
19461
19833
|
const selected = style.value === value;
|
|
19462
|
-
return /* @__PURE__ */
|
|
19834
|
+
return /* @__PURE__ */ jsxs13(
|
|
19463
19835
|
DropdownMenuItem,
|
|
19464
19836
|
{
|
|
19465
19837
|
role: "menuitemradio",
|
|
@@ -19467,9 +19839,9 @@ function CardStyleMenu({
|
|
|
19467
19839
|
onSelect: () => onChange(style.value),
|
|
19468
19840
|
className: cn("grid grid-cols-[18px_1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
19469
19841
|
children: [
|
|
19470
|
-
/* @__PURE__ */
|
|
19471
|
-
/* @__PURE__ */
|
|
19472
|
-
selected && /* @__PURE__ */
|
|
19842
|
+
/* @__PURE__ */ jsx22(StyleSwatch, { style: style.value }),
|
|
19843
|
+
/* @__PURE__ */ jsx22("span", { children: style.label }),
|
|
19844
|
+
selected && /* @__PURE__ */ jsx22(Check3, { size: 16, className: "text-bridge-primary" })
|
|
19473
19845
|
]
|
|
19474
19846
|
},
|
|
19475
19847
|
style.value
|
|
@@ -19499,7 +19871,7 @@ function PricingCardToolbar({
|
|
|
19499
19871
|
const style = pricingCardStyle(entry.tree, index);
|
|
19500
19872
|
const featuredTag = pricingCardFeaturedTag(entry.tree, index);
|
|
19501
19873
|
const mobile = window.innerWidth <= 480;
|
|
19502
|
-
return /* @__PURE__ */
|
|
19874
|
+
return /* @__PURE__ */ jsx22(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs13(
|
|
19503
19875
|
"div",
|
|
19504
19876
|
{
|
|
19505
19877
|
"data-ohw-bridge": "",
|
|
@@ -19511,7 +19883,7 @@ function PricingCardToolbar({
|
|
|
19511
19883
|
),
|
|
19512
19884
|
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
19513
19885
|
children: [
|
|
19514
|
-
/* @__PURE__ */
|
|
19886
|
+
/* @__PURE__ */ jsxs13(
|
|
19515
19887
|
"div",
|
|
19516
19888
|
{
|
|
19517
19889
|
className: cn(
|
|
@@ -19520,8 +19892,8 @@ function PricingCardToolbar({
|
|
|
19520
19892
|
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
19521
19893
|
),
|
|
19522
19894
|
children: [
|
|
19523
|
-
/* @__PURE__ */
|
|
19524
|
-
/* @__PURE__ */
|
|
19895
|
+
/* @__PURE__ */ jsxs13(Tooltip, { children: [
|
|
19896
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx22(
|
|
19525
19897
|
CustomToolbarButton,
|
|
19526
19898
|
{
|
|
19527
19899
|
type: "button",
|
|
@@ -19529,7 +19901,7 @@ function PricingCardToolbar({
|
|
|
19529
19901
|
"aria-pressed": featuredTag,
|
|
19530
19902
|
onClick: () => onSetFeaturedTag(!featuredTag),
|
|
19531
19903
|
className: "group size-8",
|
|
19532
|
-
children: /* @__PURE__ */
|
|
19904
|
+
children: /* @__PURE__ */ jsx22(
|
|
19533
19905
|
Star2,
|
|
19534
19906
|
{
|
|
19535
19907
|
size: 16,
|
|
@@ -19544,25 +19916,25 @@ function PricingCardToolbar({
|
|
|
19544
19916
|
)
|
|
19545
19917
|
}
|
|
19546
19918
|
) }),
|
|
19547
|
-
/* @__PURE__ */
|
|
19919
|
+
/* @__PURE__ */ jsx22(TooltipContent, { side: "bottom", sideOffset: 8, children: featuredTag ? "Unmark featured" : "Mark as featured" })
|
|
19548
19920
|
] }),
|
|
19549
|
-
/* @__PURE__ */
|
|
19550
|
-
/* @__PURE__ */
|
|
19551
|
-
/* @__PURE__ */
|
|
19552
|
-
/* @__PURE__ */
|
|
19553
|
-
/* @__PURE__ */
|
|
19554
|
-
/* @__PURE__ */
|
|
19555
|
-
/* @__PURE__ */
|
|
19921
|
+
/* @__PURE__ */ jsx22(ToolbarSeparator2, {}),
|
|
19922
|
+
/* @__PURE__ */ jsx22(CardStyleMenu, { value: style, onChange: onSetStyle, disabled: !featuredTag }),
|
|
19923
|
+
/* @__PURE__ */ jsx22(ToolbarSeparator2, {}),
|
|
19924
|
+
/* @__PURE__ */ jsx22(ToolbarAction2, { label: "Add button", onClick: onAddButton, disabled: buttonCount >= 2, children: /* @__PURE__ */ jsx22(ButtonGlyph, {}) }),
|
|
19925
|
+
/* @__PURE__ */ jsx22(ToolbarAction2, { label: "Remove button", onClick: onRemoveButton, disabled: buttonCount === 0, children: /* @__PURE__ */ jsxs13("span", { className: "relative inline-flex", children: [
|
|
19926
|
+
/* @__PURE__ */ jsx22(ButtonGlyph, {}),
|
|
19927
|
+
/* @__PURE__ */ jsx22(Minus2, { size: 10, strokeWidth: 2.5, className: "absolute -right-1.5 -top-1.5 rounded-full bg-background text-bridge-primary" })
|
|
19556
19928
|
] }) }),
|
|
19557
|
-
/* @__PURE__ */
|
|
19558
|
-
/* @__PURE__ */
|
|
19559
|
-
/* @__PURE__ */
|
|
19560
|
-
/* @__PURE__ */
|
|
19561
|
-
/* @__PURE__ */
|
|
19929
|
+
/* @__PURE__ */ jsx22(ToolbarAction2, { label: "Add feature", onClick: onAddFeature, disabled: featureCount >= 10, children: /* @__PURE__ */ jsx22(FeatureGlyph, { mode: "add" }) }),
|
|
19930
|
+
/* @__PURE__ */ jsx22(ToolbarAction2, { label: "Remove feature", onClick: onRemoveFeature, disabled: featureCount <= 1, children: /* @__PURE__ */ jsx22(FeatureGlyph, { mode: "remove" }) }),
|
|
19931
|
+
/* @__PURE__ */ jsx22(ToolbarSeparator2, {}),
|
|
19932
|
+
/* @__PURE__ */ jsx22(ToolbarAction2, { label: "Add tier", onClick: onAddTier, disabled: collectionCount >= 4, children: /* @__PURE__ */ jsx22(Plus3, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19933
|
+
/* @__PURE__ */ jsx22(ToolbarAction2, { label: "Remove tier", onClick: onRemoveTier, disabled: collectionCount <= 1, children: /* @__PURE__ */ jsx22(Minus2, { size: 16, style: { pointerEvents: "none" } }) })
|
|
19562
19934
|
]
|
|
19563
19935
|
}
|
|
19564
19936
|
),
|
|
19565
|
-
error && /* @__PURE__ */
|
|
19937
|
+
error && /* @__PURE__ */ jsx22("div", { className: "max-w-[260px] rounded-md bg-background px-2 py-1 text-center text-[11px] text-destructive shadow-sm", children: error })
|
|
19566
19938
|
]
|
|
19567
19939
|
}
|
|
19568
19940
|
) });
|
|
@@ -19596,7 +19968,7 @@ function AiPricingCardOverlay({
|
|
|
19596
19968
|
const overEditable = Boolean(t?.closest?.("[data-ohw-editable], [data-ohw-role], a, button"));
|
|
19597
19969
|
setHover((prev) => {
|
|
19598
19970
|
const next = ref && !overEditable ? ref : null;
|
|
19599
|
-
return
|
|
19971
|
+
return sameRef2(prev, next) ? prev : next;
|
|
19600
19972
|
});
|
|
19601
19973
|
};
|
|
19602
19974
|
const onLeave = () => setHover(null);
|
|
@@ -19611,10 +19983,10 @@ function AiPricingCardOverlay({
|
|
|
19611
19983
|
const onClick = (e) => {
|
|
19612
19984
|
const t = e.target;
|
|
19613
19985
|
if (!(t instanceof Element)) return;
|
|
19614
|
-
if (t.closest(
|
|
19986
|
+
if (t.closest(CHROME_SELECTOR2)) return;
|
|
19615
19987
|
const ref = cardRefFromTarget(t);
|
|
19616
|
-
setActive((prev) =>
|
|
19617
|
-
if (!ref || !
|
|
19988
|
+
setActive((prev) => sameRef2(prev, ref) ? prev : ref);
|
|
19989
|
+
if (!ref || !sameRef2(activeRef.current, ref)) setError(null);
|
|
19618
19990
|
};
|
|
19619
19991
|
document.addEventListener("click", onClick, true);
|
|
19620
19992
|
return () => document.removeEventListener("click", onClick, true);
|
|
@@ -19679,12 +20051,12 @@ function AiPricingCardOverlay({
|
|
|
19679
20051
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
19680
20052
|
const activeCardRect = useLiveCardRect(active);
|
|
19681
20053
|
const activeGridRect = useLiveCardRect(active, true);
|
|
19682
|
-
const hoverRect = useLiveCardRect(hover && !
|
|
19683
|
-
return /* @__PURE__ */
|
|
19684
|
-
hoverRect && /* @__PURE__ */
|
|
19685
|
-
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */
|
|
19686
|
-
/* @__PURE__ */
|
|
19687
|
-
/* @__PURE__ */
|
|
20054
|
+
const hoverRect = useLiveCardRect(hover && !sameRef2(hover, active) ? hover : null);
|
|
20055
|
+
return /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
20056
|
+
hoverRect && /* @__PURE__ */ jsx22(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
20057
|
+
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
20058
|
+
/* @__PURE__ */ jsx22(ItemInteractionLayer, { rect: activeCardRect, state: "active-top" }),
|
|
20059
|
+
/* @__PURE__ */ jsx22(GridToolbarSlot, { gridRect: activeGridRect, children: /* @__PURE__ */ jsx22(
|
|
19688
20060
|
PricingCardToolbar,
|
|
19689
20061
|
{
|
|
19690
20062
|
entry: activeEntry,
|
|
@@ -19712,7 +20084,7 @@ function AiPricingCardOverlay({
|
|
|
19712
20084
|
onRemoveFeature: () => runMutation(active.sectionId, (tree) => removePricingCardFeature(tree, active.index))
|
|
19713
20085
|
}
|
|
19714
20086
|
) }),
|
|
19715
|
-
/* @__PURE__ */
|
|
20087
|
+
/* @__PURE__ */ jsx22(
|
|
19716
20088
|
"div",
|
|
19717
20089
|
{
|
|
19718
20090
|
"data-ohw-bridge": "",
|
|
@@ -19805,10 +20177,10 @@ function extractYouTubeId(input) {
|
|
|
19805
20177
|
}
|
|
19806
20178
|
|
|
19807
20179
|
// src/ui/ai-section/AiVideoOverlay.tsx
|
|
19808
|
-
import { Fragment as Fragment9, jsx as
|
|
20180
|
+
import { Fragment as Fragment9, jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
19809
20181
|
var PRIMARY5 = "#0885FE";
|
|
19810
|
-
var
|
|
19811
|
-
var
|
|
20182
|
+
var OHW_BLUE = `var(--ohw-primary, ${PRIMARY5})`;
|
|
20183
|
+
var OHW_BLUE_DARK = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY5}) 60%, #000000)`;
|
|
19812
20184
|
function findVideoBlockElement(sectionId, path) {
|
|
19813
20185
|
const sectionEl = findByInstanceId(sectionId);
|
|
19814
20186
|
if (!sectionEl) return null;
|
|
@@ -19868,12 +20240,12 @@ function requestValidateTree3(postToParent2, tree) {
|
|
|
19868
20240
|
postToParent2({ type: "ow:ai-validate-tree-request", id, tree });
|
|
19869
20241
|
});
|
|
19870
20242
|
}
|
|
19871
|
-
function
|
|
20243
|
+
function Pill({
|
|
19872
20244
|
label,
|
|
19873
20245
|
onClick,
|
|
19874
20246
|
disabled
|
|
19875
20247
|
}) {
|
|
19876
|
-
return /* @__PURE__ */
|
|
20248
|
+
return /* @__PURE__ */ jsx23(
|
|
19877
20249
|
"button",
|
|
19878
20250
|
{
|
|
19879
20251
|
type: "button",
|
|
@@ -19889,7 +20261,7 @@ function Pill2({
|
|
|
19889
20261
|
border: "none",
|
|
19890
20262
|
cursor: disabled ? "default" : "pointer",
|
|
19891
20263
|
background: "#ffffff",
|
|
19892
|
-
color:
|
|
20264
|
+
color: OHW_BLUE_DARK,
|
|
19893
20265
|
opacity: disabled ? 0.4 : 1,
|
|
19894
20266
|
fontSize: 12,
|
|
19895
20267
|
lineHeight: "16px",
|
|
@@ -19911,7 +20283,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
19911
20283
|
setDraft(value ? watchUrl(value) : "");
|
|
19912
20284
|
setInvalid(false);
|
|
19913
20285
|
}, [value]);
|
|
19914
|
-
const
|
|
20286
|
+
const commit2 = () => {
|
|
19915
20287
|
const next = draft.trim();
|
|
19916
20288
|
if (!next) {
|
|
19917
20289
|
setInvalid(false);
|
|
@@ -19932,8 +20304,8 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
19932
20304
|
onCommit(id);
|
|
19933
20305
|
}
|
|
19934
20306
|
};
|
|
19935
|
-
return /* @__PURE__ */
|
|
19936
|
-
/* @__PURE__ */
|
|
20307
|
+
return /* @__PURE__ */ jsxs14("div", { style: { display: "flex", flexDirection: "column", gap: 4, width: "100%", maxWidth: 280 }, children: [
|
|
20308
|
+
/* @__PURE__ */ jsxs14(
|
|
19937
20309
|
"div",
|
|
19938
20310
|
{
|
|
19939
20311
|
style: {
|
|
@@ -19949,12 +20321,12 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
19949
20321
|
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
19950
20322
|
},
|
|
19951
20323
|
children: [
|
|
19952
|
-
/* @__PURE__ */
|
|
20324
|
+
/* @__PURE__ */ jsx23(
|
|
19953
20325
|
"span",
|
|
19954
20326
|
{
|
|
19955
20327
|
style: {
|
|
19956
20328
|
flex: "0 0 auto",
|
|
19957
|
-
color:
|
|
20329
|
+
color: OHW_BLUE_DARK,
|
|
19958
20330
|
fontSize: 10,
|
|
19959
20331
|
lineHeight: "16px",
|
|
19960
20332
|
fontWeight: 700,
|
|
@@ -19964,14 +20336,14 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
19964
20336
|
children: "Video"
|
|
19965
20337
|
}
|
|
19966
20338
|
),
|
|
19967
|
-
/* @__PURE__ */
|
|
20339
|
+
/* @__PURE__ */ jsx23(
|
|
19968
20340
|
"input",
|
|
19969
20341
|
{
|
|
19970
20342
|
type: "text",
|
|
19971
20343
|
inputMode: "url",
|
|
19972
20344
|
value: draft,
|
|
19973
20345
|
onChange: (e) => handleChange(e.target.value),
|
|
19974
|
-
onBlur:
|
|
20346
|
+
onBlur: commit2,
|
|
19975
20347
|
onKeyDown: (e) => {
|
|
19976
20348
|
if (e.key === "Enter") e.currentTarget.blur();
|
|
19977
20349
|
if (e.key === "Escape") {
|
|
@@ -20001,7 +20373,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20001
20373
|
]
|
|
20002
20374
|
}
|
|
20003
20375
|
),
|
|
20004
|
-
invalid && /* @__PURE__ */
|
|
20376
|
+
invalid && /* @__PURE__ */ jsx23("div", { style: { color: "#FCA5A5", fontSize: 11, textAlign: "center" }, children: "That doesn't look like a YouTube link \u2014 try pasting the video URL again." })
|
|
20005
20377
|
] });
|
|
20006
20378
|
}
|
|
20007
20379
|
function VideoToolbar({
|
|
@@ -20011,7 +20383,7 @@ function VideoToolbar({
|
|
|
20011
20383
|
onSetVideoId,
|
|
20012
20384
|
onRemove
|
|
20013
20385
|
}) {
|
|
20014
|
-
return /* @__PURE__ */
|
|
20386
|
+
return /* @__PURE__ */ jsxs14(
|
|
20015
20387
|
"div",
|
|
20016
20388
|
{
|
|
20017
20389
|
"data-ohw-bridge": "",
|
|
@@ -20023,7 +20395,7 @@ function VideoToolbar({
|
|
|
20023
20395
|
gap: 6,
|
|
20024
20396
|
alignItems: "center",
|
|
20025
20397
|
width: 280,
|
|
20026
|
-
background:
|
|
20398
|
+
background: OHW_BLUE,
|
|
20027
20399
|
padding: 8,
|
|
20028
20400
|
borderRadius: 12,
|
|
20029
20401
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -20031,9 +20403,9 @@ function VideoToolbar({
|
|
|
20031
20403
|
opacity: pending ? 0.6 : 1
|
|
20032
20404
|
},
|
|
20033
20405
|
children: [
|
|
20034
|
-
/* @__PURE__ */
|
|
20035
|
-
/* @__PURE__ */
|
|
20036
|
-
error && /* @__PURE__ */
|
|
20406
|
+
/* @__PURE__ */ jsx23(VideoUrlInput, { value: videoId, onCommit: onSetVideoId }),
|
|
20407
|
+
/* @__PURE__ */ jsx23(Pill, { label: "Remove video", onClick: onRemove, disabled: !videoId }),
|
|
20408
|
+
error && /* @__PURE__ */ jsx23("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
20037
20409
|
]
|
|
20038
20410
|
}
|
|
20039
20411
|
);
|
|
@@ -20153,8 +20525,8 @@ function AiVideoOverlay({
|
|
|
20153
20525
|
const activeBlockRect = useLiveBlockRect(active);
|
|
20154
20526
|
const TOOLBAR_APPROX_H = 90;
|
|
20155
20527
|
const toolbarState = activeBlockRect && activeBlockRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
20156
|
-
return /* @__PURE__ */
|
|
20157
|
-
hoverHandleRect && hover && /* @__PURE__ */
|
|
20528
|
+
return /* @__PURE__ */ jsxs14(Fragment9, { children: [
|
|
20529
|
+
hoverHandleRect && hover && /* @__PURE__ */ jsx23(
|
|
20158
20530
|
"button",
|
|
20159
20531
|
{
|
|
20160
20532
|
type: "button",
|
|
@@ -20182,15 +20554,15 @@ function AiVideoOverlay({
|
|
|
20182
20554
|
fontSize: 14,
|
|
20183
20555
|
fontWeight: 700
|
|
20184
20556
|
},
|
|
20185
|
-
children: /* @__PURE__ */
|
|
20557
|
+
children: /* @__PURE__ */ jsx23(Star3, { size: 14, style: { pointerEvents: "none" } })
|
|
20186
20558
|
}
|
|
20187
20559
|
),
|
|
20188
|
-
activeBlockRect && active && activeEntry && /* @__PURE__ */
|
|
20560
|
+
activeBlockRect && active && activeEntry && /* @__PURE__ */ jsx23(
|
|
20189
20561
|
ItemInteractionLayer,
|
|
20190
20562
|
{
|
|
20191
20563
|
rect: activeBlockRect,
|
|
20192
20564
|
state: toolbarState,
|
|
20193
|
-
toolbar: /* @__PURE__ */
|
|
20565
|
+
toolbar: /* @__PURE__ */ jsx23(
|
|
20194
20566
|
VideoToolbar,
|
|
20195
20567
|
{
|
|
20196
20568
|
videoId: videoIdAt(activeEntry.tree, active.path),
|
|
@@ -20265,10 +20637,10 @@ function setCarouselAutoplay(tree, on) {
|
|
|
20265
20637
|
}
|
|
20266
20638
|
|
|
20267
20639
|
// src/ui/ai-section/AiFadeCarouselOverlay.tsx
|
|
20268
|
-
import { Fragment as Fragment10, jsx as
|
|
20640
|
+
import { Fragment as Fragment10, jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
20269
20641
|
var PRIMARY6 = "#0885FE";
|
|
20270
|
-
var
|
|
20271
|
-
var
|
|
20642
|
+
var OHW_BLUE2 = `var(--ohw-primary, ${PRIMARY6})`;
|
|
20643
|
+
var OHW_BLUE_DARK2 = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY6}) 60%, #000000)`;
|
|
20272
20644
|
function findCarouselItemElement(sectionId, index) {
|
|
20273
20645
|
const sectionEl = findByInstanceId(sectionId);
|
|
20274
20646
|
if (!sectionEl) return null;
|
|
@@ -20347,8 +20719,8 @@ function requestAssetPick2(postToParent2) {
|
|
|
20347
20719
|
postToParent2({ type: "ow:asset-pick", id });
|
|
20348
20720
|
});
|
|
20349
20721
|
}
|
|
20350
|
-
function
|
|
20351
|
-
return /* @__PURE__ */
|
|
20722
|
+
function Pill2({ label, onClick, disabled }) {
|
|
20723
|
+
return /* @__PURE__ */ jsx24(
|
|
20352
20724
|
"button",
|
|
20353
20725
|
{
|
|
20354
20726
|
type: "button",
|
|
@@ -20364,7 +20736,7 @@ function Pill3({ label, onClick, disabled }) {
|
|
|
20364
20736
|
border: "none",
|
|
20365
20737
|
cursor: disabled ? "default" : "pointer",
|
|
20366
20738
|
background: "#ffffff",
|
|
20367
|
-
color:
|
|
20739
|
+
color: OHW_BLUE_DARK2,
|
|
20368
20740
|
opacity: disabled ? 0.4 : 1,
|
|
20369
20741
|
fontSize: 12,
|
|
20370
20742
|
lineHeight: "16px",
|
|
@@ -20382,7 +20754,7 @@ function TogglePill({
|
|
|
20382
20754
|
onToggle,
|
|
20383
20755
|
disabled
|
|
20384
20756
|
}) {
|
|
20385
|
-
return /* @__PURE__ */
|
|
20757
|
+
return /* @__PURE__ */ jsxs15(
|
|
20386
20758
|
"button",
|
|
20387
20759
|
{
|
|
20388
20760
|
type: "button",
|
|
@@ -20401,7 +20773,7 @@ function TogglePill({
|
|
|
20401
20773
|
border: "none",
|
|
20402
20774
|
cursor: disabled ? "default" : "pointer",
|
|
20403
20775
|
background: "#ffffff",
|
|
20404
|
-
color:
|
|
20776
|
+
color: OHW_BLUE_DARK2,
|
|
20405
20777
|
opacity: disabled ? 0.4 : 1,
|
|
20406
20778
|
fontSize: 12,
|
|
20407
20779
|
lineHeight: "16px",
|
|
@@ -20411,7 +20783,7 @@ function TogglePill({
|
|
|
20411
20783
|
},
|
|
20412
20784
|
children: [
|
|
20413
20785
|
label,
|
|
20414
|
-
/* @__PURE__ */
|
|
20786
|
+
/* @__PURE__ */ jsx24(
|
|
20415
20787
|
"span",
|
|
20416
20788
|
{
|
|
20417
20789
|
"aria-hidden": true,
|
|
@@ -20424,10 +20796,10 @@ function TogglePill({
|
|
|
20424
20796
|
// Off is a grey track, not a washed-out blue: the pill's own white background already
|
|
20425
20797
|
// carries the brand colour in the text, and a pale blue track next to it read as
|
|
20426
20798
|
// "disabled control" rather than "switch that is off".
|
|
20427
|
-
background: on ?
|
|
20799
|
+
background: on ? OHW_BLUE_DARK2 : "#CBD5E1",
|
|
20428
20800
|
transition: "background 120ms ease"
|
|
20429
20801
|
},
|
|
20430
|
-
children: /* @__PURE__ */
|
|
20802
|
+
children: /* @__PURE__ */ jsx24(
|
|
20431
20803
|
"span",
|
|
20432
20804
|
{
|
|
20433
20805
|
style: {
|
|
@@ -20456,7 +20828,7 @@ function CarouselSlideToolbar({
|
|
|
20456
20828
|
onChangeImage,
|
|
20457
20829
|
onToggleAutoplay
|
|
20458
20830
|
}) {
|
|
20459
|
-
return /* @__PURE__ */
|
|
20831
|
+
return /* @__PURE__ */ jsxs15(
|
|
20460
20832
|
"div",
|
|
20461
20833
|
{
|
|
20462
20834
|
"data-ohw-bridge": "",
|
|
@@ -20467,7 +20839,7 @@ function CarouselSlideToolbar({
|
|
|
20467
20839
|
flexDirection: "column",
|
|
20468
20840
|
gap: 6,
|
|
20469
20841
|
alignItems: "center",
|
|
20470
|
-
background:
|
|
20842
|
+
background: OHW_BLUE2,
|
|
20471
20843
|
padding: 8,
|
|
20472
20844
|
borderRadius: 12,
|
|
20473
20845
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -20479,11 +20851,11 @@ function CarouselSlideToolbar({
|
|
|
20479
20851
|
pointerEvents: pending ? "none" : "auto"
|
|
20480
20852
|
},
|
|
20481
20853
|
children: [
|
|
20482
|
-
/* @__PURE__ */
|
|
20483
|
-
/* @__PURE__ */
|
|
20484
|
-
/* @__PURE__ */
|
|
20854
|
+
/* @__PURE__ */ jsxs15("div", { style: { display: "flex", gap: 6, alignItems: "center" }, children: [
|
|
20855
|
+
/* @__PURE__ */ jsx24(Pill2, { label: "Change Image", onClick: onChangeImage }),
|
|
20856
|
+
/* @__PURE__ */ jsx24(TogglePill, { label: "Autoplay", on: autoplay, onToggle: onToggleAutoplay })
|
|
20485
20857
|
] }),
|
|
20486
|
-
error && /* @__PURE__ */
|
|
20858
|
+
error && /* @__PURE__ */ jsx24("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
20487
20859
|
]
|
|
20488
20860
|
}
|
|
20489
20861
|
);
|
|
@@ -20623,8 +20995,8 @@ function AiFadeCarouselOverlay({
|
|
|
20623
20995
|
const activeItemRect = useLiveItemRect2(active);
|
|
20624
20996
|
const TOOLBAR_APPROX_H = 90;
|
|
20625
20997
|
const toolbarState = activeItemRect && activeItemRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
20626
|
-
return /* @__PURE__ */
|
|
20627
|
-
hoverHandleRect && hover && /* @__PURE__ */
|
|
20998
|
+
return /* @__PURE__ */ jsxs15(Fragment10, { children: [
|
|
20999
|
+
hoverHandleRect && hover && /* @__PURE__ */ jsx24(
|
|
20628
21000
|
"button",
|
|
20629
21001
|
{
|
|
20630
21002
|
type: "button",
|
|
@@ -20653,10 +21025,10 @@ function AiFadeCarouselOverlay({
|
|
|
20653
21025
|
fontSize: 14,
|
|
20654
21026
|
fontWeight: 700
|
|
20655
21027
|
},
|
|
20656
|
-
children: /* @__PURE__ */
|
|
21028
|
+
children: /* @__PURE__ */ jsx24(Star4, { size: 14, style: { pointerEvents: "none" } })
|
|
20657
21029
|
}
|
|
20658
21030
|
),
|
|
20659
|
-
swapping && /* @__PURE__ */
|
|
21031
|
+
swapping && /* @__PURE__ */ jsx24(
|
|
20660
21032
|
"div",
|
|
20661
21033
|
{
|
|
20662
21034
|
ref: skeletonRef,
|
|
@@ -20674,15 +21046,15 @@ function AiFadeCarouselOverlay({
|
|
|
20674
21046
|
zIndex: 2147483646,
|
|
20675
21047
|
pointerEvents: "none"
|
|
20676
21048
|
},
|
|
20677
|
-
children: /* @__PURE__ */
|
|
21049
|
+
children: /* @__PURE__ */ jsx24("style", { children: MEDIA_SKELETON_CSS })
|
|
20678
21050
|
}
|
|
20679
21051
|
),
|
|
20680
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */
|
|
21052
|
+
activeItemRect && active && activeEntry && /* @__PURE__ */ jsx24(
|
|
20681
21053
|
ItemInteractionLayer,
|
|
20682
21054
|
{
|
|
20683
21055
|
rect: activeItemRect,
|
|
20684
21056
|
state: toolbarState,
|
|
20685
|
-
toolbar: /* @__PURE__ */
|
|
21057
|
+
toolbar: /* @__PURE__ */ jsx24(
|
|
20686
21058
|
CarouselSlideToolbar,
|
|
20687
21059
|
{
|
|
20688
21060
|
pending,
|
|
@@ -20900,118 +21272,11 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
|
|
|
20900
21272
|
// src/ui/link-modal/LinkPopover.tsx
|
|
20901
21273
|
import { useEffect as useEffect13 } from "react";
|
|
20902
21274
|
|
|
20903
|
-
// src/ui/dialog.tsx
|
|
20904
|
-
import * as React9 from "react";
|
|
20905
|
-
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
20906
|
-
import { X as X2 } from "lucide-react";
|
|
20907
|
-
import { jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
20908
|
-
function Dialog2({
|
|
20909
|
-
...props
|
|
20910
|
-
}) {
|
|
20911
|
-
return /* @__PURE__ */ jsx24(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
|
|
20912
|
-
}
|
|
20913
|
-
function DialogPortal({
|
|
20914
|
-
...props
|
|
20915
|
-
}) {
|
|
20916
|
-
return /* @__PURE__ */ jsx24(DialogPrimitive.Portal, { ...props });
|
|
20917
|
-
}
|
|
20918
|
-
function DialogOverlay({
|
|
20919
|
-
className,
|
|
20920
|
-
...props
|
|
20921
|
-
}) {
|
|
20922
|
-
return /* @__PURE__ */ jsx24(
|
|
20923
|
-
DialogPrimitive.Overlay,
|
|
20924
|
-
{
|
|
20925
|
-
"data-slot": "dialog-overlay",
|
|
20926
|
-
"data-ohw-link-modal-root": "",
|
|
20927
|
-
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
20928
|
-
...props
|
|
20929
|
-
}
|
|
20930
|
-
);
|
|
20931
|
-
}
|
|
20932
|
-
var DialogContent = React9.forwardRef(
|
|
20933
|
-
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
20934
|
-
const positionMode = container ? "absolute" : "fixed";
|
|
20935
|
-
return /* @__PURE__ */ jsxs15(DialogPortal, { container: container ?? void 0, children: [
|
|
20936
|
-
/* @__PURE__ */ jsx24(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
20937
|
-
/* @__PURE__ */ jsxs15(
|
|
20938
|
-
DialogPrimitive.Content,
|
|
20939
|
-
{
|
|
20940
|
-
ref,
|
|
20941
|
-
"data-slot": "dialog-content",
|
|
20942
|
-
className: cn(
|
|
20943
|
-
positionMode,
|
|
20944
|
-
"left-1/2 top-1/2 z-[2147483647] flex w-full max-w-[448px] -translate-x-1/2 -translate-y-1/2 flex-col overflow-visible",
|
|
20945
|
-
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
20946
|
-
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
20947
|
-
className
|
|
20948
|
-
),
|
|
20949
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
20950
|
-
...props,
|
|
20951
|
-
children: [
|
|
20952
|
-
children,
|
|
20953
|
-
showCloseButton ? /* @__PURE__ */ jsx24(
|
|
20954
|
-
DialogPrimitive.Close,
|
|
20955
|
-
{
|
|
20956
|
-
type: "button",
|
|
20957
|
-
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
20958
|
-
"aria-label": "Close",
|
|
20959
|
-
children: /* @__PURE__ */ jsx24(X2, { size: 16, "aria-hidden": true })
|
|
20960
|
-
}
|
|
20961
|
-
) : null
|
|
20962
|
-
]
|
|
20963
|
-
}
|
|
20964
|
-
)
|
|
20965
|
-
] });
|
|
20966
|
-
}
|
|
20967
|
-
);
|
|
20968
|
-
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
20969
|
-
function DialogHeader({
|
|
20970
|
-
className,
|
|
20971
|
-
...props
|
|
20972
|
-
}) {
|
|
20973
|
-
return /* @__PURE__ */ jsx24("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
20974
|
-
}
|
|
20975
|
-
function DialogFooter({
|
|
20976
|
-
className,
|
|
20977
|
-
...props
|
|
20978
|
-
}) {
|
|
20979
|
-
return /* @__PURE__ */ jsx24(
|
|
20980
|
-
"div",
|
|
20981
|
-
{
|
|
20982
|
-
className: cn("flex items-center justify-end gap-2", className),
|
|
20983
|
-
...props
|
|
20984
|
-
}
|
|
20985
|
-
);
|
|
20986
|
-
}
|
|
20987
|
-
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx24(
|
|
20988
|
-
DialogPrimitive.Title,
|
|
20989
|
-
{
|
|
20990
|
-
ref,
|
|
20991
|
-
className: cn(
|
|
20992
|
-
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
20993
|
-
className
|
|
20994
|
-
),
|
|
20995
|
-
...props
|
|
20996
|
-
}
|
|
20997
|
-
));
|
|
20998
|
-
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
20999
|
-
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx24(
|
|
21000
|
-
DialogPrimitive.Description,
|
|
21001
|
-
{
|
|
21002
|
-
ref,
|
|
21003
|
-
className: cn("text-sm text-muted-foreground", className),
|
|
21004
|
-
...props
|
|
21005
|
-
}
|
|
21006
|
-
));
|
|
21007
|
-
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
21008
|
-
var DialogClose = DialogPrimitive.Close;
|
|
21009
|
-
|
|
21010
21275
|
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
21011
21276
|
import { Info, X as X4 } from "lucide-react";
|
|
21012
21277
|
|
|
21013
21278
|
// src/ui/link-modal/DestinationBreadcrumb.tsx
|
|
21014
|
-
import { ArrowRight as
|
|
21279
|
+
import { ArrowRight as ArrowRight3, File, GalleryVertical } from "lucide-react";
|
|
21015
21280
|
import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
21016
21281
|
function DestinationBreadcrumb({
|
|
21017
21282
|
pageTitle,
|
|
@@ -21025,7 +21290,7 @@ function DestinationBreadcrumb({
|
|
|
21025
21290
|
/* @__PURE__ */ jsx25("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
|
|
21026
21291
|
] }),
|
|
21027
21292
|
/* @__PURE__ */ jsx25(
|
|
21028
|
-
|
|
21293
|
+
ArrowRight3,
|
|
21029
21294
|
{
|
|
21030
21295
|
size: 16,
|
|
21031
21296
|
className: "shrink-0 text-muted-foreground",
|
|
@@ -21137,7 +21402,7 @@ function Label({ className, ...props }) {
|
|
|
21137
21402
|
}
|
|
21138
21403
|
|
|
21139
21404
|
// src/ui/link-modal/UrlOrPageInput.tsx
|
|
21140
|
-
import { ChevronDown as
|
|
21405
|
+
import { ChevronDown as ChevronDown5, File as File2, X as X3 } from "lucide-react";
|
|
21141
21406
|
import { jsx as jsx29, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
21142
21407
|
function FieldChevron({
|
|
21143
21408
|
onClick
|
|
@@ -21150,7 +21415,7 @@ function FieldChevron({
|
|
|
21150
21415
|
onClick,
|
|
21151
21416
|
"aria-label": "Open page list",
|
|
21152
21417
|
tabIndex: -1,
|
|
21153
|
-
children: /* @__PURE__ */ jsx29(
|
|
21418
|
+
children: /* @__PURE__ */ jsx29(ChevronDown5, { size: 16 })
|
|
21154
21419
|
}
|
|
21155
21420
|
);
|
|
21156
21421
|
}
|
|
@@ -21380,7 +21645,7 @@ function LinkEditorPanel({ state, onClose }) {
|
|
|
21380
21645
|
// src/ui/link-modal/SectionPickerOverlay.tsx
|
|
21381
21646
|
import { useCallback as useCallback7, useEffect as useEffect11, useMemo as useMemo2, useRef as useRef10, useState as useState13 } from "react";
|
|
21382
21647
|
import { createPortal as createPortal2 } from "react-dom";
|
|
21383
|
-
import { ArrowLeft as
|
|
21648
|
+
import { ArrowLeft as ArrowLeft3, Check as Check4 } from "lucide-react";
|
|
21384
21649
|
import { usePathname, useRouter as useRouter2 } from "next/navigation";
|
|
21385
21650
|
|
|
21386
21651
|
// src/lib/parent-scroll.ts
|
|
@@ -21657,7 +21922,7 @@ function SectionPickerOverlay({
|
|
|
21657
21922
|
className: "h-8 min-w-0 gap-1 border-border bg-background px-2 py-1.5 shadow-sm hover:bg-muted cursor-pointer",
|
|
21658
21923
|
onClick: onBack,
|
|
21659
21924
|
children: [
|
|
21660
|
-
/* @__PURE__ */ jsx31(
|
|
21925
|
+
/* @__PURE__ */ jsx31(ArrowLeft3, { className: "size-4 shrink-0", "aria-hidden": true }),
|
|
21661
21926
|
"Back"
|
|
21662
21927
|
]
|
|
21663
21928
|
}
|
|
@@ -21726,7 +21991,7 @@ function SectionPickerOverlay({
|
|
|
21726
21991
|
className: "absolute right-3 top-3 flex size-8 items-center justify-center rounded-full text-white",
|
|
21727
21992
|
style: { backgroundColor: "var(--ohw-primary, #0885fe)" },
|
|
21728
21993
|
"aria-hidden": true,
|
|
21729
|
-
children: /* @__PURE__ */ jsx31(
|
|
21994
|
+
children: /* @__PURE__ */ jsx31(Check4, { className: "size-5" })
|
|
21730
21995
|
}
|
|
21731
21996
|
) : null
|
|
21732
21997
|
]
|
|
@@ -22110,6 +22375,7 @@ function shouldUseDevFixtures() {
|
|
|
22110
22375
|
function getLogoElement(el) {
|
|
22111
22376
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
22112
22377
|
if (marked) return marked;
|
|
22378
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
22113
22379
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
22114
22380
|
if (!root) return null;
|
|
22115
22381
|
const anchor = el.closest("a");
|
|
@@ -22179,7 +22445,7 @@ function addFooterColumnWithPersist({
|
|
|
22179
22445
|
import {
|
|
22180
22446
|
useCallback as useCallback9,
|
|
22181
22447
|
useEffect as useEffect14,
|
|
22182
|
-
useLayoutEffect as
|
|
22448
|
+
useLayoutEffect as useLayoutEffect6,
|
|
22183
22449
|
useRef as useRef11,
|
|
22184
22450
|
useState as useState15
|
|
22185
22451
|
} from "react";
|
|
@@ -22276,7 +22542,7 @@ function FloatingPanel({
|
|
|
22276
22542
|
return () => window.removeEventListener("message", onParentScroll);
|
|
22277
22543
|
}, [open]);
|
|
22278
22544
|
const positionRef = useRef11(position);
|
|
22279
|
-
|
|
22545
|
+
useLayoutEffect6(() => {
|
|
22280
22546
|
if (!open) {
|
|
22281
22547
|
positionRef.current = position;
|
|
22282
22548
|
return;
|
|
@@ -22286,7 +22552,7 @@ function FloatingPanel({
|
|
|
22286
22552
|
}
|
|
22287
22553
|
positionRef.current = position;
|
|
22288
22554
|
}, [open, position, liveScroll, parentScroll]);
|
|
22289
|
-
|
|
22555
|
+
useLayoutEffect6(() => {
|
|
22290
22556
|
if (!open || !panelRef.current) return;
|
|
22291
22557
|
const el = panelRef.current;
|
|
22292
22558
|
const header = el.querySelector("[data-ohw-floating-panel-header]");
|
|
@@ -22495,7 +22761,7 @@ function SocialsDisplayPanel({ display, onChange, className }) {
|
|
|
22495
22761
|
}
|
|
22496
22762
|
|
|
22497
22763
|
// src/ui/button-style-panel.tsx
|
|
22498
|
-
import { Check as
|
|
22764
|
+
import { Check as Check5 } from "lucide-react";
|
|
22499
22765
|
import { jsx as jsx35, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
22500
22766
|
var SIZE_LABEL = { s: "S", m: "M", l: "L" };
|
|
22501
22767
|
function ButtonStylePanel({
|
|
@@ -22566,7 +22832,7 @@ function ButtonStylePanel({
|
|
|
22566
22832
|
{
|
|
22567
22833
|
className: "absolute right-0.5 top-0.5 flex size-5 items-center justify-center rounded-full bg-primary text-primary-foreground",
|
|
22568
22834
|
"aria-hidden": true,
|
|
22569
|
-
children: /* @__PURE__ */ jsx35(
|
|
22835
|
+
children: /* @__PURE__ */ jsx35(Check5, { className: "size-3", strokeWidth: 3 })
|
|
22570
22836
|
}
|
|
22571
22837
|
) : null
|
|
22572
22838
|
]
|
|
@@ -23591,7 +23857,7 @@ function useSectionDrag({
|
|
|
23591
23857
|
}
|
|
23592
23858
|
|
|
23593
23859
|
// src/ui/footer-container-chrome.tsx
|
|
23594
|
-
import { Plus as
|
|
23860
|
+
import { Plus as Plus4 } from "lucide-react";
|
|
23595
23861
|
import { jsx as jsx36, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
23596
23862
|
function FooterContainerChrome({
|
|
23597
23863
|
rect,
|
|
@@ -23632,7 +23898,7 @@ function FooterContainerChrome({
|
|
|
23632
23898
|
if (addDisabled) return;
|
|
23633
23899
|
onAdd();
|
|
23634
23900
|
},
|
|
23635
|
-
children: /* @__PURE__ */ jsx36(
|
|
23901
|
+
children: /* @__PURE__ */ jsx36(Plus4, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
23636
23902
|
}
|
|
23637
23903
|
) }),
|
|
23638
23904
|
/* @__PURE__ */ jsx36(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
|
|
@@ -23810,8 +24076,104 @@ function deleteSelectedNavFooterItem(deps) {
|
|
|
23810
24076
|
return false;
|
|
23811
24077
|
}
|
|
23812
24078
|
|
|
24079
|
+
// src/lib/nav-page-sync.ts
|
|
24080
|
+
function labelKeyFor(hrefKey) {
|
|
24081
|
+
return hrefKey.replace(/-href$/, "-label");
|
|
24082
|
+
}
|
|
24083
|
+
function isPageLinkKey(key) {
|
|
24084
|
+
return isNavbarHrefKey(key) || isFooterHrefKey(key);
|
|
24085
|
+
}
|
|
24086
|
+
function currentHref(key, anchor, content) {
|
|
24087
|
+
const stored = content[key];
|
|
24088
|
+
if (typeof stored === "string" && stored.length > 0) return stored;
|
|
24089
|
+
return anchor.getAttribute("href") ?? "";
|
|
24090
|
+
}
|
|
24091
|
+
function normalizePath2(value) {
|
|
24092
|
+
if (value.length > 1 && value.endsWith("/")) return value.slice(0, -1);
|
|
24093
|
+
return value;
|
|
24094
|
+
}
|
|
24095
|
+
function pointsAt(href, path) {
|
|
24096
|
+
const normalized = normalizePath2(href);
|
|
24097
|
+
const target = normalizePath2(path);
|
|
24098
|
+
if (normalized === target) return true;
|
|
24099
|
+
return (normalized.startsWith(`${target}#`) || normalized.startsWith(`${target}?`)) && target !== "/";
|
|
24100
|
+
}
|
|
24101
|
+
function retargetHref(href, oldPath, newPath) {
|
|
24102
|
+
const normalized = normalizePath2(href);
|
|
24103
|
+
const target = normalizePath2(oldPath);
|
|
24104
|
+
if (normalized === target) return newPath;
|
|
24105
|
+
return `${newPath}${normalized.slice(target.length)}`;
|
|
24106
|
+
}
|
|
24107
|
+
function setLabelText(key, text) {
|
|
24108
|
+
document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`).forEach((el) => {
|
|
24109
|
+
el.textContent = text;
|
|
24110
|
+
});
|
|
24111
|
+
}
|
|
24112
|
+
function commit(delta, deps) {
|
|
24113
|
+
if (Object.keys(delta).length === 0) return;
|
|
24114
|
+
deps.setEditContent({ ...deps.getEditContent(), ...delta });
|
|
24115
|
+
deps.postToParent({
|
|
24116
|
+
type: "ow:change",
|
|
24117
|
+
nodes: Object.entries(delta).map(([key, text]) => ({ key, text }))
|
|
24118
|
+
});
|
|
24119
|
+
}
|
|
24120
|
+
function navLinksTo(path, content) {
|
|
24121
|
+
return Array.from(document.querySelectorAll("[data-ohw-href-key]")).filter((anchor) => {
|
|
24122
|
+
const key = anchor.getAttribute("data-ohw-href-key");
|
|
24123
|
+
return isNavbarHrefKey(key) && pointsAt(currentHref(key, anchor, content), path);
|
|
24124
|
+
}).map((anchor) => anchor.getAttribute("data-ohw-href-key"));
|
|
24125
|
+
}
|
|
24126
|
+
function addNavLinkForPage(page, deps) {
|
|
24127
|
+
const content = deps.getEditContent();
|
|
24128
|
+
if (navLinksTo(page.path, content).length > 0) return false;
|
|
24129
|
+
const roots = listNavbarRootItems();
|
|
24130
|
+
const afterAnchor = roots[roots.length - 1] ?? null;
|
|
24131
|
+
let inserted;
|
|
24132
|
+
try {
|
|
24133
|
+
inserted = insertNavbarItem(page.path, page.title, afterAnchor);
|
|
24134
|
+
} catch {
|
|
24135
|
+
return false;
|
|
24136
|
+
}
|
|
24137
|
+
const { hrefKey, labelKey, index } = inserted;
|
|
24138
|
+
deps.applyLinkByKey(hrefKey, page.path);
|
|
24139
|
+
setLabelText(labelKey, page.title);
|
|
24140
|
+
commit(
|
|
24141
|
+
{
|
|
24142
|
+
[hrefKey]: page.path,
|
|
24143
|
+
[labelKey]: page.title,
|
|
24144
|
+
[NAV_COUNT_KEY]: String(index + 1),
|
|
24145
|
+
[NAV_ORDER_KEY]: getNavbarOrderJson()
|
|
24146
|
+
},
|
|
24147
|
+
deps
|
|
24148
|
+
);
|
|
24149
|
+
return true;
|
|
24150
|
+
}
|
|
24151
|
+
function retargetPageLinks(change, deps) {
|
|
24152
|
+
const { oldPath, newPath, oldTitle, newTitle } = change;
|
|
24153
|
+
if (!oldPath || !newPath || normalizePath2(oldPath) === normalizePath2(newPath)) return 0;
|
|
24154
|
+
const content = deps.getEditContent();
|
|
24155
|
+
const delta = {};
|
|
24156
|
+
for (const anchor of Array.from(document.querySelectorAll("[data-ohw-href-key]"))) {
|
|
24157
|
+
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
24158
|
+
if (!isPageLinkKey(hrefKey)) continue;
|
|
24159
|
+
const href = currentHref(hrefKey, anchor, content);
|
|
24160
|
+
if (!pointsAt(href, oldPath)) continue;
|
|
24161
|
+
const nextHref = retargetHref(href, oldPath, newPath);
|
|
24162
|
+
deps.applyLinkByKey(hrefKey, nextHref);
|
|
24163
|
+
delta[hrefKey] = nextHref;
|
|
24164
|
+
if (!oldTitle || !newTitle) continue;
|
|
24165
|
+
const labelKey = labelKeyFor(hrefKey);
|
|
24166
|
+
const label = content[labelKey] ?? anchor.querySelector('[data-ohw-editable="text"]')?.textContent ?? "";
|
|
24167
|
+
if (label.trim() !== oldTitle) continue;
|
|
24168
|
+
setLabelText(labelKey, newTitle);
|
|
24169
|
+
delta[labelKey] = newTitle;
|
|
24170
|
+
}
|
|
24171
|
+
commit(delta, deps);
|
|
24172
|
+
return Object.keys(delta).filter((key) => key.endsWith("-href")).length;
|
|
24173
|
+
}
|
|
24174
|
+
|
|
23813
24175
|
// src/ui/navbar-container-chrome.tsx
|
|
23814
|
-
import { Plus as
|
|
24176
|
+
import { Plus as Plus5 } from "lucide-react";
|
|
23815
24177
|
import { jsx as jsx37 } from "react/jsx-runtime";
|
|
23816
24178
|
function NavbarContainerChrome({
|
|
23817
24179
|
rect,
|
|
@@ -23847,7 +24209,7 @@ function NavbarContainerChrome({
|
|
|
23847
24209
|
e.stopPropagation();
|
|
23848
24210
|
onAdd();
|
|
23849
24211
|
},
|
|
23850
|
-
children: /* @__PURE__ */ jsx37(
|
|
24212
|
+
children: /* @__PURE__ */ jsx37(Plus5, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
23851
24213
|
}
|
|
23852
24214
|
)
|
|
23853
24215
|
}
|
|
@@ -23919,7 +24281,7 @@ function Badge({ className, variant, ...props }) {
|
|
|
23919
24281
|
}
|
|
23920
24282
|
|
|
23921
24283
|
// src/OhhwellsBridge.tsx
|
|
23922
|
-
import { Brush as Brush2, Link as Link2, Plus as
|
|
24284
|
+
import { Brush as Brush2, Link as Link2, Plus as Plus6, Settings } from "lucide-react";
|
|
23923
24285
|
import { Fragment as Fragment13, jsx as jsx40, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
23924
24286
|
var PRIMARY7 = "#0885FE";
|
|
23925
24287
|
var IMAGE_FADE_MS = 300;
|
|
@@ -24697,7 +25059,7 @@ function getNavigationSelectionParent(el) {
|
|
|
24697
25059
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
24698
25060
|
return resolveFooterLinksContainerFrom(el);
|
|
24699
25061
|
}
|
|
24700
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
25062
|
+
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)) {
|
|
24701
25063
|
return getNavigationRoot(el);
|
|
24702
25064
|
}
|
|
24703
25065
|
return null;
|
|
@@ -24919,7 +25281,6 @@ var ICONS = {
|
|
|
24919
25281
|
insertUnorderedList: '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>',
|
|
24920
25282
|
insertOrderedList: '<line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/>'
|
|
24921
25283
|
};
|
|
24922
|
-
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
24923
25284
|
var SELECTION_CHROME_GAP2 = 4;
|
|
24924
25285
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
24925
25286
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -25017,7 +25378,7 @@ function applyVisibleViewport(el, parentScroll) {
|
|
|
25017
25378
|
el.style.top = `${top}px`;
|
|
25018
25379
|
el.style.height = `${height}px`;
|
|
25019
25380
|
}
|
|
25020
|
-
var
|
|
25381
|
+
var TOOLBAR_EDGE_MARGIN4 = 4;
|
|
25021
25382
|
function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
25022
25383
|
const isAbove = transform.includes("translateY(-100%)");
|
|
25023
25384
|
let visualTop = isAbove ? top - approxH : top;
|
|
@@ -25044,8 +25405,8 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
|
25044
25405
|
function clampToolbarLeft(centerX, toolbarWidth) {
|
|
25045
25406
|
const half = toolbarWidth / 2;
|
|
25046
25407
|
return Math.max(
|
|
25047
|
-
|
|
25048
|
-
Math.min(centerX, window.innerWidth -
|
|
25408
|
+
TOOLBAR_EDGE_MARGIN4 + half,
|
|
25409
|
+
Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN4 - half)
|
|
25049
25410
|
);
|
|
25050
25411
|
}
|
|
25051
25412
|
function calcToolbarPos(rect, parentScroll, toolbarW = 306) {
|
|
@@ -25446,7 +25807,7 @@ function OhhwellsBridge() {
|
|
|
25446
25807
|
}, []);
|
|
25447
25808
|
const subdomainFromQuery = searchParams.get("subdomain");
|
|
25448
25809
|
const [subdomain, setSubdomain] = useState18(() => resolveSubdomain(subdomainFromQuery));
|
|
25449
|
-
|
|
25810
|
+
useLayoutEffect7(() => {
|
|
25450
25811
|
const next = resolveSubdomain(subdomainFromQuery);
|
|
25451
25812
|
if (next !== subdomain) setSubdomain(next);
|
|
25452
25813
|
if (next) return;
|
|
@@ -25925,21 +26286,6 @@ function OhhwellsBridge() {
|
|
|
25925
26286
|
const [isItemDragging, setIsItemDragging] = useState18(false);
|
|
25926
26287
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = useState18(false);
|
|
25927
26288
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
25928
|
-
const [floatingPanel, setFloatingPanel] = useState18(null);
|
|
25929
|
-
const floatingPanelOpenRef = useRef14(false);
|
|
25930
|
-
floatingPanelOpenRef.current = floatingPanel !== null;
|
|
25931
|
-
const floatingPanelRef = useRef14(null);
|
|
25932
|
-
floatingPanelRef.current = floatingPanel;
|
|
25933
|
-
const [floatingPanelPos, setFloatingPanelPos] = useState18(null);
|
|
25934
|
-
const buttonCollectionDragRef = useRef14(null);
|
|
25935
|
-
const buttonDropInsertIndexRef = useRef14(null);
|
|
25936
|
-
const [buttonDropSlots, setButtonDropSlots] = useState18([]);
|
|
25937
|
-
const [activeButtonDropIndex, setActiveButtonDropIndex] = useState18(null);
|
|
25938
|
-
const buttonPointerDragRef = useRef14(null);
|
|
25939
|
-
const [buttonStyleTick, setButtonStyleTick] = useState18(0);
|
|
25940
|
-
const [logoSizeDraft, setLogoSizeDraft] = useState18(null);
|
|
25941
|
-
const [editorViewport, setEditorViewport] = useState18("desktop");
|
|
25942
|
-
const [parentScrollSnap, setParentScrollSnap] = useState18(null);
|
|
25943
26289
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = useState18(null);
|
|
25944
26290
|
const [footerHeadingVisible, setFooterHeadingVisible] = useState18(null);
|
|
25945
26291
|
const footerDragRef = useRef14(null);
|
|
@@ -25965,6 +26311,21 @@ function OhhwellsBridge() {
|
|
|
25965
26311
|
const stylesRef = useRef14("");
|
|
25966
26312
|
const appliedDrawerRef = useRef14(null);
|
|
25967
26313
|
const pendingDeleteUndoRef = useRef14(null);
|
|
26314
|
+
const [floatingPanel, setFloatingPanel] = useState18(null);
|
|
26315
|
+
const floatingPanelOpenRef = useRef14(false);
|
|
26316
|
+
const floatingPanelRef = useRef14(null);
|
|
26317
|
+
floatingPanelRef.current = floatingPanel;
|
|
26318
|
+
const setFloatingPanelRef = useRef14(setFloatingPanel);
|
|
26319
|
+
const [floatingPanelPos, setFloatingPanelPos] = useState18(null);
|
|
26320
|
+
const buttonCollectionDragRef = useRef14(null);
|
|
26321
|
+
const buttonDropInsertIndexRef = useRef14(null);
|
|
26322
|
+
const [buttonDropSlots, setButtonDropSlots] = useState18([]);
|
|
26323
|
+
const [activeButtonDropIndex, setActiveButtonDropIndex] = useState18(null);
|
|
26324
|
+
const buttonPointerDragRef = useRef14(null);
|
|
26325
|
+
const [buttonStyleTick, setButtonStyleTick] = useState18(0);
|
|
26326
|
+
const [logoSizeDraft, setLogoSizeDraft] = useState18(null);
|
|
26327
|
+
const [editorViewport, setEditorViewport] = useState18("desktop");
|
|
26328
|
+
const [parentScrollSnap, setParentScrollSnap] = useState18(null);
|
|
25968
26329
|
const [sitePages, setSitePages] = useState18([]);
|
|
25969
26330
|
const collectionItemsRef = useRef14(/* @__PURE__ */ new Map());
|
|
25970
26331
|
const [sectionsByPath, setSectionsByPath] = useState18({});
|
|
@@ -25974,7 +26335,18 @@ function OhhwellsBridge() {
|
|
|
25974
26335
|
const linkPopoverOpenRef = useRef14(false);
|
|
25975
26336
|
const linkPopoverGraceUntilRef = useRef14(0);
|
|
25976
26337
|
setLinkPopoverRef.current = setLinkPopover;
|
|
26338
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
25977
26339
|
linkPopoverSessionRef.current = linkPopover;
|
|
26340
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
26341
|
+
useEffect17(() => {
|
|
26342
|
+
const syncViewport = () => {
|
|
26343
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
26344
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
26345
|
+
};
|
|
26346
|
+
syncViewport();
|
|
26347
|
+
window.addEventListener("resize", syncViewport);
|
|
26348
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
26349
|
+
}, []);
|
|
25978
26350
|
useEffect17(() => {
|
|
25979
26351
|
setSectionOrderPersistHandler((entries) => {
|
|
25980
26352
|
const currentPath = window.location.pathname;
|
|
@@ -26123,6 +26495,43 @@ function OhhwellsBridge() {
|
|
|
26123
26495
|
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
26124
26496
|
return () => window.removeEventListener("message", onSitePages);
|
|
26125
26497
|
}, [isEditMode, postToParent2]);
|
|
26498
|
+
useEffect17(() => {
|
|
26499
|
+
if (!isEditMode) return;
|
|
26500
|
+
const deps = {
|
|
26501
|
+
getEditContent: () => editContentRef.current,
|
|
26502
|
+
setEditContent: (next) => {
|
|
26503
|
+
editContentRef.current = next;
|
|
26504
|
+
},
|
|
26505
|
+
applyLinkByKey,
|
|
26506
|
+
postToParent: postToParent2
|
|
26507
|
+
};
|
|
26508
|
+
const onPageMessage = (e) => {
|
|
26509
|
+
if (e.data?.type === "ow:page-created") {
|
|
26510
|
+
const { path, title } = e.data;
|
|
26511
|
+
if (typeof path !== "string" || !path) return;
|
|
26512
|
+
if (addNavLinkForPage({ path, title: typeof title === "string" && title ? title : path }, deps)) {
|
|
26513
|
+
enforceLinkHrefs();
|
|
26514
|
+
}
|
|
26515
|
+
return;
|
|
26516
|
+
}
|
|
26517
|
+
if (e.data?.type === "ow:page-renamed") {
|
|
26518
|
+
const { oldPath, newPath, oldTitle, newTitle } = e.data;
|
|
26519
|
+
if (typeof oldPath !== "string" || typeof newPath !== "string") return;
|
|
26520
|
+
const moved = retargetPageLinks(
|
|
26521
|
+
{
|
|
26522
|
+
oldPath,
|
|
26523
|
+
newPath,
|
|
26524
|
+
oldTitle: typeof oldTitle === "string" ? oldTitle : void 0,
|
|
26525
|
+
newTitle: typeof newTitle === "string" ? newTitle : void 0
|
|
26526
|
+
},
|
|
26527
|
+
deps
|
|
26528
|
+
);
|
|
26529
|
+
if (moved > 0) enforceLinkHrefs();
|
|
26530
|
+
}
|
|
26531
|
+
};
|
|
26532
|
+
window.addEventListener("message", onPageMessage);
|
|
26533
|
+
return () => window.removeEventListener("message", onPageMessage);
|
|
26534
|
+
}, [isEditMode, postToParent2]);
|
|
26126
26535
|
useEffect17(() => {
|
|
26127
26536
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
26128
26537
|
void loadAllSectionsManifest().then((manifest) => {
|
|
@@ -27644,7 +28053,7 @@ function OhhwellsBridge() {
|
|
|
27644
28053
|
isFooterFrameSelection,
|
|
27645
28054
|
postToParent2
|
|
27646
28055
|
]);
|
|
27647
|
-
|
|
28056
|
+
useLayoutEffect7(() => {
|
|
27648
28057
|
if (!subdomain || isEditMode) {
|
|
27649
28058
|
setFetchState("done");
|
|
27650
28059
|
return;
|
|
@@ -27671,6 +28080,7 @@ function OhhwellsBridge() {
|
|
|
27671
28080
|
applyAiFooterFromContent(content);
|
|
27672
28081
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
27673
28082
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
28083
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
27674
28084
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
27675
28085
|
}
|
|
27676
28086
|
applyBrandChrome(content);
|
|
@@ -27681,12 +28091,12 @@ function OhhwellsBridge() {
|
|
|
27681
28091
|
if (key === "__ohw_sections") continue;
|
|
27682
28092
|
if (key === AI_SECTIONS_KEY) continue;
|
|
27683
28093
|
if (key === AI_FOOTER_KEY) continue;
|
|
28094
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28095
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27684
28096
|
if (key === BRAND_KIT_KEY) continue;
|
|
27685
28097
|
if (key === STYLE_STORE_KEY) continue;
|
|
27686
28098
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
27687
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27688
28099
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
27689
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27690
28100
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
27691
28101
|
continue;
|
|
27692
28102
|
}
|
|
@@ -27917,17 +28327,18 @@ function OhhwellsBridge() {
|
|
|
27917
28327
|
}
|
|
27918
28328
|
applyAiFooterFromContent(content);
|
|
27919
28329
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
28330
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
27920
28331
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
27921
28332
|
}
|
|
27922
28333
|
for (const [key, val] of Object.entries(content)) {
|
|
27923
28334
|
if (key === "__ohw_sections") continue;
|
|
27924
28335
|
if (key === AI_SECTIONS_KEY) continue;
|
|
27925
28336
|
if (key === AI_FOOTER_KEY) continue;
|
|
28337
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28338
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27926
28339
|
if (key === BRAND_KIT_KEY) continue;
|
|
27927
28340
|
if (key === STYLE_STORE_KEY) continue;
|
|
27928
28341
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
27929
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27930
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27931
28342
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
27932
28343
|
continue;
|
|
27933
28344
|
}
|
|
@@ -28010,7 +28421,7 @@ function OhhwellsBridge() {
|
|
|
28010
28421
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
28011
28422
|
};
|
|
28012
28423
|
}, [subdomain, isEditMode, pathname]);
|
|
28013
|
-
|
|
28424
|
+
useLayoutEffect7(() => {
|
|
28014
28425
|
const el = document.getElementById("ohw-loader");
|
|
28015
28426
|
if (!el) return;
|
|
28016
28427
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
@@ -28194,26 +28605,11 @@ function OhhwellsBridge() {
|
|
|
28194
28605
|
const t2 = setTimeout(measure, 500);
|
|
28195
28606
|
const ro = new ResizeObserver(schedule);
|
|
28196
28607
|
ro.observe(document.body);
|
|
28197
|
-
let lastWidth = window.innerWidth;
|
|
28198
|
-
let resizeTimers = [];
|
|
28199
|
-
const clearResizeTimers = () => {
|
|
28200
|
-
resizeTimers.forEach(clearTimeout);
|
|
28201
|
-
resizeTimers = [];
|
|
28202
|
-
};
|
|
28203
|
-
const handleResize = () => {
|
|
28204
|
-
if (window.innerWidth === lastWidth) return;
|
|
28205
|
-
lastWidth = window.innerWidth;
|
|
28206
|
-
clearResizeTimers();
|
|
28207
|
-
resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
|
|
28208
|
-
};
|
|
28209
|
-
window.addEventListener("resize", handleResize);
|
|
28210
28608
|
return () => {
|
|
28211
28609
|
clearTimeout(t1);
|
|
28212
28610
|
clearTimeout(t2);
|
|
28213
28611
|
if (raf != null) cancelAnimationFrame(raf);
|
|
28214
28612
|
ro.disconnect();
|
|
28215
|
-
clearResizeTimers();
|
|
28216
|
-
window.removeEventListener("resize", handleResize);
|
|
28217
28613
|
};
|
|
28218
28614
|
}, [pathname, isEditMode, postToParent2]);
|
|
28219
28615
|
useEffect17(() => {
|
|
@@ -28510,6 +28906,13 @@ function OhhwellsBridge() {
|
|
|
28510
28906
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
28511
28907
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
28512
28908
|
if (isInsideLinkEditor(target)) return;
|
|
28909
|
+
if (isInsideFloatingPanel(target)) return;
|
|
28910
|
+
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
28911
|
+
if (target.closest(
|
|
28912
|
+
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
28913
|
+
)) {
|
|
28914
|
+
return;
|
|
28915
|
+
}
|
|
28513
28916
|
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
28514
28917
|
clearMediaSelectionRef.current();
|
|
28515
28918
|
}
|
|
@@ -28533,8 +28936,6 @@ function OhhwellsBridge() {
|
|
|
28533
28936
|
return;
|
|
28534
28937
|
}
|
|
28535
28938
|
}
|
|
28536
|
-
if (isInsideFloatingPanel(target)) return;
|
|
28537
|
-
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
28538
28939
|
const collectionItem = matchCollectionItemClick(target, collectionItemsRef.current);
|
|
28539
28940
|
if (collectionItem) {
|
|
28540
28941
|
e.preventDefault();
|
|
@@ -28546,11 +28947,6 @@ function OhhwellsBridge() {
|
|
|
28546
28947
|
});
|
|
28547
28948
|
return;
|
|
28548
28949
|
}
|
|
28549
|
-
if (target.closest(
|
|
28550
|
-
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
28551
|
-
)) {
|
|
28552
|
-
return;
|
|
28553
|
-
}
|
|
28554
28950
|
{
|
|
28555
28951
|
const formEl = getFormElement(target);
|
|
28556
28952
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -28704,9 +29100,13 @@ function OhhwellsBridge() {
|
|
|
28704
29100
|
if (isIconEditable(editable) && !getSocialItem(editable)) {
|
|
28705
29101
|
e.preventDefault();
|
|
28706
29102
|
e.stopPropagation();
|
|
28707
|
-
selectIconElementRef.current(editable);
|
|
28708
29103
|
const aiIcon = editable.hasAttribute("data-ai-icon");
|
|
28709
29104
|
const featureIcon = aiIcon && /\.features\.\d+\.icon$/.test(editable.dataset.ohwKey ?? "");
|
|
29105
|
+
if (aiIcon) {
|
|
29106
|
+
aiSectionApiRef.current?.selectFromElement(editable);
|
|
29107
|
+
} else {
|
|
29108
|
+
selectIconElementRef.current(editable);
|
|
29109
|
+
}
|
|
28710
29110
|
postToParentRef.current({
|
|
28711
29111
|
type: "ow:icon-pick",
|
|
28712
29112
|
key: editable.dataset.ohwKey ?? "",
|
|
@@ -28934,6 +29334,9 @@ function OhhwellsBridge() {
|
|
|
28934
29334
|
setHoveredItemRect(null);
|
|
28935
29335
|
hoveredNavContainerRef.current = null;
|
|
28936
29336
|
setHoveredNavContainerRect(null);
|
|
29337
|
+
siblingHintElRef.current = null;
|
|
29338
|
+
setSiblingHintRect(null);
|
|
29339
|
+
setSiblingHintRects([]);
|
|
28937
29340
|
return;
|
|
28938
29341
|
}
|
|
28939
29342
|
{
|
|
@@ -29054,7 +29457,6 @@ function OhhwellsBridge() {
|
|
|
29054
29457
|
hoveredNavContainerRef.current = null;
|
|
29055
29458
|
setHoveredNavContainerRect(null);
|
|
29056
29459
|
hoveredItemElRef.current = editable;
|
|
29057
|
-
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
29058
29460
|
}
|
|
29059
29461
|
}
|
|
29060
29462
|
}
|
|
@@ -29764,7 +30166,11 @@ function OhhwellsBridge() {
|
|
|
29764
30166
|
};
|
|
29765
30167
|
const handleMouseMove = (e) => {
|
|
29766
30168
|
const { clientX, clientY } = e;
|
|
29767
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
30169
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
30170
|
+
dismissImageHover();
|
|
30171
|
+
clearImageHover();
|
|
30172
|
+
return;
|
|
30173
|
+
}
|
|
29768
30174
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) {
|
|
29769
30175
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
29770
30176
|
formHoverElRef.current = null;
|
|
@@ -29793,7 +30199,12 @@ function OhhwellsBridge() {
|
|
|
29793
30199
|
setHoveredItemRect(null);
|
|
29794
30200
|
hoveredNavContainerRef.current = null;
|
|
29795
30201
|
setHoveredNavContainerRect(null);
|
|
30202
|
+
siblingHintElRef.current = null;
|
|
30203
|
+
setSiblingHintRect(null);
|
|
30204
|
+
setSiblingHintRects([]);
|
|
29796
30205
|
dismissImageHover();
|
|
30206
|
+
clearImageHover();
|
|
30207
|
+
setSectionGap(null);
|
|
29797
30208
|
return;
|
|
29798
30209
|
}
|
|
29799
30210
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -29805,7 +30216,11 @@ function OhhwellsBridge() {
|
|
|
29805
30216
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
29806
30217
|
const { clientX, clientY } = e.data;
|
|
29807
30218
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
29808
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
30219
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
30220
|
+
dismissImageHover();
|
|
30221
|
+
clearImageHover();
|
|
30222
|
+
return;
|
|
30223
|
+
}
|
|
29809
30224
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) return;
|
|
29810
30225
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
29811
30226
|
probeSectionGapAt(clientX, clientY);
|
|
@@ -30185,6 +30600,7 @@ function OhhwellsBridge() {
|
|
|
30185
30600
|
applyAiFooterFromContent(content);
|
|
30186
30601
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
30187
30602
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
30603
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
30188
30604
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
30189
30605
|
}
|
|
30190
30606
|
applyBrandChrome(content);
|
|
@@ -30199,12 +30615,12 @@ function OhhwellsBridge() {
|
|
|
30199
30615
|
}
|
|
30200
30616
|
if (key === AI_SECTIONS_KEY) continue;
|
|
30201
30617
|
if (key === AI_FOOTER_KEY) continue;
|
|
30618
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
30619
|
+
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
30202
30620
|
if (key === BRAND_KIT_KEY) continue;
|
|
30203
30621
|
if (key === STYLE_STORE_KEY) continue;
|
|
30204
30622
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
30205
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
30206
30623
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
30207
|
-
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
30208
30624
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
30209
30625
|
continue;
|
|
30210
30626
|
}
|
|
@@ -30840,6 +31256,12 @@ function OhhwellsBridge() {
|
|
|
30840
31256
|
closeLinkPopoverRef.current();
|
|
30841
31257
|
return;
|
|
30842
31258
|
}
|
|
31259
|
+
if (floatingPanelOpenRef.current) {
|
|
31260
|
+
setFloatingPanelRef.current(null);
|
|
31261
|
+
deselectRef.current();
|
|
31262
|
+
deactivateRef.current();
|
|
31263
|
+
return;
|
|
31264
|
+
}
|
|
30843
31265
|
deselectRef.current();
|
|
30844
31266
|
deactivateRef.current();
|
|
30845
31267
|
clearMediaSelectionRef.current();
|
|
@@ -31220,13 +31642,15 @@ function OhhwellsBridge() {
|
|
|
31220
31642
|
if (e.data?.type !== "ow:collect-section") return;
|
|
31221
31643
|
const sectionId = e.data.sectionId;
|
|
31222
31644
|
if (typeof sectionId !== "string" || !sectionId) return;
|
|
31223
|
-
const
|
|
31224
|
-
|
|
31645
|
+
const escapedSectionId = CSS.escape(sectionId);
|
|
31646
|
+
const instanceEl = document.querySelector(
|
|
31647
|
+
`[data-ohw-instance="${escapedSectionId}"]`
|
|
31225
31648
|
);
|
|
31649
|
+
const foundEl = instanceEl ? sectionElementOf(instanceEl) : document.querySelector(`[data-ohw-section="${escapedSectionId}"]`);
|
|
31226
31650
|
const sectionEl = foundEl && !foundEl.hasAttribute("data-ohw-ai-template-hidden") && !foundEl.hasAttribute("data-ohw-ai-removed") && !foundEl.hasAttribute("data-ohw-ai-replaced-by") ? foundEl : null;
|
|
31227
31651
|
const nodes = sectionEl ? collectEditableNodes(void 0, sectionEl).filter(
|
|
31228
31652
|
(n) => n.key && !n.key.startsWith("__ohw_") && !["meta", "sections", "video-setting"].includes(n.type)
|
|
31229
|
-
).map((n) => ({ ...n, text: n.text ?? "", type: normalizeAiNodeType(n.type) })) : [];
|
|
31653
|
+
).map((n) => ({ ...n, text: n.text ?? "", type: normalizeAiNodeType(n.type) })).map((n) => withNodeFontSize(n, sectionEl)) : [];
|
|
31230
31654
|
const items = sectionEl ? collectItemGroups(sectionEl) : [];
|
|
31231
31655
|
const box = sectionEl?.getBoundingClientRect();
|
|
31232
31656
|
const rect = box ? {
|
|
@@ -31235,7 +31659,11 @@ function OhhwellsBridge() {
|
|
|
31235
31659
|
width: box.width,
|
|
31236
31660
|
height: box.height
|
|
31237
31661
|
} : null;
|
|
31238
|
-
const settings = resolveSectionSettingsContext(
|
|
31662
|
+
const settings = resolveSectionSettingsContext(
|
|
31663
|
+
sectionId,
|
|
31664
|
+
aiSectionsRef.current,
|
|
31665
|
+
stylesRef.current
|
|
31666
|
+
);
|
|
31239
31667
|
const tree = resolveSectionTree(sectionId, aiSectionsRef.current);
|
|
31240
31668
|
postToParentRef.current({
|
|
31241
31669
|
type: "ow:section-nodes",
|
|
@@ -31669,10 +32097,10 @@ function OhhwellsBridge() {
|
|
|
31669
32097
|
window.removeEventListener("message", handleDuplicateSection);
|
|
31670
32098
|
window.removeEventListener("message", handleDeactivate);
|
|
31671
32099
|
window.removeEventListener("message", handleSelectNav);
|
|
31672
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31673
32100
|
window.removeEventListener("message", handleToastAction);
|
|
31674
32101
|
window.removeEventListener("message", handleFormCount);
|
|
31675
32102
|
window.removeEventListener("message", handleUiEscape);
|
|
32103
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31676
32104
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
31677
32105
|
autoSaveTimers.current.clear();
|
|
31678
32106
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -31966,7 +32394,7 @@ function OhhwellsBridge() {
|
|
|
31966
32394
|
postToParent2({
|
|
31967
32395
|
type: "ow:ready",
|
|
31968
32396
|
version: "1",
|
|
31969
|
-
bridgeVersion: "0.1.
|
|
32397
|
+
bridgeVersion: "0.1.160-next.427",
|
|
31970
32398
|
path: pathname,
|
|
31971
32399
|
nodes: collectEditableNodes(editContentRef.current),
|
|
31972
32400
|
sections
|
|
@@ -32701,7 +33129,7 @@ function OhhwellsBridge() {
|
|
|
32701
33129
|
className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
|
|
32702
33130
|
onClick: () => setFieldTypePickerOpen((open) => !open),
|
|
32703
33131
|
"data-ohw-add-field": "",
|
|
32704
|
-
children: /* @__PURE__ */ jsx40(
|
|
33132
|
+
children: /* @__PURE__ */ jsx40(Plus6, { size: 15, "aria-hidden": true })
|
|
32705
33133
|
}
|
|
32706
33134
|
),
|
|
32707
33135
|
/* @__PURE__ */ jsx40("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|