@ohhwells/bridge 0.1.121 → 0.1.122
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2411 -402
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +2407 -398
- package/dist/index.js.map +1 -1
- package/dist/styles.css +79 -8
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -598,9 +598,9 @@ function styleSheetCss() {
|
|
|
598
598
|
);
|
|
599
599
|
}
|
|
600
600
|
const pad = { tight: 40, balanced: 64, airy: 96 };
|
|
601
|
-
for (const [spacing,
|
|
601
|
+
for (const [spacing, px2] of Object.entries(pad)) {
|
|
602
602
|
rules.push(
|
|
603
|
-
`[data-ohw-style-spacing="${spacing}"] { padding-top: ${
|
|
603
|
+
`[data-ohw-style-spacing="${spacing}"] { padding-top: ${px2}px !important; padding-bottom: ${px2}px !important; }`
|
|
604
604
|
);
|
|
605
605
|
}
|
|
606
606
|
rules.push(
|
|
@@ -3167,12 +3167,12 @@ function deriveTemplateButtonStyle() {
|
|
|
3167
3167
|
cs.borderBottomLeftRadius
|
|
3168
3168
|
].map((v) => v || "0px");
|
|
3169
3169
|
const radius = corners.every((v) => v === corners[0]) ? corners[0] : corners.join(" ");
|
|
3170
|
-
const
|
|
3171
|
-
const lineHeight =
|
|
3172
|
-
const contentH = btn.getBoundingClientRect().height -
|
|
3170
|
+
const px2 = (v) => parseFloat(v) || 0;
|
|
3171
|
+
const lineHeight = px2(cs.lineHeight) || px2(cs.fontSize) * 1.2;
|
|
3172
|
+
const contentH = btn.getBoundingClientRect().height - px2(cs.borderTopWidth) - px2(cs.borderBottomWidth);
|
|
3173
3173
|
const impliedY = Math.round(Math.max(0, (contentH - lineHeight) / 2));
|
|
3174
|
-
const padY = Math.max(
|
|
3175
|
-
const padX = Math.max(
|
|
3174
|
+
const padY = Math.max(px2(cs.paddingTop), px2(cs.paddingBottom), impliedY);
|
|
3175
|
+
const padX = Math.max(px2(cs.paddingLeft), px2(cs.paddingRight));
|
|
3176
3176
|
return {
|
|
3177
3177
|
radius: radius || "10px",
|
|
3178
3178
|
padding: `${padY}px ${padX}px`,
|
|
@@ -8089,6 +8089,14 @@ function ItemActionToolbar({
|
|
|
8089
8089
|
e.preventDefault();
|
|
8090
8090
|
e.stopPropagation();
|
|
8091
8091
|
onStyle?.();
|
|
8092
|
+
},
|
|
8093
|
+
// Same as Edit link: mousedown opens the panel and remounts this toolbar
|
|
8094
|
+
// (styleActive flips). Without stopping click, the gesture lands on whatever
|
|
8095
|
+
// is now under the cursor — navbar CTAs park the toolbar below the button, so
|
|
8096
|
+
// that miss deselects and the panel closes as soon as it opens.
|
|
8097
|
+
onClick: (e) => {
|
|
8098
|
+
e.preventDefault();
|
|
8099
|
+
e.stopPropagation();
|
|
8092
8100
|
}
|
|
8093
8101
|
},
|
|
8094
8102
|
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.Brush, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
@@ -8411,20 +8419,32 @@ function ItemInteractionLayer({
|
|
|
8411
8419
|
itemDragSurface = true,
|
|
8412
8420
|
chromeGap,
|
|
8413
8421
|
toolbarAlign = "center",
|
|
8422
|
+
hidden = false,
|
|
8414
8423
|
className
|
|
8415
8424
|
}) {
|
|
8425
|
+
const localRef = (0, import_react7.useRef)(null);
|
|
8426
|
+
(0, import_react7.useLayoutEffect)(() => {
|
|
8427
|
+
const node = localRef.current;
|
|
8428
|
+
if (!node) return;
|
|
8429
|
+
node.style.display = hidden ? "none" : "block";
|
|
8430
|
+
}, [hidden, rect.top, rect.left, rect.width, rect.height, state]);
|
|
8416
8431
|
if (state === "default") return null;
|
|
8417
8432
|
const gap = chromeGap ?? (state === "hover" ? HOVER_CHROME_GAP : SELECTION_CHROME_GAP);
|
|
8418
8433
|
const isActive = state === "active-top" || state === "active-bottom";
|
|
8419
8434
|
const isDragging = state === "dragging";
|
|
8420
8435
|
const showToolbar = isActive && toolbar;
|
|
8421
8436
|
const showDragHandle = (isActive || isDragging) && showHandle;
|
|
8422
|
-
const itemDragEnabled = itemDragSurface && isActive &&
|
|
8437
|
+
const itemDragEnabled = itemDragSurface && isActive && !isDragging && !dragDisabled && Boolean(showHandle || onItemPointerDown);
|
|
8423
8438
|
const useDetachedBelowToolbar = Boolean(showToolbar && state === "active-bottom" && toolbarBelowRect);
|
|
8439
|
+
const setRootRef = (node) => {
|
|
8440
|
+
localRef.current = node;
|
|
8441
|
+
if (typeof elRef === "function") elRef(node);
|
|
8442
|
+
else if (elRef) elRef.current = node;
|
|
8443
|
+
};
|
|
8424
8444
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
8425
8445
|
"div",
|
|
8426
8446
|
{
|
|
8427
|
-
ref:
|
|
8447
|
+
ref: setRootRef,
|
|
8428
8448
|
"data-ohw-item-interaction": "",
|
|
8429
8449
|
"data-ohw-item-interaction-state": state,
|
|
8430
8450
|
className: cn("pointer-events-none", className),
|
|
@@ -8434,7 +8454,8 @@ function ItemInteractionLayer({
|
|
|
8434
8454
|
left: rect.left - gap,
|
|
8435
8455
|
width: rect.width + gap * 2,
|
|
8436
8456
|
height: rect.height + gap * 2,
|
|
8437
|
-
zIndex: getChromeZIndex(state)
|
|
8457
|
+
zIndex: getChromeZIndex(state),
|
|
8458
|
+
display: hidden ? "none" : "block"
|
|
8438
8459
|
},
|
|
8439
8460
|
children: [
|
|
8440
8461
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
@@ -11255,6 +11276,13 @@ function findButtonAtPoint(x, y, media) {
|
|
|
11255
11276
|
if (hits.length === 0) return null;
|
|
11256
11277
|
return hits.reduce((best, el) => best.contains(el) ? el : best);
|
|
11257
11278
|
}
|
|
11279
|
+
function findNavbarCtaAtPoint(x, y) {
|
|
11280
|
+
const hits = Array.from(
|
|
11281
|
+
document.querySelectorAll('[data-ohw-role="navbar-button"]')
|
|
11282
|
+
).filter((el) => containsPoint(el, x, y) && !el.closest("[data-ohw-bridge]"));
|
|
11283
|
+
if (hits.length === 0) return null;
|
|
11284
|
+
return hits.reduce((best, el) => best.contains(el) ? el : best);
|
|
11285
|
+
}
|
|
11258
11286
|
|
|
11259
11287
|
// src/lib/session-search.ts
|
|
11260
11288
|
var STORAGE_KEY = "ohw-preserved-search";
|
|
@@ -11990,6 +12018,26 @@ var import_react12 = require("react");
|
|
|
11990
12018
|
var import_react_dom3 = require("react-dom");
|
|
11991
12019
|
var import_lucide_react15 = require("lucide-react");
|
|
11992
12020
|
var import_navigation2 = require("next/navigation");
|
|
12021
|
+
|
|
12022
|
+
// src/lib/parent-scroll.ts
|
|
12023
|
+
function visibleBand(parentScroll) {
|
|
12024
|
+
const { iframeOffsetTop, headerH: visibleCanvasTop, canvasH } = parentScroll;
|
|
12025
|
+
const top = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
12026
|
+
const bottom = Math.min(window.innerHeight, visibleCanvasTop + canvasH - iframeOffsetTop);
|
|
12027
|
+
return { top, bottom: Math.max(top, bottom) };
|
|
12028
|
+
}
|
|
12029
|
+
function getIframeVisibleClip(parentScroll) {
|
|
12030
|
+
if (!parentScroll) return null;
|
|
12031
|
+
return visibleBand(parentScroll);
|
|
12032
|
+
}
|
|
12033
|
+
function getIframeChromeClip(parentScroll) {
|
|
12034
|
+
if (!parentScroll) return null;
|
|
12035
|
+
const band = visibleBand(parentScroll);
|
|
12036
|
+
const promptBarH = Math.max(0, parentScroll.promptBarH ?? 0);
|
|
12037
|
+
return { top: band.top, bottom: Math.max(band.top, band.bottom - promptBarH) };
|
|
12038
|
+
}
|
|
12039
|
+
|
|
12040
|
+
// src/ui/link-modal/SectionPickerOverlay.tsx
|
|
11993
12041
|
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
11994
12042
|
var DIM_OVERLAY = "rgba(0, 0, 0, 0.45)";
|
|
11995
12043
|
function rectsEqual(a, b) {
|
|
@@ -12127,20 +12175,22 @@ function SectionPickerOverlay({
|
|
|
12127
12175
|
[]
|
|
12128
12176
|
);
|
|
12129
12177
|
(0, import_react12.useEffect)(() => {
|
|
12130
|
-
const applyClip = (iframeOffsetTop, visibleCanvasTop, canvasH) => {
|
|
12131
|
-
const
|
|
12132
|
-
|
|
12133
|
-
|
|
12134
|
-
|
|
12135
|
-
|
|
12178
|
+
const applyClip = (iframeOffsetTop, visibleCanvasTop, canvasH, promptBarH = 0) => {
|
|
12179
|
+
const next = getIframeVisibleClip({
|
|
12180
|
+
iframeOffsetTop,
|
|
12181
|
+
headerH: visibleCanvasTop,
|
|
12182
|
+
canvasH,
|
|
12183
|
+
promptBarH
|
|
12184
|
+
});
|
|
12185
|
+
if (!next) return;
|
|
12136
12186
|
setChromeClip(
|
|
12137
|
-
(prev) => prev.top === top && prev.bottom === bottom ? prev :
|
|
12187
|
+
(prev) => prev.top === next.top && prev.bottom === next.bottom ? prev : next
|
|
12138
12188
|
);
|
|
12139
12189
|
};
|
|
12140
12190
|
const onParentScroll = (e) => {
|
|
12141
12191
|
if (e.data?.type !== "ow:parent-scroll") return;
|
|
12142
|
-
const { iframeOffsetTop, headerH, canvasH } = e.data;
|
|
12143
|
-
applyClip(iframeOffsetTop, headerH, canvasH);
|
|
12192
|
+
const { iframeOffsetTop, headerH, canvasH, promptBarH = 0 } = e.data;
|
|
12193
|
+
applyClip(iframeOffsetTop, headerH, canvasH, promptBarH);
|
|
12144
12194
|
iframeOffsetTopRef.current = iframeOffsetTop;
|
|
12145
12195
|
if (!pointerScreenRef.current && pointerRef.current) {
|
|
12146
12196
|
pointerScreenRef.current = {
|
|
@@ -15804,36 +15854,50 @@ var import_lucide_react16 = require("lucide-react");
|
|
|
15804
15854
|
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
15805
15855
|
var PANEL_WIDTH = 256;
|
|
15806
15856
|
var EDGE_MARGIN = 16;
|
|
15857
|
+
var HEADER_MIN = 56;
|
|
15807
15858
|
function getVisibleClip(parentScroll) {
|
|
15808
15859
|
const left = 0;
|
|
15809
15860
|
const right = window.innerWidth;
|
|
15810
|
-
|
|
15861
|
+
const band = getIframeChromeClip(parentScroll);
|
|
15862
|
+
if (!band) {
|
|
15811
15863
|
return { top: 0, bottom: window.innerHeight, left, right };
|
|
15812
15864
|
}
|
|
15813
|
-
|
|
15814
|
-
const top = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
15815
|
-
const bottom = Math.min(window.innerHeight, visibleCanvasTop + canvasH - iframeOffsetTop);
|
|
15816
|
-
return { top, bottom: Math.max(top, bottom), left, right };
|
|
15865
|
+
return { ...band, left, right };
|
|
15817
15866
|
}
|
|
15818
|
-
function defaultFloatingPanelPosition(parentScroll,
|
|
15867
|
+
function defaultFloatingPanelPosition(parentScroll, _panelHeight = 280) {
|
|
15819
15868
|
const clip = getVisibleClip(parentScroll);
|
|
15820
15869
|
return {
|
|
15821
15870
|
x: Math.max(EDGE_MARGIN, clip.right - PANEL_WIDTH - EDGE_MARGIN),
|
|
15822
|
-
y:
|
|
15823
|
-
Math.max(clip.top + EDGE_MARGIN, EDGE_MARGIN),
|
|
15824
|
-
Math.max(clip.top + EDGE_MARGIN, clip.bottom - panelHeight - EDGE_MARGIN)
|
|
15825
|
-
)
|
|
15871
|
+
y: clip.top + EDGE_MARGIN
|
|
15826
15872
|
};
|
|
15827
15873
|
}
|
|
15828
|
-
function
|
|
15874
|
+
function clampX(x, panelW) {
|
|
15875
|
+
const left = EDGE_MARGIN;
|
|
15876
|
+
const maxX = Math.max(left, window.innerWidth - panelW - EDGE_MARGIN);
|
|
15877
|
+
return Math.min(Math.max(x, left), maxX);
|
|
15878
|
+
}
|
|
15879
|
+
function clampDragPosition(pos, parentScroll, panelW) {
|
|
15829
15880
|
const clip = getVisibleClip(parentScroll);
|
|
15830
|
-
const
|
|
15831
|
-
const maxY = Math.max(
|
|
15881
|
+
const minY = clip.top + EDGE_MARGIN;
|
|
15882
|
+
const maxY = Math.max(minY, clip.bottom - EDGE_MARGIN - HEADER_MIN);
|
|
15832
15883
|
return {
|
|
15833
|
-
x:
|
|
15834
|
-
y: Math.min(Math.max(pos.y,
|
|
15884
|
+
x: clampX(pos.x, panelW),
|
|
15885
|
+
y: Math.min(Math.max(pos.y, minY), maxY)
|
|
15835
15886
|
};
|
|
15836
15887
|
}
|
|
15888
|
+
function fitPanelInClip(homeY, parentScroll, preferredHeight) {
|
|
15889
|
+
const clip = getVisibleClip(parentScroll);
|
|
15890
|
+
const minY = clip.top + EDGE_MARGIN;
|
|
15891
|
+
const maxBottom = clip.bottom - EDGE_MARGIN;
|
|
15892
|
+
const band = Math.max(HEADER_MIN, maxBottom - minY);
|
|
15893
|
+
let y = Math.max(homeY, minY);
|
|
15894
|
+
const want = Math.min(Math.max(preferredHeight, HEADER_MIN), band);
|
|
15895
|
+
if (y + want > maxBottom) {
|
|
15896
|
+
y = Math.max(minY, maxBottom - want);
|
|
15897
|
+
}
|
|
15898
|
+
const maxHeight = Math.max(HEADER_MIN, Math.floor(maxBottom - y));
|
|
15899
|
+
return { y, maxHeight };
|
|
15900
|
+
}
|
|
15837
15901
|
function FloatingPanel({
|
|
15838
15902
|
open,
|
|
15839
15903
|
title,
|
|
@@ -15850,19 +15914,54 @@ function FloatingPanel({
|
|
|
15850
15914
|
const panelRef = (0, import_react15.useRef)(null);
|
|
15851
15915
|
const [measured, setMeasured] = (0, import_react15.useState)({ w: PANEL_WIDTH, h: 280 });
|
|
15852
15916
|
const dragRef = (0, import_react15.useRef)(null);
|
|
15853
|
-
const
|
|
15854
|
-
|
|
15917
|
+
const homeRef = (0, import_react15.useRef)(null);
|
|
15918
|
+
if (!open) {
|
|
15919
|
+
homeRef.current = null;
|
|
15920
|
+
} else if (position) {
|
|
15921
|
+
homeRef.current = position;
|
|
15922
|
+
} else if (homeRef.current == null) {
|
|
15923
|
+
homeRef.current = defaultFloatingPanelPosition(parentScroll);
|
|
15924
|
+
}
|
|
15925
|
+
const [liveScroll, setLiveScroll] = (0, import_react15.useState)(parentScroll);
|
|
15926
|
+
const home = position ?? homeRef.current ?? defaultFloatingPanelPosition(parentScroll);
|
|
15927
|
+
const { y: fittedY, maxHeight } = fitPanelInClip(home.y, liveScroll, measured.h);
|
|
15928
|
+
const clamped = {
|
|
15929
|
+
x: clampX(home.x, measured.w),
|
|
15930
|
+
y: fittedY
|
|
15931
|
+
};
|
|
15932
|
+
(0, import_react15.useEffect)(() => {
|
|
15933
|
+
setLiveScroll(parentScroll);
|
|
15934
|
+
}, [parentScroll]);
|
|
15935
|
+
(0, import_react15.useEffect)(() => {
|
|
15936
|
+
if (!open) return;
|
|
15937
|
+
const onParentScroll = (e) => {
|
|
15938
|
+
if (e.data?.type !== "ow:parent-scroll") return;
|
|
15939
|
+
const { iframeOffsetTop, headerH, canvasH, promptBarH = 0 } = e.data;
|
|
15940
|
+
setLiveScroll({ iframeOffsetTop, headerH, canvasH, promptBarH });
|
|
15941
|
+
};
|
|
15942
|
+
window.addEventListener("message", onParentScroll);
|
|
15943
|
+
return () => window.removeEventListener("message", onParentScroll);
|
|
15944
|
+
}, [open]);
|
|
15945
|
+
const positionRef = (0, import_react15.useRef)(position);
|
|
15946
|
+
(0, import_react15.useLayoutEffect)(() => {
|
|
15947
|
+
if (!open) {
|
|
15948
|
+
positionRef.current = position;
|
|
15949
|
+
return;
|
|
15950
|
+
}
|
|
15951
|
+
if (position == null && positionRef.current != null) {
|
|
15952
|
+
homeRef.current = defaultFloatingPanelPosition(liveScroll ?? parentScroll);
|
|
15953
|
+
}
|
|
15954
|
+
positionRef.current = position;
|
|
15955
|
+
}, [open, position, liveScroll, parentScroll]);
|
|
15855
15956
|
(0, import_react15.useLayoutEffect)(() => {
|
|
15856
15957
|
if (!open || !panelRef.current) return;
|
|
15857
15958
|
const el = panelRef.current;
|
|
15858
|
-
const
|
|
15959
|
+
const header = el.querySelector("[data-ohw-floating-panel-header]");
|
|
15960
|
+
const body = el.querySelector("[data-ohw-floating-panel-body]");
|
|
15961
|
+
const contentH = (header?.offsetHeight ?? 0) + (body?.scrollHeight ?? 0) || el.scrollHeight || 280;
|
|
15962
|
+
const next = { w: el.offsetWidth || PANEL_WIDTH, h: contentH };
|
|
15859
15963
|
setMeasured((prev) => prev.w === next.w && prev.h === next.h ? prev : next);
|
|
15860
15964
|
}, [open, children, title, context]);
|
|
15861
|
-
(0, import_react15.useEffect)(() => {
|
|
15862
|
-
if (!open || !position || !onPositionChange) return;
|
|
15863
|
-
const next = clampPosition(position, parentScroll, measured.w, measured.h);
|
|
15864
|
-
if (next.x !== position.x || next.y !== position.y) onPositionChange(next);
|
|
15865
|
-
}, [open, parentScroll, measured.w, measured.h, position, onPositionChange]);
|
|
15866
15965
|
const onHeaderPointerDown = (0, import_react15.useCallback)(
|
|
15867
15966
|
(e) => {
|
|
15868
15967
|
if (e.button !== 0) return;
|
|
@@ -15896,18 +15995,17 @@ function FloatingPanel({
|
|
|
15896
15995
|
return;
|
|
15897
15996
|
}
|
|
15898
15997
|
e.preventDefault();
|
|
15899
|
-
const next =
|
|
15998
|
+
const next = clampDragPosition(
|
|
15900
15999
|
{
|
|
15901
16000
|
x: drag.originX + (e.clientX - drag.startX),
|
|
15902
16001
|
y: drag.originY + (e.clientY - drag.startY)
|
|
15903
16002
|
},
|
|
15904
|
-
|
|
15905
|
-
measured.w
|
|
15906
|
-
measured.h
|
|
16003
|
+
liveScroll,
|
|
16004
|
+
measured.w
|
|
15907
16005
|
);
|
|
15908
16006
|
onPositionChange?.(next);
|
|
15909
16007
|
},
|
|
15910
|
-
[measured.
|
|
16008
|
+
[measured.w, onPositionChange, liveScroll]
|
|
15911
16009
|
);
|
|
15912
16010
|
const endDrag = (0, import_react15.useCallback)((e) => {
|
|
15913
16011
|
const drag = dragRef.current;
|
|
@@ -15937,7 +16035,7 @@ function FloatingPanel({
|
|
|
15937
16035
|
"fixed z-[2147483647] flex w-64 flex-col overflow-hidden rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
15938
16036
|
className
|
|
15939
16037
|
),
|
|
15940
|
-
style: { left: clamped.x, top: clamped.y },
|
|
16038
|
+
style: { left: clamped.x, top: clamped.y, maxHeight },
|
|
15941
16039
|
onMouseDown: (e) => e.stopPropagation(),
|
|
15942
16040
|
onPointerDown: (e) => e.stopPropagation(),
|
|
15943
16041
|
onClick: (e) => e.stopPropagation(),
|
|
@@ -15946,7 +16044,7 @@ function FloatingPanel({
|
|
|
15946
16044
|
"div",
|
|
15947
16045
|
{
|
|
15948
16046
|
"data-ohw-floating-panel-header": "",
|
|
15949
|
-
className: "relative flex cursor-grab items-start gap-2 border-b border-border py-
|
|
16047
|
+
className: "relative flex shrink-0 cursor-grab items-start gap-2 border-b border-border py-4! pl-5! pr-11! active:cursor-grabbing",
|
|
15950
16048
|
onPointerDown: onHeaderPointerDown,
|
|
15951
16049
|
onPointerMove: onHeaderPointerMove,
|
|
15952
16050
|
onPointerUp: endDrag,
|
|
@@ -15981,7 +16079,11 @@ function FloatingPanel({
|
|
|
15981
16079
|
"div",
|
|
15982
16080
|
{
|
|
15983
16081
|
"data-ohw-floating-panel-body": "",
|
|
15984
|
-
className: cn(
|
|
16082
|
+
className: cn(
|
|
16083
|
+
"flex min-h-0 w-full flex-1 flex-col gap-4 overflow-y-auto overscroll-contain p-4",
|
|
16084
|
+
bodyClassName
|
|
16085
|
+
),
|
|
16086
|
+
style: { WebkitOverflowScrolling: "touch" },
|
|
15985
16087
|
children
|
|
15986
16088
|
}
|
|
15987
16089
|
)
|
|
@@ -16059,201 +16161,1635 @@ function SocialsDisplayPanel({ display, onChange, className }) {
|
|
|
16059
16161
|
] });
|
|
16060
16162
|
}
|
|
16061
16163
|
|
|
16062
|
-
// src/
|
|
16063
|
-
|
|
16064
|
-
|
|
16065
|
-
|
|
16066
|
-
|
|
16164
|
+
// src/ui/button-style-panel.tsx
|
|
16165
|
+
var import_lucide_react17 = require("lucide-react");
|
|
16166
|
+
|
|
16167
|
+
// src/lib/button-styles.ts
|
|
16168
|
+
var BUTTON_VARIANTS_KEY = "__ohw_button_variants";
|
|
16169
|
+
var BUTTON_SIZES_KEY = "__ohw_button_sizes";
|
|
16170
|
+
var BUTTON_ASSIGNMENTS_KEY = "__ohw_button_assignments";
|
|
16171
|
+
var BUTTON_VARIANT_IDS = ["primary", "secondary", "ghost"];
|
|
16172
|
+
var BUTTON_SIZE_IDS = ["s", "m", "l"];
|
|
16173
|
+
var TRANSPARENT = "rgba(0, 0, 0, 0)";
|
|
16174
|
+
var REFERENCE_SIZES = {
|
|
16175
|
+
s: { height: 40, paddingTop: 8, paddingRight: 16, paddingBottom: 8, paddingLeft: 16, fontSize: 15, borderRadius: 8, gap: 8 },
|
|
16176
|
+
m: { height: 48, paddingTop: 12, paddingRight: 24, paddingBottom: 12, paddingLeft: 24, fontSize: 15, borderRadius: 8, gap: 8 },
|
|
16177
|
+
l: { height: 56, paddingTop: 16, paddingRight: 32, paddingBottom: 16, paddingLeft: 32, fontSize: 15, borderRadius: 8, gap: 8 }
|
|
16178
|
+
};
|
|
16179
|
+
function buttonStyleContext(_el) {
|
|
16180
|
+
return "Button";
|
|
16181
|
+
}
|
|
16182
|
+
function previewSlotBackground(el) {
|
|
16183
|
+
let node = el.parentElement;
|
|
16184
|
+
while (node && node !== el.ownerDocument.documentElement) {
|
|
16185
|
+
if (node.closest("[data-ohw-bridge], [data-ohw-bridge-root]")) {
|
|
16186
|
+
node = node.parentElement;
|
|
16187
|
+
continue;
|
|
16188
|
+
}
|
|
16189
|
+
const bg = getComputedStyle(node).backgroundColor;
|
|
16190
|
+
const parsed = parseColor(bg);
|
|
16191
|
+
if (parsed && !isTransparent(parsed)) return bg;
|
|
16192
|
+
node = node.parentElement;
|
|
16193
|
+
}
|
|
16194
|
+
const root = el.ownerDocument.documentElement;
|
|
16195
|
+
const style = getComputedStyle(root);
|
|
16196
|
+
for (const name of ["--brand-surface", "--brand-background", "--ohw-brand-light", "--color-light"]) {
|
|
16197
|
+
const value = style.getPropertyValue(name).trim();
|
|
16198
|
+
if (value) return value;
|
|
16067
16199
|
}
|
|
16200
|
+
return "var(--brand-background, var(--ohw-brand-light, var(--color-light, #ffffff)))";
|
|
16068
16201
|
}
|
|
16069
|
-
function
|
|
16070
|
-
|
|
16071
|
-
|
|
16202
|
+
function buttonId(el) {
|
|
16203
|
+
if (!el) return null;
|
|
16204
|
+
const button = el.matches(CTA_BUTTON_SELECTOR) ? el : el.closest(CTA_BUTTON_SELECTOR);
|
|
16205
|
+
const id = button?.getAttribute("data-ohw-href-key")?.trim();
|
|
16206
|
+
return id || null;
|
|
16072
16207
|
}
|
|
16073
|
-
function
|
|
16074
|
-
|
|
16208
|
+
function isButtonVariantId(value) {
|
|
16209
|
+
return BUTTON_VARIANT_IDS.includes(value);
|
|
16075
16210
|
}
|
|
16076
|
-
function
|
|
16077
|
-
|
|
16078
|
-
document.documentElement.setAttribute("data-ohw-item-dragging", "");
|
|
16079
|
-
clearTextSelection();
|
|
16211
|
+
function isButtonSizeId(value) {
|
|
16212
|
+
return BUTTON_SIZE_IDS.includes(value);
|
|
16080
16213
|
}
|
|
16081
|
-
function
|
|
16082
|
-
const
|
|
16083
|
-
|
|
16084
|
-
document.documentElement.removeAttribute("data-ohw-item-dragging");
|
|
16085
|
-
if (wasDragging) clearTextSelection();
|
|
16214
|
+
function px(value) {
|
|
16215
|
+
const rounded = Math.round(value * 100) / 100;
|
|
16216
|
+
return `${rounded}px`;
|
|
16086
16217
|
}
|
|
16087
|
-
|
|
16088
|
-
|
|
16089
|
-
|
|
16090
|
-
|
|
16091
|
-
|
|
16092
|
-
|
|
16093
|
-
return listActiveNavbarItems(draggedEl).filter((el) => {
|
|
16094
|
-
const key = el.getAttribute("data-ohw-href-key");
|
|
16095
|
-
return isNavbarHrefKey(key) && !isNestedNavChild(el);
|
|
16096
|
-
});
|
|
16218
|
+
function parsePx(value, rootFont = 16) {
|
|
16219
|
+
if (!value) return 0;
|
|
16220
|
+
const n = parseFloat(value);
|
|
16221
|
+
if (!Number.isFinite(n)) return 0;
|
|
16222
|
+
if (value.trim().endsWith("rem") || value.trim().endsWith("em")) return n * rootFont;
|
|
16223
|
+
return n;
|
|
16097
16224
|
}
|
|
16098
|
-
function
|
|
16099
|
-
|
|
16100
|
-
|
|
16101
|
-
|
|
16102
|
-
const trigger = group.querySelector(":scope > [data-ohw-href-key]") ?? Array.from(group.querySelectorAll("[data-ohw-href-key]")).find(
|
|
16103
|
-
(el) => !el.closest("[data-ohw-nav-children]")
|
|
16104
|
-
) ?? null;
|
|
16105
|
-
const key = trigger?.getAttribute("data-ohw-href-key");
|
|
16106
|
-
return key && isNavbarHrefKey(key) ? key : null;
|
|
16225
|
+
function classifyHeight(height) {
|
|
16226
|
+
if (height < 44) return "s";
|
|
16227
|
+
if (height < 52) return "m";
|
|
16228
|
+
return "l";
|
|
16107
16229
|
}
|
|
16108
|
-
function
|
|
16109
|
-
|
|
16110
|
-
|
|
16111
|
-
|
|
16112
|
-
|
|
16113
|
-
|
|
16114
|
-
|
|
16115
|
-
|
|
16116
|
-
(
|
|
16117
|
-
|
|
16230
|
+
function scaleGeometry(geometry, scale = 0.75) {
|
|
16231
|
+
return {
|
|
16232
|
+
paddingTop: px(parsePx(geometry.paddingTop) * scale),
|
|
16233
|
+
paddingRight: px(parsePx(geometry.paddingRight) * scale),
|
|
16234
|
+
paddingBottom: px(parsePx(geometry.paddingBottom) * scale),
|
|
16235
|
+
paddingLeft: px(parsePx(geometry.paddingLeft) * scale),
|
|
16236
|
+
fontSize: px(parsePx(geometry.fontSize) * scale),
|
|
16237
|
+
borderRadius: px(parsePx(geometry.borderRadius) * scale),
|
|
16238
|
+
gap: px(parsePx(geometry.gap) * scale),
|
|
16239
|
+
height: Math.round(geometry.height * scale)
|
|
16240
|
+
};
|
|
16118
16241
|
}
|
|
16119
|
-
function
|
|
16120
|
-
const
|
|
16121
|
-
|
|
16122
|
-
|
|
16123
|
-
|
|
16124
|
-
|
|
16125
|
-
const horizontalGap = b.left - a.right;
|
|
16126
|
-
return verticalGap > horizontalGap;
|
|
16127
|
-
}
|
|
16128
|
-
const container = getActiveNavbarListContainer(draggedEl);
|
|
16129
|
-
if (!container) return false;
|
|
16130
|
-
const style = window.getComputedStyle(container);
|
|
16131
|
-
return style.flexDirection === "column" || style.flexDirection === "column-reverse";
|
|
16242
|
+
function relativeLuminance(color) {
|
|
16243
|
+
const channel = (value) => {
|
|
16244
|
+
const s = value / 255;
|
|
16245
|
+
return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
|
|
16246
|
+
};
|
|
16247
|
+
return 0.2126 * channel(color.r) + 0.7152 * channel(color.g) + 0.0722 * channel(color.b);
|
|
16132
16248
|
}
|
|
16133
|
-
function
|
|
16134
|
-
const
|
|
16135
|
-
const
|
|
16136
|
-
|
|
16137
|
-
|
|
16138
|
-
|
|
16139
|
-
|
|
16140
|
-
|
|
16141
|
-
|
|
16142
|
-
|
|
16143
|
-
|
|
16144
|
-
|
|
16145
|
-
|
|
16146
|
-
|
|
16147
|
-
|
|
16148
|
-
|
|
16149
|
-
|
|
16150
|
-
|
|
16151
|
-
const
|
|
16152
|
-
|
|
16153
|
-
|
|
16154
|
-
|
|
16155
|
-
|
|
16156
|
-
|
|
16157
|
-
|
|
16158
|
-
|
|
16159
|
-
|
|
16160
|
-
|
|
16161
|
-
|
|
16162
|
-
|
|
16163
|
-
|
|
16164
|
-
|
|
16165
|
-
|
|
16166
|
-
|
|
16167
|
-
|
|
16168
|
-
|
|
16169
|
-
|
|
16170
|
-
|
|
16171
|
-
|
|
16172
|
-
}
|
|
16173
|
-
|
|
16174
|
-
|
|
16175
|
-
|
|
16176
|
-
|
|
16177
|
-
|
|
16249
|
+
function contrastRatio(a, b) {
|
|
16250
|
+
const lighter = Math.max(relativeLuminance(a), relativeLuminance(b));
|
|
16251
|
+
const darker = Math.min(relativeLuminance(a), relativeLuminance(b));
|
|
16252
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
16253
|
+
}
|
|
16254
|
+
function compositeOver(fg, bg) {
|
|
16255
|
+
const a = fg.a + bg.a * (1 - fg.a);
|
|
16256
|
+
if (a < 1e-3) return { ...bg, a: 0 };
|
|
16257
|
+
return {
|
|
16258
|
+
r: (fg.r * fg.a + bg.r * bg.a * (1 - fg.a)) / a,
|
|
16259
|
+
g: (fg.g * fg.a + bg.g * bg.a * (1 - fg.a)) / a,
|
|
16260
|
+
b: (fg.b * fg.a + bg.b * bg.a * (1 - fg.a)) / a,
|
|
16261
|
+
a
|
|
16262
|
+
};
|
|
16263
|
+
}
|
|
16264
|
+
function previewSlotForChrome(chrome, slotBackground) {
|
|
16265
|
+
const text = parseColor(chrome.color);
|
|
16266
|
+
if (!text || text.a < 0.2) return slotBackground;
|
|
16267
|
+
const slot = parseColor(slotBackground) ?? { r: 250, g: 250, b: 249, a: 1 };
|
|
16268
|
+
const fill = parseColor(chrome.background);
|
|
16269
|
+
const effective = fill && !isTransparent(fill) ? compositeOver(fill, slot) : slot;
|
|
16270
|
+
if (contrastRatio(text, effective) >= 3) return slotBackground;
|
|
16271
|
+
return relativeLuminance(text) > 0.55 ? "#2c2c2c" : "#f4f4f5";
|
|
16272
|
+
}
|
|
16273
|
+
function parseColor(input) {
|
|
16274
|
+
if (!input) return null;
|
|
16275
|
+
const value = input.trim().toLowerCase();
|
|
16276
|
+
if (value === "transparent") return { r: 0, g: 0, b: 0, a: 0 };
|
|
16277
|
+
const hex = value.match(/^#([0-9a-f]{3,8})$/);
|
|
16278
|
+
if (hex) {
|
|
16279
|
+
const raw = hex[1];
|
|
16280
|
+
const expand = (pair) => parseInt(pair.length === 1 ? pair + pair : pair, 16);
|
|
16281
|
+
if (raw.length === 3 || raw.length === 4) {
|
|
16282
|
+
return {
|
|
16283
|
+
r: expand(raw[0]),
|
|
16284
|
+
g: expand(raw[1]),
|
|
16285
|
+
b: expand(raw[2]),
|
|
16286
|
+
a: raw.length === 4 ? expand(raw[3]) / 255 : 1
|
|
16287
|
+
};
|
|
16288
|
+
}
|
|
16289
|
+
if (raw.length === 6 || raw.length === 8) {
|
|
16290
|
+
return {
|
|
16291
|
+
r: expand(raw.slice(0, 2)),
|
|
16292
|
+
g: expand(raw.slice(2, 4)),
|
|
16293
|
+
b: expand(raw.slice(4, 6)),
|
|
16294
|
+
a: raw.length === 8 ? expand(raw.slice(6, 8)) / 255 : 1
|
|
16295
|
+
};
|
|
16178
16296
|
}
|
|
16179
|
-
slots.push({
|
|
16180
|
-
insertIndex: i,
|
|
16181
|
-
parentId: null,
|
|
16182
|
-
left,
|
|
16183
|
-
top,
|
|
16184
|
-
width: Math.max(width, 40),
|
|
16185
|
-
height: barThickness,
|
|
16186
|
-
direction: "horizontal"
|
|
16187
|
-
});
|
|
16188
16297
|
}
|
|
16189
|
-
|
|
16190
|
-
|
|
16191
|
-
|
|
16192
|
-
|
|
16193
|
-
|
|
16194
|
-
|
|
16195
|
-
|
|
16196
|
-
if (!container) return slots;
|
|
16197
|
-
const rect = container.getBoundingClientRect();
|
|
16198
|
-
slots.push({
|
|
16199
|
-
insertIndex: 0,
|
|
16200
|
-
parentId: null,
|
|
16201
|
-
left: rect.left + rect.width / 2 - barThickness / 2,
|
|
16202
|
-
top: rect.top,
|
|
16203
|
-
width: barThickness,
|
|
16204
|
-
height: Math.max(rect.height, 24),
|
|
16205
|
-
direction: "vertical"
|
|
16206
|
-
});
|
|
16207
|
-
return slots;
|
|
16298
|
+
const rgb = value.match(
|
|
16299
|
+
/^rgba?\(\s*([\d.]+)[%\s,]+([\d.]+)[%\s,]+([\d.]+)(?:%?\s*[,/]\s*([\d.]+%?))?\s*\)$/
|
|
16300
|
+
);
|
|
16301
|
+
if (rgb) {
|
|
16302
|
+
const alphaRaw = rgb[4];
|
|
16303
|
+
const alpha = alphaRaw == null ? 1 : alphaRaw.endsWith("%") ? parseFloat(alphaRaw) / 100 : parseFloat(alphaRaw);
|
|
16304
|
+
return { r: Number(rgb[1]), g: Number(rgb[2]), b: Number(rgb[3]), a: alpha };
|
|
16208
16305
|
}
|
|
16209
|
-
const
|
|
16210
|
-
|
|
16211
|
-
|
|
16212
|
-
|
|
16213
|
-
|
|
16214
|
-
|
|
16215
|
-
|
|
16216
|
-
|
|
16217
|
-
|
|
16218
|
-
|
|
16219
|
-
if (i === 0) {
|
|
16220
|
-
const first = items[0].getBoundingClientRect();
|
|
16221
|
-
left = first.left - edgeGap / 2 - barThickness / 2;
|
|
16222
|
-
top = first.top;
|
|
16223
|
-
height = first.height;
|
|
16224
|
-
} else if (i === items.length) {
|
|
16225
|
-
const last = items[items.length - 1].getBoundingClientRect();
|
|
16226
|
-
const lastGap = items.length >= 2 ? Math.max(0, last.left - items[items.length - 2].getBoundingClientRect().right) : edgeGap;
|
|
16227
|
-
left = last.right + lastGap / 2 - barThickness / 2;
|
|
16228
|
-
top = last.top;
|
|
16229
|
-
height = last.height;
|
|
16230
|
-
} else {
|
|
16231
|
-
const prev = items[i - 1].getBoundingClientRect();
|
|
16232
|
-
const next = items[i].getBoundingClientRect();
|
|
16233
|
-
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
16234
|
-
top = Math.min(prev.top, next.top);
|
|
16235
|
-
height = Math.max(prev.bottom, next.bottom) - top;
|
|
16236
|
-
}
|
|
16237
|
-
slots.push({
|
|
16238
|
-
insertIndex: i,
|
|
16239
|
-
parentId: null,
|
|
16240
|
-
left,
|
|
16241
|
-
top,
|
|
16242
|
-
width: barThickness,
|
|
16243
|
-
height: Math.max(height, 24),
|
|
16244
|
-
direction: "vertical"
|
|
16245
|
-
});
|
|
16306
|
+
const oklch = value.match(
|
|
16307
|
+
/^oklch\(\s*([\d.]+%?)\s+([\d.]+)\s+([\d.]+)(?:deg)?(?:\s*\/\s*([\d.]+%?))?\s*\)$/
|
|
16308
|
+
);
|
|
16309
|
+
if (oklch) {
|
|
16310
|
+
const Lraw = oklch[1];
|
|
16311
|
+
const L = Lraw.endsWith("%") ? parseFloat(Lraw) / 100 : parseFloat(Lraw);
|
|
16312
|
+
const gray = Math.max(0, Math.min(1, L)) * 255;
|
|
16313
|
+
const alphaRaw = oklch[4];
|
|
16314
|
+
const alpha = alphaRaw == null ? 1 : alphaRaw.endsWith("%") ? parseFloat(alphaRaw) / 100 : parseFloat(alphaRaw);
|
|
16315
|
+
return { r: gray, g: gray, b: gray, a: alpha };
|
|
16246
16316
|
}
|
|
16247
|
-
return
|
|
16317
|
+
return null;
|
|
16248
16318
|
}
|
|
16249
|
-
function
|
|
16250
|
-
|
|
16251
|
-
if (isVerticalNavLayout(items, draggedEl)) {
|
|
16252
|
-
return buildVerticalRootNavDropSlots(items, draggedEl);
|
|
16253
|
-
}
|
|
16254
|
-
return buildHorizontalRootNavDropSlots(items, draggedEl);
|
|
16319
|
+
function isTransparent(color) {
|
|
16320
|
+
return !color || color.a < 0.05;
|
|
16255
16321
|
}
|
|
16256
|
-
function
|
|
16322
|
+
function hasOpaqueBackground(background) {
|
|
16323
|
+
if (!background) return false;
|
|
16324
|
+
const value = background.trim().toLowerCase();
|
|
16325
|
+
if (!value || value === "transparent" || value === "rgba(0, 0, 0, 0)" || value === "rgb(0, 0, 0, 0)") {
|
|
16326
|
+
return false;
|
|
16327
|
+
}
|
|
16328
|
+
const parsed = parseColor(background);
|
|
16329
|
+
if (parsed) return !isTransparent(parsed);
|
|
16330
|
+
return true;
|
|
16331
|
+
}
|
|
16332
|
+
function toCss(color) {
|
|
16333
|
+
const r2 = Math.round(color.r);
|
|
16334
|
+
const g = Math.round(color.g);
|
|
16335
|
+
const b = Math.round(color.b);
|
|
16336
|
+
if (color.a >= 0.995) return `rgb(${r2}, ${g}, ${b})`;
|
|
16337
|
+
return `rgba(${r2}, ${g}, ${b}, ${Math.round(color.a * 100) / 100})`;
|
|
16338
|
+
}
|
|
16339
|
+
function colorKey(input) {
|
|
16340
|
+
const parsed = parseColor(input);
|
|
16341
|
+
if (!parsed || isTransparent(parsed)) return "transparent";
|
|
16342
|
+
return `${Math.round(parsed.r / 8)}-${Math.round(parsed.g / 8)}-${Math.round(parsed.b / 8)}-${Math.round(parsed.a * 4)}`;
|
|
16343
|
+
}
|
|
16344
|
+
function declaredVariant(className) {
|
|
16345
|
+
const match = className.match(/\bbtn--(primary|secondary|ghost)\b/);
|
|
16346
|
+
return match && isButtonVariantId(match[1]) ? match[1] : null;
|
|
16347
|
+
}
|
|
16348
|
+
function fillSlot(sample) {
|
|
16349
|
+
const width = parseFloat(sample.borderWidth);
|
|
16350
|
+
const border = parseColor(sample.borderColor);
|
|
16351
|
+
if (width > 0 && !isTransparent(border)) return "secondary";
|
|
16352
|
+
if (hasOpaqueBackground(sample.background)) return "primary";
|
|
16353
|
+
return "ghost";
|
|
16354
|
+
}
|
|
16355
|
+
function sampleSlot(sample) {
|
|
16356
|
+
return declaredVariant(sample.className) ?? fillSlot(sample);
|
|
16357
|
+
}
|
|
16358
|
+
function fingerprint(sample) {
|
|
16359
|
+
const width = parseFloat(sample.borderWidth);
|
|
16360
|
+
const border = width > 0 ? colorKey(sample.borderColor) : "none";
|
|
16361
|
+
return `${colorKey(sample.background)}|${border}|${colorKey(sample.color)}|${sampleSlot(sample)}`;
|
|
16362
|
+
}
|
|
16363
|
+
function paintColor(chrome) {
|
|
16364
|
+
if (hasOpaqueBackground(chrome.background)) {
|
|
16365
|
+
const parsed = parseColor(chrome.background);
|
|
16366
|
+
return parsed ? toCss({ ...parsed, a: 1 }) : chrome.background;
|
|
16367
|
+
}
|
|
16368
|
+
const width = parseFloat(chrome.borderWidth);
|
|
16369
|
+
if (width > 0 && hasOpaqueBackground(chrome.borderColor)) {
|
|
16370
|
+
const parsed = parseColor(chrome.borderColor);
|
|
16371
|
+
return parsed ? toCss({ ...parsed, a: 1 }) : chrome.borderColor;
|
|
16372
|
+
}
|
|
16373
|
+
const text = parseColor(chrome.color);
|
|
16374
|
+
return text ? toCss({ ...text, a: 1 }) : chrome.color;
|
|
16375
|
+
}
|
|
16376
|
+
function accentColor(chrome) {
|
|
16377
|
+
const bg = parseColor(chrome.background);
|
|
16378
|
+
if (bg && !isTransparent(bg) && relativeLuminance(bg) < 0.55) {
|
|
16379
|
+
return toCss({ ...bg, a: 1 });
|
|
16380
|
+
}
|
|
16381
|
+
const text = parseColor(chrome.color);
|
|
16382
|
+
if (text && !isTransparent(text)) return toCss({ ...text, a: 1 });
|
|
16383
|
+
return paintColor(chrome);
|
|
16384
|
+
}
|
|
16385
|
+
function chromeFrom(sample) {
|
|
16386
|
+
return {
|
|
16387
|
+
background: sample.background || TRANSPARENT,
|
|
16388
|
+
color: sample.color || "currentColor",
|
|
16389
|
+
borderColor: sample.borderColor || TRANSPARENT,
|
|
16390
|
+
borderWidth: sample.borderWidth || "0px"
|
|
16391
|
+
};
|
|
16392
|
+
}
|
|
16393
|
+
function filledPrimary(seed) {
|
|
16394
|
+
const paint = parseColor(paintColor(seed)) ?? { r: 15, g: 15, b: 15, a: 1 };
|
|
16395
|
+
const luminance = relativeLuminance(paint);
|
|
16396
|
+
return {
|
|
16397
|
+
background: toCss({ ...paint, a: 1 }),
|
|
16398
|
+
color: luminance > 0.55 ? "rgb(15, 15, 15)" : "rgb(255, 255, 255)",
|
|
16399
|
+
borderColor: TRANSPARENT,
|
|
16400
|
+
borderWidth: "0px"
|
|
16401
|
+
};
|
|
16402
|
+
}
|
|
16403
|
+
function generatedSecondary(primary) {
|
|
16404
|
+
const paint = accentColor(primary);
|
|
16405
|
+
return {
|
|
16406
|
+
background: TRANSPARENT,
|
|
16407
|
+
color: paint,
|
|
16408
|
+
borderColor: paint,
|
|
16409
|
+
borderWidth: "1px"
|
|
16410
|
+
};
|
|
16411
|
+
}
|
|
16412
|
+
function generatedGhost(primary) {
|
|
16413
|
+
return {
|
|
16414
|
+
background: TRANSPARENT,
|
|
16415
|
+
color: accentColor(primary),
|
|
16416
|
+
borderColor: TRANSPARENT,
|
|
16417
|
+
borderWidth: "0px"
|
|
16418
|
+
};
|
|
16419
|
+
}
|
|
16420
|
+
function normalizeOutlineChrome(outline, primary) {
|
|
16421
|
+
const paint = accentColor(primary);
|
|
16422
|
+
const text = parseColor(outline.color);
|
|
16423
|
+
const paintRgb = parseColor(paint);
|
|
16424
|
+
const primaryLabel = parseColor(primary.color);
|
|
16425
|
+
const matchesOnPrimary = Boolean(text && primaryLabel) && colorKey(outline.color) === colorKey(primary.color);
|
|
16426
|
+
const textTooLight = text ? relativeLuminance(text) > 0.7 : false;
|
|
16427
|
+
const paintIsDarker = paintRgb ? relativeLuminance(paintRgb) < 0.65 : hasOpaqueBackground(primary.background);
|
|
16428
|
+
if (!(matchesOnPrimary || textTooLight) || !paintIsDarker) return outline;
|
|
16429
|
+
const hasBorder = parseFloat(outline.borderWidth) > 0;
|
|
16430
|
+
return {
|
|
16431
|
+
...outline,
|
|
16432
|
+
color: paint,
|
|
16433
|
+
borderColor: hasBorder ? paint : outline.borderColor
|
|
16434
|
+
};
|
|
16435
|
+
}
|
|
16436
|
+
function generateButtonVariants(samples) {
|
|
16437
|
+
if (samples.length === 0) return { status: "unresolved" };
|
|
16438
|
+
const groups = /* @__PURE__ */ new Map();
|
|
16439
|
+
for (const sample of samples) {
|
|
16440
|
+
const key = fingerprint(sample);
|
|
16441
|
+
const list = groups.get(key) ?? [];
|
|
16442
|
+
list.push(sample);
|
|
16443
|
+
groups.set(key, list);
|
|
16444
|
+
}
|
|
16445
|
+
if (groups.size > 3) return { status: "unresolved" };
|
|
16446
|
+
const bySlot = /* @__PURE__ */ new Map();
|
|
16447
|
+
for (const group of groups.values()) {
|
|
16448
|
+
const sample = group[0];
|
|
16449
|
+
const slot = sampleSlot(sample);
|
|
16450
|
+
if (bySlot.has(slot)) return { status: "unresolved" };
|
|
16451
|
+
bySlot.set(slot, sample);
|
|
16452
|
+
}
|
|
16453
|
+
const primarySample = bySlot.get("primary");
|
|
16454
|
+
const seed = chromeFrom(primarySample ?? samples[0]);
|
|
16455
|
+
const primary = primarySample ? seed : filledPrimary(seed);
|
|
16456
|
+
const secondary = normalizeOutlineChrome(
|
|
16457
|
+
bySlot.has("secondary") ? chromeFrom(bySlot.get("secondary")) : generatedSecondary(primary),
|
|
16458
|
+
primary
|
|
16459
|
+
);
|
|
16460
|
+
const ghost = normalizeOutlineChrome(
|
|
16461
|
+
bySlot.has("ghost") ? chromeFrom(bySlot.get("ghost")) : generatedGhost(primary),
|
|
16462
|
+
primary
|
|
16463
|
+
);
|
|
16464
|
+
return {
|
|
16465
|
+
status: "ready",
|
|
16466
|
+
tokens: { primary, secondary, ghost }
|
|
16467
|
+
};
|
|
16468
|
+
}
|
|
16469
|
+
function geometryFromSample(sample) {
|
|
16470
|
+
return {
|
|
16471
|
+
paddingTop: px(sample.paddingTop),
|
|
16472
|
+
paddingRight: px(sample.paddingRight),
|
|
16473
|
+
paddingBottom: px(sample.paddingBottom),
|
|
16474
|
+
paddingLeft: px(sample.paddingLeft),
|
|
16475
|
+
fontSize: px(sample.fontSize),
|
|
16476
|
+
borderRadius: px(sample.borderRadius),
|
|
16477
|
+
gap: px(sample.gap),
|
|
16478
|
+
height: Math.round(sample.height)
|
|
16479
|
+
};
|
|
16480
|
+
}
|
|
16481
|
+
function shiftSample(base, steps) {
|
|
16482
|
+
return {
|
|
16483
|
+
height: Math.max(24, base.height + steps * 8),
|
|
16484
|
+
paddingTop: Math.max(0, base.paddingTop + steps * 4),
|
|
16485
|
+
paddingBottom: Math.max(0, base.paddingBottom + steps * 4),
|
|
16486
|
+
paddingLeft: Math.max(0, base.paddingLeft + steps * 8),
|
|
16487
|
+
paddingRight: Math.max(0, base.paddingRight + steps * 8),
|
|
16488
|
+
fontSize: base.fontSize,
|
|
16489
|
+
borderRadius: base.borderRadius,
|
|
16490
|
+
gap: base.gap
|
|
16491
|
+
};
|
|
16492
|
+
}
|
|
16493
|
+
function clusterSizes(samples) {
|
|
16494
|
+
const sorted = [...samples].sort((a, b) => a.height - b.height);
|
|
16495
|
+
const clusters = [];
|
|
16496
|
+
for (const sample of sorted) {
|
|
16497
|
+
const current = clusters[clusters.length - 1];
|
|
16498
|
+
const head = current?.[0];
|
|
16499
|
+
if (!current || !head || Math.abs(sample.height - head.height) > 2) clusters.push([sample]);
|
|
16500
|
+
else current.push(sample);
|
|
16501
|
+
}
|
|
16502
|
+
return clusters.map((group) => {
|
|
16503
|
+
const pick = (key) => group.reduce((sum, item) => sum + item[key], 0) / group.length;
|
|
16504
|
+
return {
|
|
16505
|
+
height: pick("height"),
|
|
16506
|
+
paddingTop: pick("paddingTop"),
|
|
16507
|
+
paddingRight: pick("paddingRight"),
|
|
16508
|
+
paddingBottom: pick("paddingBottom"),
|
|
16509
|
+
paddingLeft: pick("paddingLeft"),
|
|
16510
|
+
fontSize: pick("fontSize"),
|
|
16511
|
+
borderRadius: pick("borderRadius"),
|
|
16512
|
+
gap: pick("gap")
|
|
16513
|
+
};
|
|
16514
|
+
});
|
|
16515
|
+
}
|
|
16516
|
+
function tokensFromSamples(bySlot, radius, gap) {
|
|
16517
|
+
const fill = (id) => {
|
|
16518
|
+
const sample = bySlot[id] ?? REFERENCE_SIZES[id];
|
|
16519
|
+
return geometryFromSample({ ...sample, borderRadius: radius, gap });
|
|
16520
|
+
};
|
|
16521
|
+
return { s: fill("s"), m: fill("m"), l: fill("l") };
|
|
16522
|
+
}
|
|
16523
|
+
function interpolateSizes(known) {
|
|
16524
|
+
const order = BUTTON_SIZE_IDS;
|
|
16525
|
+
const indexOf = (id) => order.indexOf(id);
|
|
16526
|
+
const sorted = [...known].sort((a, b) => indexOf(a.id) - indexOf(b.id));
|
|
16527
|
+
const left = sorted[0];
|
|
16528
|
+
const right = sorted[1];
|
|
16529
|
+
const span = indexOf(right.id) - indexOf(left.id);
|
|
16530
|
+
const step = (key) => (right.sample[key] - left.sample[key]) / span;
|
|
16531
|
+
const at = (index) => {
|
|
16532
|
+
const steps = index - indexOf(left.id);
|
|
16533
|
+
return {
|
|
16534
|
+
height: left.sample.height + step("height") * steps,
|
|
16535
|
+
paddingTop: Math.max(0, left.sample.paddingTop + step("paddingTop") * steps),
|
|
16536
|
+
paddingBottom: Math.max(0, left.sample.paddingBottom + step("paddingBottom") * steps),
|
|
16537
|
+
paddingLeft: Math.max(0, left.sample.paddingLeft + step("paddingLeft") * steps),
|
|
16538
|
+
paddingRight: Math.max(0, left.sample.paddingRight + step("paddingRight") * steps),
|
|
16539
|
+
fontSize: Math.max(10, left.sample.fontSize + step("fontSize") * steps),
|
|
16540
|
+
borderRadius: left.sample.borderRadius,
|
|
16541
|
+
gap: left.sample.gap
|
|
16542
|
+
};
|
|
16543
|
+
};
|
|
16544
|
+
const bySlot = {
|
|
16545
|
+
[left.id]: left.sample,
|
|
16546
|
+
[right.id]: { ...right.sample, borderRadius: left.sample.borderRadius, gap: left.sample.gap }
|
|
16547
|
+
};
|
|
16548
|
+
for (const id of order) {
|
|
16549
|
+
if (!bySlot[id]) bySlot[id] = at(indexOf(id));
|
|
16550
|
+
}
|
|
16551
|
+
return tokensFromSamples(bySlot, left.sample.borderRadius, left.sample.gap);
|
|
16552
|
+
}
|
|
16553
|
+
function generateButtonSizes(samples) {
|
|
16554
|
+
const clusters = clusterSizes(samples.filter((sample) => sample.height > 0));
|
|
16555
|
+
if (clusters.length === 0) {
|
|
16556
|
+
return { status: "ready", tokens: tokensFromSamples(REFERENCE_SIZES, 8, 8) };
|
|
16557
|
+
}
|
|
16558
|
+
if (clusters.length > 3) return { status: "unresolved" };
|
|
16559
|
+
if (clusters.length === 3) {
|
|
16560
|
+
const sorted = [...clusters].sort((a, b) => a.height - b.height);
|
|
16561
|
+
const radius = sorted[1].borderRadius;
|
|
16562
|
+
const gap = sorted[1].gap;
|
|
16563
|
+
return {
|
|
16564
|
+
status: "ready",
|
|
16565
|
+
tokens: {
|
|
16566
|
+
s: geometryFromSample({ ...sorted[0], borderRadius: radius, gap }),
|
|
16567
|
+
m: geometryFromSample({ ...sorted[1], borderRadius: radius, gap }),
|
|
16568
|
+
l: geometryFromSample({ ...sorted[2], borderRadius: radius, gap })
|
|
16569
|
+
}
|
|
16570
|
+
};
|
|
16571
|
+
}
|
|
16572
|
+
if (clusters.length === 1) {
|
|
16573
|
+
const known = clusters[0];
|
|
16574
|
+
const slot = classifyHeight(known.height);
|
|
16575
|
+
const offset = BUTTON_SIZE_IDS.indexOf(slot);
|
|
16576
|
+
const bySlot = Object.fromEntries(
|
|
16577
|
+
BUTTON_SIZE_IDS.map((id, index) => [id, shiftSample(known, index - offset)])
|
|
16578
|
+
);
|
|
16579
|
+
bySlot[slot] = known;
|
|
16580
|
+
return { status: "ready", tokens: tokensFromSamples(bySlot, known.borderRadius, known.gap) };
|
|
16581
|
+
}
|
|
16582
|
+
const mapped = clusters.map((sample) => ({ id: classifyHeight(sample.height), sample }));
|
|
16583
|
+
if (mapped[0].id === mapped[1].id) {
|
|
16584
|
+
const larger = clusters.slice().sort((a, b) => b.height - a.height)[0];
|
|
16585
|
+
return generateButtonSizes([larger]);
|
|
16586
|
+
}
|
|
16587
|
+
return { status: "ready", tokens: interpolateSizes(mapped) };
|
|
16588
|
+
}
|
|
16589
|
+
function parseJson(raw) {
|
|
16590
|
+
if (!raw) return null;
|
|
16591
|
+
try {
|
|
16592
|
+
return JSON.parse(raw);
|
|
16593
|
+
} catch {
|
|
16594
|
+
return null;
|
|
16595
|
+
}
|
|
16596
|
+
}
|
|
16597
|
+
function isChrome(value) {
|
|
16598
|
+
if (!value || typeof value !== "object") return false;
|
|
16599
|
+
const chrome = value;
|
|
16600
|
+
return typeof chrome.background === "string" && typeof chrome.color === "string";
|
|
16601
|
+
}
|
|
16602
|
+
function isGeometry(value) {
|
|
16603
|
+
if (!value || typeof value !== "object") return false;
|
|
16604
|
+
const geometry = value;
|
|
16605
|
+
return typeof geometry.paddingTop === "string" && typeof geometry.height === "number";
|
|
16606
|
+
}
|
|
16607
|
+
function readVariantTokens(content) {
|
|
16608
|
+
const parsed = parseJson(content[BUTTON_VARIANTS_KEY]);
|
|
16609
|
+
if (!parsed) return null;
|
|
16610
|
+
if (!BUTTON_VARIANT_IDS.every((id) => isChrome(parsed[id]))) return null;
|
|
16611
|
+
return parsed;
|
|
16612
|
+
}
|
|
16613
|
+
function readSizeTokens(content) {
|
|
16614
|
+
const parsed = parseJson(content[BUTTON_SIZES_KEY]);
|
|
16615
|
+
if (!parsed) return null;
|
|
16616
|
+
if (!BUTTON_SIZE_IDS.every((id) => isGeometry(parsed[id]))) return null;
|
|
16617
|
+
return parsed;
|
|
16618
|
+
}
|
|
16619
|
+
function readAssignments(content) {
|
|
16620
|
+
const parsed = parseJson(content[BUTTON_ASSIGNMENTS_KEY]);
|
|
16621
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
16622
|
+
const next = {};
|
|
16623
|
+
for (const [id, value] of Object.entries(parsed)) {
|
|
16624
|
+
if (!value || !isButtonVariantId(value.variant) || !isButtonSizeId(value.size)) continue;
|
|
16625
|
+
next[id] = { variant: value.variant, size: value.size };
|
|
16626
|
+
}
|
|
16627
|
+
return next;
|
|
16628
|
+
}
|
|
16629
|
+
function cssLength(style, prop) {
|
|
16630
|
+
return style.getPropertyValue(prop) || "0px";
|
|
16631
|
+
}
|
|
16632
|
+
function readVariantSample(el) {
|
|
16633
|
+
const style = getComputedStyle(el);
|
|
16634
|
+
return {
|
|
16635
|
+
background: style.backgroundColor,
|
|
16636
|
+
color: style.color,
|
|
16637
|
+
borderColor: style.borderTopColor,
|
|
16638
|
+
borderWidth: style.borderTopWidth,
|
|
16639
|
+
className: el.className || ""
|
|
16640
|
+
};
|
|
16641
|
+
}
|
|
16642
|
+
function readSizeSample(el) {
|
|
16643
|
+
const style = getComputedStyle(el);
|
|
16644
|
+
const rootFont = parsePx(getComputedStyle(el.ownerDocument.documentElement).fontSize) || 16;
|
|
16645
|
+
const rect = el.getBoundingClientRect();
|
|
16646
|
+
return {
|
|
16647
|
+
height: rect.height,
|
|
16648
|
+
paddingTop: parsePx(cssLength(style, "padding-top"), rootFont),
|
|
16649
|
+
paddingRight: parsePx(cssLength(style, "padding-right"), rootFont),
|
|
16650
|
+
paddingBottom: parsePx(cssLength(style, "padding-bottom"), rootFont),
|
|
16651
|
+
paddingLeft: parsePx(cssLength(style, "padding-left"), rootFont),
|
|
16652
|
+
fontSize: parsePx(style.fontSize, rootFont),
|
|
16653
|
+
borderRadius: parsePx(style.borderTopLeftRadius, rootFont),
|
|
16654
|
+
gap: parsePx(style.columnGap || style.gap, rootFont)
|
|
16655
|
+
};
|
|
16656
|
+
}
|
|
16657
|
+
function readTypography(el) {
|
|
16658
|
+
const style = getComputedStyle(el);
|
|
16659
|
+
return {
|
|
16660
|
+
fontFamily: style.fontFamily,
|
|
16661
|
+
fontWeight: style.fontWeight,
|
|
16662
|
+
letterSpacing: style.letterSpacing,
|
|
16663
|
+
textTransform: style.textTransform,
|
|
16664
|
+
textDecoration: style.textDecorationLine || style.textDecoration || "none"
|
|
16665
|
+
};
|
|
16666
|
+
}
|
|
16667
|
+
var buttonOriginByEl = /* @__PURE__ */ new WeakMap();
|
|
16668
|
+
var ORIGIN_ATTR = "data-ohw-btn-origin";
|
|
16669
|
+
function parseOriginAttr(raw) {
|
|
16670
|
+
if (!raw) return null;
|
|
16671
|
+
try {
|
|
16672
|
+
const value = JSON.parse(raw);
|
|
16673
|
+
if (!value?.variant || !value.size || !value.typography) return null;
|
|
16674
|
+
return value;
|
|
16675
|
+
} catch {
|
|
16676
|
+
return null;
|
|
16677
|
+
}
|
|
16678
|
+
}
|
|
16679
|
+
function measureLiveOrigin(el) {
|
|
16680
|
+
return {
|
|
16681
|
+
variant: readVariantSample(el),
|
|
16682
|
+
size: readSizeSample(el),
|
|
16683
|
+
typography: readTypography(el)
|
|
16684
|
+
};
|
|
16685
|
+
}
|
|
16686
|
+
function captureButtonOrigin(el) {
|
|
16687
|
+
const cached = buttonOriginByEl.get(el);
|
|
16688
|
+
if (cached) return cached;
|
|
16689
|
+
const fromAttr = parseOriginAttr(el.getAttribute(ORIGIN_ATTR));
|
|
16690
|
+
if (fromAttr) {
|
|
16691
|
+
buttonOriginByEl.set(el, fromAttr);
|
|
16692
|
+
return fromAttr;
|
|
16693
|
+
}
|
|
16694
|
+
const origin = measureLiveOrigin(el);
|
|
16695
|
+
buttonOriginByEl.set(el, origin);
|
|
16696
|
+
try {
|
|
16697
|
+
el.setAttribute(ORIGIN_ATTR, JSON.stringify(origin));
|
|
16698
|
+
} catch {
|
|
16699
|
+
}
|
|
16700
|
+
return origin;
|
|
16701
|
+
}
|
|
16702
|
+
function listStyleButtons(doc) {
|
|
16703
|
+
return Array.from(doc.querySelectorAll(CTA_BUTTON_SELECTOR)).filter((el) => {
|
|
16704
|
+
if (el.closest("[data-ohw-bridge], [data-ohw-bridge-root]")) return false;
|
|
16705
|
+
const rect = el.getBoundingClientRect();
|
|
16706
|
+
return rect.width > 0 && rect.height > 0;
|
|
16707
|
+
});
|
|
16708
|
+
}
|
|
16709
|
+
function generateTokensFromButtons(buttons) {
|
|
16710
|
+
const variants = generateButtonVariants(buttons.map(readVariantSample));
|
|
16711
|
+
const sizes = generateButtonSizes(buttons.map(readSizeSample));
|
|
16712
|
+
if (variants.status !== "ready" || sizes.status !== "ready") return { status: "unresolved" };
|
|
16713
|
+
return { status: "ready", tokens: { variants: variants.tokens, sizes: sizes.tokens } };
|
|
16714
|
+
}
|
|
16715
|
+
function tokensFromButton(el) {
|
|
16716
|
+
const origin = captureButtonOrigin(el);
|
|
16717
|
+
const sample = origin.variant;
|
|
16718
|
+
const variants = generateButtonVariants([sample]);
|
|
16719
|
+
const sizes = generateButtonSizes([origin.size]);
|
|
16720
|
+
const primary = chromeFrom(sample);
|
|
16721
|
+
return {
|
|
16722
|
+
variants: variants.status === "ready" ? variants.tokens : { primary, secondary: generatedSecondary(primary), ghost: generatedGhost(primary) },
|
|
16723
|
+
sizes: sizes.status === "ready" ? sizes.tokens : tokensFromSamples(REFERENCE_SIZES, 8, 8)
|
|
16724
|
+
};
|
|
16725
|
+
}
|
|
16726
|
+
function readStoredStyleTokens(content) {
|
|
16727
|
+
const variants = readVariantTokens(content);
|
|
16728
|
+
const sizes = readSizeTokens(content);
|
|
16729
|
+
if (!variants || !sizes) return null;
|
|
16730
|
+
return { variants, sizes };
|
|
16731
|
+
}
|
|
16732
|
+
function styleTokenNodes(tokens) {
|
|
16733
|
+
return [
|
|
16734
|
+
{ key: BUTTON_VARIANTS_KEY, text: JSON.stringify(tokens.variants) },
|
|
16735
|
+
{ key: BUTTON_SIZES_KEY, text: JSON.stringify(tokens.sizes) }
|
|
16736
|
+
];
|
|
16737
|
+
}
|
|
16738
|
+
function ensureButtonStyleTokens(doc, content) {
|
|
16739
|
+
const stored = readStoredStyleTokens(content);
|
|
16740
|
+
if (stored) return { tokens: stored, nodes: [] };
|
|
16741
|
+
const generated = generateTokensFromButtons(listStyleButtons(doc));
|
|
16742
|
+
if (generated.status !== "ready") return { tokens: null, nodes: [] };
|
|
16743
|
+
return { tokens: generated.tokens, nodes: styleTokenNodes(generated.tokens) };
|
|
16744
|
+
}
|
|
16745
|
+
function detectVariant(el, tokens) {
|
|
16746
|
+
const declared = declaredVariant(el.className || "");
|
|
16747
|
+
if (declared) return declared;
|
|
16748
|
+
const stamped = el.getAttribute("data-ohw-btn-variant");
|
|
16749
|
+
if (stamped && isButtonVariantId(stamped)) return stamped;
|
|
16750
|
+
const sample = readVariantSample(el);
|
|
16751
|
+
if (!tokens) return sampleSlot(sample);
|
|
16752
|
+
const key = fingerprint(sample);
|
|
16753
|
+
for (const id of BUTTON_VARIANT_IDS) {
|
|
16754
|
+
const chrome = tokens[id];
|
|
16755
|
+
const tokenKey = fingerprint({
|
|
16756
|
+
background: chrome.background,
|
|
16757
|
+
color: chrome.color,
|
|
16758
|
+
borderColor: chrome.borderColor,
|
|
16759
|
+
borderWidth: chrome.borderWidth,
|
|
16760
|
+
className: `btn btn--${id}`
|
|
16761
|
+
});
|
|
16762
|
+
if (tokenKey === key) return id;
|
|
16763
|
+
}
|
|
16764
|
+
return sampleSlot(sample);
|
|
16765
|
+
}
|
|
16766
|
+
function detectSize(el, tokens) {
|
|
16767
|
+
const stamped = el.getAttribute("data-ohw-btn-size");
|
|
16768
|
+
if (stamped && isButtonSizeId(stamped)) return stamped;
|
|
16769
|
+
const height = el.getBoundingClientRect().height;
|
|
16770
|
+
if (!tokens) return classifyHeight(height);
|
|
16771
|
+
let best = "m";
|
|
16772
|
+
let bestDelta = Number.POSITIVE_INFINITY;
|
|
16773
|
+
for (const id of BUTTON_SIZE_IDS) {
|
|
16774
|
+
const delta = Math.abs(tokens[id].height - height);
|
|
16775
|
+
if (delta < bestDelta) {
|
|
16776
|
+
best = id;
|
|
16777
|
+
bestDelta = delta;
|
|
16778
|
+
}
|
|
16779
|
+
}
|
|
16780
|
+
return best;
|
|
16781
|
+
}
|
|
16782
|
+
function assignmentFor(el, content, tokens) {
|
|
16783
|
+
const id = buttonId(el);
|
|
16784
|
+
const stored = id ? readAssignments(content)[id] : void 0;
|
|
16785
|
+
if (stored) return stored;
|
|
16786
|
+
return {
|
|
16787
|
+
variant: detectVariant(el, tokens?.variants ?? null),
|
|
16788
|
+
size: detectSize(el, tokens?.sizes ?? null)
|
|
16789
|
+
};
|
|
16790
|
+
}
|
|
16791
|
+
function labelElement(el) {
|
|
16792
|
+
return el.querySelector('[data-ohw-editable="text"], [data-ohw-editable="plain"]') ?? (el.matches('[data-ohw-editable="text"], [data-ohw-editable="plain"]') ? el : null);
|
|
16793
|
+
}
|
|
16794
|
+
var paintLockByEl = /* @__PURE__ */ new WeakMap();
|
|
16795
|
+
var paintObserverByEl = /* @__PURE__ */ new WeakMap();
|
|
16796
|
+
var paintingButton = false;
|
|
16797
|
+
function paintButtonChrome(el, assignment, tokens) {
|
|
16798
|
+
const origin = captureButtonOrigin(el);
|
|
16799
|
+
const chrome = tokens.variants[assignment.variant];
|
|
16800
|
+
const originSlot = classifyHeight(origin.size.height);
|
|
16801
|
+
const geometry = assignment.size === originSlot ? geometryFromSample({ ...origin.size, borderRadius: origin.size.borderRadius, gap: origin.size.gap }) : tokens.sizes[assignment.size];
|
|
16802
|
+
const { typography } = origin;
|
|
16803
|
+
el.setAttribute("data-ohw-btn-variant", assignment.variant);
|
|
16804
|
+
el.setAttribute("data-ohw-btn-size", assignment.size);
|
|
16805
|
+
el.style.transition = "none";
|
|
16806
|
+
el.style.boxSizing = "border-box";
|
|
16807
|
+
el.style.display = "inline-flex";
|
|
16808
|
+
el.style.alignItems = "center";
|
|
16809
|
+
el.style.justifyContent = "center";
|
|
16810
|
+
el.style.background = chrome.background;
|
|
16811
|
+
el.style.color = chrome.color;
|
|
16812
|
+
el.style.borderStyle = parseFloat(chrome.borderWidth) > 0 ? "solid" : "none";
|
|
16813
|
+
el.style.borderColor = chrome.borderColor;
|
|
16814
|
+
el.style.borderWidth = chrome.borderWidth;
|
|
16815
|
+
el.style.padding = `${geometry.paddingTop} ${geometry.paddingRight} ${geometry.paddingBottom} ${geometry.paddingLeft}`;
|
|
16816
|
+
el.style.fontSize = geometry.fontSize;
|
|
16817
|
+
el.style.borderRadius = px(origin.size.borderRadius);
|
|
16818
|
+
el.style.gap = geometry.gap;
|
|
16819
|
+
el.style.height = px(geometry.height);
|
|
16820
|
+
el.style.fontFamily = typography.fontFamily;
|
|
16821
|
+
el.style.fontWeight = typography.fontWeight;
|
|
16822
|
+
el.style.letterSpacing = typography.letterSpacing;
|
|
16823
|
+
el.style.textTransform = typography.textTransform;
|
|
16824
|
+
if (typography.textDecoration && typography.textDecoration !== "none") {
|
|
16825
|
+
el.style.textDecoration = typography.textDecoration;
|
|
16826
|
+
} else {
|
|
16827
|
+
el.style.textDecoration = "none";
|
|
16828
|
+
}
|
|
16829
|
+
const label = labelElement(el);
|
|
16830
|
+
if (label && label !== el) label.style.color = chrome.color;
|
|
16831
|
+
}
|
|
16832
|
+
function guardTemplateHover(el) {
|
|
16833
|
+
if (paintObserverByEl.has(el)) return;
|
|
16834
|
+
const observer = new MutationObserver(() => {
|
|
16835
|
+
if (paintingButton) return;
|
|
16836
|
+
const lock = paintLockByEl.get(el);
|
|
16837
|
+
if (!lock) return;
|
|
16838
|
+
paintingButton = true;
|
|
16839
|
+
paintButtonChrome(el, lock.assignment, lock.tokens);
|
|
16840
|
+
paintingButton = false;
|
|
16841
|
+
});
|
|
16842
|
+
observer.observe(el, { attributes: true, attributeFilter: ["style", "class"] });
|
|
16843
|
+
paintObserverByEl.set(el, observer);
|
|
16844
|
+
}
|
|
16845
|
+
function applyButtonStyle(el, assignment, tokens) {
|
|
16846
|
+
paintLockByEl.set(el, { assignment, tokens });
|
|
16847
|
+
paintingButton = true;
|
|
16848
|
+
paintButtonChrome(el, assignment, tokens);
|
|
16849
|
+
paintingButton = false;
|
|
16850
|
+
guardTemplateHover(el);
|
|
16851
|
+
}
|
|
16852
|
+
function applyButtonStylesFromContent(doc, content) {
|
|
16853
|
+
const assignments = readAssignments(content);
|
|
16854
|
+
for (const [id, assignment] of Object.entries(assignments)) {
|
|
16855
|
+
const el = doc.querySelector(`[data-ohw-href-key="${CSS.escape(id)}"]`);
|
|
16856
|
+
if (!el) continue;
|
|
16857
|
+
applyButtonStyle(el, assignment, tokensFromButton(el));
|
|
16858
|
+
}
|
|
16859
|
+
}
|
|
16860
|
+
function withAssignment(content, id, assignment) {
|
|
16861
|
+
return { ...readAssignments(content), [id]: assignment };
|
|
16862
|
+
}
|
|
16863
|
+
|
|
16864
|
+
// src/ui/button-style-panel.tsx
|
|
16865
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
16866
|
+
var SIZE_LABEL = { s: "S", m: "M", l: "L" };
|
|
16867
|
+
function ButtonStylePanel({
|
|
16868
|
+
variants,
|
|
16869
|
+
sizes,
|
|
16870
|
+
variant,
|
|
16871
|
+
size,
|
|
16872
|
+
onVariant,
|
|
16873
|
+
onSize,
|
|
16874
|
+
previewLabel = "Book Now",
|
|
16875
|
+
slotBackground = "var(--brand-background, var(--ohw-brand-light, var(--color-light, #ffffff)))"
|
|
16876
|
+
}) {
|
|
16877
|
+
const preview = scaleGeometry(sizes.m, 0.75);
|
|
16878
|
+
const label = previewLabel.trim() || "Book Now";
|
|
16879
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex w-full flex-col gap-5", children: [
|
|
16880
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("section", { className: "flex w-full flex-col gap-2.5", children: [
|
|
16881
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("h3", { className: "text-xs font-semibold uppercase leading-4 tracking-[0.6px] text-stone-500 font-sans", children: "Variants" }),
|
|
16882
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex w-full flex-col gap-2.5", children: BUTTON_VARIANT_IDS.map((id) => {
|
|
16883
|
+
const chrome = variants[id];
|
|
16884
|
+
const selected = id === variant;
|
|
16885
|
+
const hasBorder = parseFloat(chrome.borderWidth) > 0;
|
|
16886
|
+
const cardSlot = previewSlotForChrome(chrome, slotBackground);
|
|
16887
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
16888
|
+
"button",
|
|
16889
|
+
{
|
|
16890
|
+
type: "button",
|
|
16891
|
+
"aria-pressed": selected,
|
|
16892
|
+
"aria-label": id,
|
|
16893
|
+
onMouseDown: (e) => {
|
|
16894
|
+
e.preventDefault();
|
|
16895
|
+
e.stopPropagation();
|
|
16896
|
+
},
|
|
16897
|
+
onClick: () => onVariant(id),
|
|
16898
|
+
className: cn(
|
|
16899
|
+
"relative w-full overflow-hidden rounded-xl border-solid text-left",
|
|
16900
|
+
selected ? "border-2 border-primary" : "border border-border"
|
|
16901
|
+
),
|
|
16902
|
+
children: [
|
|
16903
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
16904
|
+
"div",
|
|
16905
|
+
{
|
|
16906
|
+
className: "flex w-full items-center justify-center py-4",
|
|
16907
|
+
style: { background: cardSlot },
|
|
16908
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
16909
|
+
"span",
|
|
16910
|
+
{
|
|
16911
|
+
className: "inline-flex items-center justify-center whitespace-nowrap font-semibold uppercase leading-none",
|
|
16912
|
+
style: {
|
|
16913
|
+
background: chrome.background,
|
|
16914
|
+
color: chrome.color,
|
|
16915
|
+
borderColor: chrome.borderColor,
|
|
16916
|
+
borderWidth: hasBorder ? chrome.borderWidth : "0px",
|
|
16917
|
+
borderStyle: hasBorder ? "solid" : "none",
|
|
16918
|
+
padding: `${preview.paddingTop} ${preview.paddingRight} ${preview.paddingBottom} ${preview.paddingLeft}`,
|
|
16919
|
+
fontSize: preview.fontSize,
|
|
16920
|
+
borderRadius: preview.borderRadius,
|
|
16921
|
+
height: preview.height,
|
|
16922
|
+
boxSizing: "border-box",
|
|
16923
|
+
letterSpacing: "0.12em"
|
|
16924
|
+
},
|
|
16925
|
+
children: label
|
|
16926
|
+
}
|
|
16927
|
+
)
|
|
16928
|
+
}
|
|
16929
|
+
),
|
|
16930
|
+
selected ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
16931
|
+
"span",
|
|
16932
|
+
{
|
|
16933
|
+
className: "absolute right-0.5 top-0.5 flex size-5 items-center justify-center rounded-full bg-primary text-primary-foreground",
|
|
16934
|
+
"aria-hidden": true,
|
|
16935
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react17.Check, { className: "size-3", strokeWidth: 3 })
|
|
16936
|
+
}
|
|
16937
|
+
) : null
|
|
16938
|
+
]
|
|
16939
|
+
},
|
|
16940
|
+
id
|
|
16941
|
+
);
|
|
16942
|
+
}) })
|
|
16943
|
+
] }),
|
|
16944
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("section", { className: "flex w-full flex-col gap-2.5", children: [
|
|
16945
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("h3", { className: "text-xs font-semibold uppercase leading-4 tracking-[0.6px] text-stone-500 font-sans", children: "Size" }),
|
|
16946
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
16947
|
+
"div",
|
|
16948
|
+
{
|
|
16949
|
+
className: "flex w-full items-start rounded-lg bg-stone-100 p-1",
|
|
16950
|
+
role: "radiogroup",
|
|
16951
|
+
"aria-label": "Size",
|
|
16952
|
+
children: BUTTON_SIZE_IDS.map((id) => {
|
|
16953
|
+
const selected = id === size;
|
|
16954
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
16955
|
+
"button",
|
|
16956
|
+
{
|
|
16957
|
+
type: "button",
|
|
16958
|
+
role: "radio",
|
|
16959
|
+
"aria-checked": selected,
|
|
16960
|
+
onMouseDown: (e) => {
|
|
16961
|
+
e.preventDefault();
|
|
16962
|
+
e.stopPropagation();
|
|
16963
|
+
},
|
|
16964
|
+
onClick: () => onSize(id),
|
|
16965
|
+
className: cn(
|
|
16966
|
+
"flex min-w-14 flex-1 items-center justify-center rounded-md px-3 py-1.5 text-sm font-medium leading-5",
|
|
16967
|
+
selected ? "bg-white text-stone-950 shadow-sm" : "bg-transparent text-stone-500"
|
|
16968
|
+
),
|
|
16969
|
+
children: SIZE_LABEL[id]
|
|
16970
|
+
},
|
|
16971
|
+
id
|
|
16972
|
+
);
|
|
16973
|
+
})
|
|
16974
|
+
}
|
|
16975
|
+
)
|
|
16976
|
+
] })
|
|
16977
|
+
] });
|
|
16978
|
+
}
|
|
16979
|
+
|
|
16980
|
+
// src/lib/button-collections.ts
|
|
16981
|
+
var BUTTON_COLLECTIONS_KEY = "__ohw_button_collections";
|
|
16982
|
+
var BUTTON_SNAPSHOTS_KEY = "__ohw_button_snapshots";
|
|
16983
|
+
var BUTTON_HIDDEN_KEY = "__ohw_button_hidden";
|
|
16984
|
+
var COLLECTION_ATTR = "data-ohw-button-collection";
|
|
16985
|
+
function parseJson2(raw) {
|
|
16986
|
+
if (!raw) return null;
|
|
16987
|
+
try {
|
|
16988
|
+
return JSON.parse(raw);
|
|
16989
|
+
} catch {
|
|
16990
|
+
return null;
|
|
16991
|
+
}
|
|
16992
|
+
}
|
|
16993
|
+
function readCollections(content) {
|
|
16994
|
+
const parsed = parseJson2(content[BUTTON_COLLECTIONS_KEY]);
|
|
16995
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
16996
|
+
const next = {};
|
|
16997
|
+
for (const [id, value] of Object.entries(parsed)) {
|
|
16998
|
+
if (!value || !Array.isArray(value.members)) continue;
|
|
16999
|
+
next[id] = {
|
|
17000
|
+
id,
|
|
17001
|
+
members: value.members.filter((member) => typeof member === "string" && member),
|
|
17002
|
+
gap: typeof value.gap === "string" ? value.gap : "12px"
|
|
17003
|
+
};
|
|
17004
|
+
}
|
|
17005
|
+
return next;
|
|
17006
|
+
}
|
|
17007
|
+
function readSnapshots(content) {
|
|
17008
|
+
const parsed = parseJson2(content[BUTTON_SNAPSHOTS_KEY]);
|
|
17009
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
17010
|
+
const next = {};
|
|
17011
|
+
for (const [id, value] of Object.entries(parsed)) {
|
|
17012
|
+
if (!value || typeof value.html !== "string") continue;
|
|
17013
|
+
next[id] = value;
|
|
17014
|
+
}
|
|
17015
|
+
return next;
|
|
17016
|
+
}
|
|
17017
|
+
function readHiddenButtons(content) {
|
|
17018
|
+
const parsed = parseJson2(content[BUTTON_HIDDEN_KEY]);
|
|
17019
|
+
if (!Array.isArray(parsed)) return [];
|
|
17020
|
+
return parsed.filter((id) => typeof id === "string" && id);
|
|
17021
|
+
}
|
|
17022
|
+
function buttonCollectionOf(el) {
|
|
17023
|
+
return el?.closest(`[${COLLECTION_ATTR}]`) ?? null;
|
|
17024
|
+
}
|
|
17025
|
+
function isNavbarCta(el) {
|
|
17026
|
+
return el.getAttribute("data-ohw-role") === "navbar-button" || Boolean(el.closest('[data-ohw-role="navbar-button"]'));
|
|
17027
|
+
}
|
|
17028
|
+
function navbarScope(el) {
|
|
17029
|
+
return el.closest("nav, [data-ohw-nav-container], [data-ohw-nav-drawer]") ?? el.ownerDocument;
|
|
17030
|
+
}
|
|
17031
|
+
function isLastNavbarButton(el) {
|
|
17032
|
+
if (!isNavbarCta(el)) return false;
|
|
17033
|
+
const buttons = Array.from(navbarScope(el).querySelectorAll(CTA_BUTTON_SELECTOR)).filter(
|
|
17034
|
+
(button) => isNavbarCta(button) && buttonId(button)
|
|
17035
|
+
);
|
|
17036
|
+
return buttons.length <= 1;
|
|
17037
|
+
}
|
|
17038
|
+
function canDeleteButton(el) {
|
|
17039
|
+
return !isLastNavbarButton(el);
|
|
17040
|
+
}
|
|
17041
|
+
function canDuplicateButton(el) {
|
|
17042
|
+
return isNavbarCta(el);
|
|
17043
|
+
}
|
|
17044
|
+
function labelElement2(el) {
|
|
17045
|
+
return el.querySelector('[data-ohw-editable="text"], [data-ohw-editable="plain"]') ?? el.querySelector("[data-ohw-key]");
|
|
17046
|
+
}
|
|
17047
|
+
function buttonLabel(el) {
|
|
17048
|
+
return (labelElement2(el)?.textContent ?? el.textContent ?? "").trim();
|
|
17049
|
+
}
|
|
17050
|
+
function buttonHref(el) {
|
|
17051
|
+
return el.getAttribute("href") ?? "";
|
|
17052
|
+
}
|
|
17053
|
+
function hrefKeyBase(hrefKey) {
|
|
17054
|
+
return hrefKey.replace(/-href$/, "").replace(/-copy-\d+$/, "");
|
|
17055
|
+
}
|
|
17056
|
+
function labelKeyForHrefKey(hrefKey) {
|
|
17057
|
+
return `${hrefKey.replace(/-href$/, "")}-label`;
|
|
17058
|
+
}
|
|
17059
|
+
function cleanClone(el) {
|
|
17060
|
+
const copy = el.cloneNode(true);
|
|
17061
|
+
copy.querySelectorAll("[data-ohw-selected], [data-ohw-hovered], [data-ohw-editing]").forEach((node) => {
|
|
17062
|
+
node.removeAttribute("data-ohw-selected");
|
|
17063
|
+
node.removeAttribute("data-ohw-hovered");
|
|
17064
|
+
node.removeAttribute("data-ohw-editing");
|
|
17065
|
+
node.removeAttribute("contenteditable");
|
|
17066
|
+
});
|
|
17067
|
+
copy.removeAttribute("data-ohw-selected");
|
|
17068
|
+
copy.removeAttribute("data-ohw-hovered");
|
|
17069
|
+
copy.removeAttribute("data-ohw-editing");
|
|
17070
|
+
copy.removeAttribute("contenteditable");
|
|
17071
|
+
copy.removeAttribute("data-ohw-drag-disabled");
|
|
17072
|
+
return copy;
|
|
17073
|
+
}
|
|
17074
|
+
function nextCopyId(sourceId, content, doc) {
|
|
17075
|
+
const used = /* @__PURE__ */ new Set([
|
|
17076
|
+
...Object.keys(readSnapshots(content)),
|
|
17077
|
+
...Object.keys(readAssignments(content)),
|
|
17078
|
+
...Array.from(doc.querySelectorAll("[data-ohw-href-key]")).map(
|
|
17079
|
+
(el) => el.getAttribute("data-ohw-href-key") ?? ""
|
|
17080
|
+
)
|
|
17081
|
+
]);
|
|
17082
|
+
const base = hrefKeyBase(sourceId);
|
|
17083
|
+
let n = 2;
|
|
17084
|
+
while (used.has(`${base}-copy-${n}-href`)) n += 1;
|
|
17085
|
+
return `${base}-copy-${n}-href`;
|
|
17086
|
+
}
|
|
17087
|
+
function nextCollectionId(content, doc) {
|
|
17088
|
+
const used = /* @__PURE__ */ new Set([
|
|
17089
|
+
...Object.keys(readCollections(content)),
|
|
17090
|
+
...Array.from(doc.querySelectorAll(`[${COLLECTION_ATTR}]`)).map(
|
|
17091
|
+
(el) => el.getAttribute(COLLECTION_ATTR) ?? ""
|
|
17092
|
+
)
|
|
17093
|
+
]);
|
|
17094
|
+
let n = 1;
|
|
17095
|
+
while (used.has(`bc-${n}`)) n += 1;
|
|
17096
|
+
return `bc-${n}`;
|
|
17097
|
+
}
|
|
17098
|
+
var COLLECTION_GAP_MAX_PX = 12;
|
|
17099
|
+
var COLLECTION_GAP_DEFAULT = "12px";
|
|
17100
|
+
function usableGap(value) {
|
|
17101
|
+
if (!value || value === "normal") return null;
|
|
17102
|
+
const n = parseFloat(value);
|
|
17103
|
+
if (!Number.isFinite(n) || n <= 0) return null;
|
|
17104
|
+
if (n > COLLECTION_GAP_MAX_PX) return COLLECTION_GAP_DEFAULT;
|
|
17105
|
+
return `${Math.round(n * 100) / 100}px`;
|
|
17106
|
+
}
|
|
17107
|
+
function collectionGap(el, tokens) {
|
|
17108
|
+
const fromCollection = usableGap(buttonCollectionOf(el)?.style.gap);
|
|
17109
|
+
if (fromCollection) return fromCollection;
|
|
17110
|
+
const parent = el.parentElement;
|
|
17111
|
+
if (parent) {
|
|
17112
|
+
const style = getComputedStyle(parent);
|
|
17113
|
+
const fromParent = usableGap(style.columnGap) ?? usableGap(style.gap);
|
|
17114
|
+
if (fromParent) return fromParent;
|
|
17115
|
+
}
|
|
17116
|
+
const fromTokens = usableGap(tokens?.sizes.m.gap);
|
|
17117
|
+
if (fromTokens) return fromTokens;
|
|
17118
|
+
return COLLECTION_GAP_DEFAULT;
|
|
17119
|
+
}
|
|
17120
|
+
function styleCollection(collection, gap) {
|
|
17121
|
+
collection.style.display = "inline-flex";
|
|
17122
|
+
collection.style.alignItems = "center";
|
|
17123
|
+
collection.style.flexWrap = "wrap";
|
|
17124
|
+
collection.style.gap = gap;
|
|
17125
|
+
collection.style.maxWidth = "100%";
|
|
17126
|
+
}
|
|
17127
|
+
function createCollection(doc, id, gap) {
|
|
17128
|
+
const collection = doc.createElement("div");
|
|
17129
|
+
collection.setAttribute(COLLECTION_ATTR, id);
|
|
17130
|
+
styleCollection(collection, gap);
|
|
17131
|
+
return collection;
|
|
17132
|
+
}
|
|
17133
|
+
function setButtonDragAttr(el) {
|
|
17134
|
+
if (isNavbarCta(el) && buttonCollectionOf(el)) el.removeAttribute("data-ohw-drag-disabled");
|
|
17135
|
+
else el.setAttribute("data-ohw-drag-disabled", "true");
|
|
17136
|
+
}
|
|
17137
|
+
function rekeyCopy(copy, id) {
|
|
17138
|
+
copy.setAttribute("data-ohw-href-key", id);
|
|
17139
|
+
const label = labelElement2(copy);
|
|
17140
|
+
const labelKey = labelKeyForHrefKey(id);
|
|
17141
|
+
if (label) label.setAttribute("data-ohw-key", labelKey);
|
|
17142
|
+
setButtonDragAttr(copy);
|
|
17143
|
+
return { labelKey };
|
|
17144
|
+
}
|
|
17145
|
+
function stampVariantClass(el, variant) {
|
|
17146
|
+
const raw = typeof el.className === "string" ? el.className : el.getAttribute("class") || "";
|
|
17147
|
+
const without = raw.replace(/\bbtn--(?:primary|secondary|ghost)\b/g, "").replace(/\s+/g, " ").trim();
|
|
17148
|
+
el.className = without ? `${without} btn--${variant}` : `btn btn--${variant}`;
|
|
17149
|
+
}
|
|
17150
|
+
function snapshotOf(el) {
|
|
17151
|
+
const id = buttonId(el) ?? "";
|
|
17152
|
+
const label = labelElement2(el);
|
|
17153
|
+
return {
|
|
17154
|
+
id,
|
|
17155
|
+
href: buttonHref(el),
|
|
17156
|
+
label: buttonLabel(el),
|
|
17157
|
+
labelKey: label?.getAttribute("data-ohw-key") ?? labelKeyForHrefKey(id),
|
|
17158
|
+
html: cleanClone(el).outerHTML
|
|
17159
|
+
};
|
|
17160
|
+
}
|
|
17161
|
+
function htmlToElement(doc, html) {
|
|
17162
|
+
const wrap = doc.createElement("div");
|
|
17163
|
+
wrap.innerHTML = html;
|
|
17164
|
+
const el = wrap.firstElementChild;
|
|
17165
|
+
return el instanceof HTMLElement ? el : null;
|
|
17166
|
+
}
|
|
17167
|
+
function findButton(doc, id) {
|
|
17168
|
+
return doc.querySelector(`[data-ohw-href-key="${CSS.escape(id)}"]`);
|
|
17169
|
+
}
|
|
17170
|
+
function duplicateButton(source, content) {
|
|
17171
|
+
if (!canDuplicateButton(source)) return null;
|
|
17172
|
+
const sourceId = buttonId(source);
|
|
17173
|
+
if (!sourceId) return null;
|
|
17174
|
+
const doc = source.ownerDocument;
|
|
17175
|
+
const tokens = tokensFromButton(source);
|
|
17176
|
+
const copyId = nextCopyId(sourceId, content, doc);
|
|
17177
|
+
const copy = cleanClone(source);
|
|
17178
|
+
const { labelKey } = rekeyCopy(copy, copyId);
|
|
17179
|
+
const href = buttonHref(source);
|
|
17180
|
+
const label = buttonLabel(source);
|
|
17181
|
+
if (href) copy.setAttribute("href", href);
|
|
17182
|
+
const sourceAssignment = readAssignments(content)[sourceId] ?? assignmentFor(source, content, tokens);
|
|
17183
|
+
const copyAssignment = {
|
|
17184
|
+
variant: "secondary",
|
|
17185
|
+
size: sourceAssignment.size
|
|
17186
|
+
};
|
|
17187
|
+
stampVariantClass(copy, "secondary");
|
|
17188
|
+
applyButtonStyle(copy, copyAssignment, tokens);
|
|
17189
|
+
const copyLabelEl = labelElement2(copy);
|
|
17190
|
+
if (copyLabelEl) copyLabelEl.textContent = label;
|
|
17191
|
+
let collection = buttonCollectionOf(source);
|
|
17192
|
+
const collections = readCollections(content);
|
|
17193
|
+
let collectionId = collection?.getAttribute(COLLECTION_ATTR) ?? "";
|
|
17194
|
+
let members = collectionId && collections[collectionId] ? [...collections[collectionId].members] : [];
|
|
17195
|
+
const gap = collectionGap(source, tokens);
|
|
17196
|
+
if (!collection) {
|
|
17197
|
+
collectionId = nextCollectionId(content, doc);
|
|
17198
|
+
collection = createCollection(doc, collectionId, gap);
|
|
17199
|
+
source.parentElement?.insertBefore(collection, source);
|
|
17200
|
+
collection.append(source, copy);
|
|
17201
|
+
setButtonDragAttr(source);
|
|
17202
|
+
setButtonDragAttr(copy);
|
|
17203
|
+
members = [sourceId, copyId];
|
|
17204
|
+
} else {
|
|
17205
|
+
styleCollection(collection, gap);
|
|
17206
|
+
source.after(copy);
|
|
17207
|
+
setButtonDragAttr(copy);
|
|
17208
|
+
if (!members.includes(sourceId)) members = listCollectionMembers(collection);
|
|
17209
|
+
const at = members.indexOf(sourceId);
|
|
17210
|
+
members.splice(at >= 0 ? at + 1 : members.length, 0, copyId);
|
|
17211
|
+
}
|
|
17212
|
+
const sourceLabelKey = labelElement2(source)?.getAttribute("data-ohw-key");
|
|
17213
|
+
const snapshots = {
|
|
17214
|
+
...readSnapshots(content),
|
|
17215
|
+
[sourceId]: snapshotOf(source),
|
|
17216
|
+
[copyId]: snapshotOf(copy)
|
|
17217
|
+
};
|
|
17218
|
+
const nextCollections = {
|
|
17219
|
+
...collections,
|
|
17220
|
+
[collectionId]: { id: collectionId, members, gap }
|
|
17221
|
+
};
|
|
17222
|
+
const assignments = withAssignment(content, copyId, copyAssignment);
|
|
17223
|
+
const nextContent = {
|
|
17224
|
+
...content,
|
|
17225
|
+
[copyId]: href,
|
|
17226
|
+
[labelKey]: label,
|
|
17227
|
+
[BUTTON_COLLECTIONS_KEY]: JSON.stringify(nextCollections),
|
|
17228
|
+
[BUTTON_SNAPSHOTS_KEY]: JSON.stringify(snapshots),
|
|
17229
|
+
[BUTTON_ASSIGNMENTS_KEY]: JSON.stringify(assignments)
|
|
17230
|
+
};
|
|
17231
|
+
if (sourceLabelKey && nextContent[sourceLabelKey] === void 0) {
|
|
17232
|
+
nextContent[sourceLabelKey] = label;
|
|
17233
|
+
}
|
|
17234
|
+
const nodeKeys = [
|
|
17235
|
+
copyId,
|
|
17236
|
+
labelKey,
|
|
17237
|
+
BUTTON_COLLECTIONS_KEY,
|
|
17238
|
+
BUTTON_SNAPSHOTS_KEY,
|
|
17239
|
+
BUTTON_ASSIGNMENTS_KEY
|
|
17240
|
+
];
|
|
17241
|
+
if (sourceLabelKey) nodeKeys.push(sourceLabelKey);
|
|
17242
|
+
return {
|
|
17243
|
+
copy,
|
|
17244
|
+
content: nextContent,
|
|
17245
|
+
nodes: contentNodes(nextContent, nodeKeys)
|
|
17246
|
+
};
|
|
17247
|
+
}
|
|
17248
|
+
function listCollectionMembers(collection) {
|
|
17249
|
+
return Array.from(collection.querySelectorAll(CTA_BUTTON_SELECTOR)).map((el) => buttonId(el)).filter((id) => Boolean(id));
|
|
17250
|
+
}
|
|
17251
|
+
function contentNodes(content, keys) {
|
|
17252
|
+
return keys.filter((key) => content[key] !== void 0).map((key) => ({ key, text: content[key] }));
|
|
17253
|
+
}
|
|
17254
|
+
function deleteButton(source, content) {
|
|
17255
|
+
if (!canDeleteButton(source)) return null;
|
|
17256
|
+
const id = buttonId(source);
|
|
17257
|
+
if (!id) return null;
|
|
17258
|
+
const parent = source.parentElement;
|
|
17259
|
+
const nextSibling = source.nextSibling;
|
|
17260
|
+
const removed = source;
|
|
17261
|
+
const collection = buttonCollectionOf(source);
|
|
17262
|
+
const collectionId = collection?.getAttribute(COLLECTION_ATTR) ?? "";
|
|
17263
|
+
const previousCollections = readCollections(content);
|
|
17264
|
+
const previousHidden = readHiddenButtons(content);
|
|
17265
|
+
const snapshots = { ...readSnapshots(content) };
|
|
17266
|
+
const assignments = { ...readAssignments(content) };
|
|
17267
|
+
delete assignments[id];
|
|
17268
|
+
const remainingBeforeUnwrap = collection ? listCollectionMembers(collection).filter((member) => member !== id) : [];
|
|
17269
|
+
removed.remove();
|
|
17270
|
+
let nextCollections = { ...previousCollections };
|
|
17271
|
+
let unwrapped = null;
|
|
17272
|
+
if (collection && collectionId) {
|
|
17273
|
+
const members = listCollectionMembers(collection);
|
|
17274
|
+
if (members.length <= 1) {
|
|
17275
|
+
unwrapped = collection;
|
|
17276
|
+
unwrapCollection(collection);
|
|
17277
|
+
delete nextCollections[collectionId];
|
|
17278
|
+
} else {
|
|
17279
|
+
nextCollections[collectionId] = {
|
|
17280
|
+
id: collectionId,
|
|
17281
|
+
members,
|
|
17282
|
+
gap: collection.style.gap || previousCollections[collectionId]?.gap || "12px"
|
|
17283
|
+
};
|
|
17284
|
+
}
|
|
17285
|
+
}
|
|
17286
|
+
const hidden = previousHidden.includes(id) ? previousHidden : [...previousHidden, id];
|
|
17287
|
+
const nextContent = {
|
|
17288
|
+
...content,
|
|
17289
|
+
[id]: "",
|
|
17290
|
+
[BUTTON_COLLECTIONS_KEY]: JSON.stringify(nextCollections),
|
|
17291
|
+
[BUTTON_HIDDEN_KEY]: JSON.stringify(hidden),
|
|
17292
|
+
[BUTTON_SNAPSHOTS_KEY]: JSON.stringify(snapshots),
|
|
17293
|
+
[BUTTON_ASSIGNMENTS_KEY]: JSON.stringify(assignments)
|
|
17294
|
+
};
|
|
17295
|
+
return {
|
|
17296
|
+
content: nextContent,
|
|
17297
|
+
nodes: contentNodes(nextContent, [id, BUTTON_COLLECTIONS_KEY, BUTTON_HIDDEN_KEY, BUTTON_SNAPSHOTS_KEY, BUTTON_ASSIGNMENTS_KEY]),
|
|
17298
|
+
undo: () => {
|
|
17299
|
+
if (unwrapped && remainingBeforeUnwrap.length === 1) {
|
|
17300
|
+
const remaining = findButton(removed.ownerDocument, remainingBeforeUnwrap[0]);
|
|
17301
|
+
const host = remaining?.parentElement;
|
|
17302
|
+
if (remaining && host) {
|
|
17303
|
+
const restoredCollection = createCollection(
|
|
17304
|
+
removed.ownerDocument,
|
|
17305
|
+
collectionId,
|
|
17306
|
+
previousCollections[collectionId]?.gap || "12px"
|
|
17307
|
+
);
|
|
17308
|
+
host.insertBefore(restoredCollection, remaining);
|
|
17309
|
+
restoredCollection.append(remaining, removed);
|
|
17310
|
+
return;
|
|
17311
|
+
}
|
|
17312
|
+
}
|
|
17313
|
+
if (nextSibling && nextSibling.parentNode === parent) parent?.insertBefore(removed, nextSibling);
|
|
17314
|
+
else parent?.appendChild(removed);
|
|
17315
|
+
}
|
|
17316
|
+
};
|
|
17317
|
+
}
|
|
17318
|
+
function unwrapCollection(collection) {
|
|
17319
|
+
const parent = collection.parentElement;
|
|
17320
|
+
if (!parent) return;
|
|
17321
|
+
while (collection.firstChild) parent.insertBefore(collection.firstChild, collection);
|
|
17322
|
+
collection.remove();
|
|
17323
|
+
}
|
|
17324
|
+
function reorderButtonInCollection(button, clientX) {
|
|
17325
|
+
const collection = buttonCollectionOf(button);
|
|
17326
|
+
const id = buttonId(button);
|
|
17327
|
+
if (!collection || !id) return null;
|
|
17328
|
+
const siblings = Array.from(collection.querySelectorAll(CTA_BUTTON_SELECTOR)).filter((el) => el !== button);
|
|
17329
|
+
let placed = false;
|
|
17330
|
+
for (const sibling of siblings) {
|
|
17331
|
+
const rect = sibling.getBoundingClientRect();
|
|
17332
|
+
if (clientX < rect.left + rect.width / 2) {
|
|
17333
|
+
sibling.before(button);
|
|
17334
|
+
placed = true;
|
|
17335
|
+
break;
|
|
17336
|
+
}
|
|
17337
|
+
}
|
|
17338
|
+
if (!placed) collection.append(button);
|
|
17339
|
+
return listCollectionMembers(collection);
|
|
17340
|
+
}
|
|
17341
|
+
function listVisibleCollectionButtons(collection) {
|
|
17342
|
+
return Array.from(collection.querySelectorAll(CTA_BUTTON_SELECTOR)).filter((el) => {
|
|
17343
|
+
if (!buttonId(el)) return false;
|
|
17344
|
+
return el.getClientRects().length > 0;
|
|
17345
|
+
});
|
|
17346
|
+
}
|
|
17347
|
+
function isVerticalButtonLayout(items, collection) {
|
|
17348
|
+
if (items.length >= 2) {
|
|
17349
|
+
const a = items[0].getBoundingClientRect();
|
|
17350
|
+
const b = items[1].getBoundingClientRect();
|
|
17351
|
+
return b.top - a.bottom > b.left - a.right;
|
|
17352
|
+
}
|
|
17353
|
+
const style = window.getComputedStyle(collection);
|
|
17354
|
+
return style.flexDirection === "column" || style.flexDirection === "column-reverse";
|
|
17355
|
+
}
|
|
17356
|
+
function buildButtonCollectionDropSlots(collection) {
|
|
17357
|
+
const items = listVisibleCollectionButtons(collection);
|
|
17358
|
+
const barThickness = 3;
|
|
17359
|
+
const slots = [];
|
|
17360
|
+
if (items.length === 0) {
|
|
17361
|
+
const rect = collection.getBoundingClientRect();
|
|
17362
|
+
slots.push({
|
|
17363
|
+
insertIndex: 0,
|
|
17364
|
+
left: rect.left + rect.width / 2 - barThickness / 2,
|
|
17365
|
+
top: rect.top,
|
|
17366
|
+
width: barThickness,
|
|
17367
|
+
height: Math.max(rect.height, 24),
|
|
17368
|
+
direction: "vertical"
|
|
17369
|
+
});
|
|
17370
|
+
return slots;
|
|
17371
|
+
}
|
|
17372
|
+
if (isVerticalButtonLayout(items, collection)) {
|
|
17373
|
+
const edgeGap2 = items.length >= 2 ? Math.max(0, items[1].getBoundingClientRect().top - items[0].getBoundingClientRect().bottom) : 16;
|
|
17374
|
+
for (let i = 0; i <= items.length; i++) {
|
|
17375
|
+
let top;
|
|
17376
|
+
let left;
|
|
17377
|
+
let width;
|
|
17378
|
+
if (i === 0) {
|
|
17379
|
+
const first = items[0].getBoundingClientRect();
|
|
17380
|
+
top = first.top - edgeGap2 / 2 - barThickness / 2;
|
|
17381
|
+
left = first.left;
|
|
17382
|
+
width = first.width;
|
|
17383
|
+
} else if (i === items.length) {
|
|
17384
|
+
const last = items[items.length - 1].getBoundingClientRect();
|
|
17385
|
+
const lastGap = items.length >= 2 ? Math.max(0, last.top - items[items.length - 2].getBoundingClientRect().bottom) : edgeGap2;
|
|
17386
|
+
top = last.bottom + lastGap / 2 - barThickness / 2;
|
|
17387
|
+
left = last.left;
|
|
17388
|
+
width = last.width;
|
|
17389
|
+
} else {
|
|
17390
|
+
const prev = items[i - 1].getBoundingClientRect();
|
|
17391
|
+
const next = items[i].getBoundingClientRect();
|
|
17392
|
+
top = (prev.bottom + next.top) / 2 - barThickness / 2;
|
|
17393
|
+
left = Math.min(prev.left, next.left);
|
|
17394
|
+
width = Math.max(prev.right, next.right) - left;
|
|
17395
|
+
}
|
|
17396
|
+
slots.push({
|
|
17397
|
+
insertIndex: i,
|
|
17398
|
+
left,
|
|
17399
|
+
top,
|
|
17400
|
+
width: Math.max(width, 40),
|
|
17401
|
+
height: barThickness,
|
|
17402
|
+
direction: "horizontal"
|
|
17403
|
+
});
|
|
17404
|
+
}
|
|
17405
|
+
return slots;
|
|
17406
|
+
}
|
|
17407
|
+
const edgeGap = items.length >= 2 ? Math.max(0, items[1].getBoundingClientRect().left - items[0].getBoundingClientRect().right) : 12;
|
|
17408
|
+
for (let i = 0; i <= items.length; i++) {
|
|
17409
|
+
let left;
|
|
17410
|
+
let top;
|
|
17411
|
+
let height;
|
|
17412
|
+
if (i === 0) {
|
|
17413
|
+
const first = items[0].getBoundingClientRect();
|
|
17414
|
+
left = first.left - edgeGap / 2 - barThickness / 2;
|
|
17415
|
+
top = first.top;
|
|
17416
|
+
height = first.height;
|
|
17417
|
+
} else if (i === items.length) {
|
|
17418
|
+
const last = items[items.length - 1].getBoundingClientRect();
|
|
17419
|
+
const lastGap = items.length >= 2 ? Math.max(0, last.left - items[items.length - 2].getBoundingClientRect().right) : edgeGap;
|
|
17420
|
+
left = last.right + lastGap / 2 - barThickness / 2;
|
|
17421
|
+
top = last.top;
|
|
17422
|
+
height = last.height;
|
|
17423
|
+
} else {
|
|
17424
|
+
const prev = items[i - 1].getBoundingClientRect();
|
|
17425
|
+
const next = items[i].getBoundingClientRect();
|
|
17426
|
+
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
17427
|
+
top = Math.min(prev.top, next.top);
|
|
17428
|
+
height = Math.max(prev.bottom, next.bottom) - top;
|
|
17429
|
+
}
|
|
17430
|
+
slots.push({
|
|
17431
|
+
insertIndex: i,
|
|
17432
|
+
left,
|
|
17433
|
+
top,
|
|
17434
|
+
width: barThickness,
|
|
17435
|
+
height: Math.max(height, 24),
|
|
17436
|
+
direction: "vertical"
|
|
17437
|
+
});
|
|
17438
|
+
}
|
|
17439
|
+
return slots;
|
|
17440
|
+
}
|
|
17441
|
+
function hitTestButtonCollectionDropSlot(collection, clientX, clientY) {
|
|
17442
|
+
const slots = buildButtonCollectionDropSlots(collection);
|
|
17443
|
+
let best = null;
|
|
17444
|
+
for (const slot of slots) {
|
|
17445
|
+
const cx2 = slot.left + slot.width / 2;
|
|
17446
|
+
const cy = slot.top + slot.height / 2;
|
|
17447
|
+
const dist = slot.direction === "vertical" ? Math.abs(clientX - cx2) + Math.abs(clientY - cy) * 0.25 : Math.abs(clientY - cy) + Math.abs(clientX - cx2) * 0.25;
|
|
17448
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
17449
|
+
}
|
|
17450
|
+
return best?.slot ?? null;
|
|
17451
|
+
}
|
|
17452
|
+
function insertButtonAtCollectionIndex(button, insertIndex) {
|
|
17453
|
+
const collection = buttonCollectionOf(button);
|
|
17454
|
+
if (!collection) return null;
|
|
17455
|
+
const items = listVisibleCollectionButtons(collection);
|
|
17456
|
+
const from = items.indexOf(button);
|
|
17457
|
+
if (from < 0) return null;
|
|
17458
|
+
const others = items.filter((el) => el !== button);
|
|
17459
|
+
let index = insertIndex;
|
|
17460
|
+
if (from < insertIndex) index -= 1;
|
|
17461
|
+
if (index <= 0) {
|
|
17462
|
+
const first = others[0];
|
|
17463
|
+
if (first) first.before(button);
|
|
17464
|
+
else collection.append(button);
|
|
17465
|
+
} else if (index >= others.length) {
|
|
17466
|
+
collection.append(button);
|
|
17467
|
+
} else {
|
|
17468
|
+
others[index].before(button);
|
|
17469
|
+
}
|
|
17470
|
+
return listCollectionMembers(collection);
|
|
17471
|
+
}
|
|
17472
|
+
function persistCollectionOrder(collection, content) {
|
|
17473
|
+
const id = collection.getAttribute(COLLECTION_ATTR);
|
|
17474
|
+
if (!id) return null;
|
|
17475
|
+
const collections = readCollections(content);
|
|
17476
|
+
const current = collections[id];
|
|
17477
|
+
const members = listCollectionMembers(collection);
|
|
17478
|
+
const next = {
|
|
17479
|
+
...collections,
|
|
17480
|
+
[id]: { id, members, gap: collection.style.gap || current?.gap || "12px" }
|
|
17481
|
+
};
|
|
17482
|
+
const nextContent = { ...content, [BUTTON_COLLECTIONS_KEY]: JSON.stringify(next) };
|
|
17483
|
+
return { content: nextContent, nodes: [{ key: BUTTON_COLLECTIONS_KEY, text: nextContent[BUTTON_COLLECTIONS_KEY] }] };
|
|
17484
|
+
}
|
|
17485
|
+
function hideButton(el) {
|
|
17486
|
+
if (el.getAttribute("data-ohw-button-hidden") === "") return;
|
|
17487
|
+
el.setAttribute("data-ohw-button-hidden", "");
|
|
17488
|
+
el.style.display = "none";
|
|
17489
|
+
}
|
|
17490
|
+
function syncButtonsFromContent(doc, content) {
|
|
17491
|
+
reconcileButtonCollections(doc, content);
|
|
17492
|
+
applyButtonContentFromContent(doc, content);
|
|
17493
|
+
applyButtonStylesFromContent(doc, content);
|
|
17494
|
+
}
|
|
17495
|
+
function applyButtonContentFromContent(doc, content) {
|
|
17496
|
+
const snapshots = readSnapshots(content);
|
|
17497
|
+
for (const snapshot of Object.values(snapshots)) {
|
|
17498
|
+
const el = findButton(doc, snapshot.id);
|
|
17499
|
+
if (!el) continue;
|
|
17500
|
+
applySnapshotContent(el, snapshot, content);
|
|
17501
|
+
}
|
|
17502
|
+
}
|
|
17503
|
+
function applySnapshotContent(el, snapshot, content) {
|
|
17504
|
+
const href = content[snapshot.id] ?? snapshot.href;
|
|
17505
|
+
if (href) el.setAttribute("href", href);
|
|
17506
|
+
const labelKey = snapshot.labelKey || labelKeyForHrefKey(snapshot.id);
|
|
17507
|
+
if (labelKey && !el.querySelector(`[data-ohw-key="${CSS.escape(labelKey)}"]`)) {
|
|
17508
|
+
const label2 = labelElement2(el);
|
|
17509
|
+
if (label2) label2.setAttribute("data-ohw-key", labelKey);
|
|
17510
|
+
}
|
|
17511
|
+
const text = content[labelKey];
|
|
17512
|
+
if (text === void 0) return;
|
|
17513
|
+
const label = labelElement2(el);
|
|
17514
|
+
if (label) {
|
|
17515
|
+
if (label.getAttribute("data-ohw-key") !== labelKey) label.setAttribute("data-ohw-key", labelKey);
|
|
17516
|
+
if (label.textContent !== text) label.textContent = text;
|
|
17517
|
+
}
|
|
17518
|
+
}
|
|
17519
|
+
function reconcileButtonCollections(doc, content) {
|
|
17520
|
+
const hidden = new Set(readHiddenButtons(content));
|
|
17521
|
+
for (const id of hidden) {
|
|
17522
|
+
const el = findButton(doc, id);
|
|
17523
|
+
if (el) hideButton(el);
|
|
17524
|
+
}
|
|
17525
|
+
const snapshots = readSnapshots(content);
|
|
17526
|
+
const collections = readCollections(content);
|
|
17527
|
+
for (const collectionState of Object.values(collections)) {
|
|
17528
|
+
const live = collectionState.members.map((id) => findButton(doc, id) ?? restoreSnapshot(doc, snapshots[id], content)).filter((el) => Boolean(el && !hidden.has(buttonId(el) ?? "")));
|
|
17529
|
+
if (live.length === 0) continue;
|
|
17530
|
+
if (live.length === 1) {
|
|
17531
|
+
const existing = buttonCollectionOf(live[0]);
|
|
17532
|
+
if (existing) unwrapCollection(existing);
|
|
17533
|
+
continue;
|
|
17534
|
+
}
|
|
17535
|
+
const anchor = live.find((el) => el.isConnected) ?? live[0];
|
|
17536
|
+
let collection = live.map((el) => buttonCollectionOf(el)).find((el) => el?.getAttribute(COLLECTION_ATTR) === collectionState.id) ?? null;
|
|
17537
|
+
if (!collection) {
|
|
17538
|
+
if (!anchor.parentElement) continue;
|
|
17539
|
+
collection = createCollection(doc, collectionState.id, collectionState.gap);
|
|
17540
|
+
anchor.parentElement.insertBefore(collection, anchor);
|
|
17541
|
+
}
|
|
17542
|
+
styleCollection(collection, collectionState.gap);
|
|
17543
|
+
const current = listCollectionMembers(collection);
|
|
17544
|
+
const sameOrder = current.length === live.length && current.every((id, index) => id === buttonId(live[index]));
|
|
17545
|
+
if (!sameOrder) {
|
|
17546
|
+
for (const member of live) collection.append(member);
|
|
17547
|
+
}
|
|
17548
|
+
for (const member of live) setButtonDragAttr(member);
|
|
17549
|
+
}
|
|
17550
|
+
}
|
|
17551
|
+
function restoreSnapshot(doc, snapshot, content) {
|
|
17552
|
+
if (!snapshot) return null;
|
|
17553
|
+
const existing = findButton(doc, snapshot.id);
|
|
17554
|
+
if (existing) {
|
|
17555
|
+
applySnapshotContent(existing, snapshot, content);
|
|
17556
|
+
return existing;
|
|
17557
|
+
}
|
|
17558
|
+
const el = htmlToElement(doc, snapshot.html);
|
|
17559
|
+
if (!el) return null;
|
|
17560
|
+
el.setAttribute("data-ohw-href-key", snapshot.id);
|
|
17561
|
+
const label = labelElement2(el);
|
|
17562
|
+
const labelKey = snapshot.labelKey || labelKeyForHrefKey(snapshot.id);
|
|
17563
|
+
if (label) label.setAttribute("data-ohw-key", labelKey);
|
|
17564
|
+
applySnapshotContent(el, snapshot, content);
|
|
17565
|
+
setButtonDragAttr(el);
|
|
17566
|
+
return el;
|
|
17567
|
+
}
|
|
17568
|
+
function navbarCtasInScope(el) {
|
|
17569
|
+
const scope = el.closest("nav, [data-ohw-nav-root], [data-ohw-nav-drawer]") ?? el.parentElement;
|
|
17570
|
+
if (!scope) return [];
|
|
17571
|
+
return Array.from(scope.querySelectorAll(CTA_BUTTON_SELECTOR)).filter(
|
|
17572
|
+
(button) => isNavbarCta(button) && buttonId(button)
|
|
17573
|
+
);
|
|
17574
|
+
}
|
|
17575
|
+
function ensureNavbarButtonCollection(button, content) {
|
|
17576
|
+
const existing = buttonCollectionOf(button);
|
|
17577
|
+
if (existing) return existing;
|
|
17578
|
+
if (!isNavbarCta(button) || !buttonId(button)) return null;
|
|
17579
|
+
const parent = button.parentElement;
|
|
17580
|
+
if (!parent) return null;
|
|
17581
|
+
const siblings = navbarCtasInScope(button).filter((el) => el.parentElement === parent);
|
|
17582
|
+
if (siblings.length < 2) return null;
|
|
17583
|
+
const id = nextCollectionId(content, button.ownerDocument);
|
|
17584
|
+
const collection = createCollection(button.ownerDocument, id, collectionGap(button, tokensFromButton(button)));
|
|
17585
|
+
siblings[0].before(collection);
|
|
17586
|
+
for (const member of siblings) {
|
|
17587
|
+
collection.append(member);
|
|
17588
|
+
setButtonDragAttr(member);
|
|
17589
|
+
}
|
|
17590
|
+
return collection;
|
|
17591
|
+
}
|
|
17592
|
+
function collectionDragEnabled(el) {
|
|
17593
|
+
if (!isNavbarCta(el) || !buttonId(el)) return false;
|
|
17594
|
+
if (buttonCollectionOf(el)) return true;
|
|
17595
|
+
return navbarCtasInScope(el).length >= 2;
|
|
17596
|
+
}
|
|
17597
|
+
|
|
17598
|
+
// src/lib/item-drag-interaction.ts
|
|
17599
|
+
function disableNativeHrefDrag(el) {
|
|
17600
|
+
if (el.draggable) el.draggable = false;
|
|
17601
|
+
if (el.getAttribute("draggable") !== "false") {
|
|
17602
|
+
el.setAttribute("draggable", "false");
|
|
17603
|
+
}
|
|
17604
|
+
}
|
|
17605
|
+
function clearTextSelection() {
|
|
17606
|
+
const sel = window.getSelection();
|
|
17607
|
+
if (sel && !sel.isCollapsed) sel.removeAllRanges();
|
|
17608
|
+
}
|
|
17609
|
+
function armItemPressDrag() {
|
|
17610
|
+
document.documentElement.setAttribute("data-ohw-footer-press-drag", "");
|
|
17611
|
+
}
|
|
17612
|
+
function lockItemDuringDrag() {
|
|
17613
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
17614
|
+
document.documentElement.setAttribute("data-ohw-item-dragging", "");
|
|
17615
|
+
clearTextSelection();
|
|
17616
|
+
}
|
|
17617
|
+
function unlockItemDragInteraction() {
|
|
17618
|
+
const wasDragging = document.documentElement.hasAttribute("data-ohw-item-dragging");
|
|
17619
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
17620
|
+
document.documentElement.removeAttribute("data-ohw-item-dragging");
|
|
17621
|
+
if (wasDragging) clearTextSelection();
|
|
17622
|
+
}
|
|
17623
|
+
var armFooterPressDrag = armItemPressDrag;
|
|
17624
|
+
var lockFooterDuringDrag = lockItemDuringDrag;
|
|
17625
|
+
var unlockFooterDragInteraction = unlockItemDragInteraction;
|
|
17626
|
+
|
|
17627
|
+
// src/lib/nav-dnd.ts
|
|
17628
|
+
function listReorderableNavItems(draggedEl) {
|
|
17629
|
+
return listActiveNavbarItems(draggedEl).filter((el) => {
|
|
17630
|
+
const key = el.getAttribute("data-ohw-href-key");
|
|
17631
|
+
return isNavbarHrefKey(key) && !isNestedNavChild(el);
|
|
17632
|
+
});
|
|
17633
|
+
}
|
|
17634
|
+
function resolveParentNavHrefKey(child) {
|
|
17635
|
+
const childrenRoot = child.closest("[data-ohw-nav-children]");
|
|
17636
|
+
const group = childrenRoot?.closest("[data-ohw-nav-group]");
|
|
17637
|
+
if (!group) return null;
|
|
17638
|
+
const trigger = group.querySelector(":scope > [data-ohw-href-key]") ?? Array.from(group.querySelectorAll("[data-ohw-href-key]")).find(
|
|
17639
|
+
(el) => !el.closest("[data-ohw-nav-children]")
|
|
17640
|
+
) ?? null;
|
|
17641
|
+
const key = trigger?.getAttribute("data-ohw-href-key");
|
|
17642
|
+
return key && isNavbarHrefKey(key) ? key : null;
|
|
17643
|
+
}
|
|
17644
|
+
function listNavChildren(parentHrefKey, draggedEl) {
|
|
17645
|
+
const items = listActiveNavbarItems(draggedEl);
|
|
17646
|
+
const parent = items.find((el) => el.getAttribute("data-ohw-href-key") === parentHrefKey);
|
|
17647
|
+
if (!parent) return [];
|
|
17648
|
+
const group = parent.closest("[data-ohw-nav-group]");
|
|
17649
|
+
const childrenRoot = group?.querySelector(":scope > [data-ohw-nav-children]");
|
|
17650
|
+
if (!childrenRoot) return [];
|
|
17651
|
+
return Array.from(childrenRoot.querySelectorAll(":scope > [data-ohw-href-key]")).filter(
|
|
17652
|
+
(el) => isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))
|
|
17653
|
+
);
|
|
17654
|
+
}
|
|
17655
|
+
function isVerticalNavLayout(items, draggedEl) {
|
|
17656
|
+
const visible = items.filter((el) => el.getClientRects().length > 0);
|
|
17657
|
+
if (visible.length >= 2) {
|
|
17658
|
+
const a = visible[0].getBoundingClientRect();
|
|
17659
|
+
const b = visible[1].getBoundingClientRect();
|
|
17660
|
+
const verticalGap = b.top - a.bottom;
|
|
17661
|
+
const horizontalGap = b.left - a.right;
|
|
17662
|
+
return verticalGap > horizontalGap;
|
|
17663
|
+
}
|
|
17664
|
+
const container = getActiveNavbarListContainer(draggedEl);
|
|
17665
|
+
if (!container) return false;
|
|
17666
|
+
const style = window.getComputedStyle(container);
|
|
17667
|
+
return style.flexDirection === "column" || style.flexDirection === "column-reverse";
|
|
17668
|
+
}
|
|
17669
|
+
function buildVerticalRootNavDropSlots(items, draggedEl) {
|
|
17670
|
+
const slots = [];
|
|
17671
|
+
const barThickness = 3;
|
|
17672
|
+
if (items.length === 0) {
|
|
17673
|
+
const container = getActiveNavbarListContainer(draggedEl);
|
|
17674
|
+
if (!container) return slots;
|
|
17675
|
+
const rect = container.getBoundingClientRect();
|
|
17676
|
+
slots.push({
|
|
17677
|
+
insertIndex: 0,
|
|
17678
|
+
parentId: null,
|
|
17679
|
+
left: rect.left,
|
|
17680
|
+
top: rect.top + rect.height / 2 - barThickness / 2,
|
|
17681
|
+
width: Math.max(rect.width, 40),
|
|
17682
|
+
height: barThickness,
|
|
17683
|
+
direction: "horizontal"
|
|
17684
|
+
});
|
|
17685
|
+
return slots;
|
|
17686
|
+
}
|
|
17687
|
+
const edgeGap = (() => {
|
|
17688
|
+
if (items.length < 2) return 16;
|
|
17689
|
+
const a = items[0].getBoundingClientRect();
|
|
17690
|
+
const b = items[1].getBoundingClientRect();
|
|
17691
|
+
return Math.max(0, b.top - a.bottom);
|
|
17692
|
+
})();
|
|
17693
|
+
for (let i = 0; i <= items.length; i++) {
|
|
17694
|
+
let top;
|
|
17695
|
+
let width;
|
|
17696
|
+
let left;
|
|
17697
|
+
if (i === 0) {
|
|
17698
|
+
const first = items[0].getBoundingClientRect();
|
|
17699
|
+
top = first.top - edgeGap / 2 - barThickness / 2;
|
|
17700
|
+
left = first.left;
|
|
17701
|
+
width = first.width;
|
|
17702
|
+
} else if (i === items.length) {
|
|
17703
|
+
const last = items[items.length - 1].getBoundingClientRect();
|
|
17704
|
+
const lastGap = items.length >= 2 ? Math.max(0, last.top - items[items.length - 2].getBoundingClientRect().bottom) : edgeGap;
|
|
17705
|
+
top = last.bottom + lastGap / 2 - barThickness / 2;
|
|
17706
|
+
left = last.left;
|
|
17707
|
+
width = last.width;
|
|
17708
|
+
} else {
|
|
17709
|
+
const prev = items[i - 1].getBoundingClientRect();
|
|
17710
|
+
const next = items[i].getBoundingClientRect();
|
|
17711
|
+
top = (prev.bottom + next.top) / 2 - barThickness / 2;
|
|
17712
|
+
left = Math.min(prev.left, next.left);
|
|
17713
|
+
width = Math.max(prev.right, next.right) - left;
|
|
17714
|
+
}
|
|
17715
|
+
slots.push({
|
|
17716
|
+
insertIndex: i,
|
|
17717
|
+
parentId: null,
|
|
17718
|
+
left,
|
|
17719
|
+
top,
|
|
17720
|
+
width: Math.max(width, 40),
|
|
17721
|
+
height: barThickness,
|
|
17722
|
+
direction: "horizontal"
|
|
17723
|
+
});
|
|
17724
|
+
}
|
|
17725
|
+
return slots;
|
|
17726
|
+
}
|
|
17727
|
+
function buildHorizontalRootNavDropSlots(items, draggedEl) {
|
|
17728
|
+
const slots = [];
|
|
17729
|
+
const barThickness = 3;
|
|
17730
|
+
if (items.length === 0) {
|
|
17731
|
+
const container = getActiveNavbarListContainer(draggedEl);
|
|
17732
|
+
if (!container) return slots;
|
|
17733
|
+
const rect = container.getBoundingClientRect();
|
|
17734
|
+
slots.push({
|
|
17735
|
+
insertIndex: 0,
|
|
17736
|
+
parentId: null,
|
|
17737
|
+
left: rect.left + rect.width / 2 - barThickness / 2,
|
|
17738
|
+
top: rect.top,
|
|
17739
|
+
width: barThickness,
|
|
17740
|
+
height: Math.max(rect.height, 24),
|
|
17741
|
+
direction: "vertical"
|
|
17742
|
+
});
|
|
17743
|
+
return slots;
|
|
17744
|
+
}
|
|
17745
|
+
const edgeGap = (() => {
|
|
17746
|
+
if (items.length < 2) return 32;
|
|
17747
|
+
const a = items[0].getBoundingClientRect();
|
|
17748
|
+
const b = items[1].getBoundingClientRect();
|
|
17749
|
+
return Math.max(0, b.left - a.right);
|
|
17750
|
+
})();
|
|
17751
|
+
for (let i = 0; i <= items.length; i++) {
|
|
17752
|
+
let left;
|
|
17753
|
+
let top;
|
|
17754
|
+
let height;
|
|
17755
|
+
if (i === 0) {
|
|
17756
|
+
const first = items[0].getBoundingClientRect();
|
|
17757
|
+
left = first.left - edgeGap / 2 - barThickness / 2;
|
|
17758
|
+
top = first.top;
|
|
17759
|
+
height = first.height;
|
|
17760
|
+
} else if (i === items.length) {
|
|
17761
|
+
const last = items[items.length - 1].getBoundingClientRect();
|
|
17762
|
+
const lastGap = items.length >= 2 ? Math.max(0, last.left - items[items.length - 2].getBoundingClientRect().right) : edgeGap;
|
|
17763
|
+
left = last.right + lastGap / 2 - barThickness / 2;
|
|
17764
|
+
top = last.top;
|
|
17765
|
+
height = last.height;
|
|
17766
|
+
} else {
|
|
17767
|
+
const prev = items[i - 1].getBoundingClientRect();
|
|
17768
|
+
const next = items[i].getBoundingClientRect();
|
|
17769
|
+
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
17770
|
+
top = Math.min(prev.top, next.top);
|
|
17771
|
+
height = Math.max(prev.bottom, next.bottom) - top;
|
|
17772
|
+
}
|
|
17773
|
+
slots.push({
|
|
17774
|
+
insertIndex: i,
|
|
17775
|
+
parentId: null,
|
|
17776
|
+
left,
|
|
17777
|
+
top,
|
|
17778
|
+
width: barThickness,
|
|
17779
|
+
height: Math.max(height, 24),
|
|
17780
|
+
direction: "vertical"
|
|
17781
|
+
});
|
|
17782
|
+
}
|
|
17783
|
+
return slots;
|
|
17784
|
+
}
|
|
17785
|
+
function buildRootNavDropSlots(draggedEl) {
|
|
17786
|
+
const items = listReorderableNavItems(draggedEl);
|
|
17787
|
+
if (isVerticalNavLayout(items, draggedEl)) {
|
|
17788
|
+
return buildVerticalRootNavDropSlots(items, draggedEl);
|
|
17789
|
+
}
|
|
17790
|
+
return buildHorizontalRootNavDropSlots(items, draggedEl);
|
|
17791
|
+
}
|
|
17792
|
+
function buildChildNavDropSlots(parentHrefKey, draggedEl) {
|
|
16257
17793
|
const children = listNavChildren(parentHrefKey, draggedEl);
|
|
16258
17794
|
const slots = [];
|
|
16259
17795
|
const barThickness = 3;
|
|
@@ -16488,7 +18024,7 @@ function useNavItemDrag({
|
|
|
16488
18024
|
document.querySelectorAll(
|
|
16489
18025
|
"nav [data-ohw-href-key], [data-ohw-nav-container] [data-ohw-href-key], [data-ohw-nav-drawer] [data-ohw-href-key]"
|
|
16490
18026
|
).forEach((el) => {
|
|
16491
|
-
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
18027
|
+
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key")) || isCtaButton(el)) {
|
|
16492
18028
|
disableNativeHrefDrag(el);
|
|
16493
18029
|
}
|
|
16494
18030
|
});
|
|
@@ -16797,12 +18333,6 @@ var SECTION_DRAG_EXCLUDED_SELECTOR = [
|
|
|
16797
18333
|
"[data-ohw-media-overlay]",
|
|
16798
18334
|
"[data-ohw-media-skeleton]"
|
|
16799
18335
|
].join(", ");
|
|
16800
|
-
function visibleClip(ps) {
|
|
16801
|
-
if (!ps) return null;
|
|
16802
|
-
const top = Math.max(0, ps.headerH - ps.iframeOffsetTop);
|
|
16803
|
-
const bottom = Math.min(window.innerHeight, ps.headerH + ps.canvasH - ps.iframeOffsetTop);
|
|
16804
|
-
return { top, bottom: Math.max(top, bottom) };
|
|
16805
|
-
}
|
|
16806
18336
|
function useSectionDrag({
|
|
16807
18337
|
isEditMode,
|
|
16808
18338
|
editContentRef,
|
|
@@ -16839,7 +18369,7 @@ function useSectionDrag({
|
|
|
16839
18369
|
}, [postToParentRef, stopAutoScroll]);
|
|
16840
18370
|
const updateAutoScroll = (0, import_react17.useCallback)(
|
|
16841
18371
|
(clientY) => {
|
|
16842
|
-
const clip =
|
|
18372
|
+
const clip = getIframeChromeClip(parentScrollRef.current);
|
|
16843
18373
|
let delta = 0;
|
|
16844
18374
|
if (clip) {
|
|
16845
18375
|
const distTop = clientY - clip.top;
|
|
@@ -17045,8 +18575,8 @@ function useSectionDrag({
|
|
|
17045
18575
|
}
|
|
17046
18576
|
|
|
17047
18577
|
// src/ui/footer-container-chrome.tsx
|
|
17048
|
-
var
|
|
17049
|
-
var
|
|
18578
|
+
var import_lucide_react18 = require("lucide-react");
|
|
18579
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
17050
18580
|
function FooterContainerChrome({
|
|
17051
18581
|
rect,
|
|
17052
18582
|
onAdd,
|
|
@@ -17054,7 +18584,7 @@ function FooterContainerChrome({
|
|
|
17054
18584
|
}) {
|
|
17055
18585
|
const chromeGap = 6;
|
|
17056
18586
|
const buttonMargin = 7;
|
|
17057
|
-
return /* @__PURE__ */ (0,
|
|
18587
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
17058
18588
|
"div",
|
|
17059
18589
|
{
|
|
17060
18590
|
"data-ohw-footer-container-chrome": "",
|
|
@@ -17066,8 +18596,8 @@ function FooterContainerChrome({
|
|
|
17066
18596
|
width: rect.width + chromeGap * 2,
|
|
17067
18597
|
height: rect.height + chromeGap * 2
|
|
17068
18598
|
},
|
|
17069
|
-
children: /* @__PURE__ */ (0,
|
|
17070
|
-
/* @__PURE__ */ (0,
|
|
18599
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Tooltip, { children: [
|
|
18600
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
17071
18601
|
"button",
|
|
17072
18602
|
{
|
|
17073
18603
|
type: "button",
|
|
@@ -17086,10 +18616,10 @@ function FooterContainerChrome({
|
|
|
17086
18616
|
if (addDisabled) return;
|
|
17087
18617
|
onAdd();
|
|
17088
18618
|
},
|
|
17089
|
-
children: /* @__PURE__ */ (0,
|
|
18619
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react18.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
17090
18620
|
}
|
|
17091
18621
|
) }),
|
|
17092
|
-
/* @__PURE__ */ (0,
|
|
18622
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
|
|
17093
18623
|
] })
|
|
17094
18624
|
}
|
|
17095
18625
|
) });
|
|
@@ -17251,7 +18781,14 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
17251
18781
|
// so collecting the DOM alone left them behind: the draft knew the row was showing icons and
|
|
17252
18782
|
// had gained an item, and the published page went back to the template's own (OHH-736).
|
|
17253
18783
|
SOCIALS_ORDER_KEY,
|
|
17254
|
-
SOCIALS_DISPLAY_KEY
|
|
18784
|
+
SOCIALS_DISPLAY_KEY,
|
|
18785
|
+
// Button variant/size tokens and per-CTA assignments — JSON in editContent, applied on hydrate.
|
|
18786
|
+
BUTTON_VARIANTS_KEY,
|
|
18787
|
+
BUTTON_SIZES_KEY,
|
|
18788
|
+
BUTTON_ASSIGNMENTS_KEY,
|
|
18789
|
+
BUTTON_COLLECTIONS_KEY,
|
|
18790
|
+
BUTTON_SNAPSHOTS_KEY,
|
|
18791
|
+
BUTTON_HIDDEN_KEY
|
|
17255
18792
|
]) {
|
|
17256
18793
|
const text = extraContent[key];
|
|
17257
18794
|
if (typeof text === "string" && text.length > 0) {
|
|
@@ -17571,14 +19108,14 @@ function deleteSelectedNavFooterItem(deps) {
|
|
|
17571
19108
|
}
|
|
17572
19109
|
|
|
17573
19110
|
// src/ui/navbar-container-chrome.tsx
|
|
17574
|
-
var
|
|
17575
|
-
var
|
|
19111
|
+
var import_lucide_react19 = require("lucide-react");
|
|
19112
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
17576
19113
|
function NavbarContainerChrome({
|
|
17577
19114
|
rect,
|
|
17578
19115
|
onAdd
|
|
17579
19116
|
}) {
|
|
17580
19117
|
const chromeGap = 6;
|
|
17581
|
-
return /* @__PURE__ */ (0,
|
|
19118
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17582
19119
|
"div",
|
|
17583
19120
|
{
|
|
17584
19121
|
"data-ohw-navbar-container-chrome": "",
|
|
@@ -17590,7 +19127,7 @@ function NavbarContainerChrome({
|
|
|
17590
19127
|
width: rect.width + chromeGap * 2,
|
|
17591
19128
|
height: rect.height + chromeGap * 2
|
|
17592
19129
|
},
|
|
17593
|
-
children: /* @__PURE__ */ (0,
|
|
19130
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
17594
19131
|
"button",
|
|
17595
19132
|
{
|
|
17596
19133
|
type: "button",
|
|
@@ -17607,7 +19144,7 @@ function NavbarContainerChrome({
|
|
|
17607
19144
|
e.stopPropagation();
|
|
17608
19145
|
onAdd();
|
|
17609
19146
|
},
|
|
17610
|
-
children: /* @__PURE__ */ (0,
|
|
19147
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react19.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
17611
19148
|
}
|
|
17612
19149
|
)
|
|
17613
19150
|
}
|
|
@@ -17616,7 +19153,7 @@ function NavbarContainerChrome({
|
|
|
17616
19153
|
|
|
17617
19154
|
// src/ui/drop-indicator.tsx
|
|
17618
19155
|
var React11 = __toESM(require("react"), 1);
|
|
17619
|
-
var
|
|
19156
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
17620
19157
|
var dropIndicatorVariants = cva(
|
|
17621
19158
|
"ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
|
|
17622
19159
|
{
|
|
@@ -17640,7 +19177,7 @@ var dropIndicatorVariants = cva(
|
|
|
17640
19177
|
);
|
|
17641
19178
|
var DropIndicator = React11.forwardRef(
|
|
17642
19179
|
({ className, direction, state, ...props }, ref) => {
|
|
17643
|
-
return /* @__PURE__ */ (0,
|
|
19180
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
17644
19181
|
"div",
|
|
17645
19182
|
{
|
|
17646
19183
|
ref,
|
|
@@ -17657,7 +19194,7 @@ var DropIndicator = React11.forwardRef(
|
|
|
17657
19194
|
DropIndicator.displayName = "DropIndicator";
|
|
17658
19195
|
|
|
17659
19196
|
// src/ui/badge.tsx
|
|
17660
|
-
var
|
|
19197
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
17661
19198
|
var badgeVariants = cva(
|
|
17662
19199
|
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
17663
19200
|
{
|
|
@@ -17675,12 +19212,12 @@ var badgeVariants = cva(
|
|
|
17675
19212
|
}
|
|
17676
19213
|
);
|
|
17677
19214
|
function Badge({ className, variant, ...props }) {
|
|
17678
|
-
return /* @__PURE__ */ (0,
|
|
19215
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
17679
19216
|
}
|
|
17680
19217
|
|
|
17681
19218
|
// src/OhhwellsBridge.tsx
|
|
17682
|
-
var
|
|
17683
|
-
var
|
|
19219
|
+
var import_lucide_react20 = require("lucide-react");
|
|
19220
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
17684
19221
|
var PRIMARY5 = "#0885FE";
|
|
17685
19222
|
var IMAGE_FADE_MS = 300;
|
|
17686
19223
|
var MEDIA_SETTLE_TIMEOUT_MS = 2500;
|
|
@@ -17802,7 +19339,7 @@ function duplicateSchedulingWidget(instanceId, scheduleId) {
|
|
|
17802
19339
|
schedulingRoots.set(container, root);
|
|
17803
19340
|
(0, import_react_dom4.flushSync)(() => {
|
|
17804
19341
|
root.render(
|
|
17805
|
-
/* @__PURE__ */ (0,
|
|
19342
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
17806
19343
|
SchedulingWidget,
|
|
17807
19344
|
{
|
|
17808
19345
|
notifyOnConnect: false,
|
|
@@ -17940,7 +19477,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
17940
19477
|
schedulingRoots.set(container, root);
|
|
17941
19478
|
(0, import_react_dom4.flushSync)(() => {
|
|
17942
19479
|
root.render(
|
|
17943
|
-
/* @__PURE__ */ (0,
|
|
19480
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
17944
19481
|
SchedulingWidget,
|
|
17945
19482
|
{
|
|
17946
19483
|
notifyOnConnect,
|
|
@@ -18103,8 +19640,8 @@ function lockVideoBox(video) {
|
|
|
18103
19640
|
}
|
|
18104
19641
|
const fit = video.style.objectFit || getComputedStyle(video).objectFit;
|
|
18105
19642
|
const bg = getComputedStyle(video).backgroundColor;
|
|
18106
|
-
const
|
|
18107
|
-
if (fit === "contain" &&
|
|
19643
|
+
const isTransparent2 = bg === "rgba(0, 0, 0, 0)" || bg === "transparent" || !bg;
|
|
19644
|
+
if (fit === "contain" && isTransparent2) {
|
|
18108
19645
|
video.style.backgroundColor = "var(--color-dark, #000)";
|
|
18109
19646
|
}
|
|
18110
19647
|
}
|
|
@@ -18254,7 +19791,10 @@ function listNavigationItems() {
|
|
|
18254
19791
|
).filter((el) => isNavigationItem2(el));
|
|
18255
19792
|
}
|
|
18256
19793
|
function getNavigationItemReorderState(anchor) {
|
|
18257
|
-
if (isCtaButton(anchor))
|
|
19794
|
+
if (isCtaButton(anchor)) {
|
|
19795
|
+
if (!collectionDragEnabled(anchor)) return { key: null, disabled: true };
|
|
19796
|
+
return { key: buttonId(anchor), disabled: false };
|
|
19797
|
+
}
|
|
18258
19798
|
return getReorderHandleStateFromAnchor(anchor);
|
|
18259
19799
|
}
|
|
18260
19800
|
function getReorderHandleState(el) {
|
|
@@ -18353,6 +19893,12 @@ function isPointOverNavigation(x, y) {
|
|
|
18353
19893
|
const r2 = panel.getBoundingClientRect();
|
|
18354
19894
|
if (x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom) return true;
|
|
18355
19895
|
}
|
|
19896
|
+
for (const el of document.querySelectorAll('[data-ohw-role="navbar-button"]')) {
|
|
19897
|
+
const r2 = el.getBoundingClientRect();
|
|
19898
|
+
if (r2.width > 0 && r2.height > 0 && x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom) {
|
|
19899
|
+
return true;
|
|
19900
|
+
}
|
|
19901
|
+
}
|
|
18356
19902
|
return false;
|
|
18357
19903
|
}
|
|
18358
19904
|
function findHoveredNavOrFooterContainer(x, y) {
|
|
@@ -18686,7 +20232,7 @@ function EditGlowChrome({
|
|
|
18686
20232
|
hideHandle = false
|
|
18687
20233
|
}) {
|
|
18688
20234
|
const GAP = SELECTION_CHROME_GAP2;
|
|
18689
|
-
return /* @__PURE__ */ (0,
|
|
20235
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
18690
20236
|
"div",
|
|
18691
20237
|
{
|
|
18692
20238
|
ref: elRef,
|
|
@@ -18701,7 +20247,7 @@ function EditGlowChrome({
|
|
|
18701
20247
|
zIndex: 2147483646
|
|
18702
20248
|
},
|
|
18703
20249
|
children: [
|
|
18704
|
-
/* @__PURE__ */ (0,
|
|
20250
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18705
20251
|
"div",
|
|
18706
20252
|
{
|
|
18707
20253
|
style: {
|
|
@@ -18715,7 +20261,7 @@ function EditGlowChrome({
|
|
|
18715
20261
|
}
|
|
18716
20262
|
}
|
|
18717
20263
|
),
|
|
18718
|
-
reorderHrefKey && !hideHandle && /* @__PURE__ */ (0,
|
|
20264
|
+
reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18719
20265
|
"div",
|
|
18720
20266
|
{
|
|
18721
20267
|
"data-ohw-drag-handle-container": "",
|
|
@@ -18727,7 +20273,7 @@ function EditGlowChrome({
|
|
|
18727
20273
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
18728
20274
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
18729
20275
|
},
|
|
18730
|
-
children: /* @__PURE__ */ (0,
|
|
20276
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18731
20277
|
DragHandle,
|
|
18732
20278
|
{
|
|
18733
20279
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -18741,22 +20287,12 @@ function EditGlowChrome({
|
|
|
18741
20287
|
}
|
|
18742
20288
|
);
|
|
18743
20289
|
}
|
|
18744
|
-
function getIframeVisibleClip(parentScroll) {
|
|
18745
|
-
if (!parentScroll) return null;
|
|
18746
|
-
const { iframeOffsetTop, headerH: visibleCanvasTop, canvasH } = parentScroll;
|
|
18747
|
-
const clipTop = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
18748
|
-
const clipBottom = Math.min(
|
|
18749
|
-
window.innerHeight,
|
|
18750
|
-
visibleCanvasTop + canvasH - iframeOffsetTop
|
|
18751
|
-
);
|
|
18752
|
-
return { top: clipTop, bottom: Math.max(clipTop, clipBottom) };
|
|
18753
|
-
}
|
|
18754
20290
|
function isRectOutsideClip(rect, clip) {
|
|
18755
20291
|
if (!clip) return false;
|
|
18756
20292
|
return rect.bottom < clip.top || rect.top > clip.bottom;
|
|
18757
20293
|
}
|
|
18758
20294
|
function applyVisibleViewport(el, parentScroll) {
|
|
18759
|
-
const clip =
|
|
20295
|
+
const clip = getIframeChromeClip(parentScroll);
|
|
18760
20296
|
const top = clip?.top ?? 0;
|
|
18761
20297
|
const height = clip ? clip.bottom - clip.top : window.innerHeight;
|
|
18762
20298
|
el.style.top = `${top}px`;
|
|
@@ -18796,7 +20332,7 @@ function clampToolbarLeft(centerX, toolbarWidth) {
|
|
|
18796
20332
|
function calcToolbarPos(rect, parentScroll, toolbarW = 306) {
|
|
18797
20333
|
const GAP = TOOLBAR_OFFSET_FROM_ELEMENT;
|
|
18798
20334
|
const APPROX_H = 32;
|
|
18799
|
-
const clip =
|
|
20335
|
+
const clip = getIframeChromeClip(parentScroll);
|
|
18800
20336
|
const clipTop = clip?.top ?? 0;
|
|
18801
20337
|
const canvasTopInIframe = parentScroll != null ? parentScroll.headerH - parentScroll.iframeOffsetTop : 0;
|
|
18802
20338
|
const visibleTop = rect.top - canvasTopInIframe;
|
|
@@ -18941,7 +20477,7 @@ function FloatingToolbar({
|
|
|
18941
20477
|
return () => ro.disconnect();
|
|
18942
20478
|
}, [showEditLink, activeCommands]);
|
|
18943
20479
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
|
|
18944
|
-
return /* @__PURE__ */ (0,
|
|
20480
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18945
20481
|
"div",
|
|
18946
20482
|
{
|
|
18947
20483
|
ref: setRefs,
|
|
@@ -18953,12 +20489,12 @@ function FloatingToolbar({
|
|
|
18953
20489
|
zIndex: 2147483647,
|
|
18954
20490
|
pointerEvents: "auto"
|
|
18955
20491
|
},
|
|
18956
|
-
children: /* @__PURE__ */ (0,
|
|
18957
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0,
|
|
18958
|
-
gi > 0 && /* @__PURE__ */ (0,
|
|
20492
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(CustomToolbar, { children: [
|
|
20493
|
+
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_react19.default.Fragment, { children: [
|
|
20494
|
+
gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(CustomToolbarDivider, {}),
|
|
18959
20495
|
btns.map((btn) => {
|
|
18960
20496
|
const isActive = activeCommands.has(btn.cmd);
|
|
18961
|
-
return /* @__PURE__ */ (0,
|
|
20497
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18962
20498
|
CustomToolbarButton,
|
|
18963
20499
|
{
|
|
18964
20500
|
title: btn.title,
|
|
@@ -18967,7 +20503,7 @@ function FloatingToolbar({
|
|
|
18967
20503
|
e.preventDefault();
|
|
18968
20504
|
onCommand(btn.cmd);
|
|
18969
20505
|
},
|
|
18970
|
-
children: /* @__PURE__ */ (0,
|
|
20506
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18971
20507
|
"svg",
|
|
18972
20508
|
{
|
|
18973
20509
|
width: "16",
|
|
@@ -18988,7 +20524,7 @@ function FloatingToolbar({
|
|
|
18988
20524
|
);
|
|
18989
20525
|
})
|
|
18990
20526
|
] }, gi)),
|
|
18991
|
-
showEditLink ? /* @__PURE__ */ (0,
|
|
20527
|
+
showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
18992
20528
|
CustomToolbarButton,
|
|
18993
20529
|
{
|
|
18994
20530
|
type: "button",
|
|
@@ -19002,7 +20538,7 @@ function FloatingToolbar({
|
|
|
19002
20538
|
e.preventDefault();
|
|
19003
20539
|
e.stopPropagation();
|
|
19004
20540
|
},
|
|
19005
|
-
children: /* @__PURE__ */ (0,
|
|
20541
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react20.Link, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
19006
20542
|
}
|
|
19007
20543
|
) : null
|
|
19008
20544
|
] })
|
|
@@ -19019,7 +20555,7 @@ function StateToggle({
|
|
|
19019
20555
|
states,
|
|
19020
20556
|
onStateChange
|
|
19021
20557
|
}) {
|
|
19022
|
-
return /* @__PURE__ */ (0,
|
|
20558
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
19023
20559
|
ToggleGroup,
|
|
19024
20560
|
{
|
|
19025
20561
|
"data-ohw-state-toggle": "",
|
|
@@ -19033,7 +20569,7 @@ function StateToggle({
|
|
|
19033
20569
|
left: rect.right - 8,
|
|
19034
20570
|
transform: "translateX(-100%)"
|
|
19035
20571
|
},
|
|
19036
|
-
children: states.map((state) => /* @__PURE__ */ (0,
|
|
20572
|
+
children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
19037
20573
|
}
|
|
19038
20574
|
);
|
|
19039
20575
|
}
|
|
@@ -19049,9 +20585,9 @@ var OHW_LOADER_STYLE = {
|
|
|
19049
20585
|
justifyContent: "center"
|
|
19050
20586
|
};
|
|
19051
20587
|
function OhwLoaderSpinner() {
|
|
19052
|
-
return /* @__PURE__ */ (0,
|
|
19053
|
-
/* @__PURE__ */ (0,
|
|
19054
|
-
/* @__PURE__ */ (0,
|
|
20588
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", "aria-hidden": true, children: [
|
|
20589
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("circle", { cx: "14", cy: "14", r: "11", stroke: "#E7E5E4", strokeWidth: "3" }),
|
|
20590
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
19055
20591
|
"circle",
|
|
19056
20592
|
{
|
|
19057
20593
|
cx: "14",
|
|
@@ -19061,7 +20597,7 @@ function OhwLoaderSpinner() {
|
|
|
19061
20597
|
strokeWidth: "3",
|
|
19062
20598
|
strokeDasharray: "17 52",
|
|
19063
20599
|
strokeLinecap: "round",
|
|
19064
|
-
children: /* @__PURE__ */ (0,
|
|
20600
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
19065
20601
|
"animateTransform",
|
|
19066
20602
|
{
|
|
19067
20603
|
attributeName: "transform",
|
|
@@ -19077,7 +20613,7 @@ function OhwLoaderSpinner() {
|
|
|
19077
20613
|
] });
|
|
19078
20614
|
}
|
|
19079
20615
|
function OhwBrandMark() {
|
|
19080
|
-
return /* @__PURE__ */ (0,
|
|
20616
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
19081
20617
|
"svg",
|
|
19082
20618
|
{
|
|
19083
20619
|
width: "16",
|
|
@@ -19088,7 +20624,7 @@ function OhwBrandMark() {
|
|
|
19088
20624
|
style: { display: "block", flexShrink: 0 },
|
|
19089
20625
|
xmlns: "http://www.w3.org/2000/svg",
|
|
19090
20626
|
children: [
|
|
19091
|
-
/* @__PURE__ */ (0,
|
|
20627
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
19092
20628
|
"mask",
|
|
19093
20629
|
{
|
|
19094
20630
|
id: "ohw-badge-mark",
|
|
@@ -19098,15 +20634,15 @@ function OhwBrandMark() {
|
|
|
19098
20634
|
y: "0",
|
|
19099
20635
|
width: "48",
|
|
19100
20636
|
height: "48",
|
|
19101
|
-
children: /* @__PURE__ */ (0,
|
|
20637
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("path", { d: "M23.8741 48C37.0594 48 47.7481 37.2548 47.7481 24C47.7481 10.7452 37.0594 0 23.8741 0C10.6888 0 0 10.7452 0 24C0 37.2548 10.6888 48 23.8741 48Z", fill: "white" })
|
|
19102
20638
|
}
|
|
19103
20639
|
),
|
|
19104
|
-
/* @__PURE__ */ (0,
|
|
19105
|
-
/* @__PURE__ */ (0,
|
|
19106
|
-
/* @__PURE__ */ (0,
|
|
19107
|
-
/* @__PURE__ */ (0,
|
|
19108
|
-
/* @__PURE__ */ (0,
|
|
19109
|
-
/* @__PURE__ */ (0,
|
|
20640
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("g", { mask: "url(#ohw-badge-mark)", children: [
|
|
20641
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("path", { d: "M23.8731 48.0497C37.0584 48.0497 47.7472 37.3046 47.7472 24.0497C47.7472 10.7949 37.0584 0.0497208 23.8731 0.0497208C10.6878 0.0497208 -0.000976562 10.7949 -0.000976562 24.0497C-0.000976562 37.3046 10.6878 48.0497 23.8731 48.0497Z", fill: "#0078E5" }),
|
|
20642
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("path", { d: "M17.1307 14.7172C13.1687 14.7172 9.38102 18.1154 8.65114 22.34C8.38885 23.8488 8.5598 25.2581 9.06929 26.4451C6.20005 29.1677 1.77216 27.8721 -1.40212 26.1536C-2.73618 25.4317 -3.92695 27.4745 -2.59037 28.1981C1.33389 30.3226 6.86037 31.6621 10.4402 28.4188C11.4718 29.3859 12.867 29.9621 14.4894 29.9621C18.4161 29.9621 22.2038 26.5318 22.9337 22.34C23.6636 18.1162 21.0566 14.7172 17.1298 14.7172H17.1307ZM19.9798 22.34C19.5281 25.0399 17.2689 27.231 14.9754 27.231C12.6466 27.231 11.1877 25.0399 11.6394 22.34C12.1262 19.6401 14.3151 17.4482 16.6438 17.4482C18.9374 17.4482 20.4667 19.6401 19.9798 22.34Z", fill: "white" }),
|
|
20643
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("path", { d: "M40.0017 27.0262C39.1797 27.081 38.2721 26.995 37.4668 26.7415C37.3344 26.6993 37.28 26.5401 37.3529 26.4205C37.5959 26.0212 37.8255 25.6152 38.009 25.1889C38.1071 24.9918 38.2018 24.793 38.2897 24.5908C38.3274 24.5041 38.4163 24.451 38.5101 24.4619C38.63 24.4754 38.7054 24.4821 38.8881 24.4821L39.1529 24.4796L39.8283 24.4543C45.9229 24.0492 50.4765 20.4319 54.8466 16.9014C56.0172 15.9554 57.6932 17.6208 56.5116 18.5752C51.7687 22.4065 47.1966 26.5081 40.9319 26.9689", fill: "white" }),
|
|
20644
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("path", { d: "M37.9687 24.27C38.4472 23.1319 38.7656 21.9045 38.9609 20.6991C39.5927 16.76 38.5058 14.2193 36.1553 14.2193C34.1835 14.2193 33.1469 17.2427 32.9199 18.8694C32.743 19.9872 32.5914 22.1219 33.6028 23.9524C33.7553 24.259 34.15 24.7712 34.471 25.1259C34.5447 25.2067 34.6746 25.2 34.7349 25.1082C34.9528 24.7788 35.1615 24.4039 35.3584 24.0257C35.5444 23.6677 35.5888 23.6138 35.8587 23.0207C35.8838 22.966 35.8813 22.9002 35.8478 22.8505C35.5888 22.4597 35.2168 21.9787 35.1204 21.4614C34.9184 20.4455 34.9436 19.2257 35.2218 18.1078C35.4413 17.3118 35.7195 16.7844 35.9039 16.5106C35.9466 16.4466 36.0279 16.4129 36.0975 16.4449C36.369 16.5671 36.5827 16.8838 36.7385 17.396C37.0167 18.2089 37.0167 19.3782 36.814 20.6999C36.6991 21.5271 36.4771 22.3729 36.1746 23.1673C36.1293 23.308 36.0757 23.4461 36.0187 23.5826C36.0187 23.5868 36.0187 23.591 36.0187 23.5961C35.9911 23.6946 35.9207 23.8067 35.8846 23.901C35.5536 24.5497 35.2344 25.1697 34.8439 25.7838C34.8388 25.7863 34.8346 25.7914 34.8296 25.7931C34.6528 26.0525 34.4718 26.2901 34.2866 26.4965C34.2774 26.5099 34.2682 26.5234 34.2589 26.5369C34.2405 26.5638 34.2179 26.5815 34.1944 26.595C33.5064 27.3212 32.7665 27.6893 32.0123 27.6893C31.8606 27.6893 31.6838 27.664 31.507 27.4349C31.3042 27.1299 30.85 26.0879 31.2539 22.9112C31.4785 21.3949 31.8011 20.0268 31.931 19.5408C31.9579 19.4413 31.8908 19.3419 31.7886 19.3293L30.0062 19.1162C29.9241 19.1061 29.8478 19.1566 29.8252 19.2366C29.2704 21.1615 27.0305 27.6885 24.9599 27.6885C24.328 27.6885 24.1512 26.6211 24.1001 26.2909C23.775 23.6264 25.528 18.5492 29.5302 16.2267C29.6048 16.1838 29.635 16.0928 29.5998 16.0136L28.9042 14.467C28.8632 14.3752 28.7501 14.3389 28.6638 14.3886C25.8079 16.0414 24.1847 18.5231 23.2915 20.3436C22.2046 22.5793 21.6993 25.0189 21.9515 26.8738C22.1795 28.7794 23.1398 29.872 24.6054 29.872C26.0543 29.872 27.4369 28.9066 28.7098 27.0187C28.7953 26.8915 28.9889 26.9311 29.0149 27.0819C29.2646 28.5283 29.9811 29.872 31.6579 29.872C33.5282 29.872 35.3232 28.7288 36.7134 26.6447C36.7712 26.5874 36.7972 26.5411 36.8181 26.4906C36.8232 26.4931 36.8282 26.4948 36.8332 26.4973C37.01 26.2025 37.181 25.9051 37.3444 25.6027C37.4508 25.4005 37.5572 25.1992 37.6586 24.9945C37.7181 24.874 37.7743 24.7527 37.8262 24.6289C37.838 24.6002 37.8547 24.5665 37.8706 24.5337", fill: "white" }),
|
|
20645
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("path", { d: "M30.5839 31.6397C25.7546 34.8577 19.4773 34.7853 14.6907 31.5243C13.5368 30.7384 12.5044 32.6498 13.6474 33.4281C19.034 37.0985 26.3077 37.096 31.7218 33.488C32.8791 32.7172 31.7478 30.8639 30.5839 31.6397Z", fill: "white" })
|
|
19110
20646
|
] })
|
|
19111
20647
|
]
|
|
19112
20648
|
}
|
|
@@ -19143,7 +20679,7 @@ var OHW_BADGE_LABEL_STYLE = {
|
|
|
19143
20679
|
whiteSpace: "nowrap"
|
|
19144
20680
|
};
|
|
19145
20681
|
function MadeWithOhhWells() {
|
|
19146
|
-
return /* @__PURE__ */ (0,
|
|
20682
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
19147
20683
|
"a",
|
|
19148
20684
|
{
|
|
19149
20685
|
href: "https://ohhwells.com",
|
|
@@ -19153,8 +20689,8 @@ function MadeWithOhhWells() {
|
|
|
19153
20689
|
"data-ohw-badge": "",
|
|
19154
20690
|
style: OHW_BADGE_STYLE,
|
|
19155
20691
|
children: [
|
|
19156
|
-
/* @__PURE__ */ (0,
|
|
19157
|
-
/* @__PURE__ */ (0,
|
|
20692
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(OhwBrandMark, {}),
|
|
20693
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { style: OHW_BADGE_LABEL_STYLE, children: "Made with OhhWells" })
|
|
19158
20694
|
]
|
|
19159
20695
|
}
|
|
19160
20696
|
);
|
|
@@ -19644,7 +21180,15 @@ function OhhwellsBridge() {
|
|
|
19644
21180
|
const [floatingPanel, setFloatingPanel] = (0, import_react19.useState)(null);
|
|
19645
21181
|
const floatingPanelOpenRef = (0, import_react19.useRef)(false);
|
|
19646
21182
|
floatingPanelOpenRef.current = floatingPanel !== null;
|
|
21183
|
+
const floatingPanelRef = (0, import_react19.useRef)(null);
|
|
21184
|
+
floatingPanelRef.current = floatingPanel;
|
|
19647
21185
|
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react19.useState)(null);
|
|
21186
|
+
const buttonCollectionDragRef = (0, import_react19.useRef)(null);
|
|
21187
|
+
const buttonDropInsertIndexRef = (0, import_react19.useRef)(null);
|
|
21188
|
+
const [buttonDropSlots, setButtonDropSlots] = (0, import_react19.useState)([]);
|
|
21189
|
+
const [activeButtonDropIndex, setActiveButtonDropIndex] = (0, import_react19.useState)(null);
|
|
21190
|
+
const buttonPointerDragRef = (0, import_react19.useRef)(null);
|
|
21191
|
+
const [buttonStyleTick, setButtonStyleTick] = (0, import_react19.useState)(0);
|
|
19648
21192
|
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react19.useState)(null);
|
|
19649
21193
|
const [editorViewport, setEditorViewport] = (0, import_react19.useState)("desktop");
|
|
19650
21194
|
const [parentScrollSnap, setParentScrollSnap] = (0, import_react19.useState)(null);
|
|
@@ -19945,6 +21489,7 @@ function OhhwellsBridge() {
|
|
|
19945
21489
|
hoveredItemElRef.current = null;
|
|
19946
21490
|
setHoveredItemRect(null);
|
|
19947
21491
|
setFloatingPanel(null);
|
|
21492
|
+
setFloatingPanelPos(null);
|
|
19948
21493
|
setLogoSizeDraft(null);
|
|
19949
21494
|
if (!activeElRef.current) {
|
|
19950
21495
|
if (nestedGroup?.isConnected) {
|
|
@@ -20545,6 +22090,47 @@ function OhhwellsBridge() {
|
|
|
20545
22090
|
},
|
|
20546
22091
|
[beginFooterDrag]
|
|
20547
22092
|
);
|
|
22093
|
+
const persistButtonCollectionDrag = (0, import_react19.useCallback)(
|
|
22094
|
+
(button, clientX) => {
|
|
22095
|
+
const insertIndex = buttonDropInsertIndexRef.current;
|
|
22096
|
+
if (insertIndex != null) insertButtonAtCollectionIndex(button, insertIndex);
|
|
22097
|
+
else if (typeof clientX === "number" && clientX !== 0) reorderButtonInCollection(button, clientX);
|
|
22098
|
+
buttonDropInsertIndexRef.current = null;
|
|
22099
|
+
const collection = buttonCollectionOf(button);
|
|
22100
|
+
if (collection) {
|
|
22101
|
+
const persisted = persistCollectionOrder(collection, editContentRef.current);
|
|
22102
|
+
if (persisted) {
|
|
22103
|
+
editContentRef.current = persisted.content;
|
|
22104
|
+
postToParent2({ type: "ow:change", nodes: persisted.nodes });
|
|
22105
|
+
}
|
|
22106
|
+
}
|
|
22107
|
+
buttonCollectionDragRef.current = null;
|
|
22108
|
+
buttonPointerDragRef.current = null;
|
|
22109
|
+
setButtonDropSlots([]);
|
|
22110
|
+
setActiveButtonDropIndex(null);
|
|
22111
|
+
setIsItemDragging(false);
|
|
22112
|
+
unlockFooterDragInteraction();
|
|
22113
|
+
if (button.isConnected) setToolbarRect(button.getBoundingClientRect());
|
|
22114
|
+
},
|
|
22115
|
+
[postToParent2]
|
|
22116
|
+
);
|
|
22117
|
+
const refreshButtonDragVisuals = (0, import_react19.useCallback)((button, clientX, clientY) => {
|
|
22118
|
+
const collection = buttonCollectionOf(button);
|
|
22119
|
+
if (!collection) {
|
|
22120
|
+
setButtonDropSlots([]);
|
|
22121
|
+
setActiveButtonDropIndex(null);
|
|
22122
|
+
buttonDropInsertIndexRef.current = null;
|
|
22123
|
+
return;
|
|
22124
|
+
}
|
|
22125
|
+
const slots = buildButtonCollectionDropSlots(collection);
|
|
22126
|
+
const active = hitTestButtonCollectionDropSlot(collection, clientX, clientY);
|
|
22127
|
+
setButtonDropSlots(slots);
|
|
22128
|
+
const idx = active ? slots.findIndex((slot) => slot.insertIndex === active.insertIndex) : -1;
|
|
22129
|
+
setActiveButtonDropIndex(idx >= 0 ? idx : null);
|
|
22130
|
+
buttonDropInsertIndexRef.current = active?.insertIndex ?? null;
|
|
22131
|
+
setDraggedItemRect(button.getBoundingClientRect());
|
|
22132
|
+
if (selectedElRef.current === button) setToolbarRect(button.getBoundingClientRect());
|
|
22133
|
+
}, []);
|
|
20548
22134
|
const handleItemDragStart = (0, import_react19.useCallback)(
|
|
20549
22135
|
(e) => {
|
|
20550
22136
|
const selected = selectedElRef.current;
|
|
@@ -20554,6 +22140,17 @@ function OhhwellsBridge() {
|
|
|
20554
22140
|
}
|
|
20555
22141
|
const clientX = e?.clientX ?? selected.getBoundingClientRect().left + 8;
|
|
20556
22142
|
const clientY = e?.clientY ?? selected.getBoundingClientRect().top + 8;
|
|
22143
|
+
if (isCtaButton(selected) && collectionDragEnabled(selected)) {
|
|
22144
|
+
buttonCollectionDragRef.current = selected;
|
|
22145
|
+
setMediaHover(null);
|
|
22146
|
+
if (e?.dataTransfer) {
|
|
22147
|
+
e.dataTransfer.effectAllowed = "move";
|
|
22148
|
+
e.dataTransfer.setData("text/plain", buttonId(selected) ?? "button");
|
|
22149
|
+
}
|
|
22150
|
+
setIsItemDragging(true);
|
|
22151
|
+
refreshButtonDragVisuals(selected, clientX, clientY);
|
|
22152
|
+
return;
|
|
22153
|
+
}
|
|
20557
22154
|
if (startFooterLinkDrag(selected, clientX, clientY, true)) return;
|
|
20558
22155
|
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup2(selected) && selected.closest("footer")) {
|
|
20559
22156
|
if (startFooterColumnDrag(selected, clientX, clientY, true)) return;
|
|
@@ -20563,10 +22160,15 @@ function OhhwellsBridge() {
|
|
|
20563
22160
|
setSiblingHintRect(null);
|
|
20564
22161
|
setIsItemDragging(true);
|
|
20565
22162
|
},
|
|
20566
|
-
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
|
|
22163
|
+
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag, refreshButtonDragVisuals]
|
|
20567
22164
|
);
|
|
20568
22165
|
const handleItemDragEnd = (0, import_react19.useCallback)(
|
|
20569
22166
|
(e) => {
|
|
22167
|
+
const collectionButton = buttonCollectionDragRef.current;
|
|
22168
|
+
if (collectionButton) {
|
|
22169
|
+
persistButtonCollectionDrag(collectionButton, e?.clientX);
|
|
22170
|
+
return;
|
|
22171
|
+
}
|
|
20570
22172
|
if (footerDragRef.current) {
|
|
20571
22173
|
const x = e?.clientX;
|
|
20572
22174
|
const y = e?.clientY;
|
|
@@ -20589,12 +22191,22 @@ function OhhwellsBridge() {
|
|
|
20589
22191
|
}
|
|
20590
22192
|
setIsItemDragging(false);
|
|
20591
22193
|
},
|
|
20592
|
-
[commitFooterDrag, commitNavDrag, navDragRef]
|
|
22194
|
+
[commitFooterDrag, commitNavDrag, navDragRef, persistButtonCollectionDrag]
|
|
20593
22195
|
);
|
|
20594
22196
|
const handleItemChromePointerDown = (0, import_react19.useCallback)((e) => {
|
|
20595
22197
|
if (e.button !== 0) return;
|
|
20596
22198
|
const selected = selectedElRef.current;
|
|
20597
22199
|
if (!selected) return;
|
|
22200
|
+
if (isCtaButton(selected) && collectionDragEnabled(selected)) {
|
|
22201
|
+
buttonPointerDragRef.current = {
|
|
22202
|
+
el: selected,
|
|
22203
|
+
startX: e.clientX,
|
|
22204
|
+
startY: e.clientY,
|
|
22205
|
+
pointerId: e.pointerId,
|
|
22206
|
+
started: false
|
|
22207
|
+
};
|
|
22208
|
+
return;
|
|
22209
|
+
}
|
|
20598
22210
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
20599
22211
|
if (hrefKey && isFooterHrefKey(hrefKey)) {
|
|
20600
22212
|
footerPointerDragRef.current = {
|
|
@@ -20673,10 +22285,29 @@ function OhhwellsBridge() {
|
|
|
20673
22285
|
setIsFooterFrameSelection(false);
|
|
20674
22286
|
setToolbarVariant("link-action");
|
|
20675
22287
|
setToolbarRect(anchor.getBoundingClientRect());
|
|
22288
|
+
if (glowElRef.current) glowElRef.current.style.display = "";
|
|
20676
22289
|
setToolbarShowEditLink(false);
|
|
20677
22290
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
20678
|
-
|
|
20679
|
-
|
|
22291
|
+
const panel = floatingPanelRef.current;
|
|
22292
|
+
if (panel?.kind === "button-style" && isCtaButton(anchor)) {
|
|
22293
|
+
const id = buttonId(anchor);
|
|
22294
|
+
if (id && panel.buttonId !== id) {
|
|
22295
|
+
captureButtonOrigin(anchor);
|
|
22296
|
+
setFloatingPanelPos(null);
|
|
22297
|
+
setParentScrollSnap(parentScrollRef.current);
|
|
22298
|
+
setFloatingPanel({
|
|
22299
|
+
...panel,
|
|
22300
|
+
key: `button-style:${id}`,
|
|
22301
|
+
buttonId: id,
|
|
22302
|
+
context: buttonStyleContext(anchor)
|
|
22303
|
+
});
|
|
22304
|
+
setButtonStyleTick((n) => n + 1);
|
|
22305
|
+
}
|
|
22306
|
+
} else {
|
|
22307
|
+
setFloatingPanel(null);
|
|
22308
|
+
setFloatingPanelPos(null);
|
|
22309
|
+
setLogoSizeDraft(null);
|
|
22310
|
+
}
|
|
20680
22311
|
}, [deactivate, markSelected]);
|
|
20681
22312
|
const selectFrame = (0, import_react19.useCallback)((el) => {
|
|
20682
22313
|
if (!isNavigationContainer(el)) return;
|
|
@@ -20716,6 +22347,7 @@ function OhhwellsBridge() {
|
|
|
20716
22347
|
setToolbarShowEditLink(false);
|
|
20717
22348
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
20718
22349
|
setFloatingPanel(null);
|
|
22350
|
+
setFloatingPanelPos(null);
|
|
20719
22351
|
setLogoSizeDraft(null);
|
|
20720
22352
|
}, [deactivate, markSelected, postToParent2]);
|
|
20721
22353
|
const selectLogo = (0, import_react19.useCallback)(
|
|
@@ -20761,6 +22393,7 @@ function OhhwellsBridge() {
|
|
|
20761
22393
|
});
|
|
20762
22394
|
}, []);
|
|
20763
22395
|
const openSocialsDisplayPanel = (0, import_react19.useCallback)((row) => {
|
|
22396
|
+
setFloatingPanelPos(null);
|
|
20764
22397
|
setParentScrollSnap(parentScrollRef.current);
|
|
20765
22398
|
setFloatingPanel({
|
|
20766
22399
|
key: "socials-display",
|
|
@@ -20770,6 +22403,87 @@ function OhhwellsBridge() {
|
|
|
20770
22403
|
row
|
|
20771
22404
|
});
|
|
20772
22405
|
}, []);
|
|
22406
|
+
const rememberButtonTokens = (0, import_react19.useCallback)(
|
|
22407
|
+
(content, tokens, nodes) => {
|
|
22408
|
+
if (nodes.length === 0) return content;
|
|
22409
|
+
const next = { ...content };
|
|
22410
|
+
for (const node of nodes) next[node.key] = node.text;
|
|
22411
|
+
editContentRef.current = next;
|
|
22412
|
+
postToParent2({ type: "ow:change", nodes });
|
|
22413
|
+
return next;
|
|
22414
|
+
},
|
|
22415
|
+
[postToParent2]
|
|
22416
|
+
);
|
|
22417
|
+
const tokensForButton = (0, import_react19.useCallback)(
|
|
22418
|
+
(el, persistFallback = false) => {
|
|
22419
|
+
const stored = readStoredStyleTokens(editContentRef.current);
|
|
22420
|
+
if (stored) return stored;
|
|
22421
|
+
const ensured = ensureButtonStyleTokens(document, editContentRef.current);
|
|
22422
|
+
if (ensured.tokens) {
|
|
22423
|
+
rememberButtonTokens(editContentRef.current, ensured.tokens, ensured.nodes);
|
|
22424
|
+
return ensured.tokens;
|
|
22425
|
+
}
|
|
22426
|
+
const fallback = tokensFromButton(el);
|
|
22427
|
+
if (persistFallback) rememberButtonTokens(editContentRef.current, fallback, styleTokenNodes(fallback));
|
|
22428
|
+
return fallback;
|
|
22429
|
+
},
|
|
22430
|
+
[rememberButtonTokens]
|
|
22431
|
+
);
|
|
22432
|
+
const openButtonStylePanel = (0, import_react19.useCallback)(
|
|
22433
|
+
(anchor) => {
|
|
22434
|
+
const id = buttonId(anchor);
|
|
22435
|
+
if (!id) return;
|
|
22436
|
+
captureButtonOrigin(anchor);
|
|
22437
|
+
tokensForButton(anchor);
|
|
22438
|
+
setFloatingPanelPos(null);
|
|
22439
|
+
setParentScrollSnap(parentScrollRef.current);
|
|
22440
|
+
setFloatingPanel({
|
|
22441
|
+
key: `button-style:${id}`,
|
|
22442
|
+
title: "Style",
|
|
22443
|
+
context: buttonStyleContext(anchor),
|
|
22444
|
+
kind: "button-style",
|
|
22445
|
+
buttonId: id
|
|
22446
|
+
});
|
|
22447
|
+
},
|
|
22448
|
+
[tokensForButton]
|
|
22449
|
+
);
|
|
22450
|
+
const applySelectedButtonStyle = (0, import_react19.useCallback)(
|
|
22451
|
+
(patch) => {
|
|
22452
|
+
const panel = floatingPanelRef.current;
|
|
22453
|
+
const id = panel?.kind === "button-style" ? panel.buttonId : null;
|
|
22454
|
+
const el = id ? document.querySelector(`[data-ohw-href-key="${CSS.escape(id)}"]`) : null;
|
|
22455
|
+
if (!el || !id || !isCtaButton(el)) return;
|
|
22456
|
+
const tokens = tokensFromButton(el);
|
|
22457
|
+
const next = { ...assignmentFor(el, editContentRef.current, tokens), ...patch };
|
|
22458
|
+
const assignments = withAssignment(editContentRef.current, id, next);
|
|
22459
|
+
const text = JSON.stringify(assignments);
|
|
22460
|
+
editContentRef.current = { ...editContentRef.current, [BUTTON_ASSIGNMENTS_KEY]: text };
|
|
22461
|
+
applyButtonStyle(el, next, tokens);
|
|
22462
|
+
postToParent2({ type: "ow:change", nodes: [{ key: BUTTON_ASSIGNMENTS_KEY, text }] });
|
|
22463
|
+
setButtonStyleTick((n) => n + 1);
|
|
22464
|
+
if (selectedElRef.current === el) setToolbarRect(el.getBoundingClientRect());
|
|
22465
|
+
},
|
|
22466
|
+
[postToParent2]
|
|
22467
|
+
);
|
|
22468
|
+
(0, import_react19.useEffect)(() => {
|
|
22469
|
+
const onDragOver = (e) => {
|
|
22470
|
+
const dragged = buttonCollectionDragRef.current;
|
|
22471
|
+
if (!dragged) return;
|
|
22472
|
+
e.preventDefault();
|
|
22473
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
22474
|
+
refreshButtonDragVisuals(dragged, e.clientX, e.clientY);
|
|
22475
|
+
};
|
|
22476
|
+
const onDrop = (e) => {
|
|
22477
|
+
if (!buttonCollectionDragRef.current) return;
|
|
22478
|
+
e.preventDefault();
|
|
22479
|
+
};
|
|
22480
|
+
document.addEventListener("dragover", onDragOver);
|
|
22481
|
+
document.addEventListener("drop", onDrop);
|
|
22482
|
+
return () => {
|
|
22483
|
+
document.removeEventListener("dragover", onDragOver);
|
|
22484
|
+
document.removeEventListener("drop", onDrop);
|
|
22485
|
+
};
|
|
22486
|
+
}, [refreshButtonDragVisuals]);
|
|
20773
22487
|
const isEditModeRef = (0, import_react19.useRef)(false);
|
|
20774
22488
|
const requestMissingSocialIconsRef = (0, import_react19.useRef)(() => {
|
|
20775
22489
|
});
|
|
@@ -20812,11 +22526,13 @@ function OhhwellsBridge() {
|
|
|
20812
22526
|
);
|
|
20813
22527
|
const closeFloatingPanelOnly = (0, import_react19.useCallback)(() => {
|
|
20814
22528
|
setFloatingPanel(null);
|
|
22529
|
+
setFloatingPanelPos(null);
|
|
20815
22530
|
setLogoSizeDraft(null);
|
|
20816
22531
|
}, []);
|
|
20817
22532
|
closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
|
|
20818
22533
|
const closeFloatingPanelAndDeselect = (0, import_react19.useCallback)(() => {
|
|
20819
22534
|
setFloatingPanel(null);
|
|
22535
|
+
setFloatingPanelPos(null);
|
|
20820
22536
|
setLogoSizeDraft(null);
|
|
20821
22537
|
deselectRef.current();
|
|
20822
22538
|
}, []);
|
|
@@ -21085,6 +22801,7 @@ function OhhwellsBridge() {
|
|
|
21085
22801
|
reconcileSocialsFromContent(content);
|
|
21086
22802
|
applySocialsDisplayFromContent(content);
|
|
21087
22803
|
applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
|
|
22804
|
+
syncButtonsFromContent(document, content);
|
|
21088
22805
|
if (isEditModeRef.current) requestMissingSocialIconsRef.current();
|
|
21089
22806
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
21090
22807
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
@@ -21285,6 +23002,7 @@ function OhhwellsBridge() {
|
|
|
21285
23002
|
reconcileSocialsFromContent(content);
|
|
21286
23003
|
applySocialsDisplayFromContent(content);
|
|
21287
23004
|
applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
|
|
23005
|
+
syncButtonsFromContent(document, content);
|
|
21288
23006
|
if (isEditModeRef.current) requestMissingSocialIconsRef.current();
|
|
21289
23007
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
21290
23008
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
@@ -21373,7 +23091,10 @@ function OhhwellsBridge() {
|
|
|
21373
23091
|
if (roots.length === 0) {
|
|
21374
23092
|
reconcileNavbarItemsFromContent(contentForNav());
|
|
21375
23093
|
reconcileFooterOrderFromContent(contentForNav());
|
|
21376
|
-
if (isEditMode)
|
|
23094
|
+
if (isEditMode) {
|
|
23095
|
+
syncButtonsFromContent(document, contentForNav());
|
|
23096
|
+
syncNavigationDragCursorAttrs();
|
|
23097
|
+
}
|
|
21377
23098
|
return;
|
|
21378
23099
|
}
|
|
21379
23100
|
let rafId = null;
|
|
@@ -21385,7 +23106,7 @@ function OhhwellsBridge() {
|
|
|
21385
23106
|
}
|
|
21386
23107
|
};
|
|
21387
23108
|
const run = () => {
|
|
21388
|
-
if (footerDragRef.current || navDragRef.current || applying) return;
|
|
23109
|
+
if (footerDragRef.current || navDragRef.current || buttonCollectionDragRef.current || applying) return;
|
|
21389
23110
|
applying = true;
|
|
21390
23111
|
observer?.disconnect();
|
|
21391
23112
|
try {
|
|
@@ -21395,6 +23116,7 @@ function OhhwellsBridge() {
|
|
|
21395
23116
|
reconcileSocialsFromContent(content);
|
|
21396
23117
|
applySocialsDisplayFromContent(content);
|
|
21397
23118
|
applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
|
|
23119
|
+
syncButtonsFromContent(document, content);
|
|
21398
23120
|
if (isEditModeRef.current) requestMissingSocialIconsRef.current();
|
|
21399
23121
|
document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
|
|
21400
23122
|
if (isFooterHrefKey(el.getAttribute("data-ohw-href-key")) || getSocialItem(el)) {
|
|
@@ -21402,9 +23124,9 @@ function OhhwellsBridge() {
|
|
|
21402
23124
|
}
|
|
21403
23125
|
});
|
|
21404
23126
|
document.querySelectorAll(
|
|
21405
|
-
|
|
23127
|
+
'nav [data-ohw-href-key], [data-ohw-nav-container] [data-ohw-href-key], [data-ohw-nav-drawer] [data-ohw-href-key], [data-ohw-role="navbar-button"]'
|
|
21406
23128
|
).forEach((el) => {
|
|
21407
|
-
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
23129
|
+
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key")) || isCtaButton(el)) {
|
|
21408
23130
|
disableNativeHrefDrag(el);
|
|
21409
23131
|
}
|
|
21410
23132
|
});
|
|
@@ -21429,6 +23151,44 @@ function OhhwellsBridge() {
|
|
|
21429
23151
|
observer?.disconnect();
|
|
21430
23152
|
};
|
|
21431
23153
|
}, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
|
|
23154
|
+
(0, import_react19.useEffect)(() => {
|
|
23155
|
+
if (!isEditMode) return;
|
|
23156
|
+
let applying = false;
|
|
23157
|
+
let rafId = null;
|
|
23158
|
+
const run = () => {
|
|
23159
|
+
if (applying || buttonCollectionDragRef.current) return;
|
|
23160
|
+
const content = editContentRef.current;
|
|
23161
|
+
if (!content[BUTTON_COLLECTIONS_KEY] && !content[BUTTON_SNAPSHOTS_KEY]) return;
|
|
23162
|
+
applying = true;
|
|
23163
|
+
try {
|
|
23164
|
+
syncButtonsFromContent(document, content);
|
|
23165
|
+
} finally {
|
|
23166
|
+
applying = false;
|
|
23167
|
+
}
|
|
23168
|
+
};
|
|
23169
|
+
const schedule = () => {
|
|
23170
|
+
if (rafId != null) return;
|
|
23171
|
+
rafId = requestAnimationFrame(() => {
|
|
23172
|
+
rafId = null;
|
|
23173
|
+
run();
|
|
23174
|
+
});
|
|
23175
|
+
};
|
|
23176
|
+
const observer = new MutationObserver((mutations) => {
|
|
23177
|
+
if (mutations.every((m) => {
|
|
23178
|
+
const t = m.target;
|
|
23179
|
+
return t instanceof Element && Boolean(t.closest("[data-ohw-bridge], [data-ohw-bridge-root], [data-ohw-button-collection]"));
|
|
23180
|
+
})) {
|
|
23181
|
+
return;
|
|
23182
|
+
}
|
|
23183
|
+
schedule();
|
|
23184
|
+
});
|
|
23185
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
23186
|
+
run();
|
|
23187
|
+
return () => {
|
|
23188
|
+
if (rafId != null) cancelAnimationFrame(rafId);
|
|
23189
|
+
observer.disconnect();
|
|
23190
|
+
};
|
|
23191
|
+
}, [isEditMode, pathname]);
|
|
21432
23192
|
(0, import_react19.useEffect)(() => {
|
|
21433
23193
|
if (!isEditMode) return;
|
|
21434
23194
|
let lastPosted = 0;
|
|
@@ -21955,14 +23715,6 @@ function OhhwellsBridge() {
|
|
|
21955
23715
|
}
|
|
21956
23716
|
const clickedButton = findClosestButtonLike(target);
|
|
21957
23717
|
const buttonOnMedia = Boolean(clickedButton && isMediaEditable(editable) && editable.contains(clickedButton));
|
|
21958
|
-
console.log("[click-debug]", {
|
|
21959
|
-
editableType: editable.dataset.ohwEditable,
|
|
21960
|
-
editableTag: editable.tagName,
|
|
21961
|
-
targetTag: target.tagName,
|
|
21962
|
-
clickedButtonTag: clickedButton?.tagName ?? null,
|
|
21963
|
-
buttonOnMedia,
|
|
21964
|
-
isMediaEditableEditable: isMediaEditable(editable)
|
|
21965
|
-
});
|
|
21966
23718
|
if (isMediaEditable(editable) && !buttonOnMedia) {
|
|
21967
23719
|
e.preventDefault();
|
|
21968
23720
|
e.stopPropagation();
|
|
@@ -21997,11 +23749,6 @@ function OhhwellsBridge() {
|
|
|
21997
23749
|
const hrefLookupTarget = buttonOnMedia ? clickedButton : editable;
|
|
21998
23750
|
const hrefCtx = getHrefKeyFromElement(hrefLookupTarget);
|
|
21999
23751
|
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
22000
|
-
console.log("[click-debug 2]", {
|
|
22001
|
-
hrefLookupTargetTag: hrefLookupTarget.tagName,
|
|
22002
|
-
hrefCtx: hrefCtx ? { key: hrefCtx.key } : null,
|
|
22003
|
-
navAnchorTag: navAnchor?.tagName ?? null
|
|
22004
|
-
});
|
|
22005
23752
|
if (navAnchor) {
|
|
22006
23753
|
e.preventDefault();
|
|
22007
23754
|
e.stopPropagation();
|
|
@@ -22517,6 +24264,20 @@ function OhhwellsBridge() {
|
|
|
22517
24264
|
}
|
|
22518
24265
|
return;
|
|
22519
24266
|
}
|
|
24267
|
+
const navbarCtaHit = findNavbarCtaAtPoint(x, y);
|
|
24268
|
+
if (navbarCtaHit) {
|
|
24269
|
+
hoveredNavContainerRef.current = null;
|
|
24270
|
+
setHoveredNavContainerRect(null);
|
|
24271
|
+
if (selected !== navbarCtaHit && !selected?.contains(navbarCtaHit)) {
|
|
24272
|
+
clearHrefKeyHover(navbarCtaHit);
|
|
24273
|
+
hoveredItemElRef.current = navbarCtaHit;
|
|
24274
|
+
setHoveredItemRect(navbarCtaHit.getBoundingClientRect());
|
|
24275
|
+
} else if (hoveredItemElRef.current === navbarCtaHit) {
|
|
24276
|
+
hoveredItemElRef.current = null;
|
|
24277
|
+
setHoveredItemRect(null);
|
|
24278
|
+
}
|
|
24279
|
+
return;
|
|
24280
|
+
}
|
|
22520
24281
|
const navContainers = Array.from(
|
|
22521
24282
|
document.querySelectorAll("[data-ohw-nav-container]")
|
|
22522
24283
|
);
|
|
@@ -22619,6 +24380,24 @@ function OhhwellsBridge() {
|
|
|
22619
24380
|
return;
|
|
22620
24381
|
}
|
|
22621
24382
|
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
24383
|
+
if (!isDragOver) {
|
|
24384
|
+
const buttonHit = findButtonAtPoint(x, y);
|
|
24385
|
+
if (buttonHit) {
|
|
24386
|
+
dismissImageHover();
|
|
24387
|
+
if (findNavbarCtaAtPoint(x, y)) {
|
|
24388
|
+
probeNavigationHoverAt(x, y);
|
|
24389
|
+
return;
|
|
24390
|
+
}
|
|
24391
|
+
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
24392
|
+
const selected = selectedElRef.current;
|
|
24393
|
+
if (selected !== buttonHit && !selected?.contains(buttonHit)) {
|
|
24394
|
+
clearHrefKeyHover(buttonHit);
|
|
24395
|
+
hoveredItemElRef.current = buttonHit;
|
|
24396
|
+
setHoveredItemRect(buttonHit.getBoundingClientRect());
|
|
24397
|
+
}
|
|
24398
|
+
return;
|
|
24399
|
+
}
|
|
24400
|
+
}
|
|
22622
24401
|
if (isPointOverNavigation(x, y)) {
|
|
22623
24402
|
dismissImageHover();
|
|
22624
24403
|
probeNavigationHoverAt(x, y);
|
|
@@ -23040,6 +24819,11 @@ function OhhwellsBridge() {
|
|
|
23040
24819
|
return;
|
|
23041
24820
|
}
|
|
23042
24821
|
if (onNavDragOver(e)) return;
|
|
24822
|
+
if (buttonCollectionDragRef.current) {
|
|
24823
|
+
e.preventDefault();
|
|
24824
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
24825
|
+
return;
|
|
24826
|
+
}
|
|
23043
24827
|
e.preventDefault();
|
|
23044
24828
|
const el = findImageAtPoint(e.clientX, e.clientY, false);
|
|
23045
24829
|
if (!el) {
|
|
@@ -23064,6 +24848,7 @@ function OhhwellsBridge() {
|
|
|
23064
24848
|
};
|
|
23065
24849
|
const handleDrop = (e) => {
|
|
23066
24850
|
e.preventDefault();
|
|
24851
|
+
if (buttonCollectionDragRef.current || navDragRef.current || footerDragRef.current) return;
|
|
23067
24852
|
const el = findImageAtPoint(e.clientX, e.clientY, false);
|
|
23068
24853
|
if (!el) return;
|
|
23069
24854
|
const file = e.dataTransfer?.files?.[0];
|
|
@@ -23419,6 +25204,7 @@ function OhhwellsBridge() {
|
|
|
23419
25204
|
editContentRef.current = { ...editContentRef.current, ...content };
|
|
23420
25205
|
reconcileNavbarItemsFromContent(editContentRef.current);
|
|
23421
25206
|
reconcileFooterOrderFromContent(editContentRef.current);
|
|
25207
|
+
syncButtonsFromContent(document, editContentRef.current);
|
|
23422
25208
|
syncNavigationDragCursorAttrs();
|
|
23423
25209
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
23424
25210
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
@@ -24328,11 +26114,8 @@ function OhhwellsBridge() {
|
|
|
24328
26114
|
};
|
|
24329
26115
|
const handleParentScroll = (e) => {
|
|
24330
26116
|
if (e.data?.type !== "ow:parent-scroll") return;
|
|
24331
|
-
const { iframeOffsetTop, headerH, canvasH } = e.data;
|
|
24332
|
-
parentScrollRef.current = { iframeOffsetTop, headerH, canvasH };
|
|
24333
|
-
if (floatingPanelOpenRef.current) {
|
|
24334
|
-
setParentScrollSnap({ iframeOffsetTop, headerH, canvasH });
|
|
24335
|
-
}
|
|
26117
|
+
const { iframeOffsetTop, headerH, canvasH, promptBarH = 0 } = e.data;
|
|
26118
|
+
parentScrollRef.current = { iframeOffsetTop, headerH, canvasH, promptBarH };
|
|
24336
26119
|
if (visibleViewportRef.current) {
|
|
24337
26120
|
applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
|
|
24338
26121
|
}
|
|
@@ -24722,6 +26505,97 @@ function OhhwellsBridge() {
|
|
|
24722
26505
|
unlockFooterDragInteraction();
|
|
24723
26506
|
};
|
|
24724
26507
|
}, [isEditMode]);
|
|
26508
|
+
(0, import_react19.useEffect)(() => {
|
|
26509
|
+
if (!isEditMode) return;
|
|
26510
|
+
const THRESHOLD = 10;
|
|
26511
|
+
const onPointerDown = (e) => {
|
|
26512
|
+
if (e.button !== 0) return;
|
|
26513
|
+
if (buttonCollectionDragRef.current || navDragRef.current || footerDragRef.current) return;
|
|
26514
|
+
if (buttonPointerDragRef.current) return;
|
|
26515
|
+
const target = e.target;
|
|
26516
|
+
if (!target) return;
|
|
26517
|
+
if (target.closest(
|
|
26518
|
+
'[data-ohw-drag-handle-container], [data-slot="drag-handle"], [data-ohw-toolbar], [data-ohw-item-toolbar-anchor], [data-ohw-link-popover-root], [data-ohw-floating-panel]'
|
|
26519
|
+
)) {
|
|
26520
|
+
return;
|
|
26521
|
+
}
|
|
26522
|
+
const fromTarget = target.closest('[data-ohw-role="navbar-button"]');
|
|
26523
|
+
const anchor = (fromTarget && !fromTarget.closest("[data-ohw-bridge]") ? fromTarget : null) ?? findNavbarCtaAtPoint(e.clientX, e.clientY);
|
|
26524
|
+
if (!anchor || !collectionDragEnabled(anchor)) return;
|
|
26525
|
+
disableNativeHrefDrag(anchor);
|
|
26526
|
+
setMediaHover(null);
|
|
26527
|
+
buttonPointerDragRef.current = {
|
|
26528
|
+
el: anchor,
|
|
26529
|
+
startX: e.clientX,
|
|
26530
|
+
startY: e.clientY,
|
|
26531
|
+
pointerId: e.pointerId,
|
|
26532
|
+
started: false
|
|
26533
|
+
};
|
|
26534
|
+
};
|
|
26535
|
+
const onPointerMove = (e) => {
|
|
26536
|
+
const pending = buttonPointerDragRef.current;
|
|
26537
|
+
if (!pending) return;
|
|
26538
|
+
if (pending.started) {
|
|
26539
|
+
e.preventDefault();
|
|
26540
|
+
clearTextSelection();
|
|
26541
|
+
const dragged = buttonCollectionDragRef.current;
|
|
26542
|
+
if (!dragged) return;
|
|
26543
|
+
refreshButtonDragVisuals(dragged, e.clientX, e.clientY);
|
|
26544
|
+
return;
|
|
26545
|
+
}
|
|
26546
|
+
const dx = e.clientX - pending.startX;
|
|
26547
|
+
const dy = e.clientY - pending.startY;
|
|
26548
|
+
if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
|
|
26549
|
+
e.preventDefault();
|
|
26550
|
+
pending.started = true;
|
|
26551
|
+
armFooterPressDrag();
|
|
26552
|
+
clearTextSelection();
|
|
26553
|
+
try {
|
|
26554
|
+
document.body.setPointerCapture(pending.pointerId);
|
|
26555
|
+
} catch {
|
|
26556
|
+
}
|
|
26557
|
+
if (linkPopoverOpenRef.current) setLinkPopoverRef.current(null);
|
|
26558
|
+
if (activeElRef.current) deactivateRef.current();
|
|
26559
|
+
ensureNavbarButtonCollection(pending.el, editContentRef.current);
|
|
26560
|
+
buttonCollectionDragRef.current = pending.el;
|
|
26561
|
+
lockFooterDuringDrag();
|
|
26562
|
+
setIsItemDragging(true);
|
|
26563
|
+
refreshButtonDragVisuals(pending.el, e.clientX, e.clientY);
|
|
26564
|
+
};
|
|
26565
|
+
const endPointerDrag = (e) => {
|
|
26566
|
+
const pending = buttonPointerDragRef.current;
|
|
26567
|
+
buttonPointerDragRef.current = null;
|
|
26568
|
+
try {
|
|
26569
|
+
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
26570
|
+
document.body.releasePointerCapture(e.pointerId);
|
|
26571
|
+
}
|
|
26572
|
+
} catch {
|
|
26573
|
+
}
|
|
26574
|
+
if (!pending) return;
|
|
26575
|
+
if (!pending.started) {
|
|
26576
|
+
unlockFooterDragInteraction();
|
|
26577
|
+
return;
|
|
26578
|
+
}
|
|
26579
|
+
suppressNextClickRef.current = true;
|
|
26580
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
26581
|
+
persistButtonCollectionDrag(pending.el, e.clientX);
|
|
26582
|
+
};
|
|
26583
|
+
const blockSelectStart = (e) => {
|
|
26584
|
+
if (buttonCollectionDragRef.current || buttonPointerDragRef.current?.started) e.preventDefault();
|
|
26585
|
+
};
|
|
26586
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
26587
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
26588
|
+
document.addEventListener("pointerup", endPointerDrag, true);
|
|
26589
|
+
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
26590
|
+
document.addEventListener("selectstart", blockSelectStart, true);
|
|
26591
|
+
return () => {
|
|
26592
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
26593
|
+
document.removeEventListener("pointermove", onPointerMove, true);
|
|
26594
|
+
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
26595
|
+
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
26596
|
+
document.removeEventListener("selectstart", blockSelectStart, true);
|
|
26597
|
+
};
|
|
26598
|
+
}, [isEditMode, persistButtonCollectionDrag, refreshButtonDragVisuals]);
|
|
24725
26599
|
(0, import_react19.useEffect)(() => {
|
|
24726
26600
|
const handler = (e) => {
|
|
24727
26601
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
@@ -24762,7 +26636,7 @@ function OhhwellsBridge() {
|
|
|
24762
26636
|
postToParent2({
|
|
24763
26637
|
type: "ow:ready",
|
|
24764
26638
|
version: "1",
|
|
24765
|
-
bridgeVersion: "0.1.
|
|
26639
|
+
bridgeVersion: "0.1.121",
|
|
24766
26640
|
path: pathname,
|
|
24767
26641
|
nodes: collectEditableNodes(editContentRef.current),
|
|
24768
26642
|
sections
|
|
@@ -24841,12 +26715,12 @@ function OhhwellsBridge() {
|
|
|
24841
26715
|
return;
|
|
24842
26716
|
}
|
|
24843
26717
|
if (type !== "ow:logo-size-set") return;
|
|
24844
|
-
const
|
|
24845
|
-
if (!Number.isFinite(
|
|
24846
|
-
const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx:
|
|
26718
|
+
const px2 = Number(e.data.px);
|
|
26719
|
+
if (!Number.isFinite(px2)) return;
|
|
26720
|
+
const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px2, mobileFollowing: false } : {
|
|
24847
26721
|
...logoSizeDraft,
|
|
24848
|
-
desktopPx:
|
|
24849
|
-
mobilePx: logoSizeDraft.mobileFollowing ?
|
|
26722
|
+
desktopPx: px2,
|
|
26723
|
+
mobilePx: logoSizeDraft.mobileFollowing ? px2 : logoSizeDraft.mobilePx
|
|
24850
26724
|
};
|
|
24851
26725
|
setLogoSizeDraft(next);
|
|
24852
26726
|
persistLogoSizeDraft(session.placement, next);
|
|
@@ -24944,6 +26818,36 @@ function OhhwellsBridge() {
|
|
|
24944
26818
|
const handleDuplicateSelected = (0, import_react19.useCallback)(() => {
|
|
24945
26819
|
const selected = selectedElRef.current;
|
|
24946
26820
|
if (!selected || !isNavigationItem2(selected)) return;
|
|
26821
|
+
if (isCtaButton(selected)) {
|
|
26822
|
+
const id = buttonId(selected);
|
|
26823
|
+
if (!id) return;
|
|
26824
|
+
const tokens = tokensForButton(selected, true);
|
|
26825
|
+
if (!readAssignments(editContentRef.current)[id]) {
|
|
26826
|
+
const assignment = assignmentFor(selected, editContentRef.current, tokens);
|
|
26827
|
+
const assignments = withAssignment(editContentRef.current, id, assignment);
|
|
26828
|
+
editContentRef.current = {
|
|
26829
|
+
...editContentRef.current,
|
|
26830
|
+
[BUTTON_ASSIGNMENTS_KEY]: JSON.stringify(assignments)
|
|
26831
|
+
};
|
|
26832
|
+
applyButtonStyle(selected, assignment, tokens);
|
|
26833
|
+
}
|
|
26834
|
+
const result = duplicateButton(selected, editContentRef.current);
|
|
26835
|
+
if (!result) return;
|
|
26836
|
+
editContentRef.current = result.content;
|
|
26837
|
+
const copyHref = result.copy.getAttribute("data-ohw-href-key");
|
|
26838
|
+
const copyHrefVal = copyHref ? result.content[copyHref] : void 0;
|
|
26839
|
+
if (copyHref && copyHrefVal !== void 0) applyLinkByKey(copyHref, copyHrefVal);
|
|
26840
|
+
postToParent2({ type: "ow:change", nodes: result.nodes });
|
|
26841
|
+
enforceLinkHrefs();
|
|
26842
|
+
requestAnimationFrame(() => {
|
|
26843
|
+
selectRef.current(result.copy);
|
|
26844
|
+
requestAnimationFrame(() => {
|
|
26845
|
+
const el = selectedElRef.current;
|
|
26846
|
+
if (el?.isConnected) setToolbarRect(el.getBoundingClientRect());
|
|
26847
|
+
});
|
|
26848
|
+
});
|
|
26849
|
+
return;
|
|
26850
|
+
}
|
|
24947
26851
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
24948
26852
|
if (!hrefKey) return;
|
|
24949
26853
|
const social = getSocialItem(selected);
|
|
@@ -25073,7 +26977,7 @@ function OhhwellsBridge() {
|
|
|
25073
26977
|
selectRef.current(result.anchor);
|
|
25074
26978
|
});
|
|
25075
26979
|
}
|
|
25076
|
-
}, [postToParent2]);
|
|
26980
|
+
}, [postToParent2, tokensForButton]);
|
|
25077
26981
|
const runPendingDeleteUndo = (0, import_react19.useCallback)(() => {
|
|
25078
26982
|
const pending = pendingDeleteUndoRef.current;
|
|
25079
26983
|
if (!pending) return false;
|
|
@@ -25085,6 +26989,38 @@ function OhhwellsBridge() {
|
|
|
25085
26989
|
const handleDeleteSelected = (0, import_react19.useCallback)(() => {
|
|
25086
26990
|
const selected = selectedElRef.current;
|
|
25087
26991
|
if (!selected) return false;
|
|
26992
|
+
if (isCtaButton(selected)) {
|
|
26993
|
+
if (!canDeleteButton(selected)) return false;
|
|
26994
|
+
const previousContent = editContentRef.current;
|
|
26995
|
+
const result = deleteButton(selected, previousContent);
|
|
26996
|
+
if (!result) return false;
|
|
26997
|
+
editContentRef.current = result.content;
|
|
26998
|
+
postToParent2({ type: "ow:change", nodes: result.nodes });
|
|
26999
|
+
const actionId = typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `delete-${Date.now()}`;
|
|
27000
|
+
const restoreNodes = result.nodes.map((node) => ({
|
|
27001
|
+
key: node.key,
|
|
27002
|
+
text: previousContent[node.key] ?? ""
|
|
27003
|
+
}));
|
|
27004
|
+
pendingDeleteUndoRef.current = {
|
|
27005
|
+
actionId,
|
|
27006
|
+
restore: () => {
|
|
27007
|
+
result.undo();
|
|
27008
|
+
editContentRef.current = { ...editContentRef.current, ...Object.fromEntries(restoreNodes.map((node) => [node.key, node.text])) };
|
|
27009
|
+
postToParent2({ type: "ow:change", nodes: restoreNodes });
|
|
27010
|
+
syncButtonsFromContent(document, editContentRef.current);
|
|
27011
|
+
}
|
|
27012
|
+
};
|
|
27013
|
+
deselectRef.current();
|
|
27014
|
+
postToParent2({
|
|
27015
|
+
type: "ow:toast",
|
|
27016
|
+
title: "Button deleted",
|
|
27017
|
+
toastType: "success",
|
|
27018
|
+
actionLabel: "Undo",
|
|
27019
|
+
actionId,
|
|
27020
|
+
duration: 6e3
|
|
27021
|
+
});
|
|
27022
|
+
return true;
|
|
27023
|
+
}
|
|
25088
27024
|
return deleteSelectedNavFooterItem({
|
|
25089
27025
|
selected,
|
|
25090
27026
|
isTextEditing: Boolean(activeElRef.current),
|
|
@@ -25222,14 +27158,14 @@ function OhhwellsBridge() {
|
|
|
25222
27158
|
},
|
|
25223
27159
|
[postToParent2]
|
|
25224
27160
|
);
|
|
25225
|
-
return /* @__PURE__ */ (0,
|
|
25226
|
-
/* @__PURE__ */ (0,
|
|
25227
|
-
/* @__PURE__ */ (0,
|
|
25228
|
-
subdomain && !isEditMode && showBranding && /* @__PURE__ */ (0,
|
|
27161
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
|
|
27162
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { id: "ohw-loader", suppressHydrationWarning: true, style: { ...OHW_LOADER_STYLE, display: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(OhwLoaderSpinner, {}) }),
|
|
27163
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("script", { suppressHydrationWarning: true, dangerouslySetInnerHTML: { __html: OHW_LOADER_PREHYDRATE_SCRIPT } }),
|
|
27164
|
+
subdomain && !isEditMode && showBranding && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(MadeWithOhhWells, {}),
|
|
25229
27165
|
bridgeRoot ? (0, import_react_dom5.createPortal)(
|
|
25230
|
-
/* @__PURE__ */ (0,
|
|
25231
|
-
/* @__PURE__ */ (0,
|
|
25232
|
-
isEditMode && /* @__PURE__ */ (0,
|
|
27166
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
|
|
27167
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
27168
|
+
isEditMode && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25233
27169
|
AiSectionOverlay,
|
|
25234
27170
|
{
|
|
25235
27171
|
postToParent: postToParent2,
|
|
@@ -25237,7 +27173,7 @@ function OhhwellsBridge() {
|
|
|
25237
27173
|
onSelectionChange: handleAiSectionSelectionChange
|
|
25238
27174
|
}
|
|
25239
27175
|
),
|
|
25240
|
-
isEditMode && /* @__PURE__ */ (0,
|
|
27176
|
+
isEditMode && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25241
27177
|
AiMediaStripOverlay,
|
|
25242
27178
|
{
|
|
25243
27179
|
postToParent: postToParent2,
|
|
@@ -25246,7 +27182,7 @@ function OhhwellsBridge() {
|
|
|
25246
27182
|
clearInteractionChromeRef
|
|
25247
27183
|
}
|
|
25248
27184
|
),
|
|
25249
|
-
isEditMode && /* @__PURE__ */ (0,
|
|
27185
|
+
isEditMode && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25250
27186
|
AiPricingCardOverlay,
|
|
25251
27187
|
{
|
|
25252
27188
|
postToParent: postToParent2,
|
|
@@ -25254,12 +27190,12 @@ function OhhwellsBridge() {
|
|
|
25254
27190
|
applyTreeLocalRef
|
|
25255
27191
|
}
|
|
25256
27192
|
),
|
|
25257
|
-
isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ (0,
|
|
27193
|
+
isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25258
27194
|
"div",
|
|
25259
27195
|
{
|
|
25260
27196
|
className: "pointer-events-none fixed z-2147483646",
|
|
25261
27197
|
style: { left: slot.left, top: slot.y, width: slot.width, height: 3, transform: "translateY(-50%)" },
|
|
25262
|
-
children: /* @__PURE__ */ (0,
|
|
27198
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25263
27199
|
DropIndicator,
|
|
25264
27200
|
{
|
|
25265
27201
|
direction: "horizontal",
|
|
@@ -25270,7 +27206,7 @@ function OhhwellsBridge() {
|
|
|
25270
27206
|
},
|
|
25271
27207
|
`section-drop-${slot.insertIndex}-${i}`
|
|
25272
27208
|
)),
|
|
25273
|
-
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0,
|
|
27209
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25274
27210
|
MediaOverlay,
|
|
25275
27211
|
{
|
|
25276
27212
|
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
@@ -25281,7 +27217,7 @@ function OhhwellsBridge() {
|
|
|
25281
27217
|
},
|
|
25282
27218
|
`uploading-${key}`
|
|
25283
27219
|
)),
|
|
25284
|
-
mediaHover && !(mediaHover.key in uploadingRects) && mediaHover.key !== selectedMedia?.key && /* @__PURE__ */ (0,
|
|
27220
|
+
mediaHover && !(mediaHover.key in uploadingRects) && mediaHover.key !== selectedMedia?.key && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25285
27221
|
MediaOverlay,
|
|
25286
27222
|
{
|
|
25287
27223
|
hover: mediaHover,
|
|
@@ -25292,7 +27228,7 @@ function OhhwellsBridge() {
|
|
|
25292
27228
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
25293
27229
|
}
|
|
25294
27230
|
),
|
|
25295
|
-
selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */ (0,
|
|
27231
|
+
selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25296
27232
|
MediaOverlay,
|
|
25297
27233
|
{
|
|
25298
27234
|
hover: selectedMedia,
|
|
@@ -25304,7 +27240,7 @@ function OhhwellsBridge() {
|
|
|
25304
27240
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
25305
27241
|
}
|
|
25306
27242
|
),
|
|
25307
|
-
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0,
|
|
27243
|
+
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25308
27244
|
CarouselOverlay,
|
|
25309
27245
|
{
|
|
25310
27246
|
hover: carouselHover,
|
|
@@ -25312,10 +27248,10 @@ function OhhwellsBridge() {
|
|
|
25312
27248
|
cueOnly: !!carouselHover.fullBleedSectionId && carouselHover.fullBleedSectionId !== selectedAiSectionId
|
|
25313
27249
|
}
|
|
25314
27250
|
),
|
|
25315
|
-
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0,
|
|
25316
|
-
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0,
|
|
25317
|
-
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0,
|
|
25318
|
-
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0,
|
|
27251
|
+
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
27252
|
+
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
27253
|
+
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && selectedElRef.current !== buttonCollectionDragRef.current && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
27254
|
+
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25319
27255
|
"div",
|
|
25320
27256
|
{
|
|
25321
27257
|
className: "pointer-events-none fixed z-2147483646",
|
|
@@ -25325,7 +27261,7 @@ function OhhwellsBridge() {
|
|
|
25325
27261
|
width: slot.width,
|
|
25326
27262
|
height: slot.height
|
|
25327
27263
|
},
|
|
25328
|
-
children: /* @__PURE__ */ (0,
|
|
27264
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25329
27265
|
DropIndicator,
|
|
25330
27266
|
{
|
|
25331
27267
|
direction: slot.direction,
|
|
@@ -25336,7 +27272,7 @@ function OhhwellsBridge() {
|
|
|
25336
27272
|
},
|
|
25337
27273
|
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
25338
27274
|
)),
|
|
25339
|
-
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0,
|
|
27275
|
+
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25340
27276
|
"div",
|
|
25341
27277
|
{
|
|
25342
27278
|
className: "pointer-events-none fixed z-2147483646",
|
|
@@ -25346,7 +27282,7 @@ function OhhwellsBridge() {
|
|
|
25346
27282
|
width: slot.width,
|
|
25347
27283
|
height: slot.height
|
|
25348
27284
|
},
|
|
25349
|
-
children: /* @__PURE__ */ (0,
|
|
27285
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25350
27286
|
DropIndicator,
|
|
25351
27287
|
{
|
|
25352
27288
|
direction: slot.direction,
|
|
@@ -25357,10 +27293,31 @@ function OhhwellsBridge() {
|
|
|
25357
27293
|
},
|
|
25358
27294
|
`nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
|
|
25359
27295
|
)),
|
|
25360
|
-
|
|
25361
|
-
|
|
25362
|
-
|
|
25363
|
-
|
|
27296
|
+
isItemDragging && buttonDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
27297
|
+
"div",
|
|
27298
|
+
{
|
|
27299
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
27300
|
+
style: {
|
|
27301
|
+
left: slot.left,
|
|
27302
|
+
top: slot.top,
|
|
27303
|
+
width: slot.width,
|
|
27304
|
+
height: slot.height
|
|
27305
|
+
},
|
|
27306
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
27307
|
+
DropIndicator,
|
|
27308
|
+
{
|
|
27309
|
+
direction: slot.direction,
|
|
27310
|
+
state: activeButtonDropIndex === i ? "dragActive" : "dragIdle",
|
|
27311
|
+
className: "!h-full !w-full"
|
|
27312
|
+
}
|
|
27313
|
+
)
|
|
27314
|
+
},
|
|
27315
|
+
`button-drop-${slot.direction}-${slot.insertIndex}-${i}`
|
|
27316
|
+
)),
|
|
27317
|
+
hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
27318
|
+
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
27319
|
+
hoveredTextRect && !hoveredNavContainerRect && !hoveredItemRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
|
|
27320
|
+
formPickRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25364
27321
|
ItemInteractionLayer,
|
|
25365
27322
|
{
|
|
25366
27323
|
rect: formPickRect,
|
|
@@ -25368,13 +27325,13 @@ function OhhwellsBridge() {
|
|
|
25368
27325
|
itemDragSurface: false,
|
|
25369
27326
|
toolbarAlign: "left",
|
|
25370
27327
|
chromeGap: 24,
|
|
25371
|
-
toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0,
|
|
27328
|
+
toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
25372
27329
|
"div",
|
|
25373
27330
|
{
|
|
25374
27331
|
"data-ohw-form-toolbar": "",
|
|
25375
27332
|
className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
|
|
25376
27333
|
children: [
|
|
25377
|
-
/* @__PURE__ */ (0,
|
|
27334
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25378
27335
|
"button",
|
|
25379
27336
|
{
|
|
25380
27337
|
type: "button",
|
|
@@ -25382,11 +27339,11 @@ function OhhwellsBridge() {
|
|
|
25382
27339
|
className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
|
|
25383
27340
|
onClick: () => setFieldTypePickerOpen((open) => !open),
|
|
25384
27341
|
"data-ohw-add-field": "",
|
|
25385
|
-
children: /* @__PURE__ */ (0,
|
|
27342
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react20.Plus, { size: 15, "aria-hidden": true })
|
|
25386
27343
|
}
|
|
25387
27344
|
),
|
|
25388
|
-
/* @__PURE__ */ (0,
|
|
25389
|
-
/* @__PURE__ */ (0,
|
|
27345
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
27346
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
25390
27347
|
"button",
|
|
25391
27348
|
{
|
|
25392
27349
|
type: "button",
|
|
@@ -25402,11 +27359,11 @@ function OhhwellsBridge() {
|
|
|
25402
27359
|
});
|
|
25403
27360
|
},
|
|
25404
27361
|
children: [
|
|
25405
|
-
/* @__PURE__ */ (0,
|
|
27362
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react20.Settings, { size: 14, "aria-hidden": true }),
|
|
25406
27363
|
"Form settings",
|
|
25407
27364
|
formPickCount ? (
|
|
25408
27365
|
// Counter pill, per the design — not a text suffix.
|
|
25409
|
-
/* @__PURE__ */ (0,
|
|
27366
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25410
27367
|
"span",
|
|
25411
27368
|
{
|
|
25412
27369
|
"data-ohw-form-count": "",
|
|
@@ -25418,8 +27375,8 @@ function OhhwellsBridge() {
|
|
|
25418
27375
|
]
|
|
25419
27376
|
}
|
|
25420
27377
|
),
|
|
25421
|
-
/* @__PURE__ */ (0,
|
|
25422
|
-
/* @__PURE__ */ (0,
|
|
27378
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
27379
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25423
27380
|
"button",
|
|
25424
27381
|
{
|
|
25425
27382
|
type: "button",
|
|
@@ -25450,7 +27407,7 @@ function OhhwellsBridge() {
|
|
|
25450
27407
|
)
|
|
25451
27408
|
}
|
|
25452
27409
|
),
|
|
25453
|
-
formHoverRect && !isItemDragging && /* @__PURE__ */ (0,
|
|
27410
|
+
formHoverRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25454
27411
|
ItemInteractionLayer,
|
|
25455
27412
|
{
|
|
25456
27413
|
rect: formHoverRect,
|
|
@@ -25458,7 +27415,7 @@ function OhhwellsBridge() {
|
|
|
25458
27415
|
chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
|
|
25459
27416
|
}
|
|
25460
27417
|
),
|
|
25461
|
-
fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0,
|
|
27418
|
+
fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25462
27419
|
ItemInteractionLayer,
|
|
25463
27420
|
{
|
|
25464
27421
|
rect: fieldPickRect,
|
|
@@ -25470,7 +27427,7 @@ function OhhwellsBridge() {
|
|
|
25470
27427
|
dragHandleLabel: "Reorder field",
|
|
25471
27428
|
onDragHandleDragStart: handleFieldDragStart,
|
|
25472
27429
|
onDragHandleDragEnd: handleFieldDragEnd,
|
|
25473
|
-
toolbar: /* @__PURE__ */ (0,
|
|
27430
|
+
toolbar: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25474
27431
|
FormFieldToolbar,
|
|
25475
27432
|
{
|
|
25476
27433
|
type: fieldPickState.type,
|
|
@@ -25483,12 +27440,12 @@ function OhhwellsBridge() {
|
|
|
25483
27440
|
)
|
|
25484
27441
|
}
|
|
25485
27442
|
),
|
|
25486
|
-
fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0,
|
|
27443
|
+
fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25487
27444
|
"div",
|
|
25488
27445
|
{
|
|
25489
27446
|
className: "pointer-events-none fixed z-[2147483644]",
|
|
25490
27447
|
style: { top: slot.top, left: slot.left, width: slot.width },
|
|
25491
|
-
children: /* @__PURE__ */ (0,
|
|
27448
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25492
27449
|
DropIndicator,
|
|
25493
27450
|
{
|
|
25494
27451
|
direction: "horizontal",
|
|
@@ -25501,7 +27458,7 @@ function OhhwellsBridge() {
|
|
|
25501
27458
|
)) : null,
|
|
25502
27459
|
fieldTypePickerOpen && formPickRect ? (() => {
|
|
25503
27460
|
const toolbar = document.querySelector("[data-ohw-form-toolbar]")?.getBoundingClientRect();
|
|
25504
|
-
return /* @__PURE__ */ (0,
|
|
27461
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25505
27462
|
"div",
|
|
25506
27463
|
{
|
|
25507
27464
|
className: "pointer-events-none fixed z-[2147483645]",
|
|
@@ -25509,12 +27466,12 @@ function OhhwellsBridge() {
|
|
|
25509
27466
|
top: toolbar ? toolbar.bottom + 6 : formPickRect.top + 16,
|
|
25510
27467
|
left: toolbar ? toolbar.left : formPickRect.left + 24
|
|
25511
27468
|
},
|
|
25512
|
-
children: /* @__PURE__ */ (0,
|
|
27469
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(FieldTypePicker, { onPick: handleAddField })
|
|
25513
27470
|
}
|
|
25514
27471
|
);
|
|
25515
27472
|
})() : null,
|
|
25516
|
-
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0,
|
|
25517
|
-
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0,
|
|
27473
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
|
|
27474
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25518
27475
|
FooterContainerChrome,
|
|
25519
27476
|
{
|
|
25520
27477
|
rect: toolbarRect,
|
|
@@ -25522,13 +27479,17 @@ function OhhwellsBridge() {
|
|
|
25522
27479
|
addDisabled: !canAddFooterColumn()
|
|
25523
27480
|
}
|
|
25524
27481
|
),
|
|
25525
|
-
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0,
|
|
27482
|
+
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25526
27483
|
ItemInteractionLayer,
|
|
25527
27484
|
{
|
|
25528
|
-
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
|
|
27485
|
+
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected || selectedElRef.current === buttonCollectionDragRef.current) ? draggedItemRect : toolbarRect,
|
|
25529
27486
|
toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
|
|
25530
27487
|
toolbarBelowEl: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanel(selectedElRef.current) : null,
|
|
25531
27488
|
elRef: glowElRef,
|
|
27489
|
+
hidden: isRectOutsideClip(
|
|
27490
|
+
isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected || selectedElRef.current === buttonCollectionDragRef.current) ? draggedItemRect : toolbarRect,
|
|
27491
|
+
getIframeVisibleClip(parentScrollRef.current)
|
|
27492
|
+
),
|
|
25532
27493
|
state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanel(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
25533
27494
|
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
|
|
25534
27495
|
dragDisabled: reorderDragDisabled,
|
|
@@ -25538,18 +27499,25 @@ function OhhwellsBridge() {
|
|
|
25538
27499
|
onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
|
|
25539
27500
|
onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
|
|
25540
27501
|
itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection && !selectedIsSocialsRow,
|
|
25541
|
-
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0,
|
|
27502
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25542
27503
|
ItemActionToolbar,
|
|
25543
27504
|
{
|
|
25544
27505
|
onEditLink: openLinkPopoverForSelected,
|
|
25545
27506
|
onStyle: () => {
|
|
25546
27507
|
const row = selectedElRef.current;
|
|
25547
27508
|
if (!row) return;
|
|
25548
|
-
|
|
27509
|
+
suppressNextClickRef.current = true;
|
|
27510
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
27511
|
+
if (isCtaButton(row)) {
|
|
27512
|
+
if (floatingPanelRef.current?.kind === "button-style") closeFloatingPanelOnly();
|
|
27513
|
+
else openButtonStylePanel(row);
|
|
27514
|
+
return;
|
|
27515
|
+
}
|
|
27516
|
+
if (floatingPanelRef.current?.kind === "socials-display") closeFloatingPanelOnly();
|
|
25549
27517
|
else openSocialsDisplayPanel(row);
|
|
25550
27518
|
},
|
|
25551
|
-
showStyle: selectedIsSocialsRow,
|
|
25552
|
-
styleActive: floatingPanel?.kind === "socials-display",
|
|
27519
|
+
showStyle: selectedIsSocialsRow || selectedIsCta,
|
|
27520
|
+
styleActive: floatingPanel?.kind === "socials-display" || floatingPanel?.kind === "button-style",
|
|
25553
27521
|
onAddItem: handleAddChildItem,
|
|
25554
27522
|
onSelectParent: handleSelectParent,
|
|
25555
27523
|
onDuplicate: handleDuplicateSelected,
|
|
@@ -25560,11 +27528,11 @@ function OhhwellsBridge() {
|
|
|
25560
27528
|
})(),
|
|
25561
27529
|
editLinkDisabled: false,
|
|
25562
27530
|
moreDisabled: false,
|
|
25563
|
-
deleteDisabled: selectedElRef.current !== null && (() => {
|
|
27531
|
+
deleteDisabled: selectedElRef.current !== null && isCtaButton(selectedElRef.current) && !canDeleteButton(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
25564
27532
|
const social = getSocialItem(selectedElRef.current);
|
|
25565
27533
|
return social ? !canRemoveSocialItem(social) : false;
|
|
25566
27534
|
})(),
|
|
25567
|
-
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow || selectedElRef.current !== null && (() => {
|
|
27535
|
+
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow || selectedElRef.current !== null && isCtaButton(selectedElRef.current) && !canDuplicateButton(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
25568
27536
|
const social = getSocialItem(selectedElRef.current);
|
|
25569
27537
|
const row = social ? findSocialsRow(social) : null;
|
|
25570
27538
|
return row ? !canAddSocialItem(row) : false;
|
|
@@ -25573,7 +27541,7 @@ function OhhwellsBridge() {
|
|
|
25573
27541
|
showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
|
|
25574
27542
|
selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
|
|
25575
27543
|
),
|
|
25576
|
-
showMore:
|
|
27544
|
+
showMore: !selectedIsSocialsRow,
|
|
25577
27545
|
dropdownOpen: navDropdownPreviewOpen,
|
|
25578
27546
|
onDropdownOpenChange: handleNavDropdownOpenChange,
|
|
25579
27547
|
headingVisible: footerHeadingVisible,
|
|
@@ -25582,8 +27550,8 @@ function OhhwellsBridge() {
|
|
|
25582
27550
|
) : void 0
|
|
25583
27551
|
}
|
|
25584
27552
|
),
|
|
25585
|
-
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && !isRectOutsideClip(toolbarRect, getIframeVisibleClip(parentScrollRef.current)) && /* @__PURE__ */ (0,
|
|
25586
|
-
/* @__PURE__ */ (0,
|
|
27553
|
+
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && !isRectOutsideClip(toolbarRect, getIframeVisibleClip(parentScrollRef.current)) && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
|
|
27554
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25587
27555
|
EditGlowChrome,
|
|
25588
27556
|
{
|
|
25589
27557
|
rect: toolbarRect,
|
|
@@ -25593,7 +27561,7 @@ function OhhwellsBridge() {
|
|
|
25593
27561
|
hideHandle: isItemDragging
|
|
25594
27562
|
}
|
|
25595
27563
|
),
|
|
25596
|
-
/* @__PURE__ */ (0,
|
|
27564
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25597
27565
|
FloatingToolbar,
|
|
25598
27566
|
{
|
|
25599
27567
|
rect: toolbarRect,
|
|
@@ -25606,7 +27574,7 @@ function OhhwellsBridge() {
|
|
|
25606
27574
|
}
|
|
25607
27575
|
)
|
|
25608
27576
|
] }),
|
|
25609
|
-
maxBadge && /* @__PURE__ */ (0,
|
|
27577
|
+
maxBadge && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
25610
27578
|
"div",
|
|
25611
27579
|
{
|
|
25612
27580
|
"data-ohw-max-badge": "",
|
|
@@ -25632,7 +27600,7 @@ function OhhwellsBridge() {
|
|
|
25632
27600
|
]
|
|
25633
27601
|
}
|
|
25634
27602
|
),
|
|
25635
|
-
toggleState && !linkPopover && /* @__PURE__ */ (0,
|
|
27603
|
+
toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25636
27604
|
StateToggle,
|
|
25637
27605
|
{
|
|
25638
27606
|
rect: toggleState.rect,
|
|
@@ -25641,15 +27609,15 @@ function OhhwellsBridge() {
|
|
|
25641
27609
|
onStateChange: handleStateChange
|
|
25642
27610
|
}
|
|
25643
27611
|
),
|
|
25644
|
-
sectionGap && !linkPopover && /* @__PURE__ */ (0,
|
|
27612
|
+
sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
|
|
25645
27613
|
"div",
|
|
25646
27614
|
{
|
|
25647
27615
|
"data-ohw-section-insert-line": "",
|
|
25648
27616
|
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
25649
27617
|
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
25650
27618
|
children: [
|
|
25651
|
-
/* @__PURE__ */ (0,
|
|
25652
|
-
/* @__PURE__ */ (0,
|
|
27619
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } }),
|
|
27620
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25653
27621
|
Badge,
|
|
25654
27622
|
{
|
|
25655
27623
|
className: "px-8 py-1 bg-bridge-primary hover:bg-bridge-primary text-primary-foreground text-xs font-medium shrink-0 rounded-full cursor-pointer pointer-events-auto",
|
|
@@ -25666,11 +27634,11 @@ function OhhwellsBridge() {
|
|
|
25666
27634
|
children: "Add Section"
|
|
25667
27635
|
}
|
|
25668
27636
|
),
|
|
25669
|
-
/* @__PURE__ */ (0,
|
|
27637
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } })
|
|
25670
27638
|
]
|
|
25671
27639
|
}
|
|
25672
27640
|
),
|
|
25673
|
-
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0,
|
|
27641
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25674
27642
|
LinkPopover,
|
|
25675
27643
|
{
|
|
25676
27644
|
panelRef: linkPopoverPanelRef,
|
|
@@ -25687,7 +27655,7 @@ function OhhwellsBridge() {
|
|
|
25687
27655
|
},
|
|
25688
27656
|
linkPopover.key
|
|
25689
27657
|
) : null,
|
|
25690
|
-
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0,
|
|
27658
|
+
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25691
27659
|
FloatingPanel,
|
|
25692
27660
|
{
|
|
25693
27661
|
open: true,
|
|
@@ -25697,7 +27665,7 @@ function OhhwellsBridge() {
|
|
|
25697
27665
|
onPositionChange: setFloatingPanelPos,
|
|
25698
27666
|
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
25699
27667
|
onClose: closeFloatingPanelOnly,
|
|
25700
|
-
children: /* @__PURE__ */ (0,
|
|
27668
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
25701
27669
|
SocialsDisplayPanel,
|
|
25702
27670
|
{
|
|
25703
27671
|
display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
|
|
@@ -25708,7 +27676,48 @@ function OhhwellsBridge() {
|
|
|
25708
27676
|
}
|
|
25709
27677
|
)
|
|
25710
27678
|
}
|
|
25711
|
-
) : null
|
|
27679
|
+
) : null,
|
|
27680
|
+
floatingPanel && floatingPanel.kind === "button-style" ? (() => {
|
|
27681
|
+
const button = document.querySelector(
|
|
27682
|
+
`[data-ohw-href-key="${CSS.escape(floatingPanel.buttonId)}"]`
|
|
27683
|
+
);
|
|
27684
|
+
if (!button) return null;
|
|
27685
|
+
captureButtonOrigin(button);
|
|
27686
|
+
const tokens = tokensFromButton(button);
|
|
27687
|
+
const current = assignmentFor(button, editContentRef.current, tokens);
|
|
27688
|
+
void buttonStyleTick;
|
|
27689
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
27690
|
+
FloatingPanel,
|
|
27691
|
+
{
|
|
27692
|
+
open: true,
|
|
27693
|
+
title: floatingPanel.title,
|
|
27694
|
+
context: floatingPanel.context,
|
|
27695
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react20.Brush, { className: "size-4 shrink-0", "aria-hidden": true }),
|
|
27696
|
+
position: floatingPanelPos,
|
|
27697
|
+
onPositionChange: setFloatingPanelPos,
|
|
27698
|
+
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
27699
|
+
onClose: closeFloatingPanelOnly,
|
|
27700
|
+
bodyClassName: "gap-5",
|
|
27701
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
27702
|
+
ButtonStylePanel,
|
|
27703
|
+
{
|
|
27704
|
+
variants: tokens.variants,
|
|
27705
|
+
sizes: tokens.sizes,
|
|
27706
|
+
variant: current.variant,
|
|
27707
|
+
size: current.size,
|
|
27708
|
+
slotBackground: previewSlotBackground(button),
|
|
27709
|
+
previewLabel: (button.querySelector(
|
|
27710
|
+
'[data-ohw-editable="text"], [data-ohw-editable="plain"]'
|
|
27711
|
+
)?.textContent ?? button.textContent ?? "Book Now").trim() || "Book Now",
|
|
27712
|
+
onVariant: (variant) => applySelectedButtonStyle({ variant }),
|
|
27713
|
+
onSize: (size) => applySelectedButtonStyle({ size })
|
|
27714
|
+
},
|
|
27715
|
+
floatingPanel.key
|
|
27716
|
+
)
|
|
27717
|
+
},
|
|
27718
|
+
floatingPanel.key
|
|
27719
|
+
);
|
|
27720
|
+
})() : null
|
|
25712
27721
|
] }),
|
|
25713
27722
|
bridgeRoot
|
|
25714
27723
|
) : null
|