@ohhwells/bridge 0.1.39 → 0.1.41
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 +1796 -596
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -3
- package/dist/index.d.ts +50 -3
- package/dist/index.js +1765 -565
- package/dist/index.js.map +1 -1
- package/dist/styles.css +127 -16
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -60,15 +60,18 @@ __export(index_exports, {
|
|
|
60
60
|
module.exports = __toCommonJS(index_exports);
|
|
61
61
|
|
|
62
62
|
// src/OhhwellsBridge.tsx
|
|
63
|
-
var
|
|
63
|
+
var import_react8 = __toESM(require("react"), 1);
|
|
64
64
|
var import_client = require("react-dom/client");
|
|
65
|
-
var
|
|
65
|
+
var import_react_dom2 = require("react-dom");
|
|
66
66
|
|
|
67
67
|
// src/linkHrefStore.ts
|
|
68
68
|
var linkHrefStore = /* @__PURE__ */ new Map();
|
|
69
69
|
function setStoredLinkHref(key, href) {
|
|
70
70
|
linkHrefStore.set(key, href);
|
|
71
71
|
}
|
|
72
|
+
function getStoredLinkHref(key) {
|
|
73
|
+
return linkHrefStore.get(key);
|
|
74
|
+
}
|
|
72
75
|
function enforceLinkHrefs() {
|
|
73
76
|
document.querySelectorAll("[data-ohw-href-key]").forEach((el) => {
|
|
74
77
|
const key = el.getAttribute("data-ohw-href-key") ?? "";
|
|
@@ -4408,6 +4411,7 @@ function ItemActionToolbar({
|
|
|
4408
4411
|
onEditLink,
|
|
4409
4412
|
onAddItem,
|
|
4410
4413
|
onMore,
|
|
4414
|
+
editLinkDisabled = false,
|
|
4411
4415
|
addItemDisabled = true,
|
|
4412
4416
|
moreDisabled = true,
|
|
4413
4417
|
tooltipSide = "bottom"
|
|
@@ -4416,10 +4420,12 @@ function ItemActionToolbar({
|
|
|
4416
4420
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
4417
4421
|
ToolbarActionTooltip,
|
|
4418
4422
|
{
|
|
4419
|
-
label: "
|
|
4423
|
+
label: "Edit link",
|
|
4420
4424
|
side: tooltipSide,
|
|
4425
|
+
disabled: editLinkDisabled,
|
|
4421
4426
|
buttonProps: {
|
|
4422
4427
|
onMouseDown: (e) => {
|
|
4428
|
+
if (editLinkDisabled) return;
|
|
4423
4429
|
e.preventDefault();
|
|
4424
4430
|
e.stopPropagation();
|
|
4425
4431
|
onEditLink?.();
|
|
@@ -4806,8 +4812,8 @@ function MediaOverlay({
|
|
|
4806
4812
|
}
|
|
4807
4813
|
|
|
4808
4814
|
// src/OhhwellsBridge.tsx
|
|
4809
|
-
var
|
|
4810
|
-
var
|
|
4815
|
+
var import_react_dom3 = require("react-dom");
|
|
4816
|
+
var import_navigation2 = require("next/navigation");
|
|
4811
4817
|
|
|
4812
4818
|
// src/lib/session-search.ts
|
|
4813
4819
|
var STORAGE_KEY = "ohw-preserved-search";
|
|
@@ -4837,6 +4843,7 @@ function parseSectionsFromRoot(root) {
|
|
|
4837
4843
|
for (const el of root.querySelectorAll("[data-ohw-section]")) {
|
|
4838
4844
|
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
4839
4845
|
if (!id || seen.has(id)) continue;
|
|
4846
|
+
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
4840
4847
|
seen.add(id);
|
|
4841
4848
|
const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
|
|
4842
4849
|
sections.push({ id, label });
|
|
@@ -5083,61 +5090,29 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
|
|
|
5083
5090
|
tick();
|
|
5084
5091
|
}
|
|
5085
5092
|
|
|
5093
|
+
// src/ui/link-modal/LinkPopover.tsx
|
|
5094
|
+
var import_react7 = require("react");
|
|
5095
|
+
|
|
5086
5096
|
// src/ui/dialog.tsx
|
|
5087
5097
|
var React7 = __toESM(require("react"), 1);
|
|
5088
5098
|
var import_radix_ui5 = require("radix-ui");
|
|
5089
|
-
|
|
5090
|
-
// src/ui/icons.tsx
|
|
5099
|
+
var import_lucide_react4 = require("lucide-react");
|
|
5091
5100
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
5092
|
-
function
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
] });
|
|
5097
|
-
}
|
|
5098
|
-
function IconChevronDown({ className, ...props }) {
|
|
5099
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m6 9 6 6 6-6" }) });
|
|
5100
|
-
}
|
|
5101
|
-
function IconFile({ className, ...props }) {
|
|
5102
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
|
|
5103
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
|
|
5104
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })
|
|
5105
|
-
] });
|
|
5106
|
-
}
|
|
5107
|
-
function IconInfo({ className, ...props }) {
|
|
5108
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
|
|
5109
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
|
|
5110
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M12 16v-4" }),
|
|
5111
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M12 8h.01" })
|
|
5112
|
-
] });
|
|
5113
|
-
}
|
|
5114
|
-
function IconArrowRight({ className, ...props }) {
|
|
5115
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
|
|
5116
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M5 12h14" }),
|
|
5117
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m12 5 7 7-7 7" })
|
|
5118
|
-
] });
|
|
5119
|
-
}
|
|
5120
|
-
function IconSection({ className, ...props }) {
|
|
5121
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
|
|
5122
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("rect", { width: "18", height: "7", x: "3", y: "3", rx: "1" }),
|
|
5123
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("rect", { width: "9", height: "7", x: "3", y: "14", rx: "1" }),
|
|
5124
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("rect", { width: "5", height: "7", x: "16", y: "14", rx: "1" })
|
|
5125
|
-
] });
|
|
5126
|
-
}
|
|
5127
|
-
|
|
5128
|
-
// src/ui/dialog.tsx
|
|
5129
|
-
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
5130
|
-
function Dialog2({ ...props }) {
|
|
5131
|
-
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_radix_ui5.Dialog.Root, { "data-slot": "dialog", ...props });
|
|
5101
|
+
function Dialog2({
|
|
5102
|
+
...props
|
|
5103
|
+
}) {
|
|
5104
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_radix_ui5.Dialog.Root, { "data-slot": "dialog", ...props });
|
|
5132
5105
|
}
|
|
5133
|
-
function DialogPortal({
|
|
5134
|
-
|
|
5106
|
+
function DialogPortal({
|
|
5107
|
+
...props
|
|
5108
|
+
}) {
|
|
5109
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_radix_ui5.Dialog.Portal, { ...props });
|
|
5135
5110
|
}
|
|
5136
5111
|
function DialogOverlay({
|
|
5137
5112
|
className,
|
|
5138
5113
|
...props
|
|
5139
5114
|
}) {
|
|
5140
|
-
return /* @__PURE__ */ (0,
|
|
5115
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
5141
5116
|
import_radix_ui5.Dialog.Overlay,
|
|
5142
5117
|
{
|
|
5143
5118
|
"data-slot": "dialog-overlay",
|
|
@@ -5147,57 +5122,74 @@ function DialogOverlay({
|
|
|
5147
5122
|
}
|
|
5148
5123
|
);
|
|
5149
5124
|
}
|
|
5150
|
-
var DialogContent = React7.forwardRef(
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
/* @__PURE__ */ (0,
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
children
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
});
|
|
5125
|
+
var DialogContent = React7.forwardRef(
|
|
5126
|
+
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
5127
|
+
const positionMode = container ? "absolute" : "fixed";
|
|
5128
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(DialogPortal, { container: container ?? void 0, children: [
|
|
5129
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
5130
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
5131
|
+
import_radix_ui5.Dialog.Content,
|
|
5132
|
+
{
|
|
5133
|
+
ref,
|
|
5134
|
+
"data-slot": "dialog-content",
|
|
5135
|
+
className: cn(
|
|
5136
|
+
positionMode,
|
|
5137
|
+
"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",
|
|
5138
|
+
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
5139
|
+
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
5140
|
+
className
|
|
5141
|
+
),
|
|
5142
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
5143
|
+
...props,
|
|
5144
|
+
children: [
|
|
5145
|
+
children,
|
|
5146
|
+
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
5147
|
+
import_radix_ui5.Dialog.Close,
|
|
5148
|
+
{
|
|
5149
|
+
type: "button",
|
|
5150
|
+
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
5151
|
+
"aria-label": "Close",
|
|
5152
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react4.X, { size: 16, "aria-hidden": true })
|
|
5153
|
+
}
|
|
5154
|
+
) : null
|
|
5155
|
+
]
|
|
5156
|
+
}
|
|
5157
|
+
)
|
|
5158
|
+
] });
|
|
5159
|
+
}
|
|
5160
|
+
);
|
|
5184
5161
|
DialogContent.displayName = import_radix_ui5.Dialog.Content.displayName;
|
|
5185
|
-
function DialogHeader({
|
|
5186
|
-
|
|
5162
|
+
function DialogHeader({
|
|
5163
|
+
className,
|
|
5164
|
+
...props
|
|
5165
|
+
}) {
|
|
5166
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
5187
5167
|
}
|
|
5188
|
-
function DialogFooter({
|
|
5189
|
-
|
|
5168
|
+
function DialogFooter({
|
|
5169
|
+
className,
|
|
5170
|
+
...props
|
|
5171
|
+
}) {
|
|
5172
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
5173
|
+
"div",
|
|
5174
|
+
{
|
|
5175
|
+
className: cn("flex items-center justify-end gap-2", className),
|
|
5176
|
+
...props
|
|
5177
|
+
}
|
|
5178
|
+
);
|
|
5190
5179
|
}
|
|
5191
|
-
var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0,
|
|
5180
|
+
var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
5192
5181
|
import_radix_ui5.Dialog.Title,
|
|
5193
5182
|
{
|
|
5194
5183
|
ref,
|
|
5195
|
-
className: cn(
|
|
5184
|
+
className: cn(
|
|
5185
|
+
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
5186
|
+
className
|
|
5187
|
+
),
|
|
5196
5188
|
...props
|
|
5197
5189
|
}
|
|
5198
5190
|
));
|
|
5199
5191
|
DialogTitle.displayName = import_radix_ui5.Dialog.Title.displayName;
|
|
5200
|
-
var DialogDescription = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0,
|
|
5192
|
+
var DialogDescription = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
5201
5193
|
import_radix_ui5.Dialog.Description,
|
|
5202
5194
|
{
|
|
5203
5195
|
ref,
|
|
@@ -5208,38 +5200,64 @@ var DialogDescription = React7.forwardRef(({ className, ...props }, ref) => /* @
|
|
|
5208
5200
|
DialogDescription.displayName = import_radix_ui5.Dialog.Description.displayName;
|
|
5209
5201
|
var DialogClose = import_radix_ui5.Dialog.Close;
|
|
5210
5202
|
|
|
5203
|
+
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
5204
|
+
var import_lucide_react8 = require("lucide-react");
|
|
5205
|
+
|
|
5211
5206
|
// src/ui/link-modal/DestinationBreadcrumb.tsx
|
|
5212
|
-
var
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5207
|
+
var import_lucide_react5 = require("lucide-react");
|
|
5208
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
5209
|
+
function DestinationBreadcrumb({
|
|
5210
|
+
pageTitle,
|
|
5211
|
+
sectionLabel
|
|
5212
|
+
}) {
|
|
5213
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
|
|
5214
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-sm font-medium! text-foreground m-0", children: "Destination" }),
|
|
5215
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
5216
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
5217
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react5.File, { size: 16, className: "shrink-0 text-foreground", "aria-hidden": true }),
|
|
5218
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
|
|
5220
5219
|
] }),
|
|
5221
|
-
/* @__PURE__ */ (0,
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5220
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
5221
|
+
import_lucide_react5.ArrowRight,
|
|
5222
|
+
{
|
|
5223
|
+
size: 16,
|
|
5224
|
+
className: "shrink-0 text-muted-foreground",
|
|
5225
|
+
"aria-hidden": true
|
|
5226
|
+
}
|
|
5227
|
+
),
|
|
5228
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
|
|
5229
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
5230
|
+
import_lucide_react5.GalleryVertical,
|
|
5231
|
+
{
|
|
5232
|
+
size: 16,
|
|
5233
|
+
className: "shrink-0 text-foreground",
|
|
5234
|
+
"aria-hidden": true
|
|
5235
|
+
}
|
|
5236
|
+
),
|
|
5237
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
|
|
5225
5238
|
] })
|
|
5226
5239
|
] })
|
|
5227
5240
|
] });
|
|
5228
5241
|
}
|
|
5229
5242
|
|
|
5230
5243
|
// src/ui/link-modal/SectionTreeItem.tsx
|
|
5231
|
-
var
|
|
5232
|
-
|
|
5244
|
+
var import_lucide_react6 = require("lucide-react");
|
|
5245
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
5246
|
+
function SectionTreeItem({
|
|
5247
|
+
section,
|
|
5248
|
+
onSelect,
|
|
5249
|
+
selected
|
|
5250
|
+
}) {
|
|
5233
5251
|
const interactive = Boolean(onSelect);
|
|
5234
|
-
return /* @__PURE__ */ (0,
|
|
5235
|
-
/* @__PURE__ */ (0,
|
|
5252
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex h-9 w-full items-end pl-3", children: [
|
|
5253
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
5236
5254
|
"div",
|
|
5237
5255
|
{
|
|
5238
5256
|
className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
|
|
5239
5257
|
"aria-hidden": true
|
|
5240
5258
|
}
|
|
5241
5259
|
),
|
|
5242
|
-
/* @__PURE__ */ (0,
|
|
5260
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
5243
5261
|
"div",
|
|
5244
5262
|
{
|
|
5245
5263
|
role: interactive ? "button" : void 0,
|
|
@@ -5257,32 +5275,30 @@ function SectionTreeItem({ section, onSelect, selected }) {
|
|
|
5257
5275
|
interactive && selected && "border-primary"
|
|
5258
5276
|
),
|
|
5259
5277
|
children: [
|
|
5260
|
-
/* @__PURE__ */ (0,
|
|
5261
|
-
|
|
5278
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
5279
|
+
import_lucide_react6.GalleryVertical,
|
|
5280
|
+
{
|
|
5281
|
+
size: 16,
|
|
5282
|
+
className: "shrink-0 text-foreground",
|
|
5283
|
+
"aria-hidden": true
|
|
5284
|
+
}
|
|
5285
|
+
),
|
|
5286
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
|
|
5262
5287
|
]
|
|
5263
5288
|
}
|
|
5264
5289
|
)
|
|
5265
5290
|
] });
|
|
5266
5291
|
}
|
|
5267
|
-
function SectionPickerList({ sections, onSelect }) {
|
|
5268
|
-
if (sections.length === 0) {
|
|
5269
|
-
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." });
|
|
5270
|
-
}
|
|
5271
|
-
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
5272
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-sm text-muted-foreground", children: "Pick a section this link should scroll to." }),
|
|
5273
|
-
sections.map((section) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(SectionTreeItem, { section, onSelect }, section.id))
|
|
5274
|
-
] });
|
|
5275
|
-
}
|
|
5276
5292
|
|
|
5277
5293
|
// src/ui/link-modal/UrlOrPageInput.tsx
|
|
5278
5294
|
var import_react4 = require("react");
|
|
5279
5295
|
|
|
5280
5296
|
// src/ui/input.tsx
|
|
5281
5297
|
var React8 = __toESM(require("react"), 1);
|
|
5282
|
-
var
|
|
5298
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
5283
5299
|
var Input = React8.forwardRef(
|
|
5284
5300
|
({ className, type, ...props }, ref) => {
|
|
5285
|
-
return /* @__PURE__ */ (0,
|
|
5301
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
5286
5302
|
"input",
|
|
5287
5303
|
{
|
|
5288
5304
|
type,
|
|
@@ -5301,9 +5317,9 @@ Input.displayName = "Input";
|
|
|
5301
5317
|
|
|
5302
5318
|
// src/ui/label.tsx
|
|
5303
5319
|
var import_radix_ui6 = require("radix-ui");
|
|
5304
|
-
var
|
|
5320
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
5305
5321
|
function Label({ className, ...props }) {
|
|
5306
|
-
return /* @__PURE__ */ (0,
|
|
5322
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
5307
5323
|
import_radix_ui6.Label.Root,
|
|
5308
5324
|
{
|
|
5309
5325
|
"data-slot": "label",
|
|
@@ -5314,9 +5330,12 @@ function Label({ className, ...props }) {
|
|
|
5314
5330
|
}
|
|
5315
5331
|
|
|
5316
5332
|
// src/ui/link-modal/UrlOrPageInput.tsx
|
|
5317
|
-
var
|
|
5318
|
-
|
|
5319
|
-
|
|
5333
|
+
var import_lucide_react7 = require("lucide-react");
|
|
5334
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
5335
|
+
function FieldChevron({
|
|
5336
|
+
onClick
|
|
5337
|
+
}) {
|
|
5338
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5320
5339
|
"button",
|
|
5321
5340
|
{
|
|
5322
5341
|
type: "button",
|
|
@@ -5324,7 +5343,7 @@ function FieldChevron({ onClick }) {
|
|
|
5324
5343
|
onClick,
|
|
5325
5344
|
"aria-label": "Open page list",
|
|
5326
5345
|
tabIndex: -1,
|
|
5327
|
-
children: /* @__PURE__ */ (0,
|
|
5346
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.ChevronDown, { size: 16 })
|
|
5328
5347
|
}
|
|
5329
5348
|
);
|
|
5330
5349
|
}
|
|
@@ -5342,7 +5361,29 @@ function UrlOrPageInput({
|
|
|
5342
5361
|
}) {
|
|
5343
5362
|
const inputId = (0, import_react4.useId)();
|
|
5344
5363
|
const inputRef = (0, import_react4.useRef)(null);
|
|
5364
|
+
const rootRef = (0, import_react4.useRef)(null);
|
|
5345
5365
|
const [isFocused, setIsFocused] = (0, import_react4.useState)(false);
|
|
5366
|
+
(0, import_react4.useEffect)(() => {
|
|
5367
|
+
if (!dropdownOpen) return;
|
|
5368
|
+
const isOutside = (e) => {
|
|
5369
|
+
const root = rootRef.current;
|
|
5370
|
+
if (!root) return true;
|
|
5371
|
+
const path = typeof e.composedPath === "function" ? e.composedPath() : [];
|
|
5372
|
+
if (path.includes(root)) return false;
|
|
5373
|
+
const target = e.target;
|
|
5374
|
+
return !(target instanceof Node && root.contains(target));
|
|
5375
|
+
};
|
|
5376
|
+
const closeIfOutside = (e) => {
|
|
5377
|
+
if (!isOutside(e)) return;
|
|
5378
|
+
onDropdownOpenChange(false);
|
|
5379
|
+
};
|
|
5380
|
+
document.addEventListener("pointerdown", closeIfOutside, true);
|
|
5381
|
+
document.addEventListener("mousedown", closeIfOutside, true);
|
|
5382
|
+
return () => {
|
|
5383
|
+
document.removeEventListener("pointerdown", closeIfOutside, true);
|
|
5384
|
+
document.removeEventListener("mousedown", closeIfOutside, true);
|
|
5385
|
+
};
|
|
5386
|
+
}, [dropdownOpen, onDropdownOpenChange]);
|
|
5346
5387
|
const openDropdown = () => {
|
|
5347
5388
|
if (readOnly || filteredPages.length === 0) return;
|
|
5348
5389
|
onDropdownOpenChange(true);
|
|
@@ -5360,15 +5401,22 @@ function UrlOrPageInput({
|
|
|
5360
5401
|
requestAnimationFrame(() => inputRef.current?.focus());
|
|
5361
5402
|
};
|
|
5362
5403
|
const fieldClassName = cn(
|
|
5363
|
-
"data-ohw-link-field flex h-
|
|
5404
|
+
"data-ohw-link-field flex h-[36px] w-full items-center overflow-hidden rounded-md border bg-background pl-3 pr-3 py-2 outline-none transition-[border-color,box-shadow]",
|
|
5364
5405
|
urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
|
|
5365
5406
|
);
|
|
5366
|
-
return /* @__PURE__ */ (0,
|
|
5367
|
-
/* @__PURE__ */ (0,
|
|
5368
|
-
/* @__PURE__ */ (0,
|
|
5369
|
-
/* @__PURE__ */ (0,
|
|
5370
|
-
selectedPage ? /* @__PURE__ */ (0,
|
|
5371
|
-
|
|
5407
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
|
|
5408
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
|
|
5409
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { ref: rootRef, className: "relative w-full", children: [
|
|
5410
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
|
|
5411
|
+
selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5412
|
+
import_lucide_react7.File,
|
|
5413
|
+
{
|
|
5414
|
+
size: 16,
|
|
5415
|
+
className: "shrink-0 text-foreground",
|
|
5416
|
+
"aria-hidden": true
|
|
5417
|
+
}
|
|
5418
|
+
) }) : null,
|
|
5419
|
+
readOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5372
5420
|
Input,
|
|
5373
5421
|
{
|
|
5374
5422
|
ref: inputRef,
|
|
@@ -5379,7 +5427,14 @@ function UrlOrPageInput({
|
|
|
5379
5427
|
setIsFocused(true);
|
|
5380
5428
|
if (!selectedPage) openDropdown();
|
|
5381
5429
|
},
|
|
5382
|
-
onBlur: () =>
|
|
5430
|
+
onBlur: () => {
|
|
5431
|
+
setIsFocused(false);
|
|
5432
|
+
requestAnimationFrame(() => {
|
|
5433
|
+
if (!rootRef.current?.contains(document.activeElement)) {
|
|
5434
|
+
onDropdownOpenChange(false);
|
|
5435
|
+
}
|
|
5436
|
+
});
|
|
5437
|
+
},
|
|
5383
5438
|
placeholder,
|
|
5384
5439
|
className: cn(
|
|
5385
5440
|
"min-w-0 flex-1 truncate border-0 bg-transparent p-0 text-sm font-normal leading-5 shadow-none outline-none ring-0 caret-foreground",
|
|
@@ -5387,7 +5442,7 @@ function UrlOrPageInput({
|
|
|
5387
5442
|
)
|
|
5388
5443
|
}
|
|
5389
5444
|
),
|
|
5390
|
-
selectedPage && !readOnly ? /* @__PURE__ */ (0,
|
|
5445
|
+
selectedPage && !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5391
5446
|
"button",
|
|
5392
5447
|
{
|
|
5393
5448
|
type: "button",
|
|
@@ -5395,26 +5450,26 @@ function UrlOrPageInput({
|
|
|
5395
5450
|
onMouseDown: clearSelection,
|
|
5396
5451
|
"aria-label": "Clear selected page",
|
|
5397
5452
|
tabIndex: -1,
|
|
5398
|
-
children: /* @__PURE__ */ (0,
|
|
5453
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.X, { size: 16, "aria-hidden": true })
|
|
5399
5454
|
}
|
|
5400
5455
|
) : null,
|
|
5401
|
-
!readOnly ? /* @__PURE__ */ (0,
|
|
5456
|
+
!readOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(FieldChevron, { onClick: toggleDropdown }) : null
|
|
5402
5457
|
] }),
|
|
5403
|
-
dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ (0,
|
|
5458
|
+
dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5404
5459
|
"div",
|
|
5405
5460
|
{
|
|
5406
5461
|
"data-ohw-link-page-dropdown": "",
|
|
5407
|
-
className: "absolute left-0 right-0
|
|
5462
|
+
className: "absolute left-0 right-0 top-[calc(100%+4px)] z-50 max-h-48 overflow-auto rounded-lg border border-border bg-popover py-1 shadow-lg",
|
|
5408
5463
|
onMouseDown: (e) => e.preventDefault(),
|
|
5409
|
-
children: filteredPages.map((page) => /* @__PURE__ */ (0,
|
|
5464
|
+
children: filteredPages.map((page) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
5410
5465
|
"button",
|
|
5411
5466
|
{
|
|
5412
5467
|
type: "button",
|
|
5413
5468
|
className: "flex h-9 w-full items-center gap-2 border-0 bg-transparent px-3 text-left text-sm leading-5 text-foreground outline-none hover:bg-muted",
|
|
5414
5469
|
onClick: () => onPageSelect(page),
|
|
5415
5470
|
children: [
|
|
5416
|
-
/* @__PURE__ */ (0,
|
|
5417
|
-
/* @__PURE__ */ (0,
|
|
5471
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.File, { size: 16, className: "shrink-0", "aria-hidden": true }),
|
|
5472
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "truncate", children: page.title })
|
|
5418
5473
|
]
|
|
5419
5474
|
},
|
|
5420
5475
|
page.path
|
|
@@ -5422,108 +5477,539 @@ function UrlOrPageInput({
|
|
|
5422
5477
|
}
|
|
5423
5478
|
) : null
|
|
5424
5479
|
] }),
|
|
5425
|
-
urlError ? /* @__PURE__ */ (0,
|
|
5480
|
+
urlError ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
|
|
5426
5481
|
] });
|
|
5427
5482
|
}
|
|
5428
5483
|
|
|
5429
|
-
// src/ui/link-modal/
|
|
5484
|
+
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
5485
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
5486
|
+
function LinkEditorPanel({ state, onClose }) {
|
|
5487
|
+
const isCancel = state.secondaryLabel === "Cancel" || state.secondaryLabel === "Back to sections";
|
|
5488
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
|
|
5489
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DialogClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5490
|
+
"button",
|
|
5491
|
+
{
|
|
5492
|
+
type: "button",
|
|
5493
|
+
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50 h-7",
|
|
5494
|
+
"aria-label": "Close",
|
|
5495
|
+
onClick: onClose,
|
|
5496
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.X, { size: 16, "aria-hidden": true })
|
|
5497
|
+
}
|
|
5498
|
+
) }),
|
|
5499
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
|
|
5500
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
|
|
5501
|
+
state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5502
|
+
DestinationBreadcrumb,
|
|
5503
|
+
{
|
|
5504
|
+
pageTitle: state.selectedPage.title,
|
|
5505
|
+
sectionLabel: state.selectedSection.label
|
|
5506
|
+
}
|
|
5507
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5508
|
+
UrlOrPageInput,
|
|
5509
|
+
{
|
|
5510
|
+
value: state.searchValue,
|
|
5511
|
+
selectedPage: state.selectedPage,
|
|
5512
|
+
dropdownOpen: state.dropdownOpen,
|
|
5513
|
+
onDropdownOpenChange: state.setDropdownOpen,
|
|
5514
|
+
filteredPages: state.filteredPages,
|
|
5515
|
+
onInputChange: state.handleInputChange,
|
|
5516
|
+
onPageSelect: state.handlePageSelect,
|
|
5517
|
+
urlError: state.urlError
|
|
5518
|
+
}
|
|
5519
|
+
),
|
|
5520
|
+
state.showChooseSection ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex flex-col justify-center gap-2", children: [
|
|
5521
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5522
|
+
Button,
|
|
5523
|
+
{
|
|
5524
|
+
type: "button",
|
|
5525
|
+
variant: "outline",
|
|
5526
|
+
className: "w-fit cursor-pointer",
|
|
5527
|
+
size: "sm",
|
|
5528
|
+
onClick: state.handleChooseSection,
|
|
5529
|
+
children: "Choose a section"
|
|
5530
|
+
}
|
|
5531
|
+
),
|
|
5532
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
|
|
5533
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Info, { size: 16, className: "shrink-0", "aria-hidden": true }),
|
|
5534
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: "Pick a section this link should scroll to." })
|
|
5535
|
+
] })
|
|
5536
|
+
] }) : null,
|
|
5537
|
+
state.showSectionRow && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
|
|
5538
|
+
] }),
|
|
5539
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(DialogFooter, { className: "w-full px-6 pb-6", children: [
|
|
5540
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5541
|
+
Button,
|
|
5542
|
+
{
|
|
5543
|
+
type: "button",
|
|
5544
|
+
variant: isCancel ? "outline" : "ghost",
|
|
5545
|
+
className: "leading-6 shadow-none cursor-pointer",
|
|
5546
|
+
style: isCancel ? {
|
|
5547
|
+
backgroundColor: "var(--ohw-background)",
|
|
5548
|
+
borderColor: "var(--ohw-border)",
|
|
5549
|
+
color: "var(--ohw-foreground)"
|
|
5550
|
+
} : void 0,
|
|
5551
|
+
onClick: state.handleSecondary,
|
|
5552
|
+
children: state.secondaryLabel
|
|
5553
|
+
}
|
|
5554
|
+
),
|
|
5555
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5556
|
+
Button,
|
|
5557
|
+
{
|
|
5558
|
+
type: "button",
|
|
5559
|
+
className: "border-0 leading-6 shadow-none hover:opacity-90 disabled:opacity-50 cursor-pointer",
|
|
5560
|
+
style: {
|
|
5561
|
+
backgroundColor: "var(--ohw-primary)",
|
|
5562
|
+
color: "var(--ohw-primary-foreground)"
|
|
5563
|
+
},
|
|
5564
|
+
disabled: !state.isValid,
|
|
5565
|
+
onClick: state.handleSubmit,
|
|
5566
|
+
children: state.submitLabel
|
|
5567
|
+
}
|
|
5568
|
+
)
|
|
5569
|
+
] })
|
|
5570
|
+
] });
|
|
5571
|
+
}
|
|
5572
|
+
|
|
5573
|
+
// src/ui/link-modal/SectionPickerOverlay.tsx
|
|
5430
5574
|
var import_react5 = require("react");
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5575
|
+
var import_react_dom = require("react-dom");
|
|
5576
|
+
var import_lucide_react9 = require("lucide-react");
|
|
5577
|
+
var import_navigation = require("next/navigation");
|
|
5578
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
5579
|
+
var DIM_OVERLAY = "rgba(0, 0, 0, 0.45)";
|
|
5580
|
+
function rectsEqual(a, b) {
|
|
5581
|
+
if (a.size !== b.size) return false;
|
|
5582
|
+
for (const [id, rect] of a) {
|
|
5583
|
+
const other = b.get(id);
|
|
5584
|
+
if (!other || rect.top !== other.top || rect.left !== other.left || rect.width !== other.width || rect.height !== other.height) {
|
|
5585
|
+
return false;
|
|
5586
|
+
}
|
|
5587
|
+
}
|
|
5588
|
+
return true;
|
|
5589
|
+
}
|
|
5590
|
+
function readSectionRects(sectionIds) {
|
|
5591
|
+
const next = /* @__PURE__ */ new Map();
|
|
5592
|
+
for (const id of sectionIds) {
|
|
5593
|
+
const el = document.querySelector(
|
|
5594
|
+
`[data-ohw-section="${CSS.escape(id)}"]`
|
|
5595
|
+
);
|
|
5596
|
+
if (el) next.set(id, el.getBoundingClientRect());
|
|
5597
|
+
}
|
|
5598
|
+
return next;
|
|
5599
|
+
}
|
|
5600
|
+
function hitTestSectionId(x, y, sectionIds, rects) {
|
|
5601
|
+
for (const id of sectionIds) {
|
|
5602
|
+
const rect = rects.get(id);
|
|
5603
|
+
if (!rect || rect.width <= 0 || rect.height <= 0) continue;
|
|
5604
|
+
if (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom) {
|
|
5605
|
+
return id;
|
|
5606
|
+
}
|
|
5607
|
+
}
|
|
5608
|
+
return null;
|
|
5609
|
+
}
|
|
5610
|
+
function useSectionRects(sectionIdsKey, enabled) {
|
|
5611
|
+
const [rects, setRects] = (0, import_react5.useState)(/* @__PURE__ */ new Map());
|
|
5612
|
+
const sectionIds = (0, import_react5.useMemo)(
|
|
5613
|
+
() => sectionIdsKey ? sectionIdsKey.split("\0") : [],
|
|
5614
|
+
[sectionIdsKey]
|
|
5445
5615
|
);
|
|
5446
|
-
const [searchValue, setSearchValue] = (0, import_react5.useState)("");
|
|
5447
|
-
const [selectedPage, setSelectedPage] = (0, import_react5.useState)(null);
|
|
5448
|
-
const [selectedSection, setSelectedSection] = (0, import_react5.useState)(null);
|
|
5449
|
-
const [step, setStep] = (0, import_react5.useState)("input");
|
|
5450
|
-
const [dropdownOpen, setDropdownOpen] = (0, import_react5.useState)(false);
|
|
5451
|
-
const [urlError, setUrlError] = (0, import_react5.useState)("");
|
|
5452
|
-
const reset = (0, import_react5.useCallback)(() => {
|
|
5453
|
-
setSearchValue("");
|
|
5454
|
-
setSelectedPage(null);
|
|
5455
|
-
setSelectedSection(null);
|
|
5456
|
-
setStep("input");
|
|
5457
|
-
setDropdownOpen(false);
|
|
5458
|
-
setUrlError("");
|
|
5459
|
-
}, []);
|
|
5460
5616
|
(0, import_react5.useEffect)(() => {
|
|
5461
|
-
if (!
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
const targetSections = getSectionsForPath(sectionsByPath, pageRoute);
|
|
5465
|
-
const init = getEditModeInitialState(initialTarget, pages, targetSections);
|
|
5466
|
-
setSearchValue(init.searchValue);
|
|
5467
|
-
setSelectedPage(init.selectedPage);
|
|
5468
|
-
setSelectedSection(init.selectedSection);
|
|
5469
|
-
setStep(init.step);
|
|
5470
|
-
} else {
|
|
5471
|
-
reset();
|
|
5617
|
+
if (!enabled || sectionIds.length === 0) {
|
|
5618
|
+
setRects((prev) => prev.size === 0 ? prev : /* @__PURE__ */ new Map());
|
|
5619
|
+
return;
|
|
5472
5620
|
}
|
|
5473
|
-
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
setSelectedPage(null);
|
|
5491
|
-
setSelectedSection(null);
|
|
5492
|
-
setStep("input");
|
|
5493
|
-
setUrlError("");
|
|
5494
|
-
const filtered = value.trim() ? availablePages.filter((p) => p.title.toLowerCase().startsWith(value.toLowerCase())) : availablePages;
|
|
5495
|
-
setDropdownOpen(filtered.length > 0);
|
|
5496
|
-
if (value.trim()) {
|
|
5497
|
-
setUrlError(validateUrlInput(value, availablePages, pages));
|
|
5621
|
+
const update = () => {
|
|
5622
|
+
const next = readSectionRects(sectionIds);
|
|
5623
|
+
setRects((prev) => rectsEqual(prev, next) ? prev : next);
|
|
5624
|
+
};
|
|
5625
|
+
update();
|
|
5626
|
+
const opts = { capture: true, passive: true };
|
|
5627
|
+
window.addEventListener("scroll", update, opts);
|
|
5628
|
+
window.addEventListener("resize", update);
|
|
5629
|
+
const vv = window.visualViewport;
|
|
5630
|
+
vv?.addEventListener("resize", update);
|
|
5631
|
+
vv?.addEventListener("scroll", update);
|
|
5632
|
+
const ro = new ResizeObserver(update);
|
|
5633
|
+
for (const id of sectionIds) {
|
|
5634
|
+
const el = document.querySelector(
|
|
5635
|
+
`[data-ohw-section="${CSS.escape(id)}"]`
|
|
5636
|
+
);
|
|
5637
|
+
if (el) ro.observe(el);
|
|
5498
5638
|
}
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5639
|
+
return () => {
|
|
5640
|
+
window.removeEventListener("scroll", update, opts);
|
|
5641
|
+
window.removeEventListener("resize", update);
|
|
5642
|
+
vv?.removeEventListener("resize", update);
|
|
5643
|
+
vv?.removeEventListener("scroll", update);
|
|
5644
|
+
ro.disconnect();
|
|
5645
|
+
};
|
|
5646
|
+
}, [sectionIds, enabled]);
|
|
5647
|
+
return rects;
|
|
5648
|
+
}
|
|
5649
|
+
function SectionPickerOverlay({
|
|
5650
|
+
pagePath,
|
|
5651
|
+
sections,
|
|
5652
|
+
onBack,
|
|
5653
|
+
onSelect
|
|
5654
|
+
}) {
|
|
5655
|
+
const router = (0, import_navigation.useRouter)();
|
|
5656
|
+
const pathname = (0, import_navigation.usePathname)();
|
|
5657
|
+
const [selectedId, setSelectedId] = (0, import_react5.useState)(null);
|
|
5658
|
+
const [hoveredId, setHoveredId] = (0, import_react5.useState)(null);
|
|
5659
|
+
const pointerRef = (0, import_react5.useRef)(null);
|
|
5660
|
+
const pointerScreenRef = (0, import_react5.useRef)(null);
|
|
5661
|
+
const iframeOffsetTopRef = (0, import_react5.useRef)(null);
|
|
5662
|
+
const sectionIdsRef = (0, import_react5.useRef)([]);
|
|
5663
|
+
const [chromeClip, setChromeClip] = (0, import_react5.useState)(
|
|
5664
|
+
() => ({
|
|
5665
|
+
top: 0,
|
|
5666
|
+
bottom: typeof window !== "undefined" ? window.innerHeight : 0
|
|
5667
|
+
})
|
|
5668
|
+
);
|
|
5669
|
+
const normalizedTarget = normalizePath(pagePath);
|
|
5670
|
+
const isOnTargetPage = normalizePath(pathname) === normalizedTarget;
|
|
5671
|
+
(0, import_react5.useEffect)(() => {
|
|
5672
|
+
if (isOnTargetPage) return;
|
|
5673
|
+
const search = readPreservedSearch();
|
|
5674
|
+
router.push(`${normalizedTarget}${search}`);
|
|
5675
|
+
}, [isOnTargetPage, normalizedTarget, router]);
|
|
5676
|
+
(0, import_react5.useEffect)(() => {
|
|
5677
|
+
document.documentElement.setAttribute("data-ohw-section-picking", "");
|
|
5678
|
+
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => {
|
|
5679
|
+
el.removeAttribute("data-ohw-hovered");
|
|
5680
|
+
});
|
|
5681
|
+
document.querySelectorAll("[data-ohw-state-hovered]").forEach((el) => {
|
|
5682
|
+
el.removeAttribute("data-ohw-state-hovered");
|
|
5683
|
+
});
|
|
5684
|
+
return () => {
|
|
5685
|
+
document.documentElement.removeAttribute("data-ohw-section-picking");
|
|
5686
|
+
};
|
|
5687
|
+
}, []);
|
|
5688
|
+
const liveSections = (0, import_react5.useMemo)(() => {
|
|
5689
|
+
if (!isOnTargetPage) return sections;
|
|
5690
|
+
const live = collectSectionsFromDom();
|
|
5691
|
+
if (live.length === 0) return sections;
|
|
5692
|
+
const labels = new Map(sections.map((s) => [s.id, s.label]));
|
|
5693
|
+
return live.map((s) => ({ id: s.id, label: labels.get(s.id) ?? s.label }));
|
|
5694
|
+
}, [isOnTargetPage, sections, pathname]);
|
|
5695
|
+
const sectionIdsKey = (0, import_react5.useMemo)(
|
|
5696
|
+
() => liveSections.map((s) => s.id).join("\0"),
|
|
5697
|
+
[liveSections]
|
|
5698
|
+
);
|
|
5699
|
+
const sectionIds = (0, import_react5.useMemo)(
|
|
5700
|
+
() => liveSections.map((s) => s.id),
|
|
5701
|
+
[liveSections]
|
|
5702
|
+
);
|
|
5703
|
+
sectionIdsRef.current = sectionIds;
|
|
5704
|
+
const rects = useSectionRects(sectionIdsKey, isOnTargetPage);
|
|
5705
|
+
const applyHoverAt = (0, import_react5.useCallback)(
|
|
5706
|
+
(x, y, liveRects) => {
|
|
5707
|
+
const ids = sectionIdsRef.current;
|
|
5708
|
+
const map = liveRects ?? readSectionRects(ids);
|
|
5709
|
+
const next = hitTestSectionId(x, y, ids, map);
|
|
5710
|
+
setHoveredId((prev) => prev === next ? prev : next);
|
|
5711
|
+
},
|
|
5712
|
+
[]
|
|
5713
|
+
);
|
|
5714
|
+
(0, import_react5.useEffect)(() => {
|
|
5715
|
+
const applyClip = (iframeOffsetTop, visibleCanvasTop, canvasH) => {
|
|
5716
|
+
const top = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
5717
|
+
const bottom = Math.min(
|
|
5718
|
+
window.innerHeight,
|
|
5719
|
+
visibleCanvasTop + canvasH - iframeOffsetTop
|
|
5720
|
+
);
|
|
5721
|
+
setChromeClip(
|
|
5722
|
+
(prev) => prev.top === top && prev.bottom === bottom ? prev : { top, bottom: Math.max(top, bottom) }
|
|
5723
|
+
);
|
|
5724
|
+
};
|
|
5725
|
+
const onParentScroll = (e) => {
|
|
5726
|
+
if (e.data?.type !== "ow:parent-scroll") return;
|
|
5727
|
+
const { iframeOffsetTop, headerH, canvasH } = e.data;
|
|
5728
|
+
applyClip(iframeOffsetTop, headerH, canvasH);
|
|
5729
|
+
iframeOffsetTopRef.current = iframeOffsetTop;
|
|
5730
|
+
if (!pointerScreenRef.current && pointerRef.current) {
|
|
5731
|
+
pointerScreenRef.current = {
|
|
5732
|
+
x: pointerRef.current.x,
|
|
5733
|
+
y: pointerRef.current.y + iframeOffsetTop
|
|
5734
|
+
};
|
|
5735
|
+
}
|
|
5736
|
+
const screen = pointerScreenRef.current;
|
|
5737
|
+
if (screen) {
|
|
5738
|
+
const next = { x: screen.x, y: screen.y - iframeOffsetTop };
|
|
5739
|
+
pointerRef.current = next;
|
|
5740
|
+
applyHoverAt(next.x, next.y);
|
|
5741
|
+
}
|
|
5742
|
+
};
|
|
5743
|
+
const onResize = () => {
|
|
5744
|
+
setChromeClip((prev) => {
|
|
5745
|
+
const bottom = Math.max(prev.top, window.innerHeight);
|
|
5746
|
+
return prev.bottom === bottom ? prev : { ...prev, bottom };
|
|
5747
|
+
});
|
|
5748
|
+
};
|
|
5749
|
+
window.addEventListener("message", onParentScroll);
|
|
5750
|
+
window.addEventListener("resize", onResize);
|
|
5751
|
+
return () => {
|
|
5752
|
+
window.removeEventListener("message", onParentScroll);
|
|
5753
|
+
window.removeEventListener("resize", onResize);
|
|
5754
|
+
};
|
|
5755
|
+
}, [applyHoverAt]);
|
|
5756
|
+
(0, import_react5.useEffect)(() => {
|
|
5757
|
+
const ptr = pointerRef.current;
|
|
5758
|
+
if (!ptr) return;
|
|
5759
|
+
applyHoverAt(ptr.x, ptr.y, rects);
|
|
5760
|
+
}, [rects, applyHoverAt]);
|
|
5761
|
+
(0, import_react5.useEffect)(() => {
|
|
5762
|
+
const rememberPointer = (clientX, clientY) => {
|
|
5763
|
+
pointerRef.current = { x: clientX, y: clientY };
|
|
5764
|
+
const top = iframeOffsetTopRef.current;
|
|
5765
|
+
if (top != null) {
|
|
5766
|
+
pointerScreenRef.current = { x: clientX, y: clientY + top };
|
|
5767
|
+
}
|
|
5768
|
+
applyHoverAt(clientX, clientY, rects);
|
|
5769
|
+
};
|
|
5770
|
+
const onPointerMove = (e) => {
|
|
5771
|
+
rememberPointer(e.clientX, e.clientY);
|
|
5772
|
+
};
|
|
5773
|
+
const onPointerSync = (e) => {
|
|
5774
|
+
if (e.data?.type !== "ow:pointer-sync") return;
|
|
5775
|
+
const { clientX, clientY } = e.data;
|
|
5776
|
+
rememberPointer(clientX, clientY);
|
|
5777
|
+
};
|
|
5778
|
+
window.addEventListener("pointermove", onPointerMove, { passive: true });
|
|
5779
|
+
window.addEventListener("message", onPointerSync);
|
|
5780
|
+
return () => {
|
|
5781
|
+
window.removeEventListener("pointermove", onPointerMove);
|
|
5782
|
+
window.removeEventListener("message", onPointerSync);
|
|
5783
|
+
};
|
|
5784
|
+
}, [rects, applyHoverAt]);
|
|
5785
|
+
const handleSelect = (0, import_react5.useCallback)(
|
|
5786
|
+
(section) => {
|
|
5787
|
+
if (selectedId) return;
|
|
5788
|
+
setSelectedId(section.id);
|
|
5789
|
+
onSelect(section);
|
|
5790
|
+
},
|
|
5791
|
+
[selectedId, onSelect]
|
|
5792
|
+
);
|
|
5793
|
+
(0, import_react5.useEffect)(() => {
|
|
5794
|
+
const onKeyDown = (e) => {
|
|
5795
|
+
if (e.key === "Escape") {
|
|
5796
|
+
e.preventDefault();
|
|
5797
|
+
e.stopPropagation();
|
|
5798
|
+
onBack();
|
|
5799
|
+
}
|
|
5800
|
+
};
|
|
5801
|
+
window.addEventListener("keydown", onKeyDown, true);
|
|
5802
|
+
return () => window.removeEventListener("keydown", onKeyDown, true);
|
|
5803
|
+
}, [onBack]);
|
|
5804
|
+
const portalRoot = typeof document !== "undefined" ? document.querySelector("[data-ohw-bridge-root]") ?? document.body : null;
|
|
5805
|
+
if (!portalRoot) return null;
|
|
5806
|
+
return (0, import_react_dom.createPortal)(
|
|
5807
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
5808
|
+
"div",
|
|
5809
|
+
{
|
|
5810
|
+
"data-ohw-section-picker": "",
|
|
5811
|
+
"data-ohw-bridge": "",
|
|
5812
|
+
className: `pointer-events-none fixed inset-0 z-[2147483647] transition-opacity duration-200 ${"opacity-100"}`,
|
|
5813
|
+
"aria-modal": true,
|
|
5814
|
+
role: "dialog",
|
|
5815
|
+
"aria-label": "Choose a section",
|
|
5816
|
+
children: [
|
|
5817
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5818
|
+
"div",
|
|
5819
|
+
{
|
|
5820
|
+
className: "pointer-events-auto fixed left-5 z-[2]",
|
|
5821
|
+
style: { top: chromeClip.top + 20 },
|
|
5822
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
5823
|
+
Button,
|
|
5824
|
+
{
|
|
5825
|
+
type: "button",
|
|
5826
|
+
variant: "outline",
|
|
5827
|
+
size: "sm",
|
|
5828
|
+
className: "h-8 min-w-0 gap-1 border-border bg-background px-2 py-1.5 shadow-sm hover:bg-muted cursor-pointer",
|
|
5829
|
+
onClick: onBack,
|
|
5830
|
+
children: [
|
|
5831
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
|
|
5832
|
+
"Back"
|
|
5833
|
+
]
|
|
5834
|
+
}
|
|
5835
|
+
)
|
|
5836
|
+
}
|
|
5837
|
+
),
|
|
5838
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5839
|
+
"div",
|
|
5840
|
+
{
|
|
5841
|
+
className: "pointer-events-none fixed left-1/2 z-[2] rounded-lg px-4 py-3 text-xs leading-4 tracking-[0.18px] text-white shadow-md",
|
|
5842
|
+
style: {
|
|
5843
|
+
top: chromeClip.bottom - 20,
|
|
5844
|
+
transform: "translate(-50%, -100%)",
|
|
5845
|
+
backgroundColor: "var(--ohw-popover-foreground, #0c0a09)"
|
|
5846
|
+
},
|
|
5847
|
+
"data-ohw-section-picker-hint": "",
|
|
5848
|
+
children: "Click on section to select"
|
|
5849
|
+
}
|
|
5850
|
+
),
|
|
5851
|
+
!isOnTargetPage ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5852
|
+
"div",
|
|
5853
|
+
{
|
|
5854
|
+
className: "pointer-events-none fixed left-1/2 z-[1] -translate-x-1/2 rounded-md bg-background/90 px-3 py-2 text-sm text-muted-foreground shadow-sm",
|
|
5855
|
+
style: { top: chromeClip.top + 64 },
|
|
5856
|
+
children: "Loading page preview\u2026"
|
|
5857
|
+
}
|
|
5858
|
+
) : null,
|
|
5859
|
+
isOnTargetPage && liveSections.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "pointer-events-auto fixed inset-0 z-[1] flex items-center justify-center bg-muted/40", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." }) }) : null,
|
|
5860
|
+
isOnTargetPage ? liveSections.map((section) => {
|
|
5861
|
+
const rect = rects.get(section.id);
|
|
5862
|
+
if (!rect || rect.width <= 0 || rect.height <= 0) return null;
|
|
5863
|
+
const isSelected = selectedId === section.id;
|
|
5864
|
+
const isHovered = hoveredId === section.id;
|
|
5865
|
+
const isLit = isSelected || isHovered;
|
|
5866
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
5867
|
+
"button",
|
|
5868
|
+
{
|
|
5869
|
+
type: "button",
|
|
5870
|
+
className: "pointer-events-auto fixed z-[1] cursor-pointer border-0 bg-transparent p-0 transition-[background-color] duration-150",
|
|
5871
|
+
style: {
|
|
5872
|
+
top: rect.top,
|
|
5873
|
+
left: rect.left,
|
|
5874
|
+
width: rect.width,
|
|
5875
|
+
height: rect.height,
|
|
5876
|
+
backgroundColor: isLit ? "transparent" : DIM_OVERLAY
|
|
5877
|
+
},
|
|
5878
|
+
"aria-label": `Select section ${section.label}`,
|
|
5879
|
+
onClick: () => handleSelect(section),
|
|
5880
|
+
children: [
|
|
5881
|
+
isLit ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5882
|
+
"span",
|
|
5883
|
+
{
|
|
5884
|
+
className: "pointer-events-none absolute",
|
|
5885
|
+
style: {
|
|
5886
|
+
inset: 4,
|
|
5887
|
+
borderRadius: "var(--radius, 6px)",
|
|
5888
|
+
border: "1.5px dashed var(--primary, #0885FE)",
|
|
5889
|
+
boxSizing: "border-box"
|
|
5890
|
+
},
|
|
5891
|
+
"aria-hidden": true
|
|
5892
|
+
}
|
|
5893
|
+
) : null,
|
|
5894
|
+
isSelected ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5895
|
+
"span",
|
|
5896
|
+
{
|
|
5897
|
+
className: "absolute right-3 top-3 flex size-8 items-center justify-center rounded-full text-white",
|
|
5898
|
+
style: { backgroundColor: "var(--ohw-primary, #0885fe)" },
|
|
5899
|
+
"aria-hidden": true,
|
|
5900
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.Check, { className: "size-5" })
|
|
5901
|
+
}
|
|
5902
|
+
) : null
|
|
5903
|
+
]
|
|
5904
|
+
},
|
|
5905
|
+
section.id
|
|
5906
|
+
);
|
|
5907
|
+
}) : null
|
|
5908
|
+
]
|
|
5909
|
+
}
|
|
5910
|
+
),
|
|
5911
|
+
portalRoot
|
|
5912
|
+
);
|
|
5913
|
+
}
|
|
5914
|
+
|
|
5915
|
+
// src/ui/link-modal/useLinkModalState.ts
|
|
5916
|
+
var import_react6 = require("react");
|
|
5917
|
+
function useLinkModalState({
|
|
5918
|
+
open,
|
|
5919
|
+
mode,
|
|
5920
|
+
pages,
|
|
5921
|
+
sections: _sections,
|
|
5922
|
+
sectionsByPath,
|
|
5923
|
+
initialTarget,
|
|
5924
|
+
existingTargets: _existingTargets,
|
|
5925
|
+
onClose,
|
|
5926
|
+
onSubmit
|
|
5927
|
+
}) {
|
|
5928
|
+
const availablePages = (0, import_react6.useMemo)(() => pages, [pages]);
|
|
5929
|
+
const [searchValue, setSearchValue] = (0, import_react6.useState)("");
|
|
5930
|
+
const [selectedPage, setSelectedPage] = (0, import_react6.useState)(null);
|
|
5931
|
+
const [selectedSection, setSelectedSection] = (0, import_react6.useState)(null);
|
|
5932
|
+
const [step, setStep] = (0, import_react6.useState)("input");
|
|
5933
|
+
const [dropdownOpen, setDropdownOpen] = (0, import_react6.useState)(false);
|
|
5934
|
+
const [urlError, setUrlError] = (0, import_react6.useState)("");
|
|
5935
|
+
const reset = (0, import_react6.useCallback)(() => {
|
|
5936
|
+
setSearchValue("");
|
|
5937
|
+
setSelectedPage(null);
|
|
5938
|
+
setSelectedSection(null);
|
|
5939
|
+
setStep("input");
|
|
5940
|
+
setDropdownOpen(false);
|
|
5941
|
+
setUrlError("");
|
|
5942
|
+
}, []);
|
|
5943
|
+
(0, import_react6.useEffect)(() => {
|
|
5944
|
+
if (!open) return;
|
|
5945
|
+
if (mode === "edit" && initialTarget) {
|
|
5946
|
+
const { pageRoute } = parseTarget(initialTarget);
|
|
5947
|
+
const targetSections = getSectionsForPath(sectionsByPath, pageRoute);
|
|
5948
|
+
const init = getEditModeInitialState(initialTarget, pages, targetSections);
|
|
5949
|
+
setSearchValue(init.searchValue);
|
|
5950
|
+
setSelectedPage(init.selectedPage);
|
|
5951
|
+
setSelectedSection(init.selectedSection);
|
|
5952
|
+
setStep(init.step);
|
|
5953
|
+
} else {
|
|
5954
|
+
reset();
|
|
5955
|
+
}
|
|
5956
|
+
setDropdownOpen(false);
|
|
5957
|
+
setUrlError("");
|
|
5958
|
+
}, [open, mode, initialTarget, reset]);
|
|
5959
|
+
const filteredPages = (0, import_react6.useMemo)(() => {
|
|
5960
|
+
if (!searchValue.trim()) return availablePages;
|
|
5961
|
+
return availablePages.filter((p) => p.title.toLowerCase().startsWith(searchValue.toLowerCase()));
|
|
5962
|
+
}, [availablePages, searchValue]);
|
|
5963
|
+
const activeSections = (0, import_react6.useMemo)(() => {
|
|
5964
|
+
if (!selectedPage) return [];
|
|
5965
|
+
return getSectionsForPath(sectionsByPath, selectedPage.path);
|
|
5966
|
+
}, [selectedPage, sectionsByPath]);
|
|
5967
|
+
const showBreadcrumb = step === "confirmed" && selectedPage && selectedSection;
|
|
5968
|
+
const showSectionPicker = step === "sectionPicker" && selectedPage;
|
|
5969
|
+
const showSectionRow = mode === "edit" && selectedPage && selectedSection && step === "input";
|
|
5970
|
+
const showChooseSection = step === "input" && selectedPage && !selectedSection && !showSectionRow && activeSections.length > 0;
|
|
5971
|
+
const handleInputChange = (value) => {
|
|
5972
|
+
setSearchValue(value);
|
|
5973
|
+
setSelectedPage(null);
|
|
5974
|
+
setSelectedSection(null);
|
|
5975
|
+
setStep("input");
|
|
5976
|
+
setUrlError("");
|
|
5977
|
+
const filtered = value.trim() ? availablePages.filter((p) => p.title.toLowerCase().startsWith(value.toLowerCase())) : availablePages;
|
|
5978
|
+
setDropdownOpen(filtered.length > 0);
|
|
5979
|
+
if (value.trim()) {
|
|
5980
|
+
setUrlError(validateUrlInput(value, availablePages, pages));
|
|
5981
|
+
}
|
|
5982
|
+
};
|
|
5983
|
+
const handlePageSelect = (page) => {
|
|
5984
|
+
setSelectedPage({ path: page.path, title: page.title });
|
|
5985
|
+
setSelectedSection(null);
|
|
5986
|
+
setSearchValue(page.title);
|
|
5987
|
+
setStep("input");
|
|
5988
|
+
setDropdownOpen(false);
|
|
5989
|
+
setUrlError("");
|
|
5990
|
+
};
|
|
5991
|
+
const handleChooseSection = () => {
|
|
5992
|
+
setStep("sectionPicker");
|
|
5993
|
+
};
|
|
5994
|
+
const handleSectionSelect = (section) => {
|
|
5995
|
+
setSelectedSection({ id: section.id, label: section.label });
|
|
5996
|
+
if (mode === "create") {
|
|
5997
|
+
setStep("confirmed");
|
|
5998
|
+
} else {
|
|
5516
5999
|
setStep("input");
|
|
5517
6000
|
}
|
|
5518
6001
|
};
|
|
5519
6002
|
const handleBackToSections = () => {
|
|
5520
6003
|
setStep("sectionPicker");
|
|
5521
6004
|
};
|
|
6005
|
+
const handleSectionPickerBack = () => {
|
|
6006
|
+
setStep("input");
|
|
6007
|
+
};
|
|
5522
6008
|
const handleClose = () => {
|
|
5523
6009
|
reset();
|
|
5524
6010
|
onClose();
|
|
5525
6011
|
};
|
|
5526
|
-
const isValid = (0,
|
|
6012
|
+
const isValid = (0, import_react6.useMemo)(() => {
|
|
5527
6013
|
if (urlError) return false;
|
|
5528
6014
|
if (showBreadcrumb) return true;
|
|
5529
6015
|
if (selectedPage) return true;
|
|
@@ -5556,7 +6042,7 @@ function useLinkModalState({
|
|
|
5556
6042
|
onSubmit(normalizeUrl(searchValue));
|
|
5557
6043
|
handleClose();
|
|
5558
6044
|
};
|
|
5559
|
-
const submitLabel = mode === "edit" ? "Save" : "Create";
|
|
6045
|
+
const submitLabel = showBreadcrumb ? "Save" : mode === "edit" ? "Save" : "Create";
|
|
5560
6046
|
const title = mode === "edit" ? "Edit navigation item" : "Create navigation item";
|
|
5561
6047
|
const secondaryLabel = showBreadcrumb ? "Back to sections" : "Cancel";
|
|
5562
6048
|
const handleSecondary = showBreadcrumb ? handleBackToSections : handleClose;
|
|
@@ -5583,23 +6069,29 @@ function useLinkModalState({
|
|
|
5583
6069
|
handleChooseSection,
|
|
5584
6070
|
handleSectionSelect,
|
|
5585
6071
|
handleBackToSections,
|
|
6072
|
+
handleSectionPickerBack,
|
|
5586
6073
|
handleClose,
|
|
5587
6074
|
handleSecondary,
|
|
5588
6075
|
handleSubmit
|
|
5589
6076
|
};
|
|
5590
6077
|
}
|
|
5591
6078
|
|
|
5592
|
-
// src/ui/link-modal/
|
|
5593
|
-
var
|
|
5594
|
-
function
|
|
6079
|
+
// src/ui/link-modal/LinkPopover.tsx
|
|
6080
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
6081
|
+
function postToParent(data) {
|
|
6082
|
+
window.parent?.postMessage(data, "*");
|
|
6083
|
+
}
|
|
6084
|
+
function LinkPopover({
|
|
5595
6085
|
open = true,
|
|
6086
|
+
panelRef,
|
|
6087
|
+
portalContainer,
|
|
6088
|
+
onClose,
|
|
5596
6089
|
mode = "create",
|
|
5597
6090
|
pages,
|
|
5598
6091
|
sections = [],
|
|
5599
6092
|
sectionsByPath,
|
|
5600
6093
|
initialTarget,
|
|
5601
6094
|
existingTargets = [],
|
|
5602
|
-
onClose,
|
|
5603
6095
|
onSubmit
|
|
5604
6096
|
}) {
|
|
5605
6097
|
const state = useLinkModalState({
|
|
@@ -5613,175 +6105,449 @@ function LinkEditorPanel({
|
|
|
5613
6105
|
onClose,
|
|
5614
6106
|
onSubmit
|
|
5615
6107
|
});
|
|
5616
|
-
const
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
6108
|
+
const sectionPickerActive = state.showSectionPicker && Boolean(state.selectedPage);
|
|
6109
|
+
(0, import_react7.useEffect)(() => {
|
|
6110
|
+
if (!open) return;
|
|
6111
|
+
if (sectionPickerActive) {
|
|
6112
|
+
postToParent({ type: "ui:unlock" });
|
|
6113
|
+
postToParent({ type: "ow:section-picker", active: true });
|
|
6114
|
+
document.documentElement.style.overflow = "";
|
|
6115
|
+
document.body.style.overflow = "";
|
|
6116
|
+
return () => {
|
|
6117
|
+
postToParent({ type: "ow:section-picker", active: false });
|
|
6118
|
+
};
|
|
6119
|
+
}
|
|
6120
|
+
postToParent({ type: "ow:section-picker", active: false });
|
|
6121
|
+
postToParent({ type: "ui:lock" });
|
|
6122
|
+
const html = document.documentElement;
|
|
6123
|
+
const body = document.body;
|
|
6124
|
+
const prevHtmlOverflow = html.style.overflow;
|
|
6125
|
+
const prevBodyOverflow = body.style.overflow;
|
|
6126
|
+
const prevHtmlOverscroll = html.style.overscrollBehavior;
|
|
6127
|
+
const prevBodyOverscroll = body.style.overscrollBehavior;
|
|
6128
|
+
html.style.overflow = "hidden";
|
|
6129
|
+
body.style.overflow = "hidden";
|
|
6130
|
+
html.style.overscrollBehavior = "none";
|
|
6131
|
+
body.style.overscrollBehavior = "none";
|
|
6132
|
+
const canScrollElement = (el, deltaY) => {
|
|
6133
|
+
const { overflowY } = getComputedStyle(el);
|
|
6134
|
+
if (overflowY !== "auto" && overflowY !== "scroll") return false;
|
|
6135
|
+
if (el.scrollHeight <= el.clientHeight + 1) return false;
|
|
6136
|
+
if (deltaY < 0) return el.scrollTop > 0;
|
|
6137
|
+
if (deltaY > 0)
|
|
6138
|
+
return el.scrollTop + el.clientHeight < el.scrollHeight - 1;
|
|
6139
|
+
return true;
|
|
6140
|
+
};
|
|
6141
|
+
const allowsInternalScroll = (e) => {
|
|
6142
|
+
const target = e.target;
|
|
6143
|
+
if (!(target instanceof Element)) return false;
|
|
6144
|
+
const scrollRoot = target.closest(
|
|
6145
|
+
"[data-ohw-link-page-dropdown], [data-ohw-allow-scroll]"
|
|
6146
|
+
);
|
|
6147
|
+
if (!scrollRoot) return false;
|
|
6148
|
+
const deltaY = e instanceof WheelEvent ? e.deltaY : 0;
|
|
6149
|
+
return canScrollElement(scrollRoot, deltaY);
|
|
6150
|
+
};
|
|
6151
|
+
const preventBackgroundScroll = (e) => {
|
|
6152
|
+
if (allowsInternalScroll(e)) return;
|
|
6153
|
+
e.preventDefault();
|
|
6154
|
+
};
|
|
6155
|
+
const scrollOpts = { passive: false, capture: true };
|
|
6156
|
+
document.addEventListener("wheel", preventBackgroundScroll, scrollOpts);
|
|
6157
|
+
document.addEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
6158
|
+
return () => {
|
|
6159
|
+
postToParent({ type: "ui:unlock" });
|
|
6160
|
+
html.style.overflow = prevHtmlOverflow;
|
|
6161
|
+
body.style.overflow = prevBodyOverflow;
|
|
6162
|
+
html.style.overscrollBehavior = prevHtmlOverscroll;
|
|
6163
|
+
body.style.overscrollBehavior = prevBodyOverscroll;
|
|
6164
|
+
document.removeEventListener(
|
|
6165
|
+
"wheel",
|
|
6166
|
+
preventBackgroundScroll,
|
|
6167
|
+
scrollOpts
|
|
6168
|
+
);
|
|
6169
|
+
document.removeEventListener(
|
|
6170
|
+
"touchmove",
|
|
6171
|
+
preventBackgroundScroll,
|
|
6172
|
+
scrollOpts
|
|
6173
|
+
);
|
|
6174
|
+
};
|
|
6175
|
+
}, [open, sectionPickerActive]);
|
|
6176
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
|
|
6177
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
6178
|
+
Dialog2,
|
|
5620
6179
|
{
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
6180
|
+
open: open && !sectionPickerActive,
|
|
6181
|
+
onOpenChange: (next) => {
|
|
6182
|
+
if (!next) onClose?.();
|
|
6183
|
+
},
|
|
6184
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
6185
|
+
DialogContent,
|
|
6186
|
+
{
|
|
6187
|
+
ref: panelRef,
|
|
6188
|
+
container: portalContainer,
|
|
6189
|
+
"data-ohw-link-popover-root": "",
|
|
6190
|
+
"data-ohw-link-modal-root": "",
|
|
6191
|
+
"data-ohw-bridge": "",
|
|
6192
|
+
showCloseButton: false,
|
|
6193
|
+
className: "gap-0 p-0 w-full max-w-[448px] pointer-events-auto z-[2147483646] overflow-visible",
|
|
6194
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(LinkEditorPanel, { state, onClose })
|
|
6195
|
+
}
|
|
6196
|
+
)
|
|
5625
6197
|
}
|
|
5626
|
-
)
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
UrlOrPageInput,
|
|
5637
|
-
{
|
|
5638
|
-
value: state.searchValue,
|
|
5639
|
-
selectedPage: state.selectedPage,
|
|
5640
|
-
dropdownOpen: state.dropdownOpen,
|
|
5641
|
-
onDropdownOpenChange: state.setDropdownOpen,
|
|
5642
|
-
filteredPages: state.filteredPages,
|
|
5643
|
-
onInputChange: state.handleInputChange,
|
|
5644
|
-
onPageSelect: state.handlePageSelect,
|
|
5645
|
-
urlError: state.urlError
|
|
5646
|
-
}
|
|
5647
|
-
),
|
|
5648
|
-
state.showChooseSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-col justify-center gap-2", children: [
|
|
5649
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Button, { type: "button", variant: "outline", className: "w-fit cursor-pointer", size: "sm", onClick: state.handleChooseSection, children: "Choose a section" }),
|
|
5650
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
|
|
5651
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(IconInfo, { className: "shrink-0", "aria-hidden": true }),
|
|
5652
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: "Pick a section this link should scroll to." })
|
|
5653
|
-
] })
|
|
5654
|
-
] }) : null,
|
|
5655
|
-
state.showSectionPicker ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SectionPickerList, { sections: state.activeSections, onSelect: state.handleSectionSelect }) : null,
|
|
5656
|
-
state.showSectionRow && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
|
|
5657
|
-
] }),
|
|
5658
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(DialogFooter, { className: "w-full px-6 pb-6", children: [
|
|
5659
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5660
|
-
Button,
|
|
5661
|
-
{
|
|
5662
|
-
type: "button",
|
|
5663
|
-
variant: isCancel ? "outline" : "ghost",
|
|
5664
|
-
className: "leading-6 shadow-none cursor-pointer",
|
|
5665
|
-
style: isCancel ? {
|
|
5666
|
-
backgroundColor: "var(--ohw-background)",
|
|
5667
|
-
borderColor: "var(--ohw-border)",
|
|
5668
|
-
color: "var(--ohw-foreground)"
|
|
5669
|
-
} : void 0,
|
|
5670
|
-
onClick: state.handleSecondary,
|
|
5671
|
-
children: state.secondaryLabel
|
|
5672
|
-
}
|
|
5673
|
-
),
|
|
5674
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5675
|
-
Button,
|
|
5676
|
-
{
|
|
5677
|
-
type: "button",
|
|
5678
|
-
className: "border-0 leading-6 shadow-none hover:opacity-90 disabled:opacity-50 cursor-pointer",
|
|
5679
|
-
style: {
|
|
5680
|
-
backgroundColor: "var(--ohw-primary)",
|
|
5681
|
-
color: "var(--ohw-primary-foreground)"
|
|
5682
|
-
},
|
|
5683
|
-
disabled: !state.isValid,
|
|
5684
|
-
onClick: state.handleSubmit,
|
|
5685
|
-
children: state.submitLabel
|
|
5686
|
-
}
|
|
5687
|
-
)
|
|
5688
|
-
] })
|
|
6198
|
+
),
|
|
6199
|
+
sectionPickerActive && state.selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
6200
|
+
SectionPickerOverlay,
|
|
6201
|
+
{
|
|
6202
|
+
pagePath: state.selectedPage.path,
|
|
6203
|
+
sections: state.activeSections,
|
|
6204
|
+
onBack: state.handleSectionPickerBack,
|
|
6205
|
+
onSelect: state.handleSectionSelect
|
|
6206
|
+
}
|
|
6207
|
+
) : null
|
|
5689
6208
|
] });
|
|
5690
6209
|
}
|
|
5691
6210
|
|
|
5692
|
-
// src/ui/link-modal/
|
|
5693
|
-
var
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
6211
|
+
// src/ui/link-modal/devFixtures.ts
|
|
6212
|
+
var DEV_SITE_PAGES = [
|
|
6213
|
+
{ path: "/", title: "Home" },
|
|
6214
|
+
{ path: "/about", title: "About" },
|
|
6215
|
+
{ path: "/classes", title: "Classes" },
|
|
6216
|
+
{ path: "/pricing", title: "Pricing" },
|
|
6217
|
+
{ path: "/studio", title: "Studio" },
|
|
6218
|
+
{ path: "/instructors", title: "Instructors" },
|
|
6219
|
+
{ path: "/contact", title: "Contact" }
|
|
6220
|
+
];
|
|
6221
|
+
var DEV_SECTIONS_BY_PATH = {
|
|
6222
|
+
"/": [
|
|
6223
|
+
{ id: "hero", label: "Hero" },
|
|
6224
|
+
{ id: "lagree-intro", label: "Lagree Intro" },
|
|
6225
|
+
{ id: "classes-strip", label: "Classes" },
|
|
6226
|
+
{ id: "feel-split", label: "Feel Split" },
|
|
6227
|
+
{ id: "founder-teaser", label: "Founder" },
|
|
6228
|
+
{ id: "plan-form", label: "Plan Form" },
|
|
6229
|
+
{ id: "testimonials", label: "Testimonials" },
|
|
6230
|
+
{ id: "wordmark", label: "Wordmark" },
|
|
6231
|
+
{ id: "footer", label: "Footer" }
|
|
6232
|
+
],
|
|
6233
|
+
"/about": [
|
|
6234
|
+
{ id: "manifesto", label: "Manifesto" },
|
|
6235
|
+
{ id: "story-letter", label: "Our Story" },
|
|
6236
|
+
{ id: "lagree-explainer", label: "Lagree Explainer" },
|
|
6237
|
+
{ id: "waitlist-cta", label: "Waitlist" },
|
|
6238
|
+
{ id: "personal-training", label: "Personal training" },
|
|
6239
|
+
{ id: "footer", label: "Footer" }
|
|
6240
|
+
],
|
|
6241
|
+
"/classes": [
|
|
6242
|
+
{ id: "class-library", label: "Class Library" },
|
|
6243
|
+
{ id: "footer", label: "Footer" }
|
|
6244
|
+
],
|
|
6245
|
+
"/pricing": [
|
|
6246
|
+
{ id: "page-header", label: "Page Header" },
|
|
6247
|
+
{ id: "free-class-cta", label: "Free Class" },
|
|
6248
|
+
{ id: "benefits-marquee", label: "Benefits" },
|
|
6249
|
+
{ id: "monthly-memberships", label: "Memberships" },
|
|
6250
|
+
{ id: "specialty-programs", label: "Specialty Programs" },
|
|
6251
|
+
{ id: "package-matcher", label: "Packages" },
|
|
6252
|
+
{ id: "wordmark", label: "Wordmark" },
|
|
6253
|
+
{ id: "footer", label: "Footer" }
|
|
6254
|
+
],
|
|
6255
|
+
"/studio": [
|
|
6256
|
+
{ id: "studio-intro", label: "Studio Intro" },
|
|
6257
|
+
{ id: "studio-features", label: "Studio Features" },
|
|
6258
|
+
{ id: "studio-gallery", label: "Studio Gallery" },
|
|
6259
|
+
{ id: "studio-visit", label: "Visit Studio" },
|
|
6260
|
+
{ id: "footer", label: "Footer" }
|
|
6261
|
+
],
|
|
6262
|
+
"/instructors": [
|
|
6263
|
+
{ id: "instructor-grid", label: "Instructors" },
|
|
6264
|
+
{ id: "footer", label: "Footer" }
|
|
6265
|
+
],
|
|
6266
|
+
"/contact": [
|
|
6267
|
+
{ id: "hello-hero", label: "Hello" },
|
|
6268
|
+
{ id: "contact-form", label: "Contact Form" },
|
|
6269
|
+
{ id: "faq", label: "FAQ" },
|
|
6270
|
+
{ id: "footer", label: "Footer" }
|
|
6271
|
+
]
|
|
6272
|
+
};
|
|
6273
|
+
function shouldUseDevFixtures() {
|
|
6274
|
+
if (typeof window === "undefined") return false;
|
|
6275
|
+
const raw = readPreservedSearch();
|
|
6276
|
+
const q = raw.startsWith("?") ? raw.slice(1) : raw;
|
|
6277
|
+
return new URLSearchParams(q).get("ohw-fixtures") === "1";
|
|
6278
|
+
}
|
|
6279
|
+
|
|
6280
|
+
// src/lib/nav-items.ts
|
|
6281
|
+
var NAV_COUNT_KEY = "__ohw_nav_count";
|
|
6282
|
+
var NAV_ORDER_KEY = "__ohw_nav_order";
|
|
6283
|
+
function getLinkHref(el) {
|
|
6284
|
+
const key = el.getAttribute("data-ohw-href-key");
|
|
6285
|
+
if (key) {
|
|
6286
|
+
const stored = getStoredLinkHref(key);
|
|
6287
|
+
if (stored !== void 0) return stored;
|
|
6288
|
+
}
|
|
6289
|
+
return el.getAttribute("href") ?? "";
|
|
6290
|
+
}
|
|
6291
|
+
function isNavbarButton(el) {
|
|
6292
|
+
return el.hasAttribute("data-ohw-role") && el.getAttribute("data-ohw-role") === "navbar-button";
|
|
6293
|
+
}
|
|
6294
|
+
function isNavbarLinkItem(el) {
|
|
6295
|
+
if (!el.matches("[data-ohw-href-key]")) return false;
|
|
6296
|
+
if (isNavbarButton(el)) return false;
|
|
6297
|
+
if (!el.querySelector('[data-ohw-editable="text"]')) return false;
|
|
6298
|
+
return Boolean(el.closest("nav, [data-ohw-nav-container], [data-ohw-nav-drawer]"));
|
|
6299
|
+
}
|
|
6300
|
+
function getNavbarDesktopContainer() {
|
|
6301
|
+
return document.querySelector("[data-ohw-nav-container]");
|
|
6302
|
+
}
|
|
6303
|
+
function getNavbarDrawerContainer() {
|
|
6304
|
+
return document.querySelector("[data-ohw-nav-drawer]");
|
|
6305
|
+
}
|
|
6306
|
+
function listNavbarItems() {
|
|
6307
|
+
const desktop = getNavbarDesktopContainer();
|
|
6308
|
+
if (desktop) {
|
|
6309
|
+
return Array.from(desktop.querySelectorAll("[data-ohw-href-key]")).filter(isNavbarLinkItem);
|
|
6310
|
+
}
|
|
6311
|
+
const drawer = getNavbarDrawerContainer();
|
|
6312
|
+
if (drawer) {
|
|
6313
|
+
return Array.from(drawer.querySelectorAll("[data-ohw-href-key]")).filter(isNavbarLinkItem);
|
|
6314
|
+
}
|
|
6315
|
+
return Array.from(document.querySelectorAll("nav [data-ohw-href-key]")).filter(isNavbarLinkItem);
|
|
6316
|
+
}
|
|
6317
|
+
function parseNavIndexFromKey(key) {
|
|
6318
|
+
if (!key) return null;
|
|
6319
|
+
const match = key.match(/^nav-(\d+)-href$/);
|
|
6320
|
+
if (!match) return null;
|
|
6321
|
+
return parseInt(match[1], 10);
|
|
6322
|
+
}
|
|
6323
|
+
function getNavbarIndicesInDom() {
|
|
6324
|
+
const indices = /* @__PURE__ */ new Set();
|
|
6325
|
+
for (const item of listNavbarItems()) {
|
|
6326
|
+
const idx = parseNavIndexFromKey(item.getAttribute("data-ohw-href-key"));
|
|
6327
|
+
if (idx !== null) indices.add(idx);
|
|
6328
|
+
}
|
|
6329
|
+
return [...indices].sort((a, b) => a - b);
|
|
6330
|
+
}
|
|
6331
|
+
function getNextNavbarIndex() {
|
|
6332
|
+
const indices = getNavbarIndicesInDom();
|
|
6333
|
+
if (indices.length === 0) return 0;
|
|
6334
|
+
return Math.max(...indices) + 1;
|
|
6335
|
+
}
|
|
6336
|
+
function getNavbarExistingTargets() {
|
|
6337
|
+
return listNavbarItems().map((el) => getLinkHref(el)).filter(Boolean);
|
|
6338
|
+
}
|
|
6339
|
+
function getNavOrderFromDom() {
|
|
6340
|
+
return listNavbarItems().map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key));
|
|
6341
|
+
}
|
|
6342
|
+
function parseNavOrder(content) {
|
|
6343
|
+
const raw = content[NAV_ORDER_KEY];
|
|
6344
|
+
if (!raw) return null;
|
|
6345
|
+
try {
|
|
6346
|
+
const parsed = JSON.parse(raw);
|
|
6347
|
+
if (!Array.isArray(parsed)) return null;
|
|
6348
|
+
return parsed.filter((key) => typeof key === "string" && key.length > 0);
|
|
6349
|
+
} catch {
|
|
6350
|
+
return null;
|
|
6351
|
+
}
|
|
6352
|
+
}
|
|
6353
|
+
function findCounterpartByHrefKey(hrefKey, root) {
|
|
6354
|
+
return root.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`);
|
|
6355
|
+
}
|
|
6356
|
+
function cloneNavLinkShell(template) {
|
|
6357
|
+
const anchor = document.createElement("a");
|
|
6358
|
+
if (template) {
|
|
6359
|
+
anchor.style.cssText = template.style.cssText;
|
|
6360
|
+
if (template.className) anchor.className = template.className;
|
|
6361
|
+
}
|
|
6362
|
+
anchor.style.cursor = "pointer";
|
|
6363
|
+
anchor.style.textDecoration = "none";
|
|
6364
|
+
return anchor;
|
|
6365
|
+
}
|
|
6366
|
+
function buildNavLink(index, href, label, template) {
|
|
6367
|
+
const anchor = cloneNavLinkShell(template);
|
|
6368
|
+
anchor.href = href;
|
|
6369
|
+
anchor.setAttribute("data-ohw-href-key", `nav-${index}-href`);
|
|
6370
|
+
const span = document.createElement("span");
|
|
6371
|
+
span.setAttribute("data-ohw-editable", "text");
|
|
6372
|
+
span.setAttribute("data-ohw-key", `nav-${index}-label`);
|
|
6373
|
+
span.textContent = label;
|
|
6374
|
+
anchor.appendChild(span);
|
|
6375
|
+
return anchor;
|
|
6376
|
+
}
|
|
6377
|
+
function insertNavLinkInContainer(container, anchor, afterHrefKey) {
|
|
6378
|
+
if (!afterHrefKey) {
|
|
6379
|
+
container.appendChild(anchor);
|
|
6380
|
+
return;
|
|
6381
|
+
}
|
|
6382
|
+
const afterEl = findCounterpartByHrefKey(afterHrefKey, container);
|
|
6383
|
+
if (afterEl?.parentElement === container) {
|
|
6384
|
+
afterEl.insertAdjacentElement("afterend", anchor);
|
|
6385
|
+
return;
|
|
6386
|
+
}
|
|
6387
|
+
container.appendChild(anchor);
|
|
6388
|
+
}
|
|
6389
|
+
function insertNavbarItemDom(index, href, label, afterAnchor) {
|
|
6390
|
+
const afterHrefKey = afterAnchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
6391
|
+
const desktopItems = getNavbarDesktopContainer()?.querySelectorAll("[data-ohw-href-key]") ?? [];
|
|
6392
|
+
const drawerItems = getNavbarDrawerContainer()?.querySelectorAll("[data-ohw-href-key]") ?? [];
|
|
6393
|
+
const desktopTemplate = Array.from(desktopItems).find(isNavbarLinkItem) ?? null;
|
|
6394
|
+
const drawerTemplate = Array.from(drawerItems).find(isNavbarLinkItem) ?? null;
|
|
6395
|
+
let primary = null;
|
|
6396
|
+
const desktopContainer = getNavbarDesktopContainer();
|
|
6397
|
+
if (desktopContainer) {
|
|
6398
|
+
const desktopAnchor = buildNavLink(index, href, label, desktopTemplate);
|
|
6399
|
+
insertNavLinkInContainer(desktopContainer, desktopAnchor, afterHrefKey);
|
|
6400
|
+
primary = desktopAnchor;
|
|
6401
|
+
}
|
|
6402
|
+
const drawerContainer = getNavbarDrawerContainer();
|
|
6403
|
+
if (drawerContainer) {
|
|
6404
|
+
const drawerAnchor = buildNavLink(index, href, label, drawerTemplate);
|
|
6405
|
+
insertNavLinkInContainer(drawerContainer, drawerAnchor, afterHrefKey);
|
|
6406
|
+
if (!primary) primary = drawerAnchor;
|
|
6407
|
+
}
|
|
6408
|
+
if (!primary) {
|
|
6409
|
+
const fallback = buildNavLink(index, href, label, listNavbarItems()[0] ?? null);
|
|
6410
|
+
const nav = document.querySelector("nav");
|
|
6411
|
+
nav?.appendChild(fallback);
|
|
6412
|
+
primary = fallback;
|
|
6413
|
+
}
|
|
6414
|
+
return primary;
|
|
6415
|
+
}
|
|
6416
|
+
function applyNavOrderToContainer(container, order) {
|
|
6417
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6418
|
+
for (const hrefKey of order) {
|
|
6419
|
+
if (seen.has(hrefKey)) continue;
|
|
6420
|
+
seen.add(hrefKey);
|
|
6421
|
+
const el = findCounterpartByHrefKey(hrefKey, container);
|
|
6422
|
+
if (el) container.appendChild(el);
|
|
6423
|
+
}
|
|
6424
|
+
for (const el of container.querySelectorAll("[data-ohw-href-key]")) {
|
|
6425
|
+
if (!isNavbarLinkItem(el)) continue;
|
|
6426
|
+
const key = el.getAttribute("data-ohw-href-key");
|
|
6427
|
+
if (!key || seen.has(key)) continue;
|
|
6428
|
+
container.appendChild(el);
|
|
6429
|
+
}
|
|
6430
|
+
}
|
|
6431
|
+
function applyNavOrder(order) {
|
|
6432
|
+
const desktop = getNavbarDesktopContainer();
|
|
6433
|
+
if (desktop) applyNavOrderToContainer(desktop, order);
|
|
6434
|
+
const drawer = getNavbarDrawerContainer();
|
|
6435
|
+
if (drawer) applyNavOrderToContainer(drawer, order);
|
|
6436
|
+
}
|
|
6437
|
+
function collectNavbarIndicesFromContent(content) {
|
|
6438
|
+
const indices = /* @__PURE__ */ new Set();
|
|
6439
|
+
for (const key of Object.keys(content)) {
|
|
6440
|
+
const idx = parseNavIndexFromKey(key);
|
|
6441
|
+
if (idx !== null) indices.add(idx);
|
|
6442
|
+
}
|
|
6443
|
+
const countRaw = content[NAV_COUNT_KEY];
|
|
6444
|
+
if (countRaw) {
|
|
6445
|
+
const count = parseInt(countRaw, 10);
|
|
6446
|
+
if (Number.isFinite(count) && count > 0) {
|
|
6447
|
+
for (let i = 0; i < count; i++) indices.add(i);
|
|
6448
|
+
}
|
|
6449
|
+
}
|
|
6450
|
+
return [...indices].sort((a, b) => a - b);
|
|
6451
|
+
}
|
|
6452
|
+
function navbarIndexExistsInDom(index) {
|
|
6453
|
+
return document.querySelector(`[data-ohw-href-key="nav-${index}-href"]`) !== null;
|
|
6454
|
+
}
|
|
6455
|
+
function reconcileNavbarItemsFromContent(content) {
|
|
6456
|
+
const indices = collectNavbarIndicesFromContent(content);
|
|
6457
|
+
for (const index of indices) {
|
|
6458
|
+
if (navbarIndexExistsInDom(index)) continue;
|
|
6459
|
+
const href = content[`nav-${index}-href`];
|
|
6460
|
+
const label = content[`nav-${index}-label`];
|
|
6461
|
+
if (!href && !label) continue;
|
|
6462
|
+
insertNavbarItemDom(index, href ?? "/", label ?? "Untitled", null);
|
|
6463
|
+
}
|
|
6464
|
+
const order = parseNavOrder(content);
|
|
6465
|
+
if (order?.length) applyNavOrder(order);
|
|
6466
|
+
}
|
|
6467
|
+
function buildNavOrderAfterInsert(afterAnchor, newHrefKey) {
|
|
6468
|
+
const order = getNavOrderFromDom();
|
|
6469
|
+
if (!afterAnchor) {
|
|
6470
|
+
if (!order.includes(newHrefKey)) order.push(newHrefKey);
|
|
6471
|
+
return order;
|
|
6472
|
+
}
|
|
6473
|
+
const afterKey = afterAnchor.getAttribute("data-ohw-href-key");
|
|
6474
|
+
if (!afterKey) {
|
|
6475
|
+
if (!order.includes(newHrefKey)) order.push(newHrefKey);
|
|
6476
|
+
return order;
|
|
6477
|
+
}
|
|
6478
|
+
const withoutNew = order.filter((key) => key !== newHrefKey);
|
|
6479
|
+
const pos = withoutNew.indexOf(afterKey);
|
|
6480
|
+
if (pos >= 0) {
|
|
6481
|
+
withoutNew.splice(pos + 1, 0, newHrefKey);
|
|
6482
|
+
return withoutNew;
|
|
6483
|
+
}
|
|
6484
|
+
withoutNew.push(newHrefKey);
|
|
6485
|
+
return withoutNew;
|
|
6486
|
+
}
|
|
6487
|
+
function insertNavbarItem(href, label, afterAnchor = null) {
|
|
6488
|
+
const index = getNextNavbarIndex();
|
|
6489
|
+
const anchor = insertNavbarItemDom(index, href, label, afterAnchor);
|
|
6490
|
+
if (!anchor) throw new Error("Failed to insert navbar item");
|
|
6491
|
+
const hrefKey = `nav-${index}-href`;
|
|
6492
|
+
const order = buildNavOrderAfterInsert(afterAnchor, hrefKey);
|
|
6493
|
+
applyNavOrder(order);
|
|
6494
|
+
return {
|
|
6495
|
+
anchor,
|
|
6496
|
+
index,
|
|
6497
|
+
hrefKey,
|
|
6498
|
+
labelKey: `nav-${index}-label`,
|
|
6499
|
+
href,
|
|
6500
|
+
label,
|
|
6501
|
+
order
|
|
6502
|
+
};
|
|
6503
|
+
}
|
|
6504
|
+
|
|
6505
|
+
// src/ui/navbar-container-chrome.tsx
|
|
6506
|
+
var import_lucide_react10 = require("lucide-react");
|
|
6507
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
6508
|
+
function NavbarContainerChrome({
|
|
6509
|
+
rect,
|
|
6510
|
+
onAdd
|
|
5700
6511
|
}) {
|
|
5701
|
-
|
|
5702
|
-
|
|
6512
|
+
const chromeGap = 6;
|
|
6513
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6514
|
+
"div",
|
|
5703
6515
|
{
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
6516
|
+
"data-ohw-navbar-container-chrome": "",
|
|
6517
|
+
"data-ohw-bridge": "",
|
|
6518
|
+
className: "pointer-events-none fixed z-[2147483647]",
|
|
6519
|
+
style: {
|
|
6520
|
+
top: rect.top - chromeGap,
|
|
6521
|
+
left: rect.left - chromeGap,
|
|
6522
|
+
width: rect.width + chromeGap * 2,
|
|
6523
|
+
height: rect.height + chromeGap * 2
|
|
5707
6524
|
},
|
|
5708
|
-
children: /* @__PURE__ */ (0,
|
|
5709
|
-
|
|
6525
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6526
|
+
"button",
|
|
5710
6527
|
{
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
"
|
|
5714
|
-
|
|
5715
|
-
"
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
6528
|
+
type: "button",
|
|
6529
|
+
"data-ohw-navbar-add-button": "",
|
|
6530
|
+
className: "pointer-events-auto absolute left-1/2 flex p-0.5 rounded-[10px] size-7 -translate-x-1/2 translate-y-1/2 items-center justify-center border border-border bg-background shadow-sm transition-colors hover:bg-muted/80",
|
|
6531
|
+
style: { top: "70%" },
|
|
6532
|
+
"aria-label": "Add item",
|
|
6533
|
+
onMouseDown: (e) => {
|
|
6534
|
+
e.preventDefault();
|
|
6535
|
+
e.stopPropagation();
|
|
6536
|
+
},
|
|
6537
|
+
onClick: (e) => {
|
|
6538
|
+
e.preventDefault();
|
|
6539
|
+
e.stopPropagation();
|
|
6540
|
+
onAdd();
|
|
6541
|
+
},
|
|
6542
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
5719
6543
|
}
|
|
5720
6544
|
)
|
|
5721
6545
|
}
|
|
5722
6546
|
);
|
|
5723
6547
|
}
|
|
5724
6548
|
|
|
5725
|
-
// src/ui/link-modal/devFixtures.ts
|
|
5726
|
-
var DEV_SITE_PAGES = [
|
|
5727
|
-
{ path: "/", title: "Home" },
|
|
5728
|
-
{ path: "/about", title: "About" },
|
|
5729
|
-
{ path: "/classes", title: "Classes" },
|
|
5730
|
-
{ path: "/pricing", title: "Pricing" },
|
|
5731
|
-
{ path: "/studio", title: "Studio" },
|
|
5732
|
-
{ path: "/instructors", title: "Instructors" },
|
|
5733
|
-
{ path: "/contact", title: "Contact" }
|
|
5734
|
-
];
|
|
5735
|
-
var DEV_SECTIONS_BY_PATH = {
|
|
5736
|
-
"/": [
|
|
5737
|
-
{ id: "hero", label: "Hero" },
|
|
5738
|
-
{ id: "lagree-intro", label: "Lagree Intro" },
|
|
5739
|
-
{ id: "classes-strip", label: "Classes" },
|
|
5740
|
-
{ id: "feel-split", label: "Feel Split" },
|
|
5741
|
-
{ id: "founder-teaser", label: "Founder" },
|
|
5742
|
-
{ id: "plan-form", label: "Plan Form" },
|
|
5743
|
-
{ id: "testimonials", label: "Testimonials" },
|
|
5744
|
-
{ id: "wordmark", label: "Wordmark" }
|
|
5745
|
-
],
|
|
5746
|
-
"/about": [
|
|
5747
|
-
{ id: "manifesto", label: "Manifesto" },
|
|
5748
|
-
{ id: "story-letter", label: "Our Story" },
|
|
5749
|
-
{ id: "lagree-explainer", label: "Lagree Explainer" },
|
|
5750
|
-
{ id: "waitlist-cta", label: "Waitlist" },
|
|
5751
|
-
{ id: "personal-training", label: "Personal training" }
|
|
5752
|
-
],
|
|
5753
|
-
"/classes": [{ id: "class-library", label: "Class Library" }],
|
|
5754
|
-
"/pricing": [
|
|
5755
|
-
{ id: "page-header", label: "Page Header" },
|
|
5756
|
-
{ id: "free-class-cta", label: "Free Class" },
|
|
5757
|
-
{ id: "benefits-marquee", label: "Benefits" },
|
|
5758
|
-
{ id: "monthly-memberships", label: "Memberships" },
|
|
5759
|
-
{ id: "specialty-programs", label: "Specialty Programs" },
|
|
5760
|
-
{ id: "package-matcher", label: "Packages" },
|
|
5761
|
-
{ id: "wordmark", label: "Wordmark" }
|
|
5762
|
-
],
|
|
5763
|
-
"/studio": [
|
|
5764
|
-
{ id: "studio-intro", label: "Studio Intro" },
|
|
5765
|
-
{ id: "studio-features", label: "Studio Features" },
|
|
5766
|
-
{ id: "studio-gallery", label: "Studio Gallery" },
|
|
5767
|
-
{ id: "studio-visit", label: "Visit Studio" }
|
|
5768
|
-
],
|
|
5769
|
-
"/instructors": [{ id: "instructor-grid", label: "Instructors" }],
|
|
5770
|
-
"/contact": [
|
|
5771
|
-
{ id: "hello-hero", label: "Hello" },
|
|
5772
|
-
{ id: "contact-form", label: "Contact Form" },
|
|
5773
|
-
{ id: "faq", label: "FAQ" }
|
|
5774
|
-
]
|
|
5775
|
-
};
|
|
5776
|
-
function shouldUseDevFixtures() {
|
|
5777
|
-
if (typeof window === "undefined") return false;
|
|
5778
|
-
const raw = readPreservedSearch();
|
|
5779
|
-
const q = raw.startsWith("?") ? raw.slice(1) : raw;
|
|
5780
|
-
return new URLSearchParams(q).get("ohw-fixtures") === "1";
|
|
5781
|
-
}
|
|
5782
|
-
|
|
5783
6549
|
// src/ui/badge.tsx
|
|
5784
|
-
var
|
|
6550
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
5785
6551
|
var badgeVariants = cva(
|
|
5786
6552
|
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
5787
6553
|
{
|
|
@@ -5799,12 +6565,12 @@ var badgeVariants = cva(
|
|
|
5799
6565
|
}
|
|
5800
6566
|
);
|
|
5801
6567
|
function Badge({ className, variant, ...props }) {
|
|
5802
|
-
return /* @__PURE__ */ (0,
|
|
6568
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
5803
6569
|
}
|
|
5804
6570
|
|
|
5805
6571
|
// src/OhhwellsBridge.tsx
|
|
5806
|
-
var
|
|
5807
|
-
var
|
|
6572
|
+
var import_lucide_react11 = require("lucide-react");
|
|
6573
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
5808
6574
|
var PRIMARY2 = "#0885FE";
|
|
5809
6575
|
var IMAGE_FADE_MS = 300;
|
|
5810
6576
|
function runOpacityFade(el, onDone) {
|
|
@@ -5981,9 +6747,9 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
5981
6747
|
tail.insertAdjacentElement("afterend", container);
|
|
5982
6748
|
}
|
|
5983
6749
|
const root = (0, import_client.createRoot)(container);
|
|
5984
|
-
(0,
|
|
6750
|
+
(0, import_react_dom2.flushSync)(() => {
|
|
5985
6751
|
root.render(
|
|
5986
|
-
/* @__PURE__ */ (0,
|
|
6752
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
5987
6753
|
SchedulingWidget,
|
|
5988
6754
|
{
|
|
5989
6755
|
notifyOnConnect,
|
|
@@ -6023,7 +6789,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
6023
6789
|
}
|
|
6024
6790
|
}
|
|
6025
6791
|
}
|
|
6026
|
-
function
|
|
6792
|
+
function getLinkHref2(el) {
|
|
6027
6793
|
const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
|
|
6028
6794
|
return anchor?.getAttribute("href") ?? "";
|
|
6029
6795
|
}
|
|
@@ -6060,7 +6826,7 @@ function collectEditableNodes() {
|
|
|
6060
6826
|
return { key: el.dataset.ohwKey ?? "", type: "video", text: getVideoEl(el)?.src ?? "" };
|
|
6061
6827
|
}
|
|
6062
6828
|
if (el.dataset.ohwEditable === "link") {
|
|
6063
|
-
return { key: el.dataset.ohwKey ?? "", type: "link", text:
|
|
6829
|
+
return { key: el.dataset.ohwKey ?? "", type: "link", text: getLinkHref2(el) };
|
|
6064
6830
|
}
|
|
6065
6831
|
return {
|
|
6066
6832
|
key: el.dataset.ohwKey ?? "",
|
|
@@ -6071,7 +6837,7 @@ function collectEditableNodes() {
|
|
|
6071
6837
|
document.querySelectorAll("[data-ohw-href-key]").forEach((el) => {
|
|
6072
6838
|
const key = el.getAttribute("data-ohw-href-key") ?? "";
|
|
6073
6839
|
if (!key) return;
|
|
6074
|
-
nodes.push({ key, type: "link", text:
|
|
6840
|
+
nodes.push({ key, type: "link", text: getLinkHref2(el) });
|
|
6075
6841
|
});
|
|
6076
6842
|
document.querySelectorAll('[data-ohw-editable="video"]').forEach((el) => {
|
|
6077
6843
|
const key = el.dataset.ohwKey ?? "";
|
|
@@ -6163,7 +6929,7 @@ function applyLinkByKey(key, val) {
|
|
|
6163
6929
|
}
|
|
6164
6930
|
function isInsideLinkEditor(target) {
|
|
6165
6931
|
return Boolean(
|
|
6166
|
-
target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
|
|
6932
|
+
target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest("[data-ohw-section-picker]") || target.closest("[data-ohw-navbar-container-chrome]") || target.closest("[data-ohw-navbar-add-button]") || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
|
|
6167
6933
|
);
|
|
6168
6934
|
}
|
|
6169
6935
|
function getHrefKeyFromElement(el) {
|
|
@@ -6174,7 +6940,7 @@ function getHrefKeyFromElement(el) {
|
|
|
6174
6940
|
if (!key) return null;
|
|
6175
6941
|
return { anchor, key };
|
|
6176
6942
|
}
|
|
6177
|
-
function
|
|
6943
|
+
function isNavbarButton2(el) {
|
|
6178
6944
|
return Boolean(el.closest('[data-ohw-role="navbar-button"]'));
|
|
6179
6945
|
}
|
|
6180
6946
|
function getNavigationItemAnchor(el) {
|
|
@@ -6186,19 +6952,8 @@ function getNavigationItemAnchor(el) {
|
|
|
6186
6952
|
function isNavigationItem(el) {
|
|
6187
6953
|
return getNavigationItemAnchor(el) !== null;
|
|
6188
6954
|
}
|
|
6189
|
-
function getNavigationItemAddHintTarget(anchor) {
|
|
6190
|
-
const items = listNavigationItems();
|
|
6191
|
-
const idx = items.indexOf(anchor);
|
|
6192
|
-
if (idx >= 0 && idx < items.length - 1) return items[idx + 1];
|
|
6193
|
-
return anchor;
|
|
6194
|
-
}
|
|
6195
|
-
function listNavigationItems() {
|
|
6196
|
-
return Array.from(
|
|
6197
|
-
document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
|
|
6198
|
-
).filter((el) => isNavigationItem(el));
|
|
6199
|
-
}
|
|
6200
6955
|
function getNavigationItemReorderState(anchor) {
|
|
6201
|
-
if (
|
|
6956
|
+
if (isNavbarButton2(anchor)) return { key: null, disabled: false };
|
|
6202
6957
|
return getReorderHandleStateFromAnchor(anchor);
|
|
6203
6958
|
}
|
|
6204
6959
|
function getReorderHandleState(el) {
|
|
@@ -6220,6 +6975,120 @@ function clearHrefKeyHover(anchor) {
|
|
|
6220
6975
|
function isInsideNavigationItem(el) {
|
|
6221
6976
|
return getNavigationItemAnchor(el) !== null;
|
|
6222
6977
|
}
|
|
6978
|
+
function getNavigationRoot(el) {
|
|
6979
|
+
const explicit = el.closest("[data-ohw-nav-root]");
|
|
6980
|
+
if (explicit) return explicit;
|
|
6981
|
+
return el.closest("nav, footer, aside");
|
|
6982
|
+
}
|
|
6983
|
+
function findFooterItemGroup(item) {
|
|
6984
|
+
const footer = item.closest("footer");
|
|
6985
|
+
if (!footer) return null;
|
|
6986
|
+
let node = item.parentElement;
|
|
6987
|
+
while (node && node !== footer) {
|
|
6988
|
+
const hasDirectNavItems = Array.from(
|
|
6989
|
+
node.querySelectorAll(":scope > [data-ohw-href-key]")
|
|
6990
|
+
).some(isNavigationItem);
|
|
6991
|
+
if (hasDirectNavItems) return node;
|
|
6992
|
+
node = node.parentElement;
|
|
6993
|
+
}
|
|
6994
|
+
return null;
|
|
6995
|
+
}
|
|
6996
|
+
function isNavigationRoot(el) {
|
|
6997
|
+
return el.hasAttribute("data-ohw-nav-root") || el.matches("nav, footer, aside");
|
|
6998
|
+
}
|
|
6999
|
+
function isInferredFooterGroup(el) {
|
|
7000
|
+
const footer = el.closest("footer");
|
|
7001
|
+
if (!footer || el === footer) return false;
|
|
7002
|
+
return Array.from(el.querySelectorAll(":scope > [data-ohw-href-key]")).some(isNavigationItem);
|
|
7003
|
+
}
|
|
7004
|
+
function isNavigationContainer(el) {
|
|
7005
|
+
return el.hasAttribute("data-ohw-nav-container") || isNavigationRoot(el) || isInferredFooterGroup(el);
|
|
7006
|
+
}
|
|
7007
|
+
function isPointOverNavigation(x, y) {
|
|
7008
|
+
const navRoot = document.querySelector("[data-ohw-nav-root]") ?? document.querySelector("nav");
|
|
7009
|
+
if (!navRoot) return false;
|
|
7010
|
+
const r2 = navRoot.getBoundingClientRect();
|
|
7011
|
+
return x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom;
|
|
7012
|
+
}
|
|
7013
|
+
function isPointOverNavItem(container, x, y) {
|
|
7014
|
+
return Array.from(container.querySelectorAll("[data-ohw-href-key]")).some((el) => {
|
|
7015
|
+
if (!isNavigationItem(el) || isNavbarButton2(el)) return false;
|
|
7016
|
+
const itemRect = el.getBoundingClientRect();
|
|
7017
|
+
return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
|
|
7018
|
+
});
|
|
7019
|
+
}
|
|
7020
|
+
function resolveNavContainerSelectionTarget(target, clientX, clientY) {
|
|
7021
|
+
if (getNavigationItemAnchor(target)) return null;
|
|
7022
|
+
if (target.closest('[data-ohw-role="navbar-button"]')) return null;
|
|
7023
|
+
const plainLink = target.closest("a");
|
|
7024
|
+
if (plainLink && !plainLink.hasAttribute("data-ohw-href-key") && !plainLink.closest("[data-ohw-nav-container]")) {
|
|
7025
|
+
return null;
|
|
7026
|
+
}
|
|
7027
|
+
const fromClosest = target.closest("[data-ohw-nav-container]");
|
|
7028
|
+
if (fromClosest && !isPointOverNavItem(fromClosest, clientX, clientY)) {
|
|
7029
|
+
return fromClosest;
|
|
7030
|
+
}
|
|
7031
|
+
const navRoot = target.closest("[data-ohw-nav-root]");
|
|
7032
|
+
if (!navRoot) return null;
|
|
7033
|
+
const container = navRoot.querySelector("[data-ohw-nav-container]");
|
|
7034
|
+
if (!container || isPointOverNavItem(container, clientX, clientY)) return null;
|
|
7035
|
+
if (target === navRoot || target.hasAttribute("data-ohw-nav-root")) {
|
|
7036
|
+
return container;
|
|
7037
|
+
}
|
|
7038
|
+
return null;
|
|
7039
|
+
}
|
|
7040
|
+
function getNavigationSelectionParent(el) {
|
|
7041
|
+
if (isNavigationItem(el)) {
|
|
7042
|
+
const explicit = el.closest("[data-ohw-nav-container]");
|
|
7043
|
+
if (explicit) return explicit;
|
|
7044
|
+
const footerGroup = findFooterItemGroup(el);
|
|
7045
|
+
if (footerGroup) return footerGroup;
|
|
7046
|
+
return getNavigationRoot(el);
|
|
7047
|
+
}
|
|
7048
|
+
if (el.hasAttribute("data-ohw-nav-container") || isInferredFooterGroup(el)) {
|
|
7049
|
+
return getNavigationRoot(el);
|
|
7050
|
+
}
|
|
7051
|
+
return null;
|
|
7052
|
+
}
|
|
7053
|
+
function placeCaretAtPoint(el, x, y) {
|
|
7054
|
+
const selection = window.getSelection();
|
|
7055
|
+
if (!selection) return;
|
|
7056
|
+
if (typeof document.caretRangeFromPoint === "function") {
|
|
7057
|
+
const range = document.caretRangeFromPoint(x, y);
|
|
7058
|
+
if (range && el.contains(range.startContainer)) {
|
|
7059
|
+
selection.removeAllRanges();
|
|
7060
|
+
selection.addRange(range);
|
|
7061
|
+
return;
|
|
7062
|
+
}
|
|
7063
|
+
}
|
|
7064
|
+
const caretPositionFromPoint = document.caretPositionFromPoint;
|
|
7065
|
+
if (typeof caretPositionFromPoint === "function") {
|
|
7066
|
+
const position = caretPositionFromPoint(x, y);
|
|
7067
|
+
if (position && el.contains(position.offsetNode)) {
|
|
7068
|
+
const range = document.createRange();
|
|
7069
|
+
range.setStart(position.offsetNode, position.offset);
|
|
7070
|
+
range.collapse(true);
|
|
7071
|
+
selection.removeAllRanges();
|
|
7072
|
+
selection.addRange(range);
|
|
7073
|
+
}
|
|
7074
|
+
}
|
|
7075
|
+
}
|
|
7076
|
+
function selectAllTextInEditable(el) {
|
|
7077
|
+
const selection = window.getSelection();
|
|
7078
|
+
if (!selection) return;
|
|
7079
|
+
const range = document.createRange();
|
|
7080
|
+
range.selectNodeContents(el);
|
|
7081
|
+
selection.removeAllRanges();
|
|
7082
|
+
selection.addRange(range);
|
|
7083
|
+
}
|
|
7084
|
+
function getNavigationLabelEditable(target) {
|
|
7085
|
+
const editable = target.closest('[data-ohw-editable="text"]');
|
|
7086
|
+
if (!editable) return null;
|
|
7087
|
+
const hrefCtx = getHrefKeyFromElement(editable);
|
|
7088
|
+
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
7089
|
+
if (!navAnchor) return null;
|
|
7090
|
+
return { editable, navAnchor };
|
|
7091
|
+
}
|
|
6223
7092
|
function collectSections() {
|
|
6224
7093
|
return collectSectionsFromDom();
|
|
6225
7094
|
}
|
|
@@ -6367,7 +7236,7 @@ function EditGlowChrome({
|
|
|
6367
7236
|
dragDisabled = false
|
|
6368
7237
|
}) {
|
|
6369
7238
|
const GAP = 6;
|
|
6370
|
-
return /* @__PURE__ */ (0,
|
|
7239
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
6371
7240
|
"div",
|
|
6372
7241
|
{
|
|
6373
7242
|
ref: elRef,
|
|
@@ -6382,7 +7251,7 @@ function EditGlowChrome({
|
|
|
6382
7251
|
zIndex: 2147483646
|
|
6383
7252
|
},
|
|
6384
7253
|
children: [
|
|
6385
|
-
/* @__PURE__ */ (0,
|
|
7254
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
6386
7255
|
"div",
|
|
6387
7256
|
{
|
|
6388
7257
|
style: {
|
|
@@ -6395,7 +7264,7 @@ function EditGlowChrome({
|
|
|
6395
7264
|
}
|
|
6396
7265
|
}
|
|
6397
7266
|
),
|
|
6398
|
-
reorderHrefKey && /* @__PURE__ */ (0,
|
|
7267
|
+
reorderHrefKey && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
6399
7268
|
"div",
|
|
6400
7269
|
{
|
|
6401
7270
|
"data-ohw-drag-handle-container": "",
|
|
@@ -6407,7 +7276,7 @@ function EditGlowChrome({
|
|
|
6407
7276
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
6408
7277
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
6409
7278
|
},
|
|
6410
|
-
children: /* @__PURE__ */ (0,
|
|
7279
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
6411
7280
|
DragHandle,
|
|
6412
7281
|
{
|
|
6413
7282
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -6511,7 +7380,7 @@ function FloatingToolbar({
|
|
|
6511
7380
|
onEditLink
|
|
6512
7381
|
}) {
|
|
6513
7382
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll, 330);
|
|
6514
|
-
return /* @__PURE__ */ (0,
|
|
7383
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
6515
7384
|
"div",
|
|
6516
7385
|
{
|
|
6517
7386
|
ref: elRef,
|
|
@@ -6523,12 +7392,12 @@ function FloatingToolbar({
|
|
|
6523
7392
|
zIndex: 2147483647,
|
|
6524
7393
|
pointerEvents: "auto"
|
|
6525
7394
|
},
|
|
6526
|
-
children: /* @__PURE__ */ (0,
|
|
6527
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0,
|
|
6528
|
-
gi > 0 && /* @__PURE__ */ (0,
|
|
7395
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(CustomToolbar, { children: [
|
|
7396
|
+
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_react8.default.Fragment, { children: [
|
|
7397
|
+
gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CustomToolbarDivider, {}),
|
|
6529
7398
|
btns.map((btn) => {
|
|
6530
7399
|
const isActive = activeCommands.has(btn.cmd);
|
|
6531
|
-
return /* @__PURE__ */ (0,
|
|
7400
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
6532
7401
|
CustomToolbarButton,
|
|
6533
7402
|
{
|
|
6534
7403
|
title: btn.title,
|
|
@@ -6537,7 +7406,7 @@ function FloatingToolbar({
|
|
|
6537
7406
|
e.preventDefault();
|
|
6538
7407
|
onCommand(btn.cmd);
|
|
6539
7408
|
},
|
|
6540
|
-
children: /* @__PURE__ */ (0,
|
|
7409
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
6541
7410
|
"svg",
|
|
6542
7411
|
{
|
|
6543
7412
|
width: "16",
|
|
@@ -6558,7 +7427,7 @@ function FloatingToolbar({
|
|
|
6558
7427
|
);
|
|
6559
7428
|
})
|
|
6560
7429
|
] }, gi)),
|
|
6561
|
-
showEditLink ? /* @__PURE__ */ (0,
|
|
7430
|
+
showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
6562
7431
|
CustomToolbarButton,
|
|
6563
7432
|
{
|
|
6564
7433
|
type: "button",
|
|
@@ -6572,7 +7441,7 @@ function FloatingToolbar({
|
|
|
6572
7441
|
e.preventDefault();
|
|
6573
7442
|
e.stopPropagation();
|
|
6574
7443
|
},
|
|
6575
|
-
children: /* @__PURE__ */ (0,
|
|
7444
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Link, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
6576
7445
|
}
|
|
6577
7446
|
) : null
|
|
6578
7447
|
] })
|
|
@@ -6589,7 +7458,7 @@ function StateToggle({
|
|
|
6589
7458
|
states,
|
|
6590
7459
|
onStateChange
|
|
6591
7460
|
}) {
|
|
6592
|
-
return /* @__PURE__ */ (0,
|
|
7461
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
6593
7462
|
ToggleGroup,
|
|
6594
7463
|
{
|
|
6595
7464
|
"data-ohw-state-toggle": "",
|
|
@@ -6603,7 +7472,7 @@ function StateToggle({
|
|
|
6603
7472
|
left: rect.right - 8,
|
|
6604
7473
|
transform: "translateX(-100%)"
|
|
6605
7474
|
},
|
|
6606
|
-
children: states.map((state) => /* @__PURE__ */ (0,
|
|
7475
|
+
children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
6607
7476
|
}
|
|
6608
7477
|
);
|
|
6609
7478
|
}
|
|
@@ -6626,12 +7495,12 @@ function resolveSubdomain(subdomainFromQuery) {
|
|
|
6626
7495
|
return "";
|
|
6627
7496
|
}
|
|
6628
7497
|
function OhhwellsBridge() {
|
|
6629
|
-
const pathname = (0,
|
|
6630
|
-
const router = (0,
|
|
6631
|
-
const searchParams = (0,
|
|
7498
|
+
const pathname = (0, import_navigation2.usePathname)();
|
|
7499
|
+
const router = (0, import_navigation2.useRouter)();
|
|
7500
|
+
const searchParams = (0, import_navigation2.useSearchParams)();
|
|
6632
7501
|
const isEditMode = isEditSessionActive();
|
|
6633
|
-
const [bridgeRoot, setBridgeRoot] = (0,
|
|
6634
|
-
(0,
|
|
7502
|
+
const [bridgeRoot, setBridgeRoot] = (0, import_react8.useState)(null);
|
|
7503
|
+
(0, import_react8.useEffect)(() => {
|
|
6635
7504
|
const figtreeFontId = "ohw-figtree-font";
|
|
6636
7505
|
if (!document.getElementById(figtreeFontId)) {
|
|
6637
7506
|
const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
|
|
@@ -6659,83 +7528,91 @@ function OhhwellsBridge() {
|
|
|
6659
7528
|
const subdomainFromQuery = searchParams.get("subdomain");
|
|
6660
7529
|
const subdomain = resolveSubdomain(subdomainFromQuery);
|
|
6661
7530
|
useLinkHrefGuardian(pathname, subdomain, isEditMode);
|
|
6662
|
-
const
|
|
7531
|
+
const postToParent2 = (0, import_react8.useCallback)((data) => {
|
|
6663
7532
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
6664
7533
|
window.parent.postMessage(data, "*");
|
|
6665
7534
|
}
|
|
6666
7535
|
}, []);
|
|
6667
|
-
const [fetchState, setFetchState] = (0,
|
|
6668
|
-
const autoSaveTimers = (0,
|
|
6669
|
-
const activeElRef = (0,
|
|
6670
|
-
const selectedElRef = (0,
|
|
6671
|
-
const originalContentRef = (0,
|
|
6672
|
-
const activeStateElRef = (0,
|
|
6673
|
-
const parentScrollRef = (0,
|
|
6674
|
-
const visibleViewportRef = (0,
|
|
6675
|
-
const [dialogPortalContainer, setDialogPortalContainer] = (0,
|
|
6676
|
-
const attachVisibleViewport = (0,
|
|
7536
|
+
const [fetchState, setFetchState] = (0, import_react8.useState)("idle");
|
|
7537
|
+
const autoSaveTimers = (0, import_react8.useRef)(/* @__PURE__ */ new Map());
|
|
7538
|
+
const activeElRef = (0, import_react8.useRef)(null);
|
|
7539
|
+
const selectedElRef = (0, import_react8.useRef)(null);
|
|
7540
|
+
const originalContentRef = (0, import_react8.useRef)(null);
|
|
7541
|
+
const activeStateElRef = (0, import_react8.useRef)(null);
|
|
7542
|
+
const parentScrollRef = (0, import_react8.useRef)(null);
|
|
7543
|
+
const visibleViewportRef = (0, import_react8.useRef)(null);
|
|
7544
|
+
const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react8.useState)(null);
|
|
7545
|
+
const attachVisibleViewport = (0, import_react8.useCallback)((node) => {
|
|
6677
7546
|
visibleViewportRef.current = node;
|
|
6678
7547
|
setDialogPortalContainer(node);
|
|
6679
7548
|
if (node) applyVisibleViewport(node, parentScrollRef.current);
|
|
6680
7549
|
}, []);
|
|
6681
|
-
const toolbarElRef = (0,
|
|
6682
|
-
const glowElRef = (0,
|
|
6683
|
-
const hoveredImageRef = (0,
|
|
6684
|
-
const hoveredImageHasTextOverlapRef = (0,
|
|
6685
|
-
const dragOverElRef = (0,
|
|
6686
|
-
const [mediaHover, setMediaHover] = (0,
|
|
6687
|
-
const [uploadingRects, setUploadingRects] = (0,
|
|
6688
|
-
const hoveredGapRef = (0,
|
|
6689
|
-
const imageUnhoverTimerRef = (0,
|
|
6690
|
-
const imageShowTimerRef = (0,
|
|
6691
|
-
const editStylesRef = (0,
|
|
6692
|
-
const activateRef = (0,
|
|
7550
|
+
const toolbarElRef = (0, import_react8.useRef)(null);
|
|
7551
|
+
const glowElRef = (0, import_react8.useRef)(null);
|
|
7552
|
+
const hoveredImageRef = (0, import_react8.useRef)(null);
|
|
7553
|
+
const hoveredImageHasTextOverlapRef = (0, import_react8.useRef)(false);
|
|
7554
|
+
const dragOverElRef = (0, import_react8.useRef)(null);
|
|
7555
|
+
const [mediaHover, setMediaHover] = (0, import_react8.useState)(null);
|
|
7556
|
+
const [uploadingRects, setUploadingRects] = (0, import_react8.useState)({});
|
|
7557
|
+
const hoveredGapRef = (0, import_react8.useRef)(null);
|
|
7558
|
+
const imageUnhoverTimerRef = (0, import_react8.useRef)(null);
|
|
7559
|
+
const imageShowTimerRef = (0, import_react8.useRef)(null);
|
|
7560
|
+
const editStylesRef = (0, import_react8.useRef)(null);
|
|
7561
|
+
const activateRef = (0, import_react8.useRef)(() => {
|
|
7562
|
+
});
|
|
7563
|
+
const deactivateRef = (0, import_react8.useRef)(() => {
|
|
6693
7564
|
});
|
|
6694
|
-
const
|
|
7565
|
+
const selectRef = (0, import_react8.useRef)(() => {
|
|
6695
7566
|
});
|
|
6696
|
-
const
|
|
7567
|
+
const selectFrameRef = (0, import_react8.useRef)(() => {
|
|
6697
7568
|
});
|
|
6698
|
-
const deselectRef = (0,
|
|
7569
|
+
const deselectRef = (0, import_react8.useRef)(() => {
|
|
6699
7570
|
});
|
|
6700
|
-
const reselectNavigationItemRef = (0,
|
|
7571
|
+
const reselectNavigationItemRef = (0, import_react8.useRef)(() => {
|
|
6701
7572
|
});
|
|
6702
|
-
const commitNavigationTextEditRef = (0,
|
|
7573
|
+
const commitNavigationTextEditRef = (0, import_react8.useRef)(() => {
|
|
6703
7574
|
});
|
|
6704
|
-
const refreshActiveCommandsRef = (0,
|
|
7575
|
+
const refreshActiveCommandsRef = (0, import_react8.useRef)(() => {
|
|
6705
7576
|
});
|
|
6706
|
-
const postToParentRef = (0,
|
|
6707
|
-
postToParentRef.current =
|
|
6708
|
-
const sectionsLoadedRef = (0,
|
|
6709
|
-
const pendingScheduleConfigRequests = (0,
|
|
6710
|
-
const [toolbarRect, setToolbarRect] = (0,
|
|
6711
|
-
const [toolbarVariant, setToolbarVariant] = (0,
|
|
6712
|
-
const toolbarVariantRef = (0,
|
|
7577
|
+
const postToParentRef = (0, import_react8.useRef)(postToParent2);
|
|
7578
|
+
postToParentRef.current = postToParent2;
|
|
7579
|
+
const sectionsLoadedRef = (0, import_react8.useRef)(false);
|
|
7580
|
+
const pendingScheduleConfigRequests = (0, import_react8.useRef)([]);
|
|
7581
|
+
const [toolbarRect, setToolbarRect] = (0, import_react8.useState)(null);
|
|
7582
|
+
const [toolbarVariant, setToolbarVariant] = (0, import_react8.useState)("none");
|
|
7583
|
+
const toolbarVariantRef = (0, import_react8.useRef)("none");
|
|
6713
7584
|
toolbarVariantRef.current = toolbarVariant;
|
|
6714
|
-
const [reorderHrefKey, setReorderHrefKey] = (0,
|
|
6715
|
-
const [reorderDragDisabled, setReorderDragDisabled] = (0,
|
|
6716
|
-
const [toggleState, setToggleState] = (0,
|
|
6717
|
-
const [maxBadge, setMaxBadge] = (0,
|
|
6718
|
-
const [activeCommands, setActiveCommands] = (0,
|
|
6719
|
-
const [sectionGap, setSectionGap] = (0,
|
|
6720
|
-
const [toolbarShowEditLink, setToolbarShowEditLink] = (0,
|
|
6721
|
-
const
|
|
6722
|
-
const [
|
|
6723
|
-
const
|
|
6724
|
-
const [
|
|
6725
|
-
const
|
|
6726
|
-
const [
|
|
6727
|
-
const [
|
|
6728
|
-
const [
|
|
6729
|
-
const
|
|
6730
|
-
const
|
|
6731
|
-
const
|
|
6732
|
-
const
|
|
6733
|
-
const
|
|
7585
|
+
const [reorderHrefKey, setReorderHrefKey] = (0, import_react8.useState)(null);
|
|
7586
|
+
const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react8.useState)(false);
|
|
7587
|
+
const [toggleState, setToggleState] = (0, import_react8.useState)(null);
|
|
7588
|
+
const [maxBadge, setMaxBadge] = (0, import_react8.useState)(null);
|
|
7589
|
+
const [activeCommands, setActiveCommands] = (0, import_react8.useState)(/* @__PURE__ */ new Set());
|
|
7590
|
+
const [sectionGap, setSectionGap] = (0, import_react8.useState)(null);
|
|
7591
|
+
const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react8.useState)(false);
|
|
7592
|
+
const hoveredNavContainerRef = (0, import_react8.useRef)(null);
|
|
7593
|
+
const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react8.useState)(null);
|
|
7594
|
+
const hoveredItemElRef = (0, import_react8.useRef)(null);
|
|
7595
|
+
const [hoveredItemRect, setHoveredItemRect] = (0, import_react8.useState)(null);
|
|
7596
|
+
const siblingHintElRef = (0, import_react8.useRef)(null);
|
|
7597
|
+
const [siblingHintRect, setSiblingHintRect] = (0, import_react8.useState)(null);
|
|
7598
|
+
const [isItemDragging, setIsItemDragging] = (0, import_react8.useState)(false);
|
|
7599
|
+
const [linkPopover, setLinkPopover] = (0, import_react8.useState)(null);
|
|
7600
|
+
const linkPopoverSessionRef = (0, import_react8.useRef)(null);
|
|
7601
|
+
const addNavAfterAnchorRef = (0, import_react8.useRef)(null);
|
|
7602
|
+
const editContentRef = (0, import_react8.useRef)({});
|
|
7603
|
+
const [sitePages, setSitePages] = (0, import_react8.useState)([]);
|
|
7604
|
+
const [sectionsByPath, setSectionsByPath] = (0, import_react8.useState)({});
|
|
7605
|
+
const sectionsPrefetchGenRef = (0, import_react8.useRef)(0);
|
|
7606
|
+
const setLinkPopoverRef = (0, import_react8.useRef)(setLinkPopover);
|
|
7607
|
+
const linkPopoverPanelRef = (0, import_react8.useRef)(null);
|
|
7608
|
+
const linkPopoverOpenRef = (0, import_react8.useRef)(false);
|
|
7609
|
+
const linkPopoverGraceUntilRef = (0, import_react8.useRef)(0);
|
|
6734
7610
|
setLinkPopoverRef.current = setLinkPopover;
|
|
7611
|
+
linkPopoverSessionRef.current = linkPopover;
|
|
6735
7612
|
const bumpLinkPopoverGrace = () => {
|
|
6736
7613
|
linkPopoverGraceUntilRef.current = Date.now() + 350;
|
|
6737
7614
|
};
|
|
6738
|
-
const runSectionsPrefetch = (0,
|
|
7615
|
+
const runSectionsPrefetch = (0, import_react8.useCallback)((pages) => {
|
|
6739
7616
|
if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
|
|
6740
7617
|
const gen = ++sectionsPrefetchGenRef.current;
|
|
6741
7618
|
const paths = pages.map((p) => p.path);
|
|
@@ -6754,9 +7631,9 @@ function OhhwellsBridge() {
|
|
|
6754
7631
|
);
|
|
6755
7632
|
});
|
|
6756
7633
|
}, [isEditMode, pathname]);
|
|
6757
|
-
const runSectionsPrefetchRef = (0,
|
|
7634
|
+
const runSectionsPrefetchRef = (0, import_react8.useRef)(runSectionsPrefetch);
|
|
6758
7635
|
runSectionsPrefetchRef.current = runSectionsPrefetch;
|
|
6759
|
-
(0,
|
|
7636
|
+
(0, import_react8.useEffect)(() => {
|
|
6760
7637
|
if (!linkPopover) return;
|
|
6761
7638
|
if (hoveredImageRef.current) {
|
|
6762
7639
|
hoveredImageRef.current = null;
|
|
@@ -6765,7 +7642,7 @@ function OhhwellsBridge() {
|
|
|
6765
7642
|
hoveredGapRef.current = null;
|
|
6766
7643
|
setSectionGap(null);
|
|
6767
7644
|
setMediaHover(null);
|
|
6768
|
-
|
|
7645
|
+
postToParent2({ type: "ow:link-modal-lock", locked: true });
|
|
6769
7646
|
const html = document.documentElement;
|
|
6770
7647
|
const body = document.body;
|
|
6771
7648
|
const prevHtmlOverflow = html.style.overflow;
|
|
@@ -6782,15 +7659,16 @@ function OhhwellsBridge() {
|
|
|
6782
7659
|
const scrollOpts = { passive: false, capture: true };
|
|
6783
7660
|
document.addEventListener("wheel", preventBackgroundScroll, scrollOpts);
|
|
6784
7661
|
document.addEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
7662
|
+
postToParent2({ type: "ow:image-unhover" });
|
|
6785
7663
|
return () => {
|
|
6786
|
-
|
|
7664
|
+
postToParent2({ type: "ow:link-modal-lock", locked: false });
|
|
6787
7665
|
html.style.overflow = prevHtmlOverflow;
|
|
6788
7666
|
body.style.overflow = prevBodyOverflow;
|
|
6789
7667
|
document.removeEventListener("wheel", preventBackgroundScroll, scrollOpts);
|
|
6790
7668
|
document.removeEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
6791
7669
|
};
|
|
6792
|
-
}, [linkPopover,
|
|
6793
|
-
(0,
|
|
7670
|
+
}, [linkPopover, postToParent2]);
|
|
7671
|
+
(0, import_react8.useEffect)(() => {
|
|
6794
7672
|
if (!isEditMode) return;
|
|
6795
7673
|
const useFixtures = shouldUseDevFixtures();
|
|
6796
7674
|
if (useFixtures) {
|
|
@@ -6811,17 +7689,17 @@ function OhhwellsBridge() {
|
|
|
6811
7689
|
runSectionsPrefetchRef.current(mapped);
|
|
6812
7690
|
};
|
|
6813
7691
|
window.addEventListener("message", onSitePages);
|
|
6814
|
-
if (!useFixtures)
|
|
7692
|
+
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
6815
7693
|
return () => window.removeEventListener("message", onSitePages);
|
|
6816
|
-
}, [isEditMode,
|
|
6817
|
-
(0,
|
|
7694
|
+
}, [isEditMode, postToParent2]);
|
|
7695
|
+
(0, import_react8.useEffect)(() => {
|
|
6818
7696
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
6819
7697
|
void loadAllSectionsManifest().then((manifest) => {
|
|
6820
7698
|
if (Object.keys(manifest).length === 0) return;
|
|
6821
7699
|
setSectionsByPath((prev) => ({ ...manifest, ...prev }));
|
|
6822
7700
|
});
|
|
6823
7701
|
}, [isEditMode]);
|
|
6824
|
-
(0,
|
|
7702
|
+
(0, import_react8.useEffect)(() => {
|
|
6825
7703
|
const update = () => {
|
|
6826
7704
|
const el = activeElRef.current ?? selectedElRef.current;
|
|
6827
7705
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
@@ -6845,10 +7723,10 @@ function OhhwellsBridge() {
|
|
|
6845
7723
|
vvp.removeEventListener("resize", update);
|
|
6846
7724
|
};
|
|
6847
7725
|
}, []);
|
|
6848
|
-
const refreshStateRules = (0,
|
|
7726
|
+
const refreshStateRules = (0, import_react8.useCallback)(() => {
|
|
6849
7727
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
6850
7728
|
}, []);
|
|
6851
|
-
const processConfigRequest = (0,
|
|
7729
|
+
const processConfigRequest = (0, import_react8.useCallback)((insertAfterVal) => {
|
|
6852
7730
|
const tracker = getSectionsTracker();
|
|
6853
7731
|
let entries = [];
|
|
6854
7732
|
try {
|
|
@@ -6871,7 +7749,7 @@ function OhhwellsBridge() {
|
|
|
6871
7749
|
}
|
|
6872
7750
|
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
|
|
6873
7751
|
}, [isEditMode]);
|
|
6874
|
-
const deactivate = (0,
|
|
7752
|
+
const deactivate = (0, import_react8.useCallback)(() => {
|
|
6875
7753
|
const el = activeElRef.current;
|
|
6876
7754
|
if (!el) return;
|
|
6877
7755
|
const key = el.dataset.ohwKey;
|
|
@@ -6900,21 +7778,23 @@ function OhhwellsBridge() {
|
|
|
6900
7778
|
setMaxBadge(null);
|
|
6901
7779
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6902
7780
|
setToolbarShowEditLink(false);
|
|
6903
|
-
|
|
6904
|
-
}, [
|
|
6905
|
-
const deselect = (0,
|
|
7781
|
+
postToParent2({ type: "ow:exit-edit" });
|
|
7782
|
+
}, [postToParent2]);
|
|
7783
|
+
const deselect = (0, import_react8.useCallback)(() => {
|
|
6906
7784
|
selectedElRef.current = null;
|
|
6907
7785
|
setReorderHrefKey(null);
|
|
6908
7786
|
setReorderDragDisabled(false);
|
|
6909
7787
|
siblingHintElRef.current = null;
|
|
6910
7788
|
setSiblingHintRect(null);
|
|
6911
7789
|
setIsItemDragging(false);
|
|
7790
|
+
hoveredNavContainerRef.current = null;
|
|
7791
|
+
setHoveredNavContainerRect(null);
|
|
6912
7792
|
if (!activeElRef.current) {
|
|
6913
7793
|
setToolbarRect(null);
|
|
6914
7794
|
setToolbarVariant("none");
|
|
6915
7795
|
}
|
|
6916
7796
|
}, []);
|
|
6917
|
-
const reselectNavigationItem = (0,
|
|
7797
|
+
const reselectNavigationItem = (0, import_react8.useCallback)((navAnchor) => {
|
|
6918
7798
|
selectedElRef.current = navAnchor;
|
|
6919
7799
|
const { key, disabled } = getNavigationItemReorderState(navAnchor);
|
|
6920
7800
|
setReorderHrefKey(key);
|
|
@@ -6924,7 +7804,7 @@ function OhhwellsBridge() {
|
|
|
6924
7804
|
setToolbarShowEditLink(false);
|
|
6925
7805
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6926
7806
|
}, []);
|
|
6927
|
-
const commitNavigationTextEdit = (0,
|
|
7807
|
+
const commitNavigationTextEdit = (0, import_react8.useCallback)((navAnchor) => {
|
|
6928
7808
|
const el = activeElRef.current;
|
|
6929
7809
|
if (!el) return;
|
|
6930
7810
|
const key = el.dataset.ohwKey;
|
|
@@ -6937,9 +7817,9 @@ function OhhwellsBridge() {
|
|
|
6937
7817
|
const html = sanitizeHtml(el.innerHTML);
|
|
6938
7818
|
const original = originalContentRef.current ?? "";
|
|
6939
7819
|
if (html !== sanitizeHtml(original)) {
|
|
6940
|
-
|
|
7820
|
+
postToParent2({ type: "ow:change", nodes: [{ key, text: html }] });
|
|
6941
7821
|
const h = document.documentElement.scrollHeight;
|
|
6942
|
-
if (h > 50)
|
|
7822
|
+
if (h > 50) postToParent2({ type: "ow:height", height: h });
|
|
6943
7823
|
}
|
|
6944
7824
|
}
|
|
6945
7825
|
el.removeAttribute("contenteditable");
|
|
@@ -6947,31 +7827,38 @@ function OhhwellsBridge() {
|
|
|
6947
7827
|
setMaxBadge(null);
|
|
6948
7828
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6949
7829
|
setToolbarShowEditLink(false);
|
|
6950
|
-
|
|
7830
|
+
postToParent2({ type: "ow:exit-edit" });
|
|
6951
7831
|
reselectNavigationItem(navAnchor);
|
|
6952
|
-
}, [
|
|
6953
|
-
const
|
|
6954
|
-
const
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
7832
|
+
}, [postToParent2, reselectNavigationItem]);
|
|
7833
|
+
const handleAddTopLevelNavItem = (0, import_react8.useCallback)(() => {
|
|
7834
|
+
const items = listNavbarItems();
|
|
7835
|
+
addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
|
|
7836
|
+
deselectRef.current();
|
|
7837
|
+
deactivateRef.current();
|
|
7838
|
+
bumpLinkPopoverGrace();
|
|
7839
|
+
setLinkPopover({
|
|
7840
|
+
key: "__add-nav__",
|
|
7841
|
+
mode: "create",
|
|
7842
|
+
intent: "add-nav"
|
|
7843
|
+
});
|
|
6959
7844
|
}, []);
|
|
6960
|
-
const handleItemDragStart = (0,
|
|
7845
|
+
const handleItemDragStart = (0, import_react8.useCallback)(() => {
|
|
6961
7846
|
siblingHintElRef.current = null;
|
|
6962
7847
|
setSiblingHintRect(null);
|
|
6963
7848
|
setIsItemDragging(true);
|
|
6964
7849
|
}, []);
|
|
6965
|
-
const handleItemDragEnd = (0,
|
|
7850
|
+
const handleItemDragEnd = (0, import_react8.useCallback)(() => {
|
|
6966
7851
|
setIsItemDragging(false);
|
|
6967
7852
|
}, []);
|
|
6968
7853
|
reselectNavigationItemRef.current = reselectNavigationItem;
|
|
6969
7854
|
commitNavigationTextEditRef.current = commitNavigationTextEdit;
|
|
6970
|
-
const select = (0,
|
|
7855
|
+
const select = (0, import_react8.useCallback)((anchor) => {
|
|
6971
7856
|
if (!isNavigationItem(anchor)) return;
|
|
6972
7857
|
if (activeElRef.current) deactivate();
|
|
6973
7858
|
selectedElRef.current = anchor;
|
|
6974
7859
|
clearHrefKeyHover(anchor);
|
|
7860
|
+
hoveredNavContainerRef.current = null;
|
|
7861
|
+
setHoveredNavContainerRect(null);
|
|
6975
7862
|
setHoveredItemRect(null);
|
|
6976
7863
|
hoveredItemElRef.current = null;
|
|
6977
7864
|
siblingHintElRef.current = null;
|
|
@@ -6985,7 +7872,26 @@ function OhhwellsBridge() {
|
|
|
6985
7872
|
setToolbarShowEditLink(false);
|
|
6986
7873
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6987
7874
|
}, [deactivate]);
|
|
6988
|
-
const
|
|
7875
|
+
const selectFrame = (0, import_react8.useCallback)((el) => {
|
|
7876
|
+
if (!isNavigationContainer(el)) return;
|
|
7877
|
+
if (activeElRef.current) deactivate();
|
|
7878
|
+
selectedElRef.current = el;
|
|
7879
|
+
clearHrefKeyHover(el);
|
|
7880
|
+
hoveredNavContainerRef.current = null;
|
|
7881
|
+
setHoveredNavContainerRect(null);
|
|
7882
|
+
setHoveredItemRect(null);
|
|
7883
|
+
hoveredItemElRef.current = null;
|
|
7884
|
+
siblingHintElRef.current = null;
|
|
7885
|
+
setSiblingHintRect(null);
|
|
7886
|
+
setIsItemDragging(false);
|
|
7887
|
+
setReorderHrefKey(null);
|
|
7888
|
+
setReorderDragDisabled(false);
|
|
7889
|
+
setToolbarVariant("select-frame");
|
|
7890
|
+
setToolbarRect(el.getBoundingClientRect());
|
|
7891
|
+
setToolbarShowEditLink(false);
|
|
7892
|
+
setActiveCommands(/* @__PURE__ */ new Set());
|
|
7893
|
+
}, [deactivate]);
|
|
7894
|
+
const activate = (0, import_react8.useCallback)((el, options) => {
|
|
6989
7895
|
if (activeElRef.current === el) return;
|
|
6990
7896
|
selectedElRef.current = null;
|
|
6991
7897
|
deactivate();
|
|
@@ -7003,6 +7909,9 @@ function OhhwellsBridge() {
|
|
|
7003
7909
|
activeElRef.current = el;
|
|
7004
7910
|
originalContentRef.current = el.innerHTML;
|
|
7005
7911
|
el.focus();
|
|
7912
|
+
if (options?.caretX !== void 0 && options?.caretY !== void 0) {
|
|
7913
|
+
placeCaretAtPoint(el, options.caretX, options.caretY);
|
|
7914
|
+
}
|
|
7006
7915
|
setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
|
|
7007
7916
|
const navAnchor = getNavigationItemAnchor(el);
|
|
7008
7917
|
if (navAnchor) {
|
|
@@ -7014,14 +7923,15 @@ function OhhwellsBridge() {
|
|
|
7014
7923
|
setReorderDragDisabled(reorderDisabled);
|
|
7015
7924
|
}
|
|
7016
7925
|
setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
7017
|
-
|
|
7926
|
+
postToParent2({ type: "ow:enter-edit", key: el.dataset.ohwKey });
|
|
7018
7927
|
requestAnimationFrame(() => refreshActiveCommandsRef.current());
|
|
7019
|
-
}, [deactivate,
|
|
7928
|
+
}, [deactivate, postToParent2]);
|
|
7020
7929
|
activateRef.current = activate;
|
|
7021
7930
|
deactivateRef.current = deactivate;
|
|
7022
7931
|
selectRef.current = select;
|
|
7932
|
+
selectFrameRef.current = selectFrame;
|
|
7023
7933
|
deselectRef.current = deselect;
|
|
7024
|
-
(0,
|
|
7934
|
+
(0, import_react8.useLayoutEffect)(() => {
|
|
7025
7935
|
if (!subdomain || isEditMode) {
|
|
7026
7936
|
setFetchState("done");
|
|
7027
7937
|
return;
|
|
@@ -7061,6 +7971,7 @@ function OhhwellsBridge() {
|
|
|
7061
7971
|
});
|
|
7062
7972
|
applyLinkByKey(key, val);
|
|
7063
7973
|
}
|
|
7974
|
+
reconcileNavbarItemsFromContent(content);
|
|
7064
7975
|
enforceLinkHrefs();
|
|
7065
7976
|
initSectionsFromContent(content, true);
|
|
7066
7977
|
sectionsLoadedRef.current = true;
|
|
@@ -7089,7 +8000,7 @@ function OhhwellsBridge() {
|
|
|
7089
8000
|
cancelled = true;
|
|
7090
8001
|
};
|
|
7091
8002
|
}, [subdomain, isEditMode]);
|
|
7092
|
-
(0,
|
|
8003
|
+
(0, import_react8.useEffect)(() => {
|
|
7093
8004
|
if (!subdomain || isEditMode) return;
|
|
7094
8005
|
let debounceTimer = null;
|
|
7095
8006
|
let observer = null;
|
|
@@ -7120,6 +8031,7 @@ function OhhwellsBridge() {
|
|
|
7120
8031
|
});
|
|
7121
8032
|
applyLinkByKey(key, val);
|
|
7122
8033
|
}
|
|
8034
|
+
reconcileNavbarItemsFromContent(content);
|
|
7123
8035
|
} finally {
|
|
7124
8036
|
observer?.observe(document.body, { childList: true, subtree: true });
|
|
7125
8037
|
}
|
|
@@ -7137,26 +8049,44 @@ function OhhwellsBridge() {
|
|
|
7137
8049
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
7138
8050
|
};
|
|
7139
8051
|
}, [subdomain, isEditMode, pathname]);
|
|
7140
|
-
(0,
|
|
8052
|
+
(0, import_react8.useLayoutEffect)(() => {
|
|
7141
8053
|
const el = document.getElementById("ohw-loader");
|
|
7142
8054
|
if (!el) return;
|
|
7143
8055
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
7144
8056
|
el.style.display = visible ? "flex" : "none";
|
|
7145
8057
|
}, [subdomain, fetchState]);
|
|
7146
|
-
(0,
|
|
7147
|
-
|
|
7148
|
-
}, [pathname,
|
|
7149
|
-
(0,
|
|
8058
|
+
(0, import_react8.useEffect)(() => {
|
|
8059
|
+
postToParent2({ type: "ow:navigation", path: pathname });
|
|
8060
|
+
}, [pathname, postToParent2]);
|
|
8061
|
+
(0, import_react8.useEffect)(() => {
|
|
7150
8062
|
if (!isEditMode) return;
|
|
8063
|
+
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
8064
|
+
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
7151
8065
|
setLinkPopover(null);
|
|
7152
8066
|
deselectRef.current();
|
|
7153
8067
|
deactivateRef.current();
|
|
7154
8068
|
}, [pathname, isEditMode]);
|
|
7155
|
-
(0,
|
|
8069
|
+
(0, import_react8.useEffect)(() => {
|
|
8070
|
+
const contentForNav = () => {
|
|
8071
|
+
if (isEditMode) return editContentRef.current;
|
|
8072
|
+
if (!subdomain) return {};
|
|
8073
|
+
return contentCache.get(subdomain) ?? {};
|
|
8074
|
+
};
|
|
8075
|
+
const run = () => reconcileNavbarItemsFromContent(contentForNav());
|
|
8076
|
+
run();
|
|
8077
|
+
const nav = document.querySelector("nav");
|
|
8078
|
+
if (!nav) return;
|
|
8079
|
+
const observer = new MutationObserver(() => {
|
|
8080
|
+
requestAnimationFrame(run);
|
|
8081
|
+
});
|
|
8082
|
+
observer.observe(nav, { childList: true, subtree: true });
|
|
8083
|
+
return () => observer.disconnect();
|
|
8084
|
+
}, [isEditMode, pathname, subdomain, fetchState]);
|
|
8085
|
+
(0, import_react8.useEffect)(() => {
|
|
7156
8086
|
if (!isEditMode) return;
|
|
7157
8087
|
const measure = () => {
|
|
7158
8088
|
const h = document.body.scrollHeight;
|
|
7159
|
-
if (h > 50)
|
|
8089
|
+
if (h > 50) postToParent2({ type: "ow:height", height: h });
|
|
7160
8090
|
};
|
|
7161
8091
|
const t1 = setTimeout(measure, 50);
|
|
7162
8092
|
const t2 = setTimeout(measure, 500);
|
|
@@ -7175,8 +8105,8 @@ function OhhwellsBridge() {
|
|
|
7175
8105
|
if (resizeTimer) clearTimeout(resizeTimer);
|
|
7176
8106
|
window.removeEventListener("resize", handleResize);
|
|
7177
8107
|
};
|
|
7178
|
-
}, [pathname, isEditMode,
|
|
7179
|
-
(0,
|
|
8108
|
+
}, [pathname, isEditMode, postToParent2]);
|
|
8109
|
+
(0, import_react8.useEffect)(() => {
|
|
7180
8110
|
if (!subdomainFromQuery || isEditMode) return;
|
|
7181
8111
|
const handleClick = (e) => {
|
|
7182
8112
|
const anchor = e.target.closest("a");
|
|
@@ -7192,7 +8122,7 @@ function OhhwellsBridge() {
|
|
|
7192
8122
|
document.addEventListener("click", handleClick, true);
|
|
7193
8123
|
return () => document.removeEventListener("click", handleClick, true);
|
|
7194
8124
|
}, [subdomainFromQuery, isEditMode, router]);
|
|
7195
|
-
(0,
|
|
8125
|
+
(0, import_react8.useEffect)(() => {
|
|
7196
8126
|
if (!isEditMode) {
|
|
7197
8127
|
editStylesRef.current?.base.remove();
|
|
7198
8128
|
editStylesRef.current?.forceHover.remove();
|
|
@@ -7265,6 +8195,13 @@ function OhhwellsBridge() {
|
|
|
7265
8195
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
7266
8196
|
if (isInsideLinkEditor(target)) return;
|
|
7267
8197
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
8198
|
+
const navFromChrome = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
8199
|
+
if (navFromChrome) {
|
|
8200
|
+
e.preventDefault();
|
|
8201
|
+
e.stopPropagation();
|
|
8202
|
+
selectFrameRef.current(navFromChrome);
|
|
8203
|
+
return;
|
|
8204
|
+
}
|
|
7268
8205
|
e.preventDefault();
|
|
7269
8206
|
e.stopPropagation();
|
|
7270
8207
|
return;
|
|
@@ -7279,7 +8216,8 @@ function OhhwellsBridge() {
|
|
|
7279
8216
|
bumpLinkPopoverGrace();
|
|
7280
8217
|
setLinkPopoverRef.current({
|
|
7281
8218
|
key: editable.dataset.ohwKey ?? "",
|
|
7282
|
-
|
|
8219
|
+
mode: "edit",
|
|
8220
|
+
target: getLinkHref2(editable)
|
|
7283
8221
|
});
|
|
7284
8222
|
return;
|
|
7285
8223
|
}
|
|
@@ -7295,7 +8233,8 @@ function OhhwellsBridge() {
|
|
|
7295
8233
|
e.preventDefault();
|
|
7296
8234
|
e.stopPropagation();
|
|
7297
8235
|
if (selectedElRef.current === navAnchor) {
|
|
7298
|
-
|
|
8236
|
+
if (e.detail >= 2) return;
|
|
8237
|
+
activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
|
|
7299
8238
|
return;
|
|
7300
8239
|
}
|
|
7301
8240
|
selectRef.current(navAnchor);
|
|
@@ -7314,6 +8253,22 @@ function OhhwellsBridge() {
|
|
|
7314
8253
|
selectRef.current(hrefAnchor);
|
|
7315
8254
|
return;
|
|
7316
8255
|
}
|
|
8256
|
+
const navContainerToSelect = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
8257
|
+
if (navContainerToSelect) {
|
|
8258
|
+
e.preventDefault();
|
|
8259
|
+
e.stopPropagation();
|
|
8260
|
+
selectFrameRef.current(navContainerToSelect);
|
|
8261
|
+
return;
|
|
8262
|
+
}
|
|
8263
|
+
const selectedContainer = selectedElRef.current;
|
|
8264
|
+
if (selectedContainer && isNavigationContainer(selectedContainer)) {
|
|
8265
|
+
const navItem = getNavigationItemAnchor(target);
|
|
8266
|
+
if (!navItem && (selectedContainer === target || selectedContainer.contains(target))) {
|
|
8267
|
+
e.preventDefault();
|
|
8268
|
+
e.stopPropagation();
|
|
8269
|
+
return;
|
|
8270
|
+
}
|
|
8271
|
+
}
|
|
7317
8272
|
if (activeElRef.current) {
|
|
7318
8273
|
const sel = window.getSelection();
|
|
7319
8274
|
if (sel && !sel.isCollapsed) {
|
|
@@ -7339,10 +8294,49 @@ function OhhwellsBridge() {
|
|
|
7339
8294
|
deselectRef.current();
|
|
7340
8295
|
deactivateRef.current();
|
|
7341
8296
|
};
|
|
8297
|
+
const handleDblClick = (e) => {
|
|
8298
|
+
const target = e.target;
|
|
8299
|
+
if (target.closest("[data-ohw-toolbar]")) return;
|
|
8300
|
+
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
8301
|
+
if (target.closest("[data-ohw-max-badge]")) return;
|
|
8302
|
+
if (isInsideLinkEditor(target)) return;
|
|
8303
|
+
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
8304
|
+
return;
|
|
8305
|
+
}
|
|
8306
|
+
const navLabel = getNavigationLabelEditable(target);
|
|
8307
|
+
if (!navLabel) return;
|
|
8308
|
+
const { editable } = navLabel;
|
|
8309
|
+
e.preventDefault();
|
|
8310
|
+
e.stopPropagation();
|
|
8311
|
+
if (activeElRef.current !== editable) {
|
|
8312
|
+
activateRef.current(editable);
|
|
8313
|
+
}
|
|
8314
|
+
requestAnimationFrame(() => {
|
|
8315
|
+
selectAllTextInEditable(editable);
|
|
8316
|
+
refreshActiveCommandsRef.current();
|
|
8317
|
+
});
|
|
8318
|
+
};
|
|
7342
8319
|
const handleMouseOver = (e) => {
|
|
8320
|
+
if (document.documentElement.hasAttribute("data-ohw-section-picking")) return;
|
|
7343
8321
|
const target = e.target;
|
|
8322
|
+
if (toolbarVariantRef.current !== "select-frame") {
|
|
8323
|
+
const navContainer = target.closest("[data-ohw-nav-container]");
|
|
8324
|
+
if (navContainer && !getNavigationItemAnchor(target)) {
|
|
8325
|
+
hoveredNavContainerRef.current = navContainer;
|
|
8326
|
+
setHoveredNavContainerRect(navContainer.getBoundingClientRect());
|
|
8327
|
+
hoveredItemElRef.current = null;
|
|
8328
|
+
setHoveredItemRect(null);
|
|
8329
|
+
return;
|
|
8330
|
+
}
|
|
8331
|
+
if (!target.closest("[data-ohw-nav-container]")) {
|
|
8332
|
+
hoveredNavContainerRef.current = null;
|
|
8333
|
+
setHoveredNavContainerRect(null);
|
|
8334
|
+
}
|
|
8335
|
+
}
|
|
7344
8336
|
const navAnchor = getNavigationItemAnchor(target);
|
|
7345
8337
|
if (navAnchor) {
|
|
8338
|
+
hoveredNavContainerRef.current = null;
|
|
8339
|
+
setHoveredNavContainerRect(null);
|
|
7346
8340
|
const selected2 = selectedElRef.current;
|
|
7347
8341
|
if (selected2 === navAnchor || selected2?.contains(navAnchor)) return;
|
|
7348
8342
|
clearHrefKeyHover(navAnchor);
|
|
@@ -7367,6 +8361,14 @@ function OhhwellsBridge() {
|
|
|
7367
8361
|
};
|
|
7368
8362
|
const handleMouseOut = (e) => {
|
|
7369
8363
|
const target = e.target;
|
|
8364
|
+
if (target.closest("[data-ohw-nav-container]")) {
|
|
8365
|
+
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
8366
|
+
if (related2?.closest("[data-ohw-nav-container], [data-ohw-navbar-container-chrome], [data-ohw-navbar-add-button]")) {
|
|
8367
|
+
return;
|
|
8368
|
+
}
|
|
8369
|
+
hoveredNavContainerRef.current = null;
|
|
8370
|
+
setHoveredNavContainerRect(null);
|
|
8371
|
+
}
|
|
7370
8372
|
const navAnchor = getNavigationItemAnchor(target);
|
|
7371
8373
|
if (navAnchor) {
|
|
7372
8374
|
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
@@ -7488,6 +8490,56 @@ function OhhwellsBridge() {
|
|
|
7488
8490
|
}
|
|
7489
8491
|
return smallest;
|
|
7490
8492
|
};
|
|
8493
|
+
const dismissImageHover = () => {
|
|
8494
|
+
if (hoveredImageRef.current) {
|
|
8495
|
+
hoveredImageRef.current = null;
|
|
8496
|
+
hoveredImageHasTextOverlapRef.current = false;
|
|
8497
|
+
resumeAnimTracks();
|
|
8498
|
+
postToParentRef.current({ type: "ow:image-unhover" });
|
|
8499
|
+
}
|
|
8500
|
+
};
|
|
8501
|
+
const probeNavigationHoverAt = (x, y) => {
|
|
8502
|
+
if (toolbarVariantRef.current === "select-frame") {
|
|
8503
|
+
hoveredNavContainerRef.current = null;
|
|
8504
|
+
setHoveredNavContainerRect(null);
|
|
8505
|
+
return;
|
|
8506
|
+
}
|
|
8507
|
+
const navContainer = document.querySelector("[data-ohw-nav-container]");
|
|
8508
|
+
if (!navContainer) {
|
|
8509
|
+
hoveredNavContainerRef.current = null;
|
|
8510
|
+
setHoveredNavContainerRect(null);
|
|
8511
|
+
return;
|
|
8512
|
+
}
|
|
8513
|
+
const containerRect = navContainer.getBoundingClientRect();
|
|
8514
|
+
const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
|
|
8515
|
+
if (!overContainer) {
|
|
8516
|
+
hoveredNavContainerRef.current = null;
|
|
8517
|
+
setHoveredNavContainerRect(null);
|
|
8518
|
+
return;
|
|
8519
|
+
}
|
|
8520
|
+
const navItemHit = Array.from(
|
|
8521
|
+
navContainer.querySelectorAll("[data-ohw-href-key]")
|
|
8522
|
+
).find((el) => {
|
|
8523
|
+
if (!isNavigationItem(el) || isNavbarButton2(el)) return false;
|
|
8524
|
+
const itemRect = el.getBoundingClientRect();
|
|
8525
|
+
return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
|
|
8526
|
+
});
|
|
8527
|
+
if (navItemHit) {
|
|
8528
|
+
hoveredNavContainerRef.current = null;
|
|
8529
|
+
setHoveredNavContainerRect(null);
|
|
8530
|
+
const selected = selectedElRef.current;
|
|
8531
|
+
if (selected !== navItemHit && !selected?.contains(navItemHit)) {
|
|
8532
|
+
clearHrefKeyHover(navItemHit);
|
|
8533
|
+
hoveredItemElRef.current = navItemHit;
|
|
8534
|
+
setHoveredItemRect(navItemHit.getBoundingClientRect());
|
|
8535
|
+
}
|
|
8536
|
+
return;
|
|
8537
|
+
}
|
|
8538
|
+
hoveredNavContainerRef.current = navContainer;
|
|
8539
|
+
setHoveredNavContainerRect(containerRect);
|
|
8540
|
+
hoveredItemElRef.current = null;
|
|
8541
|
+
setHoveredItemRect(null);
|
|
8542
|
+
};
|
|
7491
8543
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
7492
8544
|
if (linkPopoverOpenRef.current) {
|
|
7493
8545
|
if (hoveredImageRef.current) {
|
|
@@ -7496,18 +8548,22 @@ function OhhwellsBridge() {
|
|
|
7496
8548
|
resumeAnimTracks();
|
|
7497
8549
|
clearImageHover();
|
|
7498
8550
|
}
|
|
8551
|
+
dismissImageHover();
|
|
8552
|
+
return;
|
|
8553
|
+
}
|
|
8554
|
+
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
8555
|
+
if (isPointOverNavigation(x, y)) {
|
|
8556
|
+
dismissImageHover();
|
|
8557
|
+
probeNavigationHoverAt(x, y);
|
|
7499
8558
|
return;
|
|
7500
8559
|
}
|
|
8560
|
+
hoveredNavContainerRef.current = null;
|
|
8561
|
+
setHoveredNavContainerRect(null);
|
|
7501
8562
|
const toggleEl = document.querySelector("[data-ohw-state-toggle]");
|
|
7502
8563
|
if (toggleEl) {
|
|
7503
|
-
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7504
8564
|
const tr = toggleEl.getBoundingClientRect();
|
|
7505
8565
|
if (x >= tr.left && x <= tr.right && y >= tr.top && y <= tr.bottom) {
|
|
7506
|
-
|
|
7507
|
-
hoveredImageRef.current = null;
|
|
7508
|
-
resumeAnimTracks();
|
|
7509
|
-
clearImageHover();
|
|
7510
|
-
}
|
|
8566
|
+
dismissImageHover();
|
|
7511
8567
|
return;
|
|
7512
8568
|
}
|
|
7513
8569
|
}
|
|
@@ -7520,15 +8576,18 @@ function OhhwellsBridge() {
|
|
|
7520
8576
|
resumeAnimTracks();
|
|
7521
8577
|
clearImageHover();
|
|
7522
8578
|
}
|
|
7523
|
-
|
|
8579
|
+
if (activeElRef.current) {
|
|
8580
|
+
dismissImageHover();
|
|
8581
|
+
return;
|
|
8582
|
+
}
|
|
7524
8583
|
}
|
|
7525
8584
|
if (imgEl) {
|
|
7526
|
-
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
8585
|
+
const { x: x2, y: y2 } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7527
8586
|
const overMediaChrome = Array.from(
|
|
7528
8587
|
document.querySelectorAll("[data-ohw-media-chrome]")
|
|
7529
8588
|
).some((el) => {
|
|
7530
8589
|
const r2 = el.getBoundingClientRect();
|
|
7531
|
-
return
|
|
8590
|
+
return x2 >= r2.left && x2 <= r2.right && y2 >= r2.top && y2 <= r2.bottom;
|
|
7532
8591
|
});
|
|
7533
8592
|
if (overMediaChrome) {
|
|
7534
8593
|
if (hoveredImageRef.current) {
|
|
@@ -7539,7 +8598,7 @@ function OhhwellsBridge() {
|
|
|
7539
8598
|
}
|
|
7540
8599
|
return;
|
|
7541
8600
|
}
|
|
7542
|
-
const topEl = document.elementFromPoint(
|
|
8601
|
+
const topEl = document.elementFromPoint(x2, y2);
|
|
7543
8602
|
if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
7544
8603
|
if (hoveredImageRef.current) {
|
|
7545
8604
|
hoveredImageRef.current = null;
|
|
@@ -7562,7 +8621,7 @@ function OhhwellsBridge() {
|
|
|
7562
8621
|
document.querySelectorAll(NON_MEDIA_SELECTOR)
|
|
7563
8622
|
).find((el) => {
|
|
7564
8623
|
const er = el.getBoundingClientRect();
|
|
7565
|
-
return
|
|
8624
|
+
return x2 >= er.left && x2 <= er.right && y2 >= er.top && y2 <= er.bottom;
|
|
7566
8625
|
});
|
|
7567
8626
|
if (imageUnhoverTimerRef.current) {
|
|
7568
8627
|
clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -7638,12 +8697,12 @@ function OhhwellsBridge() {
|
|
|
7638
8697
|
resumeAnimTracks();
|
|
7639
8698
|
clearImageHover();
|
|
7640
8699
|
}
|
|
7641
|
-
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
8700
|
+
const { x: x2, y: y2 } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7642
8701
|
const textEl = Array.from(
|
|
7643
8702
|
document.querySelectorAll(NON_MEDIA_SELECTOR)
|
|
7644
8703
|
).find((el) => {
|
|
7645
8704
|
const er = el.getBoundingClientRect();
|
|
7646
|
-
return
|
|
8705
|
+
return x2 >= er.left && x2 <= er.right && y2 >= er.top && y2 <= er.bottom;
|
|
7647
8706
|
});
|
|
7648
8707
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
7649
8708
|
if (textEl && !textEl.hasAttribute("contenteditable")) {
|
|
@@ -7667,6 +8726,14 @@ function OhhwellsBridge() {
|
|
|
7667
8726
|
}
|
|
7668
8727
|
};
|
|
7669
8728
|
const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
|
|
8729
|
+
if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
|
|
8730
|
+
if (activeStateElRef.current) {
|
|
8731
|
+
activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
|
|
8732
|
+
activeStateElRef.current = null;
|
|
8733
|
+
setToggleState(null);
|
|
8734
|
+
}
|
|
8735
|
+
return;
|
|
8736
|
+
}
|
|
7670
8737
|
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7671
8738
|
const toggleEl = document.querySelector("[data-ohw-state-toggle]");
|
|
7672
8739
|
if (toggleEl) {
|
|
@@ -7943,6 +9010,8 @@ function OhhwellsBridge() {
|
|
|
7943
9010
|
sectionsLoadedRef.current = true;
|
|
7944
9011
|
pendingScheduleConfigRequests.current.splice(0).forEach(processConfigRequest);
|
|
7945
9012
|
}
|
|
9013
|
+
editContentRef.current = { ...editContentRef.current, ...content };
|
|
9014
|
+
reconcileNavbarItemsFromContent(editContentRef.current);
|
|
7946
9015
|
enforceLinkHrefs();
|
|
7947
9016
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
7948
9017
|
};
|
|
@@ -7950,6 +9019,7 @@ function OhhwellsBridge() {
|
|
|
7950
9019
|
const handleDeactivate = (e) => {
|
|
7951
9020
|
if (e.data?.type !== "ow:deactivate") return;
|
|
7952
9021
|
if (Date.now() < linkPopoverGraceUntilRef.current) return;
|
|
9022
|
+
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
7953
9023
|
if (linkPopoverOpenRef.current) {
|
|
7954
9024
|
setLinkPopoverRef.current(null);
|
|
7955
9025
|
return;
|
|
@@ -7958,13 +9028,40 @@ function OhhwellsBridge() {
|
|
|
7958
9028
|
deactivateRef.current();
|
|
7959
9029
|
};
|
|
7960
9030
|
window.addEventListener("message", handleDeactivate);
|
|
9031
|
+
const handleUiEscape = (e) => {
|
|
9032
|
+
if (e.data?.type !== "ui:escape") return;
|
|
9033
|
+
if (linkPopoverOpenRef.current) {
|
|
9034
|
+
setLinkPopoverRef.current(null);
|
|
9035
|
+
}
|
|
9036
|
+
};
|
|
9037
|
+
window.addEventListener("message", handleUiEscape);
|
|
7961
9038
|
const handleKeyDown = (e) => {
|
|
9039
|
+
if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
|
|
9040
|
+
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
|
|
9041
|
+
const navAnchor = getNavigationItemAnchor(activeElRef.current);
|
|
9042
|
+
if (navAnchor) {
|
|
9043
|
+
e.preventDefault();
|
|
9044
|
+
selectAllTextInEditable(activeElRef.current);
|
|
9045
|
+
refreshActiveCommandsRef.current();
|
|
9046
|
+
return;
|
|
9047
|
+
}
|
|
9048
|
+
}
|
|
7962
9049
|
if (e.key === "Escape" && linkPopoverOpenRef.current) {
|
|
7963
9050
|
setLinkPopoverRef.current(null);
|
|
7964
9051
|
return;
|
|
7965
9052
|
}
|
|
7966
9053
|
if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
|
|
7967
|
-
|
|
9054
|
+
if (toolbarVariantRef.current === "select-frame") {
|
|
9055
|
+
deselectRef.current();
|
|
9056
|
+
return;
|
|
9057
|
+
}
|
|
9058
|
+
const parent = getNavigationSelectionParent(selectedElRef.current);
|
|
9059
|
+
if (parent) {
|
|
9060
|
+
e.preventDefault();
|
|
9061
|
+
selectFrameRef.current(parent);
|
|
9062
|
+
} else {
|
|
9063
|
+
deselectRef.current();
|
|
9064
|
+
}
|
|
7968
9065
|
return;
|
|
7969
9066
|
}
|
|
7970
9067
|
if (e.key === "Escape" && activeElRef.current) {
|
|
@@ -8022,6 +9119,9 @@ function OhhwellsBridge() {
|
|
|
8022
9119
|
if (hoveredItemElRef.current) {
|
|
8023
9120
|
setHoveredItemRect(hoveredItemElRef.current.getBoundingClientRect());
|
|
8024
9121
|
}
|
|
9122
|
+
if (hoveredNavContainerRef.current) {
|
|
9123
|
+
setHoveredNavContainerRect(hoveredNavContainerRef.current.getBoundingClientRect());
|
|
9124
|
+
}
|
|
8025
9125
|
if (siblingHintElRef.current) {
|
|
8026
9126
|
setSiblingHintRect(siblingHintElRef.current.getBoundingClientRect());
|
|
8027
9127
|
}
|
|
@@ -8218,9 +9318,45 @@ function OhhwellsBridge() {
|
|
|
8218
9318
|
return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
|
|
8219
9319
|
});
|
|
8220
9320
|
if (textEditable) {
|
|
8221
|
-
|
|
9321
|
+
const hrefCtx = getHrefKeyFromElement(textEditable);
|
|
9322
|
+
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
9323
|
+
if (navAnchor) {
|
|
9324
|
+
if (selectedElRef.current === navAnchor) {
|
|
9325
|
+
activateRef.current(textEditable, { caretX: clientX, caretY: clientY });
|
|
9326
|
+
} else {
|
|
9327
|
+
selectRef.current(navAnchor);
|
|
9328
|
+
}
|
|
9329
|
+
return;
|
|
9330
|
+
}
|
|
9331
|
+
activateRef.current(textEditable, { caretX: clientX, caretY: clientY });
|
|
8222
9332
|
return;
|
|
8223
9333
|
}
|
|
9334
|
+
const navContainer = document.querySelector("[data-ohw-nav-container]");
|
|
9335
|
+
if (navContainer) {
|
|
9336
|
+
const r2 = navContainer.getBoundingClientRect();
|
|
9337
|
+
const pad = 8;
|
|
9338
|
+
const over = clientX >= r2.left - pad && clientX <= r2.right + pad && clientY >= r2.top - pad && clientY <= r2.bottom + pad;
|
|
9339
|
+
if (over && !isPointOverNavItem(navContainer, clientX, clientY)) {
|
|
9340
|
+
selectFrameRef.current(navContainer);
|
|
9341
|
+
return;
|
|
9342
|
+
}
|
|
9343
|
+
}
|
|
9344
|
+
const navRoot = document.querySelector("[data-ohw-nav-root]");
|
|
9345
|
+
if (navRoot && navContainer) {
|
|
9346
|
+
const rr = navRoot.getBoundingClientRect();
|
|
9347
|
+
if (clientX >= rr.left && clientX <= rr.right && clientY >= rr.top && clientY <= rr.bottom && !isPointOverNavItem(navContainer, clientX, clientY)) {
|
|
9348
|
+
const book = navRoot.querySelector('[data-ohw-role="navbar-button"]');
|
|
9349
|
+
if (book) {
|
|
9350
|
+
const br = book.getBoundingClientRect();
|
|
9351
|
+
if (clientX >= br.left && clientX <= br.right && clientY >= br.top && clientY <= br.bottom) {
|
|
9352
|
+
deactivateRef.current();
|
|
9353
|
+
return;
|
|
9354
|
+
}
|
|
9355
|
+
}
|
|
9356
|
+
selectFrameRef.current(navContainer);
|
|
9357
|
+
return;
|
|
9358
|
+
}
|
|
9359
|
+
}
|
|
8224
9360
|
deactivateRef.current();
|
|
8225
9361
|
};
|
|
8226
9362
|
window.addEventListener("message", handleSave);
|
|
@@ -8242,6 +9378,7 @@ function OhhwellsBridge() {
|
|
|
8242
9378
|
};
|
|
8243
9379
|
window.addEventListener("resize", handleViewportResize, { passive: true });
|
|
8244
9380
|
document.addEventListener("click", handleClick, true);
|
|
9381
|
+
document.addEventListener("dblclick", handleDblClick, true);
|
|
8245
9382
|
document.addEventListener("paste", handlePaste, true);
|
|
8246
9383
|
document.addEventListener("input", handleInput, true);
|
|
8247
9384
|
document.addEventListener("mouseover", handleMouseOver, true);
|
|
@@ -8256,6 +9393,7 @@ function OhhwellsBridge() {
|
|
|
8256
9393
|
window.addEventListener("scroll", handleScroll, true);
|
|
8257
9394
|
return () => {
|
|
8258
9395
|
document.removeEventListener("click", handleClick, true);
|
|
9396
|
+
document.removeEventListener("dblclick", handleDblClick, true);
|
|
8259
9397
|
document.removeEventListener("paste", handlePaste, true);
|
|
8260
9398
|
document.removeEventListener("input", handleInput, true);
|
|
8261
9399
|
document.removeEventListener("mouseover", handleMouseOver, true);
|
|
@@ -8283,13 +9421,14 @@ function OhhwellsBridge() {
|
|
|
8283
9421
|
window.removeEventListener("message", handleClickAt);
|
|
8284
9422
|
window.removeEventListener("message", handleHydrate);
|
|
8285
9423
|
window.removeEventListener("message", handleDeactivate);
|
|
9424
|
+
window.removeEventListener("message", handleUiEscape);
|
|
8286
9425
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
8287
9426
|
autoSaveTimers.current.clear();
|
|
8288
9427
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
8289
9428
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
8290
9429
|
};
|
|
8291
9430
|
}, [isEditMode, refreshStateRules]);
|
|
8292
|
-
(0,
|
|
9431
|
+
(0, import_react8.useEffect)(() => {
|
|
8293
9432
|
const handler = (e) => {
|
|
8294
9433
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
8295
9434
|
const insertAfterVal = e.data.insertAfter;
|
|
@@ -8305,7 +9444,7 @@ function OhhwellsBridge() {
|
|
|
8305
9444
|
window.addEventListener("message", handler);
|
|
8306
9445
|
return () => window.removeEventListener("message", handler);
|
|
8307
9446
|
}, [processConfigRequest]);
|
|
8308
|
-
(0,
|
|
9447
|
+
(0, import_react8.useEffect)(() => {
|
|
8309
9448
|
if (!isEditMode) return;
|
|
8310
9449
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|
|
8311
9450
|
el.removeAttribute("data-ohw-active-state");
|
|
@@ -8326,27 +9465,27 @@ function OhhwellsBridge() {
|
|
|
8326
9465
|
const next = { ...prev, [pathKey]: sections };
|
|
8327
9466
|
return shouldUseDevFixtures() ? { ...DEV_SECTIONS_BY_PATH, ...next } : next;
|
|
8328
9467
|
});
|
|
8329
|
-
|
|
8330
|
-
|
|
9468
|
+
postToParent2({ type: "ow:ready", version: "1", path: pathname, nodes: collectEditableNodes(), sections });
|
|
9469
|
+
postToParent2({ type: "ow:request-site-pages" });
|
|
8331
9470
|
}, 150);
|
|
8332
9471
|
return () => {
|
|
8333
9472
|
cancelAnimationFrame(raf);
|
|
8334
9473
|
clearTimeout(timer);
|
|
8335
9474
|
};
|
|
8336
|
-
}, [pathname, isEditMode, refreshStateRules,
|
|
8337
|
-
(0,
|
|
9475
|
+
}, [pathname, isEditMode, refreshStateRules, postToParent2]);
|
|
9476
|
+
(0, import_react8.useEffect)(() => {
|
|
8338
9477
|
scrollToHashSectionWhenReady();
|
|
8339
9478
|
const onHashChange = () => scrollToHashSectionWhenReady();
|
|
8340
9479
|
window.addEventListener("hashchange", onHashChange);
|
|
8341
9480
|
return () => window.removeEventListener("hashchange", onHashChange);
|
|
8342
9481
|
}, [pathname]);
|
|
8343
|
-
const handleCommand = (0,
|
|
9482
|
+
const handleCommand = (0, import_react8.useCallback)((cmd) => {
|
|
8344
9483
|
document.execCommand(cmd, false);
|
|
8345
9484
|
activeElRef.current?.focus();
|
|
8346
9485
|
if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
|
|
8347
9486
|
refreshActiveCommandsRef.current();
|
|
8348
9487
|
}, []);
|
|
8349
|
-
const handleStateChange = (0,
|
|
9488
|
+
const handleStateChange = (0, import_react8.useCallback)((state) => {
|
|
8350
9489
|
if (!activeStateElRef.current) return;
|
|
8351
9490
|
const el = activeStateElRef.current;
|
|
8352
9491
|
if (state === "Default") {
|
|
@@ -8359,18 +9498,22 @@ function OhhwellsBridge() {
|
|
|
8359
9498
|
}
|
|
8360
9499
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
8361
9500
|
}, [deactivate]);
|
|
8362
|
-
const closeLinkPopover = (0,
|
|
8363
|
-
|
|
9501
|
+
const closeLinkPopover = (0, import_react8.useCallback)(() => {
|
|
9502
|
+
addNavAfterAnchorRef.current = null;
|
|
9503
|
+
setLinkPopover(null);
|
|
9504
|
+
}, []);
|
|
9505
|
+
const openLinkPopoverForActive = (0, import_react8.useCallback)(() => {
|
|
8364
9506
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
8365
9507
|
if (!hrefCtx) return;
|
|
8366
9508
|
bumpLinkPopoverGrace();
|
|
8367
9509
|
setLinkPopover({
|
|
8368
9510
|
key: hrefCtx.key,
|
|
8369
|
-
|
|
9511
|
+
mode: "edit",
|
|
9512
|
+
target: getLinkHref2(hrefCtx.anchor)
|
|
8370
9513
|
});
|
|
8371
9514
|
deactivate();
|
|
8372
9515
|
}, [deactivate]);
|
|
8373
|
-
const openLinkPopoverForSelected = (0,
|
|
9516
|
+
const openLinkPopoverForSelected = (0, import_react8.useCallback)(() => {
|
|
8374
9517
|
const anchor = selectedElRef.current;
|
|
8375
9518
|
if (!anchor) return;
|
|
8376
9519
|
const key = anchor.getAttribute("data-ohw-href-key");
|
|
@@ -8378,30 +9521,77 @@ function OhhwellsBridge() {
|
|
|
8378
9521
|
bumpLinkPopoverGrace();
|
|
8379
9522
|
setLinkPopover({
|
|
8380
9523
|
key,
|
|
8381
|
-
|
|
9524
|
+
mode: "edit",
|
|
9525
|
+
target: getLinkHref2(anchor)
|
|
8382
9526
|
});
|
|
8383
9527
|
deselect();
|
|
8384
9528
|
}, [deselect]);
|
|
8385
|
-
const handleLinkPopoverSubmit = (0,
|
|
9529
|
+
const handleLinkPopoverSubmit = (0, import_react8.useCallback)(
|
|
8386
9530
|
(target) => {
|
|
8387
|
-
|
|
8388
|
-
|
|
9531
|
+
const session = linkPopoverSessionRef.current;
|
|
9532
|
+
if (!session) return;
|
|
9533
|
+
if (session.intent === "add-nav") {
|
|
9534
|
+
const trimmed = target.trim();
|
|
9535
|
+
let href = trimmed;
|
|
9536
|
+
let label = "Untitled";
|
|
9537
|
+
if (trimmed) {
|
|
9538
|
+
const { pageRoute, sectionId } = parseTarget(trimmed);
|
|
9539
|
+
const page = resolvePage(pageRoute, sitePages);
|
|
9540
|
+
const pageSections = getSectionsForPath(sectionsByPath, pageRoute);
|
|
9541
|
+
const section = sectionId ? pageSections.find((s) => s.id === sectionId) : void 0;
|
|
9542
|
+
label = section?.label ?? page.title;
|
|
9543
|
+
href = trimmed;
|
|
9544
|
+
}
|
|
9545
|
+
const afterAnchor = addNavAfterAnchorRef.current;
|
|
9546
|
+
const { anchor, hrefKey, labelKey, index, order } = insertNavbarItem(href, label, afterAnchor);
|
|
9547
|
+
applyLinkByKey(hrefKey, href);
|
|
9548
|
+
document.querySelectorAll(`[data-ohw-key="${labelKey}"]`).forEach((el) => {
|
|
9549
|
+
el.textContent = label;
|
|
9550
|
+
});
|
|
9551
|
+
const navCount = String(index + 1);
|
|
9552
|
+
const orderJson = JSON.stringify(order);
|
|
9553
|
+
editContentRef.current = {
|
|
9554
|
+
...editContentRef.current,
|
|
9555
|
+
[hrefKey]: href,
|
|
9556
|
+
[labelKey]: label,
|
|
9557
|
+
[NAV_COUNT_KEY]: navCount,
|
|
9558
|
+
[NAV_ORDER_KEY]: orderJson
|
|
9559
|
+
};
|
|
9560
|
+
postToParent2({
|
|
9561
|
+
type: "ow:change",
|
|
9562
|
+
nodes: [
|
|
9563
|
+
{ key: hrefKey, text: href },
|
|
9564
|
+
{ key: labelKey, text: label },
|
|
9565
|
+
{ key: NAV_COUNT_KEY, text: navCount },
|
|
9566
|
+
{ key: NAV_ORDER_KEY, text: orderJson }
|
|
9567
|
+
]
|
|
9568
|
+
});
|
|
9569
|
+
postToParent2({ type: "ow:toast", title: "Link added", toastType: "success" });
|
|
9570
|
+
addNavAfterAnchorRef.current = null;
|
|
9571
|
+
setLinkPopover(null);
|
|
9572
|
+
enforceLinkHrefs();
|
|
9573
|
+
requestAnimationFrame(() => {
|
|
9574
|
+
selectRef.current(anchor);
|
|
9575
|
+
});
|
|
9576
|
+
return;
|
|
9577
|
+
}
|
|
9578
|
+
const { key } = session;
|
|
8389
9579
|
applyLinkByKey(key, target);
|
|
8390
|
-
|
|
9580
|
+
postToParent2({ type: "ow:change", nodes: [{ key, text: target }] });
|
|
8391
9581
|
setLinkPopover(null);
|
|
8392
9582
|
},
|
|
8393
|
-
[
|
|
9583
|
+
[postToParent2, sitePages, sectionsByPath]
|
|
8394
9584
|
);
|
|
8395
9585
|
const showEditLink = toolbarShowEditLink;
|
|
8396
9586
|
const currentSections = sectionsByPath[pathname] ?? [];
|
|
8397
9587
|
linkPopoverOpenRef.current = linkPopover !== null;
|
|
8398
|
-
const handleMediaReplace = (0,
|
|
9588
|
+
const handleMediaReplace = (0, import_react8.useCallback)(
|
|
8399
9589
|
(key) => {
|
|
8400
|
-
|
|
9590
|
+
postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
|
|
8401
9591
|
},
|
|
8402
|
-
[
|
|
9592
|
+
[postToParent2, mediaHover?.elementType]
|
|
8403
9593
|
);
|
|
8404
|
-
const handleMediaFadeOutComplete = (0,
|
|
9594
|
+
const handleMediaFadeOutComplete = (0, import_react8.useCallback)((key) => {
|
|
8405
9595
|
setUploadingRects((prev) => {
|
|
8406
9596
|
if (!(key in prev)) return prev;
|
|
8407
9597
|
const next = { ...prev };
|
|
@@ -8409,7 +9599,7 @@ function OhhwellsBridge() {
|
|
|
8409
9599
|
return next;
|
|
8410
9600
|
});
|
|
8411
9601
|
}, []);
|
|
8412
|
-
const handleVideoSettingsChange = (0,
|
|
9602
|
+
const handleVideoSettingsChange = (0, import_react8.useCallback)(
|
|
8413
9603
|
(key, settings) => {
|
|
8414
9604
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
8415
9605
|
const video = getVideoEl(el);
|
|
@@ -8417,7 +9607,7 @@ function OhhwellsBridge() {
|
|
|
8417
9607
|
if (typeof settings.autoplay === "boolean") video.autoplay = settings.autoplay;
|
|
8418
9608
|
if (typeof settings.muted === "boolean") video.muted = settings.muted;
|
|
8419
9609
|
syncVideoPlayback(video);
|
|
8420
|
-
|
|
9610
|
+
postToParent2({
|
|
8421
9611
|
type: "ow:change",
|
|
8422
9612
|
nodes: [
|
|
8423
9613
|
{ key: `${key}${VIDEO_AUTOPLAY_SUFFIX}`, text: String(video.autoplay) },
|
|
@@ -8429,12 +9619,12 @@ function OhhwellsBridge() {
|
|
|
8429
9619
|
);
|
|
8430
9620
|
});
|
|
8431
9621
|
},
|
|
8432
|
-
[
|
|
9622
|
+
[postToParent2]
|
|
8433
9623
|
);
|
|
8434
|
-
return bridgeRoot ? (0,
|
|
8435
|
-
/* @__PURE__ */ (0,
|
|
8436
|
-
/* @__PURE__ */ (0,
|
|
8437
|
-
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0,
|
|
9624
|
+
return bridgeRoot ? (0, import_react_dom3.createPortal)(
|
|
9625
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
9626
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
9627
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8438
9628
|
MediaOverlay,
|
|
8439
9629
|
{
|
|
8440
9630
|
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
@@ -8445,7 +9635,7 @@ function OhhwellsBridge() {
|
|
|
8445
9635
|
},
|
|
8446
9636
|
`uploading-${key}`
|
|
8447
9637
|
)),
|
|
8448
|
-
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0,
|
|
9638
|
+
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8449
9639
|
MediaOverlay,
|
|
8450
9640
|
{
|
|
8451
9641
|
hover: mediaHover,
|
|
@@ -8454,31 +9644,40 @@ function OhhwellsBridge() {
|
|
|
8454
9644
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
8455
9645
|
}
|
|
8456
9646
|
),
|
|
8457
|
-
siblingHintRect && !isItemDragging && /* @__PURE__ */ (0,
|
|
8458
|
-
|
|
8459
|
-
|
|
9647
|
+
siblingHintRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
9648
|
+
hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && !siblingHintRect && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
9649
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
9650
|
+
NavbarContainerChrome,
|
|
9651
|
+
{
|
|
9652
|
+
rect: toolbarRect,
|
|
9653
|
+
onAdd: handleAddTopLevelNavItem
|
|
9654
|
+
}
|
|
9655
|
+
),
|
|
9656
|
+
hoveredItemRect && !hoveredNavContainerRect && !siblingHintRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
9657
|
+
toolbarRect && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8460
9658
|
ItemInteractionLayer,
|
|
8461
9659
|
{
|
|
8462
9660
|
rect: toolbarRect,
|
|
8463
9661
|
elRef: glowElRef,
|
|
8464
9662
|
state: isItemDragging ? "dragging" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
8465
|
-
showHandle: Boolean(reorderHrefKey),
|
|
9663
|
+
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey),
|
|
8466
9664
|
dragDisabled: reorderDragDisabled,
|
|
8467
9665
|
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
8468
9666
|
onDragHandleDragStart: handleItemDragStart,
|
|
8469
9667
|
onDragHandleDragEnd: handleItemDragEnd,
|
|
8470
|
-
toolbar:
|
|
9668
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8471
9669
|
ItemActionToolbar,
|
|
8472
9670
|
{
|
|
8473
9671
|
onEditLink: openLinkPopoverForSelected,
|
|
8474
|
-
|
|
8475
|
-
|
|
9672
|
+
addItemDisabled: true,
|
|
9673
|
+
editLinkDisabled: false,
|
|
9674
|
+
moreDisabled: true
|
|
8476
9675
|
}
|
|
8477
|
-
)
|
|
9676
|
+
) : void 0
|
|
8478
9677
|
}
|
|
8479
9678
|
),
|
|
8480
|
-
toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ (0,
|
|
8481
|
-
/* @__PURE__ */ (0,
|
|
9679
|
+
toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
9680
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8482
9681
|
EditGlowChrome,
|
|
8483
9682
|
{
|
|
8484
9683
|
rect: toolbarRect,
|
|
@@ -8487,7 +9686,7 @@ function OhhwellsBridge() {
|
|
|
8487
9686
|
dragDisabled: reorderDragDisabled
|
|
8488
9687
|
}
|
|
8489
9688
|
),
|
|
8490
|
-
/* @__PURE__ */ (0,
|
|
9689
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8491
9690
|
FloatingToolbar,
|
|
8492
9691
|
{
|
|
8493
9692
|
rect: toolbarRect,
|
|
@@ -8500,7 +9699,7 @@ function OhhwellsBridge() {
|
|
|
8500
9699
|
}
|
|
8501
9700
|
)
|
|
8502
9701
|
] }),
|
|
8503
|
-
maxBadge && /* @__PURE__ */ (0,
|
|
9702
|
+
maxBadge && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
8504
9703
|
"div",
|
|
8505
9704
|
{
|
|
8506
9705
|
"data-ohw-max-badge": "",
|
|
@@ -8526,7 +9725,7 @@ function OhhwellsBridge() {
|
|
|
8526
9725
|
]
|
|
8527
9726
|
}
|
|
8528
9727
|
),
|
|
8529
|
-
toggleState && /* @__PURE__ */ (0,
|
|
9728
|
+
toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8530
9729
|
StateToggle,
|
|
8531
9730
|
{
|
|
8532
9731
|
rect: toggleState.rect,
|
|
@@ -8535,15 +9734,15 @@ function OhhwellsBridge() {
|
|
|
8535
9734
|
onStateChange: handleStateChange
|
|
8536
9735
|
}
|
|
8537
9736
|
),
|
|
8538
|
-
sectionGap && /* @__PURE__ */ (0,
|
|
9737
|
+
sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
8539
9738
|
"div",
|
|
8540
9739
|
{
|
|
8541
9740
|
"data-ohw-section-insert-line": "",
|
|
8542
9741
|
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
8543
9742
|
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
8544
9743
|
children: [
|
|
8545
|
-
/* @__PURE__ */ (0,
|
|
8546
|
-
/* @__PURE__ */ (0,
|
|
9744
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
9745
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8547
9746
|
Badge,
|
|
8548
9747
|
{
|
|
8549
9748
|
className: "px-8 py-1 bg-primary hover:bg-primary text-primary-foreground text-xs font-medium shrink-0 rounded-full cursor-pointer pointer-events-auto",
|
|
@@ -8556,25 +9755,26 @@ function OhhwellsBridge() {
|
|
|
8556
9755
|
children: "Add Section"
|
|
8557
9756
|
}
|
|
8558
9757
|
),
|
|
8559
|
-
/* @__PURE__ */ (0,
|
|
9758
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
8560
9759
|
]
|
|
8561
9760
|
}
|
|
8562
9761
|
),
|
|
8563
|
-
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0,
|
|
9762
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8564
9763
|
LinkPopover,
|
|
8565
9764
|
{
|
|
8566
9765
|
panelRef: linkPopoverPanelRef,
|
|
8567
9766
|
portalContainer: dialogPortalContainer,
|
|
8568
9767
|
open: true,
|
|
8569
|
-
mode: "edit",
|
|
9768
|
+
mode: linkPopover.mode ?? "edit",
|
|
8570
9769
|
pages: sitePages,
|
|
8571
9770
|
sections: currentSections,
|
|
8572
9771
|
sectionsByPath,
|
|
8573
9772
|
initialTarget: linkPopover.target,
|
|
9773
|
+
existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [],
|
|
8574
9774
|
onClose: closeLinkPopover,
|
|
8575
9775
|
onSubmit: handleLinkPopoverSubmit
|
|
8576
9776
|
},
|
|
8577
|
-
|
|
9777
|
+
linkPopover.key
|
|
8578
9778
|
) : null
|
|
8579
9779
|
] }),
|
|
8580
9780
|
bridgeRoot
|