@ohhwells/bridge 0.1.120 → 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 +2457 -400
- 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 +2456 -399
- package/dist/index.js.map +1 -1
- package/dist/styles.css +79 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -428,6 +428,40 @@ function applyBrandToDom(kit) {
|
|
|
428
428
|
}
|
|
429
429
|
}
|
|
430
430
|
|
|
431
|
+
// src/lib/custom-code.ts
|
|
432
|
+
var ALLOWED_HEAD_TAGS = /* @__PURE__ */ new Set(["style", "meta", "link", "script", "noscript", "base"]);
|
|
433
|
+
var CUSTOM_CODE_AFTER_HEAD_KEY = "__ohw_custom_code_after_head";
|
|
434
|
+
var CUSTOM_CODE_BEFORE_HEAD_KEY = "__ohw_custom_code_before_head";
|
|
435
|
+
function clearExisting(slot) {
|
|
436
|
+
document.querySelectorAll(`[data-ohw-custom-code="${slot}"]`).forEach((el) => el.remove());
|
|
437
|
+
}
|
|
438
|
+
function buildNodes(raw, slot) {
|
|
439
|
+
if (!raw || !raw.trim()) return [];
|
|
440
|
+
const parsed = new DOMParser().parseFromString(raw, "text/html");
|
|
441
|
+
const source = [...parsed.head.childNodes, ...parsed.body.childNodes];
|
|
442
|
+
const nodes = [];
|
|
443
|
+
for (const node of source) {
|
|
444
|
+
if (node.nodeType !== Node.ELEMENT_NODE) continue;
|
|
445
|
+
const el = node;
|
|
446
|
+
const tag = el.tagName.toLowerCase();
|
|
447
|
+
if (!ALLOWED_HEAD_TAGS.has(tag)) continue;
|
|
448
|
+
const built = document.createElement(tag);
|
|
449
|
+
for (const attr of Array.from(el.attributes)) built.setAttribute(attr.name, attr.value);
|
|
450
|
+
if (tag === "script" || tag === "style" || tag === "noscript") built.textContent = el.textContent;
|
|
451
|
+
built.dataset.ohwCustomCode = slot;
|
|
452
|
+
nodes.push(built);
|
|
453
|
+
}
|
|
454
|
+
return nodes;
|
|
455
|
+
}
|
|
456
|
+
function applyCustomCodeToHead(content) {
|
|
457
|
+
clearExisting("after");
|
|
458
|
+
clearExisting("before");
|
|
459
|
+
const afterNodes = buildNodes(content[CUSTOM_CODE_AFTER_HEAD_KEY], "after");
|
|
460
|
+
if (afterNodes.length > 0) document.head.prepend(...afterNodes);
|
|
461
|
+
const beforeNodes = buildNodes(content[CUSTOM_CODE_BEFORE_HEAD_KEY], "before");
|
|
462
|
+
if (beforeNodes.length > 0) document.head.append(...beforeNodes);
|
|
463
|
+
}
|
|
464
|
+
|
|
431
465
|
// src/lib/section-styles.ts
|
|
432
466
|
var STYLE_STORE_KEY = "__ohw_styles";
|
|
433
467
|
var STYLE_SHEET_ID = "ohw-section-styles";
|
|
@@ -491,9 +525,9 @@ function styleSheetCss() {
|
|
|
491
525
|
);
|
|
492
526
|
}
|
|
493
527
|
const pad = { tight: 40, balanced: 64, airy: 96 };
|
|
494
|
-
for (const [spacing,
|
|
528
|
+
for (const [spacing, px2] of Object.entries(pad)) {
|
|
495
529
|
rules.push(
|
|
496
|
-
`[data-ohw-style-spacing="${spacing}"] { padding-top: ${
|
|
530
|
+
`[data-ohw-style-spacing="${spacing}"] { padding-top: ${px2}px !important; padding-bottom: ${px2}px !important; }`
|
|
497
531
|
);
|
|
498
532
|
}
|
|
499
533
|
rules.push(
|
|
@@ -3060,12 +3094,12 @@ function deriveTemplateButtonStyle() {
|
|
|
3060
3094
|
cs.borderBottomLeftRadius
|
|
3061
3095
|
].map((v) => v || "0px");
|
|
3062
3096
|
const radius = corners.every((v) => v === corners[0]) ? corners[0] : corners.join(" ");
|
|
3063
|
-
const
|
|
3064
|
-
const lineHeight =
|
|
3065
|
-
const contentH = btn.getBoundingClientRect().height -
|
|
3097
|
+
const px2 = (v) => parseFloat(v) || 0;
|
|
3098
|
+
const lineHeight = px2(cs.lineHeight) || px2(cs.fontSize) * 1.2;
|
|
3099
|
+
const contentH = btn.getBoundingClientRect().height - px2(cs.borderTopWidth) - px2(cs.borderBottomWidth);
|
|
3066
3100
|
const impliedY = Math.round(Math.max(0, (contentH - lineHeight) / 2));
|
|
3067
|
-
const padY = Math.max(
|
|
3068
|
-
const padX = Math.max(
|
|
3101
|
+
const padY = Math.max(px2(cs.paddingTop), px2(cs.paddingBottom), impliedY);
|
|
3102
|
+
const padX = Math.max(px2(cs.paddingLeft), px2(cs.paddingRight));
|
|
3069
3103
|
return {
|
|
3070
3104
|
radius: radius || "10px",
|
|
3071
3105
|
padding: `${padY}px ${padX}px`,
|
|
@@ -7982,6 +8016,14 @@ function ItemActionToolbar({
|
|
|
7982
8016
|
e.preventDefault();
|
|
7983
8017
|
e.stopPropagation();
|
|
7984
8018
|
onStyle?.();
|
|
8019
|
+
},
|
|
8020
|
+
// Same as Edit link: mousedown opens the panel and remounts this toolbar
|
|
8021
|
+
// (styleActive flips). Without stopping click, the gesture lands on whatever
|
|
8022
|
+
// is now under the cursor — navbar CTAs park the toolbar below the button, so
|
|
8023
|
+
// that miss deselects and the panel closes as soon as it opens.
|
|
8024
|
+
onClick: (e) => {
|
|
8025
|
+
e.preventDefault();
|
|
8026
|
+
e.stopPropagation();
|
|
7985
8027
|
}
|
|
7986
8028
|
},
|
|
7987
8029
|
children: /* @__PURE__ */ jsx11(Brush, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
@@ -8304,20 +8346,32 @@ function ItemInteractionLayer({
|
|
|
8304
8346
|
itemDragSurface = true,
|
|
8305
8347
|
chromeGap,
|
|
8306
8348
|
toolbarAlign = "center",
|
|
8349
|
+
hidden = false,
|
|
8307
8350
|
className
|
|
8308
8351
|
}) {
|
|
8352
|
+
const localRef = useRef2(null);
|
|
8353
|
+
useLayoutEffect2(() => {
|
|
8354
|
+
const node = localRef.current;
|
|
8355
|
+
if (!node) return;
|
|
8356
|
+
node.style.display = hidden ? "none" : "block";
|
|
8357
|
+
}, [hidden, rect.top, rect.left, rect.width, rect.height, state]);
|
|
8309
8358
|
if (state === "default") return null;
|
|
8310
8359
|
const gap = chromeGap ?? (state === "hover" ? HOVER_CHROME_GAP : SELECTION_CHROME_GAP);
|
|
8311
8360
|
const isActive = state === "active-top" || state === "active-bottom";
|
|
8312
8361
|
const isDragging = state === "dragging";
|
|
8313
8362
|
const showToolbar = isActive && toolbar;
|
|
8314
8363
|
const showDragHandle = (isActive || isDragging) && showHandle;
|
|
8315
|
-
const itemDragEnabled = itemDragSurface && isActive &&
|
|
8364
|
+
const itemDragEnabled = itemDragSurface && isActive && !isDragging && !dragDisabled && Boolean(showHandle || onItemPointerDown);
|
|
8316
8365
|
const useDetachedBelowToolbar = Boolean(showToolbar && state === "active-bottom" && toolbarBelowRect);
|
|
8366
|
+
const setRootRef = (node) => {
|
|
8367
|
+
localRef.current = node;
|
|
8368
|
+
if (typeof elRef === "function") elRef(node);
|
|
8369
|
+
else if (elRef) elRef.current = node;
|
|
8370
|
+
};
|
|
8317
8371
|
return /* @__PURE__ */ jsxs5(
|
|
8318
8372
|
"div",
|
|
8319
8373
|
{
|
|
8320
|
-
ref:
|
|
8374
|
+
ref: setRootRef,
|
|
8321
8375
|
"data-ohw-item-interaction": "",
|
|
8322
8376
|
"data-ohw-item-interaction-state": state,
|
|
8323
8377
|
className: cn("pointer-events-none", className),
|
|
@@ -8327,7 +8381,8 @@ function ItemInteractionLayer({
|
|
|
8327
8381
|
left: rect.left - gap,
|
|
8328
8382
|
width: rect.width + gap * 2,
|
|
8329
8383
|
height: rect.height + gap * 2,
|
|
8330
|
-
zIndex: getChromeZIndex(state)
|
|
8384
|
+
zIndex: getChromeZIndex(state),
|
|
8385
|
+
display: hidden ? "none" : "block"
|
|
8331
8386
|
},
|
|
8332
8387
|
children: [
|
|
8333
8388
|
/* @__PURE__ */ jsx12(
|
|
@@ -11148,6 +11203,13 @@ function findButtonAtPoint(x, y, media) {
|
|
|
11148
11203
|
if (hits.length === 0) return null;
|
|
11149
11204
|
return hits.reduce((best, el) => best.contains(el) ? el : best);
|
|
11150
11205
|
}
|
|
11206
|
+
function findNavbarCtaAtPoint(x, y) {
|
|
11207
|
+
const hits = Array.from(
|
|
11208
|
+
document.querySelectorAll('[data-ohw-role="navbar-button"]')
|
|
11209
|
+
).filter((el) => containsPoint(el, x, y) && !el.closest("[data-ohw-bridge]"));
|
|
11210
|
+
if (hits.length === 0) return null;
|
|
11211
|
+
return hits.reduce((best, el) => best.contains(el) ? el : best);
|
|
11212
|
+
}
|
|
11151
11213
|
|
|
11152
11214
|
// src/lib/session-search.ts
|
|
11153
11215
|
var STORAGE_KEY = "ohw-preserved-search";
|
|
@@ -11883,6 +11945,26 @@ import { useCallback as useCallback5, useEffect as useEffect8, useMemo as useMem
|
|
|
11883
11945
|
import { createPortal as createPortal2 } from "react-dom";
|
|
11884
11946
|
import { ArrowLeft as ArrowLeft2, Check as Check2 } from "lucide-react";
|
|
11885
11947
|
import { usePathname, useRouter as useRouter2 } from "next/navigation";
|
|
11948
|
+
|
|
11949
|
+
// src/lib/parent-scroll.ts
|
|
11950
|
+
function visibleBand(parentScroll) {
|
|
11951
|
+
const { iframeOffsetTop, headerH: visibleCanvasTop, canvasH } = parentScroll;
|
|
11952
|
+
const top = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
11953
|
+
const bottom = Math.min(window.innerHeight, visibleCanvasTop + canvasH - iframeOffsetTop);
|
|
11954
|
+
return { top, bottom: Math.max(top, bottom) };
|
|
11955
|
+
}
|
|
11956
|
+
function getIframeVisibleClip(parentScroll) {
|
|
11957
|
+
if (!parentScroll) return null;
|
|
11958
|
+
return visibleBand(parentScroll);
|
|
11959
|
+
}
|
|
11960
|
+
function getIframeChromeClip(parentScroll) {
|
|
11961
|
+
if (!parentScroll) return null;
|
|
11962
|
+
const band = visibleBand(parentScroll);
|
|
11963
|
+
const promptBarH = Math.max(0, parentScroll.promptBarH ?? 0);
|
|
11964
|
+
return { top: band.top, bottom: Math.max(band.top, band.bottom - promptBarH) };
|
|
11965
|
+
}
|
|
11966
|
+
|
|
11967
|
+
// src/ui/link-modal/SectionPickerOverlay.tsx
|
|
11886
11968
|
import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
11887
11969
|
var DIM_OVERLAY = "rgba(0, 0, 0, 0.45)";
|
|
11888
11970
|
function rectsEqual(a, b) {
|
|
@@ -12020,20 +12102,22 @@ function SectionPickerOverlay({
|
|
|
12020
12102
|
[]
|
|
12021
12103
|
);
|
|
12022
12104
|
useEffect8(() => {
|
|
12023
|
-
const applyClip = (iframeOffsetTop, visibleCanvasTop, canvasH) => {
|
|
12024
|
-
const
|
|
12025
|
-
|
|
12026
|
-
|
|
12027
|
-
|
|
12028
|
-
|
|
12105
|
+
const applyClip = (iframeOffsetTop, visibleCanvasTop, canvasH, promptBarH = 0) => {
|
|
12106
|
+
const next = getIframeVisibleClip({
|
|
12107
|
+
iframeOffsetTop,
|
|
12108
|
+
headerH: visibleCanvasTop,
|
|
12109
|
+
canvasH,
|
|
12110
|
+
promptBarH
|
|
12111
|
+
});
|
|
12112
|
+
if (!next) return;
|
|
12029
12113
|
setChromeClip(
|
|
12030
|
-
(prev) => prev.top === top && prev.bottom === bottom ? prev :
|
|
12114
|
+
(prev) => prev.top === next.top && prev.bottom === next.bottom ? prev : next
|
|
12031
12115
|
);
|
|
12032
12116
|
};
|
|
12033
12117
|
const onParentScroll = (e) => {
|
|
12034
12118
|
if (e.data?.type !== "ow:parent-scroll") return;
|
|
12035
|
-
const { iframeOffsetTop, headerH, canvasH } = e.data;
|
|
12036
|
-
applyClip(iframeOffsetTop, headerH, canvasH);
|
|
12119
|
+
const { iframeOffsetTop, headerH, canvasH, promptBarH = 0 } = e.data;
|
|
12120
|
+
applyClip(iframeOffsetTop, headerH, canvasH, promptBarH);
|
|
12037
12121
|
iframeOffsetTopRef.current = iframeOffsetTop;
|
|
12038
12122
|
if (!pointerScreenRef.current && pointerRef.current) {
|
|
12039
12123
|
pointerScreenRef.current = {
|
|
@@ -15703,36 +15787,50 @@ import { X as X5 } from "lucide-react";
|
|
|
15703
15787
|
import { jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
15704
15788
|
var PANEL_WIDTH = 256;
|
|
15705
15789
|
var EDGE_MARGIN = 16;
|
|
15790
|
+
var HEADER_MIN = 56;
|
|
15706
15791
|
function getVisibleClip(parentScroll) {
|
|
15707
15792
|
const left = 0;
|
|
15708
15793
|
const right = window.innerWidth;
|
|
15709
|
-
|
|
15794
|
+
const band = getIframeChromeClip(parentScroll);
|
|
15795
|
+
if (!band) {
|
|
15710
15796
|
return { top: 0, bottom: window.innerHeight, left, right };
|
|
15711
15797
|
}
|
|
15712
|
-
|
|
15713
|
-
const top = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
15714
|
-
const bottom = Math.min(window.innerHeight, visibleCanvasTop + canvasH - iframeOffsetTop);
|
|
15715
|
-
return { top, bottom: Math.max(top, bottom), left, right };
|
|
15798
|
+
return { ...band, left, right };
|
|
15716
15799
|
}
|
|
15717
|
-
function defaultFloatingPanelPosition(parentScroll,
|
|
15800
|
+
function defaultFloatingPanelPosition(parentScroll, _panelHeight = 280) {
|
|
15718
15801
|
const clip = getVisibleClip(parentScroll);
|
|
15719
15802
|
return {
|
|
15720
15803
|
x: Math.max(EDGE_MARGIN, clip.right - PANEL_WIDTH - EDGE_MARGIN),
|
|
15721
|
-
y:
|
|
15722
|
-
Math.max(clip.top + EDGE_MARGIN, EDGE_MARGIN),
|
|
15723
|
-
Math.max(clip.top + EDGE_MARGIN, clip.bottom - panelHeight - EDGE_MARGIN)
|
|
15724
|
-
)
|
|
15804
|
+
y: clip.top + EDGE_MARGIN
|
|
15725
15805
|
};
|
|
15726
15806
|
}
|
|
15727
|
-
function
|
|
15807
|
+
function clampX(x, panelW) {
|
|
15808
|
+
const left = EDGE_MARGIN;
|
|
15809
|
+
const maxX = Math.max(left, window.innerWidth - panelW - EDGE_MARGIN);
|
|
15810
|
+
return Math.min(Math.max(x, left), maxX);
|
|
15811
|
+
}
|
|
15812
|
+
function clampDragPosition(pos, parentScroll, panelW) {
|
|
15728
15813
|
const clip = getVisibleClip(parentScroll);
|
|
15729
|
-
const
|
|
15730
|
-
const maxY = Math.max(
|
|
15814
|
+
const minY = clip.top + EDGE_MARGIN;
|
|
15815
|
+
const maxY = Math.max(minY, clip.bottom - EDGE_MARGIN - HEADER_MIN);
|
|
15731
15816
|
return {
|
|
15732
|
-
x:
|
|
15733
|
-
y: Math.min(Math.max(pos.y,
|
|
15817
|
+
x: clampX(pos.x, panelW),
|
|
15818
|
+
y: Math.min(Math.max(pos.y, minY), maxY)
|
|
15734
15819
|
};
|
|
15735
15820
|
}
|
|
15821
|
+
function fitPanelInClip(homeY, parentScroll, preferredHeight) {
|
|
15822
|
+
const clip = getVisibleClip(parentScroll);
|
|
15823
|
+
const minY = clip.top + EDGE_MARGIN;
|
|
15824
|
+
const maxBottom = clip.bottom - EDGE_MARGIN;
|
|
15825
|
+
const band = Math.max(HEADER_MIN, maxBottom - minY);
|
|
15826
|
+
let y = Math.max(homeY, minY);
|
|
15827
|
+
const want = Math.min(Math.max(preferredHeight, HEADER_MIN), band);
|
|
15828
|
+
if (y + want > maxBottom) {
|
|
15829
|
+
y = Math.max(minY, maxBottom - want);
|
|
15830
|
+
}
|
|
15831
|
+
const maxHeight = Math.max(HEADER_MIN, Math.floor(maxBottom - y));
|
|
15832
|
+
return { y, maxHeight };
|
|
15833
|
+
}
|
|
15736
15834
|
function FloatingPanel({
|
|
15737
15835
|
open,
|
|
15738
15836
|
title,
|
|
@@ -15749,19 +15847,54 @@ function FloatingPanel({
|
|
|
15749
15847
|
const panelRef = useRef9(null);
|
|
15750
15848
|
const [measured, setMeasured] = useState12({ w: PANEL_WIDTH, h: 280 });
|
|
15751
15849
|
const dragRef = useRef9(null);
|
|
15752
|
-
const
|
|
15753
|
-
|
|
15850
|
+
const homeRef = useRef9(null);
|
|
15851
|
+
if (!open) {
|
|
15852
|
+
homeRef.current = null;
|
|
15853
|
+
} else if (position) {
|
|
15854
|
+
homeRef.current = position;
|
|
15855
|
+
} else if (homeRef.current == null) {
|
|
15856
|
+
homeRef.current = defaultFloatingPanelPosition(parentScroll);
|
|
15857
|
+
}
|
|
15858
|
+
const [liveScroll, setLiveScroll] = useState12(parentScroll);
|
|
15859
|
+
const home = position ?? homeRef.current ?? defaultFloatingPanelPosition(parentScroll);
|
|
15860
|
+
const { y: fittedY, maxHeight } = fitPanelInClip(home.y, liveScroll, measured.h);
|
|
15861
|
+
const clamped = {
|
|
15862
|
+
x: clampX(home.x, measured.w),
|
|
15863
|
+
y: fittedY
|
|
15864
|
+
};
|
|
15865
|
+
useEffect11(() => {
|
|
15866
|
+
setLiveScroll(parentScroll);
|
|
15867
|
+
}, [parentScroll]);
|
|
15868
|
+
useEffect11(() => {
|
|
15869
|
+
if (!open) return;
|
|
15870
|
+
const onParentScroll = (e) => {
|
|
15871
|
+
if (e.data?.type !== "ow:parent-scroll") return;
|
|
15872
|
+
const { iframeOffsetTop, headerH, canvasH, promptBarH = 0 } = e.data;
|
|
15873
|
+
setLiveScroll({ iframeOffsetTop, headerH, canvasH, promptBarH });
|
|
15874
|
+
};
|
|
15875
|
+
window.addEventListener("message", onParentScroll);
|
|
15876
|
+
return () => window.removeEventListener("message", onParentScroll);
|
|
15877
|
+
}, [open]);
|
|
15878
|
+
const positionRef = useRef9(position);
|
|
15879
|
+
useLayoutEffect4(() => {
|
|
15880
|
+
if (!open) {
|
|
15881
|
+
positionRef.current = position;
|
|
15882
|
+
return;
|
|
15883
|
+
}
|
|
15884
|
+
if (position == null && positionRef.current != null) {
|
|
15885
|
+
homeRef.current = defaultFloatingPanelPosition(liveScroll ?? parentScroll);
|
|
15886
|
+
}
|
|
15887
|
+
positionRef.current = position;
|
|
15888
|
+
}, [open, position, liveScroll, parentScroll]);
|
|
15754
15889
|
useLayoutEffect4(() => {
|
|
15755
15890
|
if (!open || !panelRef.current) return;
|
|
15756
15891
|
const el = panelRef.current;
|
|
15757
|
-
const
|
|
15892
|
+
const header = el.querySelector("[data-ohw-floating-panel-header]");
|
|
15893
|
+
const body = el.querySelector("[data-ohw-floating-panel-body]");
|
|
15894
|
+
const contentH = (header?.offsetHeight ?? 0) + (body?.scrollHeight ?? 0) || el.scrollHeight || 280;
|
|
15895
|
+
const next = { w: el.offsetWidth || PANEL_WIDTH, h: contentH };
|
|
15758
15896
|
setMeasured((prev) => prev.w === next.w && prev.h === next.h ? prev : next);
|
|
15759
15897
|
}, [open, children, title, context]);
|
|
15760
|
-
useEffect11(() => {
|
|
15761
|
-
if (!open || !position || !onPositionChange) return;
|
|
15762
|
-
const next = clampPosition(position, parentScroll, measured.w, measured.h);
|
|
15763
|
-
if (next.x !== position.x || next.y !== position.y) onPositionChange(next);
|
|
15764
|
-
}, [open, parentScroll, measured.w, measured.h, position, onPositionChange]);
|
|
15765
15898
|
const onHeaderPointerDown = useCallback7(
|
|
15766
15899
|
(e) => {
|
|
15767
15900
|
if (e.button !== 0) return;
|
|
@@ -15795,18 +15928,17 @@ function FloatingPanel({
|
|
|
15795
15928
|
return;
|
|
15796
15929
|
}
|
|
15797
15930
|
e.preventDefault();
|
|
15798
|
-
const next =
|
|
15931
|
+
const next = clampDragPosition(
|
|
15799
15932
|
{
|
|
15800
15933
|
x: drag.originX + (e.clientX - drag.startX),
|
|
15801
15934
|
y: drag.originY + (e.clientY - drag.startY)
|
|
15802
15935
|
},
|
|
15803
|
-
|
|
15804
|
-
measured.w
|
|
15805
|
-
measured.h
|
|
15936
|
+
liveScroll,
|
|
15937
|
+
measured.w
|
|
15806
15938
|
);
|
|
15807
15939
|
onPositionChange?.(next);
|
|
15808
15940
|
},
|
|
15809
|
-
[measured.
|
|
15941
|
+
[measured.w, onPositionChange, liveScroll]
|
|
15810
15942
|
);
|
|
15811
15943
|
const endDrag = useCallback7((e) => {
|
|
15812
15944
|
const drag = dragRef.current;
|
|
@@ -15836,7 +15968,7 @@ function FloatingPanel({
|
|
|
15836
15968
|
"fixed z-[2147483647] flex w-64 flex-col overflow-hidden rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
15837
15969
|
className
|
|
15838
15970
|
),
|
|
15839
|
-
style: { left: clamped.x, top: clamped.y },
|
|
15971
|
+
style: { left: clamped.x, top: clamped.y, maxHeight },
|
|
15840
15972
|
onMouseDown: (e) => e.stopPropagation(),
|
|
15841
15973
|
onPointerDown: (e) => e.stopPropagation(),
|
|
15842
15974
|
onClick: (e) => e.stopPropagation(),
|
|
@@ -15845,7 +15977,7 @@ function FloatingPanel({
|
|
|
15845
15977
|
"div",
|
|
15846
15978
|
{
|
|
15847
15979
|
"data-ohw-floating-panel-header": "",
|
|
15848
|
-
className: "relative flex cursor-grab items-start gap-2 border-b border-border py-
|
|
15980
|
+
className: "relative flex shrink-0 cursor-grab items-start gap-2 border-b border-border py-4! pl-5! pr-11! active:cursor-grabbing",
|
|
15849
15981
|
onPointerDown: onHeaderPointerDown,
|
|
15850
15982
|
onPointerMove: onHeaderPointerMove,
|
|
15851
15983
|
onPointerUp: endDrag,
|
|
@@ -15880,7 +16012,11 @@ function FloatingPanel({
|
|
|
15880
16012
|
"div",
|
|
15881
16013
|
{
|
|
15882
16014
|
"data-ohw-floating-panel-body": "",
|
|
15883
|
-
className: cn(
|
|
16015
|
+
className: cn(
|
|
16016
|
+
"flex min-h-0 w-full flex-1 flex-col gap-4 overflow-y-auto overscroll-contain p-4",
|
|
16017
|
+
bodyClassName
|
|
16018
|
+
),
|
|
16019
|
+
style: { WebkitOverflowScrolling: "touch" },
|
|
15884
16020
|
children
|
|
15885
16021
|
}
|
|
15886
16022
|
)
|
|
@@ -15958,199 +16094,1633 @@ function SocialsDisplayPanel({ display, onChange, className }) {
|
|
|
15958
16094
|
] });
|
|
15959
16095
|
}
|
|
15960
16096
|
|
|
15961
|
-
// src/
|
|
15962
|
-
|
|
15963
|
-
|
|
15964
|
-
|
|
15965
|
-
|
|
16097
|
+
// src/ui/button-style-panel.tsx
|
|
16098
|
+
import { Check as Check3 } from "lucide-react";
|
|
16099
|
+
|
|
16100
|
+
// src/lib/button-styles.ts
|
|
16101
|
+
var BUTTON_VARIANTS_KEY = "__ohw_button_variants";
|
|
16102
|
+
var BUTTON_SIZES_KEY = "__ohw_button_sizes";
|
|
16103
|
+
var BUTTON_ASSIGNMENTS_KEY = "__ohw_button_assignments";
|
|
16104
|
+
var BUTTON_VARIANT_IDS = ["primary", "secondary", "ghost"];
|
|
16105
|
+
var BUTTON_SIZE_IDS = ["s", "m", "l"];
|
|
16106
|
+
var TRANSPARENT = "rgba(0, 0, 0, 0)";
|
|
16107
|
+
var REFERENCE_SIZES = {
|
|
16108
|
+
s: { height: 40, paddingTop: 8, paddingRight: 16, paddingBottom: 8, paddingLeft: 16, fontSize: 15, borderRadius: 8, gap: 8 },
|
|
16109
|
+
m: { height: 48, paddingTop: 12, paddingRight: 24, paddingBottom: 12, paddingLeft: 24, fontSize: 15, borderRadius: 8, gap: 8 },
|
|
16110
|
+
l: { height: 56, paddingTop: 16, paddingRight: 32, paddingBottom: 16, paddingLeft: 32, fontSize: 15, borderRadius: 8, gap: 8 }
|
|
16111
|
+
};
|
|
16112
|
+
function buttonStyleContext(_el) {
|
|
16113
|
+
return "Button";
|
|
16114
|
+
}
|
|
16115
|
+
function previewSlotBackground(el) {
|
|
16116
|
+
let node = el.parentElement;
|
|
16117
|
+
while (node && node !== el.ownerDocument.documentElement) {
|
|
16118
|
+
if (node.closest("[data-ohw-bridge], [data-ohw-bridge-root]")) {
|
|
16119
|
+
node = node.parentElement;
|
|
16120
|
+
continue;
|
|
16121
|
+
}
|
|
16122
|
+
const bg = getComputedStyle(node).backgroundColor;
|
|
16123
|
+
const parsed = parseColor(bg);
|
|
16124
|
+
if (parsed && !isTransparent(parsed)) return bg;
|
|
16125
|
+
node = node.parentElement;
|
|
15966
16126
|
}
|
|
16127
|
+
const root = el.ownerDocument.documentElement;
|
|
16128
|
+
const style = getComputedStyle(root);
|
|
16129
|
+
for (const name of ["--brand-surface", "--brand-background", "--ohw-brand-light", "--color-light"]) {
|
|
16130
|
+
const value = style.getPropertyValue(name).trim();
|
|
16131
|
+
if (value) return value;
|
|
16132
|
+
}
|
|
16133
|
+
return "var(--brand-background, var(--ohw-brand-light, var(--color-light, #ffffff)))";
|
|
15967
16134
|
}
|
|
15968
|
-
function
|
|
15969
|
-
|
|
15970
|
-
|
|
16135
|
+
function buttonId(el) {
|
|
16136
|
+
if (!el) return null;
|
|
16137
|
+
const button = el.matches(CTA_BUTTON_SELECTOR) ? el : el.closest(CTA_BUTTON_SELECTOR);
|
|
16138
|
+
const id = button?.getAttribute("data-ohw-href-key")?.trim();
|
|
16139
|
+
return id || null;
|
|
15971
16140
|
}
|
|
15972
|
-
function
|
|
15973
|
-
|
|
16141
|
+
function isButtonVariantId(value) {
|
|
16142
|
+
return BUTTON_VARIANT_IDS.includes(value);
|
|
15974
16143
|
}
|
|
15975
|
-
function
|
|
15976
|
-
|
|
15977
|
-
document.documentElement.setAttribute("data-ohw-item-dragging", "");
|
|
15978
|
-
clearTextSelection();
|
|
16144
|
+
function isButtonSizeId(value) {
|
|
16145
|
+
return BUTTON_SIZE_IDS.includes(value);
|
|
15979
16146
|
}
|
|
15980
|
-
function
|
|
15981
|
-
const
|
|
15982
|
-
|
|
15983
|
-
document.documentElement.removeAttribute("data-ohw-item-dragging");
|
|
15984
|
-
if (wasDragging) clearTextSelection();
|
|
16147
|
+
function px(value) {
|
|
16148
|
+
const rounded = Math.round(value * 100) / 100;
|
|
16149
|
+
return `${rounded}px`;
|
|
15985
16150
|
}
|
|
15986
|
-
|
|
15987
|
-
|
|
15988
|
-
|
|
15989
|
-
|
|
15990
|
-
|
|
15991
|
-
|
|
15992
|
-
return listActiveNavbarItems(draggedEl).filter((el) => {
|
|
15993
|
-
const key = el.getAttribute("data-ohw-href-key");
|
|
15994
|
-
return isNavbarHrefKey(key) && !isNestedNavChild(el);
|
|
15995
|
-
});
|
|
16151
|
+
function parsePx(value, rootFont = 16) {
|
|
16152
|
+
if (!value) return 0;
|
|
16153
|
+
const n = parseFloat(value);
|
|
16154
|
+
if (!Number.isFinite(n)) return 0;
|
|
16155
|
+
if (value.trim().endsWith("rem") || value.trim().endsWith("em")) return n * rootFont;
|
|
16156
|
+
return n;
|
|
15996
16157
|
}
|
|
15997
|
-
function
|
|
15998
|
-
|
|
15999
|
-
|
|
16000
|
-
|
|
16001
|
-
const trigger = group.querySelector(":scope > [data-ohw-href-key]") ?? Array.from(group.querySelectorAll("[data-ohw-href-key]")).find(
|
|
16002
|
-
(el) => !el.closest("[data-ohw-nav-children]")
|
|
16003
|
-
) ?? null;
|
|
16004
|
-
const key = trigger?.getAttribute("data-ohw-href-key");
|
|
16005
|
-
return key && isNavbarHrefKey(key) ? key : null;
|
|
16158
|
+
function classifyHeight(height) {
|
|
16159
|
+
if (height < 44) return "s";
|
|
16160
|
+
if (height < 52) return "m";
|
|
16161
|
+
return "l";
|
|
16006
16162
|
}
|
|
16007
|
-
function
|
|
16008
|
-
|
|
16009
|
-
|
|
16010
|
-
|
|
16011
|
-
|
|
16012
|
-
|
|
16013
|
-
|
|
16014
|
-
|
|
16015
|
-
(
|
|
16016
|
-
|
|
16163
|
+
function scaleGeometry(geometry, scale = 0.75) {
|
|
16164
|
+
return {
|
|
16165
|
+
paddingTop: px(parsePx(geometry.paddingTop) * scale),
|
|
16166
|
+
paddingRight: px(parsePx(geometry.paddingRight) * scale),
|
|
16167
|
+
paddingBottom: px(parsePx(geometry.paddingBottom) * scale),
|
|
16168
|
+
paddingLeft: px(parsePx(geometry.paddingLeft) * scale),
|
|
16169
|
+
fontSize: px(parsePx(geometry.fontSize) * scale),
|
|
16170
|
+
borderRadius: px(parsePx(geometry.borderRadius) * scale),
|
|
16171
|
+
gap: px(parsePx(geometry.gap) * scale),
|
|
16172
|
+
height: Math.round(geometry.height * scale)
|
|
16173
|
+
};
|
|
16017
16174
|
}
|
|
16018
|
-
function
|
|
16019
|
-
const
|
|
16020
|
-
|
|
16021
|
-
|
|
16022
|
-
|
|
16023
|
-
|
|
16024
|
-
const horizontalGap = b.left - a.right;
|
|
16025
|
-
return verticalGap > horizontalGap;
|
|
16026
|
-
}
|
|
16027
|
-
const container = getActiveNavbarListContainer(draggedEl);
|
|
16028
|
-
if (!container) return false;
|
|
16029
|
-
const style = window.getComputedStyle(container);
|
|
16030
|
-
return style.flexDirection === "column" || style.flexDirection === "column-reverse";
|
|
16175
|
+
function relativeLuminance(color) {
|
|
16176
|
+
const channel = (value) => {
|
|
16177
|
+
const s = value / 255;
|
|
16178
|
+
return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
|
|
16179
|
+
};
|
|
16180
|
+
return 0.2126 * channel(color.r) + 0.7152 * channel(color.g) + 0.0722 * channel(color.b);
|
|
16031
16181
|
}
|
|
16032
|
-
function
|
|
16033
|
-
const
|
|
16034
|
-
const
|
|
16035
|
-
|
|
16036
|
-
|
|
16037
|
-
|
|
16038
|
-
|
|
16039
|
-
|
|
16040
|
-
|
|
16041
|
-
|
|
16042
|
-
|
|
16043
|
-
|
|
16044
|
-
|
|
16045
|
-
|
|
16046
|
-
|
|
16047
|
-
|
|
16048
|
-
|
|
16049
|
-
|
|
16050
|
-
const
|
|
16051
|
-
|
|
16052
|
-
|
|
16053
|
-
|
|
16054
|
-
|
|
16055
|
-
|
|
16056
|
-
|
|
16057
|
-
|
|
16058
|
-
|
|
16059
|
-
|
|
16060
|
-
|
|
16061
|
-
|
|
16062
|
-
|
|
16063
|
-
|
|
16064
|
-
|
|
16065
|
-
|
|
16066
|
-
|
|
16067
|
-
|
|
16068
|
-
|
|
16069
|
-
|
|
16070
|
-
|
|
16071
|
-
}
|
|
16072
|
-
|
|
16073
|
-
|
|
16074
|
-
|
|
16075
|
-
|
|
16076
|
-
|
|
16182
|
+
function contrastRatio(a, b) {
|
|
16183
|
+
const lighter = Math.max(relativeLuminance(a), relativeLuminance(b));
|
|
16184
|
+
const darker = Math.min(relativeLuminance(a), relativeLuminance(b));
|
|
16185
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
16186
|
+
}
|
|
16187
|
+
function compositeOver(fg, bg) {
|
|
16188
|
+
const a = fg.a + bg.a * (1 - fg.a);
|
|
16189
|
+
if (a < 1e-3) return { ...bg, a: 0 };
|
|
16190
|
+
return {
|
|
16191
|
+
r: (fg.r * fg.a + bg.r * bg.a * (1 - fg.a)) / a,
|
|
16192
|
+
g: (fg.g * fg.a + bg.g * bg.a * (1 - fg.a)) / a,
|
|
16193
|
+
b: (fg.b * fg.a + bg.b * bg.a * (1 - fg.a)) / a,
|
|
16194
|
+
a
|
|
16195
|
+
};
|
|
16196
|
+
}
|
|
16197
|
+
function previewSlotForChrome(chrome, slotBackground) {
|
|
16198
|
+
const text = parseColor(chrome.color);
|
|
16199
|
+
if (!text || text.a < 0.2) return slotBackground;
|
|
16200
|
+
const slot = parseColor(slotBackground) ?? { r: 250, g: 250, b: 249, a: 1 };
|
|
16201
|
+
const fill = parseColor(chrome.background);
|
|
16202
|
+
const effective = fill && !isTransparent(fill) ? compositeOver(fill, slot) : slot;
|
|
16203
|
+
if (contrastRatio(text, effective) >= 3) return slotBackground;
|
|
16204
|
+
return relativeLuminance(text) > 0.55 ? "#2c2c2c" : "#f4f4f5";
|
|
16205
|
+
}
|
|
16206
|
+
function parseColor(input) {
|
|
16207
|
+
if (!input) return null;
|
|
16208
|
+
const value = input.trim().toLowerCase();
|
|
16209
|
+
if (value === "transparent") return { r: 0, g: 0, b: 0, a: 0 };
|
|
16210
|
+
const hex = value.match(/^#([0-9a-f]{3,8})$/);
|
|
16211
|
+
if (hex) {
|
|
16212
|
+
const raw = hex[1];
|
|
16213
|
+
const expand = (pair) => parseInt(pair.length === 1 ? pair + pair : pair, 16);
|
|
16214
|
+
if (raw.length === 3 || raw.length === 4) {
|
|
16215
|
+
return {
|
|
16216
|
+
r: expand(raw[0]),
|
|
16217
|
+
g: expand(raw[1]),
|
|
16218
|
+
b: expand(raw[2]),
|
|
16219
|
+
a: raw.length === 4 ? expand(raw[3]) / 255 : 1
|
|
16220
|
+
};
|
|
16221
|
+
}
|
|
16222
|
+
if (raw.length === 6 || raw.length === 8) {
|
|
16223
|
+
return {
|
|
16224
|
+
r: expand(raw.slice(0, 2)),
|
|
16225
|
+
g: expand(raw.slice(2, 4)),
|
|
16226
|
+
b: expand(raw.slice(4, 6)),
|
|
16227
|
+
a: raw.length === 8 ? expand(raw.slice(6, 8)) / 255 : 1
|
|
16228
|
+
};
|
|
16077
16229
|
}
|
|
16078
|
-
slots.push({
|
|
16079
|
-
insertIndex: i,
|
|
16080
|
-
parentId: null,
|
|
16081
|
-
left,
|
|
16082
|
-
top,
|
|
16083
|
-
width: Math.max(width, 40),
|
|
16084
|
-
height: barThickness,
|
|
16085
|
-
direction: "horizontal"
|
|
16086
|
-
});
|
|
16087
16230
|
}
|
|
16088
|
-
|
|
16089
|
-
|
|
16090
|
-
|
|
16091
|
-
|
|
16092
|
-
|
|
16093
|
-
|
|
16094
|
-
|
|
16095
|
-
if (!container) return slots;
|
|
16096
|
-
const rect = container.getBoundingClientRect();
|
|
16097
|
-
slots.push({
|
|
16098
|
-
insertIndex: 0,
|
|
16099
|
-
parentId: null,
|
|
16100
|
-
left: rect.left + rect.width / 2 - barThickness / 2,
|
|
16101
|
-
top: rect.top,
|
|
16102
|
-
width: barThickness,
|
|
16103
|
-
height: Math.max(rect.height, 24),
|
|
16104
|
-
direction: "vertical"
|
|
16105
|
-
});
|
|
16106
|
-
return slots;
|
|
16231
|
+
const rgb = value.match(
|
|
16232
|
+
/^rgba?\(\s*([\d.]+)[%\s,]+([\d.]+)[%\s,]+([\d.]+)(?:%?\s*[,/]\s*([\d.]+%?))?\s*\)$/
|
|
16233
|
+
);
|
|
16234
|
+
if (rgb) {
|
|
16235
|
+
const alphaRaw = rgb[4];
|
|
16236
|
+
const alpha = alphaRaw == null ? 1 : alphaRaw.endsWith("%") ? parseFloat(alphaRaw) / 100 : parseFloat(alphaRaw);
|
|
16237
|
+
return { r: Number(rgb[1]), g: Number(rgb[2]), b: Number(rgb[3]), a: alpha };
|
|
16107
16238
|
}
|
|
16108
|
-
const
|
|
16109
|
-
|
|
16110
|
-
|
|
16111
|
-
|
|
16112
|
-
|
|
16113
|
-
|
|
16114
|
-
|
|
16115
|
-
|
|
16116
|
-
|
|
16117
|
-
|
|
16118
|
-
if (i === 0) {
|
|
16119
|
-
const first = items[0].getBoundingClientRect();
|
|
16120
|
-
left = first.left - edgeGap / 2 - barThickness / 2;
|
|
16121
|
-
top = first.top;
|
|
16122
|
-
height = first.height;
|
|
16123
|
-
} else if (i === items.length) {
|
|
16124
|
-
const last = items[items.length - 1].getBoundingClientRect();
|
|
16125
|
-
const lastGap = items.length >= 2 ? Math.max(0, last.left - items[items.length - 2].getBoundingClientRect().right) : edgeGap;
|
|
16126
|
-
left = last.right + lastGap / 2 - barThickness / 2;
|
|
16127
|
-
top = last.top;
|
|
16128
|
-
height = last.height;
|
|
16129
|
-
} else {
|
|
16130
|
-
const prev = items[i - 1].getBoundingClientRect();
|
|
16131
|
-
const next = items[i].getBoundingClientRect();
|
|
16132
|
-
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
16133
|
-
top = Math.min(prev.top, next.top);
|
|
16134
|
-
height = Math.max(prev.bottom, next.bottom) - top;
|
|
16135
|
-
}
|
|
16136
|
-
slots.push({
|
|
16137
|
-
insertIndex: i,
|
|
16138
|
-
parentId: null,
|
|
16139
|
-
left,
|
|
16140
|
-
top,
|
|
16141
|
-
width: barThickness,
|
|
16142
|
-
height: Math.max(height, 24),
|
|
16143
|
-
direction: "vertical"
|
|
16144
|
-
});
|
|
16239
|
+
const oklch = value.match(
|
|
16240
|
+
/^oklch\(\s*([\d.]+%?)\s+([\d.]+)\s+([\d.]+)(?:deg)?(?:\s*\/\s*([\d.]+%?))?\s*\)$/
|
|
16241
|
+
);
|
|
16242
|
+
if (oklch) {
|
|
16243
|
+
const Lraw = oklch[1];
|
|
16244
|
+
const L = Lraw.endsWith("%") ? parseFloat(Lraw) / 100 : parseFloat(Lraw);
|
|
16245
|
+
const gray = Math.max(0, Math.min(1, L)) * 255;
|
|
16246
|
+
const alphaRaw = oklch[4];
|
|
16247
|
+
const alpha = alphaRaw == null ? 1 : alphaRaw.endsWith("%") ? parseFloat(alphaRaw) / 100 : parseFloat(alphaRaw);
|
|
16248
|
+
return { r: gray, g: gray, b: gray, a: alpha };
|
|
16145
16249
|
}
|
|
16146
|
-
return
|
|
16250
|
+
return null;
|
|
16147
16251
|
}
|
|
16148
|
-
function
|
|
16149
|
-
|
|
16150
|
-
|
|
16151
|
-
|
|
16152
|
-
|
|
16153
|
-
|
|
16252
|
+
function isTransparent(color) {
|
|
16253
|
+
return !color || color.a < 0.05;
|
|
16254
|
+
}
|
|
16255
|
+
function hasOpaqueBackground(background) {
|
|
16256
|
+
if (!background) return false;
|
|
16257
|
+
const value = background.trim().toLowerCase();
|
|
16258
|
+
if (!value || value === "transparent" || value === "rgba(0, 0, 0, 0)" || value === "rgb(0, 0, 0, 0)") {
|
|
16259
|
+
return false;
|
|
16260
|
+
}
|
|
16261
|
+
const parsed = parseColor(background);
|
|
16262
|
+
if (parsed) return !isTransparent(parsed);
|
|
16263
|
+
return true;
|
|
16264
|
+
}
|
|
16265
|
+
function toCss(color) {
|
|
16266
|
+
const r2 = Math.round(color.r);
|
|
16267
|
+
const g = Math.round(color.g);
|
|
16268
|
+
const b = Math.round(color.b);
|
|
16269
|
+
if (color.a >= 0.995) return `rgb(${r2}, ${g}, ${b})`;
|
|
16270
|
+
return `rgba(${r2}, ${g}, ${b}, ${Math.round(color.a * 100) / 100})`;
|
|
16271
|
+
}
|
|
16272
|
+
function colorKey(input) {
|
|
16273
|
+
const parsed = parseColor(input);
|
|
16274
|
+
if (!parsed || isTransparent(parsed)) return "transparent";
|
|
16275
|
+
return `${Math.round(parsed.r / 8)}-${Math.round(parsed.g / 8)}-${Math.round(parsed.b / 8)}-${Math.round(parsed.a * 4)}`;
|
|
16276
|
+
}
|
|
16277
|
+
function declaredVariant(className) {
|
|
16278
|
+
const match = className.match(/\bbtn--(primary|secondary|ghost)\b/);
|
|
16279
|
+
return match && isButtonVariantId(match[1]) ? match[1] : null;
|
|
16280
|
+
}
|
|
16281
|
+
function fillSlot(sample) {
|
|
16282
|
+
const width = parseFloat(sample.borderWidth);
|
|
16283
|
+
const border = parseColor(sample.borderColor);
|
|
16284
|
+
if (width > 0 && !isTransparent(border)) return "secondary";
|
|
16285
|
+
if (hasOpaqueBackground(sample.background)) return "primary";
|
|
16286
|
+
return "ghost";
|
|
16287
|
+
}
|
|
16288
|
+
function sampleSlot(sample) {
|
|
16289
|
+
return declaredVariant(sample.className) ?? fillSlot(sample);
|
|
16290
|
+
}
|
|
16291
|
+
function fingerprint(sample) {
|
|
16292
|
+
const width = parseFloat(sample.borderWidth);
|
|
16293
|
+
const border = width > 0 ? colorKey(sample.borderColor) : "none";
|
|
16294
|
+
return `${colorKey(sample.background)}|${border}|${colorKey(sample.color)}|${sampleSlot(sample)}`;
|
|
16295
|
+
}
|
|
16296
|
+
function paintColor(chrome) {
|
|
16297
|
+
if (hasOpaqueBackground(chrome.background)) {
|
|
16298
|
+
const parsed = parseColor(chrome.background);
|
|
16299
|
+
return parsed ? toCss({ ...parsed, a: 1 }) : chrome.background;
|
|
16300
|
+
}
|
|
16301
|
+
const width = parseFloat(chrome.borderWidth);
|
|
16302
|
+
if (width > 0 && hasOpaqueBackground(chrome.borderColor)) {
|
|
16303
|
+
const parsed = parseColor(chrome.borderColor);
|
|
16304
|
+
return parsed ? toCss({ ...parsed, a: 1 }) : chrome.borderColor;
|
|
16305
|
+
}
|
|
16306
|
+
const text = parseColor(chrome.color);
|
|
16307
|
+
return text ? toCss({ ...text, a: 1 }) : chrome.color;
|
|
16308
|
+
}
|
|
16309
|
+
function accentColor(chrome) {
|
|
16310
|
+
const bg = parseColor(chrome.background);
|
|
16311
|
+
if (bg && !isTransparent(bg) && relativeLuminance(bg) < 0.55) {
|
|
16312
|
+
return toCss({ ...bg, a: 1 });
|
|
16313
|
+
}
|
|
16314
|
+
const text = parseColor(chrome.color);
|
|
16315
|
+
if (text && !isTransparent(text)) return toCss({ ...text, a: 1 });
|
|
16316
|
+
return paintColor(chrome);
|
|
16317
|
+
}
|
|
16318
|
+
function chromeFrom(sample) {
|
|
16319
|
+
return {
|
|
16320
|
+
background: sample.background || TRANSPARENT,
|
|
16321
|
+
color: sample.color || "currentColor",
|
|
16322
|
+
borderColor: sample.borderColor || TRANSPARENT,
|
|
16323
|
+
borderWidth: sample.borderWidth || "0px"
|
|
16324
|
+
};
|
|
16325
|
+
}
|
|
16326
|
+
function filledPrimary(seed) {
|
|
16327
|
+
const paint = parseColor(paintColor(seed)) ?? { r: 15, g: 15, b: 15, a: 1 };
|
|
16328
|
+
const luminance = relativeLuminance(paint);
|
|
16329
|
+
return {
|
|
16330
|
+
background: toCss({ ...paint, a: 1 }),
|
|
16331
|
+
color: luminance > 0.55 ? "rgb(15, 15, 15)" : "rgb(255, 255, 255)",
|
|
16332
|
+
borderColor: TRANSPARENT,
|
|
16333
|
+
borderWidth: "0px"
|
|
16334
|
+
};
|
|
16335
|
+
}
|
|
16336
|
+
function generatedSecondary(primary) {
|
|
16337
|
+
const paint = accentColor(primary);
|
|
16338
|
+
return {
|
|
16339
|
+
background: TRANSPARENT,
|
|
16340
|
+
color: paint,
|
|
16341
|
+
borderColor: paint,
|
|
16342
|
+
borderWidth: "1px"
|
|
16343
|
+
};
|
|
16344
|
+
}
|
|
16345
|
+
function generatedGhost(primary) {
|
|
16346
|
+
return {
|
|
16347
|
+
background: TRANSPARENT,
|
|
16348
|
+
color: accentColor(primary),
|
|
16349
|
+
borderColor: TRANSPARENT,
|
|
16350
|
+
borderWidth: "0px"
|
|
16351
|
+
};
|
|
16352
|
+
}
|
|
16353
|
+
function normalizeOutlineChrome(outline, primary) {
|
|
16354
|
+
const paint = accentColor(primary);
|
|
16355
|
+
const text = parseColor(outline.color);
|
|
16356
|
+
const paintRgb = parseColor(paint);
|
|
16357
|
+
const primaryLabel = parseColor(primary.color);
|
|
16358
|
+
const matchesOnPrimary = Boolean(text && primaryLabel) && colorKey(outline.color) === colorKey(primary.color);
|
|
16359
|
+
const textTooLight = text ? relativeLuminance(text) > 0.7 : false;
|
|
16360
|
+
const paintIsDarker = paintRgb ? relativeLuminance(paintRgb) < 0.65 : hasOpaqueBackground(primary.background);
|
|
16361
|
+
if (!(matchesOnPrimary || textTooLight) || !paintIsDarker) return outline;
|
|
16362
|
+
const hasBorder = parseFloat(outline.borderWidth) > 0;
|
|
16363
|
+
return {
|
|
16364
|
+
...outline,
|
|
16365
|
+
color: paint,
|
|
16366
|
+
borderColor: hasBorder ? paint : outline.borderColor
|
|
16367
|
+
};
|
|
16368
|
+
}
|
|
16369
|
+
function generateButtonVariants(samples) {
|
|
16370
|
+
if (samples.length === 0) return { status: "unresolved" };
|
|
16371
|
+
const groups = /* @__PURE__ */ new Map();
|
|
16372
|
+
for (const sample of samples) {
|
|
16373
|
+
const key = fingerprint(sample);
|
|
16374
|
+
const list = groups.get(key) ?? [];
|
|
16375
|
+
list.push(sample);
|
|
16376
|
+
groups.set(key, list);
|
|
16377
|
+
}
|
|
16378
|
+
if (groups.size > 3) return { status: "unresolved" };
|
|
16379
|
+
const bySlot = /* @__PURE__ */ new Map();
|
|
16380
|
+
for (const group of groups.values()) {
|
|
16381
|
+
const sample = group[0];
|
|
16382
|
+
const slot = sampleSlot(sample);
|
|
16383
|
+
if (bySlot.has(slot)) return { status: "unresolved" };
|
|
16384
|
+
bySlot.set(slot, sample);
|
|
16385
|
+
}
|
|
16386
|
+
const primarySample = bySlot.get("primary");
|
|
16387
|
+
const seed = chromeFrom(primarySample ?? samples[0]);
|
|
16388
|
+
const primary = primarySample ? seed : filledPrimary(seed);
|
|
16389
|
+
const secondary = normalizeOutlineChrome(
|
|
16390
|
+
bySlot.has("secondary") ? chromeFrom(bySlot.get("secondary")) : generatedSecondary(primary),
|
|
16391
|
+
primary
|
|
16392
|
+
);
|
|
16393
|
+
const ghost = normalizeOutlineChrome(
|
|
16394
|
+
bySlot.has("ghost") ? chromeFrom(bySlot.get("ghost")) : generatedGhost(primary),
|
|
16395
|
+
primary
|
|
16396
|
+
);
|
|
16397
|
+
return {
|
|
16398
|
+
status: "ready",
|
|
16399
|
+
tokens: { primary, secondary, ghost }
|
|
16400
|
+
};
|
|
16401
|
+
}
|
|
16402
|
+
function geometryFromSample(sample) {
|
|
16403
|
+
return {
|
|
16404
|
+
paddingTop: px(sample.paddingTop),
|
|
16405
|
+
paddingRight: px(sample.paddingRight),
|
|
16406
|
+
paddingBottom: px(sample.paddingBottom),
|
|
16407
|
+
paddingLeft: px(sample.paddingLeft),
|
|
16408
|
+
fontSize: px(sample.fontSize),
|
|
16409
|
+
borderRadius: px(sample.borderRadius),
|
|
16410
|
+
gap: px(sample.gap),
|
|
16411
|
+
height: Math.round(sample.height)
|
|
16412
|
+
};
|
|
16413
|
+
}
|
|
16414
|
+
function shiftSample(base, steps) {
|
|
16415
|
+
return {
|
|
16416
|
+
height: Math.max(24, base.height + steps * 8),
|
|
16417
|
+
paddingTop: Math.max(0, base.paddingTop + steps * 4),
|
|
16418
|
+
paddingBottom: Math.max(0, base.paddingBottom + steps * 4),
|
|
16419
|
+
paddingLeft: Math.max(0, base.paddingLeft + steps * 8),
|
|
16420
|
+
paddingRight: Math.max(0, base.paddingRight + steps * 8),
|
|
16421
|
+
fontSize: base.fontSize,
|
|
16422
|
+
borderRadius: base.borderRadius,
|
|
16423
|
+
gap: base.gap
|
|
16424
|
+
};
|
|
16425
|
+
}
|
|
16426
|
+
function clusterSizes(samples) {
|
|
16427
|
+
const sorted = [...samples].sort((a, b) => a.height - b.height);
|
|
16428
|
+
const clusters = [];
|
|
16429
|
+
for (const sample of sorted) {
|
|
16430
|
+
const current = clusters[clusters.length - 1];
|
|
16431
|
+
const head = current?.[0];
|
|
16432
|
+
if (!current || !head || Math.abs(sample.height - head.height) > 2) clusters.push([sample]);
|
|
16433
|
+
else current.push(sample);
|
|
16434
|
+
}
|
|
16435
|
+
return clusters.map((group) => {
|
|
16436
|
+
const pick = (key) => group.reduce((sum, item) => sum + item[key], 0) / group.length;
|
|
16437
|
+
return {
|
|
16438
|
+
height: pick("height"),
|
|
16439
|
+
paddingTop: pick("paddingTop"),
|
|
16440
|
+
paddingRight: pick("paddingRight"),
|
|
16441
|
+
paddingBottom: pick("paddingBottom"),
|
|
16442
|
+
paddingLeft: pick("paddingLeft"),
|
|
16443
|
+
fontSize: pick("fontSize"),
|
|
16444
|
+
borderRadius: pick("borderRadius"),
|
|
16445
|
+
gap: pick("gap")
|
|
16446
|
+
};
|
|
16447
|
+
});
|
|
16448
|
+
}
|
|
16449
|
+
function tokensFromSamples(bySlot, radius, gap) {
|
|
16450
|
+
const fill = (id) => {
|
|
16451
|
+
const sample = bySlot[id] ?? REFERENCE_SIZES[id];
|
|
16452
|
+
return geometryFromSample({ ...sample, borderRadius: radius, gap });
|
|
16453
|
+
};
|
|
16454
|
+
return { s: fill("s"), m: fill("m"), l: fill("l") };
|
|
16455
|
+
}
|
|
16456
|
+
function interpolateSizes(known) {
|
|
16457
|
+
const order = BUTTON_SIZE_IDS;
|
|
16458
|
+
const indexOf = (id) => order.indexOf(id);
|
|
16459
|
+
const sorted = [...known].sort((a, b) => indexOf(a.id) - indexOf(b.id));
|
|
16460
|
+
const left = sorted[0];
|
|
16461
|
+
const right = sorted[1];
|
|
16462
|
+
const span = indexOf(right.id) - indexOf(left.id);
|
|
16463
|
+
const step = (key) => (right.sample[key] - left.sample[key]) / span;
|
|
16464
|
+
const at = (index) => {
|
|
16465
|
+
const steps = index - indexOf(left.id);
|
|
16466
|
+
return {
|
|
16467
|
+
height: left.sample.height + step("height") * steps,
|
|
16468
|
+
paddingTop: Math.max(0, left.sample.paddingTop + step("paddingTop") * steps),
|
|
16469
|
+
paddingBottom: Math.max(0, left.sample.paddingBottom + step("paddingBottom") * steps),
|
|
16470
|
+
paddingLeft: Math.max(0, left.sample.paddingLeft + step("paddingLeft") * steps),
|
|
16471
|
+
paddingRight: Math.max(0, left.sample.paddingRight + step("paddingRight") * steps),
|
|
16472
|
+
fontSize: Math.max(10, left.sample.fontSize + step("fontSize") * steps),
|
|
16473
|
+
borderRadius: left.sample.borderRadius,
|
|
16474
|
+
gap: left.sample.gap
|
|
16475
|
+
};
|
|
16476
|
+
};
|
|
16477
|
+
const bySlot = {
|
|
16478
|
+
[left.id]: left.sample,
|
|
16479
|
+
[right.id]: { ...right.sample, borderRadius: left.sample.borderRadius, gap: left.sample.gap }
|
|
16480
|
+
};
|
|
16481
|
+
for (const id of order) {
|
|
16482
|
+
if (!bySlot[id]) bySlot[id] = at(indexOf(id));
|
|
16483
|
+
}
|
|
16484
|
+
return tokensFromSamples(bySlot, left.sample.borderRadius, left.sample.gap);
|
|
16485
|
+
}
|
|
16486
|
+
function generateButtonSizes(samples) {
|
|
16487
|
+
const clusters = clusterSizes(samples.filter((sample) => sample.height > 0));
|
|
16488
|
+
if (clusters.length === 0) {
|
|
16489
|
+
return { status: "ready", tokens: tokensFromSamples(REFERENCE_SIZES, 8, 8) };
|
|
16490
|
+
}
|
|
16491
|
+
if (clusters.length > 3) return { status: "unresolved" };
|
|
16492
|
+
if (clusters.length === 3) {
|
|
16493
|
+
const sorted = [...clusters].sort((a, b) => a.height - b.height);
|
|
16494
|
+
const radius = sorted[1].borderRadius;
|
|
16495
|
+
const gap = sorted[1].gap;
|
|
16496
|
+
return {
|
|
16497
|
+
status: "ready",
|
|
16498
|
+
tokens: {
|
|
16499
|
+
s: geometryFromSample({ ...sorted[0], borderRadius: radius, gap }),
|
|
16500
|
+
m: geometryFromSample({ ...sorted[1], borderRadius: radius, gap }),
|
|
16501
|
+
l: geometryFromSample({ ...sorted[2], borderRadius: radius, gap })
|
|
16502
|
+
}
|
|
16503
|
+
};
|
|
16504
|
+
}
|
|
16505
|
+
if (clusters.length === 1) {
|
|
16506
|
+
const known = clusters[0];
|
|
16507
|
+
const slot = classifyHeight(known.height);
|
|
16508
|
+
const offset = BUTTON_SIZE_IDS.indexOf(slot);
|
|
16509
|
+
const bySlot = Object.fromEntries(
|
|
16510
|
+
BUTTON_SIZE_IDS.map((id, index) => [id, shiftSample(known, index - offset)])
|
|
16511
|
+
);
|
|
16512
|
+
bySlot[slot] = known;
|
|
16513
|
+
return { status: "ready", tokens: tokensFromSamples(bySlot, known.borderRadius, known.gap) };
|
|
16514
|
+
}
|
|
16515
|
+
const mapped = clusters.map((sample) => ({ id: classifyHeight(sample.height), sample }));
|
|
16516
|
+
if (mapped[0].id === mapped[1].id) {
|
|
16517
|
+
const larger = clusters.slice().sort((a, b) => b.height - a.height)[0];
|
|
16518
|
+
return generateButtonSizes([larger]);
|
|
16519
|
+
}
|
|
16520
|
+
return { status: "ready", tokens: interpolateSizes(mapped) };
|
|
16521
|
+
}
|
|
16522
|
+
function parseJson(raw) {
|
|
16523
|
+
if (!raw) return null;
|
|
16524
|
+
try {
|
|
16525
|
+
return JSON.parse(raw);
|
|
16526
|
+
} catch {
|
|
16527
|
+
return null;
|
|
16528
|
+
}
|
|
16529
|
+
}
|
|
16530
|
+
function isChrome(value) {
|
|
16531
|
+
if (!value || typeof value !== "object") return false;
|
|
16532
|
+
const chrome = value;
|
|
16533
|
+
return typeof chrome.background === "string" && typeof chrome.color === "string";
|
|
16534
|
+
}
|
|
16535
|
+
function isGeometry(value) {
|
|
16536
|
+
if (!value || typeof value !== "object") return false;
|
|
16537
|
+
const geometry = value;
|
|
16538
|
+
return typeof geometry.paddingTop === "string" && typeof geometry.height === "number";
|
|
16539
|
+
}
|
|
16540
|
+
function readVariantTokens(content) {
|
|
16541
|
+
const parsed = parseJson(content[BUTTON_VARIANTS_KEY]);
|
|
16542
|
+
if (!parsed) return null;
|
|
16543
|
+
if (!BUTTON_VARIANT_IDS.every((id) => isChrome(parsed[id]))) return null;
|
|
16544
|
+
return parsed;
|
|
16545
|
+
}
|
|
16546
|
+
function readSizeTokens(content) {
|
|
16547
|
+
const parsed = parseJson(content[BUTTON_SIZES_KEY]);
|
|
16548
|
+
if (!parsed) return null;
|
|
16549
|
+
if (!BUTTON_SIZE_IDS.every((id) => isGeometry(parsed[id]))) return null;
|
|
16550
|
+
return parsed;
|
|
16551
|
+
}
|
|
16552
|
+
function readAssignments(content) {
|
|
16553
|
+
const parsed = parseJson(content[BUTTON_ASSIGNMENTS_KEY]);
|
|
16554
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
16555
|
+
const next = {};
|
|
16556
|
+
for (const [id, value] of Object.entries(parsed)) {
|
|
16557
|
+
if (!value || !isButtonVariantId(value.variant) || !isButtonSizeId(value.size)) continue;
|
|
16558
|
+
next[id] = { variant: value.variant, size: value.size };
|
|
16559
|
+
}
|
|
16560
|
+
return next;
|
|
16561
|
+
}
|
|
16562
|
+
function cssLength(style, prop) {
|
|
16563
|
+
return style.getPropertyValue(prop) || "0px";
|
|
16564
|
+
}
|
|
16565
|
+
function readVariantSample(el) {
|
|
16566
|
+
const style = getComputedStyle(el);
|
|
16567
|
+
return {
|
|
16568
|
+
background: style.backgroundColor,
|
|
16569
|
+
color: style.color,
|
|
16570
|
+
borderColor: style.borderTopColor,
|
|
16571
|
+
borderWidth: style.borderTopWidth,
|
|
16572
|
+
className: el.className || ""
|
|
16573
|
+
};
|
|
16574
|
+
}
|
|
16575
|
+
function readSizeSample(el) {
|
|
16576
|
+
const style = getComputedStyle(el);
|
|
16577
|
+
const rootFont = parsePx(getComputedStyle(el.ownerDocument.documentElement).fontSize) || 16;
|
|
16578
|
+
const rect = el.getBoundingClientRect();
|
|
16579
|
+
return {
|
|
16580
|
+
height: rect.height,
|
|
16581
|
+
paddingTop: parsePx(cssLength(style, "padding-top"), rootFont),
|
|
16582
|
+
paddingRight: parsePx(cssLength(style, "padding-right"), rootFont),
|
|
16583
|
+
paddingBottom: parsePx(cssLength(style, "padding-bottom"), rootFont),
|
|
16584
|
+
paddingLeft: parsePx(cssLength(style, "padding-left"), rootFont),
|
|
16585
|
+
fontSize: parsePx(style.fontSize, rootFont),
|
|
16586
|
+
borderRadius: parsePx(style.borderTopLeftRadius, rootFont),
|
|
16587
|
+
gap: parsePx(style.columnGap || style.gap, rootFont)
|
|
16588
|
+
};
|
|
16589
|
+
}
|
|
16590
|
+
function readTypography(el) {
|
|
16591
|
+
const style = getComputedStyle(el);
|
|
16592
|
+
return {
|
|
16593
|
+
fontFamily: style.fontFamily,
|
|
16594
|
+
fontWeight: style.fontWeight,
|
|
16595
|
+
letterSpacing: style.letterSpacing,
|
|
16596
|
+
textTransform: style.textTransform,
|
|
16597
|
+
textDecoration: style.textDecorationLine || style.textDecoration || "none"
|
|
16598
|
+
};
|
|
16599
|
+
}
|
|
16600
|
+
var buttonOriginByEl = /* @__PURE__ */ new WeakMap();
|
|
16601
|
+
var ORIGIN_ATTR = "data-ohw-btn-origin";
|
|
16602
|
+
function parseOriginAttr(raw) {
|
|
16603
|
+
if (!raw) return null;
|
|
16604
|
+
try {
|
|
16605
|
+
const value = JSON.parse(raw);
|
|
16606
|
+
if (!value?.variant || !value.size || !value.typography) return null;
|
|
16607
|
+
return value;
|
|
16608
|
+
} catch {
|
|
16609
|
+
return null;
|
|
16610
|
+
}
|
|
16611
|
+
}
|
|
16612
|
+
function measureLiveOrigin(el) {
|
|
16613
|
+
return {
|
|
16614
|
+
variant: readVariantSample(el),
|
|
16615
|
+
size: readSizeSample(el),
|
|
16616
|
+
typography: readTypography(el)
|
|
16617
|
+
};
|
|
16618
|
+
}
|
|
16619
|
+
function captureButtonOrigin(el) {
|
|
16620
|
+
const cached = buttonOriginByEl.get(el);
|
|
16621
|
+
if (cached) return cached;
|
|
16622
|
+
const fromAttr = parseOriginAttr(el.getAttribute(ORIGIN_ATTR));
|
|
16623
|
+
if (fromAttr) {
|
|
16624
|
+
buttonOriginByEl.set(el, fromAttr);
|
|
16625
|
+
return fromAttr;
|
|
16626
|
+
}
|
|
16627
|
+
const origin = measureLiveOrigin(el);
|
|
16628
|
+
buttonOriginByEl.set(el, origin);
|
|
16629
|
+
try {
|
|
16630
|
+
el.setAttribute(ORIGIN_ATTR, JSON.stringify(origin));
|
|
16631
|
+
} catch {
|
|
16632
|
+
}
|
|
16633
|
+
return origin;
|
|
16634
|
+
}
|
|
16635
|
+
function listStyleButtons(doc) {
|
|
16636
|
+
return Array.from(doc.querySelectorAll(CTA_BUTTON_SELECTOR)).filter((el) => {
|
|
16637
|
+
if (el.closest("[data-ohw-bridge], [data-ohw-bridge-root]")) return false;
|
|
16638
|
+
const rect = el.getBoundingClientRect();
|
|
16639
|
+
return rect.width > 0 && rect.height > 0;
|
|
16640
|
+
});
|
|
16641
|
+
}
|
|
16642
|
+
function generateTokensFromButtons(buttons) {
|
|
16643
|
+
const variants = generateButtonVariants(buttons.map(readVariantSample));
|
|
16644
|
+
const sizes = generateButtonSizes(buttons.map(readSizeSample));
|
|
16645
|
+
if (variants.status !== "ready" || sizes.status !== "ready") return { status: "unresolved" };
|
|
16646
|
+
return { status: "ready", tokens: { variants: variants.tokens, sizes: sizes.tokens } };
|
|
16647
|
+
}
|
|
16648
|
+
function tokensFromButton(el) {
|
|
16649
|
+
const origin = captureButtonOrigin(el);
|
|
16650
|
+
const sample = origin.variant;
|
|
16651
|
+
const variants = generateButtonVariants([sample]);
|
|
16652
|
+
const sizes = generateButtonSizes([origin.size]);
|
|
16653
|
+
const primary = chromeFrom(sample);
|
|
16654
|
+
return {
|
|
16655
|
+
variants: variants.status === "ready" ? variants.tokens : { primary, secondary: generatedSecondary(primary), ghost: generatedGhost(primary) },
|
|
16656
|
+
sizes: sizes.status === "ready" ? sizes.tokens : tokensFromSamples(REFERENCE_SIZES, 8, 8)
|
|
16657
|
+
};
|
|
16658
|
+
}
|
|
16659
|
+
function readStoredStyleTokens(content) {
|
|
16660
|
+
const variants = readVariantTokens(content);
|
|
16661
|
+
const sizes = readSizeTokens(content);
|
|
16662
|
+
if (!variants || !sizes) return null;
|
|
16663
|
+
return { variants, sizes };
|
|
16664
|
+
}
|
|
16665
|
+
function styleTokenNodes(tokens) {
|
|
16666
|
+
return [
|
|
16667
|
+
{ key: BUTTON_VARIANTS_KEY, text: JSON.stringify(tokens.variants) },
|
|
16668
|
+
{ key: BUTTON_SIZES_KEY, text: JSON.stringify(tokens.sizes) }
|
|
16669
|
+
];
|
|
16670
|
+
}
|
|
16671
|
+
function ensureButtonStyleTokens(doc, content) {
|
|
16672
|
+
const stored = readStoredStyleTokens(content);
|
|
16673
|
+
if (stored) return { tokens: stored, nodes: [] };
|
|
16674
|
+
const generated = generateTokensFromButtons(listStyleButtons(doc));
|
|
16675
|
+
if (generated.status !== "ready") return { tokens: null, nodes: [] };
|
|
16676
|
+
return { tokens: generated.tokens, nodes: styleTokenNodes(generated.tokens) };
|
|
16677
|
+
}
|
|
16678
|
+
function detectVariant(el, tokens) {
|
|
16679
|
+
const declared = declaredVariant(el.className || "");
|
|
16680
|
+
if (declared) return declared;
|
|
16681
|
+
const stamped = el.getAttribute("data-ohw-btn-variant");
|
|
16682
|
+
if (stamped && isButtonVariantId(stamped)) return stamped;
|
|
16683
|
+
const sample = readVariantSample(el);
|
|
16684
|
+
if (!tokens) return sampleSlot(sample);
|
|
16685
|
+
const key = fingerprint(sample);
|
|
16686
|
+
for (const id of BUTTON_VARIANT_IDS) {
|
|
16687
|
+
const chrome = tokens[id];
|
|
16688
|
+
const tokenKey = fingerprint({
|
|
16689
|
+
background: chrome.background,
|
|
16690
|
+
color: chrome.color,
|
|
16691
|
+
borderColor: chrome.borderColor,
|
|
16692
|
+
borderWidth: chrome.borderWidth,
|
|
16693
|
+
className: `btn btn--${id}`
|
|
16694
|
+
});
|
|
16695
|
+
if (tokenKey === key) return id;
|
|
16696
|
+
}
|
|
16697
|
+
return sampleSlot(sample);
|
|
16698
|
+
}
|
|
16699
|
+
function detectSize(el, tokens) {
|
|
16700
|
+
const stamped = el.getAttribute("data-ohw-btn-size");
|
|
16701
|
+
if (stamped && isButtonSizeId(stamped)) return stamped;
|
|
16702
|
+
const height = el.getBoundingClientRect().height;
|
|
16703
|
+
if (!tokens) return classifyHeight(height);
|
|
16704
|
+
let best = "m";
|
|
16705
|
+
let bestDelta = Number.POSITIVE_INFINITY;
|
|
16706
|
+
for (const id of BUTTON_SIZE_IDS) {
|
|
16707
|
+
const delta = Math.abs(tokens[id].height - height);
|
|
16708
|
+
if (delta < bestDelta) {
|
|
16709
|
+
best = id;
|
|
16710
|
+
bestDelta = delta;
|
|
16711
|
+
}
|
|
16712
|
+
}
|
|
16713
|
+
return best;
|
|
16714
|
+
}
|
|
16715
|
+
function assignmentFor(el, content, tokens) {
|
|
16716
|
+
const id = buttonId(el);
|
|
16717
|
+
const stored = id ? readAssignments(content)[id] : void 0;
|
|
16718
|
+
if (stored) return stored;
|
|
16719
|
+
return {
|
|
16720
|
+
variant: detectVariant(el, tokens?.variants ?? null),
|
|
16721
|
+
size: detectSize(el, tokens?.sizes ?? null)
|
|
16722
|
+
};
|
|
16723
|
+
}
|
|
16724
|
+
function labelElement(el) {
|
|
16725
|
+
return el.querySelector('[data-ohw-editable="text"], [data-ohw-editable="plain"]') ?? (el.matches('[data-ohw-editable="text"], [data-ohw-editable="plain"]') ? el : null);
|
|
16726
|
+
}
|
|
16727
|
+
var paintLockByEl = /* @__PURE__ */ new WeakMap();
|
|
16728
|
+
var paintObserverByEl = /* @__PURE__ */ new WeakMap();
|
|
16729
|
+
var paintingButton = false;
|
|
16730
|
+
function paintButtonChrome(el, assignment, tokens) {
|
|
16731
|
+
const origin = captureButtonOrigin(el);
|
|
16732
|
+
const chrome = tokens.variants[assignment.variant];
|
|
16733
|
+
const originSlot = classifyHeight(origin.size.height);
|
|
16734
|
+
const geometry = assignment.size === originSlot ? geometryFromSample({ ...origin.size, borderRadius: origin.size.borderRadius, gap: origin.size.gap }) : tokens.sizes[assignment.size];
|
|
16735
|
+
const { typography } = origin;
|
|
16736
|
+
el.setAttribute("data-ohw-btn-variant", assignment.variant);
|
|
16737
|
+
el.setAttribute("data-ohw-btn-size", assignment.size);
|
|
16738
|
+
el.style.transition = "none";
|
|
16739
|
+
el.style.boxSizing = "border-box";
|
|
16740
|
+
el.style.display = "inline-flex";
|
|
16741
|
+
el.style.alignItems = "center";
|
|
16742
|
+
el.style.justifyContent = "center";
|
|
16743
|
+
el.style.background = chrome.background;
|
|
16744
|
+
el.style.color = chrome.color;
|
|
16745
|
+
el.style.borderStyle = parseFloat(chrome.borderWidth) > 0 ? "solid" : "none";
|
|
16746
|
+
el.style.borderColor = chrome.borderColor;
|
|
16747
|
+
el.style.borderWidth = chrome.borderWidth;
|
|
16748
|
+
el.style.padding = `${geometry.paddingTop} ${geometry.paddingRight} ${geometry.paddingBottom} ${geometry.paddingLeft}`;
|
|
16749
|
+
el.style.fontSize = geometry.fontSize;
|
|
16750
|
+
el.style.borderRadius = px(origin.size.borderRadius);
|
|
16751
|
+
el.style.gap = geometry.gap;
|
|
16752
|
+
el.style.height = px(geometry.height);
|
|
16753
|
+
el.style.fontFamily = typography.fontFamily;
|
|
16754
|
+
el.style.fontWeight = typography.fontWeight;
|
|
16755
|
+
el.style.letterSpacing = typography.letterSpacing;
|
|
16756
|
+
el.style.textTransform = typography.textTransform;
|
|
16757
|
+
if (typography.textDecoration && typography.textDecoration !== "none") {
|
|
16758
|
+
el.style.textDecoration = typography.textDecoration;
|
|
16759
|
+
} else {
|
|
16760
|
+
el.style.textDecoration = "none";
|
|
16761
|
+
}
|
|
16762
|
+
const label = labelElement(el);
|
|
16763
|
+
if (label && label !== el) label.style.color = chrome.color;
|
|
16764
|
+
}
|
|
16765
|
+
function guardTemplateHover(el) {
|
|
16766
|
+
if (paintObserverByEl.has(el)) return;
|
|
16767
|
+
const observer = new MutationObserver(() => {
|
|
16768
|
+
if (paintingButton) return;
|
|
16769
|
+
const lock = paintLockByEl.get(el);
|
|
16770
|
+
if (!lock) return;
|
|
16771
|
+
paintingButton = true;
|
|
16772
|
+
paintButtonChrome(el, lock.assignment, lock.tokens);
|
|
16773
|
+
paintingButton = false;
|
|
16774
|
+
});
|
|
16775
|
+
observer.observe(el, { attributes: true, attributeFilter: ["style", "class"] });
|
|
16776
|
+
paintObserverByEl.set(el, observer);
|
|
16777
|
+
}
|
|
16778
|
+
function applyButtonStyle(el, assignment, tokens) {
|
|
16779
|
+
paintLockByEl.set(el, { assignment, tokens });
|
|
16780
|
+
paintingButton = true;
|
|
16781
|
+
paintButtonChrome(el, assignment, tokens);
|
|
16782
|
+
paintingButton = false;
|
|
16783
|
+
guardTemplateHover(el);
|
|
16784
|
+
}
|
|
16785
|
+
function applyButtonStylesFromContent(doc, content) {
|
|
16786
|
+
const assignments = readAssignments(content);
|
|
16787
|
+
for (const [id, assignment] of Object.entries(assignments)) {
|
|
16788
|
+
const el = doc.querySelector(`[data-ohw-href-key="${CSS.escape(id)}"]`);
|
|
16789
|
+
if (!el) continue;
|
|
16790
|
+
applyButtonStyle(el, assignment, tokensFromButton(el));
|
|
16791
|
+
}
|
|
16792
|
+
}
|
|
16793
|
+
function withAssignment(content, id, assignment) {
|
|
16794
|
+
return { ...readAssignments(content), [id]: assignment };
|
|
16795
|
+
}
|
|
16796
|
+
|
|
16797
|
+
// src/ui/button-style-panel.tsx
|
|
16798
|
+
import { jsx as jsx31, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
16799
|
+
var SIZE_LABEL = { s: "S", m: "M", l: "L" };
|
|
16800
|
+
function ButtonStylePanel({
|
|
16801
|
+
variants,
|
|
16802
|
+
sizes,
|
|
16803
|
+
variant,
|
|
16804
|
+
size,
|
|
16805
|
+
onVariant,
|
|
16806
|
+
onSize,
|
|
16807
|
+
previewLabel = "Book Now",
|
|
16808
|
+
slotBackground = "var(--brand-background, var(--ohw-brand-light, var(--color-light, #ffffff)))"
|
|
16809
|
+
}) {
|
|
16810
|
+
const preview = scaleGeometry(sizes.m, 0.75);
|
|
16811
|
+
const label = previewLabel.trim() || "Book Now";
|
|
16812
|
+
return /* @__PURE__ */ jsxs21("div", { className: "flex w-full flex-col gap-5", children: [
|
|
16813
|
+
/* @__PURE__ */ jsxs21("section", { className: "flex w-full flex-col gap-2.5", children: [
|
|
16814
|
+
/* @__PURE__ */ jsx31("h3", { className: "text-xs font-semibold uppercase leading-4 tracking-[0.6px] text-stone-500 font-sans", children: "Variants" }),
|
|
16815
|
+
/* @__PURE__ */ jsx31("div", { className: "flex w-full flex-col gap-2.5", children: BUTTON_VARIANT_IDS.map((id) => {
|
|
16816
|
+
const chrome = variants[id];
|
|
16817
|
+
const selected = id === variant;
|
|
16818
|
+
const hasBorder = parseFloat(chrome.borderWidth) > 0;
|
|
16819
|
+
const cardSlot = previewSlotForChrome(chrome, slotBackground);
|
|
16820
|
+
return /* @__PURE__ */ jsxs21(
|
|
16821
|
+
"button",
|
|
16822
|
+
{
|
|
16823
|
+
type: "button",
|
|
16824
|
+
"aria-pressed": selected,
|
|
16825
|
+
"aria-label": id,
|
|
16826
|
+
onMouseDown: (e) => {
|
|
16827
|
+
e.preventDefault();
|
|
16828
|
+
e.stopPropagation();
|
|
16829
|
+
},
|
|
16830
|
+
onClick: () => onVariant(id),
|
|
16831
|
+
className: cn(
|
|
16832
|
+
"relative w-full overflow-hidden rounded-xl border-solid text-left",
|
|
16833
|
+
selected ? "border-2 border-primary" : "border border-border"
|
|
16834
|
+
),
|
|
16835
|
+
children: [
|
|
16836
|
+
/* @__PURE__ */ jsx31(
|
|
16837
|
+
"div",
|
|
16838
|
+
{
|
|
16839
|
+
className: "flex w-full items-center justify-center py-4",
|
|
16840
|
+
style: { background: cardSlot },
|
|
16841
|
+
children: /* @__PURE__ */ jsx31(
|
|
16842
|
+
"span",
|
|
16843
|
+
{
|
|
16844
|
+
className: "inline-flex items-center justify-center whitespace-nowrap font-semibold uppercase leading-none",
|
|
16845
|
+
style: {
|
|
16846
|
+
background: chrome.background,
|
|
16847
|
+
color: chrome.color,
|
|
16848
|
+
borderColor: chrome.borderColor,
|
|
16849
|
+
borderWidth: hasBorder ? chrome.borderWidth : "0px",
|
|
16850
|
+
borderStyle: hasBorder ? "solid" : "none",
|
|
16851
|
+
padding: `${preview.paddingTop} ${preview.paddingRight} ${preview.paddingBottom} ${preview.paddingLeft}`,
|
|
16852
|
+
fontSize: preview.fontSize,
|
|
16853
|
+
borderRadius: preview.borderRadius,
|
|
16854
|
+
height: preview.height,
|
|
16855
|
+
boxSizing: "border-box",
|
|
16856
|
+
letterSpacing: "0.12em"
|
|
16857
|
+
},
|
|
16858
|
+
children: label
|
|
16859
|
+
}
|
|
16860
|
+
)
|
|
16861
|
+
}
|
|
16862
|
+
),
|
|
16863
|
+
selected ? /* @__PURE__ */ jsx31(
|
|
16864
|
+
"span",
|
|
16865
|
+
{
|
|
16866
|
+
className: "absolute right-0.5 top-0.5 flex size-5 items-center justify-center rounded-full bg-primary text-primary-foreground",
|
|
16867
|
+
"aria-hidden": true,
|
|
16868
|
+
children: /* @__PURE__ */ jsx31(Check3, { className: "size-3", strokeWidth: 3 })
|
|
16869
|
+
}
|
|
16870
|
+
) : null
|
|
16871
|
+
]
|
|
16872
|
+
},
|
|
16873
|
+
id
|
|
16874
|
+
);
|
|
16875
|
+
}) })
|
|
16876
|
+
] }),
|
|
16877
|
+
/* @__PURE__ */ jsxs21("section", { className: "flex w-full flex-col gap-2.5", children: [
|
|
16878
|
+
/* @__PURE__ */ jsx31("h3", { className: "text-xs font-semibold uppercase leading-4 tracking-[0.6px] text-stone-500 font-sans", children: "Size" }),
|
|
16879
|
+
/* @__PURE__ */ jsx31(
|
|
16880
|
+
"div",
|
|
16881
|
+
{
|
|
16882
|
+
className: "flex w-full items-start rounded-lg bg-stone-100 p-1",
|
|
16883
|
+
role: "radiogroup",
|
|
16884
|
+
"aria-label": "Size",
|
|
16885
|
+
children: BUTTON_SIZE_IDS.map((id) => {
|
|
16886
|
+
const selected = id === size;
|
|
16887
|
+
return /* @__PURE__ */ jsx31(
|
|
16888
|
+
"button",
|
|
16889
|
+
{
|
|
16890
|
+
type: "button",
|
|
16891
|
+
role: "radio",
|
|
16892
|
+
"aria-checked": selected,
|
|
16893
|
+
onMouseDown: (e) => {
|
|
16894
|
+
e.preventDefault();
|
|
16895
|
+
e.stopPropagation();
|
|
16896
|
+
},
|
|
16897
|
+
onClick: () => onSize(id),
|
|
16898
|
+
className: cn(
|
|
16899
|
+
"flex min-w-14 flex-1 items-center justify-center rounded-md px-3 py-1.5 text-sm font-medium leading-5",
|
|
16900
|
+
selected ? "bg-white text-stone-950 shadow-sm" : "bg-transparent text-stone-500"
|
|
16901
|
+
),
|
|
16902
|
+
children: SIZE_LABEL[id]
|
|
16903
|
+
},
|
|
16904
|
+
id
|
|
16905
|
+
);
|
|
16906
|
+
})
|
|
16907
|
+
}
|
|
16908
|
+
)
|
|
16909
|
+
] })
|
|
16910
|
+
] });
|
|
16911
|
+
}
|
|
16912
|
+
|
|
16913
|
+
// src/lib/button-collections.ts
|
|
16914
|
+
var BUTTON_COLLECTIONS_KEY = "__ohw_button_collections";
|
|
16915
|
+
var BUTTON_SNAPSHOTS_KEY = "__ohw_button_snapshots";
|
|
16916
|
+
var BUTTON_HIDDEN_KEY = "__ohw_button_hidden";
|
|
16917
|
+
var COLLECTION_ATTR = "data-ohw-button-collection";
|
|
16918
|
+
function parseJson2(raw) {
|
|
16919
|
+
if (!raw) return null;
|
|
16920
|
+
try {
|
|
16921
|
+
return JSON.parse(raw);
|
|
16922
|
+
} catch {
|
|
16923
|
+
return null;
|
|
16924
|
+
}
|
|
16925
|
+
}
|
|
16926
|
+
function readCollections(content) {
|
|
16927
|
+
const parsed = parseJson2(content[BUTTON_COLLECTIONS_KEY]);
|
|
16928
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
16929
|
+
const next = {};
|
|
16930
|
+
for (const [id, value] of Object.entries(parsed)) {
|
|
16931
|
+
if (!value || !Array.isArray(value.members)) continue;
|
|
16932
|
+
next[id] = {
|
|
16933
|
+
id,
|
|
16934
|
+
members: value.members.filter((member) => typeof member === "string" && member),
|
|
16935
|
+
gap: typeof value.gap === "string" ? value.gap : "12px"
|
|
16936
|
+
};
|
|
16937
|
+
}
|
|
16938
|
+
return next;
|
|
16939
|
+
}
|
|
16940
|
+
function readSnapshots(content) {
|
|
16941
|
+
const parsed = parseJson2(content[BUTTON_SNAPSHOTS_KEY]);
|
|
16942
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
16943
|
+
const next = {};
|
|
16944
|
+
for (const [id, value] of Object.entries(parsed)) {
|
|
16945
|
+
if (!value || typeof value.html !== "string") continue;
|
|
16946
|
+
next[id] = value;
|
|
16947
|
+
}
|
|
16948
|
+
return next;
|
|
16949
|
+
}
|
|
16950
|
+
function readHiddenButtons(content) {
|
|
16951
|
+
const parsed = parseJson2(content[BUTTON_HIDDEN_KEY]);
|
|
16952
|
+
if (!Array.isArray(parsed)) return [];
|
|
16953
|
+
return parsed.filter((id) => typeof id === "string" && id);
|
|
16954
|
+
}
|
|
16955
|
+
function buttonCollectionOf(el) {
|
|
16956
|
+
return el?.closest(`[${COLLECTION_ATTR}]`) ?? null;
|
|
16957
|
+
}
|
|
16958
|
+
function isNavbarCta(el) {
|
|
16959
|
+
return el.getAttribute("data-ohw-role") === "navbar-button" || Boolean(el.closest('[data-ohw-role="navbar-button"]'));
|
|
16960
|
+
}
|
|
16961
|
+
function navbarScope(el) {
|
|
16962
|
+
return el.closest("nav, [data-ohw-nav-container], [data-ohw-nav-drawer]") ?? el.ownerDocument;
|
|
16963
|
+
}
|
|
16964
|
+
function isLastNavbarButton(el) {
|
|
16965
|
+
if (!isNavbarCta(el)) return false;
|
|
16966
|
+
const buttons = Array.from(navbarScope(el).querySelectorAll(CTA_BUTTON_SELECTOR)).filter(
|
|
16967
|
+
(button) => isNavbarCta(button) && buttonId(button)
|
|
16968
|
+
);
|
|
16969
|
+
return buttons.length <= 1;
|
|
16970
|
+
}
|
|
16971
|
+
function canDeleteButton(el) {
|
|
16972
|
+
return !isLastNavbarButton(el);
|
|
16973
|
+
}
|
|
16974
|
+
function canDuplicateButton(el) {
|
|
16975
|
+
return isNavbarCta(el);
|
|
16976
|
+
}
|
|
16977
|
+
function labelElement2(el) {
|
|
16978
|
+
return el.querySelector('[data-ohw-editable="text"], [data-ohw-editable="plain"]') ?? el.querySelector("[data-ohw-key]");
|
|
16979
|
+
}
|
|
16980
|
+
function buttonLabel(el) {
|
|
16981
|
+
return (labelElement2(el)?.textContent ?? el.textContent ?? "").trim();
|
|
16982
|
+
}
|
|
16983
|
+
function buttonHref(el) {
|
|
16984
|
+
return el.getAttribute("href") ?? "";
|
|
16985
|
+
}
|
|
16986
|
+
function hrefKeyBase(hrefKey) {
|
|
16987
|
+
return hrefKey.replace(/-href$/, "").replace(/-copy-\d+$/, "");
|
|
16988
|
+
}
|
|
16989
|
+
function labelKeyForHrefKey(hrefKey) {
|
|
16990
|
+
return `${hrefKey.replace(/-href$/, "")}-label`;
|
|
16991
|
+
}
|
|
16992
|
+
function cleanClone(el) {
|
|
16993
|
+
const copy = el.cloneNode(true);
|
|
16994
|
+
copy.querySelectorAll("[data-ohw-selected], [data-ohw-hovered], [data-ohw-editing]").forEach((node) => {
|
|
16995
|
+
node.removeAttribute("data-ohw-selected");
|
|
16996
|
+
node.removeAttribute("data-ohw-hovered");
|
|
16997
|
+
node.removeAttribute("data-ohw-editing");
|
|
16998
|
+
node.removeAttribute("contenteditable");
|
|
16999
|
+
});
|
|
17000
|
+
copy.removeAttribute("data-ohw-selected");
|
|
17001
|
+
copy.removeAttribute("data-ohw-hovered");
|
|
17002
|
+
copy.removeAttribute("data-ohw-editing");
|
|
17003
|
+
copy.removeAttribute("contenteditable");
|
|
17004
|
+
copy.removeAttribute("data-ohw-drag-disabled");
|
|
17005
|
+
return copy;
|
|
17006
|
+
}
|
|
17007
|
+
function nextCopyId(sourceId, content, doc) {
|
|
17008
|
+
const used = /* @__PURE__ */ new Set([
|
|
17009
|
+
...Object.keys(readSnapshots(content)),
|
|
17010
|
+
...Object.keys(readAssignments(content)),
|
|
17011
|
+
...Array.from(doc.querySelectorAll("[data-ohw-href-key]")).map(
|
|
17012
|
+
(el) => el.getAttribute("data-ohw-href-key") ?? ""
|
|
17013
|
+
)
|
|
17014
|
+
]);
|
|
17015
|
+
const base = hrefKeyBase(sourceId);
|
|
17016
|
+
let n = 2;
|
|
17017
|
+
while (used.has(`${base}-copy-${n}-href`)) n += 1;
|
|
17018
|
+
return `${base}-copy-${n}-href`;
|
|
17019
|
+
}
|
|
17020
|
+
function nextCollectionId(content, doc) {
|
|
17021
|
+
const used = /* @__PURE__ */ new Set([
|
|
17022
|
+
...Object.keys(readCollections(content)),
|
|
17023
|
+
...Array.from(doc.querySelectorAll(`[${COLLECTION_ATTR}]`)).map(
|
|
17024
|
+
(el) => el.getAttribute(COLLECTION_ATTR) ?? ""
|
|
17025
|
+
)
|
|
17026
|
+
]);
|
|
17027
|
+
let n = 1;
|
|
17028
|
+
while (used.has(`bc-${n}`)) n += 1;
|
|
17029
|
+
return `bc-${n}`;
|
|
17030
|
+
}
|
|
17031
|
+
var COLLECTION_GAP_MAX_PX = 12;
|
|
17032
|
+
var COLLECTION_GAP_DEFAULT = "12px";
|
|
17033
|
+
function usableGap(value) {
|
|
17034
|
+
if (!value || value === "normal") return null;
|
|
17035
|
+
const n = parseFloat(value);
|
|
17036
|
+
if (!Number.isFinite(n) || n <= 0) return null;
|
|
17037
|
+
if (n > COLLECTION_GAP_MAX_PX) return COLLECTION_GAP_DEFAULT;
|
|
17038
|
+
return `${Math.round(n * 100) / 100}px`;
|
|
17039
|
+
}
|
|
17040
|
+
function collectionGap(el, tokens) {
|
|
17041
|
+
const fromCollection = usableGap(buttonCollectionOf(el)?.style.gap);
|
|
17042
|
+
if (fromCollection) return fromCollection;
|
|
17043
|
+
const parent = el.parentElement;
|
|
17044
|
+
if (parent) {
|
|
17045
|
+
const style = getComputedStyle(parent);
|
|
17046
|
+
const fromParent = usableGap(style.columnGap) ?? usableGap(style.gap);
|
|
17047
|
+
if (fromParent) return fromParent;
|
|
17048
|
+
}
|
|
17049
|
+
const fromTokens = usableGap(tokens?.sizes.m.gap);
|
|
17050
|
+
if (fromTokens) return fromTokens;
|
|
17051
|
+
return COLLECTION_GAP_DEFAULT;
|
|
17052
|
+
}
|
|
17053
|
+
function styleCollection(collection, gap) {
|
|
17054
|
+
collection.style.display = "inline-flex";
|
|
17055
|
+
collection.style.alignItems = "center";
|
|
17056
|
+
collection.style.flexWrap = "wrap";
|
|
17057
|
+
collection.style.gap = gap;
|
|
17058
|
+
collection.style.maxWidth = "100%";
|
|
17059
|
+
}
|
|
17060
|
+
function createCollection(doc, id, gap) {
|
|
17061
|
+
const collection = doc.createElement("div");
|
|
17062
|
+
collection.setAttribute(COLLECTION_ATTR, id);
|
|
17063
|
+
styleCollection(collection, gap);
|
|
17064
|
+
return collection;
|
|
17065
|
+
}
|
|
17066
|
+
function setButtonDragAttr(el) {
|
|
17067
|
+
if (isNavbarCta(el) && buttonCollectionOf(el)) el.removeAttribute("data-ohw-drag-disabled");
|
|
17068
|
+
else el.setAttribute("data-ohw-drag-disabled", "true");
|
|
17069
|
+
}
|
|
17070
|
+
function rekeyCopy(copy, id) {
|
|
17071
|
+
copy.setAttribute("data-ohw-href-key", id);
|
|
17072
|
+
const label = labelElement2(copy);
|
|
17073
|
+
const labelKey = labelKeyForHrefKey(id);
|
|
17074
|
+
if (label) label.setAttribute("data-ohw-key", labelKey);
|
|
17075
|
+
setButtonDragAttr(copy);
|
|
17076
|
+
return { labelKey };
|
|
17077
|
+
}
|
|
17078
|
+
function stampVariantClass(el, variant) {
|
|
17079
|
+
const raw = typeof el.className === "string" ? el.className : el.getAttribute("class") || "";
|
|
17080
|
+
const without = raw.replace(/\bbtn--(?:primary|secondary|ghost)\b/g, "").replace(/\s+/g, " ").trim();
|
|
17081
|
+
el.className = without ? `${without} btn--${variant}` : `btn btn--${variant}`;
|
|
17082
|
+
}
|
|
17083
|
+
function snapshotOf(el) {
|
|
17084
|
+
const id = buttonId(el) ?? "";
|
|
17085
|
+
const label = labelElement2(el);
|
|
17086
|
+
return {
|
|
17087
|
+
id,
|
|
17088
|
+
href: buttonHref(el),
|
|
17089
|
+
label: buttonLabel(el),
|
|
17090
|
+
labelKey: label?.getAttribute("data-ohw-key") ?? labelKeyForHrefKey(id),
|
|
17091
|
+
html: cleanClone(el).outerHTML
|
|
17092
|
+
};
|
|
17093
|
+
}
|
|
17094
|
+
function htmlToElement(doc, html) {
|
|
17095
|
+
const wrap = doc.createElement("div");
|
|
17096
|
+
wrap.innerHTML = html;
|
|
17097
|
+
const el = wrap.firstElementChild;
|
|
17098
|
+
return el instanceof HTMLElement ? el : null;
|
|
17099
|
+
}
|
|
17100
|
+
function findButton(doc, id) {
|
|
17101
|
+
return doc.querySelector(`[data-ohw-href-key="${CSS.escape(id)}"]`);
|
|
17102
|
+
}
|
|
17103
|
+
function duplicateButton(source, content) {
|
|
17104
|
+
if (!canDuplicateButton(source)) return null;
|
|
17105
|
+
const sourceId = buttonId(source);
|
|
17106
|
+
if (!sourceId) return null;
|
|
17107
|
+
const doc = source.ownerDocument;
|
|
17108
|
+
const tokens = tokensFromButton(source);
|
|
17109
|
+
const copyId = nextCopyId(sourceId, content, doc);
|
|
17110
|
+
const copy = cleanClone(source);
|
|
17111
|
+
const { labelKey } = rekeyCopy(copy, copyId);
|
|
17112
|
+
const href = buttonHref(source);
|
|
17113
|
+
const label = buttonLabel(source);
|
|
17114
|
+
if (href) copy.setAttribute("href", href);
|
|
17115
|
+
const sourceAssignment = readAssignments(content)[sourceId] ?? assignmentFor(source, content, tokens);
|
|
17116
|
+
const copyAssignment = {
|
|
17117
|
+
variant: "secondary",
|
|
17118
|
+
size: sourceAssignment.size
|
|
17119
|
+
};
|
|
17120
|
+
stampVariantClass(copy, "secondary");
|
|
17121
|
+
applyButtonStyle(copy, copyAssignment, tokens);
|
|
17122
|
+
const copyLabelEl = labelElement2(copy);
|
|
17123
|
+
if (copyLabelEl) copyLabelEl.textContent = label;
|
|
17124
|
+
let collection = buttonCollectionOf(source);
|
|
17125
|
+
const collections = readCollections(content);
|
|
17126
|
+
let collectionId = collection?.getAttribute(COLLECTION_ATTR) ?? "";
|
|
17127
|
+
let members = collectionId && collections[collectionId] ? [...collections[collectionId].members] : [];
|
|
17128
|
+
const gap = collectionGap(source, tokens);
|
|
17129
|
+
if (!collection) {
|
|
17130
|
+
collectionId = nextCollectionId(content, doc);
|
|
17131
|
+
collection = createCollection(doc, collectionId, gap);
|
|
17132
|
+
source.parentElement?.insertBefore(collection, source);
|
|
17133
|
+
collection.append(source, copy);
|
|
17134
|
+
setButtonDragAttr(source);
|
|
17135
|
+
setButtonDragAttr(copy);
|
|
17136
|
+
members = [sourceId, copyId];
|
|
17137
|
+
} else {
|
|
17138
|
+
styleCollection(collection, gap);
|
|
17139
|
+
source.after(copy);
|
|
17140
|
+
setButtonDragAttr(copy);
|
|
17141
|
+
if (!members.includes(sourceId)) members = listCollectionMembers(collection);
|
|
17142
|
+
const at = members.indexOf(sourceId);
|
|
17143
|
+
members.splice(at >= 0 ? at + 1 : members.length, 0, copyId);
|
|
17144
|
+
}
|
|
17145
|
+
const sourceLabelKey = labelElement2(source)?.getAttribute("data-ohw-key");
|
|
17146
|
+
const snapshots = {
|
|
17147
|
+
...readSnapshots(content),
|
|
17148
|
+
[sourceId]: snapshotOf(source),
|
|
17149
|
+
[copyId]: snapshotOf(copy)
|
|
17150
|
+
};
|
|
17151
|
+
const nextCollections = {
|
|
17152
|
+
...collections,
|
|
17153
|
+
[collectionId]: { id: collectionId, members, gap }
|
|
17154
|
+
};
|
|
17155
|
+
const assignments = withAssignment(content, copyId, copyAssignment);
|
|
17156
|
+
const nextContent = {
|
|
17157
|
+
...content,
|
|
17158
|
+
[copyId]: href,
|
|
17159
|
+
[labelKey]: label,
|
|
17160
|
+
[BUTTON_COLLECTIONS_KEY]: JSON.stringify(nextCollections),
|
|
17161
|
+
[BUTTON_SNAPSHOTS_KEY]: JSON.stringify(snapshots),
|
|
17162
|
+
[BUTTON_ASSIGNMENTS_KEY]: JSON.stringify(assignments)
|
|
17163
|
+
};
|
|
17164
|
+
if (sourceLabelKey && nextContent[sourceLabelKey] === void 0) {
|
|
17165
|
+
nextContent[sourceLabelKey] = label;
|
|
17166
|
+
}
|
|
17167
|
+
const nodeKeys = [
|
|
17168
|
+
copyId,
|
|
17169
|
+
labelKey,
|
|
17170
|
+
BUTTON_COLLECTIONS_KEY,
|
|
17171
|
+
BUTTON_SNAPSHOTS_KEY,
|
|
17172
|
+
BUTTON_ASSIGNMENTS_KEY
|
|
17173
|
+
];
|
|
17174
|
+
if (sourceLabelKey) nodeKeys.push(sourceLabelKey);
|
|
17175
|
+
return {
|
|
17176
|
+
copy,
|
|
17177
|
+
content: nextContent,
|
|
17178
|
+
nodes: contentNodes(nextContent, nodeKeys)
|
|
17179
|
+
};
|
|
17180
|
+
}
|
|
17181
|
+
function listCollectionMembers(collection) {
|
|
17182
|
+
return Array.from(collection.querySelectorAll(CTA_BUTTON_SELECTOR)).map((el) => buttonId(el)).filter((id) => Boolean(id));
|
|
17183
|
+
}
|
|
17184
|
+
function contentNodes(content, keys) {
|
|
17185
|
+
return keys.filter((key) => content[key] !== void 0).map((key) => ({ key, text: content[key] }));
|
|
17186
|
+
}
|
|
17187
|
+
function deleteButton(source, content) {
|
|
17188
|
+
if (!canDeleteButton(source)) return null;
|
|
17189
|
+
const id = buttonId(source);
|
|
17190
|
+
if (!id) return null;
|
|
17191
|
+
const parent = source.parentElement;
|
|
17192
|
+
const nextSibling = source.nextSibling;
|
|
17193
|
+
const removed = source;
|
|
17194
|
+
const collection = buttonCollectionOf(source);
|
|
17195
|
+
const collectionId = collection?.getAttribute(COLLECTION_ATTR) ?? "";
|
|
17196
|
+
const previousCollections = readCollections(content);
|
|
17197
|
+
const previousHidden = readHiddenButtons(content);
|
|
17198
|
+
const snapshots = { ...readSnapshots(content) };
|
|
17199
|
+
const assignments = { ...readAssignments(content) };
|
|
17200
|
+
delete assignments[id];
|
|
17201
|
+
const remainingBeforeUnwrap = collection ? listCollectionMembers(collection).filter((member) => member !== id) : [];
|
|
17202
|
+
removed.remove();
|
|
17203
|
+
let nextCollections = { ...previousCollections };
|
|
17204
|
+
let unwrapped = null;
|
|
17205
|
+
if (collection && collectionId) {
|
|
17206
|
+
const members = listCollectionMembers(collection);
|
|
17207
|
+
if (members.length <= 1) {
|
|
17208
|
+
unwrapped = collection;
|
|
17209
|
+
unwrapCollection(collection);
|
|
17210
|
+
delete nextCollections[collectionId];
|
|
17211
|
+
} else {
|
|
17212
|
+
nextCollections[collectionId] = {
|
|
17213
|
+
id: collectionId,
|
|
17214
|
+
members,
|
|
17215
|
+
gap: collection.style.gap || previousCollections[collectionId]?.gap || "12px"
|
|
17216
|
+
};
|
|
17217
|
+
}
|
|
17218
|
+
}
|
|
17219
|
+
const hidden = previousHidden.includes(id) ? previousHidden : [...previousHidden, id];
|
|
17220
|
+
const nextContent = {
|
|
17221
|
+
...content,
|
|
17222
|
+
[id]: "",
|
|
17223
|
+
[BUTTON_COLLECTIONS_KEY]: JSON.stringify(nextCollections),
|
|
17224
|
+
[BUTTON_HIDDEN_KEY]: JSON.stringify(hidden),
|
|
17225
|
+
[BUTTON_SNAPSHOTS_KEY]: JSON.stringify(snapshots),
|
|
17226
|
+
[BUTTON_ASSIGNMENTS_KEY]: JSON.stringify(assignments)
|
|
17227
|
+
};
|
|
17228
|
+
return {
|
|
17229
|
+
content: nextContent,
|
|
17230
|
+
nodes: contentNodes(nextContent, [id, BUTTON_COLLECTIONS_KEY, BUTTON_HIDDEN_KEY, BUTTON_SNAPSHOTS_KEY, BUTTON_ASSIGNMENTS_KEY]),
|
|
17231
|
+
undo: () => {
|
|
17232
|
+
if (unwrapped && remainingBeforeUnwrap.length === 1) {
|
|
17233
|
+
const remaining = findButton(removed.ownerDocument, remainingBeforeUnwrap[0]);
|
|
17234
|
+
const host = remaining?.parentElement;
|
|
17235
|
+
if (remaining && host) {
|
|
17236
|
+
const restoredCollection = createCollection(
|
|
17237
|
+
removed.ownerDocument,
|
|
17238
|
+
collectionId,
|
|
17239
|
+
previousCollections[collectionId]?.gap || "12px"
|
|
17240
|
+
);
|
|
17241
|
+
host.insertBefore(restoredCollection, remaining);
|
|
17242
|
+
restoredCollection.append(remaining, removed);
|
|
17243
|
+
return;
|
|
17244
|
+
}
|
|
17245
|
+
}
|
|
17246
|
+
if (nextSibling && nextSibling.parentNode === parent) parent?.insertBefore(removed, nextSibling);
|
|
17247
|
+
else parent?.appendChild(removed);
|
|
17248
|
+
}
|
|
17249
|
+
};
|
|
17250
|
+
}
|
|
17251
|
+
function unwrapCollection(collection) {
|
|
17252
|
+
const parent = collection.parentElement;
|
|
17253
|
+
if (!parent) return;
|
|
17254
|
+
while (collection.firstChild) parent.insertBefore(collection.firstChild, collection);
|
|
17255
|
+
collection.remove();
|
|
17256
|
+
}
|
|
17257
|
+
function reorderButtonInCollection(button, clientX) {
|
|
17258
|
+
const collection = buttonCollectionOf(button);
|
|
17259
|
+
const id = buttonId(button);
|
|
17260
|
+
if (!collection || !id) return null;
|
|
17261
|
+
const siblings = Array.from(collection.querySelectorAll(CTA_BUTTON_SELECTOR)).filter((el) => el !== button);
|
|
17262
|
+
let placed = false;
|
|
17263
|
+
for (const sibling of siblings) {
|
|
17264
|
+
const rect = sibling.getBoundingClientRect();
|
|
17265
|
+
if (clientX < rect.left + rect.width / 2) {
|
|
17266
|
+
sibling.before(button);
|
|
17267
|
+
placed = true;
|
|
17268
|
+
break;
|
|
17269
|
+
}
|
|
17270
|
+
}
|
|
17271
|
+
if (!placed) collection.append(button);
|
|
17272
|
+
return listCollectionMembers(collection);
|
|
17273
|
+
}
|
|
17274
|
+
function listVisibleCollectionButtons(collection) {
|
|
17275
|
+
return Array.from(collection.querySelectorAll(CTA_BUTTON_SELECTOR)).filter((el) => {
|
|
17276
|
+
if (!buttonId(el)) return false;
|
|
17277
|
+
return el.getClientRects().length > 0;
|
|
17278
|
+
});
|
|
17279
|
+
}
|
|
17280
|
+
function isVerticalButtonLayout(items, collection) {
|
|
17281
|
+
if (items.length >= 2) {
|
|
17282
|
+
const a = items[0].getBoundingClientRect();
|
|
17283
|
+
const b = items[1].getBoundingClientRect();
|
|
17284
|
+
return b.top - a.bottom > b.left - a.right;
|
|
17285
|
+
}
|
|
17286
|
+
const style = window.getComputedStyle(collection);
|
|
17287
|
+
return style.flexDirection === "column" || style.flexDirection === "column-reverse";
|
|
17288
|
+
}
|
|
17289
|
+
function buildButtonCollectionDropSlots(collection) {
|
|
17290
|
+
const items = listVisibleCollectionButtons(collection);
|
|
17291
|
+
const barThickness = 3;
|
|
17292
|
+
const slots = [];
|
|
17293
|
+
if (items.length === 0) {
|
|
17294
|
+
const rect = collection.getBoundingClientRect();
|
|
17295
|
+
slots.push({
|
|
17296
|
+
insertIndex: 0,
|
|
17297
|
+
left: rect.left + rect.width / 2 - barThickness / 2,
|
|
17298
|
+
top: rect.top,
|
|
17299
|
+
width: barThickness,
|
|
17300
|
+
height: Math.max(rect.height, 24),
|
|
17301
|
+
direction: "vertical"
|
|
17302
|
+
});
|
|
17303
|
+
return slots;
|
|
17304
|
+
}
|
|
17305
|
+
if (isVerticalButtonLayout(items, collection)) {
|
|
17306
|
+
const edgeGap2 = items.length >= 2 ? Math.max(0, items[1].getBoundingClientRect().top - items[0].getBoundingClientRect().bottom) : 16;
|
|
17307
|
+
for (let i = 0; i <= items.length; i++) {
|
|
17308
|
+
let top;
|
|
17309
|
+
let left;
|
|
17310
|
+
let width;
|
|
17311
|
+
if (i === 0) {
|
|
17312
|
+
const first = items[0].getBoundingClientRect();
|
|
17313
|
+
top = first.top - edgeGap2 / 2 - barThickness / 2;
|
|
17314
|
+
left = first.left;
|
|
17315
|
+
width = first.width;
|
|
17316
|
+
} else if (i === items.length) {
|
|
17317
|
+
const last = items[items.length - 1].getBoundingClientRect();
|
|
17318
|
+
const lastGap = items.length >= 2 ? Math.max(0, last.top - items[items.length - 2].getBoundingClientRect().bottom) : edgeGap2;
|
|
17319
|
+
top = last.bottom + lastGap / 2 - barThickness / 2;
|
|
17320
|
+
left = last.left;
|
|
17321
|
+
width = last.width;
|
|
17322
|
+
} else {
|
|
17323
|
+
const prev = items[i - 1].getBoundingClientRect();
|
|
17324
|
+
const next = items[i].getBoundingClientRect();
|
|
17325
|
+
top = (prev.bottom + next.top) / 2 - barThickness / 2;
|
|
17326
|
+
left = Math.min(prev.left, next.left);
|
|
17327
|
+
width = Math.max(prev.right, next.right) - left;
|
|
17328
|
+
}
|
|
17329
|
+
slots.push({
|
|
17330
|
+
insertIndex: i,
|
|
17331
|
+
left,
|
|
17332
|
+
top,
|
|
17333
|
+
width: Math.max(width, 40),
|
|
17334
|
+
height: barThickness,
|
|
17335
|
+
direction: "horizontal"
|
|
17336
|
+
});
|
|
17337
|
+
}
|
|
17338
|
+
return slots;
|
|
17339
|
+
}
|
|
17340
|
+
const edgeGap = items.length >= 2 ? Math.max(0, items[1].getBoundingClientRect().left - items[0].getBoundingClientRect().right) : 12;
|
|
17341
|
+
for (let i = 0; i <= items.length; i++) {
|
|
17342
|
+
let left;
|
|
17343
|
+
let top;
|
|
17344
|
+
let height;
|
|
17345
|
+
if (i === 0) {
|
|
17346
|
+
const first = items[0].getBoundingClientRect();
|
|
17347
|
+
left = first.left - edgeGap / 2 - barThickness / 2;
|
|
17348
|
+
top = first.top;
|
|
17349
|
+
height = first.height;
|
|
17350
|
+
} else if (i === items.length) {
|
|
17351
|
+
const last = items[items.length - 1].getBoundingClientRect();
|
|
17352
|
+
const lastGap = items.length >= 2 ? Math.max(0, last.left - items[items.length - 2].getBoundingClientRect().right) : edgeGap;
|
|
17353
|
+
left = last.right + lastGap / 2 - barThickness / 2;
|
|
17354
|
+
top = last.top;
|
|
17355
|
+
height = last.height;
|
|
17356
|
+
} else {
|
|
17357
|
+
const prev = items[i - 1].getBoundingClientRect();
|
|
17358
|
+
const next = items[i].getBoundingClientRect();
|
|
17359
|
+
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
17360
|
+
top = Math.min(prev.top, next.top);
|
|
17361
|
+
height = Math.max(prev.bottom, next.bottom) - top;
|
|
17362
|
+
}
|
|
17363
|
+
slots.push({
|
|
17364
|
+
insertIndex: i,
|
|
17365
|
+
left,
|
|
17366
|
+
top,
|
|
17367
|
+
width: barThickness,
|
|
17368
|
+
height: Math.max(height, 24),
|
|
17369
|
+
direction: "vertical"
|
|
17370
|
+
});
|
|
17371
|
+
}
|
|
17372
|
+
return slots;
|
|
17373
|
+
}
|
|
17374
|
+
function hitTestButtonCollectionDropSlot(collection, clientX, clientY) {
|
|
17375
|
+
const slots = buildButtonCollectionDropSlots(collection);
|
|
17376
|
+
let best = null;
|
|
17377
|
+
for (const slot of slots) {
|
|
17378
|
+
const cx2 = slot.left + slot.width / 2;
|
|
17379
|
+
const cy = slot.top + slot.height / 2;
|
|
17380
|
+
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;
|
|
17381
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
17382
|
+
}
|
|
17383
|
+
return best?.slot ?? null;
|
|
17384
|
+
}
|
|
17385
|
+
function insertButtonAtCollectionIndex(button, insertIndex) {
|
|
17386
|
+
const collection = buttonCollectionOf(button);
|
|
17387
|
+
if (!collection) return null;
|
|
17388
|
+
const items = listVisibleCollectionButtons(collection);
|
|
17389
|
+
const from = items.indexOf(button);
|
|
17390
|
+
if (from < 0) return null;
|
|
17391
|
+
const others = items.filter((el) => el !== button);
|
|
17392
|
+
let index = insertIndex;
|
|
17393
|
+
if (from < insertIndex) index -= 1;
|
|
17394
|
+
if (index <= 0) {
|
|
17395
|
+
const first = others[0];
|
|
17396
|
+
if (first) first.before(button);
|
|
17397
|
+
else collection.append(button);
|
|
17398
|
+
} else if (index >= others.length) {
|
|
17399
|
+
collection.append(button);
|
|
17400
|
+
} else {
|
|
17401
|
+
others[index].before(button);
|
|
17402
|
+
}
|
|
17403
|
+
return listCollectionMembers(collection);
|
|
17404
|
+
}
|
|
17405
|
+
function persistCollectionOrder(collection, content) {
|
|
17406
|
+
const id = collection.getAttribute(COLLECTION_ATTR);
|
|
17407
|
+
if (!id) return null;
|
|
17408
|
+
const collections = readCollections(content);
|
|
17409
|
+
const current = collections[id];
|
|
17410
|
+
const members = listCollectionMembers(collection);
|
|
17411
|
+
const next = {
|
|
17412
|
+
...collections,
|
|
17413
|
+
[id]: { id, members, gap: collection.style.gap || current?.gap || "12px" }
|
|
17414
|
+
};
|
|
17415
|
+
const nextContent = { ...content, [BUTTON_COLLECTIONS_KEY]: JSON.stringify(next) };
|
|
17416
|
+
return { content: nextContent, nodes: [{ key: BUTTON_COLLECTIONS_KEY, text: nextContent[BUTTON_COLLECTIONS_KEY] }] };
|
|
17417
|
+
}
|
|
17418
|
+
function hideButton(el) {
|
|
17419
|
+
if (el.getAttribute("data-ohw-button-hidden") === "") return;
|
|
17420
|
+
el.setAttribute("data-ohw-button-hidden", "");
|
|
17421
|
+
el.style.display = "none";
|
|
17422
|
+
}
|
|
17423
|
+
function syncButtonsFromContent(doc, content) {
|
|
17424
|
+
reconcileButtonCollections(doc, content);
|
|
17425
|
+
applyButtonContentFromContent(doc, content);
|
|
17426
|
+
applyButtonStylesFromContent(doc, content);
|
|
17427
|
+
}
|
|
17428
|
+
function applyButtonContentFromContent(doc, content) {
|
|
17429
|
+
const snapshots = readSnapshots(content);
|
|
17430
|
+
for (const snapshot of Object.values(snapshots)) {
|
|
17431
|
+
const el = findButton(doc, snapshot.id);
|
|
17432
|
+
if (!el) continue;
|
|
17433
|
+
applySnapshotContent(el, snapshot, content);
|
|
17434
|
+
}
|
|
17435
|
+
}
|
|
17436
|
+
function applySnapshotContent(el, snapshot, content) {
|
|
17437
|
+
const href = content[snapshot.id] ?? snapshot.href;
|
|
17438
|
+
if (href) el.setAttribute("href", href);
|
|
17439
|
+
const labelKey = snapshot.labelKey || labelKeyForHrefKey(snapshot.id);
|
|
17440
|
+
if (labelKey && !el.querySelector(`[data-ohw-key="${CSS.escape(labelKey)}"]`)) {
|
|
17441
|
+
const label2 = labelElement2(el);
|
|
17442
|
+
if (label2) label2.setAttribute("data-ohw-key", labelKey);
|
|
17443
|
+
}
|
|
17444
|
+
const text = content[labelKey];
|
|
17445
|
+
if (text === void 0) return;
|
|
17446
|
+
const label = labelElement2(el);
|
|
17447
|
+
if (label) {
|
|
17448
|
+
if (label.getAttribute("data-ohw-key") !== labelKey) label.setAttribute("data-ohw-key", labelKey);
|
|
17449
|
+
if (label.textContent !== text) label.textContent = text;
|
|
17450
|
+
}
|
|
17451
|
+
}
|
|
17452
|
+
function reconcileButtonCollections(doc, content) {
|
|
17453
|
+
const hidden = new Set(readHiddenButtons(content));
|
|
17454
|
+
for (const id of hidden) {
|
|
17455
|
+
const el = findButton(doc, id);
|
|
17456
|
+
if (el) hideButton(el);
|
|
17457
|
+
}
|
|
17458
|
+
const snapshots = readSnapshots(content);
|
|
17459
|
+
const collections = readCollections(content);
|
|
17460
|
+
for (const collectionState of Object.values(collections)) {
|
|
17461
|
+
const live = collectionState.members.map((id) => findButton(doc, id) ?? restoreSnapshot(doc, snapshots[id], content)).filter((el) => Boolean(el && !hidden.has(buttonId(el) ?? "")));
|
|
17462
|
+
if (live.length === 0) continue;
|
|
17463
|
+
if (live.length === 1) {
|
|
17464
|
+
const existing = buttonCollectionOf(live[0]);
|
|
17465
|
+
if (existing) unwrapCollection(existing);
|
|
17466
|
+
continue;
|
|
17467
|
+
}
|
|
17468
|
+
const anchor = live.find((el) => el.isConnected) ?? live[0];
|
|
17469
|
+
let collection = live.map((el) => buttonCollectionOf(el)).find((el) => el?.getAttribute(COLLECTION_ATTR) === collectionState.id) ?? null;
|
|
17470
|
+
if (!collection) {
|
|
17471
|
+
if (!anchor.parentElement) continue;
|
|
17472
|
+
collection = createCollection(doc, collectionState.id, collectionState.gap);
|
|
17473
|
+
anchor.parentElement.insertBefore(collection, anchor);
|
|
17474
|
+
}
|
|
17475
|
+
styleCollection(collection, collectionState.gap);
|
|
17476
|
+
const current = listCollectionMembers(collection);
|
|
17477
|
+
const sameOrder = current.length === live.length && current.every((id, index) => id === buttonId(live[index]));
|
|
17478
|
+
if (!sameOrder) {
|
|
17479
|
+
for (const member of live) collection.append(member);
|
|
17480
|
+
}
|
|
17481
|
+
for (const member of live) setButtonDragAttr(member);
|
|
17482
|
+
}
|
|
17483
|
+
}
|
|
17484
|
+
function restoreSnapshot(doc, snapshot, content) {
|
|
17485
|
+
if (!snapshot) return null;
|
|
17486
|
+
const existing = findButton(doc, snapshot.id);
|
|
17487
|
+
if (existing) {
|
|
17488
|
+
applySnapshotContent(existing, snapshot, content);
|
|
17489
|
+
return existing;
|
|
17490
|
+
}
|
|
17491
|
+
const el = htmlToElement(doc, snapshot.html);
|
|
17492
|
+
if (!el) return null;
|
|
17493
|
+
el.setAttribute("data-ohw-href-key", snapshot.id);
|
|
17494
|
+
const label = labelElement2(el);
|
|
17495
|
+
const labelKey = snapshot.labelKey || labelKeyForHrefKey(snapshot.id);
|
|
17496
|
+
if (label) label.setAttribute("data-ohw-key", labelKey);
|
|
17497
|
+
applySnapshotContent(el, snapshot, content);
|
|
17498
|
+
setButtonDragAttr(el);
|
|
17499
|
+
return el;
|
|
17500
|
+
}
|
|
17501
|
+
function navbarCtasInScope(el) {
|
|
17502
|
+
const scope = el.closest("nav, [data-ohw-nav-root], [data-ohw-nav-drawer]") ?? el.parentElement;
|
|
17503
|
+
if (!scope) return [];
|
|
17504
|
+
return Array.from(scope.querySelectorAll(CTA_BUTTON_SELECTOR)).filter(
|
|
17505
|
+
(button) => isNavbarCta(button) && buttonId(button)
|
|
17506
|
+
);
|
|
17507
|
+
}
|
|
17508
|
+
function ensureNavbarButtonCollection(button, content) {
|
|
17509
|
+
const existing = buttonCollectionOf(button);
|
|
17510
|
+
if (existing) return existing;
|
|
17511
|
+
if (!isNavbarCta(button) || !buttonId(button)) return null;
|
|
17512
|
+
const parent = button.parentElement;
|
|
17513
|
+
if (!parent) return null;
|
|
17514
|
+
const siblings = navbarCtasInScope(button).filter((el) => el.parentElement === parent);
|
|
17515
|
+
if (siblings.length < 2) return null;
|
|
17516
|
+
const id = nextCollectionId(content, button.ownerDocument);
|
|
17517
|
+
const collection = createCollection(button.ownerDocument, id, collectionGap(button, tokensFromButton(button)));
|
|
17518
|
+
siblings[0].before(collection);
|
|
17519
|
+
for (const member of siblings) {
|
|
17520
|
+
collection.append(member);
|
|
17521
|
+
setButtonDragAttr(member);
|
|
17522
|
+
}
|
|
17523
|
+
return collection;
|
|
17524
|
+
}
|
|
17525
|
+
function collectionDragEnabled(el) {
|
|
17526
|
+
if (!isNavbarCta(el) || !buttonId(el)) return false;
|
|
17527
|
+
if (buttonCollectionOf(el)) return true;
|
|
17528
|
+
return navbarCtasInScope(el).length >= 2;
|
|
17529
|
+
}
|
|
17530
|
+
|
|
17531
|
+
// src/lib/item-drag-interaction.ts
|
|
17532
|
+
function disableNativeHrefDrag(el) {
|
|
17533
|
+
if (el.draggable) el.draggable = false;
|
|
17534
|
+
if (el.getAttribute("draggable") !== "false") {
|
|
17535
|
+
el.setAttribute("draggable", "false");
|
|
17536
|
+
}
|
|
17537
|
+
}
|
|
17538
|
+
function clearTextSelection() {
|
|
17539
|
+
const sel = window.getSelection();
|
|
17540
|
+
if (sel && !sel.isCollapsed) sel.removeAllRanges();
|
|
17541
|
+
}
|
|
17542
|
+
function armItemPressDrag() {
|
|
17543
|
+
document.documentElement.setAttribute("data-ohw-footer-press-drag", "");
|
|
17544
|
+
}
|
|
17545
|
+
function lockItemDuringDrag() {
|
|
17546
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
17547
|
+
document.documentElement.setAttribute("data-ohw-item-dragging", "");
|
|
17548
|
+
clearTextSelection();
|
|
17549
|
+
}
|
|
17550
|
+
function unlockItemDragInteraction() {
|
|
17551
|
+
const wasDragging = document.documentElement.hasAttribute("data-ohw-item-dragging");
|
|
17552
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
17553
|
+
document.documentElement.removeAttribute("data-ohw-item-dragging");
|
|
17554
|
+
if (wasDragging) clearTextSelection();
|
|
17555
|
+
}
|
|
17556
|
+
var armFooterPressDrag = armItemPressDrag;
|
|
17557
|
+
var lockFooterDuringDrag = lockItemDuringDrag;
|
|
17558
|
+
var unlockFooterDragInteraction = unlockItemDragInteraction;
|
|
17559
|
+
|
|
17560
|
+
// src/lib/nav-dnd.ts
|
|
17561
|
+
function listReorderableNavItems(draggedEl) {
|
|
17562
|
+
return listActiveNavbarItems(draggedEl).filter((el) => {
|
|
17563
|
+
const key = el.getAttribute("data-ohw-href-key");
|
|
17564
|
+
return isNavbarHrefKey(key) && !isNestedNavChild(el);
|
|
17565
|
+
});
|
|
17566
|
+
}
|
|
17567
|
+
function resolveParentNavHrefKey(child) {
|
|
17568
|
+
const childrenRoot = child.closest("[data-ohw-nav-children]");
|
|
17569
|
+
const group = childrenRoot?.closest("[data-ohw-nav-group]");
|
|
17570
|
+
if (!group) return null;
|
|
17571
|
+
const trigger = group.querySelector(":scope > [data-ohw-href-key]") ?? Array.from(group.querySelectorAll("[data-ohw-href-key]")).find(
|
|
17572
|
+
(el) => !el.closest("[data-ohw-nav-children]")
|
|
17573
|
+
) ?? null;
|
|
17574
|
+
const key = trigger?.getAttribute("data-ohw-href-key");
|
|
17575
|
+
return key && isNavbarHrefKey(key) ? key : null;
|
|
17576
|
+
}
|
|
17577
|
+
function listNavChildren(parentHrefKey, draggedEl) {
|
|
17578
|
+
const items = listActiveNavbarItems(draggedEl);
|
|
17579
|
+
const parent = items.find((el) => el.getAttribute("data-ohw-href-key") === parentHrefKey);
|
|
17580
|
+
if (!parent) return [];
|
|
17581
|
+
const group = parent.closest("[data-ohw-nav-group]");
|
|
17582
|
+
const childrenRoot = group?.querySelector(":scope > [data-ohw-nav-children]");
|
|
17583
|
+
if (!childrenRoot) return [];
|
|
17584
|
+
return Array.from(childrenRoot.querySelectorAll(":scope > [data-ohw-href-key]")).filter(
|
|
17585
|
+
(el) => isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))
|
|
17586
|
+
);
|
|
17587
|
+
}
|
|
17588
|
+
function isVerticalNavLayout(items, draggedEl) {
|
|
17589
|
+
const visible = items.filter((el) => el.getClientRects().length > 0);
|
|
17590
|
+
if (visible.length >= 2) {
|
|
17591
|
+
const a = visible[0].getBoundingClientRect();
|
|
17592
|
+
const b = visible[1].getBoundingClientRect();
|
|
17593
|
+
const verticalGap = b.top - a.bottom;
|
|
17594
|
+
const horizontalGap = b.left - a.right;
|
|
17595
|
+
return verticalGap > horizontalGap;
|
|
17596
|
+
}
|
|
17597
|
+
const container = getActiveNavbarListContainer(draggedEl);
|
|
17598
|
+
if (!container) return false;
|
|
17599
|
+
const style = window.getComputedStyle(container);
|
|
17600
|
+
return style.flexDirection === "column" || style.flexDirection === "column-reverse";
|
|
17601
|
+
}
|
|
17602
|
+
function buildVerticalRootNavDropSlots(items, draggedEl) {
|
|
17603
|
+
const slots = [];
|
|
17604
|
+
const barThickness = 3;
|
|
17605
|
+
if (items.length === 0) {
|
|
17606
|
+
const container = getActiveNavbarListContainer(draggedEl);
|
|
17607
|
+
if (!container) return slots;
|
|
17608
|
+
const rect = container.getBoundingClientRect();
|
|
17609
|
+
slots.push({
|
|
17610
|
+
insertIndex: 0,
|
|
17611
|
+
parentId: null,
|
|
17612
|
+
left: rect.left,
|
|
17613
|
+
top: rect.top + rect.height / 2 - barThickness / 2,
|
|
17614
|
+
width: Math.max(rect.width, 40),
|
|
17615
|
+
height: barThickness,
|
|
17616
|
+
direction: "horizontal"
|
|
17617
|
+
});
|
|
17618
|
+
return slots;
|
|
17619
|
+
}
|
|
17620
|
+
const edgeGap = (() => {
|
|
17621
|
+
if (items.length < 2) return 16;
|
|
17622
|
+
const a = items[0].getBoundingClientRect();
|
|
17623
|
+
const b = items[1].getBoundingClientRect();
|
|
17624
|
+
return Math.max(0, b.top - a.bottom);
|
|
17625
|
+
})();
|
|
17626
|
+
for (let i = 0; i <= items.length; i++) {
|
|
17627
|
+
let top;
|
|
17628
|
+
let width;
|
|
17629
|
+
let left;
|
|
17630
|
+
if (i === 0) {
|
|
17631
|
+
const first = items[0].getBoundingClientRect();
|
|
17632
|
+
top = first.top - edgeGap / 2 - barThickness / 2;
|
|
17633
|
+
left = first.left;
|
|
17634
|
+
width = first.width;
|
|
17635
|
+
} else if (i === items.length) {
|
|
17636
|
+
const last = items[items.length - 1].getBoundingClientRect();
|
|
17637
|
+
const lastGap = items.length >= 2 ? Math.max(0, last.top - items[items.length - 2].getBoundingClientRect().bottom) : edgeGap;
|
|
17638
|
+
top = last.bottom + lastGap / 2 - barThickness / 2;
|
|
17639
|
+
left = last.left;
|
|
17640
|
+
width = last.width;
|
|
17641
|
+
} else {
|
|
17642
|
+
const prev = items[i - 1].getBoundingClientRect();
|
|
17643
|
+
const next = items[i].getBoundingClientRect();
|
|
17644
|
+
top = (prev.bottom + next.top) / 2 - barThickness / 2;
|
|
17645
|
+
left = Math.min(prev.left, next.left);
|
|
17646
|
+
width = Math.max(prev.right, next.right) - left;
|
|
17647
|
+
}
|
|
17648
|
+
slots.push({
|
|
17649
|
+
insertIndex: i,
|
|
17650
|
+
parentId: null,
|
|
17651
|
+
left,
|
|
17652
|
+
top,
|
|
17653
|
+
width: Math.max(width, 40),
|
|
17654
|
+
height: barThickness,
|
|
17655
|
+
direction: "horizontal"
|
|
17656
|
+
});
|
|
17657
|
+
}
|
|
17658
|
+
return slots;
|
|
17659
|
+
}
|
|
17660
|
+
function buildHorizontalRootNavDropSlots(items, draggedEl) {
|
|
17661
|
+
const slots = [];
|
|
17662
|
+
const barThickness = 3;
|
|
17663
|
+
if (items.length === 0) {
|
|
17664
|
+
const container = getActiveNavbarListContainer(draggedEl);
|
|
17665
|
+
if (!container) return slots;
|
|
17666
|
+
const rect = container.getBoundingClientRect();
|
|
17667
|
+
slots.push({
|
|
17668
|
+
insertIndex: 0,
|
|
17669
|
+
parentId: null,
|
|
17670
|
+
left: rect.left + rect.width / 2 - barThickness / 2,
|
|
17671
|
+
top: rect.top,
|
|
17672
|
+
width: barThickness,
|
|
17673
|
+
height: Math.max(rect.height, 24),
|
|
17674
|
+
direction: "vertical"
|
|
17675
|
+
});
|
|
17676
|
+
return slots;
|
|
17677
|
+
}
|
|
17678
|
+
const edgeGap = (() => {
|
|
17679
|
+
if (items.length < 2) return 32;
|
|
17680
|
+
const a = items[0].getBoundingClientRect();
|
|
17681
|
+
const b = items[1].getBoundingClientRect();
|
|
17682
|
+
return Math.max(0, b.left - a.right);
|
|
17683
|
+
})();
|
|
17684
|
+
for (let i = 0; i <= items.length; i++) {
|
|
17685
|
+
let left;
|
|
17686
|
+
let top;
|
|
17687
|
+
let height;
|
|
17688
|
+
if (i === 0) {
|
|
17689
|
+
const first = items[0].getBoundingClientRect();
|
|
17690
|
+
left = first.left - edgeGap / 2 - barThickness / 2;
|
|
17691
|
+
top = first.top;
|
|
17692
|
+
height = first.height;
|
|
17693
|
+
} else if (i === items.length) {
|
|
17694
|
+
const last = items[items.length - 1].getBoundingClientRect();
|
|
17695
|
+
const lastGap = items.length >= 2 ? Math.max(0, last.left - items[items.length - 2].getBoundingClientRect().right) : edgeGap;
|
|
17696
|
+
left = last.right + lastGap / 2 - barThickness / 2;
|
|
17697
|
+
top = last.top;
|
|
17698
|
+
height = last.height;
|
|
17699
|
+
} else {
|
|
17700
|
+
const prev = items[i - 1].getBoundingClientRect();
|
|
17701
|
+
const next = items[i].getBoundingClientRect();
|
|
17702
|
+
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
17703
|
+
top = Math.min(prev.top, next.top);
|
|
17704
|
+
height = Math.max(prev.bottom, next.bottom) - top;
|
|
17705
|
+
}
|
|
17706
|
+
slots.push({
|
|
17707
|
+
insertIndex: i,
|
|
17708
|
+
parentId: null,
|
|
17709
|
+
left,
|
|
17710
|
+
top,
|
|
17711
|
+
width: barThickness,
|
|
17712
|
+
height: Math.max(height, 24),
|
|
17713
|
+
direction: "vertical"
|
|
17714
|
+
});
|
|
17715
|
+
}
|
|
17716
|
+
return slots;
|
|
17717
|
+
}
|
|
17718
|
+
function buildRootNavDropSlots(draggedEl) {
|
|
17719
|
+
const items = listReorderableNavItems(draggedEl);
|
|
17720
|
+
if (isVerticalNavLayout(items, draggedEl)) {
|
|
17721
|
+
return buildVerticalRootNavDropSlots(items, draggedEl);
|
|
17722
|
+
}
|
|
17723
|
+
return buildHorizontalRootNavDropSlots(items, draggedEl);
|
|
16154
17724
|
}
|
|
16155
17725
|
function buildChildNavDropSlots(parentHrefKey, draggedEl) {
|
|
16156
17726
|
const children = listNavChildren(parentHrefKey, draggedEl);
|
|
@@ -16387,7 +17957,7 @@ function useNavItemDrag({
|
|
|
16387
17957
|
document.querySelectorAll(
|
|
16388
17958
|
"nav [data-ohw-href-key], [data-ohw-nav-container] [data-ohw-href-key], [data-ohw-nav-drawer] [data-ohw-href-key]"
|
|
16389
17959
|
).forEach((el) => {
|
|
16390
|
-
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
17960
|
+
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key")) || isCtaButton(el)) {
|
|
16391
17961
|
disableNativeHrefDrag(el);
|
|
16392
17962
|
}
|
|
16393
17963
|
});
|
|
@@ -16696,12 +18266,6 @@ var SECTION_DRAG_EXCLUDED_SELECTOR = [
|
|
|
16696
18266
|
"[data-ohw-media-overlay]",
|
|
16697
18267
|
"[data-ohw-media-skeleton]"
|
|
16698
18268
|
].join(", ");
|
|
16699
|
-
function visibleClip(ps) {
|
|
16700
|
-
if (!ps) return null;
|
|
16701
|
-
const top = Math.max(0, ps.headerH - ps.iframeOffsetTop);
|
|
16702
|
-
const bottom = Math.min(window.innerHeight, ps.headerH + ps.canvasH - ps.iframeOffsetTop);
|
|
16703
|
-
return { top, bottom: Math.max(top, bottom) };
|
|
16704
|
-
}
|
|
16705
18269
|
function useSectionDrag({
|
|
16706
18270
|
isEditMode,
|
|
16707
18271
|
editContentRef,
|
|
@@ -16738,7 +18302,7 @@ function useSectionDrag({
|
|
|
16738
18302
|
}, [postToParentRef, stopAutoScroll]);
|
|
16739
18303
|
const updateAutoScroll = useCallback9(
|
|
16740
18304
|
(clientY) => {
|
|
16741
|
-
const clip =
|
|
18305
|
+
const clip = getIframeChromeClip(parentScrollRef.current);
|
|
16742
18306
|
let delta = 0;
|
|
16743
18307
|
if (clip) {
|
|
16744
18308
|
const distTop = clientY - clip.top;
|
|
@@ -16945,7 +18509,7 @@ function useSectionDrag({
|
|
|
16945
18509
|
|
|
16946
18510
|
// src/ui/footer-container-chrome.tsx
|
|
16947
18511
|
import { Plus as Plus2 } from "lucide-react";
|
|
16948
|
-
import { jsx as
|
|
18512
|
+
import { jsx as jsx32, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
16949
18513
|
function FooterContainerChrome({
|
|
16950
18514
|
rect,
|
|
16951
18515
|
onAdd,
|
|
@@ -16953,7 +18517,7 @@ function FooterContainerChrome({
|
|
|
16953
18517
|
}) {
|
|
16954
18518
|
const chromeGap = 6;
|
|
16955
18519
|
const buttonMargin = 7;
|
|
16956
|
-
return /* @__PURE__ */
|
|
18520
|
+
return /* @__PURE__ */ jsx32(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsx32(
|
|
16957
18521
|
"div",
|
|
16958
18522
|
{
|
|
16959
18523
|
"data-ohw-footer-container-chrome": "",
|
|
@@ -16965,8 +18529,8 @@ function FooterContainerChrome({
|
|
|
16965
18529
|
width: rect.width + chromeGap * 2,
|
|
16966
18530
|
height: rect.height + chromeGap * 2
|
|
16967
18531
|
},
|
|
16968
|
-
children: /* @__PURE__ */
|
|
16969
|
-
/* @__PURE__ */
|
|
18532
|
+
children: /* @__PURE__ */ jsxs22(Tooltip, { children: [
|
|
18533
|
+
/* @__PURE__ */ jsx32(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx32(
|
|
16970
18534
|
"button",
|
|
16971
18535
|
{
|
|
16972
18536
|
type: "button",
|
|
@@ -16985,10 +18549,10 @@ function FooterContainerChrome({
|
|
|
16985
18549
|
if (addDisabled) return;
|
|
16986
18550
|
onAdd();
|
|
16987
18551
|
},
|
|
16988
|
-
children: /* @__PURE__ */
|
|
18552
|
+
children: /* @__PURE__ */ jsx32(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
16989
18553
|
}
|
|
16990
18554
|
) }),
|
|
16991
|
-
/* @__PURE__ */
|
|
18555
|
+
/* @__PURE__ */ jsx32(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
|
|
16992
18556
|
] })
|
|
16993
18557
|
}
|
|
16994
18558
|
) });
|
|
@@ -17150,7 +18714,14 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
17150
18714
|
// so collecting the DOM alone left them behind: the draft knew the row was showing icons and
|
|
17151
18715
|
// had gained an item, and the published page went back to the template's own (OHH-736).
|
|
17152
18716
|
SOCIALS_ORDER_KEY,
|
|
17153
|
-
SOCIALS_DISPLAY_KEY
|
|
18717
|
+
SOCIALS_DISPLAY_KEY,
|
|
18718
|
+
// Button variant/size tokens and per-CTA assignments — JSON in editContent, applied on hydrate.
|
|
18719
|
+
BUTTON_VARIANTS_KEY,
|
|
18720
|
+
BUTTON_SIZES_KEY,
|
|
18721
|
+
BUTTON_ASSIGNMENTS_KEY,
|
|
18722
|
+
BUTTON_COLLECTIONS_KEY,
|
|
18723
|
+
BUTTON_SNAPSHOTS_KEY,
|
|
18724
|
+
BUTTON_HIDDEN_KEY
|
|
17154
18725
|
]) {
|
|
17155
18726
|
const text = extraContent[key];
|
|
17156
18727
|
if (typeof text === "string" && text.length > 0) {
|
|
@@ -17471,13 +19042,13 @@ function deleteSelectedNavFooterItem(deps) {
|
|
|
17471
19042
|
|
|
17472
19043
|
// src/ui/navbar-container-chrome.tsx
|
|
17473
19044
|
import { Plus as Plus3 } from "lucide-react";
|
|
17474
|
-
import { jsx as
|
|
19045
|
+
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
17475
19046
|
function NavbarContainerChrome({
|
|
17476
19047
|
rect,
|
|
17477
19048
|
onAdd
|
|
17478
19049
|
}) {
|
|
17479
19050
|
const chromeGap = 6;
|
|
17480
|
-
return /* @__PURE__ */
|
|
19051
|
+
return /* @__PURE__ */ jsx33(
|
|
17481
19052
|
"div",
|
|
17482
19053
|
{
|
|
17483
19054
|
"data-ohw-navbar-container-chrome": "",
|
|
@@ -17489,7 +19060,7 @@ function NavbarContainerChrome({
|
|
|
17489
19060
|
width: rect.width + chromeGap * 2,
|
|
17490
19061
|
height: rect.height + chromeGap * 2
|
|
17491
19062
|
},
|
|
17492
|
-
children: /* @__PURE__ */
|
|
19063
|
+
children: /* @__PURE__ */ jsx33(
|
|
17493
19064
|
"button",
|
|
17494
19065
|
{
|
|
17495
19066
|
type: "button",
|
|
@@ -17506,7 +19077,7 @@ function NavbarContainerChrome({
|
|
|
17506
19077
|
e.stopPropagation();
|
|
17507
19078
|
onAdd();
|
|
17508
19079
|
},
|
|
17509
|
-
children: /* @__PURE__ */
|
|
19080
|
+
children: /* @__PURE__ */ jsx33(Plus3, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
17510
19081
|
}
|
|
17511
19082
|
)
|
|
17512
19083
|
}
|
|
@@ -17515,7 +19086,7 @@ function NavbarContainerChrome({
|
|
|
17515
19086
|
|
|
17516
19087
|
// src/ui/drop-indicator.tsx
|
|
17517
19088
|
import * as React11 from "react";
|
|
17518
|
-
import { jsx as
|
|
19089
|
+
import { jsx as jsx34 } from "react/jsx-runtime";
|
|
17519
19090
|
var dropIndicatorVariants = cva(
|
|
17520
19091
|
"ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
|
|
17521
19092
|
{
|
|
@@ -17539,7 +19110,7 @@ var dropIndicatorVariants = cva(
|
|
|
17539
19110
|
);
|
|
17540
19111
|
var DropIndicator = React11.forwardRef(
|
|
17541
19112
|
({ className, direction, state, ...props }, ref) => {
|
|
17542
|
-
return /* @__PURE__ */
|
|
19113
|
+
return /* @__PURE__ */ jsx34(
|
|
17543
19114
|
"div",
|
|
17544
19115
|
{
|
|
17545
19116
|
ref,
|
|
@@ -17556,7 +19127,7 @@ var DropIndicator = React11.forwardRef(
|
|
|
17556
19127
|
DropIndicator.displayName = "DropIndicator";
|
|
17557
19128
|
|
|
17558
19129
|
// src/ui/badge.tsx
|
|
17559
|
-
import { jsx as
|
|
19130
|
+
import { jsx as jsx35 } from "react/jsx-runtime";
|
|
17560
19131
|
var badgeVariants = cva(
|
|
17561
19132
|
"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",
|
|
17562
19133
|
{
|
|
@@ -17574,12 +19145,12 @@ var badgeVariants = cva(
|
|
|
17574
19145
|
}
|
|
17575
19146
|
);
|
|
17576
19147
|
function Badge({ className, variant, ...props }) {
|
|
17577
|
-
return /* @__PURE__ */
|
|
19148
|
+
return /* @__PURE__ */ jsx35("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
17578
19149
|
}
|
|
17579
19150
|
|
|
17580
19151
|
// src/OhhwellsBridge.tsx
|
|
17581
|
-
import { Link as Link2, Plus as Plus4, Settings } from "lucide-react";
|
|
17582
|
-
import { Fragment as Fragment10, jsx as
|
|
19152
|
+
import { Brush as Brush2, Link as Link2, Plus as Plus4, Settings } from "lucide-react";
|
|
19153
|
+
import { Fragment as Fragment10, jsx as jsx36, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
17583
19154
|
var PRIMARY5 = "#0885FE";
|
|
17584
19155
|
var IMAGE_FADE_MS = 300;
|
|
17585
19156
|
var MEDIA_SETTLE_TIMEOUT_MS = 2500;
|
|
@@ -17701,7 +19272,7 @@ function duplicateSchedulingWidget(instanceId, scheduleId) {
|
|
|
17701
19272
|
schedulingRoots.set(container, root);
|
|
17702
19273
|
flushSync2(() => {
|
|
17703
19274
|
root.render(
|
|
17704
|
-
/* @__PURE__ */
|
|
19275
|
+
/* @__PURE__ */ jsx36(
|
|
17705
19276
|
SchedulingWidget,
|
|
17706
19277
|
{
|
|
17707
19278
|
notifyOnConnect: false,
|
|
@@ -17839,7 +19410,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
17839
19410
|
schedulingRoots.set(container, root);
|
|
17840
19411
|
flushSync2(() => {
|
|
17841
19412
|
root.render(
|
|
17842
|
-
/* @__PURE__ */
|
|
19413
|
+
/* @__PURE__ */ jsx36(
|
|
17843
19414
|
SchedulingWidget,
|
|
17844
19415
|
{
|
|
17845
19416
|
notifyOnConnect,
|
|
@@ -18002,8 +19573,8 @@ function lockVideoBox(video) {
|
|
|
18002
19573
|
}
|
|
18003
19574
|
const fit = video.style.objectFit || getComputedStyle(video).objectFit;
|
|
18004
19575
|
const bg = getComputedStyle(video).backgroundColor;
|
|
18005
|
-
const
|
|
18006
|
-
if (fit === "contain" &&
|
|
19576
|
+
const isTransparent2 = bg === "rgba(0, 0, 0, 0)" || bg === "transparent" || !bg;
|
|
19577
|
+
if (fit === "contain" && isTransparent2) {
|
|
18007
19578
|
video.style.backgroundColor = "var(--color-dark, #000)";
|
|
18008
19579
|
}
|
|
18009
19580
|
}
|
|
@@ -18153,7 +19724,10 @@ function listNavigationItems() {
|
|
|
18153
19724
|
).filter((el) => isNavigationItem2(el));
|
|
18154
19725
|
}
|
|
18155
19726
|
function getNavigationItemReorderState(anchor) {
|
|
18156
|
-
if (isCtaButton(anchor))
|
|
19727
|
+
if (isCtaButton(anchor)) {
|
|
19728
|
+
if (!collectionDragEnabled(anchor)) return { key: null, disabled: true };
|
|
19729
|
+
return { key: buttonId(anchor), disabled: false };
|
|
19730
|
+
}
|
|
18157
19731
|
return getReorderHandleStateFromAnchor(anchor);
|
|
18158
19732
|
}
|
|
18159
19733
|
function getReorderHandleState(el) {
|
|
@@ -18252,6 +19826,12 @@ function isPointOverNavigation(x, y) {
|
|
|
18252
19826
|
const r2 = panel.getBoundingClientRect();
|
|
18253
19827
|
if (x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom) return true;
|
|
18254
19828
|
}
|
|
19829
|
+
for (const el of document.querySelectorAll('[data-ohw-role="navbar-button"]')) {
|
|
19830
|
+
const r2 = el.getBoundingClientRect();
|
|
19831
|
+
if (r2.width > 0 && r2.height > 0 && x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom) {
|
|
19832
|
+
return true;
|
|
19833
|
+
}
|
|
19834
|
+
}
|
|
18255
19835
|
return false;
|
|
18256
19836
|
}
|
|
18257
19837
|
function findHoveredNavOrFooterContainer(x, y) {
|
|
@@ -18585,7 +20165,7 @@ function EditGlowChrome({
|
|
|
18585
20165
|
hideHandle = false
|
|
18586
20166
|
}) {
|
|
18587
20167
|
const GAP = SELECTION_CHROME_GAP2;
|
|
18588
|
-
return /* @__PURE__ */
|
|
20168
|
+
return /* @__PURE__ */ jsxs23(
|
|
18589
20169
|
"div",
|
|
18590
20170
|
{
|
|
18591
20171
|
ref: elRef,
|
|
@@ -18600,7 +20180,7 @@ function EditGlowChrome({
|
|
|
18600
20180
|
zIndex: 2147483646
|
|
18601
20181
|
},
|
|
18602
20182
|
children: [
|
|
18603
|
-
/* @__PURE__ */
|
|
20183
|
+
/* @__PURE__ */ jsx36(
|
|
18604
20184
|
"div",
|
|
18605
20185
|
{
|
|
18606
20186
|
style: {
|
|
@@ -18614,7 +20194,7 @@ function EditGlowChrome({
|
|
|
18614
20194
|
}
|
|
18615
20195
|
}
|
|
18616
20196
|
),
|
|
18617
|
-
reorderHrefKey && !hideHandle && /* @__PURE__ */
|
|
20197
|
+
reorderHrefKey && !hideHandle && /* @__PURE__ */ jsx36(
|
|
18618
20198
|
"div",
|
|
18619
20199
|
{
|
|
18620
20200
|
"data-ohw-drag-handle-container": "",
|
|
@@ -18626,7 +20206,7 @@ function EditGlowChrome({
|
|
|
18626
20206
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
18627
20207
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
18628
20208
|
},
|
|
18629
|
-
children: /* @__PURE__ */
|
|
20209
|
+
children: /* @__PURE__ */ jsx36(
|
|
18630
20210
|
DragHandle,
|
|
18631
20211
|
{
|
|
18632
20212
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -18640,22 +20220,12 @@ function EditGlowChrome({
|
|
|
18640
20220
|
}
|
|
18641
20221
|
);
|
|
18642
20222
|
}
|
|
18643
|
-
function getIframeVisibleClip(parentScroll) {
|
|
18644
|
-
if (!parentScroll) return null;
|
|
18645
|
-
const { iframeOffsetTop, headerH: visibleCanvasTop, canvasH } = parentScroll;
|
|
18646
|
-
const clipTop = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
18647
|
-
const clipBottom = Math.min(
|
|
18648
|
-
window.innerHeight,
|
|
18649
|
-
visibleCanvasTop + canvasH - iframeOffsetTop
|
|
18650
|
-
);
|
|
18651
|
-
return { top: clipTop, bottom: Math.max(clipTop, clipBottom) };
|
|
18652
|
-
}
|
|
18653
20223
|
function isRectOutsideClip(rect, clip) {
|
|
18654
20224
|
if (!clip) return false;
|
|
18655
20225
|
return rect.bottom < clip.top || rect.top > clip.bottom;
|
|
18656
20226
|
}
|
|
18657
20227
|
function applyVisibleViewport(el, parentScroll) {
|
|
18658
|
-
const clip =
|
|
20228
|
+
const clip = getIframeChromeClip(parentScroll);
|
|
18659
20229
|
const top = clip?.top ?? 0;
|
|
18660
20230
|
const height = clip ? clip.bottom - clip.top : window.innerHeight;
|
|
18661
20231
|
el.style.top = `${top}px`;
|
|
@@ -18695,7 +20265,7 @@ function clampToolbarLeft(centerX, toolbarWidth) {
|
|
|
18695
20265
|
function calcToolbarPos(rect, parentScroll, toolbarW = 306) {
|
|
18696
20266
|
const GAP = TOOLBAR_OFFSET_FROM_ELEMENT;
|
|
18697
20267
|
const APPROX_H = 32;
|
|
18698
|
-
const clip =
|
|
20268
|
+
const clip = getIframeChromeClip(parentScroll);
|
|
18699
20269
|
const clipTop = clip?.top ?? 0;
|
|
18700
20270
|
const canvasTopInIframe = parentScroll != null ? parentScroll.headerH - parentScroll.iframeOffsetTop : 0;
|
|
18701
20271
|
const visibleTop = rect.top - canvasTopInIframe;
|
|
@@ -18840,7 +20410,7 @@ function FloatingToolbar({
|
|
|
18840
20410
|
return () => ro.disconnect();
|
|
18841
20411
|
}, [showEditLink, activeCommands]);
|
|
18842
20412
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
|
|
18843
|
-
return /* @__PURE__ */
|
|
20413
|
+
return /* @__PURE__ */ jsx36(
|
|
18844
20414
|
"div",
|
|
18845
20415
|
{
|
|
18846
20416
|
ref: setRefs,
|
|
@@ -18852,12 +20422,12 @@ function FloatingToolbar({
|
|
|
18852
20422
|
zIndex: 2147483647,
|
|
18853
20423
|
pointerEvents: "auto"
|
|
18854
20424
|
},
|
|
18855
|
-
children: /* @__PURE__ */
|
|
18856
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */
|
|
18857
|
-
gi > 0 && /* @__PURE__ */
|
|
20425
|
+
children: /* @__PURE__ */ jsxs23(CustomToolbar, { children: [
|
|
20426
|
+
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs23(React12.Fragment, { children: [
|
|
20427
|
+
gi > 0 && /* @__PURE__ */ jsx36(CustomToolbarDivider, {}),
|
|
18858
20428
|
btns.map((btn) => {
|
|
18859
20429
|
const isActive = activeCommands.has(btn.cmd);
|
|
18860
|
-
return /* @__PURE__ */
|
|
20430
|
+
return /* @__PURE__ */ jsx36(
|
|
18861
20431
|
CustomToolbarButton,
|
|
18862
20432
|
{
|
|
18863
20433
|
title: btn.title,
|
|
@@ -18866,7 +20436,7 @@ function FloatingToolbar({
|
|
|
18866
20436
|
e.preventDefault();
|
|
18867
20437
|
onCommand(btn.cmd);
|
|
18868
20438
|
},
|
|
18869
|
-
children: /* @__PURE__ */
|
|
20439
|
+
children: /* @__PURE__ */ jsx36(
|
|
18870
20440
|
"svg",
|
|
18871
20441
|
{
|
|
18872
20442
|
width: "16",
|
|
@@ -18887,7 +20457,7 @@ function FloatingToolbar({
|
|
|
18887
20457
|
);
|
|
18888
20458
|
})
|
|
18889
20459
|
] }, gi)),
|
|
18890
|
-
showEditLink ? /* @__PURE__ */
|
|
20460
|
+
showEditLink ? /* @__PURE__ */ jsx36(
|
|
18891
20461
|
CustomToolbarButton,
|
|
18892
20462
|
{
|
|
18893
20463
|
type: "button",
|
|
@@ -18901,7 +20471,7 @@ function FloatingToolbar({
|
|
|
18901
20471
|
e.preventDefault();
|
|
18902
20472
|
e.stopPropagation();
|
|
18903
20473
|
},
|
|
18904
|
-
children: /* @__PURE__ */
|
|
20474
|
+
children: /* @__PURE__ */ jsx36(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
18905
20475
|
}
|
|
18906
20476
|
) : null
|
|
18907
20477
|
] })
|
|
@@ -18918,7 +20488,7 @@ function StateToggle({
|
|
|
18918
20488
|
states,
|
|
18919
20489
|
onStateChange
|
|
18920
20490
|
}) {
|
|
18921
|
-
return /* @__PURE__ */
|
|
20491
|
+
return /* @__PURE__ */ jsx36(
|
|
18922
20492
|
ToggleGroup,
|
|
18923
20493
|
{
|
|
18924
20494
|
"data-ohw-state-toggle": "",
|
|
@@ -18932,7 +20502,7 @@ function StateToggle({
|
|
|
18932
20502
|
left: rect.right - 8,
|
|
18933
20503
|
transform: "translateX(-100%)"
|
|
18934
20504
|
},
|
|
18935
|
-
children: states.map((state) => /* @__PURE__ */
|
|
20505
|
+
children: states.map((state) => /* @__PURE__ */ jsx36(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
18936
20506
|
}
|
|
18937
20507
|
);
|
|
18938
20508
|
}
|
|
@@ -18948,9 +20518,9 @@ var OHW_LOADER_STYLE = {
|
|
|
18948
20518
|
justifyContent: "center"
|
|
18949
20519
|
};
|
|
18950
20520
|
function OhwLoaderSpinner() {
|
|
18951
|
-
return /* @__PURE__ */
|
|
18952
|
-
/* @__PURE__ */
|
|
18953
|
-
/* @__PURE__ */
|
|
20521
|
+
return /* @__PURE__ */ jsxs23("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", "aria-hidden": true, children: [
|
|
20522
|
+
/* @__PURE__ */ jsx36("circle", { cx: "14", cy: "14", r: "11", stroke: "#E7E5E4", strokeWidth: "3" }),
|
|
20523
|
+
/* @__PURE__ */ jsx36(
|
|
18954
20524
|
"circle",
|
|
18955
20525
|
{
|
|
18956
20526
|
cx: "14",
|
|
@@ -18960,7 +20530,7 @@ function OhwLoaderSpinner() {
|
|
|
18960
20530
|
strokeWidth: "3",
|
|
18961
20531
|
strokeDasharray: "17 52",
|
|
18962
20532
|
strokeLinecap: "round",
|
|
18963
|
-
children: /* @__PURE__ */
|
|
20533
|
+
children: /* @__PURE__ */ jsx36(
|
|
18964
20534
|
"animateTransform",
|
|
18965
20535
|
{
|
|
18966
20536
|
attributeName: "transform",
|
|
@@ -18976,7 +20546,7 @@ function OhwLoaderSpinner() {
|
|
|
18976
20546
|
] });
|
|
18977
20547
|
}
|
|
18978
20548
|
function OhwBrandMark() {
|
|
18979
|
-
return /* @__PURE__ */
|
|
20549
|
+
return /* @__PURE__ */ jsxs23(
|
|
18980
20550
|
"svg",
|
|
18981
20551
|
{
|
|
18982
20552
|
width: "16",
|
|
@@ -18987,7 +20557,7 @@ function OhwBrandMark() {
|
|
|
18987
20557
|
style: { display: "block", flexShrink: 0 },
|
|
18988
20558
|
xmlns: "http://www.w3.org/2000/svg",
|
|
18989
20559
|
children: [
|
|
18990
|
-
/* @__PURE__ */
|
|
20560
|
+
/* @__PURE__ */ jsx36(
|
|
18991
20561
|
"mask",
|
|
18992
20562
|
{
|
|
18993
20563
|
id: "ohw-badge-mark",
|
|
@@ -18997,15 +20567,15 @@ function OhwBrandMark() {
|
|
|
18997
20567
|
y: "0",
|
|
18998
20568
|
width: "48",
|
|
18999
20569
|
height: "48",
|
|
19000
|
-
children: /* @__PURE__ */
|
|
20570
|
+
children: /* @__PURE__ */ jsx36("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" })
|
|
19001
20571
|
}
|
|
19002
20572
|
),
|
|
19003
|
-
/* @__PURE__ */
|
|
19004
|
-
/* @__PURE__ */
|
|
19005
|
-
/* @__PURE__ */
|
|
19006
|
-
/* @__PURE__ */
|
|
19007
|
-
/* @__PURE__ */
|
|
19008
|
-
/* @__PURE__ */
|
|
20573
|
+
/* @__PURE__ */ jsxs23("g", { mask: "url(#ohw-badge-mark)", children: [
|
|
20574
|
+
/* @__PURE__ */ jsx36("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" }),
|
|
20575
|
+
/* @__PURE__ */ jsx36("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" }),
|
|
20576
|
+
/* @__PURE__ */ jsx36("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" }),
|
|
20577
|
+
/* @__PURE__ */ jsx36("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" }),
|
|
20578
|
+
/* @__PURE__ */ jsx36("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" })
|
|
19009
20579
|
] })
|
|
19010
20580
|
]
|
|
19011
20581
|
}
|
|
@@ -19042,7 +20612,7 @@ var OHW_BADGE_LABEL_STYLE = {
|
|
|
19042
20612
|
whiteSpace: "nowrap"
|
|
19043
20613
|
};
|
|
19044
20614
|
function MadeWithOhhWells() {
|
|
19045
|
-
return /* @__PURE__ */
|
|
20615
|
+
return /* @__PURE__ */ jsxs23(
|
|
19046
20616
|
"a",
|
|
19047
20617
|
{
|
|
19048
20618
|
href: "https://ohhwells.com",
|
|
@@ -19052,8 +20622,8 @@ function MadeWithOhhWells() {
|
|
|
19052
20622
|
"data-ohw-badge": "",
|
|
19053
20623
|
style: OHW_BADGE_STYLE,
|
|
19054
20624
|
children: [
|
|
19055
|
-
/* @__PURE__ */
|
|
19056
|
-
/* @__PURE__ */
|
|
20625
|
+
/* @__PURE__ */ jsx36(OhwBrandMark, {}),
|
|
20626
|
+
/* @__PURE__ */ jsx36("span", { style: OHW_BADGE_LABEL_STYLE, children: "Made with OhhWells" })
|
|
19057
20627
|
]
|
|
19058
20628
|
}
|
|
19059
20629
|
);
|
|
@@ -19543,7 +21113,15 @@ function OhhwellsBridge() {
|
|
|
19543
21113
|
const [floatingPanel, setFloatingPanel] = useState16(null);
|
|
19544
21114
|
const floatingPanelOpenRef = useRef12(false);
|
|
19545
21115
|
floatingPanelOpenRef.current = floatingPanel !== null;
|
|
21116
|
+
const floatingPanelRef = useRef12(null);
|
|
21117
|
+
floatingPanelRef.current = floatingPanel;
|
|
19546
21118
|
const [floatingPanelPos, setFloatingPanelPos] = useState16(null);
|
|
21119
|
+
const buttonCollectionDragRef = useRef12(null);
|
|
21120
|
+
const buttonDropInsertIndexRef = useRef12(null);
|
|
21121
|
+
const [buttonDropSlots, setButtonDropSlots] = useState16([]);
|
|
21122
|
+
const [activeButtonDropIndex, setActiveButtonDropIndex] = useState16(null);
|
|
21123
|
+
const buttonPointerDragRef = useRef12(null);
|
|
21124
|
+
const [buttonStyleTick, setButtonStyleTick] = useState16(0);
|
|
19547
21125
|
const [logoSizeDraft, setLogoSizeDraft] = useState16(null);
|
|
19548
21126
|
const [editorViewport, setEditorViewport] = useState16("desktop");
|
|
19549
21127
|
const [parentScrollSnap, setParentScrollSnap] = useState16(null);
|
|
@@ -19844,6 +21422,7 @@ function OhhwellsBridge() {
|
|
|
19844
21422
|
hoveredItemElRef.current = null;
|
|
19845
21423
|
setHoveredItemRect(null);
|
|
19846
21424
|
setFloatingPanel(null);
|
|
21425
|
+
setFloatingPanelPos(null);
|
|
19847
21426
|
setLogoSizeDraft(null);
|
|
19848
21427
|
if (!activeElRef.current) {
|
|
19849
21428
|
if (nestedGroup?.isConnected) {
|
|
@@ -20444,6 +22023,47 @@ function OhhwellsBridge() {
|
|
|
20444
22023
|
},
|
|
20445
22024
|
[beginFooterDrag]
|
|
20446
22025
|
);
|
|
22026
|
+
const persistButtonCollectionDrag = useCallback10(
|
|
22027
|
+
(button, clientX) => {
|
|
22028
|
+
const insertIndex = buttonDropInsertIndexRef.current;
|
|
22029
|
+
if (insertIndex != null) insertButtonAtCollectionIndex(button, insertIndex);
|
|
22030
|
+
else if (typeof clientX === "number" && clientX !== 0) reorderButtonInCollection(button, clientX);
|
|
22031
|
+
buttonDropInsertIndexRef.current = null;
|
|
22032
|
+
const collection = buttonCollectionOf(button);
|
|
22033
|
+
if (collection) {
|
|
22034
|
+
const persisted = persistCollectionOrder(collection, editContentRef.current);
|
|
22035
|
+
if (persisted) {
|
|
22036
|
+
editContentRef.current = persisted.content;
|
|
22037
|
+
postToParent2({ type: "ow:change", nodes: persisted.nodes });
|
|
22038
|
+
}
|
|
22039
|
+
}
|
|
22040
|
+
buttonCollectionDragRef.current = null;
|
|
22041
|
+
buttonPointerDragRef.current = null;
|
|
22042
|
+
setButtonDropSlots([]);
|
|
22043
|
+
setActiveButtonDropIndex(null);
|
|
22044
|
+
setIsItemDragging(false);
|
|
22045
|
+
unlockFooterDragInteraction();
|
|
22046
|
+
if (button.isConnected) setToolbarRect(button.getBoundingClientRect());
|
|
22047
|
+
},
|
|
22048
|
+
[postToParent2]
|
|
22049
|
+
);
|
|
22050
|
+
const refreshButtonDragVisuals = useCallback10((button, clientX, clientY) => {
|
|
22051
|
+
const collection = buttonCollectionOf(button);
|
|
22052
|
+
if (!collection) {
|
|
22053
|
+
setButtonDropSlots([]);
|
|
22054
|
+
setActiveButtonDropIndex(null);
|
|
22055
|
+
buttonDropInsertIndexRef.current = null;
|
|
22056
|
+
return;
|
|
22057
|
+
}
|
|
22058
|
+
const slots = buildButtonCollectionDropSlots(collection);
|
|
22059
|
+
const active = hitTestButtonCollectionDropSlot(collection, clientX, clientY);
|
|
22060
|
+
setButtonDropSlots(slots);
|
|
22061
|
+
const idx = active ? slots.findIndex((slot) => slot.insertIndex === active.insertIndex) : -1;
|
|
22062
|
+
setActiveButtonDropIndex(idx >= 0 ? idx : null);
|
|
22063
|
+
buttonDropInsertIndexRef.current = active?.insertIndex ?? null;
|
|
22064
|
+
setDraggedItemRect(button.getBoundingClientRect());
|
|
22065
|
+
if (selectedElRef.current === button) setToolbarRect(button.getBoundingClientRect());
|
|
22066
|
+
}, []);
|
|
20447
22067
|
const handleItemDragStart = useCallback10(
|
|
20448
22068
|
(e) => {
|
|
20449
22069
|
const selected = selectedElRef.current;
|
|
@@ -20453,6 +22073,17 @@ function OhhwellsBridge() {
|
|
|
20453
22073
|
}
|
|
20454
22074
|
const clientX = e?.clientX ?? selected.getBoundingClientRect().left + 8;
|
|
20455
22075
|
const clientY = e?.clientY ?? selected.getBoundingClientRect().top + 8;
|
|
22076
|
+
if (isCtaButton(selected) && collectionDragEnabled(selected)) {
|
|
22077
|
+
buttonCollectionDragRef.current = selected;
|
|
22078
|
+
setMediaHover(null);
|
|
22079
|
+
if (e?.dataTransfer) {
|
|
22080
|
+
e.dataTransfer.effectAllowed = "move";
|
|
22081
|
+
e.dataTransfer.setData("text/plain", buttonId(selected) ?? "button");
|
|
22082
|
+
}
|
|
22083
|
+
setIsItemDragging(true);
|
|
22084
|
+
refreshButtonDragVisuals(selected, clientX, clientY);
|
|
22085
|
+
return;
|
|
22086
|
+
}
|
|
20456
22087
|
if (startFooterLinkDrag(selected, clientX, clientY, true)) return;
|
|
20457
22088
|
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup2(selected) && selected.closest("footer")) {
|
|
20458
22089
|
if (startFooterColumnDrag(selected, clientX, clientY, true)) return;
|
|
@@ -20462,10 +22093,15 @@ function OhhwellsBridge() {
|
|
|
20462
22093
|
setSiblingHintRect(null);
|
|
20463
22094
|
setIsItemDragging(true);
|
|
20464
22095
|
},
|
|
20465
|
-
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
|
|
22096
|
+
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag, refreshButtonDragVisuals]
|
|
20466
22097
|
);
|
|
20467
22098
|
const handleItemDragEnd = useCallback10(
|
|
20468
22099
|
(e) => {
|
|
22100
|
+
const collectionButton = buttonCollectionDragRef.current;
|
|
22101
|
+
if (collectionButton) {
|
|
22102
|
+
persistButtonCollectionDrag(collectionButton, e?.clientX);
|
|
22103
|
+
return;
|
|
22104
|
+
}
|
|
20469
22105
|
if (footerDragRef.current) {
|
|
20470
22106
|
const x = e?.clientX;
|
|
20471
22107
|
const y = e?.clientY;
|
|
@@ -20488,12 +22124,22 @@ function OhhwellsBridge() {
|
|
|
20488
22124
|
}
|
|
20489
22125
|
setIsItemDragging(false);
|
|
20490
22126
|
},
|
|
20491
|
-
[commitFooterDrag, commitNavDrag, navDragRef]
|
|
22127
|
+
[commitFooterDrag, commitNavDrag, navDragRef, persistButtonCollectionDrag]
|
|
20492
22128
|
);
|
|
20493
22129
|
const handleItemChromePointerDown = useCallback10((e) => {
|
|
20494
22130
|
if (e.button !== 0) return;
|
|
20495
22131
|
const selected = selectedElRef.current;
|
|
20496
22132
|
if (!selected) return;
|
|
22133
|
+
if (isCtaButton(selected) && collectionDragEnabled(selected)) {
|
|
22134
|
+
buttonPointerDragRef.current = {
|
|
22135
|
+
el: selected,
|
|
22136
|
+
startX: e.clientX,
|
|
22137
|
+
startY: e.clientY,
|
|
22138
|
+
pointerId: e.pointerId,
|
|
22139
|
+
started: false
|
|
22140
|
+
};
|
|
22141
|
+
return;
|
|
22142
|
+
}
|
|
20497
22143
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
20498
22144
|
if (hrefKey && isFooterHrefKey(hrefKey)) {
|
|
20499
22145
|
footerPointerDragRef.current = {
|
|
@@ -20572,10 +22218,29 @@ function OhhwellsBridge() {
|
|
|
20572
22218
|
setIsFooterFrameSelection(false);
|
|
20573
22219
|
setToolbarVariant("link-action");
|
|
20574
22220
|
setToolbarRect(anchor.getBoundingClientRect());
|
|
22221
|
+
if (glowElRef.current) glowElRef.current.style.display = "";
|
|
20575
22222
|
setToolbarShowEditLink(false);
|
|
20576
22223
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
20577
|
-
|
|
20578
|
-
|
|
22224
|
+
const panel = floatingPanelRef.current;
|
|
22225
|
+
if (panel?.kind === "button-style" && isCtaButton(anchor)) {
|
|
22226
|
+
const id = buttonId(anchor);
|
|
22227
|
+
if (id && panel.buttonId !== id) {
|
|
22228
|
+
captureButtonOrigin(anchor);
|
|
22229
|
+
setFloatingPanelPos(null);
|
|
22230
|
+
setParentScrollSnap(parentScrollRef.current);
|
|
22231
|
+
setFloatingPanel({
|
|
22232
|
+
...panel,
|
|
22233
|
+
key: `button-style:${id}`,
|
|
22234
|
+
buttonId: id,
|
|
22235
|
+
context: buttonStyleContext(anchor)
|
|
22236
|
+
});
|
|
22237
|
+
setButtonStyleTick((n) => n + 1);
|
|
22238
|
+
}
|
|
22239
|
+
} else {
|
|
22240
|
+
setFloatingPanel(null);
|
|
22241
|
+
setFloatingPanelPos(null);
|
|
22242
|
+
setLogoSizeDraft(null);
|
|
22243
|
+
}
|
|
20579
22244
|
}, [deactivate, markSelected]);
|
|
20580
22245
|
const selectFrame = useCallback10((el) => {
|
|
20581
22246
|
if (!isNavigationContainer(el)) return;
|
|
@@ -20615,6 +22280,7 @@ function OhhwellsBridge() {
|
|
|
20615
22280
|
setToolbarShowEditLink(false);
|
|
20616
22281
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
20617
22282
|
setFloatingPanel(null);
|
|
22283
|
+
setFloatingPanelPos(null);
|
|
20618
22284
|
setLogoSizeDraft(null);
|
|
20619
22285
|
}, [deactivate, markSelected, postToParent2]);
|
|
20620
22286
|
const selectLogo = useCallback10(
|
|
@@ -20660,6 +22326,7 @@ function OhhwellsBridge() {
|
|
|
20660
22326
|
});
|
|
20661
22327
|
}, []);
|
|
20662
22328
|
const openSocialsDisplayPanel = useCallback10((row) => {
|
|
22329
|
+
setFloatingPanelPos(null);
|
|
20663
22330
|
setParentScrollSnap(parentScrollRef.current);
|
|
20664
22331
|
setFloatingPanel({
|
|
20665
22332
|
key: "socials-display",
|
|
@@ -20669,6 +22336,87 @@ function OhhwellsBridge() {
|
|
|
20669
22336
|
row
|
|
20670
22337
|
});
|
|
20671
22338
|
}, []);
|
|
22339
|
+
const rememberButtonTokens = useCallback10(
|
|
22340
|
+
(content, tokens, nodes) => {
|
|
22341
|
+
if (nodes.length === 0) return content;
|
|
22342
|
+
const next = { ...content };
|
|
22343
|
+
for (const node of nodes) next[node.key] = node.text;
|
|
22344
|
+
editContentRef.current = next;
|
|
22345
|
+
postToParent2({ type: "ow:change", nodes });
|
|
22346
|
+
return next;
|
|
22347
|
+
},
|
|
22348
|
+
[postToParent2]
|
|
22349
|
+
);
|
|
22350
|
+
const tokensForButton = useCallback10(
|
|
22351
|
+
(el, persistFallback = false) => {
|
|
22352
|
+
const stored = readStoredStyleTokens(editContentRef.current);
|
|
22353
|
+
if (stored) return stored;
|
|
22354
|
+
const ensured = ensureButtonStyleTokens(document, editContentRef.current);
|
|
22355
|
+
if (ensured.tokens) {
|
|
22356
|
+
rememberButtonTokens(editContentRef.current, ensured.tokens, ensured.nodes);
|
|
22357
|
+
return ensured.tokens;
|
|
22358
|
+
}
|
|
22359
|
+
const fallback = tokensFromButton(el);
|
|
22360
|
+
if (persistFallback) rememberButtonTokens(editContentRef.current, fallback, styleTokenNodes(fallback));
|
|
22361
|
+
return fallback;
|
|
22362
|
+
},
|
|
22363
|
+
[rememberButtonTokens]
|
|
22364
|
+
);
|
|
22365
|
+
const openButtonStylePanel = useCallback10(
|
|
22366
|
+
(anchor) => {
|
|
22367
|
+
const id = buttonId(anchor);
|
|
22368
|
+
if (!id) return;
|
|
22369
|
+
captureButtonOrigin(anchor);
|
|
22370
|
+
tokensForButton(anchor);
|
|
22371
|
+
setFloatingPanelPos(null);
|
|
22372
|
+
setParentScrollSnap(parentScrollRef.current);
|
|
22373
|
+
setFloatingPanel({
|
|
22374
|
+
key: `button-style:${id}`,
|
|
22375
|
+
title: "Style",
|
|
22376
|
+
context: buttonStyleContext(anchor),
|
|
22377
|
+
kind: "button-style",
|
|
22378
|
+
buttonId: id
|
|
22379
|
+
});
|
|
22380
|
+
},
|
|
22381
|
+
[tokensForButton]
|
|
22382
|
+
);
|
|
22383
|
+
const applySelectedButtonStyle = useCallback10(
|
|
22384
|
+
(patch) => {
|
|
22385
|
+
const panel = floatingPanelRef.current;
|
|
22386
|
+
const id = panel?.kind === "button-style" ? panel.buttonId : null;
|
|
22387
|
+
const el = id ? document.querySelector(`[data-ohw-href-key="${CSS.escape(id)}"]`) : null;
|
|
22388
|
+
if (!el || !id || !isCtaButton(el)) return;
|
|
22389
|
+
const tokens = tokensFromButton(el);
|
|
22390
|
+
const next = { ...assignmentFor(el, editContentRef.current, tokens), ...patch };
|
|
22391
|
+
const assignments = withAssignment(editContentRef.current, id, next);
|
|
22392
|
+
const text = JSON.stringify(assignments);
|
|
22393
|
+
editContentRef.current = { ...editContentRef.current, [BUTTON_ASSIGNMENTS_KEY]: text };
|
|
22394
|
+
applyButtonStyle(el, next, tokens);
|
|
22395
|
+
postToParent2({ type: "ow:change", nodes: [{ key: BUTTON_ASSIGNMENTS_KEY, text }] });
|
|
22396
|
+
setButtonStyleTick((n) => n + 1);
|
|
22397
|
+
if (selectedElRef.current === el) setToolbarRect(el.getBoundingClientRect());
|
|
22398
|
+
},
|
|
22399
|
+
[postToParent2]
|
|
22400
|
+
);
|
|
22401
|
+
useEffect15(() => {
|
|
22402
|
+
const onDragOver = (e) => {
|
|
22403
|
+
const dragged = buttonCollectionDragRef.current;
|
|
22404
|
+
if (!dragged) return;
|
|
22405
|
+
e.preventDefault();
|
|
22406
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
22407
|
+
refreshButtonDragVisuals(dragged, e.clientX, e.clientY);
|
|
22408
|
+
};
|
|
22409
|
+
const onDrop = (e) => {
|
|
22410
|
+
if (!buttonCollectionDragRef.current) return;
|
|
22411
|
+
e.preventDefault();
|
|
22412
|
+
};
|
|
22413
|
+
document.addEventListener("dragover", onDragOver);
|
|
22414
|
+
document.addEventListener("drop", onDrop);
|
|
22415
|
+
return () => {
|
|
22416
|
+
document.removeEventListener("dragover", onDragOver);
|
|
22417
|
+
document.removeEventListener("drop", onDrop);
|
|
22418
|
+
};
|
|
22419
|
+
}, [refreshButtonDragVisuals]);
|
|
20672
22420
|
const isEditModeRef = useRef12(false);
|
|
20673
22421
|
const requestMissingSocialIconsRef = useRef12(() => {
|
|
20674
22422
|
});
|
|
@@ -20711,11 +22459,13 @@ function OhhwellsBridge() {
|
|
|
20711
22459
|
);
|
|
20712
22460
|
const closeFloatingPanelOnly = useCallback10(() => {
|
|
20713
22461
|
setFloatingPanel(null);
|
|
22462
|
+
setFloatingPanelPos(null);
|
|
20714
22463
|
setLogoSizeDraft(null);
|
|
20715
22464
|
}, []);
|
|
20716
22465
|
closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
|
|
20717
22466
|
const closeFloatingPanelAndDeselect = useCallback10(() => {
|
|
20718
22467
|
setFloatingPanel(null);
|
|
22468
|
+
setFloatingPanelPos(null);
|
|
20719
22469
|
setLogoSizeDraft(null);
|
|
20720
22470
|
deselectRef.current();
|
|
20721
22471
|
}, []);
|
|
@@ -20927,6 +22677,7 @@ function OhhwellsBridge() {
|
|
|
20927
22677
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
20928
22678
|
}
|
|
20929
22679
|
applyBrandChrome(content);
|
|
22680
|
+
applyCustomCodeToHead(content);
|
|
20930
22681
|
initSectionInstancesFromContent(content, window.location.pathname);
|
|
20931
22682
|
for (const [key, val] of Object.entries(content)) {
|
|
20932
22683
|
if (key === "__ohw_sections") continue;
|
|
@@ -20935,6 +22686,7 @@ function OhhwellsBridge() {
|
|
|
20935
22686
|
if (key === STYLE_STORE_KEY) continue;
|
|
20936
22687
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
20937
22688
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
22689
|
+
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
20938
22690
|
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
20939
22691
|
if (applyVideoSettingNode(key, val)) continue;
|
|
20940
22692
|
if (applyCarouselNode(key, val)) continue;
|
|
@@ -20982,6 +22734,7 @@ function OhhwellsBridge() {
|
|
|
20982
22734
|
reconcileSocialsFromContent(content);
|
|
20983
22735
|
applySocialsDisplayFromContent(content);
|
|
20984
22736
|
applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
|
|
22737
|
+
syncButtonsFromContent(document, content);
|
|
20985
22738
|
if (isEditModeRef.current) requestMissingSocialIconsRef.current();
|
|
20986
22739
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
20987
22740
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
@@ -21182,6 +22935,7 @@ function OhhwellsBridge() {
|
|
|
21182
22935
|
reconcileSocialsFromContent(content);
|
|
21183
22936
|
applySocialsDisplayFromContent(content);
|
|
21184
22937
|
applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
|
|
22938
|
+
syncButtonsFromContent(document, content);
|
|
21185
22939
|
if (isEditModeRef.current) requestMissingSocialIconsRef.current();
|
|
21186
22940
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
21187
22941
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
@@ -21270,7 +23024,10 @@ function OhhwellsBridge() {
|
|
|
21270
23024
|
if (roots.length === 0) {
|
|
21271
23025
|
reconcileNavbarItemsFromContent(contentForNav());
|
|
21272
23026
|
reconcileFooterOrderFromContent(contentForNav());
|
|
21273
|
-
if (isEditMode)
|
|
23027
|
+
if (isEditMode) {
|
|
23028
|
+
syncButtonsFromContent(document, contentForNav());
|
|
23029
|
+
syncNavigationDragCursorAttrs();
|
|
23030
|
+
}
|
|
21274
23031
|
return;
|
|
21275
23032
|
}
|
|
21276
23033
|
let rafId = null;
|
|
@@ -21282,7 +23039,7 @@ function OhhwellsBridge() {
|
|
|
21282
23039
|
}
|
|
21283
23040
|
};
|
|
21284
23041
|
const run = () => {
|
|
21285
|
-
if (footerDragRef.current || navDragRef.current || applying) return;
|
|
23042
|
+
if (footerDragRef.current || navDragRef.current || buttonCollectionDragRef.current || applying) return;
|
|
21286
23043
|
applying = true;
|
|
21287
23044
|
observer?.disconnect();
|
|
21288
23045
|
try {
|
|
@@ -21292,6 +23049,7 @@ function OhhwellsBridge() {
|
|
|
21292
23049
|
reconcileSocialsFromContent(content);
|
|
21293
23050
|
applySocialsDisplayFromContent(content);
|
|
21294
23051
|
applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
|
|
23052
|
+
syncButtonsFromContent(document, content);
|
|
21295
23053
|
if (isEditModeRef.current) requestMissingSocialIconsRef.current();
|
|
21296
23054
|
document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
|
|
21297
23055
|
if (isFooterHrefKey(el.getAttribute("data-ohw-href-key")) || getSocialItem(el)) {
|
|
@@ -21299,9 +23057,9 @@ function OhhwellsBridge() {
|
|
|
21299
23057
|
}
|
|
21300
23058
|
});
|
|
21301
23059
|
document.querySelectorAll(
|
|
21302
|
-
|
|
23060
|
+
'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"]'
|
|
21303
23061
|
).forEach((el) => {
|
|
21304
|
-
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
23062
|
+
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key")) || isCtaButton(el)) {
|
|
21305
23063
|
disableNativeHrefDrag(el);
|
|
21306
23064
|
}
|
|
21307
23065
|
});
|
|
@@ -21326,6 +23084,44 @@ function OhhwellsBridge() {
|
|
|
21326
23084
|
observer?.disconnect();
|
|
21327
23085
|
};
|
|
21328
23086
|
}, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
|
|
23087
|
+
useEffect15(() => {
|
|
23088
|
+
if (!isEditMode) return;
|
|
23089
|
+
let applying = false;
|
|
23090
|
+
let rafId = null;
|
|
23091
|
+
const run = () => {
|
|
23092
|
+
if (applying || buttonCollectionDragRef.current) return;
|
|
23093
|
+
const content = editContentRef.current;
|
|
23094
|
+
if (!content[BUTTON_COLLECTIONS_KEY] && !content[BUTTON_SNAPSHOTS_KEY]) return;
|
|
23095
|
+
applying = true;
|
|
23096
|
+
try {
|
|
23097
|
+
syncButtonsFromContent(document, content);
|
|
23098
|
+
} finally {
|
|
23099
|
+
applying = false;
|
|
23100
|
+
}
|
|
23101
|
+
};
|
|
23102
|
+
const schedule = () => {
|
|
23103
|
+
if (rafId != null) return;
|
|
23104
|
+
rafId = requestAnimationFrame(() => {
|
|
23105
|
+
rafId = null;
|
|
23106
|
+
run();
|
|
23107
|
+
});
|
|
23108
|
+
};
|
|
23109
|
+
const observer = new MutationObserver((mutations) => {
|
|
23110
|
+
if (mutations.every((m) => {
|
|
23111
|
+
const t = m.target;
|
|
23112
|
+
return t instanceof Element && Boolean(t.closest("[data-ohw-bridge], [data-ohw-bridge-root], [data-ohw-button-collection]"));
|
|
23113
|
+
})) {
|
|
23114
|
+
return;
|
|
23115
|
+
}
|
|
23116
|
+
schedule();
|
|
23117
|
+
});
|
|
23118
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
23119
|
+
run();
|
|
23120
|
+
return () => {
|
|
23121
|
+
if (rafId != null) cancelAnimationFrame(rafId);
|
|
23122
|
+
observer.disconnect();
|
|
23123
|
+
};
|
|
23124
|
+
}, [isEditMode, pathname]);
|
|
21329
23125
|
useEffect15(() => {
|
|
21330
23126
|
if (!isEditMode) return;
|
|
21331
23127
|
let lastPosted = 0;
|
|
@@ -21852,14 +23648,6 @@ function OhhwellsBridge() {
|
|
|
21852
23648
|
}
|
|
21853
23649
|
const clickedButton = findClosestButtonLike(target);
|
|
21854
23650
|
const buttonOnMedia = Boolean(clickedButton && isMediaEditable(editable) && editable.contains(clickedButton));
|
|
21855
|
-
console.log("[click-debug]", {
|
|
21856
|
-
editableType: editable.dataset.ohwEditable,
|
|
21857
|
-
editableTag: editable.tagName,
|
|
21858
|
-
targetTag: target.tagName,
|
|
21859
|
-
clickedButtonTag: clickedButton?.tagName ?? null,
|
|
21860
|
-
buttonOnMedia,
|
|
21861
|
-
isMediaEditableEditable: isMediaEditable(editable)
|
|
21862
|
-
});
|
|
21863
23651
|
if (isMediaEditable(editable) && !buttonOnMedia) {
|
|
21864
23652
|
e.preventDefault();
|
|
21865
23653
|
e.stopPropagation();
|
|
@@ -21894,11 +23682,6 @@ function OhhwellsBridge() {
|
|
|
21894
23682
|
const hrefLookupTarget = buttonOnMedia ? clickedButton : editable;
|
|
21895
23683
|
const hrefCtx = getHrefKeyFromElement(hrefLookupTarget);
|
|
21896
23684
|
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
21897
|
-
console.log("[click-debug 2]", {
|
|
21898
|
-
hrefLookupTargetTag: hrefLookupTarget.tagName,
|
|
21899
|
-
hrefCtx: hrefCtx ? { key: hrefCtx.key } : null,
|
|
21900
|
-
navAnchorTag: navAnchor?.tagName ?? null
|
|
21901
|
-
});
|
|
21902
23685
|
if (navAnchor) {
|
|
21903
23686
|
e.preventDefault();
|
|
21904
23687
|
e.stopPropagation();
|
|
@@ -22414,6 +24197,20 @@ function OhhwellsBridge() {
|
|
|
22414
24197
|
}
|
|
22415
24198
|
return;
|
|
22416
24199
|
}
|
|
24200
|
+
const navbarCtaHit = findNavbarCtaAtPoint(x, y);
|
|
24201
|
+
if (navbarCtaHit) {
|
|
24202
|
+
hoveredNavContainerRef.current = null;
|
|
24203
|
+
setHoveredNavContainerRect(null);
|
|
24204
|
+
if (selected !== navbarCtaHit && !selected?.contains(navbarCtaHit)) {
|
|
24205
|
+
clearHrefKeyHover(navbarCtaHit);
|
|
24206
|
+
hoveredItemElRef.current = navbarCtaHit;
|
|
24207
|
+
setHoveredItemRect(navbarCtaHit.getBoundingClientRect());
|
|
24208
|
+
} else if (hoveredItemElRef.current === navbarCtaHit) {
|
|
24209
|
+
hoveredItemElRef.current = null;
|
|
24210
|
+
setHoveredItemRect(null);
|
|
24211
|
+
}
|
|
24212
|
+
return;
|
|
24213
|
+
}
|
|
22417
24214
|
const navContainers = Array.from(
|
|
22418
24215
|
document.querySelectorAll("[data-ohw-nav-container]")
|
|
22419
24216
|
);
|
|
@@ -22516,6 +24313,24 @@ function OhhwellsBridge() {
|
|
|
22516
24313
|
return;
|
|
22517
24314
|
}
|
|
22518
24315
|
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
24316
|
+
if (!isDragOver) {
|
|
24317
|
+
const buttonHit = findButtonAtPoint(x, y);
|
|
24318
|
+
if (buttonHit) {
|
|
24319
|
+
dismissImageHover();
|
|
24320
|
+
if (findNavbarCtaAtPoint(x, y)) {
|
|
24321
|
+
probeNavigationHoverAt(x, y);
|
|
24322
|
+
return;
|
|
24323
|
+
}
|
|
24324
|
+
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
24325
|
+
const selected = selectedElRef.current;
|
|
24326
|
+
if (selected !== buttonHit && !selected?.contains(buttonHit)) {
|
|
24327
|
+
clearHrefKeyHover(buttonHit);
|
|
24328
|
+
hoveredItemElRef.current = buttonHit;
|
|
24329
|
+
setHoveredItemRect(buttonHit.getBoundingClientRect());
|
|
24330
|
+
}
|
|
24331
|
+
return;
|
|
24332
|
+
}
|
|
24333
|
+
}
|
|
22519
24334
|
if (isPointOverNavigation(x, y)) {
|
|
22520
24335
|
dismissImageHover();
|
|
22521
24336
|
probeNavigationHoverAt(x, y);
|
|
@@ -22937,6 +24752,11 @@ function OhhwellsBridge() {
|
|
|
22937
24752
|
return;
|
|
22938
24753
|
}
|
|
22939
24754
|
if (onNavDragOver(e)) return;
|
|
24755
|
+
if (buttonCollectionDragRef.current) {
|
|
24756
|
+
e.preventDefault();
|
|
24757
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
24758
|
+
return;
|
|
24759
|
+
}
|
|
22940
24760
|
e.preventDefault();
|
|
22941
24761
|
const el = findImageAtPoint(e.clientX, e.clientY, false);
|
|
22942
24762
|
if (!el) {
|
|
@@ -22961,6 +24781,7 @@ function OhhwellsBridge() {
|
|
|
22961
24781
|
};
|
|
22962
24782
|
const handleDrop = (e) => {
|
|
22963
24783
|
e.preventDefault();
|
|
24784
|
+
if (buttonCollectionDragRef.current || navDragRef.current || footerDragRef.current) return;
|
|
22964
24785
|
const el = findImageAtPoint(e.clientX, e.clientY, false);
|
|
22965
24786
|
if (!el) return;
|
|
22966
24787
|
const file = e.dataTransfer?.files?.[0];
|
|
@@ -23263,6 +25084,7 @@ function OhhwellsBridge() {
|
|
|
23263
25084
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
23264
25085
|
}
|
|
23265
25086
|
applyBrandChrome(content);
|
|
25087
|
+
applyCustomCodeToHead(content);
|
|
23266
25088
|
initSectionInstancesFromContent(content, window.location.pathname);
|
|
23267
25089
|
let sectionsJson = null;
|
|
23268
25090
|
for (const [key, val] of Object.entries(content)) {
|
|
@@ -23275,6 +25097,7 @@ function OhhwellsBridge() {
|
|
|
23275
25097
|
if (key === STYLE_STORE_KEY) continue;
|
|
23276
25098
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
23277
25099
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
25100
|
+
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
23278
25101
|
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
23279
25102
|
if (applyVideoSettingNode(key, val)) continue;
|
|
23280
25103
|
if (applyCarouselNode(key, val)) continue;
|
|
@@ -23314,6 +25137,7 @@ function OhhwellsBridge() {
|
|
|
23314
25137
|
editContentRef.current = { ...editContentRef.current, ...content };
|
|
23315
25138
|
reconcileNavbarItemsFromContent(editContentRef.current);
|
|
23316
25139
|
reconcileFooterOrderFromContent(editContentRef.current);
|
|
25140
|
+
syncButtonsFromContent(document, editContentRef.current);
|
|
23317
25141
|
syncNavigationDragCursorAttrs();
|
|
23318
25142
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
23319
25143
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
@@ -23986,6 +25810,16 @@ function OhhwellsBridge() {
|
|
|
23986
25810
|
if (brandKitRef.current) {
|
|
23987
25811
|
nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
|
|
23988
25812
|
}
|
|
25813
|
+
nodes.push({
|
|
25814
|
+
key: CUSTOM_CODE_BEFORE_HEAD_KEY,
|
|
25815
|
+
type: "text",
|
|
25816
|
+
text: editContentRef.current[CUSTOM_CODE_BEFORE_HEAD_KEY] ?? ""
|
|
25817
|
+
});
|
|
25818
|
+
nodes.push({
|
|
25819
|
+
key: CUSTOM_CODE_AFTER_HEAD_KEY,
|
|
25820
|
+
type: "text",
|
|
25821
|
+
text: editContentRef.current[CUSTOM_CODE_AFTER_HEAD_KEY] ?? ""
|
|
25822
|
+
});
|
|
23989
25823
|
document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
23990
25824
|
const formKey = formKeyOf(form);
|
|
23991
25825
|
if (!formKey) return;
|
|
@@ -24213,11 +26047,8 @@ function OhhwellsBridge() {
|
|
|
24213
26047
|
};
|
|
24214
26048
|
const handleParentScroll = (e) => {
|
|
24215
26049
|
if (e.data?.type !== "ow:parent-scroll") return;
|
|
24216
|
-
const { iframeOffsetTop, headerH, canvasH } = e.data;
|
|
24217
|
-
parentScrollRef.current = { iframeOffsetTop, headerH, canvasH };
|
|
24218
|
-
if (floatingPanelOpenRef.current) {
|
|
24219
|
-
setParentScrollSnap({ iframeOffsetTop, headerH, canvasH });
|
|
24220
|
-
}
|
|
26050
|
+
const { iframeOffsetTop, headerH, canvasH, promptBarH = 0 } = e.data;
|
|
26051
|
+
parentScrollRef.current = { iframeOffsetTop, headerH, canvasH, promptBarH };
|
|
24221
26052
|
if (visibleViewportRef.current) {
|
|
24222
26053
|
applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
|
|
24223
26054
|
}
|
|
@@ -24607,6 +26438,97 @@ function OhhwellsBridge() {
|
|
|
24607
26438
|
unlockFooterDragInteraction();
|
|
24608
26439
|
};
|
|
24609
26440
|
}, [isEditMode]);
|
|
26441
|
+
useEffect15(() => {
|
|
26442
|
+
if (!isEditMode) return;
|
|
26443
|
+
const THRESHOLD = 10;
|
|
26444
|
+
const onPointerDown = (e) => {
|
|
26445
|
+
if (e.button !== 0) return;
|
|
26446
|
+
if (buttonCollectionDragRef.current || navDragRef.current || footerDragRef.current) return;
|
|
26447
|
+
if (buttonPointerDragRef.current) return;
|
|
26448
|
+
const target = e.target;
|
|
26449
|
+
if (!target) return;
|
|
26450
|
+
if (target.closest(
|
|
26451
|
+
'[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]'
|
|
26452
|
+
)) {
|
|
26453
|
+
return;
|
|
26454
|
+
}
|
|
26455
|
+
const fromTarget = target.closest('[data-ohw-role="navbar-button"]');
|
|
26456
|
+
const anchor = (fromTarget && !fromTarget.closest("[data-ohw-bridge]") ? fromTarget : null) ?? findNavbarCtaAtPoint(e.clientX, e.clientY);
|
|
26457
|
+
if (!anchor || !collectionDragEnabled(anchor)) return;
|
|
26458
|
+
disableNativeHrefDrag(anchor);
|
|
26459
|
+
setMediaHover(null);
|
|
26460
|
+
buttonPointerDragRef.current = {
|
|
26461
|
+
el: anchor,
|
|
26462
|
+
startX: e.clientX,
|
|
26463
|
+
startY: e.clientY,
|
|
26464
|
+
pointerId: e.pointerId,
|
|
26465
|
+
started: false
|
|
26466
|
+
};
|
|
26467
|
+
};
|
|
26468
|
+
const onPointerMove = (e) => {
|
|
26469
|
+
const pending = buttonPointerDragRef.current;
|
|
26470
|
+
if (!pending) return;
|
|
26471
|
+
if (pending.started) {
|
|
26472
|
+
e.preventDefault();
|
|
26473
|
+
clearTextSelection();
|
|
26474
|
+
const dragged = buttonCollectionDragRef.current;
|
|
26475
|
+
if (!dragged) return;
|
|
26476
|
+
refreshButtonDragVisuals(dragged, e.clientX, e.clientY);
|
|
26477
|
+
return;
|
|
26478
|
+
}
|
|
26479
|
+
const dx = e.clientX - pending.startX;
|
|
26480
|
+
const dy = e.clientY - pending.startY;
|
|
26481
|
+
if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
|
|
26482
|
+
e.preventDefault();
|
|
26483
|
+
pending.started = true;
|
|
26484
|
+
armFooterPressDrag();
|
|
26485
|
+
clearTextSelection();
|
|
26486
|
+
try {
|
|
26487
|
+
document.body.setPointerCapture(pending.pointerId);
|
|
26488
|
+
} catch {
|
|
26489
|
+
}
|
|
26490
|
+
if (linkPopoverOpenRef.current) setLinkPopoverRef.current(null);
|
|
26491
|
+
if (activeElRef.current) deactivateRef.current();
|
|
26492
|
+
ensureNavbarButtonCollection(pending.el, editContentRef.current);
|
|
26493
|
+
buttonCollectionDragRef.current = pending.el;
|
|
26494
|
+
lockFooterDuringDrag();
|
|
26495
|
+
setIsItemDragging(true);
|
|
26496
|
+
refreshButtonDragVisuals(pending.el, e.clientX, e.clientY);
|
|
26497
|
+
};
|
|
26498
|
+
const endPointerDrag = (e) => {
|
|
26499
|
+
const pending = buttonPointerDragRef.current;
|
|
26500
|
+
buttonPointerDragRef.current = null;
|
|
26501
|
+
try {
|
|
26502
|
+
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
26503
|
+
document.body.releasePointerCapture(e.pointerId);
|
|
26504
|
+
}
|
|
26505
|
+
} catch {
|
|
26506
|
+
}
|
|
26507
|
+
if (!pending) return;
|
|
26508
|
+
if (!pending.started) {
|
|
26509
|
+
unlockFooterDragInteraction();
|
|
26510
|
+
return;
|
|
26511
|
+
}
|
|
26512
|
+
suppressNextClickRef.current = true;
|
|
26513
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
26514
|
+
persistButtonCollectionDrag(pending.el, e.clientX);
|
|
26515
|
+
};
|
|
26516
|
+
const blockSelectStart = (e) => {
|
|
26517
|
+
if (buttonCollectionDragRef.current || buttonPointerDragRef.current?.started) e.preventDefault();
|
|
26518
|
+
};
|
|
26519
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
26520
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
26521
|
+
document.addEventListener("pointerup", endPointerDrag, true);
|
|
26522
|
+
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
26523
|
+
document.addEventListener("selectstart", blockSelectStart, true);
|
|
26524
|
+
return () => {
|
|
26525
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
26526
|
+
document.removeEventListener("pointermove", onPointerMove, true);
|
|
26527
|
+
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
26528
|
+
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
26529
|
+
document.removeEventListener("selectstart", blockSelectStart, true);
|
|
26530
|
+
};
|
|
26531
|
+
}, [isEditMode, persistButtonCollectionDrag, refreshButtonDragVisuals]);
|
|
24610
26532
|
useEffect15(() => {
|
|
24611
26533
|
const handler = (e) => {
|
|
24612
26534
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
@@ -24647,7 +26569,7 @@ function OhhwellsBridge() {
|
|
|
24647
26569
|
postToParent2({
|
|
24648
26570
|
type: "ow:ready",
|
|
24649
26571
|
version: "1",
|
|
24650
|
-
bridgeVersion: "0.1.
|
|
26572
|
+
bridgeVersion: "0.1.121",
|
|
24651
26573
|
path: pathname,
|
|
24652
26574
|
nodes: collectEditableNodes(editContentRef.current),
|
|
24653
26575
|
sections
|
|
@@ -24726,12 +26648,12 @@ function OhhwellsBridge() {
|
|
|
24726
26648
|
return;
|
|
24727
26649
|
}
|
|
24728
26650
|
if (type !== "ow:logo-size-set") return;
|
|
24729
|
-
const
|
|
24730
|
-
if (!Number.isFinite(
|
|
24731
|
-
const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx:
|
|
26651
|
+
const px2 = Number(e.data.px);
|
|
26652
|
+
if (!Number.isFinite(px2)) return;
|
|
26653
|
+
const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px2, mobileFollowing: false } : {
|
|
24732
26654
|
...logoSizeDraft,
|
|
24733
|
-
desktopPx:
|
|
24734
|
-
mobilePx: logoSizeDraft.mobileFollowing ?
|
|
26655
|
+
desktopPx: px2,
|
|
26656
|
+
mobilePx: logoSizeDraft.mobileFollowing ? px2 : logoSizeDraft.mobilePx
|
|
24735
26657
|
};
|
|
24736
26658
|
setLogoSizeDraft(next);
|
|
24737
26659
|
persistLogoSizeDraft(session.placement, next);
|
|
@@ -24829,6 +26751,36 @@ function OhhwellsBridge() {
|
|
|
24829
26751
|
const handleDuplicateSelected = useCallback10(() => {
|
|
24830
26752
|
const selected = selectedElRef.current;
|
|
24831
26753
|
if (!selected || !isNavigationItem2(selected)) return;
|
|
26754
|
+
if (isCtaButton(selected)) {
|
|
26755
|
+
const id = buttonId(selected);
|
|
26756
|
+
if (!id) return;
|
|
26757
|
+
const tokens = tokensForButton(selected, true);
|
|
26758
|
+
if (!readAssignments(editContentRef.current)[id]) {
|
|
26759
|
+
const assignment = assignmentFor(selected, editContentRef.current, tokens);
|
|
26760
|
+
const assignments = withAssignment(editContentRef.current, id, assignment);
|
|
26761
|
+
editContentRef.current = {
|
|
26762
|
+
...editContentRef.current,
|
|
26763
|
+
[BUTTON_ASSIGNMENTS_KEY]: JSON.stringify(assignments)
|
|
26764
|
+
};
|
|
26765
|
+
applyButtonStyle(selected, assignment, tokens);
|
|
26766
|
+
}
|
|
26767
|
+
const result = duplicateButton(selected, editContentRef.current);
|
|
26768
|
+
if (!result) return;
|
|
26769
|
+
editContentRef.current = result.content;
|
|
26770
|
+
const copyHref = result.copy.getAttribute("data-ohw-href-key");
|
|
26771
|
+
const copyHrefVal = copyHref ? result.content[copyHref] : void 0;
|
|
26772
|
+
if (copyHref && copyHrefVal !== void 0) applyLinkByKey(copyHref, copyHrefVal);
|
|
26773
|
+
postToParent2({ type: "ow:change", nodes: result.nodes });
|
|
26774
|
+
enforceLinkHrefs();
|
|
26775
|
+
requestAnimationFrame(() => {
|
|
26776
|
+
selectRef.current(result.copy);
|
|
26777
|
+
requestAnimationFrame(() => {
|
|
26778
|
+
const el = selectedElRef.current;
|
|
26779
|
+
if (el?.isConnected) setToolbarRect(el.getBoundingClientRect());
|
|
26780
|
+
});
|
|
26781
|
+
});
|
|
26782
|
+
return;
|
|
26783
|
+
}
|
|
24832
26784
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
24833
26785
|
if (!hrefKey) return;
|
|
24834
26786
|
const social = getSocialItem(selected);
|
|
@@ -24958,7 +26910,7 @@ function OhhwellsBridge() {
|
|
|
24958
26910
|
selectRef.current(result.anchor);
|
|
24959
26911
|
});
|
|
24960
26912
|
}
|
|
24961
|
-
}, [postToParent2]);
|
|
26913
|
+
}, [postToParent2, tokensForButton]);
|
|
24962
26914
|
const runPendingDeleteUndo = useCallback10(() => {
|
|
24963
26915
|
const pending = pendingDeleteUndoRef.current;
|
|
24964
26916
|
if (!pending) return false;
|
|
@@ -24970,6 +26922,38 @@ function OhhwellsBridge() {
|
|
|
24970
26922
|
const handleDeleteSelected = useCallback10(() => {
|
|
24971
26923
|
const selected = selectedElRef.current;
|
|
24972
26924
|
if (!selected) return false;
|
|
26925
|
+
if (isCtaButton(selected)) {
|
|
26926
|
+
if (!canDeleteButton(selected)) return false;
|
|
26927
|
+
const previousContent = editContentRef.current;
|
|
26928
|
+
const result = deleteButton(selected, previousContent);
|
|
26929
|
+
if (!result) return false;
|
|
26930
|
+
editContentRef.current = result.content;
|
|
26931
|
+
postToParent2({ type: "ow:change", nodes: result.nodes });
|
|
26932
|
+
const actionId = typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `delete-${Date.now()}`;
|
|
26933
|
+
const restoreNodes = result.nodes.map((node) => ({
|
|
26934
|
+
key: node.key,
|
|
26935
|
+
text: previousContent[node.key] ?? ""
|
|
26936
|
+
}));
|
|
26937
|
+
pendingDeleteUndoRef.current = {
|
|
26938
|
+
actionId,
|
|
26939
|
+
restore: () => {
|
|
26940
|
+
result.undo();
|
|
26941
|
+
editContentRef.current = { ...editContentRef.current, ...Object.fromEntries(restoreNodes.map((node) => [node.key, node.text])) };
|
|
26942
|
+
postToParent2({ type: "ow:change", nodes: restoreNodes });
|
|
26943
|
+
syncButtonsFromContent(document, editContentRef.current);
|
|
26944
|
+
}
|
|
26945
|
+
};
|
|
26946
|
+
deselectRef.current();
|
|
26947
|
+
postToParent2({
|
|
26948
|
+
type: "ow:toast",
|
|
26949
|
+
title: "Button deleted",
|
|
26950
|
+
toastType: "success",
|
|
26951
|
+
actionLabel: "Undo",
|
|
26952
|
+
actionId,
|
|
26953
|
+
duration: 6e3
|
|
26954
|
+
});
|
|
26955
|
+
return true;
|
|
26956
|
+
}
|
|
24973
26957
|
return deleteSelectedNavFooterItem({
|
|
24974
26958
|
selected,
|
|
24975
26959
|
isTextEditing: Boolean(activeElRef.current),
|
|
@@ -25107,14 +27091,14 @@ function OhhwellsBridge() {
|
|
|
25107
27091
|
},
|
|
25108
27092
|
[postToParent2]
|
|
25109
27093
|
);
|
|
25110
|
-
return /* @__PURE__ */
|
|
25111
|
-
/* @__PURE__ */
|
|
25112
|
-
/* @__PURE__ */
|
|
25113
|
-
subdomain && !isEditMode && showBranding && /* @__PURE__ */
|
|
27094
|
+
return /* @__PURE__ */ jsxs23(Fragment10, { children: [
|
|
27095
|
+
/* @__PURE__ */ jsx36("div", { id: "ohw-loader", suppressHydrationWarning: true, style: { ...OHW_LOADER_STYLE, display: "none" }, children: /* @__PURE__ */ jsx36(OhwLoaderSpinner, {}) }),
|
|
27096
|
+
/* @__PURE__ */ jsx36("script", { suppressHydrationWarning: true, dangerouslySetInnerHTML: { __html: OHW_LOADER_PREHYDRATE_SCRIPT } }),
|
|
27097
|
+
subdomain && !isEditMode && showBranding && /* @__PURE__ */ jsx36(MadeWithOhhWells, {}),
|
|
25114
27098
|
bridgeRoot ? createPortal3(
|
|
25115
|
-
/* @__PURE__ */
|
|
25116
|
-
/* @__PURE__ */
|
|
25117
|
-
isEditMode && /* @__PURE__ */
|
|
27099
|
+
/* @__PURE__ */ jsxs23(Fragment10, { children: [
|
|
27100
|
+
/* @__PURE__ */ jsx36("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
27101
|
+
isEditMode && /* @__PURE__ */ jsx36(
|
|
25118
27102
|
AiSectionOverlay,
|
|
25119
27103
|
{
|
|
25120
27104
|
postToParent: postToParent2,
|
|
@@ -25122,7 +27106,7 @@ function OhhwellsBridge() {
|
|
|
25122
27106
|
onSelectionChange: handleAiSectionSelectionChange
|
|
25123
27107
|
}
|
|
25124
27108
|
),
|
|
25125
|
-
isEditMode && /* @__PURE__ */
|
|
27109
|
+
isEditMode && /* @__PURE__ */ jsx36(
|
|
25126
27110
|
AiMediaStripOverlay,
|
|
25127
27111
|
{
|
|
25128
27112
|
postToParent: postToParent2,
|
|
@@ -25131,7 +27115,7 @@ function OhhwellsBridge() {
|
|
|
25131
27115
|
clearInteractionChromeRef
|
|
25132
27116
|
}
|
|
25133
27117
|
),
|
|
25134
|
-
isEditMode && /* @__PURE__ */
|
|
27118
|
+
isEditMode && /* @__PURE__ */ jsx36(
|
|
25135
27119
|
AiPricingCardOverlay,
|
|
25136
27120
|
{
|
|
25137
27121
|
postToParent: postToParent2,
|
|
@@ -25139,12 +27123,12 @@ function OhhwellsBridge() {
|
|
|
25139
27123
|
applyTreeLocalRef
|
|
25140
27124
|
}
|
|
25141
27125
|
),
|
|
25142
|
-
isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */
|
|
27126
|
+
isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ jsx36(
|
|
25143
27127
|
"div",
|
|
25144
27128
|
{
|
|
25145
27129
|
className: "pointer-events-none fixed z-2147483646",
|
|
25146
27130
|
style: { left: slot.left, top: slot.y, width: slot.width, height: 3, transform: "translateY(-50%)" },
|
|
25147
|
-
children: /* @__PURE__ */
|
|
27131
|
+
children: /* @__PURE__ */ jsx36(
|
|
25148
27132
|
DropIndicator,
|
|
25149
27133
|
{
|
|
25150
27134
|
direction: "horizontal",
|
|
@@ -25155,7 +27139,7 @@ function OhhwellsBridge() {
|
|
|
25155
27139
|
},
|
|
25156
27140
|
`section-drop-${slot.insertIndex}-${i}`
|
|
25157
27141
|
)),
|
|
25158
|
-
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */
|
|
27142
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx36(
|
|
25159
27143
|
MediaOverlay,
|
|
25160
27144
|
{
|
|
25161
27145
|
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
@@ -25166,7 +27150,7 @@ function OhhwellsBridge() {
|
|
|
25166
27150
|
},
|
|
25167
27151
|
`uploading-${key}`
|
|
25168
27152
|
)),
|
|
25169
|
-
mediaHover && !(mediaHover.key in uploadingRects) && mediaHover.key !== selectedMedia?.key && /* @__PURE__ */
|
|
27153
|
+
mediaHover && !(mediaHover.key in uploadingRects) && mediaHover.key !== selectedMedia?.key && /* @__PURE__ */ jsx36(
|
|
25170
27154
|
MediaOverlay,
|
|
25171
27155
|
{
|
|
25172
27156
|
hover: mediaHover,
|
|
@@ -25177,7 +27161,7 @@ function OhhwellsBridge() {
|
|
|
25177
27161
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
25178
27162
|
}
|
|
25179
27163
|
),
|
|
25180
|
-
selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */
|
|
27164
|
+
selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */ jsx36(
|
|
25181
27165
|
MediaOverlay,
|
|
25182
27166
|
{
|
|
25183
27167
|
hover: selectedMedia,
|
|
@@ -25189,7 +27173,7 @@ function OhhwellsBridge() {
|
|
|
25189
27173
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
25190
27174
|
}
|
|
25191
27175
|
),
|
|
25192
|
-
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */
|
|
27176
|
+
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx36(
|
|
25193
27177
|
CarouselOverlay,
|
|
25194
27178
|
{
|
|
25195
27179
|
hover: carouselHover,
|
|
@@ -25197,10 +27181,10 @@ function OhhwellsBridge() {
|
|
|
25197
27181
|
cueOnly: !!carouselHover.fullBleedSectionId && carouselHover.fullBleedSectionId !== selectedAiSectionId
|
|
25198
27182
|
}
|
|
25199
27183
|
),
|
|
25200
|
-
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */
|
|
25201
|
-
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */
|
|
25202
|
-
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */
|
|
25203
|
-
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */
|
|
27184
|
+
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx36(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
27185
|
+
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx36(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
27186
|
+
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && selectedElRef.current !== buttonCollectionDragRef.current && /* @__PURE__ */ jsx36(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
27187
|
+
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx36(
|
|
25204
27188
|
"div",
|
|
25205
27189
|
{
|
|
25206
27190
|
className: "pointer-events-none fixed z-2147483646",
|
|
@@ -25210,7 +27194,7 @@ function OhhwellsBridge() {
|
|
|
25210
27194
|
width: slot.width,
|
|
25211
27195
|
height: slot.height
|
|
25212
27196
|
},
|
|
25213
|
-
children: /* @__PURE__ */
|
|
27197
|
+
children: /* @__PURE__ */ jsx36(
|
|
25214
27198
|
DropIndicator,
|
|
25215
27199
|
{
|
|
25216
27200
|
direction: slot.direction,
|
|
@@ -25221,7 +27205,7 @@ function OhhwellsBridge() {
|
|
|
25221
27205
|
},
|
|
25222
27206
|
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
25223
27207
|
)),
|
|
25224
|
-
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */
|
|
27208
|
+
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx36(
|
|
25225
27209
|
"div",
|
|
25226
27210
|
{
|
|
25227
27211
|
className: "pointer-events-none fixed z-2147483646",
|
|
@@ -25231,7 +27215,7 @@ function OhhwellsBridge() {
|
|
|
25231
27215
|
width: slot.width,
|
|
25232
27216
|
height: slot.height
|
|
25233
27217
|
},
|
|
25234
|
-
children: /* @__PURE__ */
|
|
27218
|
+
children: /* @__PURE__ */ jsx36(
|
|
25235
27219
|
DropIndicator,
|
|
25236
27220
|
{
|
|
25237
27221
|
direction: slot.direction,
|
|
@@ -25242,10 +27226,31 @@ function OhhwellsBridge() {
|
|
|
25242
27226
|
},
|
|
25243
27227
|
`nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
|
|
25244
27228
|
)),
|
|
25245
|
-
|
|
25246
|
-
|
|
25247
|
-
|
|
25248
|
-
|
|
27229
|
+
isItemDragging && buttonDropSlots.map((slot, i) => /* @__PURE__ */ jsx36(
|
|
27230
|
+
"div",
|
|
27231
|
+
{
|
|
27232
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
27233
|
+
style: {
|
|
27234
|
+
left: slot.left,
|
|
27235
|
+
top: slot.top,
|
|
27236
|
+
width: slot.width,
|
|
27237
|
+
height: slot.height
|
|
27238
|
+
},
|
|
27239
|
+
children: /* @__PURE__ */ jsx36(
|
|
27240
|
+
DropIndicator,
|
|
27241
|
+
{
|
|
27242
|
+
direction: slot.direction,
|
|
27243
|
+
state: activeButtonDropIndex === i ? "dragActive" : "dragIdle",
|
|
27244
|
+
className: "!h-full !w-full"
|
|
27245
|
+
}
|
|
27246
|
+
)
|
|
27247
|
+
},
|
|
27248
|
+
`button-drop-${slot.direction}-${slot.insertIndex}-${i}`
|
|
27249
|
+
)),
|
|
27250
|
+
hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx36(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
27251
|
+
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx36(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
27252
|
+
hoveredTextRect && !hoveredNavContainerRect && !hoveredItemRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ jsx36(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
|
|
27253
|
+
formPickRect && !isItemDragging && /* @__PURE__ */ jsx36(
|
|
25249
27254
|
ItemInteractionLayer,
|
|
25250
27255
|
{
|
|
25251
27256
|
rect: formPickRect,
|
|
@@ -25253,13 +27258,13 @@ function OhhwellsBridge() {
|
|
|
25253
27258
|
itemDragSurface: false,
|
|
25254
27259
|
toolbarAlign: "left",
|
|
25255
27260
|
chromeGap: 24,
|
|
25256
|
-
toolbar: fieldPickRect ? void 0 : /* @__PURE__ */
|
|
27261
|
+
toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ jsxs23(
|
|
25257
27262
|
"div",
|
|
25258
27263
|
{
|
|
25259
27264
|
"data-ohw-form-toolbar": "",
|
|
25260
27265
|
className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
|
|
25261
27266
|
children: [
|
|
25262
|
-
/* @__PURE__ */
|
|
27267
|
+
/* @__PURE__ */ jsx36(
|
|
25263
27268
|
"button",
|
|
25264
27269
|
{
|
|
25265
27270
|
type: "button",
|
|
@@ -25267,11 +27272,11 @@ function OhhwellsBridge() {
|
|
|
25267
27272
|
className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
|
|
25268
27273
|
onClick: () => setFieldTypePickerOpen((open) => !open),
|
|
25269
27274
|
"data-ohw-add-field": "",
|
|
25270
|
-
children: /* @__PURE__ */
|
|
27275
|
+
children: /* @__PURE__ */ jsx36(Plus4, { size: 15, "aria-hidden": true })
|
|
25271
27276
|
}
|
|
25272
27277
|
),
|
|
25273
|
-
/* @__PURE__ */
|
|
25274
|
-
/* @__PURE__ */
|
|
27278
|
+
/* @__PURE__ */ jsx36("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
27279
|
+
/* @__PURE__ */ jsxs23(
|
|
25275
27280
|
"button",
|
|
25276
27281
|
{
|
|
25277
27282
|
type: "button",
|
|
@@ -25287,11 +27292,11 @@ function OhhwellsBridge() {
|
|
|
25287
27292
|
});
|
|
25288
27293
|
},
|
|
25289
27294
|
children: [
|
|
25290
|
-
/* @__PURE__ */
|
|
27295
|
+
/* @__PURE__ */ jsx36(Settings, { size: 14, "aria-hidden": true }),
|
|
25291
27296
|
"Form settings",
|
|
25292
27297
|
formPickCount ? (
|
|
25293
27298
|
// Counter pill, per the design — not a text suffix.
|
|
25294
|
-
/* @__PURE__ */
|
|
27299
|
+
/* @__PURE__ */ jsx36(
|
|
25295
27300
|
"span",
|
|
25296
27301
|
{
|
|
25297
27302
|
"data-ohw-form-count": "",
|
|
@@ -25303,8 +27308,8 @@ function OhhwellsBridge() {
|
|
|
25303
27308
|
]
|
|
25304
27309
|
}
|
|
25305
27310
|
),
|
|
25306
|
-
/* @__PURE__ */
|
|
25307
|
-
/* @__PURE__ */
|
|
27311
|
+
/* @__PURE__ */ jsx36("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
27312
|
+
/* @__PURE__ */ jsx36("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ jsx36(
|
|
25308
27313
|
"button",
|
|
25309
27314
|
{
|
|
25310
27315
|
type: "button",
|
|
@@ -25335,7 +27340,7 @@ function OhhwellsBridge() {
|
|
|
25335
27340
|
)
|
|
25336
27341
|
}
|
|
25337
27342
|
),
|
|
25338
|
-
formHoverRect && !isItemDragging && /* @__PURE__ */
|
|
27343
|
+
formHoverRect && !isItemDragging && /* @__PURE__ */ jsx36(
|
|
25339
27344
|
ItemInteractionLayer,
|
|
25340
27345
|
{
|
|
25341
27346
|
rect: formHoverRect,
|
|
@@ -25343,7 +27348,7 @@ function OhhwellsBridge() {
|
|
|
25343
27348
|
chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
|
|
25344
27349
|
}
|
|
25345
27350
|
),
|
|
25346
|
-
fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */
|
|
27351
|
+
fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ jsx36(
|
|
25347
27352
|
ItemInteractionLayer,
|
|
25348
27353
|
{
|
|
25349
27354
|
rect: fieldPickRect,
|
|
@@ -25355,7 +27360,7 @@ function OhhwellsBridge() {
|
|
|
25355
27360
|
dragHandleLabel: "Reorder field",
|
|
25356
27361
|
onDragHandleDragStart: handleFieldDragStart,
|
|
25357
27362
|
onDragHandleDragEnd: handleFieldDragEnd,
|
|
25358
|
-
toolbar: /* @__PURE__ */
|
|
27363
|
+
toolbar: /* @__PURE__ */ jsx36(
|
|
25359
27364
|
FormFieldToolbar,
|
|
25360
27365
|
{
|
|
25361
27366
|
type: fieldPickState.type,
|
|
@@ -25368,12 +27373,12 @@ function OhhwellsBridge() {
|
|
|
25368
27373
|
)
|
|
25369
27374
|
}
|
|
25370
27375
|
),
|
|
25371
|
-
fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */
|
|
27376
|
+
fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ jsx36(
|
|
25372
27377
|
"div",
|
|
25373
27378
|
{
|
|
25374
27379
|
className: "pointer-events-none fixed z-[2147483644]",
|
|
25375
27380
|
style: { top: slot.top, left: slot.left, width: slot.width },
|
|
25376
|
-
children: /* @__PURE__ */
|
|
27381
|
+
children: /* @__PURE__ */ jsx36(
|
|
25377
27382
|
DropIndicator,
|
|
25378
27383
|
{
|
|
25379
27384
|
direction: "horizontal",
|
|
@@ -25386,7 +27391,7 @@ function OhhwellsBridge() {
|
|
|
25386
27391
|
)) : null,
|
|
25387
27392
|
fieldTypePickerOpen && formPickRect ? (() => {
|
|
25388
27393
|
const toolbar = document.querySelector("[data-ohw-form-toolbar]")?.getBoundingClientRect();
|
|
25389
|
-
return /* @__PURE__ */
|
|
27394
|
+
return /* @__PURE__ */ jsx36(
|
|
25390
27395
|
"div",
|
|
25391
27396
|
{
|
|
25392
27397
|
className: "pointer-events-none fixed z-[2147483645]",
|
|
@@ -25394,12 +27399,12 @@ function OhhwellsBridge() {
|
|
|
25394
27399
|
top: toolbar ? toolbar.bottom + 6 : formPickRect.top + 16,
|
|
25395
27400
|
left: toolbar ? toolbar.left : formPickRect.left + 24
|
|
25396
27401
|
},
|
|
25397
|
-
children: /* @__PURE__ */
|
|
27402
|
+
children: /* @__PURE__ */ jsx36(FieldTypePicker, { onPick: handleAddField })
|
|
25398
27403
|
}
|
|
25399
27404
|
);
|
|
25400
27405
|
})() : null,
|
|
25401
|
-
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */
|
|
25402
|
-
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */
|
|
27406
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ jsx36(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
|
|
27407
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx36(
|
|
25403
27408
|
FooterContainerChrome,
|
|
25404
27409
|
{
|
|
25405
27410
|
rect: toolbarRect,
|
|
@@ -25407,13 +27412,17 @@ function OhhwellsBridge() {
|
|
|
25407
27412
|
addDisabled: !canAddFooterColumn()
|
|
25408
27413
|
}
|
|
25409
27414
|
),
|
|
25410
|
-
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */
|
|
27415
|
+
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ jsx36(
|
|
25411
27416
|
ItemInteractionLayer,
|
|
25412
27417
|
{
|
|
25413
|
-
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
|
|
27418
|
+
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected || selectedElRef.current === buttonCollectionDragRef.current) ? draggedItemRect : toolbarRect,
|
|
25414
27419
|
toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
|
|
25415
27420
|
toolbarBelowEl: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanel(selectedElRef.current) : null,
|
|
25416
27421
|
elRef: glowElRef,
|
|
27422
|
+
hidden: isRectOutsideClip(
|
|
27423
|
+
isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected || selectedElRef.current === buttonCollectionDragRef.current) ? draggedItemRect : toolbarRect,
|
|
27424
|
+
getIframeVisibleClip(parentScrollRef.current)
|
|
27425
|
+
),
|
|
25417
27426
|
state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanel(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
25418
27427
|
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
|
|
25419
27428
|
dragDisabled: reorderDragDisabled,
|
|
@@ -25423,18 +27432,25 @@ function OhhwellsBridge() {
|
|
|
25423
27432
|
onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
|
|
25424
27433
|
onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
|
|
25425
27434
|
itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection && !selectedIsSocialsRow,
|
|
25426
|
-
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */
|
|
27435
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ jsx36(
|
|
25427
27436
|
ItemActionToolbar,
|
|
25428
27437
|
{
|
|
25429
27438
|
onEditLink: openLinkPopoverForSelected,
|
|
25430
27439
|
onStyle: () => {
|
|
25431
27440
|
const row = selectedElRef.current;
|
|
25432
27441
|
if (!row) return;
|
|
25433
|
-
|
|
27442
|
+
suppressNextClickRef.current = true;
|
|
27443
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
27444
|
+
if (isCtaButton(row)) {
|
|
27445
|
+
if (floatingPanelRef.current?.kind === "button-style") closeFloatingPanelOnly();
|
|
27446
|
+
else openButtonStylePanel(row);
|
|
27447
|
+
return;
|
|
27448
|
+
}
|
|
27449
|
+
if (floatingPanelRef.current?.kind === "socials-display") closeFloatingPanelOnly();
|
|
25434
27450
|
else openSocialsDisplayPanel(row);
|
|
25435
27451
|
},
|
|
25436
|
-
showStyle: selectedIsSocialsRow,
|
|
25437
|
-
styleActive: floatingPanel?.kind === "socials-display",
|
|
27452
|
+
showStyle: selectedIsSocialsRow || selectedIsCta,
|
|
27453
|
+
styleActive: floatingPanel?.kind === "socials-display" || floatingPanel?.kind === "button-style",
|
|
25438
27454
|
onAddItem: handleAddChildItem,
|
|
25439
27455
|
onSelectParent: handleSelectParent,
|
|
25440
27456
|
onDuplicate: handleDuplicateSelected,
|
|
@@ -25445,11 +27461,11 @@ function OhhwellsBridge() {
|
|
|
25445
27461
|
})(),
|
|
25446
27462
|
editLinkDisabled: false,
|
|
25447
27463
|
moreDisabled: false,
|
|
25448
|
-
deleteDisabled: selectedElRef.current !== null && (() => {
|
|
27464
|
+
deleteDisabled: selectedElRef.current !== null && isCtaButton(selectedElRef.current) && !canDeleteButton(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
25449
27465
|
const social = getSocialItem(selectedElRef.current);
|
|
25450
27466
|
return social ? !canRemoveSocialItem(social) : false;
|
|
25451
27467
|
})(),
|
|
25452
|
-
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow || selectedElRef.current !== null && (() => {
|
|
27468
|
+
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow || selectedElRef.current !== null && isCtaButton(selectedElRef.current) && !canDuplicateButton(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
25453
27469
|
const social = getSocialItem(selectedElRef.current);
|
|
25454
27470
|
const row = social ? findSocialsRow(social) : null;
|
|
25455
27471
|
return row ? !canAddSocialItem(row) : false;
|
|
@@ -25458,7 +27474,7 @@ function OhhwellsBridge() {
|
|
|
25458
27474
|
showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
|
|
25459
27475
|
selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
|
|
25460
27476
|
),
|
|
25461
|
-
showMore:
|
|
27477
|
+
showMore: !selectedIsSocialsRow,
|
|
25462
27478
|
dropdownOpen: navDropdownPreviewOpen,
|
|
25463
27479
|
onDropdownOpenChange: handleNavDropdownOpenChange,
|
|
25464
27480
|
headingVisible: footerHeadingVisible,
|
|
@@ -25467,8 +27483,8 @@ function OhhwellsBridge() {
|
|
|
25467
27483
|
) : void 0
|
|
25468
27484
|
}
|
|
25469
27485
|
),
|
|
25470
|
-
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && !isRectOutsideClip(toolbarRect, getIframeVisibleClip(parentScrollRef.current)) && /* @__PURE__ */
|
|
25471
|
-
/* @__PURE__ */
|
|
27486
|
+
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && !isRectOutsideClip(toolbarRect, getIframeVisibleClip(parentScrollRef.current)) && /* @__PURE__ */ jsxs23(Fragment10, { children: [
|
|
27487
|
+
/* @__PURE__ */ jsx36(
|
|
25472
27488
|
EditGlowChrome,
|
|
25473
27489
|
{
|
|
25474
27490
|
rect: toolbarRect,
|
|
@@ -25478,7 +27494,7 @@ function OhhwellsBridge() {
|
|
|
25478
27494
|
hideHandle: isItemDragging
|
|
25479
27495
|
}
|
|
25480
27496
|
),
|
|
25481
|
-
/* @__PURE__ */
|
|
27497
|
+
/* @__PURE__ */ jsx36(
|
|
25482
27498
|
FloatingToolbar,
|
|
25483
27499
|
{
|
|
25484
27500
|
rect: toolbarRect,
|
|
@@ -25491,7 +27507,7 @@ function OhhwellsBridge() {
|
|
|
25491
27507
|
}
|
|
25492
27508
|
)
|
|
25493
27509
|
] }),
|
|
25494
|
-
maxBadge && /* @__PURE__ */
|
|
27510
|
+
maxBadge && /* @__PURE__ */ jsxs23(
|
|
25495
27511
|
"div",
|
|
25496
27512
|
{
|
|
25497
27513
|
"data-ohw-max-badge": "",
|
|
@@ -25517,7 +27533,7 @@ function OhhwellsBridge() {
|
|
|
25517
27533
|
]
|
|
25518
27534
|
}
|
|
25519
27535
|
),
|
|
25520
|
-
toggleState && !linkPopover && /* @__PURE__ */
|
|
27536
|
+
toggleState && !linkPopover && /* @__PURE__ */ jsx36(
|
|
25521
27537
|
StateToggle,
|
|
25522
27538
|
{
|
|
25523
27539
|
rect: toggleState.rect,
|
|
@@ -25526,15 +27542,15 @@ function OhhwellsBridge() {
|
|
|
25526
27542
|
onStateChange: handleStateChange
|
|
25527
27543
|
}
|
|
25528
27544
|
),
|
|
25529
|
-
sectionGap && !linkPopover && /* @__PURE__ */
|
|
27545
|
+
sectionGap && !linkPopover && /* @__PURE__ */ jsxs23(
|
|
25530
27546
|
"div",
|
|
25531
27547
|
{
|
|
25532
27548
|
"data-ohw-section-insert-line": "",
|
|
25533
27549
|
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
25534
27550
|
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
25535
27551
|
children: [
|
|
25536
|
-
/* @__PURE__ */
|
|
25537
|
-
/* @__PURE__ */
|
|
27552
|
+
/* @__PURE__ */ jsx36("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } }),
|
|
27553
|
+
/* @__PURE__ */ jsx36(
|
|
25538
27554
|
Badge,
|
|
25539
27555
|
{
|
|
25540
27556
|
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",
|
|
@@ -25551,11 +27567,11 @@ function OhhwellsBridge() {
|
|
|
25551
27567
|
children: "Add Section"
|
|
25552
27568
|
}
|
|
25553
27569
|
),
|
|
25554
|
-
/* @__PURE__ */
|
|
27570
|
+
/* @__PURE__ */ jsx36("div", { className: "flex-1 bg-bridge-primary", style: { height: 3 } })
|
|
25555
27571
|
]
|
|
25556
27572
|
}
|
|
25557
27573
|
),
|
|
25558
|
-
linkPopover && dialogPortalContainer ? /* @__PURE__ */
|
|
27574
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx36(
|
|
25559
27575
|
LinkPopover,
|
|
25560
27576
|
{
|
|
25561
27577
|
panelRef: linkPopoverPanelRef,
|
|
@@ -25572,7 +27588,7 @@ function OhhwellsBridge() {
|
|
|
25572
27588
|
},
|
|
25573
27589
|
linkPopover.key
|
|
25574
27590
|
) : null,
|
|
25575
|
-
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */
|
|
27591
|
+
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ jsx36(
|
|
25576
27592
|
FloatingPanel,
|
|
25577
27593
|
{
|
|
25578
27594
|
open: true,
|
|
@@ -25582,7 +27598,7 @@ function OhhwellsBridge() {
|
|
|
25582
27598
|
onPositionChange: setFloatingPanelPos,
|
|
25583
27599
|
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
25584
27600
|
onClose: closeFloatingPanelOnly,
|
|
25585
|
-
children: /* @__PURE__ */
|
|
27601
|
+
children: /* @__PURE__ */ jsx36(
|
|
25586
27602
|
SocialsDisplayPanel,
|
|
25587
27603
|
{
|
|
25588
27604
|
display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
|
|
@@ -25593,7 +27609,48 @@ function OhhwellsBridge() {
|
|
|
25593
27609
|
}
|
|
25594
27610
|
)
|
|
25595
27611
|
}
|
|
25596
|
-
) : null
|
|
27612
|
+
) : null,
|
|
27613
|
+
floatingPanel && floatingPanel.kind === "button-style" ? (() => {
|
|
27614
|
+
const button = document.querySelector(
|
|
27615
|
+
`[data-ohw-href-key="${CSS.escape(floatingPanel.buttonId)}"]`
|
|
27616
|
+
);
|
|
27617
|
+
if (!button) return null;
|
|
27618
|
+
captureButtonOrigin(button);
|
|
27619
|
+
const tokens = tokensFromButton(button);
|
|
27620
|
+
const current = assignmentFor(button, editContentRef.current, tokens);
|
|
27621
|
+
void buttonStyleTick;
|
|
27622
|
+
return /* @__PURE__ */ jsx36(
|
|
27623
|
+
FloatingPanel,
|
|
27624
|
+
{
|
|
27625
|
+
open: true,
|
|
27626
|
+
title: floatingPanel.title,
|
|
27627
|
+
context: floatingPanel.context,
|
|
27628
|
+
icon: /* @__PURE__ */ jsx36(Brush2, { className: "size-4 shrink-0", "aria-hidden": true }),
|
|
27629
|
+
position: floatingPanelPos,
|
|
27630
|
+
onPositionChange: setFloatingPanelPos,
|
|
27631
|
+
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
27632
|
+
onClose: closeFloatingPanelOnly,
|
|
27633
|
+
bodyClassName: "gap-5",
|
|
27634
|
+
children: /* @__PURE__ */ jsx36(
|
|
27635
|
+
ButtonStylePanel,
|
|
27636
|
+
{
|
|
27637
|
+
variants: tokens.variants,
|
|
27638
|
+
sizes: tokens.sizes,
|
|
27639
|
+
variant: current.variant,
|
|
27640
|
+
size: current.size,
|
|
27641
|
+
slotBackground: previewSlotBackground(button),
|
|
27642
|
+
previewLabel: (button.querySelector(
|
|
27643
|
+
'[data-ohw-editable="text"], [data-ohw-editable="plain"]'
|
|
27644
|
+
)?.textContent ?? button.textContent ?? "Book Now").trim() || "Book Now",
|
|
27645
|
+
onVariant: (variant) => applySelectedButtonStyle({ variant }),
|
|
27646
|
+
onSize: (size) => applySelectedButtonStyle({ size })
|
|
27647
|
+
},
|
|
27648
|
+
floatingPanel.key
|
|
27649
|
+
)
|
|
27650
|
+
},
|
|
27651
|
+
floatingPanel.key
|
|
27652
|
+
);
|
|
27653
|
+
})() : null
|
|
25597
27654
|
] }),
|
|
25598
27655
|
bridgeRoot
|
|
25599
27656
|
) : null
|