@ohhwells/bridge 0.1.139-next.382 → 0.1.139-next.385
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 +675 -641
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +713 -663
- package/dist/index.js.map +1 -1
- package/dist/styles.css +73 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6558,6 +6558,13 @@ function applyIconNameToTree(tree, path, icon) {
|
|
|
6558
6558
|
if (feature) {
|
|
6559
6559
|
return setPricingCardFeatureIcon(tree, Number(feature[1]), Number(feature[2]), icon);
|
|
6560
6560
|
}
|
|
6561
|
+
return rewriteIconSlot(tree, path, `lucide:${icon}`);
|
|
6562
|
+
}
|
|
6563
|
+
function applyIconUploadToTree(tree, path, mediaRef) {
|
|
6564
|
+
if (FEATURE_ICON_PATH.test(path)) return null;
|
|
6565
|
+
return rewriteIconSlot(tree, path, `icon:${mediaRef}`);
|
|
6566
|
+
}
|
|
6567
|
+
function rewriteIconSlot(tree, path, ref) {
|
|
6561
6568
|
const segments = path.split(".");
|
|
6562
6569
|
const slot = segments.pop();
|
|
6563
6570
|
if (!slot || NODE_SEGMENT.test(slot)) return null;
|
|
@@ -6565,8 +6572,8 @@ function applyIconNameToTree(tree, path, icon) {
|
|
|
6565
6572
|
const node = nodeAtPath(next, segments);
|
|
6566
6573
|
if (!node) return null;
|
|
6567
6574
|
const current = node.slots?.[slot];
|
|
6568
|
-
if (typeof current !== "string" || !/^(lucide|simple):/.test(current)) return null;
|
|
6569
|
-
node.slots = { ...node.slots, [slot]:
|
|
6575
|
+
if (typeof current !== "string" || !/^(lucide|simple|icon):/.test(current)) return null;
|
|
6576
|
+
node.slots = { ...node.slots, [slot]: ref };
|
|
6570
6577
|
return next;
|
|
6571
6578
|
}
|
|
6572
6579
|
|
|
@@ -7953,7 +7960,7 @@ function MediaBox({
|
|
|
7953
7960
|
onError
|
|
7954
7961
|
}) {
|
|
7955
7962
|
const url = refValue ? ctx.resolveMedia(refValue) : null;
|
|
7956
|
-
const isIcon = /^(lucide|simple):/.test(refValue);
|
|
7963
|
+
const isIcon = /^(lucide|simple|icon):/.test(refValue);
|
|
7957
7964
|
const aspectRatio = aspect && /^\d+:\d+$/.test(aspect) ? aspect.replace(":", " / ") : void 0;
|
|
7958
7965
|
const editAttrs = ctx.keyFor && editPath && !isIcon ? {
|
|
7959
7966
|
"data-ohw-key": ctx.keyFor(editPath),
|
|
@@ -7961,6 +7968,7 @@ function MediaBox({
|
|
|
7961
7968
|
} : {};
|
|
7962
7969
|
if (isIcon) {
|
|
7963
7970
|
const Icon = refValue.startsWith("lucide:") ? lucideByName(refValue.slice(7)) : null;
|
|
7971
|
+
const uploadedIconUrl = refValue.startsWith("icon:") ? ctx.resolveMedia(refValue.slice(5)) : null;
|
|
7964
7972
|
const iconEditAttrs = ctx.keyFor && editPath && genericImageEdit ? { "data-ohw-key": ctx.keyFor(editPath), "data-ohw-editable": "icon" } : {};
|
|
7965
7973
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
7966
7974
|
"span",
|
|
@@ -7975,7 +7983,7 @@ function MediaBox({
|
|
|
7975
7983
|
justifyContent: "center",
|
|
7976
7984
|
color: ctx.brand.palette.dark
|
|
7977
7985
|
},
|
|
7978
|
-
children: Icon ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { size: 48, color: ctx.brand.palette.dark, strokeWidth: 1.5 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 24 }, children: "\u25C6" })
|
|
7986
|
+
children: uploadedIconUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: uploadedIconUrl, alt: "", style: { width: 48, height: 48, objectFit: "contain" } }) : Icon ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { size: 48, color: ctx.brand.palette.dark, strokeWidth: 1.5 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 24 }, children: "\u25C6" })
|
|
7979
7987
|
}
|
|
7980
7988
|
);
|
|
7981
7989
|
}
|
|
@@ -17960,7 +17968,7 @@ function AiSectionOverlay({
|
|
|
17960
17968
|
|
|
17961
17969
|
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
17962
17970
|
var import_react10 = require("react");
|
|
17963
|
-
var
|
|
17971
|
+
var import_lucide_react9 = require("lucide-react");
|
|
17964
17972
|
|
|
17965
17973
|
// src/lib/ai-media-strip-tree.ts
|
|
17966
17974
|
var MEDIA_STRIP_ITEM_MIN = 1;
|
|
@@ -18074,14 +18082,6 @@ function setMediaStripItemAsset(tree, index, assetId) {
|
|
|
18074
18082
|
return true;
|
|
18075
18083
|
});
|
|
18076
18084
|
}
|
|
18077
|
-
function setMediaStripItemAlt(tree, index, alt) {
|
|
18078
|
-
return withMediaStrip(tree, (block) => {
|
|
18079
|
-
const items = block.items;
|
|
18080
|
-
if (index < 0 || index >= items.length) return false;
|
|
18081
|
-
items[index] = { ...items[index], alt };
|
|
18082
|
-
return true;
|
|
18083
|
-
});
|
|
18084
|
-
}
|
|
18085
18085
|
function setMediaStripItemLink(tree, index, link) {
|
|
18086
18086
|
return withMediaStrip(tree, (block) => {
|
|
18087
18087
|
const items = block.items;
|
|
@@ -18099,11 +18099,117 @@ function setMediaStripItemLink(tree, index, link) {
|
|
|
18099
18099
|
});
|
|
18100
18100
|
}
|
|
18101
18101
|
|
|
18102
|
-
// src/ui/
|
|
18102
|
+
// src/ui/dialog.tsx
|
|
18103
|
+
var React9 = __toESM(require("react"), 1);
|
|
18104
|
+
var import_radix_ui6 = require("radix-ui");
|
|
18105
|
+
var import_lucide_react8 = require("lucide-react");
|
|
18103
18106
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
18104
|
-
|
|
18105
|
-
|
|
18106
|
-
|
|
18107
|
+
function Dialog2({
|
|
18108
|
+
...props
|
|
18109
|
+
}) {
|
|
18110
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_radix_ui6.Dialog.Root, { "data-slot": "dialog", ...props });
|
|
18111
|
+
}
|
|
18112
|
+
function DialogPortal({
|
|
18113
|
+
...props
|
|
18114
|
+
}) {
|
|
18115
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_radix_ui6.Dialog.Portal, { ...props });
|
|
18116
|
+
}
|
|
18117
|
+
function DialogOverlay({
|
|
18118
|
+
className,
|
|
18119
|
+
...props
|
|
18120
|
+
}) {
|
|
18121
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18122
|
+
import_radix_ui6.Dialog.Overlay,
|
|
18123
|
+
{
|
|
18124
|
+
"data-slot": "dialog-overlay",
|
|
18125
|
+
"data-ohw-link-modal-root": "",
|
|
18126
|
+
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
18127
|
+
...props
|
|
18128
|
+
}
|
|
18129
|
+
);
|
|
18130
|
+
}
|
|
18131
|
+
var DialogContent = React9.forwardRef(
|
|
18132
|
+
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
18133
|
+
const positionMode = container ? "absolute" : "fixed";
|
|
18134
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(DialogPortal, { container: container ?? void 0, children: [
|
|
18135
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
18136
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
18137
|
+
import_radix_ui6.Dialog.Content,
|
|
18138
|
+
{
|
|
18139
|
+
ref,
|
|
18140
|
+
"data-slot": "dialog-content",
|
|
18141
|
+
className: cn(
|
|
18142
|
+
positionMode,
|
|
18143
|
+
"left-1/2 top-1/2 z-[2147483647] flex w-full max-w-[448px] -translate-x-1/2 -translate-y-1/2 flex-col overflow-visible",
|
|
18144
|
+
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
18145
|
+
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
18146
|
+
className
|
|
18147
|
+
),
|
|
18148
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
18149
|
+
...props,
|
|
18150
|
+
children: [
|
|
18151
|
+
children,
|
|
18152
|
+
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18153
|
+
import_radix_ui6.Dialog.Close,
|
|
18154
|
+
{
|
|
18155
|
+
type: "button",
|
|
18156
|
+
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
18157
|
+
"aria-label": "Close",
|
|
18158
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react8.X, { size: 16, "aria-hidden": true })
|
|
18159
|
+
}
|
|
18160
|
+
) : null
|
|
18161
|
+
]
|
|
18162
|
+
}
|
|
18163
|
+
)
|
|
18164
|
+
] });
|
|
18165
|
+
}
|
|
18166
|
+
);
|
|
18167
|
+
DialogContent.displayName = import_radix_ui6.Dialog.Content.displayName;
|
|
18168
|
+
function DialogHeader({
|
|
18169
|
+
className,
|
|
18170
|
+
...props
|
|
18171
|
+
}) {
|
|
18172
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
18173
|
+
}
|
|
18174
|
+
function DialogFooter({
|
|
18175
|
+
className,
|
|
18176
|
+
...props
|
|
18177
|
+
}) {
|
|
18178
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18179
|
+
"div",
|
|
18180
|
+
{
|
|
18181
|
+
className: cn("flex items-center justify-end gap-2", className),
|
|
18182
|
+
...props
|
|
18183
|
+
}
|
|
18184
|
+
);
|
|
18185
|
+
}
|
|
18186
|
+
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18187
|
+
import_radix_ui6.Dialog.Title,
|
|
18188
|
+
{
|
|
18189
|
+
ref,
|
|
18190
|
+
className: cn(
|
|
18191
|
+
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
18192
|
+
className
|
|
18193
|
+
),
|
|
18194
|
+
...props
|
|
18195
|
+
}
|
|
18196
|
+
));
|
|
18197
|
+
DialogTitle.displayName = import_radix_ui6.Dialog.Title.displayName;
|
|
18198
|
+
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18199
|
+
import_radix_ui6.Dialog.Description,
|
|
18200
|
+
{
|
|
18201
|
+
ref,
|
|
18202
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
18203
|
+
...props
|
|
18204
|
+
}
|
|
18205
|
+
));
|
|
18206
|
+
DialogDescription.displayName = import_radix_ui6.Dialog.Description.displayName;
|
|
18207
|
+
var DialogClose = import_radix_ui6.Dialog.Close;
|
|
18208
|
+
|
|
18209
|
+
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
18210
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
18211
|
+
var PRIMARY3 = "var(--ohw-primary, #0885FE)";
|
|
18212
|
+
var CHROME_SELECTOR = "[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-link-modal-root], [data-ohw-section-picker], [data-ohw-ai-review], [data-ohw-more-menu]";
|
|
18107
18213
|
function findMediaStripItemElement(sectionId, index) {
|
|
18108
18214
|
const sectionEl = findByInstanceId(sectionId);
|
|
18109
18215
|
if (!sectionEl) return null;
|
|
@@ -18113,14 +18219,35 @@ function findMediaStripItemElement(sectionId, index) {
|
|
|
18113
18219
|
}
|
|
18114
18220
|
return null;
|
|
18115
18221
|
}
|
|
18116
|
-
function
|
|
18117
|
-
|
|
18222
|
+
function itemRefFromTarget(target) {
|
|
18223
|
+
if (!(target instanceof Element)) return null;
|
|
18224
|
+
if (target.closest(CHROME_SELECTOR)) return null;
|
|
18225
|
+
const itemEl = target.closest("[data-ohw-media-strip-item]");
|
|
18226
|
+
if (!itemEl) return null;
|
|
18227
|
+
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
18228
|
+
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
18229
|
+
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
18230
|
+
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
18231
|
+
if (!sectionId || Number.isNaN(index)) return null;
|
|
18232
|
+
return { sectionId, index };
|
|
18233
|
+
}
|
|
18234
|
+
function sameRef(a, b) {
|
|
18235
|
+
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
18236
|
+
}
|
|
18237
|
+
function rectOf(el) {
|
|
18118
18238
|
if (!el) return null;
|
|
18119
18239
|
const r2 = el.getBoundingClientRect();
|
|
18120
18240
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
18121
18241
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
18122
18242
|
}
|
|
18123
|
-
function
|
|
18243
|
+
function readRect2(ref) {
|
|
18244
|
+
return rectOf(ref && findMediaStripItemElement(ref.sectionId, ref.index));
|
|
18245
|
+
}
|
|
18246
|
+
function readStripRect(ref) {
|
|
18247
|
+
const item = ref && findMediaStripItemElement(ref.sectionId, ref.index);
|
|
18248
|
+
return rectOf(item?.closest("[data-ohw-media-strip]") ?? item);
|
|
18249
|
+
}
|
|
18250
|
+
function useLiveItemRect(ref, strip = false) {
|
|
18124
18251
|
const [rect, setRect] = (0, import_react10.useState)(null);
|
|
18125
18252
|
(0, import_react10.useEffect)(() => {
|
|
18126
18253
|
if (!ref) {
|
|
@@ -18128,7 +18255,7 @@ function useLiveItemRect(ref) {
|
|
|
18128
18255
|
return;
|
|
18129
18256
|
}
|
|
18130
18257
|
const update = () => {
|
|
18131
|
-
const next = readRect2(ref);
|
|
18258
|
+
const next = strip ? readStripRect(ref) : readRect2(ref);
|
|
18132
18259
|
setRect(
|
|
18133
18260
|
(prev) => prev && next && prev.top === next.top && prev.left === next.left && prev.width === next.width && prev.height === next.height ? prev : next
|
|
18134
18261
|
);
|
|
@@ -18143,9 +18270,49 @@ function useLiveItemRect(ref) {
|
|
|
18143
18270
|
window.removeEventListener("resize", update);
|
|
18144
18271
|
clearInterval(interval);
|
|
18145
18272
|
};
|
|
18146
|
-
}, [ref?.sectionId, ref?.index]);
|
|
18273
|
+
}, [ref?.sectionId, ref?.index, strip]);
|
|
18147
18274
|
return rect;
|
|
18148
18275
|
}
|
|
18276
|
+
var TOOLBAR_STRIP_GAP = 52;
|
|
18277
|
+
var TOOLBAR_STRIP_GAP_MOBILE = 42;
|
|
18278
|
+
var TOOLBAR_EDGE_MARGIN2 = 4;
|
|
18279
|
+
function StripToolbarSlot({ stripRect, children }) {
|
|
18280
|
+
const slotRef = (0, import_react10.useRef)(null);
|
|
18281
|
+
const [shift, setShift] = (0, import_react10.useState)(0);
|
|
18282
|
+
const centerX = stripRect.left + stripRect.width / 2;
|
|
18283
|
+
(0, import_react10.useLayoutEffect)(() => {
|
|
18284
|
+
const slot = slotRef.current;
|
|
18285
|
+
if (!slot) return;
|
|
18286
|
+
const clamp = () => {
|
|
18287
|
+
const w = slot.offsetWidth;
|
|
18288
|
+
if (w <= 0) return;
|
|
18289
|
+
const half = w / 2;
|
|
18290
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN2 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN2 - half));
|
|
18291
|
+
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
18292
|
+
};
|
|
18293
|
+
clamp();
|
|
18294
|
+
const ro = new ResizeObserver(clamp);
|
|
18295
|
+
ro.observe(slot);
|
|
18296
|
+
return () => ro.disconnect();
|
|
18297
|
+
}, [centerX, children]);
|
|
18298
|
+
const mobile = window.innerWidth <= 480;
|
|
18299
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18300
|
+
"div",
|
|
18301
|
+
{
|
|
18302
|
+
ref: slotRef,
|
|
18303
|
+
"data-ohw-bridge": "",
|
|
18304
|
+
"data-ohw-item-interaction": "",
|
|
18305
|
+
className: "pointer-events-auto fixed",
|
|
18306
|
+
style: {
|
|
18307
|
+
top: stripRect.top - (mobile ? TOOLBAR_STRIP_GAP_MOBILE : TOOLBAR_STRIP_GAP),
|
|
18308
|
+
left: centerX + shift,
|
|
18309
|
+
transform: "translate(-50%, -100%)",
|
|
18310
|
+
zIndex: 2147483645
|
|
18311
|
+
},
|
|
18312
|
+
children
|
|
18313
|
+
}
|
|
18314
|
+
);
|
|
18315
|
+
}
|
|
18149
18316
|
function requestValidateTree(postToParent2, tree) {
|
|
18150
18317
|
return new Promise((resolve) => {
|
|
18151
18318
|
const id = `ai-validate-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
@@ -18182,116 +18349,72 @@ function requestAssetPick(postToParent2) {
|
|
|
18182
18349
|
postToParent2({ type: "ow:asset-pick", id });
|
|
18183
18350
|
});
|
|
18184
18351
|
}
|
|
18185
|
-
function
|
|
18352
|
+
function ToolbarAction({
|
|
18186
18353
|
label,
|
|
18187
18354
|
onClick,
|
|
18188
|
-
disabled,
|
|
18189
|
-
active
|
|
18355
|
+
disabled = false,
|
|
18356
|
+
active = false,
|
|
18357
|
+
children
|
|
18190
18358
|
}) {
|
|
18191
|
-
|
|
18192
|
-
|
|
18193
|
-
{
|
|
18194
|
-
|
|
18195
|
-
|
|
18196
|
-
disabled,
|
|
18197
|
-
style: {
|
|
18198
|
-
height: 28,
|
|
18199
|
-
padding: "0 10px",
|
|
18200
|
-
display: "inline-flex",
|
|
18201
|
-
alignItems: "center",
|
|
18202
|
-
gap: 4,
|
|
18203
|
-
borderRadius: 999,
|
|
18204
|
-
border: "none",
|
|
18205
|
-
cursor: disabled ? "default" : "pointer",
|
|
18206
|
-
background: active ? OHW_BLUE_DARK : "#ffffff",
|
|
18207
|
-
color: active ? "#ffffff" : OHW_BLUE_DARK,
|
|
18208
|
-
opacity: disabled ? 0.4 : 1,
|
|
18209
|
-
fontSize: 12,
|
|
18210
|
-
lineHeight: "16px",
|
|
18211
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18212
|
-
whiteSpace: "nowrap",
|
|
18213
|
-
flex: "0 0 auto"
|
|
18214
|
-
},
|
|
18215
|
-
children: label
|
|
18216
|
-
}
|
|
18217
|
-
);
|
|
18359
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CustomToolbarButton, { type: "button", "aria-label": label, disabled, active, onClick, className: "size-8", children });
|
|
18360
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Tooltip, { children: [
|
|
18361
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "inline-flex", children: button }) : button }),
|
|
18362
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
18363
|
+
] });
|
|
18218
18364
|
}
|
|
18219
|
-
function
|
|
18220
|
-
|
|
18221
|
-
|
|
18222
|
-
|
|
18223
|
-
|
|
18224
|
-
|
|
18225
|
-
|
|
18226
|
-
|
|
18227
|
-
|
|
18228
|
-
|
|
18229
|
-
|
|
18230
|
-
|
|
18231
|
-
|
|
18232
|
-
|
|
18233
|
-
|
|
18234
|
-
|
|
18235
|
-
|
|
18236
|
-
|
|
18237
|
-
|
|
18238
|
-
|
|
18239
|
-
|
|
18240
|
-
|
|
18241
|
-
|
|
18242
|
-
|
|
18243
|
-
|
|
18244
|
-
|
|
18245
|
-
|
|
18246
|
-
|
|
18247
|
-
|
|
18248
|
-
},
|
|
18249
|
-
children: "Alt"
|
|
18250
|
-
}
|
|
18251
|
-
),
|
|
18252
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18253
|
-
"input",
|
|
18365
|
+
function ToolbarSeparator() {
|
|
18366
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
18367
|
+
}
|
|
18368
|
+
function OptionMenu({
|
|
18369
|
+
label,
|
|
18370
|
+
value,
|
|
18371
|
+
options,
|
|
18372
|
+
onChange
|
|
18373
|
+
}) {
|
|
18374
|
+
const current = options.find((o) => o.value === value) ?? options[0];
|
|
18375
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
18376
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-xs text-muted-foreground", children: label }),
|
|
18377
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(DropdownMenu, { modal: false, children: [
|
|
18378
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
18379
|
+
"button",
|
|
18380
|
+
{
|
|
18381
|
+
type: "button",
|
|
18382
|
+
"aria-label": label,
|
|
18383
|
+
className: "inline-flex h-8 min-w-[76px] items-center gap-[7px] rounded-[6px] bg-transparent px-2 text-[13px] font-medium text-foreground transition-colors hover:bg-muted data-[state=open]:bg-muted",
|
|
18384
|
+
children: [
|
|
18385
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "flex-1 text-left", children: current.label }),
|
|
18386
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.ChevronDown, { size: 16, style: { pointerEvents: "none" } })
|
|
18387
|
+
]
|
|
18388
|
+
}
|
|
18389
|
+
) }),
|
|
18390
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[132px] min-w-[132px] p-1", children: options.map((option) => {
|
|
18391
|
+
const selected = option.value === value;
|
|
18392
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
18393
|
+
DropdownMenuItem,
|
|
18254
18394
|
{
|
|
18255
|
-
|
|
18256
|
-
|
|
18257
|
-
|
|
18258
|
-
|
|
18259
|
-
|
|
18260
|
-
|
|
18261
|
-
|
|
18262
|
-
|
|
18263
|
-
|
|
18264
|
-
|
|
18265
|
-
|
|
18266
|
-
|
|
18267
|
-
|
|
18268
|
-
|
|
18269
|
-
"aria-label": "Image alt text",
|
|
18270
|
-
style: {
|
|
18271
|
-
flex: 1,
|
|
18272
|
-
minWidth: 0,
|
|
18273
|
-
border: "none",
|
|
18274
|
-
outline: "none",
|
|
18275
|
-
background: "transparent",
|
|
18276
|
-
fontSize: 12,
|
|
18277
|
-
lineHeight: "16px",
|
|
18278
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18279
|
-
color: "#1f2937"
|
|
18280
|
-
}
|
|
18281
|
-
}
|
|
18282
|
-
)
|
|
18283
|
-
]
|
|
18284
|
-
}
|
|
18285
|
-
);
|
|
18395
|
+
role: "menuitemradio",
|
|
18396
|
+
"aria-checked": selected,
|
|
18397
|
+
onSelect: () => onChange(option.value),
|
|
18398
|
+
className: cn("grid grid-cols-[1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
18399
|
+
children: [
|
|
18400
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { children: option.label }),
|
|
18401
|
+
selected && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.Check, { size: 16, className: "text-bridge-primary" })
|
|
18402
|
+
]
|
|
18403
|
+
},
|
|
18404
|
+
option.value
|
|
18405
|
+
);
|
|
18406
|
+
}) })
|
|
18407
|
+
] })
|
|
18408
|
+
] });
|
|
18286
18409
|
}
|
|
18287
18410
|
var VARIANTS = [
|
|
18288
18411
|
{ value: "logos", label: "Logos" },
|
|
18289
18412
|
{ value: "reel", label: "Reel" }
|
|
18290
18413
|
];
|
|
18291
18414
|
var ALIGNS = [
|
|
18292
|
-
{ value: "left", label: "
|
|
18293
|
-
{ value: "center", label: "
|
|
18294
|
-
{ value: "right", label: "
|
|
18415
|
+
{ value: "left", label: "Align left", Icon: import_lucide_react9.AlignLeft },
|
|
18416
|
+
{ value: "center", label: "Align center", Icon: import_lucide_react9.AlignCenter },
|
|
18417
|
+
{ value: "right", label: "Align right", Icon: import_lucide_react9.AlignRight }
|
|
18295
18418
|
];
|
|
18296
18419
|
var HOVERS = [
|
|
18297
18420
|
{ value: "none", label: "None" },
|
|
@@ -18299,104 +18422,104 @@ var HOVERS = [
|
|
|
18299
18422
|
{ value: "zoom", label: "Zoom" },
|
|
18300
18423
|
{ value: "fade", label: "Fade" }
|
|
18301
18424
|
];
|
|
18302
|
-
var TREATMENTS = [
|
|
18303
|
-
{ value: "color", label: "Color" },
|
|
18304
|
-
{ value: "grayscale", label: "Grayscale" }
|
|
18305
|
-
];
|
|
18306
18425
|
var HTTP_URL_RE = /^https?:\/\/\S+$/i;
|
|
18307
|
-
function
|
|
18308
|
-
|
|
18426
|
+
function LinkModal({
|
|
18427
|
+
href,
|
|
18428
|
+
linkTarget,
|
|
18429
|
+
onClose,
|
|
18430
|
+
onSave
|
|
18431
|
+
}) {
|
|
18432
|
+
const [draft, setDraft] = (0, import_react10.useState)(href);
|
|
18433
|
+
const [newTab, setNewTab] = (0, import_react10.useState)(linkTarget !== "same-tab");
|
|
18309
18434
|
const [invalid, setInvalid] = (0, import_react10.useState)(false);
|
|
18310
|
-
|
|
18311
|
-
setDraft(value);
|
|
18312
|
-
setInvalid(false);
|
|
18313
|
-
}, [value]);
|
|
18314
|
-
const commit = () => {
|
|
18435
|
+
const save = () => {
|
|
18315
18436
|
const next = draft.trim();
|
|
18316
|
-
if (next
|
|
18317
|
-
|
|
18318
|
-
|
|
18319
|
-
onCommit(next);
|
|
18320
|
-
};
|
|
18321
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
18322
|
-
"div",
|
|
18323
|
-
{
|
|
18324
|
-
style: {
|
|
18325
|
-
display: "flex",
|
|
18326
|
-
alignItems: "center",
|
|
18327
|
-
gap: 6,
|
|
18328
|
-
height: 28,
|
|
18329
|
-
padding: "0 12px",
|
|
18330
|
-
borderRadius: 999,
|
|
18331
|
-
background: "#ffffff",
|
|
18332
|
-
width: "100%",
|
|
18333
|
-
maxWidth: 260,
|
|
18334
|
-
boxSizing: "border-box",
|
|
18335
|
-
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
18336
|
-
},
|
|
18337
|
-
children: [
|
|
18338
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18339
|
-
"span",
|
|
18340
|
-
{
|
|
18341
|
-
style: {
|
|
18342
|
-
flex: "0 0 auto",
|
|
18343
|
-
color: OHW_BLUE_DARK,
|
|
18344
|
-
fontSize: 10,
|
|
18345
|
-
fontWeight: 700,
|
|
18346
|
-
textTransform: "uppercase",
|
|
18347
|
-
letterSpacing: 0.4
|
|
18348
|
-
},
|
|
18349
|
-
children: "Link"
|
|
18350
|
-
}
|
|
18351
|
-
),
|
|
18352
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18353
|
-
"input",
|
|
18354
|
-
{
|
|
18355
|
-
type: "text",
|
|
18356
|
-
inputMode: "url",
|
|
18357
|
-
value: draft,
|
|
18358
|
-
onChange: (e) => setDraft(e.target.value),
|
|
18359
|
-
onBlur: commit,
|
|
18360
|
-
onKeyDown: (e) => {
|
|
18361
|
-
if (e.key === "Enter") e.currentTarget.blur();
|
|
18362
|
-
if (e.key === "Escape") {
|
|
18363
|
-
setDraft(value);
|
|
18364
|
-
setInvalid(false);
|
|
18365
|
-
e.currentTarget.blur();
|
|
18366
|
-
}
|
|
18367
|
-
},
|
|
18368
|
-
placeholder: "https://example.com",
|
|
18369
|
-
"aria-label": "Image link URL",
|
|
18370
|
-
"aria-invalid": invalid,
|
|
18371
|
-
style: {
|
|
18372
|
-
flex: 1,
|
|
18373
|
-
minWidth: 0,
|
|
18374
|
-
border: "none",
|
|
18375
|
-
outline: "none",
|
|
18376
|
-
background: "transparent",
|
|
18377
|
-
fontSize: 12,
|
|
18378
|
-
lineHeight: "16px",
|
|
18379
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18380
|
-
color: "#1f2937"
|
|
18381
|
-
}
|
|
18382
|
-
}
|
|
18383
|
-
)
|
|
18384
|
-
]
|
|
18437
|
+
if (next && !HTTP_URL_RE.test(next)) {
|
|
18438
|
+
setInvalid(true);
|
|
18439
|
+
return;
|
|
18385
18440
|
}
|
|
18386
|
-
|
|
18441
|
+
onSave(next, newTab ? "new-tab" : "same-tab");
|
|
18442
|
+
onClose();
|
|
18443
|
+
};
|
|
18444
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Dialog2, { open: true, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(DialogContent, { "data-ohw-link-modal-root": "", className: "max-w-[400px] gap-4 p-5", children: [
|
|
18445
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DialogHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DialogTitle, { className: "text-base", children: "Image link" }) }),
|
|
18446
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex flex-col gap-3", children: [
|
|
18447
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18448
|
+
"input",
|
|
18449
|
+
{
|
|
18450
|
+
autoFocus: true,
|
|
18451
|
+
type: "text",
|
|
18452
|
+
inputMode: "url",
|
|
18453
|
+
value: draft,
|
|
18454
|
+
onChange: (e) => {
|
|
18455
|
+
setDraft(e.target.value);
|
|
18456
|
+
setInvalid(false);
|
|
18457
|
+
},
|
|
18458
|
+
onKeyDown: (e) => {
|
|
18459
|
+
if (e.key === "Enter") save();
|
|
18460
|
+
},
|
|
18461
|
+
placeholder: "https://example.com",
|
|
18462
|
+
"aria-label": "Image link URL",
|
|
18463
|
+
"aria-invalid": invalid,
|
|
18464
|
+
className: cn(
|
|
18465
|
+
"h-9 w-full rounded-[6px] border border-border bg-background px-3 text-[13px] text-foreground outline-none placeholder:text-muted-foreground/70 focus:border-bridge-primary",
|
|
18466
|
+
invalid && "border-destructive focus:border-destructive"
|
|
18467
|
+
)
|
|
18468
|
+
}
|
|
18469
|
+
),
|
|
18470
|
+
invalid && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-xs text-destructive", children: "Enter a full URL starting with http:// or https://" }),
|
|
18471
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("label", { className: "flex items-center gap-2 text-[13px] text-foreground", children: [
|
|
18472
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("input", { type: "checkbox", checked: newTab, onChange: (e) => setNewTab(e.target.checked) }),
|
|
18473
|
+
"Open in new tab"
|
|
18474
|
+
] })
|
|
18475
|
+
] }),
|
|
18476
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(DialogFooter, { children: [
|
|
18477
|
+
href && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18478
|
+
"button",
|
|
18479
|
+
{
|
|
18480
|
+
type: "button",
|
|
18481
|
+
onClick: () => {
|
|
18482
|
+
onSave("", "new-tab");
|
|
18483
|
+
onClose();
|
|
18484
|
+
},
|
|
18485
|
+
className: "mr-auto rounded-[6px] px-3 py-2 text-[13px] font-medium text-destructive transition-colors hover:bg-muted",
|
|
18486
|
+
children: "Remove link"
|
|
18487
|
+
}
|
|
18488
|
+
),
|
|
18489
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18490
|
+
"button",
|
|
18491
|
+
{
|
|
18492
|
+
type: "button",
|
|
18493
|
+
onClick: onClose,
|
|
18494
|
+
className: "rounded-[6px] px-3 py-2 text-[13px] font-medium text-foreground transition-colors hover:bg-muted",
|
|
18495
|
+
children: "Cancel"
|
|
18496
|
+
}
|
|
18497
|
+
),
|
|
18498
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18499
|
+
"button",
|
|
18500
|
+
{
|
|
18501
|
+
type: "button",
|
|
18502
|
+
onClick: save,
|
|
18503
|
+
className: "rounded-[6px] bg-bridge-primary px-3 py-2 text-[13px] font-medium text-primary-foreground transition-opacity hover:opacity-90",
|
|
18504
|
+
children: "Save"
|
|
18505
|
+
}
|
|
18506
|
+
)
|
|
18507
|
+
] })
|
|
18508
|
+
] }) });
|
|
18387
18509
|
}
|
|
18388
18510
|
function MediaStripToolbar({
|
|
18389
18511
|
entry,
|
|
18390
18512
|
index,
|
|
18391
18513
|
pending,
|
|
18392
18514
|
error,
|
|
18515
|
+
itemEditOn,
|
|
18516
|
+
onToggleItemEdit,
|
|
18393
18517
|
onSetVariant,
|
|
18394
18518
|
onSetAlign,
|
|
18395
18519
|
onSetHover,
|
|
18396
18520
|
onSetTreatment,
|
|
18397
18521
|
onResize,
|
|
18398
|
-
|
|
18399
|
-
onSetLink,
|
|
18522
|
+
onOpenLink,
|
|
18400
18523
|
onAddItem,
|
|
18401
18524
|
onRemoveItem,
|
|
18402
18525
|
onChangeImage,
|
|
@@ -18405,81 +18528,102 @@ function MediaStripToolbar({
|
|
|
18405
18528
|
}) {
|
|
18406
18529
|
const items = mediaStripItems(entry.tree);
|
|
18407
18530
|
const itemCount = items.length;
|
|
18408
|
-
const currentAlt = items[index]?.alt ?? "";
|
|
18409
|
-
const currentHref = items[index]?.href ?? "";
|
|
18410
|
-
const currentTarget = items[index]?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
18411
18531
|
const slots = findMediaStripSlots(entry.tree);
|
|
18412
18532
|
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
18413
18533
|
const align = slots?.align === "left" || slots?.align === "right" ? slots.align : "center";
|
|
18414
18534
|
const hover = slots?.hover === "none" || slots?.hover === "lift" || slots?.hover === "zoom" || slots?.hover === "fade" ? slots.hover : "lift";
|
|
18415
18535
|
const treatment = slots?.treatment === "color" || slots?.treatment === "grayscale" ? slots.treatment : variant === "logos" ? "grayscale" : "color";
|
|
18416
18536
|
const sizeValue = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
18417
|
-
const
|
|
18418
|
-
const
|
|
18419
|
-
|
|
18420
|
-
gap: 6,
|
|
18421
|
-
flexWrap: "nowrap",
|
|
18422
|
-
justifyContent: "center",
|
|
18423
|
-
overflowX: "auto",
|
|
18424
|
-
WebkitOverflowScrolling: "touch",
|
|
18425
|
-
width: "100%",
|
|
18426
|
-
scrollbarWidth: "none"
|
|
18427
|
-
} : { display: "flex", gap: 6, flexWrap: "nowrap", justifyContent: "center" };
|
|
18428
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
18537
|
+
const mobile = window.innerWidth <= 480;
|
|
18538
|
+
const gatedLabel = (label) => itemEditOn ? label : "Turn on the star to edit this image";
|
|
18539
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
18429
18540
|
"div",
|
|
18430
18541
|
{
|
|
18431
18542
|
"data-ohw-bridge": "",
|
|
18432
18543
|
"data-ohw-toolbar": "",
|
|
18433
18544
|
onMouseDown: (e) => e.stopPropagation(),
|
|
18434
|
-
|
|
18435
|
-
|
|
18436
|
-
flexDirection: "column",
|
|
18437
|
-
gap: 6,
|
|
18438
|
-
alignItems: "center",
|
|
18439
|
-
background: OHW_BLUE,
|
|
18440
|
-
padding: 8,
|
|
18441
|
-
borderRadius: 12,
|
|
18442
|
-
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
18443
|
-
pointerEvents: pending ? "none" : "auto",
|
|
18444
|
-
opacity: pending ? 0.6 : 1,
|
|
18445
|
-
maxWidth: isMobile ? "calc(100vw - 24px)" : "none"
|
|
18446
|
-
},
|
|
18545
|
+
className: cn("flex flex-col items-center gap-1.5 font-sans", pending && "pointer-events-none opacity-60"),
|
|
18546
|
+
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
18447
18547
|
children: [
|
|
18448
|
-
/* @__PURE__ */ (0,
|
|
18449
|
-
|
|
18450
|
-
|
|
18451
|
-
|
|
18452
|
-
|
|
18453
|
-
|
|
18454
|
-
|
|
18455
|
-
|
|
18456
|
-
|
|
18457
|
-
|
|
18458
|
-
|
|
18459
|
-
|
|
18460
|
-
|
|
18461
|
-
|
|
18462
|
-
|
|
18463
|
-
|
|
18464
|
-
|
|
18465
|
-
|
|
18466
|
-
|
|
18467
|
-
|
|
18468
|
-
|
|
18469
|
-
|
|
18470
|
-
|
|
18471
|
-
|
|
18472
|
-
|
|
18473
|
-
|
|
18474
|
-
|
|
18475
|
-
|
|
18476
|
-
|
|
18477
|
-
|
|
18478
|
-
|
|
18479
|
-
|
|
18548
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
18549
|
+
"div",
|
|
18550
|
+
{
|
|
18551
|
+
className: cn(
|
|
18552
|
+
"flex items-center gap-1 rounded-[10px] border border-border bg-background p-1 whitespace-nowrap",
|
|
18553
|
+
"shadow-[0px_10px_15px_-3px_rgba(0,0,0,0.1),0px_4px_6px_-4px_rgba(0,0,0,0.1)]",
|
|
18554
|
+
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
18555
|
+
),
|
|
18556
|
+
children: [
|
|
18557
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Tooltip, { children: [
|
|
18558
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18559
|
+
CustomToolbarButton,
|
|
18560
|
+
{
|
|
18561
|
+
type: "button",
|
|
18562
|
+
"aria-label": itemEditOn ? "Done editing this image" : "Edit this image",
|
|
18563
|
+
"aria-pressed": itemEditOn,
|
|
18564
|
+
onClick: onToggleItemEdit,
|
|
18565
|
+
className: "group size-8",
|
|
18566
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18567
|
+
import_lucide_react9.Star,
|
|
18568
|
+
{
|
|
18569
|
+
size: 16,
|
|
18570
|
+
fill: "currentColor",
|
|
18571
|
+
strokeWidth: 0,
|
|
18572
|
+
className: cn(
|
|
18573
|
+
"transition-colors",
|
|
18574
|
+
itemEditOn ? "text-[#f59e0b] group-hover:text-[#d97706]" : "text-[#d6d3d1] group-hover:text-[#fbbf24]"
|
|
18575
|
+
),
|
|
18576
|
+
style: { pointerEvents: "none" }
|
|
18577
|
+
}
|
|
18578
|
+
)
|
|
18579
|
+
}
|
|
18580
|
+
) }),
|
|
18581
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: itemEditOn ? "Done editing this image" : "Edit this image" })
|
|
18582
|
+
] }),
|
|
18583
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarSeparator, {}),
|
|
18584
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarAction, { label: gatedLabel("Change image"), onClick: onChangeImage, disabled: !itemEditOn, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.Image, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
18585
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarAction, { label: gatedLabel("Link"), onClick: onOpenLink, disabled: !itemEditOn, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.Link, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
18586
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarAction, { label: gatedLabel("Move left"), onClick: onMoveLeft, disabled: !itemEditOn || index <= 0, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.ArrowLeft, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
18587
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18588
|
+
ToolbarAction,
|
|
18589
|
+
{
|
|
18590
|
+
label: gatedLabel("Move right"),
|
|
18591
|
+
onClick: onMoveRight,
|
|
18592
|
+
disabled: !itemEditOn || index >= itemCount - 1,
|
|
18593
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.ArrowRight, { size: 16, style: { pointerEvents: "none" } })
|
|
18594
|
+
}
|
|
18595
|
+
),
|
|
18596
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarAction, { label: gatedLabel("Remove image"), onClick: onRemoveItem, disabled: !itemEditOn || itemCount <= 1, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.ImageMinus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
18597
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarSeparator, {}),
|
|
18598
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(OptionMenu, { label: "Layout", value: variant, options: VARIANTS, onChange: onSetVariant }),
|
|
18599
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(OptionMenu, { label: "Hover", value: hover, options: HOVERS, onChange: onSetHover }),
|
|
18600
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18601
|
+
ToolbarAction,
|
|
18602
|
+
{
|
|
18603
|
+
label: treatment === "grayscale" ? "Show in color" : "Show grayscale",
|
|
18604
|
+
active: treatment === "grayscale",
|
|
18605
|
+
onClick: () => onSetTreatment(treatment === "grayscale" ? "color" : "grayscale"),
|
|
18606
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.Palette, { size: 16, style: { pointerEvents: "none" } })
|
|
18607
|
+
}
|
|
18608
|
+
),
|
|
18609
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarSeparator, {}),
|
|
18610
|
+
ALIGNS.map(({ value, label, Icon }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarAction, { label, active: align === value, onClick: () => onSetAlign(value), children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Icon, { size: 16, style: { pointerEvents: "none" } }) }, value)),
|
|
18611
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarSeparator, {}),
|
|
18612
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarAction, { label: "Smaller", onClick: () => onResize(-8), children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.Minus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
18613
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "min-w-[40px] text-center text-xs tabular-nums text-muted-foreground", children: [
|
|
18614
|
+
sizeValue,
|
|
18615
|
+
"px"
|
|
18616
|
+
] }),
|
|
18617
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarAction, { label: "Larger", onClick: () => onResize(8), children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.Plus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
18618
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarSeparator, {}),
|
|
18619
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarAction, { label: "Add image", onClick: onAddItem, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.ImagePlus, { size: 16, style: { pointerEvents: "none" } }) })
|
|
18620
|
+
]
|
|
18621
|
+
}
|
|
18622
|
+
),
|
|
18623
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "max-w-[260px] rounded-md bg-background px-2 py-1 text-center text-[11px] text-destructive shadow-sm", children: error })
|
|
18480
18624
|
]
|
|
18481
18625
|
}
|
|
18482
|
-
);
|
|
18626
|
+
) });
|
|
18483
18627
|
}
|
|
18484
18628
|
function findMediaStripSlots(tree) {
|
|
18485
18629
|
const stack = tree.rows.flatMap((row) => row.blocks);
|
|
@@ -18498,31 +18642,23 @@ function AiMediaStripOverlay({
|
|
|
18498
18642
|
}) {
|
|
18499
18643
|
const [hover, setHover] = (0, import_react10.useState)(null);
|
|
18500
18644
|
const [active, setActive] = (0, import_react10.useState)(null);
|
|
18645
|
+
const [itemEditOn, setItemEditOn] = (0, import_react10.useState)(false);
|
|
18646
|
+
const [linkOpen, setLinkOpen] = (0, import_react10.useState)(false);
|
|
18501
18647
|
const [pending, setPending] = (0, import_react10.useState)(false);
|
|
18502
18648
|
const [error, setError] = (0, import_react10.useState)(null);
|
|
18503
18649
|
const activeRef = (0, import_react10.useRef)(null);
|
|
18504
18650
|
activeRef.current = active;
|
|
18651
|
+
const linkOpenRef = (0, import_react10.useRef)(false);
|
|
18652
|
+
linkOpenRef.current = linkOpen;
|
|
18505
18653
|
(0, import_react10.useEffect)(() => {
|
|
18506
18654
|
const onMove = (e) => {
|
|
18655
|
+
const ref = itemRefFromTarget(e.target);
|
|
18507
18656
|
const t = e.target;
|
|
18508
|
-
|
|
18509
|
-
|
|
18510
|
-
|
|
18511
|
-
|
|
18512
|
-
|
|
18513
|
-
if (!itemEl) {
|
|
18514
|
-
setHover(null);
|
|
18515
|
-
return;
|
|
18516
|
-
}
|
|
18517
|
-
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
18518
|
-
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
18519
|
-
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
18520
|
-
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
18521
|
-
if (!sectionId || Number.isNaN(index)) {
|
|
18522
|
-
setHover(null);
|
|
18523
|
-
return;
|
|
18524
|
-
}
|
|
18525
|
-
setHover({ sectionId, index });
|
|
18657
|
+
const overEditable = Boolean(t?.closest?.("[data-ohw-editable]"));
|
|
18658
|
+
setHover((prev) => {
|
|
18659
|
+
const next = ref && !overEditable ? ref : null;
|
|
18660
|
+
return sameRef(prev, next) ? prev : next;
|
|
18661
|
+
});
|
|
18526
18662
|
};
|
|
18527
18663
|
const onLeave = () => setHover(null);
|
|
18528
18664
|
document.addEventListener("mousemove", onMove, { passive: true });
|
|
@@ -18534,23 +18670,25 @@ function AiMediaStripOverlay({
|
|
|
18534
18670
|
}, []);
|
|
18535
18671
|
(0, import_react10.useEffect)(() => {
|
|
18536
18672
|
const onClick = (e) => {
|
|
18537
|
-
const current = activeRef.current;
|
|
18538
|
-
if (!current) return;
|
|
18539
18673
|
const t = e.target;
|
|
18540
|
-
if (!(t instanceof
|
|
18541
|
-
if (t.closest(
|
|
18542
|
-
const
|
|
18543
|
-
if (
|
|
18544
|
-
|
|
18674
|
+
if (!(t instanceof Element)) return;
|
|
18675
|
+
if (t.closest(CHROME_SELECTOR)) return;
|
|
18676
|
+
const ref = itemRefFromTarget(t);
|
|
18677
|
+
if (sameRef(activeRef.current, ref)) return;
|
|
18678
|
+
if (ref) clearInteractionChromeRef.current();
|
|
18679
|
+
setItemEditOn(false);
|
|
18545
18680
|
setError(null);
|
|
18681
|
+
setActive(ref);
|
|
18546
18682
|
};
|
|
18547
18683
|
document.addEventListener("click", onClick, true);
|
|
18548
18684
|
return () => document.removeEventListener("click", onClick, true);
|
|
18549
|
-
}, []);
|
|
18685
|
+
}, [clearInteractionChromeRef]);
|
|
18550
18686
|
(0, import_react10.useEffect)(() => {
|
|
18551
18687
|
const onBlur = () => {
|
|
18552
18688
|
if (!activeRef.current) return;
|
|
18553
18689
|
setActive(null);
|
|
18690
|
+
setItemEditOn(false);
|
|
18691
|
+
setLinkOpen(false);
|
|
18554
18692
|
setError(null);
|
|
18555
18693
|
};
|
|
18556
18694
|
window.addEventListener("blur", onBlur);
|
|
@@ -18560,7 +18698,10 @@ function AiMediaStripOverlay({
|
|
|
18560
18698
|
const onKeyDown = (e) => {
|
|
18561
18699
|
if (e.key !== "Escape") return;
|
|
18562
18700
|
if (!activeRef.current) return;
|
|
18701
|
+
if (linkOpenRef.current) return;
|
|
18702
|
+
if (document.querySelector('[data-ohw-more-menu][data-state="open"]')) return;
|
|
18563
18703
|
setActive(null);
|
|
18704
|
+
setItemEditOn(false);
|
|
18564
18705
|
setError(null);
|
|
18565
18706
|
};
|
|
18566
18707
|
document.addEventListener("keydown", onKeyDown);
|
|
@@ -18594,137 +18735,133 @@ function AiMediaStripOverlay({
|
|
|
18594
18735
|
tree: nextTree,
|
|
18595
18736
|
label: entry.label,
|
|
18596
18737
|
media: extraMedia ? { ...entry.media, ...extraMedia } : entry.media,
|
|
18597
|
-
...entry.brand ? { brand: entry.brand } : {}
|
|
18738
|
+
...entry.brand ? { brand: entry.brand } : {},
|
|
18739
|
+
// The user is already looking at the strip they just edited — recentering the viewport
|
|
18740
|
+
// on every edit reads as the section jumping around.
|
|
18741
|
+
skipScrollIntoView: true
|
|
18598
18742
|
});
|
|
18599
18743
|
return true;
|
|
18600
18744
|
},
|
|
18601
18745
|
[findEntry, postToParent2, applyTreeLocalRef]
|
|
18602
18746
|
);
|
|
18603
18747
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
18604
|
-
const hoverHandleRect = useLiveItemRect(!active && hover ? hover : null);
|
|
18605
18748
|
const activeItemRect = useLiveItemRect(active);
|
|
18606
|
-
const
|
|
18607
|
-
const
|
|
18608
|
-
|
|
18609
|
-
|
|
18610
|
-
|
|
18611
|
-
|
|
18612
|
-
|
|
18613
|
-
|
|
18614
|
-
|
|
18615
|
-
|
|
18616
|
-
|
|
18617
|
-
|
|
18618
|
-
|
|
18619
|
-
|
|
18620
|
-
|
|
18621
|
-
|
|
18622
|
-
|
|
18623
|
-
|
|
18624
|
-
|
|
18625
|
-
|
|
18626
|
-
|
|
18627
|
-
|
|
18628
|
-
|
|
18629
|
-
|
|
18630
|
-
|
|
18631
|
-
|
|
18632
|
-
|
|
18633
|
-
|
|
18634
|
-
|
|
18635
|
-
|
|
18636
|
-
|
|
18637
|
-
|
|
18638
|
-
|
|
18639
|
-
|
|
18640
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18641
|
-
ItemInteractionLayer,
|
|
18642
|
-
{
|
|
18643
|
-
rect: activeItemRect,
|
|
18644
|
-
state: toolbarState,
|
|
18645
|
-
toolbar: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18646
|
-
MediaStripToolbar,
|
|
18647
|
-
{
|
|
18648
|
-
entry: activeEntry,
|
|
18649
|
-
index: active.index,
|
|
18650
|
-
pending,
|
|
18651
|
-
error,
|
|
18652
|
-
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
18653
|
-
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
18654
|
-
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
18655
|
-
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
18656
|
-
onResize: (delta) => {
|
|
18657
|
-
const slots = findMediaStripSlots(activeEntry.tree);
|
|
18658
|
-
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
18659
|
-
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
18660
|
-
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
18661
|
-
},
|
|
18662
|
-
onSetAlt: (alt) => {
|
|
18663
|
-
void runMutation(active.sectionId, (tree) => setMediaStripItemAlt(tree, active.index, alt));
|
|
18664
|
-
},
|
|
18665
|
-
onSetLink: (href, linkTarget) => {
|
|
18749
|
+
const activeStripRect = useLiveItemRect(active, true);
|
|
18750
|
+
const hoverRect = useLiveItemRect(hover && !sameRef(hover, active) ? hover : null);
|
|
18751
|
+
const activeItems = activeEntry ? mediaStripItems(activeEntry.tree) : [];
|
|
18752
|
+
const activeItem = active ? activeItems[active.index] : void 0;
|
|
18753
|
+
const activeHref = activeItem?.href ?? "";
|
|
18754
|
+
const activeTarget = activeItem?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
18755
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
|
|
18756
|
+
hoverRect && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
18757
|
+
activeItemRect && activeStripRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
|
|
18758
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ItemInteractionLayer, { rect: activeItemRect, state: "active-top" }),
|
|
18759
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(StripToolbarSlot, { stripRect: activeStripRect, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18760
|
+
MediaStripToolbar,
|
|
18761
|
+
{
|
|
18762
|
+
entry: activeEntry,
|
|
18763
|
+
index: active.index,
|
|
18764
|
+
pending,
|
|
18765
|
+
error,
|
|
18766
|
+
itemEditOn,
|
|
18767
|
+
onToggleItemEdit: () => setItemEditOn((on) => !on),
|
|
18768
|
+
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
18769
|
+
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
18770
|
+
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
18771
|
+
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
18772
|
+
onResize: (delta) => {
|
|
18773
|
+
const slots = findMediaStripSlots(activeEntry.tree);
|
|
18774
|
+
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
18775
|
+
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
18776
|
+
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
18777
|
+
},
|
|
18778
|
+
onOpenLink: () => setLinkOpen(true),
|
|
18779
|
+
onAddItem: () => {
|
|
18780
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
18781
|
+
if (!picked) return;
|
|
18782
|
+
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
18666
18783
|
void runMutation(
|
|
18667
18784
|
active.sectionId,
|
|
18668
|
-
(tree) =>
|
|
18669
|
-
|
|
18670
|
-
|
|
18671
|
-
|
|
18672
|
-
void requestAssetPick(postToParent2).then((picked) => {
|
|
18673
|
-
if (!picked) return;
|
|
18674
|
-
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
18675
|
-
void runMutation(
|
|
18676
|
-
active.sectionId,
|
|
18677
|
-
(tree) => addMediaStripItem(tree, item, active.index),
|
|
18678
|
-
{ [picked.assetId]: picked.url }
|
|
18679
|
-
).then((applied) => {
|
|
18680
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
18681
|
-
});
|
|
18785
|
+
(tree) => addMediaStripItem(tree, item, active.index),
|
|
18786
|
+
{ [picked.assetId]: picked.url }
|
|
18787
|
+
).then((applied) => {
|
|
18788
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
18682
18789
|
});
|
|
18683
|
-
}
|
|
18684
|
-
|
|
18685
|
-
|
|
18686
|
-
|
|
18687
|
-
|
|
18688
|
-
|
|
18689
|
-
|
|
18690
|
-
|
|
18691
|
-
|
|
18692
|
-
});
|
|
18693
|
-
},
|
|
18694
|
-
onRemoveItem: () => {
|
|
18695
|
-
void runMutation(active.sectionId, (tree) => removeMediaStripItem(tree, active.index)).then(
|
|
18696
|
-
(applied) => {
|
|
18697
|
-
if (applied) setActive(null);
|
|
18698
|
-
}
|
|
18699
|
-
);
|
|
18700
|
-
},
|
|
18701
|
-
onMoveLeft: () => {
|
|
18702
|
-
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
18703
|
-
(applied) => {
|
|
18704
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
18705
|
-
}
|
|
18706
|
-
);
|
|
18707
|
-
},
|
|
18708
|
-
onMoveRight: () => {
|
|
18709
|
-
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
18710
|
-
(applied) => {
|
|
18711
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
18712
|
-
}
|
|
18790
|
+
});
|
|
18791
|
+
},
|
|
18792
|
+
onChangeImage: () => {
|
|
18793
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
18794
|
+
if (!picked) return;
|
|
18795
|
+
void runMutation(
|
|
18796
|
+
active.sectionId,
|
|
18797
|
+
(tree) => setMediaStripItemAsset(tree, active.index, picked.assetId),
|
|
18798
|
+
{ [picked.assetId]: picked.url }
|
|
18713
18799
|
);
|
|
18714
|
-
}
|
|
18800
|
+
});
|
|
18801
|
+
},
|
|
18802
|
+
onRemoveItem: () => {
|
|
18803
|
+
void runMutation(active.sectionId, (tree) => removeMediaStripItem(tree, active.index)).then(
|
|
18804
|
+
(applied) => {
|
|
18805
|
+
if (applied) setActive(null);
|
|
18806
|
+
}
|
|
18807
|
+
);
|
|
18808
|
+
},
|
|
18809
|
+
onMoveLeft: () => {
|
|
18810
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
18811
|
+
(applied) => {
|
|
18812
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
18813
|
+
}
|
|
18814
|
+
);
|
|
18815
|
+
},
|
|
18816
|
+
onMoveRight: () => {
|
|
18817
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
18818
|
+
(applied) => {
|
|
18819
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
18820
|
+
}
|
|
18821
|
+
);
|
|
18715
18822
|
}
|
|
18716
|
-
|
|
18717
|
-
}
|
|
18718
|
-
|
|
18823
|
+
}
|
|
18824
|
+
) }),
|
|
18825
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18826
|
+
"div",
|
|
18827
|
+
{
|
|
18828
|
+
"data-ohw-bridge": "",
|
|
18829
|
+
"data-ohw-item-interaction": "",
|
|
18830
|
+
"aria-hidden": true,
|
|
18831
|
+
className: "pointer-events-none fixed rounded-[4px] px-[7px] py-[3px] font-sans text-[11px] font-medium leading-none text-primary-foreground whitespace-nowrap",
|
|
18832
|
+
style: {
|
|
18833
|
+
top: activeItemRect.top + activeItemRect.height + 10,
|
|
18834
|
+
left: activeItemRect.left - 5,
|
|
18835
|
+
background: PRIMARY3,
|
|
18836
|
+
zIndex: 2147483644
|
|
18837
|
+
},
|
|
18838
|
+
children: "Media item"
|
|
18839
|
+
}
|
|
18840
|
+
),
|
|
18841
|
+
linkOpen && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18842
|
+
LinkModal,
|
|
18843
|
+
{
|
|
18844
|
+
href: activeHref,
|
|
18845
|
+
linkTarget: activeTarget,
|
|
18846
|
+
onClose: () => setLinkOpen(false),
|
|
18847
|
+
onSave: (href, linkTarget) => {
|
|
18848
|
+
void runMutation(
|
|
18849
|
+
active.sectionId,
|
|
18850
|
+
(tree) => setMediaStripItemLink(tree, active.index, href ? { href, linkTarget } : {})
|
|
18851
|
+
);
|
|
18852
|
+
}
|
|
18853
|
+
}
|
|
18854
|
+
)
|
|
18855
|
+
] })
|
|
18719
18856
|
] });
|
|
18720
18857
|
}
|
|
18721
18858
|
|
|
18722
18859
|
// src/ui/ai-section/AiPricingCardOverlay.tsx
|
|
18723
18860
|
var import_react11 = require("react");
|
|
18724
|
-
var
|
|
18725
|
-
var
|
|
18861
|
+
var import_lucide_react10 = require("lucide-react");
|
|
18862
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
18726
18863
|
var PRIMARY4 = "var(--ohw-primary, #0885FE)";
|
|
18727
|
-
var
|
|
18864
|
+
var CHROME_SELECTOR2 = "[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-link-modal-root], [data-ohw-section-picker], [data-ohw-ai-review], [data-ohw-more-menu]";
|
|
18728
18865
|
function findPricingCardElement(sectionId, index) {
|
|
18729
18866
|
const sectionEl = findByInstanceId(sectionId);
|
|
18730
18867
|
if (!sectionEl) return null;
|
|
@@ -18736,7 +18873,7 @@ function findPricingCardElement(sectionId, index) {
|
|
|
18736
18873
|
}
|
|
18737
18874
|
function cardRefFromTarget(target) {
|
|
18738
18875
|
if (!(target instanceof Element)) return null;
|
|
18739
|
-
if (target.closest(
|
|
18876
|
+
if (target.closest(CHROME_SELECTOR2)) return null;
|
|
18740
18877
|
const cardEl = target.closest("[data-ohw-pricing-card]");
|
|
18741
18878
|
if (!cardEl) return null;
|
|
18742
18879
|
const sectionEl = cardEl.closest("[data-ohw-section]");
|
|
@@ -18746,21 +18883,21 @@ function cardRefFromTarget(target) {
|
|
|
18746
18883
|
if (!sectionId || Number.isNaN(index)) return null;
|
|
18747
18884
|
return { sectionId, index };
|
|
18748
18885
|
}
|
|
18749
|
-
function
|
|
18886
|
+
function sameRef2(a, b) {
|
|
18750
18887
|
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
18751
18888
|
}
|
|
18752
|
-
function
|
|
18889
|
+
function rectOf2(el) {
|
|
18753
18890
|
if (!el) return null;
|
|
18754
18891
|
const r2 = el.getBoundingClientRect();
|
|
18755
18892
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
18756
18893
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
18757
18894
|
}
|
|
18758
18895
|
function readRect3(ref) {
|
|
18759
|
-
return
|
|
18896
|
+
return rectOf2(ref && findPricingCardElement(ref.sectionId, ref.index));
|
|
18760
18897
|
}
|
|
18761
18898
|
function readGridRect(ref) {
|
|
18762
18899
|
const card = ref && findPricingCardElement(ref.sectionId, ref.index);
|
|
18763
|
-
return
|
|
18900
|
+
return rectOf2(card?.closest("[data-ohw-pricing-collection]") ?? card);
|
|
18764
18901
|
}
|
|
18765
18902
|
function useLiveCardRect(ref, grid = false) {
|
|
18766
18903
|
const [rect, setRect] = (0, import_react11.useState)(null);
|
|
@@ -18790,7 +18927,7 @@ function useLiveCardRect(ref, grid = false) {
|
|
|
18790
18927
|
}
|
|
18791
18928
|
var TOOLBAR_GRID_GAP = 52;
|
|
18792
18929
|
var TOOLBAR_GRID_GAP_MOBILE = 42;
|
|
18793
|
-
var
|
|
18930
|
+
var TOOLBAR_EDGE_MARGIN3 = 4;
|
|
18794
18931
|
function GridToolbarSlot({ gridRect, children }) {
|
|
18795
18932
|
const slotRef = (0, import_react11.useRef)(null);
|
|
18796
18933
|
const [shift, setShift] = (0, import_react11.useState)(0);
|
|
@@ -18802,7 +18939,7 @@ function GridToolbarSlot({ gridRect, children }) {
|
|
|
18802
18939
|
const w = slot.offsetWidth;
|
|
18803
18940
|
if (w <= 0) return;
|
|
18804
18941
|
const half = w / 2;
|
|
18805
|
-
const clamped = Math.max(
|
|
18942
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN3 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN3 - half));
|
|
18806
18943
|
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
18807
18944
|
};
|
|
18808
18945
|
clamp();
|
|
@@ -18811,7 +18948,7 @@ function GridToolbarSlot({ gridRect, children }) {
|
|
|
18811
18948
|
return () => ro.disconnect();
|
|
18812
18949
|
}, [centerX, children]);
|
|
18813
18950
|
const mobile = window.innerWidth <= 480;
|
|
18814
|
-
return /* @__PURE__ */ (0,
|
|
18951
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
18815
18952
|
"div",
|
|
18816
18953
|
{
|
|
18817
18954
|
ref: slotRef,
|
|
@@ -18846,7 +18983,7 @@ function requestValidateTree2(postToParent2, tree) {
|
|
|
18846
18983
|
});
|
|
18847
18984
|
}
|
|
18848
18985
|
function StyleSwatch({ style }) {
|
|
18849
|
-
return /* @__PURE__ */ (0,
|
|
18986
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
18850
18987
|
"span",
|
|
18851
18988
|
{
|
|
18852
18989
|
"aria-hidden": true,
|
|
@@ -18860,35 +18997,35 @@ function StyleSwatch({ style }) {
|
|
|
18860
18997
|
);
|
|
18861
18998
|
}
|
|
18862
18999
|
function ButtonGlyph() {
|
|
18863
|
-
return /* @__PURE__ */ (0,
|
|
18864
|
-
/* @__PURE__ */ (0,
|
|
18865
|
-
/* @__PURE__ */ (0,
|
|
19000
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("svg", { width: "18", height: "12", viewBox: "0 0 18 12", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19001
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("rect", { x: "0.75", y: "0.75", width: "16.5", height: "10.5", rx: "3", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19002
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("path", { d: "M5.5 6H12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
|
|
18866
19003
|
] });
|
|
18867
19004
|
}
|
|
18868
19005
|
function FeatureGlyph({ mode }) {
|
|
18869
|
-
return /* @__PURE__ */ (0,
|
|
18870
|
-
/* @__PURE__ */ (0,
|
|
18871
|
-
/* @__PURE__ */ (0,
|
|
18872
|
-
/* @__PURE__ */ (0,
|
|
18873
|
-
/* @__PURE__ */ (0,
|
|
18874
|
-
/* @__PURE__ */ (0,
|
|
18875
|
-
mode === "add" && /* @__PURE__ */ (0,
|
|
19006
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19007
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("circle", { cx: "8", cy: "8", r: "7.25", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19008
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("path", { d: "M5 8.2L7.2 10.3L11 6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
19009
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("circle", { cx: "13.5", cy: "13.5", r: "4.25", fill: "var(--ohw-background, #ffffff)", stroke: "var(--ohw-background, #ffffff)", strokeWidth: "1" }),
|
|
19010
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("circle", { cx: "13.5", cy: "13.5", r: "3.75", fill: "var(--ohw-background, #ffffff)", stroke: PRIMARY4, strokeWidth: "1" }),
|
|
19011
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("path", { d: "M11.5 13.5H15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
19012
|
+
mode === "add" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("path", { d: "M13.5 11.5V15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" })
|
|
18876
19013
|
] });
|
|
18877
19014
|
}
|
|
18878
|
-
function
|
|
19015
|
+
function ToolbarAction2({
|
|
18879
19016
|
label,
|
|
18880
19017
|
onClick,
|
|
18881
19018
|
disabled = false,
|
|
18882
19019
|
children
|
|
18883
19020
|
}) {
|
|
18884
|
-
const button = /* @__PURE__ */ (0,
|
|
18885
|
-
return /* @__PURE__ */ (0,
|
|
18886
|
-
/* @__PURE__ */ (0,
|
|
18887
|
-
/* @__PURE__ */ (0,
|
|
19021
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CustomToolbarButton, { type: "button", "aria-label": label, disabled, onClick, className: "size-8", children });
|
|
19022
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tooltip, { children: [
|
|
19023
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "inline-flex", children: button }) : button }),
|
|
19024
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
18888
19025
|
] });
|
|
18889
19026
|
}
|
|
18890
|
-
function
|
|
18891
|
-
return /* @__PURE__ */ (0,
|
|
19027
|
+
function ToolbarSeparator2() {
|
|
19028
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
18892
19029
|
}
|
|
18893
19030
|
function CardStyleMenu({
|
|
18894
19031
|
value,
|
|
@@ -18896,7 +19033,7 @@ function CardStyleMenu({
|
|
|
18896
19033
|
disabled = false
|
|
18897
19034
|
}) {
|
|
18898
19035
|
const current = PRICING_CARD_STYLES.find((s) => s.value === value) ?? PRICING_CARD_STYLES[0];
|
|
18899
|
-
const trigger = /* @__PURE__ */ (0,
|
|
19036
|
+
const trigger = /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
18900
19037
|
"button",
|
|
18901
19038
|
{
|
|
18902
19039
|
type: "button",
|
|
@@ -18907,28 +19044,28 @@ function CardStyleMenu({
|
|
|
18907
19044
|
disabled && "cursor-not-allowed opacity-40 hover:bg-transparent"
|
|
18908
19045
|
),
|
|
18909
19046
|
children: [
|
|
18910
|
-
/* @__PURE__ */ (0,
|
|
18911
|
-
/* @__PURE__ */ (0,
|
|
18912
|
-
/* @__PURE__ */ (0,
|
|
19047
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StyleSwatch, { style: current.value }),
|
|
19048
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "flex-1 text-left", children: current.label }),
|
|
19049
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.ChevronDown, { size: 16, style: { pointerEvents: "none" } })
|
|
18913
19050
|
]
|
|
18914
19051
|
}
|
|
18915
19052
|
);
|
|
18916
19053
|
if (disabled) {
|
|
18917
|
-
return /* @__PURE__ */ (0,
|
|
18918
|
-
/* @__PURE__ */ (0,
|
|
18919
|
-
/* @__PURE__ */ (0,
|
|
18920
|
-
/* @__PURE__ */ (0,
|
|
18921
|
-
/* @__PURE__ */ (0,
|
|
19054
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19055
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-xs text-muted-foreground opacity-50", children: "Card style" }),
|
|
19056
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tooltip, { children: [
|
|
19057
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "inline-flex", children: trigger }) }),
|
|
19058
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: "Mark as featured to edit card style" })
|
|
18922
19059
|
] })
|
|
18923
19060
|
] });
|
|
18924
19061
|
}
|
|
18925
|
-
return /* @__PURE__ */ (0,
|
|
18926
|
-
/* @__PURE__ */ (0,
|
|
18927
|
-
/* @__PURE__ */ (0,
|
|
18928
|
-
/* @__PURE__ */ (0,
|
|
18929
|
-
/* @__PURE__ */ (0,
|
|
19062
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19063
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-xs text-muted-foreground", children: "Card style" }),
|
|
19064
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DropdownMenu, { modal: false, children: [
|
|
19065
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropdownMenuTrigger, { asChild: true, children: trigger }),
|
|
19066
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[152px] min-w-[152px] p-1", children: PRICING_CARD_STYLES.map((style) => {
|
|
18930
19067
|
const selected = style.value === value;
|
|
18931
|
-
return /* @__PURE__ */ (0,
|
|
19068
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
18932
19069
|
DropdownMenuItem,
|
|
18933
19070
|
{
|
|
18934
19071
|
role: "menuitemradio",
|
|
@@ -18936,9 +19073,9 @@ function CardStyleMenu({
|
|
|
18936
19073
|
onSelect: () => onChange(style.value),
|
|
18937
19074
|
className: cn("grid grid-cols-[18px_1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
18938
19075
|
children: [
|
|
18939
|
-
/* @__PURE__ */ (0,
|
|
18940
|
-
/* @__PURE__ */ (0,
|
|
18941
|
-
selected && /* @__PURE__ */ (0,
|
|
19076
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StyleSwatch, { style: style.value }),
|
|
19077
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: style.label }),
|
|
19078
|
+
selected && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.Check, { size: 16, className: "text-bridge-primary" })
|
|
18942
19079
|
]
|
|
18943
19080
|
},
|
|
18944
19081
|
style.value
|
|
@@ -18968,7 +19105,7 @@ function PricingCardToolbar({
|
|
|
18968
19105
|
const style = pricingCardStyle(entry.tree, index);
|
|
18969
19106
|
const featuredTag = pricingCardFeaturedTag(entry.tree, index);
|
|
18970
19107
|
const mobile = window.innerWidth <= 480;
|
|
18971
|
-
return /* @__PURE__ */ (0,
|
|
19108
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
18972
19109
|
"div",
|
|
18973
19110
|
{
|
|
18974
19111
|
"data-ohw-bridge": "",
|
|
@@ -18980,7 +19117,7 @@ function PricingCardToolbar({
|
|
|
18980
19117
|
),
|
|
18981
19118
|
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
18982
19119
|
children: [
|
|
18983
|
-
/* @__PURE__ */ (0,
|
|
19120
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
18984
19121
|
"div",
|
|
18985
19122
|
{
|
|
18986
19123
|
className: cn(
|
|
@@ -18989,8 +19126,8 @@ function PricingCardToolbar({
|
|
|
18989
19126
|
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
18990
19127
|
),
|
|
18991
19128
|
children: [
|
|
18992
|
-
/* @__PURE__ */ (0,
|
|
18993
|
-
/* @__PURE__ */ (0,
|
|
19129
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tooltip, { children: [
|
|
19130
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
18994
19131
|
CustomToolbarButton,
|
|
18995
19132
|
{
|
|
18996
19133
|
type: "button",
|
|
@@ -18998,8 +19135,8 @@ function PricingCardToolbar({
|
|
|
18998
19135
|
"aria-pressed": featuredTag,
|
|
18999
19136
|
onClick: () => onSetFeaturedTag(!featuredTag),
|
|
19000
19137
|
className: "group size-8",
|
|
19001
|
-
children: /* @__PURE__ */ (0,
|
|
19002
|
-
|
|
19138
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19139
|
+
import_lucide_react10.Star,
|
|
19003
19140
|
{
|
|
19004
19141
|
size: 16,
|
|
19005
19142
|
fill: "currentColor",
|
|
@@ -19013,25 +19150,25 @@ function PricingCardToolbar({
|
|
|
19013
19150
|
)
|
|
19014
19151
|
}
|
|
19015
19152
|
) }),
|
|
19016
|
-
/* @__PURE__ */ (0,
|
|
19153
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: featuredTag ? "Unmark featured" : "Mark as featured" })
|
|
19017
19154
|
] }),
|
|
19018
|
-
/* @__PURE__ */ (0,
|
|
19019
|
-
/* @__PURE__ */ (0,
|
|
19020
|
-
/* @__PURE__ */ (0,
|
|
19021
|
-
/* @__PURE__ */ (0,
|
|
19022
|
-
/* @__PURE__ */ (0,
|
|
19023
|
-
/* @__PURE__ */ (0,
|
|
19024
|
-
/* @__PURE__ */ (0,
|
|
19155
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator2, {}),
|
|
19156
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CardStyleMenu, { value: style, onChange: onSetStyle, disabled: !featuredTag }),
|
|
19157
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator2, {}),
|
|
19158
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction2, { label: "Add button", onClick: onAddButton, disabled: buttonCount >= 2, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ButtonGlyph, {}) }),
|
|
19159
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction2, { label: "Remove button", onClick: onRemoveButton, disabled: buttonCount === 0, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "relative inline-flex", children: [
|
|
19160
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ButtonGlyph, {}),
|
|
19161
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.Minus, { size: 10, strokeWidth: 2.5, className: "absolute -right-1.5 -top-1.5 rounded-full bg-background text-bridge-primary" })
|
|
19025
19162
|
] }) }),
|
|
19026
|
-
/* @__PURE__ */ (0,
|
|
19027
|
-
/* @__PURE__ */ (0,
|
|
19028
|
-
/* @__PURE__ */ (0,
|
|
19029
|
-
/* @__PURE__ */ (0,
|
|
19030
|
-
/* @__PURE__ */ (0,
|
|
19163
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction2, { label: "Add feature", onClick: onAddFeature, disabled: featureCount >= 10, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(FeatureGlyph, { mode: "add" }) }),
|
|
19164
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction2, { label: "Remove feature", onClick: onRemoveFeature, disabled: featureCount <= 1, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(FeatureGlyph, { mode: "remove" }) }),
|
|
19165
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator2, {}),
|
|
19166
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction2, { label: "Add tier", onClick: onAddTier, disabled: collectionCount >= 4, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.Plus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19167
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction2, { label: "Remove tier", onClick: onRemoveTier, disabled: collectionCount <= 1, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.Minus, { size: 16, style: { pointerEvents: "none" } }) })
|
|
19031
19168
|
]
|
|
19032
19169
|
}
|
|
19033
19170
|
),
|
|
19034
|
-
error && /* @__PURE__ */ (0,
|
|
19171
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "max-w-[260px] rounded-md bg-background px-2 py-1 text-center text-[11px] text-destructive shadow-sm", children: error })
|
|
19035
19172
|
]
|
|
19036
19173
|
}
|
|
19037
19174
|
) });
|
|
@@ -19065,7 +19202,7 @@ function AiPricingCardOverlay({
|
|
|
19065
19202
|
const overEditable = Boolean(t?.closest?.("[data-ohw-editable], [data-ohw-role], a, button"));
|
|
19066
19203
|
setHover((prev) => {
|
|
19067
19204
|
const next = ref && !overEditable ? ref : null;
|
|
19068
|
-
return
|
|
19205
|
+
return sameRef2(prev, next) ? prev : next;
|
|
19069
19206
|
});
|
|
19070
19207
|
};
|
|
19071
19208
|
const onLeave = () => setHover(null);
|
|
@@ -19080,10 +19217,10 @@ function AiPricingCardOverlay({
|
|
|
19080
19217
|
const onClick = (e) => {
|
|
19081
19218
|
const t = e.target;
|
|
19082
19219
|
if (!(t instanceof Element)) return;
|
|
19083
|
-
if (t.closest(
|
|
19220
|
+
if (t.closest(CHROME_SELECTOR2)) return;
|
|
19084
19221
|
const ref = cardRefFromTarget(t);
|
|
19085
|
-
setActive((prev) =>
|
|
19086
|
-
if (!ref || !
|
|
19222
|
+
setActive((prev) => sameRef2(prev, ref) ? prev : ref);
|
|
19223
|
+
if (!ref || !sameRef2(activeRef.current, ref)) setError(null);
|
|
19087
19224
|
};
|
|
19088
19225
|
document.addEventListener("click", onClick, true);
|
|
19089
19226
|
return () => document.removeEventListener("click", onClick, true);
|
|
@@ -19148,12 +19285,12 @@ function AiPricingCardOverlay({
|
|
|
19148
19285
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
19149
19286
|
const activeCardRect = useLiveCardRect(active);
|
|
19150
19287
|
const activeGridRect = useLiveCardRect(active, true);
|
|
19151
|
-
const hoverRect = useLiveCardRect(hover && !
|
|
19152
|
-
return /* @__PURE__ */ (0,
|
|
19153
|
-
hoverRect && /* @__PURE__ */ (0,
|
|
19154
|
-
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
19155
|
-
/* @__PURE__ */ (0,
|
|
19156
|
-
/* @__PURE__ */ (0,
|
|
19288
|
+
const hoverRect = useLiveCardRect(hover && !sameRef2(hover, active) ? hover : null);
|
|
19289
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
19290
|
+
hoverRect && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
19291
|
+
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
19292
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ItemInteractionLayer, { rect: activeCardRect, state: "active-top" }),
|
|
19293
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GridToolbarSlot, { gridRect: activeGridRect, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19157
19294
|
PricingCardToolbar,
|
|
19158
19295
|
{
|
|
19159
19296
|
entry: activeEntry,
|
|
@@ -19181,7 +19318,7 @@ function AiPricingCardOverlay({
|
|
|
19181
19318
|
onRemoveFeature: () => runMutation(active.sectionId, (tree) => removePricingCardFeature(tree, active.index))
|
|
19182
19319
|
}
|
|
19183
19320
|
) }),
|
|
19184
|
-
/* @__PURE__ */ (0,
|
|
19321
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19185
19322
|
"div",
|
|
19186
19323
|
{
|
|
19187
19324
|
"data-ohw-bridge": "",
|
|
@@ -19203,7 +19340,7 @@ function AiPricingCardOverlay({
|
|
|
19203
19340
|
|
|
19204
19341
|
// src/ui/ai-section/AiVideoOverlay.tsx
|
|
19205
19342
|
var import_react12 = require("react");
|
|
19206
|
-
var
|
|
19343
|
+
var import_lucide_react11 = require("lucide-react");
|
|
19207
19344
|
|
|
19208
19345
|
// src/lib/ai-video-tree.ts
|
|
19209
19346
|
function resolveVideoBlock(tree, path) {
|
|
@@ -19274,10 +19411,10 @@ function extractYouTubeId(input) {
|
|
|
19274
19411
|
}
|
|
19275
19412
|
|
|
19276
19413
|
// src/ui/ai-section/AiVideoOverlay.tsx
|
|
19277
|
-
var
|
|
19414
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
19278
19415
|
var PRIMARY5 = "#0885FE";
|
|
19279
|
-
var
|
|
19280
|
-
var
|
|
19416
|
+
var OHW_BLUE = `var(--ohw-primary, ${PRIMARY5})`;
|
|
19417
|
+
var OHW_BLUE_DARK = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY5}) 60%, #000000)`;
|
|
19281
19418
|
function findVideoBlockElement(sectionId, path) {
|
|
19282
19419
|
const sectionEl = findByInstanceId(sectionId);
|
|
19283
19420
|
if (!sectionEl) return null;
|
|
@@ -19337,12 +19474,12 @@ function requestValidateTree3(postToParent2, tree) {
|
|
|
19337
19474
|
postToParent2({ type: "ow:ai-validate-tree-request", id, tree });
|
|
19338
19475
|
});
|
|
19339
19476
|
}
|
|
19340
|
-
function
|
|
19477
|
+
function Pill({
|
|
19341
19478
|
label,
|
|
19342
19479
|
onClick,
|
|
19343
19480
|
disabled
|
|
19344
19481
|
}) {
|
|
19345
|
-
return /* @__PURE__ */ (0,
|
|
19482
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19346
19483
|
"button",
|
|
19347
19484
|
{
|
|
19348
19485
|
type: "button",
|
|
@@ -19358,7 +19495,7 @@ function Pill2({
|
|
|
19358
19495
|
border: "none",
|
|
19359
19496
|
cursor: disabled ? "default" : "pointer",
|
|
19360
19497
|
background: "#ffffff",
|
|
19361
|
-
color:
|
|
19498
|
+
color: OHW_BLUE_DARK,
|
|
19362
19499
|
opacity: disabled ? 0.4 : 1,
|
|
19363
19500
|
fontSize: 12,
|
|
19364
19501
|
lineHeight: "16px",
|
|
@@ -19401,8 +19538,8 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
19401
19538
|
onCommit(id);
|
|
19402
19539
|
}
|
|
19403
19540
|
};
|
|
19404
|
-
return /* @__PURE__ */ (0,
|
|
19405
|
-
/* @__PURE__ */ (0,
|
|
19541
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4, width: "100%", maxWidth: 280 }, children: [
|
|
19542
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19406
19543
|
"div",
|
|
19407
19544
|
{
|
|
19408
19545
|
style: {
|
|
@@ -19418,12 +19555,12 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
19418
19555
|
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
19419
19556
|
},
|
|
19420
19557
|
children: [
|
|
19421
|
-
/* @__PURE__ */ (0,
|
|
19558
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19422
19559
|
"span",
|
|
19423
19560
|
{
|
|
19424
19561
|
style: {
|
|
19425
19562
|
flex: "0 0 auto",
|
|
19426
|
-
color:
|
|
19563
|
+
color: OHW_BLUE_DARK,
|
|
19427
19564
|
fontSize: 10,
|
|
19428
19565
|
lineHeight: "16px",
|
|
19429
19566
|
fontWeight: 700,
|
|
@@ -19433,7 +19570,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
19433
19570
|
children: "Video"
|
|
19434
19571
|
}
|
|
19435
19572
|
),
|
|
19436
|
-
/* @__PURE__ */ (0,
|
|
19573
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19437
19574
|
"input",
|
|
19438
19575
|
{
|
|
19439
19576
|
type: "text",
|
|
@@ -19470,7 +19607,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
19470
19607
|
]
|
|
19471
19608
|
}
|
|
19472
19609
|
),
|
|
19473
|
-
invalid && /* @__PURE__ */ (0,
|
|
19610
|
+
invalid && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, textAlign: "center" }, children: "That doesn't look like a YouTube link \u2014 try pasting the video URL again." })
|
|
19474
19611
|
] });
|
|
19475
19612
|
}
|
|
19476
19613
|
function VideoToolbar({
|
|
@@ -19480,7 +19617,7 @@ function VideoToolbar({
|
|
|
19480
19617
|
onSetVideoId,
|
|
19481
19618
|
onRemove
|
|
19482
19619
|
}) {
|
|
19483
|
-
return /* @__PURE__ */ (0,
|
|
19620
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19484
19621
|
"div",
|
|
19485
19622
|
{
|
|
19486
19623
|
"data-ohw-bridge": "",
|
|
@@ -19492,7 +19629,7 @@ function VideoToolbar({
|
|
|
19492
19629
|
gap: 6,
|
|
19493
19630
|
alignItems: "center",
|
|
19494
19631
|
width: 280,
|
|
19495
|
-
background:
|
|
19632
|
+
background: OHW_BLUE,
|
|
19496
19633
|
padding: 8,
|
|
19497
19634
|
borderRadius: 12,
|
|
19498
19635
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -19500,9 +19637,9 @@ function VideoToolbar({
|
|
|
19500
19637
|
opacity: pending ? 0.6 : 1
|
|
19501
19638
|
},
|
|
19502
19639
|
children: [
|
|
19503
|
-
/* @__PURE__ */ (0,
|
|
19504
|
-
/* @__PURE__ */ (0,
|
|
19505
|
-
error && /* @__PURE__ */ (0,
|
|
19640
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(VideoUrlInput, { value: videoId, onCommit: onSetVideoId }),
|
|
19641
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Pill, { label: "Remove video", onClick: onRemove, disabled: !videoId }),
|
|
19642
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
19506
19643
|
]
|
|
19507
19644
|
}
|
|
19508
19645
|
);
|
|
@@ -19622,8 +19759,8 @@ function AiVideoOverlay({
|
|
|
19622
19759
|
const activeBlockRect = useLiveBlockRect(active);
|
|
19623
19760
|
const TOOLBAR_APPROX_H = 90;
|
|
19624
19761
|
const toolbarState = activeBlockRect && activeBlockRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
19625
|
-
return /* @__PURE__ */ (0,
|
|
19626
|
-
hoverHandleRect && hover && /* @__PURE__ */ (0,
|
|
19762
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
19763
|
+
hoverHandleRect && hover && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19627
19764
|
"button",
|
|
19628
19765
|
{
|
|
19629
19766
|
type: "button",
|
|
@@ -19651,15 +19788,15 @@ function AiVideoOverlay({
|
|
|
19651
19788
|
fontSize: 14,
|
|
19652
19789
|
fontWeight: 700
|
|
19653
19790
|
},
|
|
19654
|
-
children: /* @__PURE__ */ (0,
|
|
19791
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react11.Star, { size: 14, style: { pointerEvents: "none" } })
|
|
19655
19792
|
}
|
|
19656
19793
|
),
|
|
19657
|
-
activeBlockRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
19794
|
+
activeBlockRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19658
19795
|
ItemInteractionLayer,
|
|
19659
19796
|
{
|
|
19660
19797
|
rect: activeBlockRect,
|
|
19661
19798
|
state: toolbarState,
|
|
19662
|
-
toolbar: /* @__PURE__ */ (0,
|
|
19799
|
+
toolbar: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19663
19800
|
VideoToolbar,
|
|
19664
19801
|
{
|
|
19665
19802
|
videoId: videoIdAt(activeEntry.tree, active.path),
|
|
@@ -19683,7 +19820,7 @@ function AiVideoOverlay({
|
|
|
19683
19820
|
|
|
19684
19821
|
// src/ui/ai-section/AiFadeCarouselOverlay.tsx
|
|
19685
19822
|
var import_react13 = require("react");
|
|
19686
|
-
var
|
|
19823
|
+
var import_lucide_react12 = require("lucide-react");
|
|
19687
19824
|
|
|
19688
19825
|
// src/lib/ai-carousel-tree.ts
|
|
19689
19826
|
function isCarouselBlock(node) {
|
|
@@ -19734,10 +19871,10 @@ function setCarouselAutoplay(tree, on) {
|
|
|
19734
19871
|
}
|
|
19735
19872
|
|
|
19736
19873
|
// src/ui/ai-section/AiFadeCarouselOverlay.tsx
|
|
19737
|
-
var
|
|
19874
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
19738
19875
|
var PRIMARY6 = "#0885FE";
|
|
19739
|
-
var
|
|
19740
|
-
var
|
|
19876
|
+
var OHW_BLUE2 = `var(--ohw-primary, ${PRIMARY6})`;
|
|
19877
|
+
var OHW_BLUE_DARK2 = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY6}) 60%, #000000)`;
|
|
19741
19878
|
function findCarouselItemElement(sectionId, index) {
|
|
19742
19879
|
const sectionEl = findByInstanceId(sectionId);
|
|
19743
19880
|
if (!sectionEl) return null;
|
|
@@ -19816,8 +19953,8 @@ function requestAssetPick2(postToParent2) {
|
|
|
19816
19953
|
postToParent2({ type: "ow:asset-pick", id });
|
|
19817
19954
|
});
|
|
19818
19955
|
}
|
|
19819
|
-
function
|
|
19820
|
-
return /* @__PURE__ */ (0,
|
|
19956
|
+
function Pill2({ label, onClick, disabled }) {
|
|
19957
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
19821
19958
|
"button",
|
|
19822
19959
|
{
|
|
19823
19960
|
type: "button",
|
|
@@ -19833,7 +19970,7 @@ function Pill3({ label, onClick, disabled }) {
|
|
|
19833
19970
|
border: "none",
|
|
19834
19971
|
cursor: disabled ? "default" : "pointer",
|
|
19835
19972
|
background: "#ffffff",
|
|
19836
|
-
color:
|
|
19973
|
+
color: OHW_BLUE_DARK2,
|
|
19837
19974
|
opacity: disabled ? 0.4 : 1,
|
|
19838
19975
|
fontSize: 12,
|
|
19839
19976
|
lineHeight: "16px",
|
|
@@ -19851,7 +19988,7 @@ function TogglePill({
|
|
|
19851
19988
|
onToggle,
|
|
19852
19989
|
disabled
|
|
19853
19990
|
}) {
|
|
19854
|
-
return /* @__PURE__ */ (0,
|
|
19991
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
19855
19992
|
"button",
|
|
19856
19993
|
{
|
|
19857
19994
|
type: "button",
|
|
@@ -19870,7 +20007,7 @@ function TogglePill({
|
|
|
19870
20007
|
border: "none",
|
|
19871
20008
|
cursor: disabled ? "default" : "pointer",
|
|
19872
20009
|
background: "#ffffff",
|
|
19873
|
-
color:
|
|
20010
|
+
color: OHW_BLUE_DARK2,
|
|
19874
20011
|
opacity: disabled ? 0.4 : 1,
|
|
19875
20012
|
fontSize: 12,
|
|
19876
20013
|
lineHeight: "16px",
|
|
@@ -19880,7 +20017,7 @@ function TogglePill({
|
|
|
19880
20017
|
},
|
|
19881
20018
|
children: [
|
|
19882
20019
|
label,
|
|
19883
|
-
/* @__PURE__ */ (0,
|
|
20020
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
19884
20021
|
"span",
|
|
19885
20022
|
{
|
|
19886
20023
|
"aria-hidden": true,
|
|
@@ -19893,10 +20030,10 @@ function TogglePill({
|
|
|
19893
20030
|
// Off is a grey track, not a washed-out blue: the pill's own white background already
|
|
19894
20031
|
// carries the brand colour in the text, and a pale blue track next to it read as
|
|
19895
20032
|
// "disabled control" rather than "switch that is off".
|
|
19896
|
-
background: on ?
|
|
20033
|
+
background: on ? OHW_BLUE_DARK2 : "#CBD5E1",
|
|
19897
20034
|
transition: "background 120ms ease"
|
|
19898
20035
|
},
|
|
19899
|
-
children: /* @__PURE__ */ (0,
|
|
20036
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
19900
20037
|
"span",
|
|
19901
20038
|
{
|
|
19902
20039
|
style: {
|
|
@@ -19925,7 +20062,7 @@ function CarouselSlideToolbar({
|
|
|
19925
20062
|
onChangeImage,
|
|
19926
20063
|
onToggleAutoplay
|
|
19927
20064
|
}) {
|
|
19928
|
-
return /* @__PURE__ */ (0,
|
|
20065
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
19929
20066
|
"div",
|
|
19930
20067
|
{
|
|
19931
20068
|
"data-ohw-bridge": "",
|
|
@@ -19936,7 +20073,7 @@ function CarouselSlideToolbar({
|
|
|
19936
20073
|
flexDirection: "column",
|
|
19937
20074
|
gap: 6,
|
|
19938
20075
|
alignItems: "center",
|
|
19939
|
-
background:
|
|
20076
|
+
background: OHW_BLUE2,
|
|
19940
20077
|
padding: 8,
|
|
19941
20078
|
borderRadius: 12,
|
|
19942
20079
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -19948,11 +20085,11 @@ function CarouselSlideToolbar({
|
|
|
19948
20085
|
pointerEvents: pending ? "none" : "auto"
|
|
19949
20086
|
},
|
|
19950
20087
|
children: [
|
|
19951
|
-
/* @__PURE__ */ (0,
|
|
19952
|
-
/* @__PURE__ */ (0,
|
|
19953
|
-
/* @__PURE__ */ (0,
|
|
20088
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", gap: 6, alignItems: "center" }, children: [
|
|
20089
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Pill2, { label: "Change Image", onClick: onChangeImage }),
|
|
20090
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TogglePill, { label: "Autoplay", on: autoplay, onToggle: onToggleAutoplay })
|
|
19954
20091
|
] }),
|
|
19955
|
-
error && /* @__PURE__ */ (0,
|
|
20092
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
19956
20093
|
]
|
|
19957
20094
|
}
|
|
19958
20095
|
);
|
|
@@ -20092,8 +20229,8 @@ function AiFadeCarouselOverlay({
|
|
|
20092
20229
|
const activeItemRect = useLiveItemRect2(active);
|
|
20093
20230
|
const TOOLBAR_APPROX_H = 90;
|
|
20094
20231
|
const toolbarState = activeItemRect && activeItemRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
20095
|
-
return /* @__PURE__ */ (0,
|
|
20096
|
-
hoverHandleRect && hover && /* @__PURE__ */ (0,
|
|
20232
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
20233
|
+
hoverHandleRect && hover && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20097
20234
|
"button",
|
|
20098
20235
|
{
|
|
20099
20236
|
type: "button",
|
|
@@ -20122,10 +20259,10 @@ function AiFadeCarouselOverlay({
|
|
|
20122
20259
|
fontSize: 14,
|
|
20123
20260
|
fontWeight: 700
|
|
20124
20261
|
},
|
|
20125
|
-
children: /* @__PURE__ */ (0,
|
|
20262
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react12.Star, { size: 14, style: { pointerEvents: "none" } })
|
|
20126
20263
|
}
|
|
20127
20264
|
),
|
|
20128
|
-
swapping && /* @__PURE__ */ (0,
|
|
20265
|
+
swapping && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20129
20266
|
"div",
|
|
20130
20267
|
{
|
|
20131
20268
|
ref: skeletonRef,
|
|
@@ -20143,15 +20280,15 @@ function AiFadeCarouselOverlay({
|
|
|
20143
20280
|
zIndex: 2147483646,
|
|
20144
20281
|
pointerEvents: "none"
|
|
20145
20282
|
},
|
|
20146
|
-
children: /* @__PURE__ */ (0,
|
|
20283
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("style", { children: MEDIA_SKELETON_CSS })
|
|
20147
20284
|
}
|
|
20148
20285
|
),
|
|
20149
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
20286
|
+
activeItemRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20150
20287
|
ItemInteractionLayer,
|
|
20151
20288
|
{
|
|
20152
20289
|
rect: activeItemRect,
|
|
20153
20290
|
state: toolbarState,
|
|
20154
|
-
toolbar: /* @__PURE__ */ (0,
|
|
20291
|
+
toolbar: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20155
20292
|
CarouselSlideToolbar,
|
|
20156
20293
|
{
|
|
20157
20294
|
pending,
|
|
@@ -20504,113 +20641,6 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
|
|
|
20504
20641
|
// src/ui/link-modal/LinkPopover.tsx
|
|
20505
20642
|
var import_react17 = require("react");
|
|
20506
20643
|
|
|
20507
|
-
// src/ui/dialog.tsx
|
|
20508
|
-
var React9 = __toESM(require("react"), 1);
|
|
20509
|
-
var import_radix_ui6 = require("radix-ui");
|
|
20510
|
-
var import_lucide_react12 = require("lucide-react");
|
|
20511
|
-
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
20512
|
-
function Dialog2({
|
|
20513
|
-
...props
|
|
20514
|
-
}) {
|
|
20515
|
-
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_radix_ui6.Dialog.Root, { "data-slot": "dialog", ...props });
|
|
20516
|
-
}
|
|
20517
|
-
function DialogPortal({
|
|
20518
|
-
...props
|
|
20519
|
-
}) {
|
|
20520
|
-
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_radix_ui6.Dialog.Portal, { ...props });
|
|
20521
|
-
}
|
|
20522
|
-
function DialogOverlay({
|
|
20523
|
-
className,
|
|
20524
|
-
...props
|
|
20525
|
-
}) {
|
|
20526
|
-
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20527
|
-
import_radix_ui6.Dialog.Overlay,
|
|
20528
|
-
{
|
|
20529
|
-
"data-slot": "dialog-overlay",
|
|
20530
|
-
"data-ohw-link-modal-root": "",
|
|
20531
|
-
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
20532
|
-
...props
|
|
20533
|
-
}
|
|
20534
|
-
);
|
|
20535
|
-
}
|
|
20536
|
-
var DialogContent = React9.forwardRef(
|
|
20537
|
-
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
20538
|
-
const positionMode = container ? "absolute" : "fixed";
|
|
20539
|
-
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(DialogPortal, { container: container ?? void 0, children: [
|
|
20540
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
20541
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
20542
|
-
import_radix_ui6.Dialog.Content,
|
|
20543
|
-
{
|
|
20544
|
-
ref,
|
|
20545
|
-
"data-slot": "dialog-content",
|
|
20546
|
-
className: cn(
|
|
20547
|
-
positionMode,
|
|
20548
|
-
"left-1/2 top-1/2 z-[2147483647] flex w-full max-w-[448px] -translate-x-1/2 -translate-y-1/2 flex-col overflow-visible",
|
|
20549
|
-
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
20550
|
-
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
20551
|
-
className
|
|
20552
|
-
),
|
|
20553
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
20554
|
-
...props,
|
|
20555
|
-
children: [
|
|
20556
|
-
children,
|
|
20557
|
-
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20558
|
-
import_radix_ui6.Dialog.Close,
|
|
20559
|
-
{
|
|
20560
|
-
type: "button",
|
|
20561
|
-
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
20562
|
-
"aria-label": "Close",
|
|
20563
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react12.X, { size: 16, "aria-hidden": true })
|
|
20564
|
-
}
|
|
20565
|
-
) : null
|
|
20566
|
-
]
|
|
20567
|
-
}
|
|
20568
|
-
)
|
|
20569
|
-
] });
|
|
20570
|
-
}
|
|
20571
|
-
);
|
|
20572
|
-
DialogContent.displayName = import_radix_ui6.Dialog.Content.displayName;
|
|
20573
|
-
function DialogHeader({
|
|
20574
|
-
className,
|
|
20575
|
-
...props
|
|
20576
|
-
}) {
|
|
20577
|
-
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
20578
|
-
}
|
|
20579
|
-
function DialogFooter({
|
|
20580
|
-
className,
|
|
20581
|
-
...props
|
|
20582
|
-
}) {
|
|
20583
|
-
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20584
|
-
"div",
|
|
20585
|
-
{
|
|
20586
|
-
className: cn("flex items-center justify-end gap-2", className),
|
|
20587
|
-
...props
|
|
20588
|
-
}
|
|
20589
|
-
);
|
|
20590
|
-
}
|
|
20591
|
-
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20592
|
-
import_radix_ui6.Dialog.Title,
|
|
20593
|
-
{
|
|
20594
|
-
ref,
|
|
20595
|
-
className: cn(
|
|
20596
|
-
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
20597
|
-
className
|
|
20598
|
-
),
|
|
20599
|
-
...props
|
|
20600
|
-
}
|
|
20601
|
-
));
|
|
20602
|
-
DialogTitle.displayName = import_radix_ui6.Dialog.Title.displayName;
|
|
20603
|
-
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20604
|
-
import_radix_ui6.Dialog.Description,
|
|
20605
|
-
{
|
|
20606
|
-
ref,
|
|
20607
|
-
className: cn("text-sm text-muted-foreground", className),
|
|
20608
|
-
...props
|
|
20609
|
-
}
|
|
20610
|
-
));
|
|
20611
|
-
DialogDescription.displayName = import_radix_ui6.Dialog.Description.displayName;
|
|
20612
|
-
var DialogClose = import_radix_ui6.Dialog.Close;
|
|
20613
|
-
|
|
20614
20644
|
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
20615
20645
|
var import_lucide_react16 = require("lucide-react");
|
|
20616
20646
|
|
|
@@ -24614,7 +24644,7 @@ function applyVisibleViewport(el, parentScroll) {
|
|
|
24614
24644
|
el.style.top = `${top}px`;
|
|
24615
24645
|
el.style.height = `${height}px`;
|
|
24616
24646
|
}
|
|
24617
|
-
var
|
|
24647
|
+
var TOOLBAR_EDGE_MARGIN4 = 4;
|
|
24618
24648
|
function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
24619
24649
|
const isAbove = transform.includes("translateY(-100%)");
|
|
24620
24650
|
let visualTop = isAbove ? top - approxH : top;
|
|
@@ -24641,8 +24671,8 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
|
24641
24671
|
function clampToolbarLeft(centerX, toolbarWidth) {
|
|
24642
24672
|
const half = toolbarWidth / 2;
|
|
24643
24673
|
return Math.max(
|
|
24644
|
-
|
|
24645
|
-
Math.min(centerX, window.innerWidth -
|
|
24674
|
+
TOOLBAR_EDGE_MARGIN4 + half,
|
|
24675
|
+
Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN4 - half)
|
|
24646
24676
|
);
|
|
24647
24677
|
}
|
|
24648
24678
|
function calcToolbarPos(rect, parentScroll, toolbarW = 306) {
|
|
@@ -29497,12 +29527,16 @@ function OhhwellsBridge() {
|
|
|
29497
29527
|
};
|
|
29498
29528
|
const handleIconName = (e) => {
|
|
29499
29529
|
if (e.data?.type !== "ow:icon-name") return;
|
|
29500
|
-
const { key, icon } = e.data;
|
|
29501
|
-
|
|
29530
|
+
const { key, icon, url } = e.data;
|
|
29531
|
+
const isName = typeof icon === "string" && /^[a-z0-9-]+$/.test(icon);
|
|
29532
|
+
const isUpload = !isName && typeof url === "string" && /^https?:\/\/\S+$/i.test(url);
|
|
29533
|
+
if (!key || !isName && !isUpload) return;
|
|
29502
29534
|
const state = parseAiSectionsState(aiSectionsRef.current);
|
|
29503
29535
|
const entry = state.sections.find((s) => key.startsWith(aiSlotKeyPrefixFor(s.id)));
|
|
29504
29536
|
if (!entry) return;
|
|
29505
|
-
const
|
|
29537
|
+
const path = key.slice(aiSlotKeyPrefixFor(entry.id).length);
|
|
29538
|
+
const uploadRef = isUpload ? `icon-${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}` : null;
|
|
29539
|
+
const nextTree = uploadRef ? applyIconUploadToTree(entry.tree, path, uploadRef) : applyIconNameToTree(entry.tree, path, icon);
|
|
29506
29540
|
if (!nextTree) return;
|
|
29507
29541
|
void requestValidateTree5(postToParentRef.current, nextTree).then(({ ok }) => {
|
|
29508
29542
|
if (!ok) return;
|
|
@@ -29512,7 +29546,7 @@ function OhhwellsBridge() {
|
|
|
29512
29546
|
targetSectionId: entry.id,
|
|
29513
29547
|
tree: nextTree,
|
|
29514
29548
|
label: entry.label,
|
|
29515
|
-
media: entry.media,
|
|
29549
|
+
media: uploadRef ? { ...entry.media, [uploadRef]: url } : entry.media,
|
|
29516
29550
|
...entry.brand ? { brand: entry.brand } : {},
|
|
29517
29551
|
// The user is looking at the icon they just changed — no need to recenter on it.
|
|
29518
29552
|
skipScrollIntoView: true
|