@ohhwells/bridge 0.1.39 → 0.1.40
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 +1705 -555
- 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 +1716 -566
- 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,115 +6105,109 @@ 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/LinkPopover.tsx
|
|
5693
|
-
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
5694
|
-
function LinkPopover({
|
|
5695
|
-
open = true,
|
|
5696
|
-
panelRef,
|
|
5697
|
-
portalContainer,
|
|
5698
|
-
onClose,
|
|
5699
|
-
...editorProps
|
|
5700
|
-
}) {
|
|
5701
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
5702
|
-
Dialog2,
|
|
5703
|
-
{
|
|
5704
|
-
open,
|
|
5705
|
-
onOpenChange: (next) => {
|
|
5706
|
-
if (!next) onClose?.();
|
|
5707
|
-
},
|
|
5708
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
5709
|
-
DialogContent,
|
|
5710
|
-
{
|
|
5711
|
-
ref: panelRef,
|
|
5712
|
-
container: portalContainer,
|
|
5713
|
-
"data-ohw-link-popover-root": "",
|
|
5714
|
-
"data-ohw-link-modal-root": "",
|
|
5715
|
-
"data-ohw-bridge": "",
|
|
5716
|
-
showCloseButton: false,
|
|
5717
|
-
className: "gap-0 p-0 w-full md:w-md pointer-events-auto",
|
|
5718
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(LinkEditorPanel, { ...editorProps, open, onClose })
|
|
5719
|
-
}
|
|
5720
|
-
)
|
|
5721
|
-
}
|
|
5722
|
-
);
|
|
5723
|
-
}
|
|
5724
|
-
|
|
5725
6211
|
// src/ui/link-modal/devFixtures.ts
|
|
5726
6212
|
var DEV_SITE_PAGES = [
|
|
5727
6213
|
{ path: "/", title: "Home" },
|
|
@@ -5741,16 +6227,21 @@ var DEV_SECTIONS_BY_PATH = {
|
|
|
5741
6227
|
{ id: "founder-teaser", label: "Founder" },
|
|
5742
6228
|
{ id: "plan-form", label: "Plan Form" },
|
|
5743
6229
|
{ id: "testimonials", label: "Testimonials" },
|
|
5744
|
-
{ id: "wordmark", label: "Wordmark" }
|
|
6230
|
+
{ id: "wordmark", label: "Wordmark" },
|
|
6231
|
+
{ id: "footer", label: "Footer" }
|
|
5745
6232
|
],
|
|
5746
6233
|
"/about": [
|
|
5747
6234
|
{ id: "manifesto", label: "Manifesto" },
|
|
5748
6235
|
{ id: "story-letter", label: "Our Story" },
|
|
5749
6236
|
{ id: "lagree-explainer", label: "Lagree Explainer" },
|
|
5750
6237
|
{ id: "waitlist-cta", label: "Waitlist" },
|
|
5751
|
-
{ id: "personal-training", label: "Personal training" }
|
|
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" }
|
|
5752
6244
|
],
|
|
5753
|
-
"/classes": [{ id: "class-library", label: "Class Library" }],
|
|
5754
6245
|
"/pricing": [
|
|
5755
6246
|
{ id: "page-header", label: "Page Header" },
|
|
5756
6247
|
{ id: "free-class-cta", label: "Free Class" },
|
|
@@ -5758,19 +6249,25 @@ var DEV_SECTIONS_BY_PATH = {
|
|
|
5758
6249
|
{ id: "monthly-memberships", label: "Memberships" },
|
|
5759
6250
|
{ id: "specialty-programs", label: "Specialty Programs" },
|
|
5760
6251
|
{ id: "package-matcher", label: "Packages" },
|
|
5761
|
-
{ id: "wordmark", label: "Wordmark" }
|
|
6252
|
+
{ id: "wordmark", label: "Wordmark" },
|
|
6253
|
+
{ id: "footer", label: "Footer" }
|
|
5762
6254
|
],
|
|
5763
6255
|
"/studio": [
|
|
5764
6256
|
{ id: "studio-intro", label: "Studio Intro" },
|
|
5765
6257
|
{ id: "studio-features", label: "Studio Features" },
|
|
5766
6258
|
{ id: "studio-gallery", label: "Studio Gallery" },
|
|
5767
|
-
{ id: "studio-visit", label: "Visit Studio" }
|
|
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" }
|
|
5768
6265
|
],
|
|
5769
|
-
"/instructors": [{ id: "instructor-grid", label: "Instructors" }],
|
|
5770
6266
|
"/contact": [
|
|
5771
6267
|
{ id: "hello-hero", label: "Hello" },
|
|
5772
6268
|
{ id: "contact-form", label: "Contact Form" },
|
|
5773
|
-
{ id: "faq", label: "FAQ" }
|
|
6269
|
+
{ id: "faq", label: "FAQ" },
|
|
6270
|
+
{ id: "footer", label: "Footer" }
|
|
5774
6271
|
]
|
|
5775
6272
|
};
|
|
5776
6273
|
function shouldUseDevFixtures() {
|
|
@@ -5780,8 +6277,277 @@ function shouldUseDevFixtures() {
|
|
|
5780
6277
|
return new URLSearchParams(q).get("ohw-fixtures") === "1";
|
|
5781
6278
|
}
|
|
5782
6279
|
|
|
5783
|
-
// src/
|
|
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");
|
|
5784
6507
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
6508
|
+
function NavbarContainerChrome({
|
|
6509
|
+
rect,
|
|
6510
|
+
onAdd
|
|
6511
|
+
}) {
|
|
6512
|
+
const chromeGap = 6;
|
|
6513
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6514
|
+
"div",
|
|
6515
|
+
{
|
|
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
|
|
6524
|
+
},
|
|
6525
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6526
|
+
"button",
|
|
6527
|
+
{
|
|
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 })
|
|
6543
|
+
}
|
|
6544
|
+
)
|
|
6545
|
+
}
|
|
6546
|
+
);
|
|
6547
|
+
}
|
|
6548
|
+
|
|
6549
|
+
// src/ui/badge.tsx
|
|
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,104 @@ 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
|
+
}
|
|
6223
7076
|
function collectSections() {
|
|
6224
7077
|
return collectSectionsFromDom();
|
|
6225
7078
|
}
|
|
@@ -6367,7 +7220,7 @@ function EditGlowChrome({
|
|
|
6367
7220
|
dragDisabled = false
|
|
6368
7221
|
}) {
|
|
6369
7222
|
const GAP = 6;
|
|
6370
|
-
return /* @__PURE__ */ (0,
|
|
7223
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
6371
7224
|
"div",
|
|
6372
7225
|
{
|
|
6373
7226
|
ref: elRef,
|
|
@@ -6382,7 +7235,7 @@ function EditGlowChrome({
|
|
|
6382
7235
|
zIndex: 2147483646
|
|
6383
7236
|
},
|
|
6384
7237
|
children: [
|
|
6385
|
-
/* @__PURE__ */ (0,
|
|
7238
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
6386
7239
|
"div",
|
|
6387
7240
|
{
|
|
6388
7241
|
style: {
|
|
@@ -6395,7 +7248,7 @@ function EditGlowChrome({
|
|
|
6395
7248
|
}
|
|
6396
7249
|
}
|
|
6397
7250
|
),
|
|
6398
|
-
reorderHrefKey && /* @__PURE__ */ (0,
|
|
7251
|
+
reorderHrefKey && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
6399
7252
|
"div",
|
|
6400
7253
|
{
|
|
6401
7254
|
"data-ohw-drag-handle-container": "",
|
|
@@ -6407,7 +7260,7 @@ function EditGlowChrome({
|
|
|
6407
7260
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
6408
7261
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
6409
7262
|
},
|
|
6410
|
-
children: /* @__PURE__ */ (0,
|
|
7263
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
6411
7264
|
DragHandle,
|
|
6412
7265
|
{
|
|
6413
7266
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -6511,7 +7364,7 @@ function FloatingToolbar({
|
|
|
6511
7364
|
onEditLink
|
|
6512
7365
|
}) {
|
|
6513
7366
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll, 330);
|
|
6514
|
-
return /* @__PURE__ */ (0,
|
|
7367
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
6515
7368
|
"div",
|
|
6516
7369
|
{
|
|
6517
7370
|
ref: elRef,
|
|
@@ -6523,12 +7376,12 @@ function FloatingToolbar({
|
|
|
6523
7376
|
zIndex: 2147483647,
|
|
6524
7377
|
pointerEvents: "auto"
|
|
6525
7378
|
},
|
|
6526
|
-
children: /* @__PURE__ */ (0,
|
|
6527
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0,
|
|
6528
|
-
gi > 0 && /* @__PURE__ */ (0,
|
|
7379
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(CustomToolbar, { children: [
|
|
7380
|
+
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_react8.default.Fragment, { children: [
|
|
7381
|
+
gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CustomToolbarDivider, {}),
|
|
6529
7382
|
btns.map((btn) => {
|
|
6530
7383
|
const isActive = activeCommands.has(btn.cmd);
|
|
6531
|
-
return /* @__PURE__ */ (0,
|
|
7384
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
6532
7385
|
CustomToolbarButton,
|
|
6533
7386
|
{
|
|
6534
7387
|
title: btn.title,
|
|
@@ -6537,7 +7390,7 @@ function FloatingToolbar({
|
|
|
6537
7390
|
e.preventDefault();
|
|
6538
7391
|
onCommand(btn.cmd);
|
|
6539
7392
|
},
|
|
6540
|
-
children: /* @__PURE__ */ (0,
|
|
7393
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
6541
7394
|
"svg",
|
|
6542
7395
|
{
|
|
6543
7396
|
width: "16",
|
|
@@ -6558,7 +7411,7 @@ function FloatingToolbar({
|
|
|
6558
7411
|
);
|
|
6559
7412
|
})
|
|
6560
7413
|
] }, gi)),
|
|
6561
|
-
showEditLink ? /* @__PURE__ */ (0,
|
|
7414
|
+
showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
6562
7415
|
CustomToolbarButton,
|
|
6563
7416
|
{
|
|
6564
7417
|
type: "button",
|
|
@@ -6572,7 +7425,7 @@ function FloatingToolbar({
|
|
|
6572
7425
|
e.preventDefault();
|
|
6573
7426
|
e.stopPropagation();
|
|
6574
7427
|
},
|
|
6575
|
-
children: /* @__PURE__ */ (0,
|
|
7428
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Link, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
6576
7429
|
}
|
|
6577
7430
|
) : null
|
|
6578
7431
|
] })
|
|
@@ -6589,7 +7442,7 @@ function StateToggle({
|
|
|
6589
7442
|
states,
|
|
6590
7443
|
onStateChange
|
|
6591
7444
|
}) {
|
|
6592
|
-
return /* @__PURE__ */ (0,
|
|
7445
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
6593
7446
|
ToggleGroup,
|
|
6594
7447
|
{
|
|
6595
7448
|
"data-ohw-state-toggle": "",
|
|
@@ -6603,7 +7456,7 @@ function StateToggle({
|
|
|
6603
7456
|
left: rect.right - 8,
|
|
6604
7457
|
transform: "translateX(-100%)"
|
|
6605
7458
|
},
|
|
6606
|
-
children: states.map((state) => /* @__PURE__ */ (0,
|
|
7459
|
+
children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
6607
7460
|
}
|
|
6608
7461
|
);
|
|
6609
7462
|
}
|
|
@@ -6626,12 +7479,12 @@ function resolveSubdomain(subdomainFromQuery) {
|
|
|
6626
7479
|
return "";
|
|
6627
7480
|
}
|
|
6628
7481
|
function OhhwellsBridge() {
|
|
6629
|
-
const pathname = (0,
|
|
6630
|
-
const router = (0,
|
|
6631
|
-
const searchParams = (0,
|
|
7482
|
+
const pathname = (0, import_navigation2.usePathname)();
|
|
7483
|
+
const router = (0, import_navigation2.useRouter)();
|
|
7484
|
+
const searchParams = (0, import_navigation2.useSearchParams)();
|
|
6632
7485
|
const isEditMode = isEditSessionActive();
|
|
6633
|
-
const [bridgeRoot, setBridgeRoot] = (0,
|
|
6634
|
-
(0,
|
|
7486
|
+
const [bridgeRoot, setBridgeRoot] = (0, import_react8.useState)(null);
|
|
7487
|
+
(0, import_react8.useEffect)(() => {
|
|
6635
7488
|
const figtreeFontId = "ohw-figtree-font";
|
|
6636
7489
|
if (!document.getElementById(figtreeFontId)) {
|
|
6637
7490
|
const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
|
|
@@ -6659,83 +7512,91 @@ function OhhwellsBridge() {
|
|
|
6659
7512
|
const subdomainFromQuery = searchParams.get("subdomain");
|
|
6660
7513
|
const subdomain = resolveSubdomain(subdomainFromQuery);
|
|
6661
7514
|
useLinkHrefGuardian(pathname, subdomain, isEditMode);
|
|
6662
|
-
const
|
|
7515
|
+
const postToParent2 = (0, import_react8.useCallback)((data) => {
|
|
6663
7516
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
6664
7517
|
window.parent.postMessage(data, "*");
|
|
6665
7518
|
}
|
|
6666
7519
|
}, []);
|
|
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,
|
|
7520
|
+
const [fetchState, setFetchState] = (0, import_react8.useState)("idle");
|
|
7521
|
+
const autoSaveTimers = (0, import_react8.useRef)(/* @__PURE__ */ new Map());
|
|
7522
|
+
const activeElRef = (0, import_react8.useRef)(null);
|
|
7523
|
+
const selectedElRef = (0, import_react8.useRef)(null);
|
|
7524
|
+
const originalContentRef = (0, import_react8.useRef)(null);
|
|
7525
|
+
const activeStateElRef = (0, import_react8.useRef)(null);
|
|
7526
|
+
const parentScrollRef = (0, import_react8.useRef)(null);
|
|
7527
|
+
const visibleViewportRef = (0, import_react8.useRef)(null);
|
|
7528
|
+
const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react8.useState)(null);
|
|
7529
|
+
const attachVisibleViewport = (0, import_react8.useCallback)((node) => {
|
|
6677
7530
|
visibleViewportRef.current = node;
|
|
6678
7531
|
setDialogPortalContainer(node);
|
|
6679
7532
|
if (node) applyVisibleViewport(node, parentScrollRef.current);
|
|
6680
7533
|
}, []);
|
|
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,
|
|
7534
|
+
const toolbarElRef = (0, import_react8.useRef)(null);
|
|
7535
|
+
const glowElRef = (0, import_react8.useRef)(null);
|
|
7536
|
+
const hoveredImageRef = (0, import_react8.useRef)(null);
|
|
7537
|
+
const hoveredImageHasTextOverlapRef = (0, import_react8.useRef)(false);
|
|
7538
|
+
const dragOverElRef = (0, import_react8.useRef)(null);
|
|
7539
|
+
const [mediaHover, setMediaHover] = (0, import_react8.useState)(null);
|
|
7540
|
+
const [uploadingRects, setUploadingRects] = (0, import_react8.useState)({});
|
|
7541
|
+
const hoveredGapRef = (0, import_react8.useRef)(null);
|
|
7542
|
+
const imageUnhoverTimerRef = (0, import_react8.useRef)(null);
|
|
7543
|
+
const imageShowTimerRef = (0, import_react8.useRef)(null);
|
|
7544
|
+
const editStylesRef = (0, import_react8.useRef)(null);
|
|
7545
|
+
const activateRef = (0, import_react8.useRef)(() => {
|
|
6693
7546
|
});
|
|
6694
|
-
const deactivateRef = (0,
|
|
7547
|
+
const deactivateRef = (0, import_react8.useRef)(() => {
|
|
6695
7548
|
});
|
|
6696
|
-
const selectRef = (0,
|
|
7549
|
+
const selectRef = (0, import_react8.useRef)(() => {
|
|
6697
7550
|
});
|
|
6698
|
-
const
|
|
7551
|
+
const selectFrameRef = (0, import_react8.useRef)(() => {
|
|
6699
7552
|
});
|
|
6700
|
-
const
|
|
7553
|
+
const deselectRef = (0, import_react8.useRef)(() => {
|
|
6701
7554
|
});
|
|
6702
|
-
const
|
|
7555
|
+
const reselectNavigationItemRef = (0, import_react8.useRef)(() => {
|
|
6703
7556
|
});
|
|
6704
|
-
const
|
|
7557
|
+
const commitNavigationTextEditRef = (0, import_react8.useRef)(() => {
|
|
6705
7558
|
});
|
|
6706
|
-
const
|
|
6707
|
-
|
|
6708
|
-
const
|
|
6709
|
-
|
|
6710
|
-
const
|
|
6711
|
-
const
|
|
6712
|
-
const
|
|
7559
|
+
const refreshActiveCommandsRef = (0, import_react8.useRef)(() => {
|
|
7560
|
+
});
|
|
7561
|
+
const postToParentRef = (0, import_react8.useRef)(postToParent2);
|
|
7562
|
+
postToParentRef.current = postToParent2;
|
|
7563
|
+
const sectionsLoadedRef = (0, import_react8.useRef)(false);
|
|
7564
|
+
const pendingScheduleConfigRequests = (0, import_react8.useRef)([]);
|
|
7565
|
+
const [toolbarRect, setToolbarRect] = (0, import_react8.useState)(null);
|
|
7566
|
+
const [toolbarVariant, setToolbarVariant] = (0, import_react8.useState)("none");
|
|
7567
|
+
const toolbarVariantRef = (0, import_react8.useRef)("none");
|
|
6713
7568
|
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
|
|
7569
|
+
const [reorderHrefKey, setReorderHrefKey] = (0, import_react8.useState)(null);
|
|
7570
|
+
const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react8.useState)(false);
|
|
7571
|
+
const [toggleState, setToggleState] = (0, import_react8.useState)(null);
|
|
7572
|
+
const [maxBadge, setMaxBadge] = (0, import_react8.useState)(null);
|
|
7573
|
+
const [activeCommands, setActiveCommands] = (0, import_react8.useState)(/* @__PURE__ */ new Set());
|
|
7574
|
+
const [sectionGap, setSectionGap] = (0, import_react8.useState)(null);
|
|
7575
|
+
const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react8.useState)(false);
|
|
7576
|
+
const hoveredNavContainerRef = (0, import_react8.useRef)(null);
|
|
7577
|
+
const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react8.useState)(null);
|
|
7578
|
+
const hoveredItemElRef = (0, import_react8.useRef)(null);
|
|
7579
|
+
const [hoveredItemRect, setHoveredItemRect] = (0, import_react8.useState)(null);
|
|
7580
|
+
const siblingHintElRef = (0, import_react8.useRef)(null);
|
|
7581
|
+
const [siblingHintRect, setSiblingHintRect] = (0, import_react8.useState)(null);
|
|
7582
|
+
const [isItemDragging, setIsItemDragging] = (0, import_react8.useState)(false);
|
|
7583
|
+
const [linkPopover, setLinkPopover] = (0, import_react8.useState)(null);
|
|
7584
|
+
const linkPopoverSessionRef = (0, import_react8.useRef)(null);
|
|
7585
|
+
const addNavAfterAnchorRef = (0, import_react8.useRef)(null);
|
|
7586
|
+
const editContentRef = (0, import_react8.useRef)({});
|
|
7587
|
+
const [sitePages, setSitePages] = (0, import_react8.useState)([]);
|
|
7588
|
+
const [sectionsByPath, setSectionsByPath] = (0, import_react8.useState)({});
|
|
7589
|
+
const sectionsPrefetchGenRef = (0, import_react8.useRef)(0);
|
|
7590
|
+
const setLinkPopoverRef = (0, import_react8.useRef)(setLinkPopover);
|
|
7591
|
+
const linkPopoverPanelRef = (0, import_react8.useRef)(null);
|
|
7592
|
+
const linkPopoverOpenRef = (0, import_react8.useRef)(false);
|
|
7593
|
+
const linkPopoverGraceUntilRef = (0, import_react8.useRef)(0);
|
|
6734
7594
|
setLinkPopoverRef.current = setLinkPopover;
|
|
7595
|
+
linkPopoverSessionRef.current = linkPopover;
|
|
6735
7596
|
const bumpLinkPopoverGrace = () => {
|
|
6736
7597
|
linkPopoverGraceUntilRef.current = Date.now() + 350;
|
|
6737
7598
|
};
|
|
6738
|
-
const runSectionsPrefetch = (0,
|
|
7599
|
+
const runSectionsPrefetch = (0, import_react8.useCallback)((pages) => {
|
|
6739
7600
|
if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
|
|
6740
7601
|
const gen = ++sectionsPrefetchGenRef.current;
|
|
6741
7602
|
const paths = pages.map((p) => p.path);
|
|
@@ -6754,9 +7615,9 @@ function OhhwellsBridge() {
|
|
|
6754
7615
|
);
|
|
6755
7616
|
});
|
|
6756
7617
|
}, [isEditMode, pathname]);
|
|
6757
|
-
const runSectionsPrefetchRef = (0,
|
|
7618
|
+
const runSectionsPrefetchRef = (0, import_react8.useRef)(runSectionsPrefetch);
|
|
6758
7619
|
runSectionsPrefetchRef.current = runSectionsPrefetch;
|
|
6759
|
-
(0,
|
|
7620
|
+
(0, import_react8.useEffect)(() => {
|
|
6760
7621
|
if (!linkPopover) return;
|
|
6761
7622
|
if (hoveredImageRef.current) {
|
|
6762
7623
|
hoveredImageRef.current = null;
|
|
@@ -6765,7 +7626,7 @@ function OhhwellsBridge() {
|
|
|
6765
7626
|
hoveredGapRef.current = null;
|
|
6766
7627
|
setSectionGap(null);
|
|
6767
7628
|
setMediaHover(null);
|
|
6768
|
-
|
|
7629
|
+
postToParent2({ type: "ow:link-modal-lock", locked: true });
|
|
6769
7630
|
const html = document.documentElement;
|
|
6770
7631
|
const body = document.body;
|
|
6771
7632
|
const prevHtmlOverflow = html.style.overflow;
|
|
@@ -6782,15 +7643,16 @@ function OhhwellsBridge() {
|
|
|
6782
7643
|
const scrollOpts = { passive: false, capture: true };
|
|
6783
7644
|
document.addEventListener("wheel", preventBackgroundScroll, scrollOpts);
|
|
6784
7645
|
document.addEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
7646
|
+
postToParent2({ type: "ow:image-unhover" });
|
|
6785
7647
|
return () => {
|
|
6786
|
-
|
|
7648
|
+
postToParent2({ type: "ow:link-modal-lock", locked: false });
|
|
6787
7649
|
html.style.overflow = prevHtmlOverflow;
|
|
6788
7650
|
body.style.overflow = prevBodyOverflow;
|
|
6789
7651
|
document.removeEventListener("wheel", preventBackgroundScroll, scrollOpts);
|
|
6790
7652
|
document.removeEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
6791
7653
|
};
|
|
6792
|
-
}, [linkPopover,
|
|
6793
|
-
(0,
|
|
7654
|
+
}, [linkPopover, postToParent2]);
|
|
7655
|
+
(0, import_react8.useEffect)(() => {
|
|
6794
7656
|
if (!isEditMode) return;
|
|
6795
7657
|
const useFixtures = shouldUseDevFixtures();
|
|
6796
7658
|
if (useFixtures) {
|
|
@@ -6811,17 +7673,17 @@ function OhhwellsBridge() {
|
|
|
6811
7673
|
runSectionsPrefetchRef.current(mapped);
|
|
6812
7674
|
};
|
|
6813
7675
|
window.addEventListener("message", onSitePages);
|
|
6814
|
-
if (!useFixtures)
|
|
7676
|
+
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
6815
7677
|
return () => window.removeEventListener("message", onSitePages);
|
|
6816
|
-
}, [isEditMode,
|
|
6817
|
-
(0,
|
|
7678
|
+
}, [isEditMode, postToParent2]);
|
|
7679
|
+
(0, import_react8.useEffect)(() => {
|
|
6818
7680
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
6819
7681
|
void loadAllSectionsManifest().then((manifest) => {
|
|
6820
7682
|
if (Object.keys(manifest).length === 0) return;
|
|
6821
7683
|
setSectionsByPath((prev) => ({ ...manifest, ...prev }));
|
|
6822
7684
|
});
|
|
6823
7685
|
}, [isEditMode]);
|
|
6824
|
-
(0,
|
|
7686
|
+
(0, import_react8.useEffect)(() => {
|
|
6825
7687
|
const update = () => {
|
|
6826
7688
|
const el = activeElRef.current ?? selectedElRef.current;
|
|
6827
7689
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
@@ -6845,10 +7707,10 @@ function OhhwellsBridge() {
|
|
|
6845
7707
|
vvp.removeEventListener("resize", update);
|
|
6846
7708
|
};
|
|
6847
7709
|
}, []);
|
|
6848
|
-
const refreshStateRules = (0,
|
|
7710
|
+
const refreshStateRules = (0, import_react8.useCallback)(() => {
|
|
6849
7711
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
6850
7712
|
}, []);
|
|
6851
|
-
const processConfigRequest = (0,
|
|
7713
|
+
const processConfigRequest = (0, import_react8.useCallback)((insertAfterVal) => {
|
|
6852
7714
|
const tracker = getSectionsTracker();
|
|
6853
7715
|
let entries = [];
|
|
6854
7716
|
try {
|
|
@@ -6871,7 +7733,7 @@ function OhhwellsBridge() {
|
|
|
6871
7733
|
}
|
|
6872
7734
|
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
|
|
6873
7735
|
}, [isEditMode]);
|
|
6874
|
-
const deactivate = (0,
|
|
7736
|
+
const deactivate = (0, import_react8.useCallback)(() => {
|
|
6875
7737
|
const el = activeElRef.current;
|
|
6876
7738
|
if (!el) return;
|
|
6877
7739
|
const key = el.dataset.ohwKey;
|
|
@@ -6900,21 +7762,23 @@ function OhhwellsBridge() {
|
|
|
6900
7762
|
setMaxBadge(null);
|
|
6901
7763
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6902
7764
|
setToolbarShowEditLink(false);
|
|
6903
|
-
|
|
6904
|
-
}, [
|
|
6905
|
-
const deselect = (0,
|
|
7765
|
+
postToParent2({ type: "ow:exit-edit" });
|
|
7766
|
+
}, [postToParent2]);
|
|
7767
|
+
const deselect = (0, import_react8.useCallback)(() => {
|
|
6906
7768
|
selectedElRef.current = null;
|
|
6907
7769
|
setReorderHrefKey(null);
|
|
6908
7770
|
setReorderDragDisabled(false);
|
|
6909
7771
|
siblingHintElRef.current = null;
|
|
6910
7772
|
setSiblingHintRect(null);
|
|
6911
7773
|
setIsItemDragging(false);
|
|
7774
|
+
hoveredNavContainerRef.current = null;
|
|
7775
|
+
setHoveredNavContainerRect(null);
|
|
6912
7776
|
if (!activeElRef.current) {
|
|
6913
7777
|
setToolbarRect(null);
|
|
6914
7778
|
setToolbarVariant("none");
|
|
6915
7779
|
}
|
|
6916
7780
|
}, []);
|
|
6917
|
-
const reselectNavigationItem = (0,
|
|
7781
|
+
const reselectNavigationItem = (0, import_react8.useCallback)((navAnchor) => {
|
|
6918
7782
|
selectedElRef.current = navAnchor;
|
|
6919
7783
|
const { key, disabled } = getNavigationItemReorderState(navAnchor);
|
|
6920
7784
|
setReorderHrefKey(key);
|
|
@@ -6924,7 +7788,7 @@ function OhhwellsBridge() {
|
|
|
6924
7788
|
setToolbarShowEditLink(false);
|
|
6925
7789
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6926
7790
|
}, []);
|
|
6927
|
-
const commitNavigationTextEdit = (0,
|
|
7791
|
+
const commitNavigationTextEdit = (0, import_react8.useCallback)((navAnchor) => {
|
|
6928
7792
|
const el = activeElRef.current;
|
|
6929
7793
|
if (!el) return;
|
|
6930
7794
|
const key = el.dataset.ohwKey;
|
|
@@ -6937,9 +7801,9 @@ function OhhwellsBridge() {
|
|
|
6937
7801
|
const html = sanitizeHtml(el.innerHTML);
|
|
6938
7802
|
const original = originalContentRef.current ?? "";
|
|
6939
7803
|
if (html !== sanitizeHtml(original)) {
|
|
6940
|
-
|
|
7804
|
+
postToParent2({ type: "ow:change", nodes: [{ key, text: html }] });
|
|
6941
7805
|
const h = document.documentElement.scrollHeight;
|
|
6942
|
-
if (h > 50)
|
|
7806
|
+
if (h > 50) postToParent2({ type: "ow:height", height: h });
|
|
6943
7807
|
}
|
|
6944
7808
|
}
|
|
6945
7809
|
el.removeAttribute("contenteditable");
|
|
@@ -6947,31 +7811,38 @@ function OhhwellsBridge() {
|
|
|
6947
7811
|
setMaxBadge(null);
|
|
6948
7812
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6949
7813
|
setToolbarShowEditLink(false);
|
|
6950
|
-
|
|
7814
|
+
postToParent2({ type: "ow:exit-edit" });
|
|
6951
7815
|
reselectNavigationItem(navAnchor);
|
|
6952
|
-
}, [
|
|
6953
|
-
const
|
|
6954
|
-
const
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
7816
|
+
}, [postToParent2, reselectNavigationItem]);
|
|
7817
|
+
const handleAddTopLevelNavItem = (0, import_react8.useCallback)(() => {
|
|
7818
|
+
const items = listNavbarItems();
|
|
7819
|
+
addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
|
|
7820
|
+
deselectRef.current();
|
|
7821
|
+
deactivateRef.current();
|
|
7822
|
+
bumpLinkPopoverGrace();
|
|
7823
|
+
setLinkPopover({
|
|
7824
|
+
key: "__add-nav__",
|
|
7825
|
+
mode: "create",
|
|
7826
|
+
intent: "add-nav"
|
|
7827
|
+
});
|
|
6959
7828
|
}, []);
|
|
6960
|
-
const handleItemDragStart = (0,
|
|
7829
|
+
const handleItemDragStart = (0, import_react8.useCallback)(() => {
|
|
6961
7830
|
siblingHintElRef.current = null;
|
|
6962
7831
|
setSiblingHintRect(null);
|
|
6963
7832
|
setIsItemDragging(true);
|
|
6964
7833
|
}, []);
|
|
6965
|
-
const handleItemDragEnd = (0,
|
|
7834
|
+
const handleItemDragEnd = (0, import_react8.useCallback)(() => {
|
|
6966
7835
|
setIsItemDragging(false);
|
|
6967
7836
|
}, []);
|
|
6968
7837
|
reselectNavigationItemRef.current = reselectNavigationItem;
|
|
6969
7838
|
commitNavigationTextEditRef.current = commitNavigationTextEdit;
|
|
6970
|
-
const select = (0,
|
|
7839
|
+
const select = (0, import_react8.useCallback)((anchor) => {
|
|
6971
7840
|
if (!isNavigationItem(anchor)) return;
|
|
6972
7841
|
if (activeElRef.current) deactivate();
|
|
6973
7842
|
selectedElRef.current = anchor;
|
|
6974
7843
|
clearHrefKeyHover(anchor);
|
|
7844
|
+
hoveredNavContainerRef.current = null;
|
|
7845
|
+
setHoveredNavContainerRect(null);
|
|
6975
7846
|
setHoveredItemRect(null);
|
|
6976
7847
|
hoveredItemElRef.current = null;
|
|
6977
7848
|
siblingHintElRef.current = null;
|
|
@@ -6985,7 +7856,26 @@ function OhhwellsBridge() {
|
|
|
6985
7856
|
setToolbarShowEditLink(false);
|
|
6986
7857
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6987
7858
|
}, [deactivate]);
|
|
6988
|
-
const
|
|
7859
|
+
const selectFrame = (0, import_react8.useCallback)((el) => {
|
|
7860
|
+
if (!isNavigationContainer(el)) return;
|
|
7861
|
+
if (activeElRef.current) deactivate();
|
|
7862
|
+
selectedElRef.current = el;
|
|
7863
|
+
clearHrefKeyHover(el);
|
|
7864
|
+
hoveredNavContainerRef.current = null;
|
|
7865
|
+
setHoveredNavContainerRect(null);
|
|
7866
|
+
setHoveredItemRect(null);
|
|
7867
|
+
hoveredItemElRef.current = null;
|
|
7868
|
+
siblingHintElRef.current = null;
|
|
7869
|
+
setSiblingHintRect(null);
|
|
7870
|
+
setIsItemDragging(false);
|
|
7871
|
+
setReorderHrefKey(null);
|
|
7872
|
+
setReorderDragDisabled(false);
|
|
7873
|
+
setToolbarVariant("select-frame");
|
|
7874
|
+
setToolbarRect(el.getBoundingClientRect());
|
|
7875
|
+
setToolbarShowEditLink(false);
|
|
7876
|
+
setActiveCommands(/* @__PURE__ */ new Set());
|
|
7877
|
+
}, [deactivate]);
|
|
7878
|
+
const activate = (0, import_react8.useCallback)((el, options) => {
|
|
6989
7879
|
if (activeElRef.current === el) return;
|
|
6990
7880
|
selectedElRef.current = null;
|
|
6991
7881
|
deactivate();
|
|
@@ -7003,6 +7893,9 @@ function OhhwellsBridge() {
|
|
|
7003
7893
|
activeElRef.current = el;
|
|
7004
7894
|
originalContentRef.current = el.innerHTML;
|
|
7005
7895
|
el.focus();
|
|
7896
|
+
if (options?.caretX !== void 0 && options?.caretY !== void 0) {
|
|
7897
|
+
placeCaretAtPoint(el, options.caretX, options.caretY);
|
|
7898
|
+
}
|
|
7006
7899
|
setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
|
|
7007
7900
|
const navAnchor = getNavigationItemAnchor(el);
|
|
7008
7901
|
if (navAnchor) {
|
|
@@ -7014,14 +7907,15 @@ function OhhwellsBridge() {
|
|
|
7014
7907
|
setReorderDragDisabled(reorderDisabled);
|
|
7015
7908
|
}
|
|
7016
7909
|
setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
7017
|
-
|
|
7910
|
+
postToParent2({ type: "ow:enter-edit", key: el.dataset.ohwKey });
|
|
7018
7911
|
requestAnimationFrame(() => refreshActiveCommandsRef.current());
|
|
7019
|
-
}, [deactivate,
|
|
7912
|
+
}, [deactivate, postToParent2]);
|
|
7020
7913
|
activateRef.current = activate;
|
|
7021
7914
|
deactivateRef.current = deactivate;
|
|
7022
7915
|
selectRef.current = select;
|
|
7916
|
+
selectFrameRef.current = selectFrame;
|
|
7023
7917
|
deselectRef.current = deselect;
|
|
7024
|
-
(0,
|
|
7918
|
+
(0, import_react8.useLayoutEffect)(() => {
|
|
7025
7919
|
if (!subdomain || isEditMode) {
|
|
7026
7920
|
setFetchState("done");
|
|
7027
7921
|
return;
|
|
@@ -7061,6 +7955,7 @@ function OhhwellsBridge() {
|
|
|
7061
7955
|
});
|
|
7062
7956
|
applyLinkByKey(key, val);
|
|
7063
7957
|
}
|
|
7958
|
+
reconcileNavbarItemsFromContent(content);
|
|
7064
7959
|
enforceLinkHrefs();
|
|
7065
7960
|
initSectionsFromContent(content, true);
|
|
7066
7961
|
sectionsLoadedRef.current = true;
|
|
@@ -7089,7 +7984,7 @@ function OhhwellsBridge() {
|
|
|
7089
7984
|
cancelled = true;
|
|
7090
7985
|
};
|
|
7091
7986
|
}, [subdomain, isEditMode]);
|
|
7092
|
-
(0,
|
|
7987
|
+
(0, import_react8.useEffect)(() => {
|
|
7093
7988
|
if (!subdomain || isEditMode) return;
|
|
7094
7989
|
let debounceTimer = null;
|
|
7095
7990
|
let observer = null;
|
|
@@ -7120,6 +8015,7 @@ function OhhwellsBridge() {
|
|
|
7120
8015
|
});
|
|
7121
8016
|
applyLinkByKey(key, val);
|
|
7122
8017
|
}
|
|
8018
|
+
reconcileNavbarItemsFromContent(content);
|
|
7123
8019
|
} finally {
|
|
7124
8020
|
observer?.observe(document.body, { childList: true, subtree: true });
|
|
7125
8021
|
}
|
|
@@ -7137,26 +8033,44 @@ function OhhwellsBridge() {
|
|
|
7137
8033
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
7138
8034
|
};
|
|
7139
8035
|
}, [subdomain, isEditMode, pathname]);
|
|
7140
|
-
(0,
|
|
8036
|
+
(0, import_react8.useLayoutEffect)(() => {
|
|
7141
8037
|
const el = document.getElementById("ohw-loader");
|
|
7142
8038
|
if (!el) return;
|
|
7143
8039
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
7144
8040
|
el.style.display = visible ? "flex" : "none";
|
|
7145
8041
|
}, [subdomain, fetchState]);
|
|
7146
|
-
(0,
|
|
7147
|
-
|
|
7148
|
-
}, [pathname,
|
|
7149
|
-
(0,
|
|
8042
|
+
(0, import_react8.useEffect)(() => {
|
|
8043
|
+
postToParent2({ type: "ow:navigation", path: pathname });
|
|
8044
|
+
}, [pathname, postToParent2]);
|
|
8045
|
+
(0, import_react8.useEffect)(() => {
|
|
7150
8046
|
if (!isEditMode) return;
|
|
8047
|
+
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
8048
|
+
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
7151
8049
|
setLinkPopover(null);
|
|
7152
8050
|
deselectRef.current();
|
|
7153
8051
|
deactivateRef.current();
|
|
7154
8052
|
}, [pathname, isEditMode]);
|
|
7155
|
-
(0,
|
|
8053
|
+
(0, import_react8.useEffect)(() => {
|
|
8054
|
+
const contentForNav = () => {
|
|
8055
|
+
if (isEditMode) return editContentRef.current;
|
|
8056
|
+
if (!subdomain) return {};
|
|
8057
|
+
return contentCache.get(subdomain) ?? {};
|
|
8058
|
+
};
|
|
8059
|
+
const run = () => reconcileNavbarItemsFromContent(contentForNav());
|
|
8060
|
+
run();
|
|
8061
|
+
const nav = document.querySelector("nav");
|
|
8062
|
+
if (!nav) return;
|
|
8063
|
+
const observer = new MutationObserver(() => {
|
|
8064
|
+
requestAnimationFrame(run);
|
|
8065
|
+
});
|
|
8066
|
+
observer.observe(nav, { childList: true, subtree: true });
|
|
8067
|
+
return () => observer.disconnect();
|
|
8068
|
+
}, [isEditMode, pathname, subdomain, fetchState]);
|
|
8069
|
+
(0, import_react8.useEffect)(() => {
|
|
7156
8070
|
if (!isEditMode) return;
|
|
7157
8071
|
const measure = () => {
|
|
7158
8072
|
const h = document.body.scrollHeight;
|
|
7159
|
-
if (h > 50)
|
|
8073
|
+
if (h > 50) postToParent2({ type: "ow:height", height: h });
|
|
7160
8074
|
};
|
|
7161
8075
|
const t1 = setTimeout(measure, 50);
|
|
7162
8076
|
const t2 = setTimeout(measure, 500);
|
|
@@ -7175,8 +8089,8 @@ function OhhwellsBridge() {
|
|
|
7175
8089
|
if (resizeTimer) clearTimeout(resizeTimer);
|
|
7176
8090
|
window.removeEventListener("resize", handleResize);
|
|
7177
8091
|
};
|
|
7178
|
-
}, [pathname, isEditMode,
|
|
7179
|
-
(0,
|
|
8092
|
+
}, [pathname, isEditMode, postToParent2]);
|
|
8093
|
+
(0, import_react8.useEffect)(() => {
|
|
7180
8094
|
if (!subdomainFromQuery || isEditMode) return;
|
|
7181
8095
|
const handleClick = (e) => {
|
|
7182
8096
|
const anchor = e.target.closest("a");
|
|
@@ -7192,7 +8106,7 @@ function OhhwellsBridge() {
|
|
|
7192
8106
|
document.addEventListener("click", handleClick, true);
|
|
7193
8107
|
return () => document.removeEventListener("click", handleClick, true);
|
|
7194
8108
|
}, [subdomainFromQuery, isEditMode, router]);
|
|
7195
|
-
(0,
|
|
8109
|
+
(0, import_react8.useEffect)(() => {
|
|
7196
8110
|
if (!isEditMode) {
|
|
7197
8111
|
editStylesRef.current?.base.remove();
|
|
7198
8112
|
editStylesRef.current?.forceHover.remove();
|
|
@@ -7265,6 +8179,13 @@ function OhhwellsBridge() {
|
|
|
7265
8179
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
7266
8180
|
if (isInsideLinkEditor(target)) return;
|
|
7267
8181
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
8182
|
+
const navFromChrome = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
8183
|
+
if (navFromChrome) {
|
|
8184
|
+
e.preventDefault();
|
|
8185
|
+
e.stopPropagation();
|
|
8186
|
+
selectFrameRef.current(navFromChrome);
|
|
8187
|
+
return;
|
|
8188
|
+
}
|
|
7268
8189
|
e.preventDefault();
|
|
7269
8190
|
e.stopPropagation();
|
|
7270
8191
|
return;
|
|
@@ -7279,7 +8200,8 @@ function OhhwellsBridge() {
|
|
|
7279
8200
|
bumpLinkPopoverGrace();
|
|
7280
8201
|
setLinkPopoverRef.current({
|
|
7281
8202
|
key: editable.dataset.ohwKey ?? "",
|
|
7282
|
-
|
|
8203
|
+
mode: "edit",
|
|
8204
|
+
target: getLinkHref2(editable)
|
|
7283
8205
|
});
|
|
7284
8206
|
return;
|
|
7285
8207
|
}
|
|
@@ -7295,7 +8217,7 @@ function OhhwellsBridge() {
|
|
|
7295
8217
|
e.preventDefault();
|
|
7296
8218
|
e.stopPropagation();
|
|
7297
8219
|
if (selectedElRef.current === navAnchor) {
|
|
7298
|
-
activateRef.current(editable);
|
|
8220
|
+
activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
|
|
7299
8221
|
return;
|
|
7300
8222
|
}
|
|
7301
8223
|
selectRef.current(navAnchor);
|
|
@@ -7314,6 +8236,22 @@ function OhhwellsBridge() {
|
|
|
7314
8236
|
selectRef.current(hrefAnchor);
|
|
7315
8237
|
return;
|
|
7316
8238
|
}
|
|
8239
|
+
const navContainerToSelect = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
8240
|
+
if (navContainerToSelect) {
|
|
8241
|
+
e.preventDefault();
|
|
8242
|
+
e.stopPropagation();
|
|
8243
|
+
selectFrameRef.current(navContainerToSelect);
|
|
8244
|
+
return;
|
|
8245
|
+
}
|
|
8246
|
+
const selectedContainer = selectedElRef.current;
|
|
8247
|
+
if (selectedContainer && isNavigationContainer(selectedContainer)) {
|
|
8248
|
+
const navItem = getNavigationItemAnchor(target);
|
|
8249
|
+
if (!navItem && (selectedContainer === target || selectedContainer.contains(target))) {
|
|
8250
|
+
e.preventDefault();
|
|
8251
|
+
e.stopPropagation();
|
|
8252
|
+
return;
|
|
8253
|
+
}
|
|
8254
|
+
}
|
|
7317
8255
|
if (activeElRef.current) {
|
|
7318
8256
|
const sel = window.getSelection();
|
|
7319
8257
|
if (sel && !sel.isCollapsed) {
|
|
@@ -7340,9 +8278,26 @@ function OhhwellsBridge() {
|
|
|
7340
8278
|
deactivateRef.current();
|
|
7341
8279
|
};
|
|
7342
8280
|
const handleMouseOver = (e) => {
|
|
8281
|
+
if (document.documentElement.hasAttribute("data-ohw-section-picking")) return;
|
|
7343
8282
|
const target = e.target;
|
|
8283
|
+
if (toolbarVariantRef.current !== "select-frame") {
|
|
8284
|
+
const navContainer = target.closest("[data-ohw-nav-container]");
|
|
8285
|
+
if (navContainer && !getNavigationItemAnchor(target)) {
|
|
8286
|
+
hoveredNavContainerRef.current = navContainer;
|
|
8287
|
+
setHoveredNavContainerRect(navContainer.getBoundingClientRect());
|
|
8288
|
+
hoveredItemElRef.current = null;
|
|
8289
|
+
setHoveredItemRect(null);
|
|
8290
|
+
return;
|
|
8291
|
+
}
|
|
8292
|
+
if (!target.closest("[data-ohw-nav-container]")) {
|
|
8293
|
+
hoveredNavContainerRef.current = null;
|
|
8294
|
+
setHoveredNavContainerRect(null);
|
|
8295
|
+
}
|
|
8296
|
+
}
|
|
7344
8297
|
const navAnchor = getNavigationItemAnchor(target);
|
|
7345
8298
|
if (navAnchor) {
|
|
8299
|
+
hoveredNavContainerRef.current = null;
|
|
8300
|
+
setHoveredNavContainerRect(null);
|
|
7346
8301
|
const selected2 = selectedElRef.current;
|
|
7347
8302
|
if (selected2 === navAnchor || selected2?.contains(navAnchor)) return;
|
|
7348
8303
|
clearHrefKeyHover(navAnchor);
|
|
@@ -7367,6 +8322,14 @@ function OhhwellsBridge() {
|
|
|
7367
8322
|
};
|
|
7368
8323
|
const handleMouseOut = (e) => {
|
|
7369
8324
|
const target = e.target;
|
|
8325
|
+
if (target.closest("[data-ohw-nav-container]")) {
|
|
8326
|
+
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
8327
|
+
if (related2?.closest("[data-ohw-nav-container], [data-ohw-navbar-container-chrome], [data-ohw-navbar-add-button]")) {
|
|
8328
|
+
return;
|
|
8329
|
+
}
|
|
8330
|
+
hoveredNavContainerRef.current = null;
|
|
8331
|
+
setHoveredNavContainerRect(null);
|
|
8332
|
+
}
|
|
7370
8333
|
const navAnchor = getNavigationItemAnchor(target);
|
|
7371
8334
|
if (navAnchor) {
|
|
7372
8335
|
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
@@ -7488,6 +8451,56 @@ function OhhwellsBridge() {
|
|
|
7488
8451
|
}
|
|
7489
8452
|
return smallest;
|
|
7490
8453
|
};
|
|
8454
|
+
const dismissImageHover = () => {
|
|
8455
|
+
if (hoveredImageRef.current) {
|
|
8456
|
+
hoveredImageRef.current = null;
|
|
8457
|
+
hoveredImageHasTextOverlapRef.current = false;
|
|
8458
|
+
resumeAnimTracks();
|
|
8459
|
+
postToParentRef.current({ type: "ow:image-unhover" });
|
|
8460
|
+
}
|
|
8461
|
+
};
|
|
8462
|
+
const probeNavigationHoverAt = (x, y) => {
|
|
8463
|
+
if (toolbarVariantRef.current === "select-frame") {
|
|
8464
|
+
hoveredNavContainerRef.current = null;
|
|
8465
|
+
setHoveredNavContainerRect(null);
|
|
8466
|
+
return;
|
|
8467
|
+
}
|
|
8468
|
+
const navContainer = document.querySelector("[data-ohw-nav-container]");
|
|
8469
|
+
if (!navContainer) {
|
|
8470
|
+
hoveredNavContainerRef.current = null;
|
|
8471
|
+
setHoveredNavContainerRect(null);
|
|
8472
|
+
return;
|
|
8473
|
+
}
|
|
8474
|
+
const containerRect = navContainer.getBoundingClientRect();
|
|
8475
|
+
const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
|
|
8476
|
+
if (!overContainer) {
|
|
8477
|
+
hoveredNavContainerRef.current = null;
|
|
8478
|
+
setHoveredNavContainerRect(null);
|
|
8479
|
+
return;
|
|
8480
|
+
}
|
|
8481
|
+
const navItemHit = Array.from(
|
|
8482
|
+
navContainer.querySelectorAll("[data-ohw-href-key]")
|
|
8483
|
+
).find((el) => {
|
|
8484
|
+
if (!isNavigationItem(el) || isNavbarButton2(el)) return false;
|
|
8485
|
+
const itemRect = el.getBoundingClientRect();
|
|
8486
|
+
return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
|
|
8487
|
+
});
|
|
8488
|
+
if (navItemHit) {
|
|
8489
|
+
hoveredNavContainerRef.current = null;
|
|
8490
|
+
setHoveredNavContainerRect(null);
|
|
8491
|
+
const selected = selectedElRef.current;
|
|
8492
|
+
if (selected !== navItemHit && !selected?.contains(navItemHit)) {
|
|
8493
|
+
clearHrefKeyHover(navItemHit);
|
|
8494
|
+
hoveredItemElRef.current = navItemHit;
|
|
8495
|
+
setHoveredItemRect(navItemHit.getBoundingClientRect());
|
|
8496
|
+
}
|
|
8497
|
+
return;
|
|
8498
|
+
}
|
|
8499
|
+
hoveredNavContainerRef.current = navContainer;
|
|
8500
|
+
setHoveredNavContainerRect(containerRect);
|
|
8501
|
+
hoveredItemElRef.current = null;
|
|
8502
|
+
setHoveredItemRect(null);
|
|
8503
|
+
};
|
|
7491
8504
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
7492
8505
|
if (linkPopoverOpenRef.current) {
|
|
7493
8506
|
if (hoveredImageRef.current) {
|
|
@@ -7496,18 +8509,22 @@ function OhhwellsBridge() {
|
|
|
7496
8509
|
resumeAnimTracks();
|
|
7497
8510
|
clearImageHover();
|
|
7498
8511
|
}
|
|
8512
|
+
dismissImageHover();
|
|
8513
|
+
return;
|
|
8514
|
+
}
|
|
8515
|
+
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
8516
|
+
if (isPointOverNavigation(x, y)) {
|
|
8517
|
+
dismissImageHover();
|
|
8518
|
+
probeNavigationHoverAt(x, y);
|
|
7499
8519
|
return;
|
|
7500
8520
|
}
|
|
8521
|
+
hoveredNavContainerRef.current = null;
|
|
8522
|
+
setHoveredNavContainerRect(null);
|
|
7501
8523
|
const toggleEl = document.querySelector("[data-ohw-state-toggle]");
|
|
7502
8524
|
if (toggleEl) {
|
|
7503
|
-
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7504
8525
|
const tr = toggleEl.getBoundingClientRect();
|
|
7505
8526
|
if (x >= tr.left && x <= tr.right && y >= tr.top && y <= tr.bottom) {
|
|
7506
|
-
|
|
7507
|
-
hoveredImageRef.current = null;
|
|
7508
|
-
resumeAnimTracks();
|
|
7509
|
-
clearImageHover();
|
|
7510
|
-
}
|
|
8527
|
+
dismissImageHover();
|
|
7511
8528
|
return;
|
|
7512
8529
|
}
|
|
7513
8530
|
}
|
|
@@ -7520,15 +8537,18 @@ function OhhwellsBridge() {
|
|
|
7520
8537
|
resumeAnimTracks();
|
|
7521
8538
|
clearImageHover();
|
|
7522
8539
|
}
|
|
7523
|
-
|
|
8540
|
+
if (activeElRef.current) {
|
|
8541
|
+
dismissImageHover();
|
|
8542
|
+
return;
|
|
8543
|
+
}
|
|
7524
8544
|
}
|
|
7525
8545
|
if (imgEl) {
|
|
7526
|
-
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
8546
|
+
const { x: x2, y: y2 } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7527
8547
|
const overMediaChrome = Array.from(
|
|
7528
8548
|
document.querySelectorAll("[data-ohw-media-chrome]")
|
|
7529
8549
|
).some((el) => {
|
|
7530
8550
|
const r2 = el.getBoundingClientRect();
|
|
7531
|
-
return
|
|
8551
|
+
return x2 >= r2.left && x2 <= r2.right && y2 >= r2.top && y2 <= r2.bottom;
|
|
7532
8552
|
});
|
|
7533
8553
|
if (overMediaChrome) {
|
|
7534
8554
|
if (hoveredImageRef.current) {
|
|
@@ -7539,7 +8559,7 @@ function OhhwellsBridge() {
|
|
|
7539
8559
|
}
|
|
7540
8560
|
return;
|
|
7541
8561
|
}
|
|
7542
|
-
const topEl = document.elementFromPoint(
|
|
8562
|
+
const topEl = document.elementFromPoint(x2, y2);
|
|
7543
8563
|
if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
7544
8564
|
if (hoveredImageRef.current) {
|
|
7545
8565
|
hoveredImageRef.current = null;
|
|
@@ -7562,7 +8582,7 @@ function OhhwellsBridge() {
|
|
|
7562
8582
|
document.querySelectorAll(NON_MEDIA_SELECTOR)
|
|
7563
8583
|
).find((el) => {
|
|
7564
8584
|
const er = el.getBoundingClientRect();
|
|
7565
|
-
return
|
|
8585
|
+
return x2 >= er.left && x2 <= er.right && y2 >= er.top && y2 <= er.bottom;
|
|
7566
8586
|
});
|
|
7567
8587
|
if (imageUnhoverTimerRef.current) {
|
|
7568
8588
|
clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -7638,12 +8658,12 @@ function OhhwellsBridge() {
|
|
|
7638
8658
|
resumeAnimTracks();
|
|
7639
8659
|
clearImageHover();
|
|
7640
8660
|
}
|
|
7641
|
-
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
8661
|
+
const { x: x2, y: y2 } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7642
8662
|
const textEl = Array.from(
|
|
7643
8663
|
document.querySelectorAll(NON_MEDIA_SELECTOR)
|
|
7644
8664
|
).find((el) => {
|
|
7645
8665
|
const er = el.getBoundingClientRect();
|
|
7646
|
-
return
|
|
8666
|
+
return x2 >= er.left && x2 <= er.right && y2 >= er.top && y2 <= er.bottom;
|
|
7647
8667
|
});
|
|
7648
8668
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
7649
8669
|
if (textEl && !textEl.hasAttribute("contenteditable")) {
|
|
@@ -7667,6 +8687,14 @@ function OhhwellsBridge() {
|
|
|
7667
8687
|
}
|
|
7668
8688
|
};
|
|
7669
8689
|
const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
|
|
8690
|
+
if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
|
|
8691
|
+
if (activeStateElRef.current) {
|
|
8692
|
+
activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
|
|
8693
|
+
activeStateElRef.current = null;
|
|
8694
|
+
setToggleState(null);
|
|
8695
|
+
}
|
|
8696
|
+
return;
|
|
8697
|
+
}
|
|
7670
8698
|
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7671
8699
|
const toggleEl = document.querySelector("[data-ohw-state-toggle]");
|
|
7672
8700
|
if (toggleEl) {
|
|
@@ -7943,6 +8971,8 @@ function OhhwellsBridge() {
|
|
|
7943
8971
|
sectionsLoadedRef.current = true;
|
|
7944
8972
|
pendingScheduleConfigRequests.current.splice(0).forEach(processConfigRequest);
|
|
7945
8973
|
}
|
|
8974
|
+
editContentRef.current = { ...editContentRef.current, ...content };
|
|
8975
|
+
reconcileNavbarItemsFromContent(editContentRef.current);
|
|
7946
8976
|
enforceLinkHrefs();
|
|
7947
8977
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
7948
8978
|
};
|
|
@@ -7950,6 +8980,7 @@ function OhhwellsBridge() {
|
|
|
7950
8980
|
const handleDeactivate = (e) => {
|
|
7951
8981
|
if (e.data?.type !== "ow:deactivate") return;
|
|
7952
8982
|
if (Date.now() < linkPopoverGraceUntilRef.current) return;
|
|
8983
|
+
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
7953
8984
|
if (linkPopoverOpenRef.current) {
|
|
7954
8985
|
setLinkPopoverRef.current(null);
|
|
7955
8986
|
return;
|
|
@@ -7958,13 +8989,31 @@ function OhhwellsBridge() {
|
|
|
7958
8989
|
deactivateRef.current();
|
|
7959
8990
|
};
|
|
7960
8991
|
window.addEventListener("message", handleDeactivate);
|
|
8992
|
+
const handleUiEscape = (e) => {
|
|
8993
|
+
if (e.data?.type !== "ui:escape") return;
|
|
8994
|
+
if (linkPopoverOpenRef.current) {
|
|
8995
|
+
setLinkPopoverRef.current(null);
|
|
8996
|
+
}
|
|
8997
|
+
};
|
|
8998
|
+
window.addEventListener("message", handleUiEscape);
|
|
7961
8999
|
const handleKeyDown = (e) => {
|
|
9000
|
+
if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
|
|
7962
9001
|
if (e.key === "Escape" && linkPopoverOpenRef.current) {
|
|
7963
9002
|
setLinkPopoverRef.current(null);
|
|
7964
9003
|
return;
|
|
7965
9004
|
}
|
|
7966
9005
|
if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
|
|
7967
|
-
|
|
9006
|
+
if (toolbarVariantRef.current === "select-frame") {
|
|
9007
|
+
deselectRef.current();
|
|
9008
|
+
return;
|
|
9009
|
+
}
|
|
9010
|
+
const parent = getNavigationSelectionParent(selectedElRef.current);
|
|
9011
|
+
if (parent) {
|
|
9012
|
+
e.preventDefault();
|
|
9013
|
+
selectFrameRef.current(parent);
|
|
9014
|
+
} else {
|
|
9015
|
+
deselectRef.current();
|
|
9016
|
+
}
|
|
7968
9017
|
return;
|
|
7969
9018
|
}
|
|
7970
9019
|
if (e.key === "Escape" && activeElRef.current) {
|
|
@@ -8022,6 +9071,9 @@ function OhhwellsBridge() {
|
|
|
8022
9071
|
if (hoveredItemElRef.current) {
|
|
8023
9072
|
setHoveredItemRect(hoveredItemElRef.current.getBoundingClientRect());
|
|
8024
9073
|
}
|
|
9074
|
+
if (hoveredNavContainerRef.current) {
|
|
9075
|
+
setHoveredNavContainerRect(hoveredNavContainerRef.current.getBoundingClientRect());
|
|
9076
|
+
}
|
|
8025
9077
|
if (siblingHintElRef.current) {
|
|
8026
9078
|
setSiblingHintRect(siblingHintElRef.current.getBoundingClientRect());
|
|
8027
9079
|
}
|
|
@@ -8218,9 +9270,45 @@ function OhhwellsBridge() {
|
|
|
8218
9270
|
return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
|
|
8219
9271
|
});
|
|
8220
9272
|
if (textEditable) {
|
|
8221
|
-
|
|
9273
|
+
const hrefCtx = getHrefKeyFromElement(textEditable);
|
|
9274
|
+
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
9275
|
+
if (navAnchor) {
|
|
9276
|
+
if (selectedElRef.current === navAnchor) {
|
|
9277
|
+
activateRef.current(textEditable, { caretX: clientX, caretY: clientY });
|
|
9278
|
+
} else {
|
|
9279
|
+
selectRef.current(navAnchor);
|
|
9280
|
+
}
|
|
9281
|
+
return;
|
|
9282
|
+
}
|
|
9283
|
+
activateRef.current(textEditable, { caretX: clientX, caretY: clientY });
|
|
8222
9284
|
return;
|
|
8223
9285
|
}
|
|
9286
|
+
const navContainer = document.querySelector("[data-ohw-nav-container]");
|
|
9287
|
+
if (navContainer) {
|
|
9288
|
+
const r2 = navContainer.getBoundingClientRect();
|
|
9289
|
+
const pad = 8;
|
|
9290
|
+
const over = clientX >= r2.left - pad && clientX <= r2.right + pad && clientY >= r2.top - pad && clientY <= r2.bottom + pad;
|
|
9291
|
+
if (over && !isPointOverNavItem(navContainer, clientX, clientY)) {
|
|
9292
|
+
selectFrameRef.current(navContainer);
|
|
9293
|
+
return;
|
|
9294
|
+
}
|
|
9295
|
+
}
|
|
9296
|
+
const navRoot = document.querySelector("[data-ohw-nav-root]");
|
|
9297
|
+
if (navRoot && navContainer) {
|
|
9298
|
+
const rr = navRoot.getBoundingClientRect();
|
|
9299
|
+
if (clientX >= rr.left && clientX <= rr.right && clientY >= rr.top && clientY <= rr.bottom && !isPointOverNavItem(navContainer, clientX, clientY)) {
|
|
9300
|
+
const book = navRoot.querySelector('[data-ohw-role="navbar-button"]');
|
|
9301
|
+
if (book) {
|
|
9302
|
+
const br = book.getBoundingClientRect();
|
|
9303
|
+
if (clientX >= br.left && clientX <= br.right && clientY >= br.top && clientY <= br.bottom) {
|
|
9304
|
+
deactivateRef.current();
|
|
9305
|
+
return;
|
|
9306
|
+
}
|
|
9307
|
+
}
|
|
9308
|
+
selectFrameRef.current(navContainer);
|
|
9309
|
+
return;
|
|
9310
|
+
}
|
|
9311
|
+
}
|
|
8224
9312
|
deactivateRef.current();
|
|
8225
9313
|
};
|
|
8226
9314
|
window.addEventListener("message", handleSave);
|
|
@@ -8283,13 +9371,14 @@ function OhhwellsBridge() {
|
|
|
8283
9371
|
window.removeEventListener("message", handleClickAt);
|
|
8284
9372
|
window.removeEventListener("message", handleHydrate);
|
|
8285
9373
|
window.removeEventListener("message", handleDeactivate);
|
|
9374
|
+
window.removeEventListener("message", handleUiEscape);
|
|
8286
9375
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
8287
9376
|
autoSaveTimers.current.clear();
|
|
8288
9377
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
8289
9378
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
8290
9379
|
};
|
|
8291
9380
|
}, [isEditMode, refreshStateRules]);
|
|
8292
|
-
(0,
|
|
9381
|
+
(0, import_react8.useEffect)(() => {
|
|
8293
9382
|
const handler = (e) => {
|
|
8294
9383
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
8295
9384
|
const insertAfterVal = e.data.insertAfter;
|
|
@@ -8305,7 +9394,7 @@ function OhhwellsBridge() {
|
|
|
8305
9394
|
window.addEventListener("message", handler);
|
|
8306
9395
|
return () => window.removeEventListener("message", handler);
|
|
8307
9396
|
}, [processConfigRequest]);
|
|
8308
|
-
(0,
|
|
9397
|
+
(0, import_react8.useEffect)(() => {
|
|
8309
9398
|
if (!isEditMode) return;
|
|
8310
9399
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|
|
8311
9400
|
el.removeAttribute("data-ohw-active-state");
|
|
@@ -8326,27 +9415,27 @@ function OhhwellsBridge() {
|
|
|
8326
9415
|
const next = { ...prev, [pathKey]: sections };
|
|
8327
9416
|
return shouldUseDevFixtures() ? { ...DEV_SECTIONS_BY_PATH, ...next } : next;
|
|
8328
9417
|
});
|
|
8329
|
-
|
|
8330
|
-
|
|
9418
|
+
postToParent2({ type: "ow:ready", version: "1", path: pathname, nodes: collectEditableNodes(), sections });
|
|
9419
|
+
postToParent2({ type: "ow:request-site-pages" });
|
|
8331
9420
|
}, 150);
|
|
8332
9421
|
return () => {
|
|
8333
9422
|
cancelAnimationFrame(raf);
|
|
8334
9423
|
clearTimeout(timer);
|
|
8335
9424
|
};
|
|
8336
|
-
}, [pathname, isEditMode, refreshStateRules,
|
|
8337
|
-
(0,
|
|
9425
|
+
}, [pathname, isEditMode, refreshStateRules, postToParent2]);
|
|
9426
|
+
(0, import_react8.useEffect)(() => {
|
|
8338
9427
|
scrollToHashSectionWhenReady();
|
|
8339
9428
|
const onHashChange = () => scrollToHashSectionWhenReady();
|
|
8340
9429
|
window.addEventListener("hashchange", onHashChange);
|
|
8341
9430
|
return () => window.removeEventListener("hashchange", onHashChange);
|
|
8342
9431
|
}, [pathname]);
|
|
8343
|
-
const handleCommand = (0,
|
|
9432
|
+
const handleCommand = (0, import_react8.useCallback)((cmd) => {
|
|
8344
9433
|
document.execCommand(cmd, false);
|
|
8345
9434
|
activeElRef.current?.focus();
|
|
8346
9435
|
if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
|
|
8347
9436
|
refreshActiveCommandsRef.current();
|
|
8348
9437
|
}, []);
|
|
8349
|
-
const handleStateChange = (0,
|
|
9438
|
+
const handleStateChange = (0, import_react8.useCallback)((state) => {
|
|
8350
9439
|
if (!activeStateElRef.current) return;
|
|
8351
9440
|
const el = activeStateElRef.current;
|
|
8352
9441
|
if (state === "Default") {
|
|
@@ -8359,18 +9448,22 @@ function OhhwellsBridge() {
|
|
|
8359
9448
|
}
|
|
8360
9449
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
8361
9450
|
}, [deactivate]);
|
|
8362
|
-
const closeLinkPopover = (0,
|
|
8363
|
-
|
|
9451
|
+
const closeLinkPopover = (0, import_react8.useCallback)(() => {
|
|
9452
|
+
addNavAfterAnchorRef.current = null;
|
|
9453
|
+
setLinkPopover(null);
|
|
9454
|
+
}, []);
|
|
9455
|
+
const openLinkPopoverForActive = (0, import_react8.useCallback)(() => {
|
|
8364
9456
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
8365
9457
|
if (!hrefCtx) return;
|
|
8366
9458
|
bumpLinkPopoverGrace();
|
|
8367
9459
|
setLinkPopover({
|
|
8368
9460
|
key: hrefCtx.key,
|
|
8369
|
-
|
|
9461
|
+
mode: "edit",
|
|
9462
|
+
target: getLinkHref2(hrefCtx.anchor)
|
|
8370
9463
|
});
|
|
8371
9464
|
deactivate();
|
|
8372
9465
|
}, [deactivate]);
|
|
8373
|
-
const openLinkPopoverForSelected = (0,
|
|
9466
|
+
const openLinkPopoverForSelected = (0, import_react8.useCallback)(() => {
|
|
8374
9467
|
const anchor = selectedElRef.current;
|
|
8375
9468
|
if (!anchor) return;
|
|
8376
9469
|
const key = anchor.getAttribute("data-ohw-href-key");
|
|
@@ -8378,30 +9471,77 @@ function OhhwellsBridge() {
|
|
|
8378
9471
|
bumpLinkPopoverGrace();
|
|
8379
9472
|
setLinkPopover({
|
|
8380
9473
|
key,
|
|
8381
|
-
|
|
9474
|
+
mode: "edit",
|
|
9475
|
+
target: getLinkHref2(anchor)
|
|
8382
9476
|
});
|
|
8383
9477
|
deselect();
|
|
8384
9478
|
}, [deselect]);
|
|
8385
|
-
const handleLinkPopoverSubmit = (0,
|
|
9479
|
+
const handleLinkPopoverSubmit = (0, import_react8.useCallback)(
|
|
8386
9480
|
(target) => {
|
|
8387
|
-
|
|
8388
|
-
|
|
9481
|
+
const session = linkPopoverSessionRef.current;
|
|
9482
|
+
if (!session) return;
|
|
9483
|
+
if (session.intent === "add-nav") {
|
|
9484
|
+
const trimmed = target.trim();
|
|
9485
|
+
let href = trimmed;
|
|
9486
|
+
let label = "Untitled";
|
|
9487
|
+
if (trimmed) {
|
|
9488
|
+
const { pageRoute, sectionId } = parseTarget(trimmed);
|
|
9489
|
+
const page = resolvePage(pageRoute, sitePages);
|
|
9490
|
+
const pageSections = getSectionsForPath(sectionsByPath, pageRoute);
|
|
9491
|
+
const section = sectionId ? pageSections.find((s) => s.id === sectionId) : void 0;
|
|
9492
|
+
label = section?.label ?? page.title;
|
|
9493
|
+
href = trimmed;
|
|
9494
|
+
}
|
|
9495
|
+
const afterAnchor = addNavAfterAnchorRef.current;
|
|
9496
|
+
const { anchor, hrefKey, labelKey, index, order } = insertNavbarItem(href, label, afterAnchor);
|
|
9497
|
+
applyLinkByKey(hrefKey, href);
|
|
9498
|
+
document.querySelectorAll(`[data-ohw-key="${labelKey}"]`).forEach((el) => {
|
|
9499
|
+
el.textContent = label;
|
|
9500
|
+
});
|
|
9501
|
+
const navCount = String(index + 1);
|
|
9502
|
+
const orderJson = JSON.stringify(order);
|
|
9503
|
+
editContentRef.current = {
|
|
9504
|
+
...editContentRef.current,
|
|
9505
|
+
[hrefKey]: href,
|
|
9506
|
+
[labelKey]: label,
|
|
9507
|
+
[NAV_COUNT_KEY]: navCount,
|
|
9508
|
+
[NAV_ORDER_KEY]: orderJson
|
|
9509
|
+
};
|
|
9510
|
+
postToParent2({
|
|
9511
|
+
type: "ow:change",
|
|
9512
|
+
nodes: [
|
|
9513
|
+
{ key: hrefKey, text: href },
|
|
9514
|
+
{ key: labelKey, text: label },
|
|
9515
|
+
{ key: NAV_COUNT_KEY, text: navCount },
|
|
9516
|
+
{ key: NAV_ORDER_KEY, text: orderJson }
|
|
9517
|
+
]
|
|
9518
|
+
});
|
|
9519
|
+
postToParent2({ type: "ow:toast", title: "Link added", toastType: "success" });
|
|
9520
|
+
addNavAfterAnchorRef.current = null;
|
|
9521
|
+
setLinkPopover(null);
|
|
9522
|
+
enforceLinkHrefs();
|
|
9523
|
+
requestAnimationFrame(() => {
|
|
9524
|
+
selectRef.current(anchor);
|
|
9525
|
+
});
|
|
9526
|
+
return;
|
|
9527
|
+
}
|
|
9528
|
+
const { key } = session;
|
|
8389
9529
|
applyLinkByKey(key, target);
|
|
8390
|
-
|
|
9530
|
+
postToParent2({ type: "ow:change", nodes: [{ key, text: target }] });
|
|
8391
9531
|
setLinkPopover(null);
|
|
8392
9532
|
},
|
|
8393
|
-
[
|
|
9533
|
+
[postToParent2, sitePages, sectionsByPath]
|
|
8394
9534
|
);
|
|
8395
9535
|
const showEditLink = toolbarShowEditLink;
|
|
8396
9536
|
const currentSections = sectionsByPath[pathname] ?? [];
|
|
8397
9537
|
linkPopoverOpenRef.current = linkPopover !== null;
|
|
8398
|
-
const handleMediaReplace = (0,
|
|
9538
|
+
const handleMediaReplace = (0, import_react8.useCallback)(
|
|
8399
9539
|
(key) => {
|
|
8400
|
-
|
|
9540
|
+
postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
|
|
8401
9541
|
},
|
|
8402
|
-
[
|
|
9542
|
+
[postToParent2, mediaHover?.elementType]
|
|
8403
9543
|
);
|
|
8404
|
-
const handleMediaFadeOutComplete = (0,
|
|
9544
|
+
const handleMediaFadeOutComplete = (0, import_react8.useCallback)((key) => {
|
|
8405
9545
|
setUploadingRects((prev) => {
|
|
8406
9546
|
if (!(key in prev)) return prev;
|
|
8407
9547
|
const next = { ...prev };
|
|
@@ -8409,7 +9549,7 @@ function OhhwellsBridge() {
|
|
|
8409
9549
|
return next;
|
|
8410
9550
|
});
|
|
8411
9551
|
}, []);
|
|
8412
|
-
const handleVideoSettingsChange = (0,
|
|
9552
|
+
const handleVideoSettingsChange = (0, import_react8.useCallback)(
|
|
8413
9553
|
(key, settings) => {
|
|
8414
9554
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
8415
9555
|
const video = getVideoEl(el);
|
|
@@ -8417,7 +9557,7 @@ function OhhwellsBridge() {
|
|
|
8417
9557
|
if (typeof settings.autoplay === "boolean") video.autoplay = settings.autoplay;
|
|
8418
9558
|
if (typeof settings.muted === "boolean") video.muted = settings.muted;
|
|
8419
9559
|
syncVideoPlayback(video);
|
|
8420
|
-
|
|
9560
|
+
postToParent2({
|
|
8421
9561
|
type: "ow:change",
|
|
8422
9562
|
nodes: [
|
|
8423
9563
|
{ key: `${key}${VIDEO_AUTOPLAY_SUFFIX}`, text: String(video.autoplay) },
|
|
@@ -8429,12 +9569,12 @@ function OhhwellsBridge() {
|
|
|
8429
9569
|
);
|
|
8430
9570
|
});
|
|
8431
9571
|
},
|
|
8432
|
-
[
|
|
9572
|
+
[postToParent2]
|
|
8433
9573
|
);
|
|
8434
|
-
return bridgeRoot ? (0,
|
|
8435
|
-
/* @__PURE__ */ (0,
|
|
8436
|
-
/* @__PURE__ */ (0,
|
|
8437
|
-
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0,
|
|
9574
|
+
return bridgeRoot ? (0, import_react_dom3.createPortal)(
|
|
9575
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
9576
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
9577
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8438
9578
|
MediaOverlay,
|
|
8439
9579
|
{
|
|
8440
9580
|
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
@@ -8445,7 +9585,7 @@ function OhhwellsBridge() {
|
|
|
8445
9585
|
},
|
|
8446
9586
|
`uploading-${key}`
|
|
8447
9587
|
)),
|
|
8448
|
-
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0,
|
|
9588
|
+
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8449
9589
|
MediaOverlay,
|
|
8450
9590
|
{
|
|
8451
9591
|
hover: mediaHover,
|
|
@@ -8454,31 +9594,40 @@ function OhhwellsBridge() {
|
|
|
8454
9594
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
8455
9595
|
}
|
|
8456
9596
|
),
|
|
8457
|
-
siblingHintRect && !isItemDragging && /* @__PURE__ */ (0,
|
|
8458
|
-
|
|
8459
|
-
|
|
9597
|
+
siblingHintRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
9598
|
+
hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && !siblingHintRect && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
9599
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
9600
|
+
NavbarContainerChrome,
|
|
9601
|
+
{
|
|
9602
|
+
rect: toolbarRect,
|
|
9603
|
+
onAdd: handleAddTopLevelNavItem
|
|
9604
|
+
}
|
|
9605
|
+
),
|
|
9606
|
+
hoveredItemRect && !hoveredNavContainerRect && !siblingHintRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
9607
|
+
toolbarRect && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8460
9608
|
ItemInteractionLayer,
|
|
8461
9609
|
{
|
|
8462
9610
|
rect: toolbarRect,
|
|
8463
9611
|
elRef: glowElRef,
|
|
8464
9612
|
state: isItemDragging ? "dragging" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
8465
|
-
showHandle: Boolean(reorderHrefKey),
|
|
9613
|
+
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey),
|
|
8466
9614
|
dragDisabled: reorderDragDisabled,
|
|
8467
9615
|
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
8468
9616
|
onDragHandleDragStart: handleItemDragStart,
|
|
8469
9617
|
onDragHandleDragEnd: handleItemDragEnd,
|
|
8470
|
-
toolbar:
|
|
9618
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8471
9619
|
ItemActionToolbar,
|
|
8472
9620
|
{
|
|
8473
9621
|
onEditLink: openLinkPopoverForSelected,
|
|
8474
|
-
|
|
8475
|
-
|
|
9622
|
+
addItemDisabled: true,
|
|
9623
|
+
editLinkDisabled: false,
|
|
9624
|
+
moreDisabled: true
|
|
8476
9625
|
}
|
|
8477
|
-
)
|
|
9626
|
+
) : void 0
|
|
8478
9627
|
}
|
|
8479
9628
|
),
|
|
8480
|
-
toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ (0,
|
|
8481
|
-
/* @__PURE__ */ (0,
|
|
9629
|
+
toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
9630
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8482
9631
|
EditGlowChrome,
|
|
8483
9632
|
{
|
|
8484
9633
|
rect: toolbarRect,
|
|
@@ -8487,7 +9636,7 @@ function OhhwellsBridge() {
|
|
|
8487
9636
|
dragDisabled: reorderDragDisabled
|
|
8488
9637
|
}
|
|
8489
9638
|
),
|
|
8490
|
-
/* @__PURE__ */ (0,
|
|
9639
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8491
9640
|
FloatingToolbar,
|
|
8492
9641
|
{
|
|
8493
9642
|
rect: toolbarRect,
|
|
@@ -8500,7 +9649,7 @@ function OhhwellsBridge() {
|
|
|
8500
9649
|
}
|
|
8501
9650
|
)
|
|
8502
9651
|
] }),
|
|
8503
|
-
maxBadge && /* @__PURE__ */ (0,
|
|
9652
|
+
maxBadge && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
8504
9653
|
"div",
|
|
8505
9654
|
{
|
|
8506
9655
|
"data-ohw-max-badge": "",
|
|
@@ -8526,7 +9675,7 @@ function OhhwellsBridge() {
|
|
|
8526
9675
|
]
|
|
8527
9676
|
}
|
|
8528
9677
|
),
|
|
8529
|
-
toggleState && /* @__PURE__ */ (0,
|
|
9678
|
+
toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8530
9679
|
StateToggle,
|
|
8531
9680
|
{
|
|
8532
9681
|
rect: toggleState.rect,
|
|
@@ -8535,15 +9684,15 @@ function OhhwellsBridge() {
|
|
|
8535
9684
|
onStateChange: handleStateChange
|
|
8536
9685
|
}
|
|
8537
9686
|
),
|
|
8538
|
-
sectionGap && /* @__PURE__ */ (0,
|
|
9687
|
+
sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
8539
9688
|
"div",
|
|
8540
9689
|
{
|
|
8541
9690
|
"data-ohw-section-insert-line": "",
|
|
8542
9691
|
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
8543
9692
|
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
8544
9693
|
children: [
|
|
8545
|
-
/* @__PURE__ */ (0,
|
|
8546
|
-
/* @__PURE__ */ (0,
|
|
9694
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
9695
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8547
9696
|
Badge,
|
|
8548
9697
|
{
|
|
8549
9698
|
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 +9705,26 @@ function OhhwellsBridge() {
|
|
|
8556
9705
|
children: "Add Section"
|
|
8557
9706
|
}
|
|
8558
9707
|
),
|
|
8559
|
-
/* @__PURE__ */ (0,
|
|
9708
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
8560
9709
|
]
|
|
8561
9710
|
}
|
|
8562
9711
|
),
|
|
8563
|
-
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0,
|
|
9712
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8564
9713
|
LinkPopover,
|
|
8565
9714
|
{
|
|
8566
9715
|
panelRef: linkPopoverPanelRef,
|
|
8567
9716
|
portalContainer: dialogPortalContainer,
|
|
8568
9717
|
open: true,
|
|
8569
|
-
mode: "edit",
|
|
9718
|
+
mode: linkPopover.mode ?? "edit",
|
|
8570
9719
|
pages: sitePages,
|
|
8571
9720
|
sections: currentSections,
|
|
8572
9721
|
sectionsByPath,
|
|
8573
9722
|
initialTarget: linkPopover.target,
|
|
9723
|
+
existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [],
|
|
8574
9724
|
onClose: closeLinkPopover,
|
|
8575
9725
|
onSubmit: handleLinkPopoverSubmit
|
|
8576
9726
|
},
|
|
8577
|
-
|
|
9727
|
+
linkPopover.key
|
|
8578
9728
|
) : null
|
|
8579
9729
|
] }),
|
|
8580
9730
|
bridgeRoot
|