@ohhwells/bridge 0.1.28 → 0.1.29

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.js CHANGED
@@ -1,752 +1,10 @@
1
1
  "use client";
2
2
 
3
3
  // src/OhhwellsBridge.tsx
4
- import React5, { useCallback as useCallback2, useEffect as useEffect3, useLayoutEffect, useRef as useRef3, useState as useState5 } from "react";
5
- import { createRoot } from "react-dom/client";
6
- import { flushSync } from "react-dom";
7
-
8
- // src/ui/SchedulingWidget.tsx
9
- import { useEffect, useMemo, useRef, useState as useState2 } from "react";
10
-
11
- // src/ui/EmailCaptureModal.tsx
12
- import { useState } from "react";
13
- import { Dialog } from "radix-ui";
14
- import { jsx, jsxs } from "react/jsx-runtime";
15
- function Spinner() {
16
- return /* @__PURE__ */ jsxs(
17
- "svg",
18
- {
19
- width: "32",
20
- height: "32",
21
- viewBox: "0 0 32 32",
22
- fill: "none",
23
- style: { animation: "ohw-spin 0.75s linear infinite" },
24
- children: [
25
- /* @__PURE__ */ jsx("style", { children: `@keyframes ohw-spin { to { transform: rotate(360deg); } }` }),
26
- /* @__PURE__ */ jsx("circle", { cx: "16", cy: "16", r: "12", stroke: "#e5e7eb", strokeWidth: "3" }),
27
- /* @__PURE__ */ jsx(
28
- "path",
29
- {
30
- d: "M16 4a12 12 0 0 1 12 12",
31
- stroke: "#3b82f6",
32
- strokeWidth: "3",
33
- strokeLinecap: "round"
34
- }
35
- )
36
- ]
37
- }
38
- );
39
- }
40
- function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
41
- const [email, setEmail] = useState("");
42
- const [submittedEmail, setSubmittedEmail] = useState("");
43
- const [loading, setLoading] = useState(false);
44
- const [success, setSuccess] = useState(false);
45
- const [error, setError] = useState(null);
46
- const isBook = title === "Confirm your spot";
47
- const handleSubmit = async () => {
48
- if (!email.trim()) return;
49
- setLoading(true);
50
- setError(null);
51
- try {
52
- await onSubmit(email.trim());
53
- setSubmittedEmail(email.trim());
54
- setSuccess(true);
55
- } catch (e) {
56
- setError(e instanceof Error ? e.message : "Something went wrong. Please try again.");
57
- } finally {
58
- setLoading(false);
59
- }
60
- };
61
- const handleKeyDown = (e) => {
62
- if (e.key === "Enter" && !loading) handleSubmit();
63
- };
64
- return /* @__PURE__ */ jsx(Dialog.Root, { open: true, onOpenChange: (open) => {
65
- if (!open) onClose();
66
- }, children: /* @__PURE__ */ jsxs(Dialog.Portal, { children: [
67
- /* @__PURE__ */ jsx(
68
- Dialog.Overlay,
69
- {
70
- className: "fixed inset-0 z-50",
71
- style: { background: "rgba(0,0,0,0.45)" }
72
- }
73
- ),
74
- /* @__PURE__ */ jsxs(
75
- Dialog.Content,
76
- {
77
- className: "fixed left-1/2 top-1/2 z-50 w-full -translate-x-1/2 -translate-y-1/2 bg-white rounded-xl shadow-xl outline-none font-body box-border overflow-hidden",
78
- style: { maxWidth: 400 },
79
- children: [
80
- /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3 p-6", children: [
81
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
82
- /* @__PURE__ */ jsx(
83
- Dialog.Title,
84
- {
85
- className: "font-body text-xl font-bold m-0 leading-tight",
86
- style: { color: "var(--color-dark,#200C02)" },
87
- children: success ? isBook ? "Reservation confirmed!" : "You're on the waitlist!" : title
88
- }
89
- ),
90
- /* @__PURE__ */ jsx(
91
- Dialog.Description,
92
- {
93
- className: "font-body text-sm m-0",
94
- style: { color: "#6B7280" },
95
- children: success ? isBook ? `A confirmation email has been sent to ${submittedEmail}.` : "We'll let you know via email if someone cancels." : subtitle
96
- }
97
- )
98
- ] }),
99
- /* @__PURE__ */ jsx(
100
- Dialog.Close,
101
- {
102
- className: "shrink-0 w-7 h-7 flex items-center justify-center rounded-full bg-transparent border-none cursor-pointer mt-0.5 absolute top-2.5 right-1.5",
103
- style: { color: "#6B7280" },
104
- "aria-label": "Close",
105
- children: /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
106
- /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
107
- /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
108
- ] })
109
- }
110
- )
111
- ] }),
112
- !success && (loading ? (
113
- /* Loading state — full body replaced */
114
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center gap-3 px-7 py-12", children: [
115
- /* @__PURE__ */ jsx(Spinner, {}),
116
- /* @__PURE__ */ jsx("p", { className: "font-body text-sm m-0", style: { color: "#6B7280" }, children: "Please wait" })
117
- ] })
118
- ) : (
119
- /* Email form */
120
- /* @__PURE__ */ jsxs("div", { className: "px-7 pt-2 pb-6", children: [
121
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5 mb-8", children: [
122
- /* @__PURE__ */ jsx("label", { className: "font-body text-sm font-medium", style: { color: "var(--color-dark,#200C02)" }, children: "Email" }),
123
- /* @__PURE__ */ jsx(
124
- "input",
125
- {
126
- type: "email",
127
- value: email,
128
- onChange: (e) => setEmail(e.target.value),
129
- onKeyDown: handleKeyDown,
130
- placeholder: "hello@gmail.com",
131
- autoFocus: true,
132
- className: "w-full h-10 px-3 rounded-lg border font-body text-sm outline-none box-border",
133
- style: {
134
- borderColor: "#E7E5E4",
135
- background: "#fff",
136
- color: "var(--color-dark,#200C02)"
137
- }
138
- }
139
- ),
140
- error && /* @__PURE__ */ jsx("p", { className: "font-body text-xs text-red-500 m-0", children: error })
141
- ] }),
142
- /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(
143
- "button",
144
- {
145
- onClick: handleSubmit,
146
- disabled: !email.trim(),
147
- className: "h-9 px-5 rounded-lg font-body text-sm font-semibold cursor-pointer border-none disabled:opacity-50 disabled:cursor-not-allowed",
148
- style: {
149
- background: "var(--color-primary,#3D312B)",
150
- color: "var(--color-light,#FEFFF0)"
151
- },
152
- children: "Send"
153
- }
154
- ) })
155
- ] })
156
- ))
157
- ]
158
- }
159
- )
160
- ] }) });
161
- }
162
-
163
- // src/ui/SchedulingWidget.tsx
164
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
165
- var API_URL = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
166
- var DAY_ABBR = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
167
- function getApiDomain() {
168
- const h = window.location.hostname;
169
- for (const base of ["ohhwells.site", "theflowops-staging.com", "theflowops.com"]) {
170
- if (h.endsWith(`.${base}`)) return h.slice(0, -(base.length + 1));
171
- }
172
- return h;
173
- }
174
- function classRunsOnDate(cls, date, type) {
175
- if (type === "FIXED") {
176
- const d = String(date.getDate()).padStart(2, "0");
177
- const m = String(date.getMonth() + 1).padStart(2, "0");
178
- return cls.fixedDates?.some((fd) => fd.date === `${d}-${m}-${date.getFullYear()}`) ?? false;
179
- }
180
- return cls.weekdays?.some((w) => w.weekday === date.getDay()) ?? false;
181
- }
182
- function formatClassTime(cls) {
183
- let h = parseInt(cls.startTime.hour, 10);
184
- const m = parseInt(cls.startTime.minutes, 10);
185
- if (cls.startTime.time === "PM" && h !== 12) h += 12;
186
- if (cls.startTime.time === "AM" && h === 12) h = 0;
187
- const endTotal = h * 60 + m + cls.duration;
188
- const eh = Math.floor(endTotal / 60) % 24;
189
- const em = endTotal % 60;
190
- return `${h}:${cls.startTime.minutes}-${eh}:${String(em).padStart(2, "0")}`;
191
- }
192
- function getBookingsOnDate(cls, date) {
193
- if (!cls.bookings?.length) return 0;
194
- const ds = date.toISOString().split("T")[0];
195
- return cls.bookings.filter((b) => {
196
- try {
197
- return new Date(b.classDate).toISOString().split("T")[0] === ds;
198
- } catch {
199
- return false;
200
- }
201
- }).length;
202
- }
203
- function buildTimezoneLabel(tz) {
204
- try {
205
- const now = /* @__PURE__ */ new Date();
206
- const timeStr = new Intl.DateTimeFormat("en-US", {
207
- hour: "2-digit",
208
- minute: "2-digit",
209
- hour12: false,
210
- timeZone: tz
211
- }).format(now);
212
- const offsetPart = new Intl.DateTimeFormat("en-US", { timeZoneName: "short", timeZone: tz }).formatToParts(now).find((p) => p.type === "timeZoneName")?.value ?? "";
213
- const city = tz.split("/").pop()?.replace(/_/g, " ") ?? tz;
214
- return `${timeStr} (${offsetPart}) ${city} time`;
215
- } catch {
216
- return tz;
217
- }
218
- }
219
- function EmptyState({ inEditor }) {
220
- const handleAddSchedule = () => {
221
- if (inEditor) {
222
- window.parent.postMessage({ type: "ow:scheduling-not-connected" }, "*");
223
- }
224
- };
225
- return /* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center justify-center gap-6 p-12 bg-[#FAFAF9] border-2 border-dashed border-[#E7E5E4] rounded-[10px] h-[264px] w-full box-border", children: [
226
- /* @__PURE__ */ jsx2("div", { className: "w-10 h-10 bg-[#F5F5F4] rounded-[10px] flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsxs2(
227
- "svg",
228
- {
229
- width: "20",
230
- height: "20",
231
- viewBox: "0 0 24 24",
232
- fill: "none",
233
- stroke: "var(--color-accent, #A89B83)",
234
- strokeWidth: "1.5",
235
- strokeLinecap: "round",
236
- strokeLinejoin: "round",
237
- children: [
238
- /* @__PURE__ */ jsx2("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2" }),
239
- /* @__PURE__ */ jsx2("line", { x1: "16", y1: "2", x2: "16", y2: "6" }),
240
- /* @__PURE__ */ jsx2("line", { x1: "8", y1: "2", x2: "8", y2: "6" }),
241
- /* @__PURE__ */ jsx2("line", { x1: "3", y1: "10", x2: "21", y2: "10" }),
242
- /* @__PURE__ */ jsx2("line", { x1: "12", y1: "14", x2: "12", y2: "18" }),
243
- /* @__PURE__ */ jsx2("line", { x1: "10", y1: "16", x2: "14", y2: "16" })
244
- ]
245
- }
246
- ) }),
247
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center gap-2", children: [
248
- /* @__PURE__ */ jsx2("p", { className: "font-body text-lg font-medium text-center text-[#0A0A0A] m-0", children: "No schedule yet" }),
249
- /* @__PURE__ */ jsx2("p", { className: "font-body text-base font-normal text-center text-(--color-accent,#A89B83) m-0", children: "Add a scheduling widget to get instant bookings." })
250
- ] }),
251
- /* @__PURE__ */ jsx2(
252
- "button",
253
- {
254
- onClick: handleAddSchedule,
255
- className: "h-9 px-2 py-1.5 flex items-center justify-center bg-white border border-[#E7E5E4] rounded-md font-body text-sm font-medium text-(--color-dark,#200C02) cursor-pointer",
256
- children: "Add Schedule"
257
- }
258
- )
259
- ] });
260
- }
261
- function LoadingSkeleton() {
262
- const shimmer = {
263
- background: "linear-gradient(90deg,#f0f0f0 25%,#e8e8e8 50%,#f0f0f0 75%)",
264
- backgroundSize: "200% 100%",
265
- animation: "ohw-shimmer 1.5s infinite"
266
- };
267
- return /* @__PURE__ */ jsxs2("div", { className: "w-full flex flex-col gap-10", children: [
268
- /* @__PURE__ */ jsx2("style", { children: `@keyframes ohw-shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}` }),
269
- /* @__PURE__ */ jsx2("div", { className: "flex h-[70px] items-stretch", children: Array.from({ length: 7 }).map((_, i) => /* @__PURE__ */ jsxs2("div", { className: "flex-1 flex flex-col justify-between items-center px-1", children: [
270
- /* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "32px", height: "14px", borderRadius: "4px" } }),
271
- /* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "40px", height: "40px", borderRadius: "50%" } })
272
- ] }, i)) }),
273
- [0, 1, 2].map((i) => /* @__PURE__ */ jsxs2("div", { children: [
274
- /* @__PURE__ */ jsxs2("div", { className: "flex gap-4 py-4 sm:hidden", children: [
275
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-2 shrink-0", children: [
276
- /* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "100px", height: "16px", borderRadius: "4px" } }),
277
- /* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "52px", height: "20px", borderRadius: "999px" } }),
278
- /* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "60px", height: "14px", borderRadius: "4px" } })
279
- ] }),
280
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-1 flex-col gap-2", children: [
281
- /* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "75%", height: "16px", borderRadius: "4px" } }),
282
- /* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "50%", height: "14px", borderRadius: "4px" } }),
283
- /* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "100%", height: "44px", borderRadius: "8px" } })
284
- ] })
285
- ] }),
286
- /* @__PURE__ */ jsxs2("div", { className: "hidden sm:flex items-center gap-[60px] py-4", children: [
287
- /* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "120px", height: "16px", borderRadius: "4px", flexShrink: 0 } }),
288
- /* @__PURE__ */ jsxs2("div", { className: "flex-1 flex flex-col gap-2", children: [
289
- /* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "55%", height: "16px", borderRadius: "4px" } }),
290
- /* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "38%", height: "14px", borderRadius: "4px" } })
291
- ] }),
292
- /* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "56px", height: "32px", borderRadius: "4px", flexShrink: 0 } }),
293
- /* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "200px", height: "44px", borderRadius: "8px", flexShrink: 0 } })
294
- ] }),
295
- i < 2 && /* @__PURE__ */ jsx2("div", { className: "h-px bg-black/20" })
296
- ] }, i))
297
- ] });
298
- }
299
- function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal }) {
300
- const todayMs = useMemo(() => {
301
- const d = /* @__PURE__ */ new Date();
302
- d.setHours(0, 0, 0, 0);
303
- return d.getTime();
304
- }, []);
305
- const scrollRef = useRef(null);
306
- const [canScrollLeft, setCanScrollLeft] = useState2(false);
307
- const [canScrollRight, setCanScrollRight] = useState2(false);
308
- const updateScrollState = () => {
309
- const el = scrollRef.current;
310
- if (!el) return;
311
- setCanScrollLeft(el.scrollLeft > 0);
312
- setCanScrollRight(el.scrollLeft + el.clientWidth < el.scrollWidth - 1);
313
- };
314
- useEffect(() => {
315
- const el = scrollRef.current;
316
- if (!el) return;
317
- updateScrollState();
318
- el.addEventListener("scroll", updateScrollState);
319
- const ro = new ResizeObserver(updateScrollState);
320
- ro.observe(el);
321
- return () => {
322
- el.removeEventListener("scroll", updateScrollState);
323
- ro.disconnect();
324
- };
325
- }, [dates]);
326
- const scroll = (dir) => {
327
- scrollRef.current?.scrollBy({ left: dir === "left" ? -216 : 216, behavior: "smooth" });
328
- };
329
- const isDragging = useRef(false);
330
- const dragStartX = useRef(0);
331
- const dragStartScrollLeft = useRef(0);
332
- const onDragStart = (e) => {
333
- if (!scrollRef.current) return;
334
- isDragging.current = true;
335
- dragStartX.current = e.clientX;
336
- dragStartScrollLeft.current = scrollRef.current.scrollLeft;
337
- scrollRef.current.style.cursor = "grabbing";
338
- scrollRef.current.style.userSelect = "none";
339
- };
340
- const onDragMove = (e) => {
341
- if (!isDragging.current || !scrollRef.current) return;
342
- const delta = e.clientX - dragStartX.current;
343
- scrollRef.current.scrollLeft = dragStartScrollLeft.current - delta;
344
- };
345
- const onDragEnd = () => {
346
- if (!scrollRef.current) return;
347
- isDragging.current = false;
348
- scrollRef.current.style.cursor = "grab";
349
- scrollRef.current.style.userSelect = "";
350
- };
351
- const datesWithClasses = useMemo(
352
- () => new Set(dates.map(
353
- (d, i) => schedule.classes?.some((c) => classRunsOnDate(c, d, schedule.type)) ? i : -1
354
- ).filter((i) => i >= 0)),
355
- [dates, schedule]
356
- );
357
- const selectedDate = dates[selectedIdx];
358
- const selectedClasses = useMemo(
359
- () => (schedule.classes ?? []).filter((c) => selectedDate && classRunsOnDate(c, selectedDate, schedule.type)),
360
- [schedule, selectedDate]
361
- );
362
- return /* @__PURE__ */ jsxs2("div", { className: "w-full flex flex-col gap-10", children: [
363
- /* @__PURE__ */ jsxs2("div", { className: "relative w-full", children: [
364
- canScrollLeft && /* @__PURE__ */ jsx2(
365
- "button",
366
- {
367
- onClick: () => scroll("left"),
368
- className: "hidden sm:flex absolute left-0 top-1/2 -translate-y-1/2 z-10 w-8 h-8 items-center justify-center rounded-full border-none cursor-pointer",
369
- style: { background: "var(--color-light,#FEFFF0)", boxShadow: "0 1px 4px rgba(0,0,0,0.15)" },
370
- "aria-label": "Scroll left",
371
- children: /* @__PURE__ */ jsx2("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "var(--color-dark,#200C02)", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx2("polyline", { points: "15 18 9 12 15 6" }) })
372
- }
373
- ),
374
- canScrollRight && /* @__PURE__ */ jsx2(
375
- "button",
376
- {
377
- onClick: () => scroll("right"),
378
- className: "hidden sm:flex absolute right-0 top-1/2 -translate-y-1/2 z-10 w-8 h-8 items-center justify-center rounded-full border-none cursor-pointer",
379
- style: { background: "var(--color-light,#FEFFF0)", boxShadow: "0 1px 4px rgba(0,0,0,0.15)" },
380
- "aria-label": "Scroll right",
381
- children: /* @__PURE__ */ jsx2("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "var(--color-dark,#200C02)", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx2("polyline", { points: "9 18 15 12 9 6" }) })
382
- }
383
- ),
384
- canScrollLeft && /* @__PURE__ */ jsx2(
385
- "div",
386
- {
387
- className: "sm:hidden absolute left-0 top-0 bottom-0 w-10 z-10 pointer-events-none",
388
- style: { background: "linear-gradient(to right, var(--color-light,#FEFFF0), transparent)" }
389
- }
390
- ),
391
- canScrollRight && /* @__PURE__ */ jsx2(
392
- "div",
393
- {
394
- className: "sm:hidden absolute right-0 top-0 bottom-0 w-10 z-10 pointer-events-none",
395
- style: { background: "linear-gradient(to left, var(--color-light,#FEFFF0), transparent)" }
396
- }
397
- ),
398
- /* @__PURE__ */ jsx2(
399
- "div",
400
- {
401
- ref: scrollRef,
402
- className: "overflow-x-auto w-full",
403
- style: { scrollbarWidth: "none", msOverflowStyle: "none", touchAction: "pan-x", cursor: "grab" },
404
- onMouseDown: onDragStart,
405
- onMouseMove: onDragMove,
406
- onMouseUp: onDragEnd,
407
- onMouseLeave: onDragEnd,
408
- children: /* @__PURE__ */ jsx2("div", { className: "flex", style: { width: `max(100%, ${dates.length * 60}px)` }, children: dates.map((date, i) => {
409
- const isToday = date.getTime() === todayMs;
410
- const isSelected = i === selectedIdx;
411
- const clickable = datesWithClasses.has(i);
412
- const label = isToday ? "TODAY" : DAY_ABBR[date.getDay()];
413
- return /* @__PURE__ */ jsxs2(
414
- "div",
415
- {
416
- onClick: () => clickable && onSelectDate(i),
417
- className: `flex-1 h-[70px] flex flex-col justify-between items-center ${clickable ? "cursor-pointer opacity-100" : "cursor-default opacity-50"}`,
418
- children: [
419
- /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-normal text-center text-(--color-dark,#200C02)", children: label }),
420
- /* @__PURE__ */ jsx2(
421
- "div",
422
- {
423
- className: "w-10 h-10 rounded-full flex items-center justify-center",
424
- style: { background: isSelected ? "var(--color-primary, #3D312B)" : "transparent" },
425
- children: /* @__PURE__ */ jsx2(
426
- "span",
427
- {
428
- className: "font-body text-xl font-bold text-center tracking-display-tight",
429
- style: { color: isSelected ? "var(--color-light, #FEFFF0)" : "var(--color-dark, #200C02)" },
430
- children: date.getDate()
431
- }
432
- )
433
- }
434
- )
435
- ]
436
- },
437
- i
438
- );
439
- }) })
440
- }
441
- )
442
- ] }),
443
- selectedClasses.length === 0 ? /* @__PURE__ */ jsx2("p", { className: "font-body text-base text-(--color-accent,#A89B83) text-center py-8 m-0", children: "No classes scheduled for this day." }) : /* @__PURE__ */ jsx2("div", { className: "flex flex-col", children: selectedClasses.map((cls, i) => {
444
- const booked = getBookingsOnDate(cls, selectedDate);
445
- const available = cls.maxParticipants - booked;
446
- const isFull = available <= 0;
447
- return /* @__PURE__ */ jsxs2("div", { children: [
448
- /* @__PURE__ */ jsxs2("div", { className: "flex gap-4 py-4 sm:items-center sm:gap-[60px] box-border", children: [
449
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-2 shrink-0 sm:contents", children: [
450
- /* @__PURE__ */ jsx2("div", { className: "sm:w-[120px] sm:shrink-0", children: /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block", children: formatClassTime(cls) }) }),
451
- /* @__PURE__ */ jsx2(
452
- "span",
453
- {
454
- className: "inline-flex items-center px-2 py-0.5 rounded-full border text-xs font-medium sm:hidden",
455
- style: { borderColor: "#0885FE", color: "#0885FE" },
456
- children: "GROUP"
457
- }
458
- ),
459
- /* @__PURE__ */ jsx2("div", { className: "sm:hidden flex flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
460
- /* @__PURE__ */ jsxs2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
461
- available,
462
- "/",
463
- cls.maxParticipants
464
- ] }),
465
- /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "available" })
466
- ] }) })
467
- ] }),
468
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-1 flex-col gap-2 min-w-0 sm:contents", children: [
469
- /* @__PURE__ */ jsxs2("div", { className: "flex-1 flex flex-col gap-2 min-w-0", children: [
470
- /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block truncate", children: cls.name }),
471
- cls.hostName && /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName })
472
- ] }),
473
- /* @__PURE__ */ jsx2("div", { className: "hidden sm:flex w-14 shrink-0 flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
474
- /* @__PURE__ */ jsxs2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
475
- available,
476
- "/",
477
- cls.maxParticipants
478
- ] }),
479
- /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "available" })
480
- ] }) }),
481
- /* @__PURE__ */ jsx2(
482
- "button",
483
- {
484
- className: "w-full sm:w-[200px] sm:shrink-0 px-5 py-[10px] flex items-center justify-center rounded-lg font-body text-base font-bold cursor-pointer box-border",
485
- style: isFull ? {
486
- background: "transparent",
487
- border: "1px solid var(--color-dark, #200C02)",
488
- color: "var(--color-dark, #200C02)"
489
- } : {
490
- background: "var(--color-primary, #3D312B)",
491
- border: "none",
492
- color: "var(--color-light, #FEFFF0)"
493
- },
494
- onClick: () => {
495
- if (!cls.id) return;
496
- onOpenModal?.(isFull ? "waitlist" : "book", cls.id, selectedDate);
497
- },
498
- children: isFull ? "Join Waitlist" : "Book Now"
499
- }
500
- )
501
- ] })
502
- ] }),
503
- i < selectedClasses.length - 1 && /* @__PURE__ */ jsx2("div", { className: "h-px bg-black/20" })
504
- ] }, cls.id ?? i);
505
- }) })
506
- ] });
507
- }
508
- function CalendarFoldIcon() {
509
- return /* @__PURE__ */ jsxs2(
510
- "svg",
511
- {
512
- width: "16",
513
- height: "16",
514
- viewBox: "0 0 24 24",
515
- fill: "none",
516
- stroke: "currentColor",
517
- strokeWidth: "2",
518
- strokeLinecap: "round",
519
- strokeLinejoin: "round",
520
- style: { flexShrink: 0 },
521
- children: [
522
- /* @__PURE__ */ jsx2("path", { d: "M8 2v4" }),
523
- /* @__PURE__ */ jsx2("path", { d: "M16 2v4" }),
524
- /* @__PURE__ */ jsx2("path", { d: "M21 17V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h11Z" }),
525
- /* @__PURE__ */ jsx2("path", { d: "M3 10h18" }),
526
- /* @__PURE__ */ jsx2("path", { d: "M15 22v-4a2 2 0 0 1 2-2h4" })
527
- ]
528
- }
529
- );
530
- }
531
- function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAfter }) {
532
- const [schedule, setSchedule] = useState2(null);
533
- const [loading, setLoading] = useState2(true);
534
- const [inEditor, setInEditor] = useState2(false);
535
- const [isHovered, setIsHovered] = useState2(false);
536
- const [modalState, setModalState] = useState2(null);
537
- const switchScheduleIdRef = useRef(null);
538
- const dates = useMemo(() => {
539
- const today = /* @__PURE__ */ new Date();
540
- today.setHours(0, 0, 0, 0);
541
- return Array.from({ length: 14 }, (_, i) => {
542
- const d = new Date(today);
543
- d.setDate(today.getDate() + i);
544
- return d;
545
- });
546
- }, []);
547
- const [selectedIdx, setSelectedIdx] = useState2(0);
548
- useEffect(() => {
549
- if (!schedule?.classes) return;
550
- for (let i = 0; i < dates.length; i++) {
551
- if (schedule.classes.some((c) => classRunsOnDate(c, dates[i], schedule.type))) {
552
- setSelectedIdx(i);
553
- return;
554
- }
555
- }
556
- }, [schedule, dates]);
557
- useEffect(() => {
558
- if (typeof window === "undefined") return;
559
- const isInEditor = window.self !== window.top;
560
- setInEditor(isInEditor);
561
- if (isInEditor) {
562
- const startEmpty = initialScheduleId === null;
563
- if (startEmpty) setLoading(false);
564
- let initialized = startEmpty;
565
- const timer = !startEmpty ? setTimeout(() => {
566
- if (!initialized) {
567
- initialized = true;
568
- setLoading(false);
569
- }
570
- }, 5e3) : null;
571
- const handler = (e) => {
572
- if (e.data?.type === "ow:clear-scheduling-widget") {
573
- if (!e.data.insertAfter || e.data.insertAfter !== insertAfter) return;
574
- setSchedule(null);
575
- setLoading(false);
576
- return;
577
- }
578
- if (e.data?.type === "ow:switch-schedule") {
579
- if (!e.data.insertAfter || e.data.insertAfter !== insertAfter) return;
580
- switchScheduleIdRef.current = e.data.scheduleId ?? null;
581
- initialized = false;
582
- setLoading(true);
583
- window.parent.postMessage({ type: "ow:request-user-schedules", insertAfter }, "*");
584
- return;
585
- }
586
- if (e.data?.type !== "ow:user-schedules-response") return;
587
- if (e.data.insertAfter && e.data.insertAfter !== insertAfter) return;
588
- if (initialized && switchScheduleIdRef.current === null) return;
589
- initialized = true;
590
- if (timer) clearTimeout(timer);
591
- const schedules = e.data.schedules ?? [];
592
- const isSwitching = switchScheduleIdRef.current !== null;
593
- const target = isSwitching ? schedules.find((s) => s.id === switchScheduleIdRef.current) ?? schedules[0] ?? null : initialScheduleId ? schedules.find((s) => s.id === initialScheduleId) ?? schedules[0] ?? null : schedules[0] ?? null;
594
- switchScheduleIdRef.current = null;
595
- setSchedule(target);
596
- setLoading(false);
597
- if (notifyOnConnect && target && !isSwitching) {
598
- window.parent.postMessage({
599
- type: "ow:schedule-connected",
600
- schedule: { id: target.id, name: target.name },
601
- insertAfter
602
- }, "*");
603
- window.postMessage({ type: "ow:schedule-linked", scheduleId: target.id, insertAfter }, "*");
604
- }
605
- };
606
- window.addEventListener("message", handler);
607
- if (!startEmpty) window.parent.postMessage({ type: "ow:request-user-schedules", insertAfter }, "*");
608
- return () => {
609
- window.removeEventListener("message", handler);
610
- if (timer) clearTimeout(timer);
611
- };
612
- }
613
- if (initialScheduleId === null) {
614
- setLoading(false);
615
- return;
616
- }
617
- ;
618
- (async () => {
619
- try {
620
- if (initialScheduleId) {
621
- const res = await fetch(`${API_URL}/api/schedule/id/${initialScheduleId}`);
622
- const data = await res.json();
623
- setSchedule(data?.id ? data : null);
624
- } else {
625
- const domain = getApiDomain();
626
- const sitemapRes = await fetch(`${API_URL}/api/schedule/sitemap/${domain}`);
627
- const slugs = await sitemapRes.json();
628
- if (!Array.isArray(slugs) || !slugs.length) {
629
- setLoading(false);
630
- return;
631
- }
632
- const { slug } = [...slugs].sort(
633
- (a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime()
634
- )[0];
635
- const res = await fetch(`${API_URL}/api/schedule/${domain}/${slug}`);
636
- const data = await res.json();
637
- setSchedule(data?.id ? data : null);
638
- }
639
- } catch {
640
- }
641
- setLoading(false);
642
- })();
643
- }, []);
644
- const timezoneLabel = schedule?.timezone ? (() => {
645
- try {
646
- return buildTimezoneLabel(schedule.timezone);
647
- } catch {
648
- return void 0;
649
- }
650
- })() : void 0;
651
- const handleModalSubmit = async (email) => {
652
- if (!modalState) return;
653
- const { mode, classId, classDate } = modalState;
654
- const endpoint = mode === "book" ? `${API_URL}/api/schedule/class/${classId}/booking` : `${API_URL}/api/schedule/class/${classId}/waitlist`;
655
- const res = await fetch(endpoint, {
656
- method: "POST",
657
- headers: { "Content-Type": "application/json" },
658
- body: JSON.stringify({ classDate: classDate.toISOString(), email })
659
- });
660
- if (!res.ok) {
661
- const data = await res.json().catch(() => ({}));
662
- throw new Error(data?.message ?? "Something went wrong. Please try again.");
663
- }
664
- };
665
- const handleReplaceSchedule = () => {
666
- setIsHovered(false);
667
- if (schedule) {
668
- window.parent.postMessage({
669
- type: "ow:schedule-connected",
670
- schedule: { id: schedule.id, name: schedule.name },
671
- insertAfter
672
- }, "*");
673
- } else {
674
- window.parent.postMessage({ type: "ow:scheduling-not-connected", insertAfter }, "*");
675
- }
676
- };
677
- const sectionId = `scheduling-${insertAfter}`;
678
- return /* @__PURE__ */ jsxs2(
679
- "section",
680
- {
681
- "data-ohw-section": sectionId,
682
- "data-ohw-scheduling-anchor": insertAfter,
683
- className: "w-full box-border py-10 px-5 sm:py-20 sm:px-16 font-body bg-(--color-light,#FEFFF0) relative",
684
- onMouseEnter: () => inEditor && setIsHovered(true),
685
- onMouseLeave: () => setIsHovered(false),
686
- children: [
687
- inEditor && isHovered && !!schedule && /* @__PURE__ */ jsxs2(
688
- "div",
689
- {
690
- className: "absolute inset-0 z-10 pointer-events-auto cursor-pointer",
691
- onClick: handleReplaceSchedule,
692
- children: [
693
- /* @__PURE__ */ jsx2("div", { className: "absolute inset-0", style: { background: "#0885FE", opacity: 0.18 } }),
694
- /* @__PURE__ */ jsx2("div", { className: "absolute inset-0", style: { boxShadow: "inset 0 0 0 1.5px #0885FE" } }),
695
- /* @__PURE__ */ jsx2("div", { className: "absolute inset-0 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxs2(
696
- "div",
697
- {
698
- className: "bg-white border border-[#E7E5E4] rounded-md px-3 py-1.5 flex items-center gap-1.5",
699
- style: {
700
- fontSize: 14,
701
- lineHeight: "24px",
702
- fontFamily: "'Figtree', system-ui, sans-serif",
703
- fontWeight: 500,
704
- color: "#0C0A09"
705
- },
706
- children: [
707
- /* @__PURE__ */ jsx2(CalendarFoldIcon, {}),
708
- "Replace schedule"
709
- ]
710
- }
711
- ) })
712
- ]
713
- }
714
- ),
715
- /* @__PURE__ */ jsxs2("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
716
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center gap-4", children: [
717
- /* @__PURE__ */ jsx2("h2", { className: "font-display text-4xl sm:text-5xl font-bold text-center m-0 text-(--color-dark,#200C02)", children: schedule?.name ?? "Book an appointment" }),
718
- schedule?.description && /* @__PURE__ */ jsx2("p", { className: "font-body text-body text-center m-0 text-(--color-accent,#A89B83)", children: schedule.description })
719
- ] }),
720
- /* @__PURE__ */ jsxs2("div", { className: "w-full flex flex-col items-end gap-3", children: [
721
- timezoneLabel && /* @__PURE__ */ jsx2("span", { className: "font-body text-sm font-normal text-(--color-accent,#A89B83)", children: timezoneLabel }),
722
- /* @__PURE__ */ jsx2("div", { className: "w-full p-0 sm:p-10 box-border", children: loading ? /* @__PURE__ */ jsx2(LoadingSkeleton, {}) : !schedule ? /* @__PURE__ */ jsx2(EmptyState, { inEditor }) : /* @__PURE__ */ jsx2(
723
- ScheduleView,
724
- {
725
- schedule,
726
- dates,
727
- selectedIdx,
728
- onSelectDate: setSelectedIdx,
729
- onOpenModal: inEditor ? void 0 : (mode, classId, classDate) => setModalState({ mode, classId, classDate })
730
- }
731
- ) })
732
- ] })
733
- ] }),
734
- modalState && /* @__PURE__ */ jsx2(
735
- EmailCaptureModal,
736
- {
737
- title: modalState.mode === "book" ? "Confirm your spot" : "Leave your email",
738
- subtitle: modalState.mode === "book" ? "We'll send your booking confirmation here." : "We'll let you know when spots open up!",
739
- onSubmit: handleModalSubmit,
740
- onClose: () => setModalState(null)
741
- }
742
- )
743
- ]
744
- }
745
- );
746
- }
4
+ import React4, { useCallback as useCallback2, useEffect as useEffect2, useLayoutEffect, useRef as useRef2, useState as useState3 } from "react";
747
5
 
748
6
  // src/ui/toggle-group.tsx
749
- import * as React2 from "react";
7
+ import * as React from "react";
750
8
 
751
9
  // node_modules/clsx/dist/clsx.mjs
752
10
  function r(e) {
@@ -4066,7 +3324,7 @@ var cva = (base, config) => (props) => {
4066
3324
 
4067
3325
  // src/ui/toggle.tsx
4068
3326
  import { Toggle as TogglePrimitive } from "radix-ui";
4069
- import { jsx as jsx3 } from "react/jsx-runtime";
3327
+ import { jsx } from "react/jsx-runtime";
4070
3328
  var toggleVariants = cva(
4071
3329
  "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
4072
3330
  {
@@ -4093,7 +3351,7 @@ function Toggle({
4093
3351
  size,
4094
3352
  ...props
4095
3353
  }) {
4096
- return /* @__PURE__ */ jsx3(
3354
+ return /* @__PURE__ */ jsx(
4097
3355
  TogglePrimitive.Root,
4098
3356
  {
4099
3357
  "data-slot": "toggle",
@@ -4104,8 +3362,8 @@ function Toggle({
4104
3362
  }
4105
3363
 
4106
3364
  // src/ui/toggle-group.tsx
4107
- import { jsx as jsx4 } from "react/jsx-runtime";
4108
- var ToggleGroupContext = React2.createContext({
3365
+ import { jsx as jsx2 } from "react/jsx-runtime";
3366
+ var ToggleGroupContext = React.createContext({
4109
3367
  value: "",
4110
3368
  onValueChange: () => {
4111
3369
  }
@@ -4117,13 +3375,13 @@ function ToggleGroup({
4117
3375
  children,
4118
3376
  ...props
4119
3377
  }) {
4120
- return /* @__PURE__ */ jsx4(
3378
+ return /* @__PURE__ */ jsx2(
4121
3379
  "div",
4122
3380
  {
4123
3381
  role: "group",
4124
3382
  className: cn("flex items-center gap-1 p-1 bg-muted rounded-md", className),
4125
3383
  ...props,
4126
- children: /* @__PURE__ */ jsx4(ToggleGroupContext.Provider, { value: { value, onValueChange }, children })
3384
+ children: /* @__PURE__ */ jsx2(ToggleGroupContext.Provider, { value: { value, onValueChange }, children })
4127
3385
  }
4128
3386
  );
4129
3387
  }
@@ -4133,8 +3391,8 @@ function ToggleGroupItem({
4133
3391
  children,
4134
3392
  ...props
4135
3393
  }) {
4136
- const { value: groupValue, onValueChange } = React2.useContext(ToggleGroupContext);
4137
- return /* @__PURE__ */ jsx4(
3394
+ const { value: groupValue, onValueChange } = React.useContext(ToggleGroupContext);
3395
+ return /* @__PURE__ */ jsx2(
4138
3396
  Toggle,
4139
3397
  {
4140
3398
  pressed: groupValue === value,
@@ -4263,7 +3521,10 @@ function isValidUrl(urlString) {
4263
3521
  const hostname = url.hostname;
4264
3522
  if (!hostname || hostname.length === 0) return false;
4265
3523
  if (hostname.includes(" ")) return false;
4266
- return hostname.includes(".") || hostname === "localhost";
3524
+ if (hostname === "localhost") return true;
3525
+ if (!hostname.includes(".")) return false;
3526
+ if (!/[a-z]/i.test(hostname)) return false;
3527
+ return true;
4267
3528
  } catch {
4268
3529
  return false;
4269
3530
  }
@@ -4274,12 +3535,19 @@ function normalizeUrl(value) {
4274
3535
  return `https://${trimmed}`;
4275
3536
  }
4276
3537
  function validateUrlInput(value, pages, allPages) {
4277
- if (!value.trim()) return "";
4278
- const filtered = pages.filter((p) => p.title.toLowerCase().startsWith(value.toLowerCase()));
4279
- if (filtered.length > 0) return "";
4280
- const matchingPage = allPages.find((p) => p.title.toLowerCase() === value.toLowerCase());
4281
- if (matchingPage) return "";
4282
- if (!isValidUrl(normalizeUrl(value))) {
3538
+ const trimmed = value.trim();
3539
+ if (!trimmed) return "";
3540
+ const exactPage = allPages.find((p) => p.title.toLowerCase() === trimmed.toLowerCase());
3541
+ if (exactPage) return "";
3542
+ const hasPrefixMatch = pages.some((p) => p.title.toLowerCase().startsWith(trimmed.toLowerCase()));
3543
+ if (hasPrefixMatch) {
3544
+ return "Select a page from the list or enter a valid URL";
3545
+ }
3546
+ const hasScheme = /^https?:\/\//i.test(trimmed);
3547
+ if (!hasScheme && !trimmed.includes(".")) {
3548
+ return "Please enter a valid URL (e.g., https://example.com)";
3549
+ }
3550
+ if (!isValidUrl(normalizeUrl(trimmed))) {
4283
3551
  return "Please enter a valid URL (e.g., https://example.com)";
4284
3552
  }
4285
3553
  return "";
@@ -4438,9 +3706,9 @@ function calcPopoverPos(rect, parentScroll, approxW = 483, approxH = 320) {
4438
3706
  }
4439
3707
 
4440
3708
  // src/ui/button.tsx
4441
- import * as React3 from "react";
3709
+ import * as React2 from "react";
4442
3710
  import { Slot } from "radix-ui";
4443
- import { jsx as jsx5 } from "react/jsx-runtime";
3711
+ import { jsx as jsx3 } from "react/jsx-runtime";
4444
3712
  var buttonVariants = cva(
4445
3713
  "inline-flex items-center justify-center gap-1 whitespace-nowrap rounded-md text-sm font-medium transition-colors outline-none disabled:pointer-events-none disabled:opacity-50 min-w-[80px] px-3 py-2",
4446
3714
  {
@@ -4461,10 +3729,10 @@ var buttonVariants = cva(
4461
3729
  }
4462
3730
  }
4463
3731
  );
4464
- var Button = React3.forwardRef(
3732
+ var Button = React2.forwardRef(
4465
3733
  ({ className, variant, size, asChild = false, ...props }, ref) => {
4466
3734
  const Comp = asChild ? Slot.Root : "button";
4467
- return /* @__PURE__ */ jsx5(
3735
+ return /* @__PURE__ */ jsx3(
4468
3736
  Comp,
4469
3737
  {
4470
3738
  ref,
@@ -4478,75 +3746,75 @@ var Button = React3.forwardRef(
4478
3746
  Button.displayName = "Button";
4479
3747
 
4480
3748
  // src/ui/icons.tsx
4481
- import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
3749
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
4482
3750
  function IconX({ className, ...props }) {
4483
- return /* @__PURE__ */ jsxs3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4484
- /* @__PURE__ */ jsx6("path", { d: "M18 6 6 18" }),
4485
- /* @__PURE__ */ jsx6("path", { d: "m6 6 12 12" })
3751
+ return /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
3752
+ /* @__PURE__ */ jsx4("path", { d: "M18 6 6 18" }),
3753
+ /* @__PURE__ */ jsx4("path", { d: "m6 6 12 12" })
4486
3754
  ] });
4487
3755
  }
4488
3756
  function IconChevronDown({ className, ...props }) {
4489
- return /* @__PURE__ */ jsx6("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: /* @__PURE__ */ jsx6("path", { d: "m6 9 6 6 6-6" }) });
3757
+ return /* @__PURE__ */ jsx4("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: /* @__PURE__ */ jsx4("path", { d: "m6 9 6 6 6-6" }) });
4490
3758
  }
4491
3759
  function IconFile({ className, ...props }) {
4492
- return /* @__PURE__ */ jsxs3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4493
- /* @__PURE__ */ jsx6("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
4494
- /* @__PURE__ */ jsx6("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })
3760
+ return /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
3761
+ /* @__PURE__ */ jsx4("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
3762
+ /* @__PURE__ */ jsx4("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })
4495
3763
  ] });
4496
3764
  }
4497
3765
  function IconInfo({ className, ...props }) {
4498
- return /* @__PURE__ */ jsxs3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4499
- /* @__PURE__ */ jsx6("circle", { cx: "12", cy: "12", r: "10" }),
4500
- /* @__PURE__ */ jsx6("path", { d: "M12 16v-4" }),
4501
- /* @__PURE__ */ jsx6("path", { d: "M12 8h.01" })
3766
+ return /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
3767
+ /* @__PURE__ */ jsx4("circle", { cx: "12", cy: "12", r: "10" }),
3768
+ /* @__PURE__ */ jsx4("path", { d: "M12 16v-4" }),
3769
+ /* @__PURE__ */ jsx4("path", { d: "M12 8h.01" })
4502
3770
  ] });
4503
3771
  }
4504
3772
  function IconArrowRight({ className, ...props }) {
4505
- return /* @__PURE__ */ jsxs3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4506
- /* @__PURE__ */ jsx6("path", { d: "M5 12h14" }),
4507
- /* @__PURE__ */ jsx6("path", { d: "m12 5 7 7-7 7" })
3773
+ return /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
3774
+ /* @__PURE__ */ jsx4("path", { d: "M5 12h14" }),
3775
+ /* @__PURE__ */ jsx4("path", { d: "m12 5 7 7-7 7" })
4508
3776
  ] });
4509
3777
  }
4510
3778
  function IconSection({ className, ...props }) {
4511
- return /* @__PURE__ */ jsxs3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4512
- /* @__PURE__ */ jsx6("rect", { width: "18", height: "7", x: "3", y: "3", rx: "1" }),
4513
- /* @__PURE__ */ jsx6("rect", { width: "9", height: "7", x: "3", y: "14", rx: "1" }),
4514
- /* @__PURE__ */ jsx6("rect", { width: "5", height: "7", x: "16", y: "14", rx: "1" })
3779
+ return /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
3780
+ /* @__PURE__ */ jsx4("rect", { width: "18", height: "7", x: "3", y: "3", rx: "1" }),
3781
+ /* @__PURE__ */ jsx4("rect", { width: "9", height: "7", x: "3", y: "14", rx: "1" }),
3782
+ /* @__PURE__ */ jsx4("rect", { width: "5", height: "7", x: "16", y: "14", rx: "1" })
4515
3783
  ] });
4516
3784
  }
4517
3785
 
4518
3786
  // src/ui/link-modal/DestinationBreadcrumb.tsx
4519
- import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
3787
+ import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
4520
3788
  function DestinationBreadcrumb({ pageTitle, sectionLabel }) {
4521
- return /* @__PURE__ */ jsxs4("div", { className: "flex w-full flex-col gap-2", children: [
4522
- /* @__PURE__ */ jsx7("p", { className: "text-sm font-medium text-foreground", children: "Destination" }),
4523
- /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-3", children: [
4524
- /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
4525
- /* @__PURE__ */ jsx7(IconFile, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4526
- /* @__PURE__ */ jsx7("span", { className: "text-sm font-medium leading-none text-foreground", children: pageTitle })
3789
+ return /* @__PURE__ */ jsxs2("div", { className: "flex w-full flex-col gap-2", children: [
3790
+ /* @__PURE__ */ jsx5("p", { className: "text-sm font-medium text-foreground", children: "Destination" }),
3791
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3", children: [
3792
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
3793
+ /* @__PURE__ */ jsx5(IconFile, { className: "shrink-0 text-foreground", "aria-hidden": true }),
3794
+ /* @__PURE__ */ jsx5("span", { className: "text-sm font-medium leading-none text-foreground", children: pageTitle })
4527
3795
  ] }),
4528
- /* @__PURE__ */ jsx7(IconArrowRight, { className: "shrink-0 text-muted-foreground", "aria-hidden": true }),
4529
- /* @__PURE__ */ jsxs4("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
4530
- /* @__PURE__ */ jsx7(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4531
- /* @__PURE__ */ jsx7("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
3796
+ /* @__PURE__ */ jsx5(IconArrowRight, { className: "shrink-0 text-muted-foreground", "aria-hidden": true }),
3797
+ /* @__PURE__ */ jsxs2("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
3798
+ /* @__PURE__ */ jsx5(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
3799
+ /* @__PURE__ */ jsx5("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
4532
3800
  ] })
4533
3801
  ] })
4534
3802
  ] });
4535
3803
  }
4536
3804
 
4537
3805
  // src/ui/link-modal/SectionTreeItem.tsx
4538
- import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
3806
+ import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
4539
3807
  function SectionTreeItem({ section, onSelect, selected }) {
4540
3808
  const interactive = Boolean(onSelect);
4541
- return /* @__PURE__ */ jsxs5("div", { className: "flex h-9 w-full items-end pl-3", children: [
4542
- /* @__PURE__ */ jsx8(
3809
+ return /* @__PURE__ */ jsxs3("div", { className: "flex h-9 w-full items-end pl-3", children: [
3810
+ /* @__PURE__ */ jsx6(
4543
3811
  "div",
4544
3812
  {
4545
3813
  className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
4546
3814
  "aria-hidden": true
4547
3815
  }
4548
3816
  ),
4549
- /* @__PURE__ */ jsxs5(
3817
+ /* @__PURE__ */ jsxs3(
4550
3818
  "div",
4551
3819
  {
4552
3820
  role: interactive ? "button" : void 0,
@@ -4564,8 +3832,8 @@ function SectionTreeItem({ section, onSelect, selected }) {
4564
3832
  interactive && selected && "border-primary"
4565
3833
  ),
4566
3834
  children: [
4567
- /* @__PURE__ */ jsx8(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4568
- /* @__PURE__ */ jsx8("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
3835
+ /* @__PURE__ */ jsx6(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
3836
+ /* @__PURE__ */ jsx6("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
4569
3837
  ]
4570
3838
  }
4571
3839
  )
@@ -4573,23 +3841,23 @@ function SectionTreeItem({ section, onSelect, selected }) {
4573
3841
  }
4574
3842
  function SectionPickerList({ sections, onSelect }) {
4575
3843
  if (sections.length === 0) {
4576
- return /* @__PURE__ */ jsx8("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." });
3844
+ return /* @__PURE__ */ jsx6("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." });
4577
3845
  }
4578
- return /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-1", children: [
4579
- /* @__PURE__ */ jsx8("p", { className: "text-sm text-muted-foreground", children: "Pick a section this link should scroll to." }),
4580
- sections.map((section) => /* @__PURE__ */ jsx8(SectionTreeItem, { section, onSelect }, section.id))
3846
+ return /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-1", children: [
3847
+ /* @__PURE__ */ jsx6("p", { className: "text-sm text-muted-foreground", children: "Pick a section this link should scroll to." }),
3848
+ sections.map((section) => /* @__PURE__ */ jsx6(SectionTreeItem, { section, onSelect }, section.id))
4581
3849
  ] });
4582
3850
  }
4583
3851
 
4584
3852
  // src/ui/link-modal/UrlOrPageInput.tsx
4585
- import { useId, useRef as useRef2, useState as useState3 } from "react";
3853
+ import { useId, useRef, useState } from "react";
4586
3854
 
4587
3855
  // src/ui/input.tsx
4588
- import * as React4 from "react";
4589
- import { jsx as jsx9 } from "react/jsx-runtime";
4590
- var Input = React4.forwardRef(
3856
+ import * as React3 from "react";
3857
+ import { jsx as jsx7 } from "react/jsx-runtime";
3858
+ var Input = React3.forwardRef(
4591
3859
  ({ className, type, ...props }, ref) => {
4592
- return /* @__PURE__ */ jsx9(
3860
+ return /* @__PURE__ */ jsx7(
4593
3861
  "input",
4594
3862
  {
4595
3863
  type,
@@ -4608,9 +3876,9 @@ Input.displayName = "Input";
4608
3876
 
4609
3877
  // src/ui/label.tsx
4610
3878
  import { Label as LabelPrimitive } from "radix-ui";
4611
- import { jsx as jsx10 } from "react/jsx-runtime";
3879
+ import { jsx as jsx8 } from "react/jsx-runtime";
4612
3880
  function Label({ className, ...props }) {
4613
- return /* @__PURE__ */ jsx10(
3881
+ return /* @__PURE__ */ jsx8(
4614
3882
  LabelPrimitive.Root,
4615
3883
  {
4616
3884
  "data-slot": "label",
@@ -4622,12 +3890,12 @@ function Label({ className, ...props }) {
4622
3890
 
4623
3891
  // src/ui/popover.tsx
4624
3892
  import { Popover as PopoverPrimitive } from "radix-ui";
4625
- import { jsx as jsx11 } from "react/jsx-runtime";
3893
+ import { jsx as jsx9 } from "react/jsx-runtime";
4626
3894
  function Popover({ ...props }) {
4627
- return /* @__PURE__ */ jsx11(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
3895
+ return /* @__PURE__ */ jsx9(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
4628
3896
  }
4629
3897
  function PopoverTrigger({ ...props }) {
4630
- return /* @__PURE__ */ jsx11(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
3898
+ return /* @__PURE__ */ jsx9(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
4631
3899
  }
4632
3900
  function PopoverContent({
4633
3901
  className,
@@ -4635,7 +3903,7 @@ function PopoverContent({
4635
3903
  sideOffset = 6,
4636
3904
  ...props
4637
3905
  }) {
4638
- return /* @__PURE__ */ jsx11(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx11(
3906
+ return /* @__PURE__ */ jsx9(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx9(
4639
3907
  PopoverPrimitive.Content,
4640
3908
  {
4641
3909
  "data-slot": "popover-content",
@@ -4651,9 +3919,9 @@ function PopoverContent({
4651
3919
  }
4652
3920
 
4653
3921
  // src/ui/link-modal/UrlOrPageInput.tsx
4654
- import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
3922
+ import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
4655
3923
  function FieldChevron({ onClick }) {
4656
- return /* @__PURE__ */ jsx12(
3924
+ return /* @__PURE__ */ jsx10(
4657
3925
  "button",
4658
3926
  {
4659
3927
  type: "button",
@@ -4661,7 +3929,7 @@ function FieldChevron({ onClick }) {
4661
3929
  onClick,
4662
3930
  "aria-label": "Open page list",
4663
3931
  tabIndex: -1,
4664
- children: /* @__PURE__ */ jsx12(IconChevronDown, {})
3932
+ children: /* @__PURE__ */ jsx10(IconChevronDown, {})
4665
3933
  }
4666
3934
  );
4667
3935
  }
@@ -4678,8 +3946,8 @@ function UrlOrPageInput({
4678
3946
  urlError
4679
3947
  }) {
4680
3948
  const inputId = useId();
4681
- const inputRef = useRef2(null);
4682
- const [isFocused, setIsFocused] = useState3(false);
3949
+ const inputRef = useRef(null);
3950
+ const [isFocused, setIsFocused] = useState(false);
4683
3951
  const openDropdown = () => {
4684
3952
  if (readOnly || filteredPages.length === 0) return;
4685
3953
  onDropdownOpenChange(true);
@@ -4700,12 +3968,12 @@ function UrlOrPageInput({
4700
3968
  "data-ohw-link-field flex h-10 w-full items-center overflow-hidden rounded-md border bg-background pl-3 pr-3 py-2 outline-none transition-[border-color,box-shadow]",
4701
3969
  urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
4702
3970
  );
4703
- return /* @__PURE__ */ jsxs6("div", { className: "flex w-full flex-col gap-2 p-0", children: [
4704
- /* @__PURE__ */ jsx12(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
4705
- /* @__PURE__ */ jsxs6(Popover, { open: dropdownOpen && !readOnly, onOpenChange: onDropdownOpenChange, children: [
4706
- /* @__PURE__ */ jsx12(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs6("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
4707
- selectedPage ? /* @__PURE__ */ jsx12("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ jsx12(IconFile, { className: "text-foreground", "aria-hidden": true }) }) : null,
4708
- readOnly ? /* @__PURE__ */ jsx12("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ jsx12(
3971
+ return /* @__PURE__ */ jsxs4("div", { className: "flex w-full flex-col gap-2 p-0", children: [
3972
+ /* @__PURE__ */ jsx10(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
3973
+ /* @__PURE__ */ jsxs4(Popover, { open: dropdownOpen && !readOnly, onOpenChange: onDropdownOpenChange, children: [
3974
+ /* @__PURE__ */ jsx10(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs4("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
3975
+ selectedPage ? /* @__PURE__ */ jsx10("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ jsx10(IconFile, { className: "text-foreground", "aria-hidden": true }) }) : null,
3976
+ readOnly ? /* @__PURE__ */ jsx10("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ jsx10(
4709
3977
  Input,
4710
3978
  {
4711
3979
  ref: inputRef,
@@ -4724,7 +3992,7 @@ function UrlOrPageInput({
4724
3992
  )
4725
3993
  }
4726
3994
  ),
4727
- selectedPage && !readOnly ? /* @__PURE__ */ jsx12(
3995
+ selectedPage && !readOnly ? /* @__PURE__ */ jsx10(
4728
3996
  "button",
4729
3997
  {
4730
3998
  type: "button",
@@ -4732,31 +4000,31 @@ function UrlOrPageInput({
4732
4000
  onMouseDown: clearSelection,
4733
4001
  "aria-label": "Clear selected page",
4734
4002
  tabIndex: -1,
4735
- children: /* @__PURE__ */ jsx12(IconX, { "aria-hidden": true })
4003
+ children: /* @__PURE__ */ jsx10(IconX, { "aria-hidden": true })
4736
4004
  }
4737
4005
  ) : null,
4738
- !readOnly ? /* @__PURE__ */ jsx12(FieldChevron, { onClick: toggleDropdown }) : null
4006
+ !readOnly ? /* @__PURE__ */ jsx10(FieldChevron, { onClick: toggleDropdown }) : null
4739
4007
  ] }) }),
4740
- filteredPages.length > 0 && /* @__PURE__ */ jsx12(PopoverContent, { "data-ohw-link-popover-root": "", onOpenAutoFocus: (e) => e.preventDefault(), children: filteredPages.map((page) => /* @__PURE__ */ jsxs6(
4008
+ filteredPages.length > 0 && /* @__PURE__ */ jsx10(PopoverContent, { "data-ohw-link-popover-root": "", onOpenAutoFocus: (e) => e.preventDefault(), children: filteredPages.map((page) => /* @__PURE__ */ jsxs4(
4741
4009
  "button",
4742
4010
  {
4743
4011
  type: "button",
4744
4012
  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",
4745
4013
  onClick: () => onPageSelect(page),
4746
4014
  children: [
4747
- /* @__PURE__ */ jsx12(IconFile, { className: "shrink-0", "aria-hidden": true }),
4748
- /* @__PURE__ */ jsx12("span", { className: "truncate", children: page.title })
4015
+ /* @__PURE__ */ jsx10(IconFile, { className: "shrink-0", "aria-hidden": true }),
4016
+ /* @__PURE__ */ jsx10("span", { className: "truncate", children: page.title })
4749
4017
  ]
4750
4018
  },
4751
4019
  page.path
4752
4020
  )) })
4753
4021
  ] }),
4754
- urlError ? /* @__PURE__ */ jsx12("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
4022
+ urlError ? /* @__PURE__ */ jsx10("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
4755
4023
  ] });
4756
4024
  }
4757
4025
 
4758
4026
  // src/ui/link-modal/useLinkModalState.ts
4759
- import { useCallback, useEffect as useEffect2, useMemo as useMemo2, useState as useState4 } from "react";
4027
+ import { useCallback, useEffect, useMemo, useState as useState2 } from "react";
4760
4028
  function useLinkModalState({
4761
4029
  open,
4762
4030
  mode,
@@ -4768,16 +4036,16 @@ function useLinkModalState({
4768
4036
  onClose,
4769
4037
  onSubmit
4770
4038
  }) {
4771
- const availablePages = useMemo2(
4039
+ const availablePages = useMemo(
4772
4040
  () => mode === "create" ? filterAvailablePages(pages, existingTargets) : pages,
4773
4041
  [mode, pages, existingTargets]
4774
4042
  );
4775
- const [searchValue, setSearchValue] = useState4("");
4776
- const [selectedPage, setSelectedPage] = useState4(null);
4777
- const [selectedSection, setSelectedSection] = useState4(null);
4778
- const [step, setStep] = useState4("input");
4779
- const [dropdownOpen, setDropdownOpen] = useState4(false);
4780
- const [urlError, setUrlError] = useState4("");
4043
+ const [searchValue, setSearchValue] = useState2("");
4044
+ const [selectedPage, setSelectedPage] = useState2(null);
4045
+ const [selectedSection, setSelectedSection] = useState2(null);
4046
+ const [step, setStep] = useState2("input");
4047
+ const [dropdownOpen, setDropdownOpen] = useState2(false);
4048
+ const [urlError, setUrlError] = useState2("");
4781
4049
  const reset = useCallback(() => {
4782
4050
  setSearchValue("");
4783
4051
  setSelectedPage(null);
@@ -4786,7 +4054,7 @@ function useLinkModalState({
4786
4054
  setDropdownOpen(false);
4787
4055
  setUrlError("");
4788
4056
  }, []);
4789
- useEffect2(() => {
4057
+ useEffect(() => {
4790
4058
  if (!open) return;
4791
4059
  if (mode === "edit" && initialTarget) {
4792
4060
  const { pageRoute } = parseTarget(initialTarget);
@@ -4802,11 +4070,11 @@ function useLinkModalState({
4802
4070
  setDropdownOpen(false);
4803
4071
  setUrlError("");
4804
4072
  }, [open, mode, initialTarget, pages, sectionsByPath, reset]);
4805
- const filteredPages = useMemo2(() => {
4073
+ const filteredPages = useMemo(() => {
4806
4074
  if (!searchValue.trim()) return availablePages;
4807
4075
  return availablePages.filter((p) => p.title.toLowerCase().startsWith(searchValue.toLowerCase()));
4808
4076
  }, [availablePages, searchValue]);
4809
- const activeSections = useMemo2(() => {
4077
+ const activeSections = useMemo(() => {
4810
4078
  if (!selectedPage) return [];
4811
4079
  return getSectionsForPath(sectionsByPath, selectedPage.path);
4812
4080
  }, [selectedPage, sectionsByPath]);
@@ -4822,9 +4090,8 @@ function useLinkModalState({
4822
4090
  setUrlError("");
4823
4091
  const filtered = value.trim() ? availablePages.filter((p) => p.title.toLowerCase().startsWith(value.toLowerCase())) : availablePages;
4824
4092
  setDropdownOpen(filtered.length > 0);
4825
- if (value.trim() && filtered.length === 0) {
4826
- const error = validateUrlInput(value, availablePages, pages);
4827
- if (error) setUrlError(error);
4093
+ if (value.trim()) {
4094
+ setUrlError(validateUrlInput(value, availablePages, pages));
4828
4095
  }
4829
4096
  };
4830
4097
  const handlePageSelect = (page) => {
@@ -4853,7 +4120,7 @@ function useLinkModalState({
4853
4120
  reset();
4854
4121
  onClose();
4855
4122
  };
4856
- const isValid = useMemo2(() => {
4123
+ const isValid = useMemo(() => {
4857
4124
  if (urlError) return false;
4858
4125
  if (showBreadcrumb) return true;
4859
4126
  if (selectedPage) return true;
@@ -4920,7 +4187,7 @@ function useLinkModalState({
4920
4187
  }
4921
4188
 
4922
4189
  // src/ui/link-modal/LinkEditorPanel.tsx
4923
- import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
4190
+ import { Fragment, jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
4924
4191
  function LinkEditorPanel({
4925
4192
  open = true,
4926
4193
  mode = "create",
@@ -4944,26 +4211,26 @@ function LinkEditorPanel({
4944
4211
  onSubmit
4945
4212
  });
4946
4213
  const isCancel = state.secondaryLabel === "Cancel";
4947
- return /* @__PURE__ */ jsxs7(Fragment2, { children: [
4948
- /* @__PURE__ */ jsx13(
4214
+ return /* @__PURE__ */ jsxs5(Fragment, { children: [
4215
+ /* @__PURE__ */ jsx11(
4949
4216
  "button",
4950
4217
  {
4951
4218
  type: "button",
4952
4219
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
4953
4220
  onClick: state.handleClose,
4954
4221
  "aria-label": "Close",
4955
- children: /* @__PURE__ */ jsx13(IconX, { "aria-hidden": true })
4222
+ children: /* @__PURE__ */ jsx11(IconX, { "aria-hidden": true })
4956
4223
  }
4957
4224
  ),
4958
- /* @__PURE__ */ jsx13("header", { className: "flex w-full flex-col gap-1.5 p-6 pr-12", children: /* @__PURE__ */ jsx13("h2", { className: "m-0 w-full break-words text-lg font-semibold leading-none tracking-tight text-card-foreground", children: state.title }) }),
4959
- /* @__PURE__ */ jsxs7("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
4960
- state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ jsx13(
4225
+ /* @__PURE__ */ jsx11("header", { className: "flex w-full flex-col gap-1.5 p-6 pr-12", children: /* @__PURE__ */ jsx11("h2", { className: "m-0 w-full break-words text-lg font-semibold leading-none tracking-tight text-card-foreground", children: state.title }) }),
4226
+ /* @__PURE__ */ jsxs5("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
4227
+ state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ jsx11(
4961
4228
  DestinationBreadcrumb,
4962
4229
  {
4963
4230
  pageTitle: state.selectedPage.title,
4964
4231
  sectionLabel: state.selectedSection.label
4965
4232
  }
4966
- ) : /* @__PURE__ */ jsx13(
4233
+ ) : /* @__PURE__ */ jsx11(
4967
4234
  UrlOrPageInput,
4968
4235
  {
4969
4236
  value: state.searchValue,
@@ -4976,18 +4243,18 @@ function LinkEditorPanel({
4976
4243
  urlError: state.urlError
4977
4244
  }
4978
4245
  ),
4979
- state.showChooseSection ? /* @__PURE__ */ jsxs7("div", { className: "flex flex-col justify-center gap-2", children: [
4980
- /* @__PURE__ */ jsx13(Button, { type: "button", variant: "outline", className: "w-fit cursor-pointer", size: "sm", onClick: state.handleChooseSection, children: "Choose a section" }),
4981
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
4982
- /* @__PURE__ */ jsx13(IconInfo, { className: "shrink-0", "aria-hidden": true }),
4983
- /* @__PURE__ */ jsx13("span", { children: "Pick a section this link should scroll to." })
4246
+ state.showChooseSection ? /* @__PURE__ */ jsxs5("div", { className: "flex flex-col justify-center gap-2", children: [
4247
+ /* @__PURE__ */ jsx11(Button, { type: "button", variant: "outline", className: "w-fit cursor-pointer", size: "sm", onClick: state.handleChooseSection, children: "Choose a section" }),
4248
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
4249
+ /* @__PURE__ */ jsx11(IconInfo, { className: "shrink-0", "aria-hidden": true }),
4250
+ /* @__PURE__ */ jsx11("span", { children: "Pick a section this link should scroll to." })
4984
4251
  ] })
4985
4252
  ] }) : null,
4986
- state.showSectionPicker ? /* @__PURE__ */ jsx13(SectionPickerList, { sections: state.activeSections, onSelect: state.handleSectionSelect }) : null,
4987
- state.showSectionRow && state.selectedSection ? /* @__PURE__ */ jsx13(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
4253
+ state.showSectionPicker ? /* @__PURE__ */ jsx11(SectionPickerList, { sections: state.activeSections, onSelect: state.handleSectionSelect }) : null,
4254
+ state.showSectionRow && state.selectedSection ? /* @__PURE__ */ jsx11(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
4988
4255
  ] }),
4989
- /* @__PURE__ */ jsxs7("footer", { className: "flex w-full items-center justify-end gap-2 px-6 pb-6", children: [
4990
- /* @__PURE__ */ jsx13(
4256
+ /* @__PURE__ */ jsxs5("footer", { className: "flex w-full items-center justify-end gap-2 px-6 pb-6", children: [
4257
+ /* @__PURE__ */ jsx11(
4991
4258
  Button,
4992
4259
  {
4993
4260
  type: "button",
@@ -5002,7 +4269,7 @@ function LinkEditorPanel({
5002
4269
  children: state.secondaryLabel
5003
4270
  }
5004
4271
  ),
5005
- /* @__PURE__ */ jsx13(
4272
+ /* @__PURE__ */ jsx11(
5006
4273
  Button,
5007
4274
  {
5008
4275
  type: "button",
@@ -5021,7 +4288,7 @@ function LinkEditorPanel({
5021
4288
  }
5022
4289
 
5023
4290
  // src/ui/link-modal/LinkPopover.tsx
5024
- import { jsx as jsx14 } from "react/jsx-runtime";
4291
+ import { jsx as jsx12 } from "react/jsx-runtime";
5025
4292
  function LinkPopover({
5026
4293
  rect,
5027
4294
  parentScroll,
@@ -5029,7 +4296,7 @@ function LinkPopover({
5029
4296
  ...editorProps
5030
4297
  }) {
5031
4298
  const { top, left, transform } = calcPopoverPos(rect, parentScroll);
5032
- return /* @__PURE__ */ jsx14(
4299
+ return /* @__PURE__ */ jsx12(
5033
4300
  "div",
5034
4301
  {
5035
4302
  ref: panelRef,
@@ -5042,7 +4309,7 @@ function LinkPopover({
5042
4309
  ),
5043
4310
  style: { top, left, transform },
5044
4311
  onMouseDown: (e) => e.stopPropagation(),
5045
- children: /* @__PURE__ */ jsx14(LinkEditorPanel, { ...editorProps, open: true })
4312
+ children: /* @__PURE__ */ jsx12(LinkEditorPanel, { ...editorProps, open: true })
5046
4313
  }
5047
4314
  );
5048
4315
  }
@@ -5105,30 +4372,8 @@ function shouldUseDevFixtures() {
5105
4372
  return new URLSearchParams(q).get("ohw-fixtures") === "1";
5106
4373
  }
5107
4374
 
5108
- // src/ui/badge.tsx
5109
- import { jsx as jsx15 } from "react/jsx-runtime";
5110
- var badgeVariants = cva(
5111
- "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",
5112
- {
5113
- variants: {
5114
- variant: {
5115
- default: "border-transparent bg-primary text-primary-foreground",
5116
- secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
5117
- destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
5118
- outline: "text-foreground"
5119
- }
5120
- },
5121
- defaultVariants: {
5122
- variant: "default"
5123
- }
5124
- }
5125
- );
5126
- function Badge({ className, variant, ...props }) {
5127
- return /* @__PURE__ */ jsx15("div", { className: cn(badgeVariants({ variant }), className), ...props });
5128
- }
5129
-
5130
4375
  // src/OhhwellsBridge.tsx
5131
- import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs8 } from "react/jsx-runtime";
4376
+ import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
5132
4377
  var PRIMARY = "#0885FE";
5133
4378
  var IMAGE_FADE_MS = 300;
5134
4379
  function runOpacityFade(el, onDone) {
@@ -5179,163 +4424,6 @@ function fadeInBgImage(el, url, onReady) {
5179
4424
  if (!prevPos || prevPos === "static") el.style.position = prevPos;
5180
4425
  });
5181
4426
  }
5182
- function getSectionsTracker() {
5183
- let el = document.querySelector("[data-ohw-sections-tracker]");
5184
- if (!el) {
5185
- el = document.createElement("div");
5186
- el.setAttribute("data-ohw-sections-tracker", "");
5187
- el.style.display = "none";
5188
- document.body.appendChild(el);
5189
- }
5190
- return el;
5191
- }
5192
- function updateSectionScheduleId(insertAfter, scheduleId) {
5193
- const tracker = getSectionsTracker();
5194
- let sections = [];
5195
- try {
5196
- sections = JSON.parse(tracker.textContent || "[]");
5197
- } catch {
5198
- }
5199
- const currentPath = window.location.pathname;
5200
- const updated = sections.map((s) => {
5201
- if (s.type !== "scheduling" || s.insertAfter !== insertAfter) return s;
5202
- if (s.pagePath && s.pagePath !== currentPath) return s;
5203
- return { ...s, scheduleId };
5204
- });
5205
- tracker.textContent = JSON.stringify(updated);
5206
- return tracker.textContent ?? "[]";
5207
- }
5208
- function schedulingSectionId(insertAfter) {
5209
- return `scheduling-${insertAfter}`;
5210
- }
5211
- var INSERT_BEFORE_MARKER = ":before:";
5212
- function parseSchedulingInsertAfter(insertAfter) {
5213
- const idx = insertAfter.indexOf(INSERT_BEFORE_MARKER);
5214
- if (idx < 0) return { anchor: insertAfter, insertBefore: null };
5215
- return {
5216
- anchor: insertAfter.slice(0, idx),
5217
- insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
5218
- };
5219
- }
5220
- function resolveSchedulingInsert(insertAfter, explicitInsertBefore) {
5221
- const parsed = parseSchedulingInsertAfter(insertAfter);
5222
- const insertBefore = explicitInsertBefore ?? parsed.insertBefore;
5223
- const effectiveInsertAfter = insertBefore && parsed.insertBefore === null ? `${insertAfter}${INSERT_BEFORE_MARKER}${insertBefore}` : insertAfter;
5224
- return { effectiveInsertAfter, insertBefore };
5225
- }
5226
- function getSchedulingMountPoint(insertAfter) {
5227
- const { anchor } = parseSchedulingInsertAfter(insertAfter);
5228
- let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
5229
- if (!anchorEl && anchor === "scheduling") {
5230
- const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
5231
- anchorEl = widgets.at(-1) ?? null;
5232
- }
5233
- if (!anchorEl) return null;
5234
- return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
5235
- }
5236
- function schedulingMountDepth(insertAfter) {
5237
- if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
5238
- return insertAfter.split(INSERT_BEFORE_MARKER).length - 1;
5239
- }
5240
- function getPageSchedulingEntries(raw) {
5241
- if (!raw) return [];
5242
- try {
5243
- const entries = JSON.parse(raw);
5244
- const currentPath = window.location.pathname;
5245
- return entries.filter((e) => e.type === "scheduling" && (!e.pagePath || e.pagePath === currentPath));
5246
- } catch {
5247
- return [];
5248
- }
5249
- }
5250
- function isSchedulingWidgetMissing(entry) {
5251
- const { effectiveInsertAfter } = resolveSchedulingInsert(entry.insertAfter);
5252
- return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
5253
- }
5254
- function hasMissingSchedulingWidgets(entries) {
5255
- return entries.some(isSchedulingWidgetMissing);
5256
- }
5257
- function retryMissingSchedulingMounts(entries, notifyOnConnect = false) {
5258
- if (!hasMissingSchedulingWidgets(entries)) return;
5259
- mountSchedulingEntries(entries, notifyOnConnect);
5260
- }
5261
- function initSectionsFromContent(content, removeExisting = false) {
5262
- const raw = content["__ohw_sections"];
5263
- if (!raw) return;
5264
- try {
5265
- if (removeExisting) {
5266
- document.querySelectorAll('[data-ohw-section-container="scheduling"]').forEach((el) => el.remove());
5267
- }
5268
- const inEditor = typeof window !== "undefined" && window.self !== window.top;
5269
- if (inEditor) getSectionsTracker().textContent = raw;
5270
- const pageEntries = getPageSchedulingEntries(raw);
5271
- mountSchedulingEntries(pageEntries, false);
5272
- requestAnimationFrame(() => retryMissingSchedulingMounts(pageEntries, false));
5273
- setTimeout(() => retryMissingSchedulingMounts(pageEntries, false), 250);
5274
- } catch {
5275
- }
5276
- }
5277
- function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId, explicitInsertBefore) {
5278
- const { effectiveInsertAfter, insertBefore } = resolveSchedulingInsert(insertAfter, explicitInsertBefore);
5279
- const sectionId = schedulingSectionId(effectiveInsertAfter);
5280
- if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
5281
- const mountPoint = getSchedulingMountPoint(effectiveInsertAfter);
5282
- if (!mountPoint) return false;
5283
- const container = document.createElement("div");
5284
- container.dataset.ohwSectionContainer = "scheduling";
5285
- if (insertBefore) {
5286
- const beforeAnchor = document.querySelector(`[data-ohw-section="${insertBefore}"]`);
5287
- const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
5288
- if (!beforePoint) return false;
5289
- beforePoint.insertAdjacentElement("beforebegin", container);
5290
- } else {
5291
- let tail = mountPoint;
5292
- while (tail.nextElementSibling?.dataset.ohwSectionContainer === "scheduling") {
5293
- tail = tail.nextElementSibling;
5294
- }
5295
- tail.insertAdjacentElement("afterend", container);
5296
- }
5297
- const root = createRoot(container);
5298
- flushSync(() => {
5299
- root.render(
5300
- /* @__PURE__ */ jsx16(
5301
- SchedulingWidget,
5302
- {
5303
- notifyOnConnect,
5304
- initialScheduleId: scheduleId,
5305
- insertAfter: effectiveInsertAfter
5306
- }
5307
- )
5308
- );
5309
- });
5310
- const tracker = getSectionsTracker();
5311
- let sections = [];
5312
- try {
5313
- sections = JSON.parse(tracker.textContent || "[]");
5314
- } catch {
5315
- }
5316
- const inEditor = typeof window !== "undefined" && window.self !== window.top;
5317
- if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === effectiveInsertAfter)) {
5318
- sections.push({
5319
- type: "scheduling",
5320
- insertAfter: effectiveInsertAfter,
5321
- pagePath: window.location.pathname,
5322
- ...scheduleId ? { scheduleId } : {}
5323
- });
5324
- tracker.textContent = JSON.stringify(sections);
5325
- }
5326
- return true;
5327
- }
5328
- function mountSchedulingEntries(entries, notifyOnConnect = false) {
5329
- const pending = entries.filter((e) => e.type === "scheduling").sort((a, b) => schedulingMountDepth(a.insertAfter) - schedulingMountDepth(b.insertAfter));
5330
- for (let attempt = 0; attempt < pending.length + 1 && pending.length > 0; attempt++) {
5331
- for (let i = pending.length - 1; i >= 0; i--) {
5332
- const { insertAfter, scheduleId } = pending[i];
5333
- if (mountSchedulingWidget(insertAfter, notifyOnConnect, scheduleId)) {
5334
- pending.splice(i, 1);
5335
- }
5336
- }
5337
- }
5338
- }
5339
4427
  function getLinkHref(el) {
5340
4428
  const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
5341
4429
  return anchor?.getAttribute("href") ?? "";
@@ -5535,7 +4623,7 @@ var TOOLBAR_GROUPS = [
5535
4623
  ];
5536
4624
  function GlowFrame({ rect, elRef }) {
5537
4625
  const GAP = 6;
5538
- return /* @__PURE__ */ jsx16(
4626
+ return /* @__PURE__ */ jsx13(
5539
4627
  "div",
5540
4628
  {
5541
4629
  ref: elRef,
@@ -5588,7 +4676,7 @@ function FloatingToolbar({
5588
4676
  onEditLink
5589
4677
  }) {
5590
4678
  const { top, left, transform } = calcToolbarPos(rect, parentScroll);
5591
- return /* @__PURE__ */ jsxs8(
4679
+ return /* @__PURE__ */ jsxs6(
5592
4680
  "div",
5593
4681
  {
5594
4682
  ref: elRef,
@@ -5613,11 +4701,11 @@ function FloatingToolbar({
5613
4701
  },
5614
4702
  onMouseDown: (e) => e.stopPropagation(),
5615
4703
  children: [
5616
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs8(React5.Fragment, { children: [
5617
- gi > 0 && /* @__PURE__ */ jsx16("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
4704
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs6(React4.Fragment, { children: [
4705
+ gi > 0 && /* @__PURE__ */ jsx13("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
5618
4706
  btns.map((btn) => {
5619
4707
  const isActive = activeCommands.has(btn.cmd);
5620
- return /* @__PURE__ */ jsx16(
4708
+ return /* @__PURE__ */ jsx13(
5621
4709
  "button",
5622
4710
  {
5623
4711
  title: btn.title,
@@ -5643,7 +4731,7 @@ function FloatingToolbar({
5643
4731
  flexShrink: 0,
5644
4732
  padding: 6
5645
4733
  },
5646
- children: /* @__PURE__ */ jsx16(
4734
+ children: /* @__PURE__ */ jsx13(
5647
4735
  "svg",
5648
4736
  {
5649
4737
  width: "16",
@@ -5663,7 +4751,7 @@ function FloatingToolbar({
5663
4751
  );
5664
4752
  })
5665
4753
  ] }, gi)),
5666
- showEditLink ? /* @__PURE__ */ jsx16(
4754
+ showEditLink ? /* @__PURE__ */ jsx13(
5667
4755
  "button",
5668
4756
  {
5669
4757
  type: "button",
@@ -5695,9 +4783,9 @@ function FloatingToolbar({
5695
4783
  flexShrink: 0,
5696
4784
  padding: 6
5697
4785
  },
5698
- children: /* @__PURE__ */ jsxs8("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5699
- /* @__PURE__ */ jsx16("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
5700
- /* @__PURE__ */ jsx16("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
4786
+ children: /* @__PURE__ */ jsxs6("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
4787
+ /* @__PURE__ */ jsx13("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
4788
+ /* @__PURE__ */ jsx13("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
5701
4789
  ] })
5702
4790
  }
5703
4791
  ) : null
@@ -5715,7 +4803,7 @@ function StateToggle({
5715
4803
  states,
5716
4804
  onStateChange
5717
4805
  }) {
5718
- return /* @__PURE__ */ jsx16(
4806
+ return /* @__PURE__ */ jsx13(
5719
4807
  ToggleGroup,
5720
4808
  {
5721
4809
  "data-ohw-state-toggle": "",
@@ -5729,35 +4817,18 @@ function StateToggle({
5729
4817
  left: rect.right - 8,
5730
4818
  transform: "translateX(-100%)"
5731
4819
  },
5732
- children: states.map((state) => /* @__PURE__ */ jsx16(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
4820
+ children: states.map((state) => /* @__PURE__ */ jsx13(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
5733
4821
  }
5734
4822
  );
5735
4823
  }
5736
4824
  var contentCache = /* @__PURE__ */ new Map();
5737
- function resolveSubdomain(subdomainFromQuery) {
5738
- if (subdomainFromQuery) return subdomainFromQuery;
5739
- if (typeof window !== "undefined") {
5740
- const parts = window.location.hostname.split(".");
5741
- if (parts.length >= 3 && parts[0] !== "www") return parts[0];
5742
- }
5743
- const siteUrl = process.env.NEXT_PUBLIC_SITE_URL;
5744
- if (siteUrl) {
5745
- try {
5746
- const host = new URL(siteUrl).hostname;
5747
- const siteParts = host.split(".");
5748
- if (siteParts.length >= 3 && siteParts[0] !== "www") return siteParts[0];
5749
- } catch {
5750
- }
5751
- }
5752
- return "";
5753
- }
5754
4825
  function OhhwellsBridge() {
5755
4826
  const pathname = usePathname();
5756
4827
  const router = useRouter();
5757
4828
  const searchParams = useSearchParams();
5758
4829
  const isEditMode = isEditSessionActive();
5759
- const [bridgeRoot, setBridgeRoot] = useState5(null);
5760
- useEffect3(() => {
4830
+ const [bridgeRoot, setBridgeRoot] = useState3(null);
4831
+ useEffect2(() => {
5761
4832
  const figtreeFontId = "ohw-figtree-font";
5762
4833
  if (!document.getElementById(figtreeFontId)) {
5763
4834
  const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
@@ -5780,47 +4851,50 @@ function OhhwellsBridge() {
5780
4851
  };
5781
4852
  }, []);
5782
4853
  const subdomainFromQuery = searchParams.get("subdomain");
5783
- const subdomain = resolveSubdomain(subdomainFromQuery);
4854
+ const subdomain = subdomainFromQuery ?? (() => {
4855
+ if (typeof window === "undefined") return "";
4856
+ const parts = window.location.hostname.split(".");
4857
+ return parts.length >= 3 && parts[0] !== "www" ? parts[0] : "";
4858
+ })();
5784
4859
  const postToParent = useCallback2((data) => {
5785
4860
  if (typeof window !== "undefined" && window.parent !== window) {
5786
4861
  window.parent.postMessage(data, "*");
5787
4862
  }
5788
4863
  }, []);
5789
- const [fetchState, setFetchState] = useState5("idle");
5790
- const autoSaveTimers = useRef3(/* @__PURE__ */ new Map());
5791
- const activeElRef = useRef3(null);
5792
- const originalContentRef = useRef3(null);
5793
- const activeStateElRef = useRef3(null);
5794
- const parentScrollRef = useRef3(null);
5795
- const toolbarElRef = useRef3(null);
5796
- const glowElRef = useRef3(null);
5797
- const hoveredImageRef = useRef3(null);
5798
- const hoveredImageHasTextOverlapRef = useRef3(false);
5799
- const hoveredGapRef = useRef3(null);
5800
- const imageUnhoverTimerRef = useRef3(null);
5801
- const imageShowTimerRef = useRef3(null);
5802
- const editStylesRef = useRef3(null);
5803
- const activateRef = useRef3(() => {
4864
+ const [fetchState, setFetchState] = useState3("idle");
4865
+ const autoSaveTimers = useRef2(/* @__PURE__ */ new Map());
4866
+ const activeElRef = useRef2(null);
4867
+ const originalContentRef = useRef2(null);
4868
+ const activeStateElRef = useRef2(null);
4869
+ const parentScrollRef = useRef2(null);
4870
+ const toolbarElRef = useRef2(null);
4871
+ const glowElRef = useRef2(null);
4872
+ const hoveredImageRef = useRef2(null);
4873
+ const hoveredImageHasTextOverlapRef = useRef2(false);
4874
+ const imageUnhoverTimerRef = useRef2(null);
4875
+ const imageShowTimerRef = useRef2(null);
4876
+ const editStylesRef = useRef2(null);
4877
+ const activateRef = useRef2(() => {
5804
4878
  });
5805
- const deactivateRef = useRef3(() => {
4879
+ const deactivateRef = useRef2(() => {
5806
4880
  });
5807
- const refreshActiveCommandsRef = useRef3(() => {
4881
+ const refreshActiveCommandsRef = useRef2(() => {
5808
4882
  });
5809
- const postToParentRef = useRef3(postToParent);
4883
+ const postToParentRef = useRef2(postToParent);
5810
4884
  postToParentRef.current = postToParent;
5811
- const [toolbarRect, setToolbarRect] = useState5(null);
5812
- const [toggleState, setToggleState] = useState5(null);
5813
- const [maxBadge, setMaxBadge] = useState5(null);
5814
- const [activeCommands, setActiveCommands] = useState5(/* @__PURE__ */ new Set());
5815
- const [toolbarShowEditLink, setToolbarShowEditLink] = useState5(false);
5816
- const [linkPopover, setLinkPopover] = useState5(null);
5817
- const [sitePages, setSitePages] = useState5([]);
5818
- const [sectionsByPath, setSectionsByPath] = useState5({});
5819
- const sectionsPrefetchGenRef = useRef3(0);
5820
- const setLinkPopoverRef = useRef3(setLinkPopover);
5821
- const linkPopoverPanelRef = useRef3(null);
5822
- const linkPopoverOpenRef = useRef3(false);
5823
- const linkPopoverGraceUntilRef = useRef3(0);
4885
+ const [toolbarRect, setToolbarRect] = useState3(null);
4886
+ const [toggleState, setToggleState] = useState3(null);
4887
+ const [maxBadge, setMaxBadge] = useState3(null);
4888
+ const [activeCommands, setActiveCommands] = useState3(/* @__PURE__ */ new Set());
4889
+ const [toolbarShowEditLink, setToolbarShowEditLink] = useState3(false);
4890
+ const [linkPopover, setLinkPopover] = useState3(null);
4891
+ const [sitePages, setSitePages] = useState3([]);
4892
+ const [sectionsByPath, setSectionsByPath] = useState3({});
4893
+ const sectionsPrefetchGenRef = useRef2(0);
4894
+ const setLinkPopoverRef = useRef2(setLinkPopover);
4895
+ const linkPopoverPanelRef = useRef2(null);
4896
+ const linkPopoverOpenRef = useRef2(false);
4897
+ const linkPopoverGraceUntilRef = useRef2(0);
5824
4898
  setLinkPopoverRef.current = setLinkPopover;
5825
4899
  const bumpLinkPopoverGrace = () => {
5826
4900
  linkPopoverGraceUntilRef.current = Date.now() + 350;
@@ -5844,9 +4918,9 @@ function OhhwellsBridge() {
5844
4918
  );
5845
4919
  });
5846
4920
  }, [isEditMode, pathname]);
5847
- const runSectionsPrefetchRef = useRef3(runSectionsPrefetch);
4921
+ const runSectionsPrefetchRef = useRef2(runSectionsPrefetch);
5848
4922
  runSectionsPrefetchRef.current = runSectionsPrefetch;
5849
- useEffect3(() => {
4923
+ useEffect2(() => {
5850
4924
  if (!linkPopover) return;
5851
4925
  if (hoveredImageRef.current) {
5852
4926
  hoveredImageRef.current = null;
@@ -5854,7 +4928,7 @@ function OhhwellsBridge() {
5854
4928
  }
5855
4929
  postToParent({ type: "ow:image-unhover" });
5856
4930
  }, [linkPopover, postToParent]);
5857
- useEffect3(() => {
4931
+ useEffect2(() => {
5858
4932
  if (!isEditMode) return;
5859
4933
  const useFixtures = shouldUseDevFixtures();
5860
4934
  if (useFixtures) {
@@ -5878,15 +4952,14 @@ function OhhwellsBridge() {
5878
4952
  if (!useFixtures) postToParent({ type: "ow:request-site-pages" });
5879
4953
  return () => window.removeEventListener("message", onSitePages);
5880
4954
  }, [isEditMode, postToParent]);
5881
- const [sectionGap, setSectionGap] = useState5(null);
5882
- useEffect3(() => {
4955
+ useEffect2(() => {
5883
4956
  if (!isEditMode || shouldUseDevFixtures()) return;
5884
4957
  void loadAllSectionsManifest().then((manifest) => {
5885
4958
  if (Object.keys(manifest).length === 0) return;
5886
4959
  setSectionsByPath((prev) => ({ ...manifest, ...prev }));
5887
4960
  });
5888
4961
  }, [isEditMode]);
5889
- useEffect3(() => {
4962
+ useEffect2(() => {
5890
4963
  const update = () => {
5891
4964
  const el = activeElRef.current;
5892
4965
  if (el) setToolbarRect(el.getBoundingClientRect());
@@ -5894,12 +4967,6 @@ function OhhwellsBridge() {
5894
4967
  if (!prev || !activeStateElRef.current) return prev;
5895
4968
  return { ...prev, rect: activeStateElRef.current.getBoundingClientRect() };
5896
4969
  });
5897
- setSectionGap((prev) => {
5898
- if (!prev) return prev;
5899
- const anchor = document.querySelector(`[data-ohw-section="${prev.insertAfter}"]`);
5900
- if (!anchor) return prev;
5901
- return { ...prev, y: anchor.getBoundingClientRect().bottom };
5902
- });
5903
4970
  };
5904
4971
  const vvp = window.visualViewport;
5905
4972
  if (!vvp) return;
@@ -5966,7 +5033,6 @@ function OhhwellsBridge() {
5966
5033
  const applyContent = (content) => {
5967
5034
  const imageLoads = [];
5968
5035
  for (const [key, val] of Object.entries(content)) {
5969
- if (key === "__ohw_sections") continue;
5970
5036
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
5971
5037
  if (el.dataset.ohwEditable === "image") {
5972
5038
  const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
@@ -5988,7 +5054,6 @@ function OhhwellsBridge() {
5988
5054
  });
5989
5055
  applyLinkByKey(key, val);
5990
5056
  }
5991
- initSectionsFromContent(content, true);
5992
5057
  return imageLoads.length > 0 ? Promise.all(imageLoads).then(() => {
5993
5058
  }) : Promise.resolve();
5994
5059
  };
@@ -6013,15 +5078,12 @@ function OhhwellsBridge() {
6013
5078
  cancelled = true;
6014
5079
  };
6015
5080
  }, [subdomain, isEditMode, pathname]);
6016
- useEffect3(() => {
5081
+ useEffect2(() => {
6017
5082
  if (!subdomain || isEditMode) return;
6018
- let debounceTimer = null;
6019
5083
  const applyFromCache = () => {
6020
5084
  const content = contentCache.get(subdomain);
6021
5085
  if (!content) return;
6022
- retryMissingSchedulingMounts(getPageSchedulingEntries(content["__ohw_sections"]), false);
6023
5086
  for (const [key, val] of Object.entries(content)) {
6024
- if (key === "__ohw_sections") continue;
6025
5087
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
6026
5088
  if (el.dataset.ohwEditable === "image") {
6027
5089
  const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
@@ -6038,28 +5100,21 @@ function OhhwellsBridge() {
6038
5100
  applyLinkByKey(key, val);
6039
5101
  }
6040
5102
  };
6041
- const scheduleApply = () => {
6042
- if (debounceTimer) clearTimeout(debounceTimer);
6043
- debounceTimer = setTimeout(applyFromCache, 150);
6044
- };
6045
- scheduleApply();
6046
- const observer = new MutationObserver(scheduleApply);
5103
+ applyFromCache();
5104
+ const observer = new MutationObserver(applyFromCache);
6047
5105
  observer.observe(document.body, { childList: true, subtree: true });
6048
- return () => {
6049
- observer.disconnect();
6050
- if (debounceTimer) clearTimeout(debounceTimer);
6051
- };
6052
- }, [subdomain, isEditMode, pathname]);
5106
+ return () => observer.disconnect();
5107
+ }, [subdomain, isEditMode]);
6053
5108
  useLayoutEffect(() => {
6054
5109
  const el = document.getElementById("ohw-loader");
6055
5110
  if (!el) return;
6056
5111
  const visible = Boolean(subdomain) && fetchState !== "done";
6057
5112
  el.style.display = visible ? "flex" : "none";
6058
5113
  }, [subdomain, fetchState]);
6059
- useEffect3(() => {
5114
+ useEffect2(() => {
6060
5115
  postToParent({ type: "ow:navigation", path: pathname });
6061
5116
  }, [pathname, postToParent]);
6062
- useEffect3(() => {
5117
+ useEffect2(() => {
6063
5118
  if (!isEditMode) return;
6064
5119
  const measure = () => {
6065
5120
  const h = document.body.scrollHeight;
@@ -6083,7 +5138,7 @@ function OhhwellsBridge() {
6083
5138
  window.removeEventListener("resize", handleResize);
6084
5139
  };
6085
5140
  }, [pathname, isEditMode, postToParent]);
6086
- useEffect3(() => {
5141
+ useEffect2(() => {
6087
5142
  if (!subdomainFromQuery || isEditMode) return;
6088
5143
  const handleClick = (e) => {
6089
5144
  const anchor = e.target.closest("a");
@@ -6099,7 +5154,7 @@ function OhhwellsBridge() {
6099
5154
  document.addEventListener("click", handleClick, true);
6100
5155
  return () => document.removeEventListener("click", handleClick, true);
6101
5156
  }, [subdomainFromQuery, isEditMode, router]);
6102
- useEffect3(() => {
5157
+ useEffect2(() => {
6103
5158
  if (!isEditMode) {
6104
5159
  editStylesRef.current?.base.remove();
6105
5160
  editStylesRef.current?.forceHover.remove();
@@ -6400,15 +5455,6 @@ function OhhwellsBridge() {
6400
5455
  textEditable.setAttribute("data-ohw-hovered", "");
6401
5456
  return;
6402
5457
  }
6403
- if (hoveredGapRef.current) {
6404
- if (hoveredImageRef.current) {
6405
- hoveredImageRef.current = null;
6406
- resumeAnimTracks();
6407
- postToParentRef.current({ type: "ow:image-unhover" });
6408
- }
6409
- document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
6410
- return;
6411
- }
6412
5458
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
6413
5459
  if (imgEl !== hoveredImageRef.current || hoveredImageHasTextOverlapRef.current) {
6414
5460
  hoveredImageRef.current = imgEl;
@@ -6474,30 +5520,8 @@ function OhhwellsBridge() {
6474
5520
  }
6475
5521
  }
6476
5522
  };
6477
- const probeSectionGapAt = (clientX, clientY, fromParentViewport = false) => {
6478
- const { y } = toProbeCoords(clientX, clientY, fromParentViewport);
6479
- const sections = Array.from(document.querySelectorAll("[data-ohw-section]")).sort((a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top);
6480
- const ZONE = 20;
6481
- for (let i = 0; i < sections.length; i++) {
6482
- const a = sections[i];
6483
- const b = sections[i + 1] ?? null;
6484
- const boundaryY = a.getBoundingClientRect().bottom;
6485
- if (Math.abs(y - boundaryY) <= ZONE) {
6486
- const insertAfter = a.dataset.ohwSection ?? "";
6487
- const insertBefore = b?.dataset.ohwSection ?? null;
6488
- hoveredGapRef.current = { insertAfter, insertBefore };
6489
- setSectionGap({ insertAfter, insertBefore, y: boundaryY });
6490
- return;
6491
- }
6492
- }
6493
- if (hoveredGapRef.current) {
6494
- hoveredGapRef.current = null;
6495
- setSectionGap(null);
6496
- }
6497
- };
6498
5523
  const handleMouseMove = (e) => {
6499
5524
  const { clientX, clientY } = e;
6500
- probeSectionGapAt(clientX, clientY);
6501
5525
  probeImageAt(clientX, clientY);
6502
5526
  probeHoverCardsAt(clientX, clientY);
6503
5527
  };
@@ -6505,7 +5529,6 @@ function OhhwellsBridge() {
6505
5529
  if (e.data?.type !== "ow:pointer-sync") return;
6506
5530
  const { clientX, clientY } = e.data;
6507
5531
  if (typeof clientX !== "number" || typeof clientY !== "number") return;
6508
- probeSectionGapAt(clientX, clientY);
6509
5532
  probeImageAt(clientX, clientY);
6510
5533
  probeHoverCardsAt(clientX, clientY);
6511
5534
  };
@@ -6663,12 +5686,7 @@ function OhhwellsBridge() {
6663
5686
  if (e.data?.type !== "ow:hydrate") return;
6664
5687
  const content = e.data.content;
6665
5688
  if (!content) return;
6666
- let sectionsJson = null;
6667
5689
  for (const [key, val] of Object.entries(content)) {
6668
- if (key === "__ohw_sections") {
6669
- sectionsJson = val;
6670
- continue;
6671
- }
6672
5690
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
6673
5691
  if (el.dataset.ohwEditable === "image") {
6674
5692
  const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
@@ -6683,9 +5701,6 @@ function OhhwellsBridge() {
6683
5701
  });
6684
5702
  applyLinkByKey(key, val);
6685
5703
  }
6686
- if (sectionsJson) {
6687
- initSectionsFromContent({ __ohw_sections: sectionsJson }, true);
6688
- }
6689
5704
  postToParentRef.current({ type: "ow:hydrate-done" });
6690
5705
  };
6691
5706
  window.addEventListener("message", handleHydrate);
@@ -6738,63 +5753,7 @@ function OhhwellsBridge() {
6738
5753
  };
6739
5754
  const handleSave = (e) => {
6740
5755
  if (e.data?.type !== "ow:save") return;
6741
- const nodes = collectEditableNodes();
6742
- const tracker = document.querySelector("[data-ohw-sections-tracker]");
6743
- if (tracker?.textContent) nodes.push({ key: "__ohw_sections", type: "sections", text: tracker.textContent });
6744
- postToParentRef.current({ type: "ow:save-result", nodes });
6745
- };
6746
- const handleInsertSection = (e) => {
6747
- if (e.data?.type !== "ow:insert-section") return;
6748
- const { widgetType, insertAfter, insertBefore } = e.data;
6749
- if (widgetType !== "scheduling") return;
6750
- const inserted = mountSchedulingWidget(insertAfter, true, void 0, insertBefore ?? null);
6751
- if (inserted) {
6752
- const tracker = getSectionsTracker();
6753
- postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
6754
- const h = document.documentElement.scrollHeight;
6755
- if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
6756
- }
6757
- };
6758
- const handleSwitchSchedule = (e) => {
6759
- if (e.data?.type !== "ow:switch-schedule") return;
6760
- const scheduleId = e.data.scheduleId;
6761
- const insertAfter = e.data.insertAfter;
6762
- if (!scheduleId || !insertAfter) return;
6763
- const text = updateSectionScheduleId(insertAfter, scheduleId);
6764
- postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text }] });
6765
- };
6766
- const handleScheduleLinked = (e) => {
6767
- if (e.data?.type !== "ow:schedule-linked") return;
6768
- const scheduleId = e.data.scheduleId;
6769
- const insertAfter = e.data.insertAfter;
6770
- if (!scheduleId || !insertAfter) return;
6771
- const text = updateSectionScheduleId(insertAfter, scheduleId);
6772
- postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text }] });
6773
- };
6774
- const handleClearSchedulingWidget = (e) => {
6775
- if (e.data?.type !== "ow:clear-scheduling-widget") return;
6776
- const insertAfter = e.data.insertAfter;
6777
- if (!insertAfter) return;
6778
- const text = updateSectionScheduleId(insertAfter, null);
6779
- postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text }] });
6780
- };
6781
- const handleRemoveSchedulingSection = (e) => {
6782
- if (e.data?.type !== "ow:remove-scheduling-section") return;
6783
- document.querySelectorAll('[data-ohw-section-container="scheduling"]').forEach((el) => {
6784
- el.remove();
6785
- });
6786
- const tracker = getSectionsTracker();
6787
- let sections = [];
6788
- try {
6789
- sections = JSON.parse(tracker.textContent || "[]");
6790
- } catch {
6791
- }
6792
- const currentPath = window.location.pathname;
6793
- const updated = sections.filter((s) => !(s.type === "scheduling" && s.pagePath === currentPath));
6794
- tracker.textContent = JSON.stringify(updated);
6795
- postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent }] });
6796
- const h = document.documentElement.scrollHeight;
6797
- if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
5756
+ postToParentRef.current({ type: "ow:save-result", nodes: collectEditableNodes() });
6798
5757
  };
6799
5758
  const handleSelectionChange = () => {
6800
5759
  if (!activeElRef.current) return;
@@ -6899,11 +5858,6 @@ function OhhwellsBridge() {
6899
5858
  deactivateRef.current();
6900
5859
  };
6901
5860
  window.addEventListener("message", handleSave);
6902
- window.addEventListener("message", handleInsertSection);
6903
- window.addEventListener("message", handleSwitchSchedule);
6904
- window.addEventListener("message", handleScheduleLinked);
6905
- window.addEventListener("message", handleClearSchedulingWidget);
6906
- window.addEventListener("message", handleRemoveSchedulingSection);
6907
5861
  window.addEventListener("message", handleImageUrl);
6908
5862
  window.addEventListener("message", handleAnimLock);
6909
5863
  window.addEventListener("message", handleCanvasHeight);
@@ -6938,11 +5892,6 @@ function OhhwellsBridge() {
6938
5892
  document.removeEventListener("selectionchange", handleSelectionChange);
6939
5893
  window.removeEventListener("scroll", handleScroll, true);
6940
5894
  window.removeEventListener("message", handleSave);
6941
- window.removeEventListener("message", handleInsertSection);
6942
- window.removeEventListener("message", handleSwitchSchedule);
6943
- window.removeEventListener("message", handleScheduleLinked);
6944
- window.removeEventListener("message", handleClearSchedulingWidget);
6945
- window.removeEventListener("message", handleRemoveSchedulingSection);
6946
5895
  window.removeEventListener("message", handleImageUrl);
6947
5896
  window.removeEventListener("message", handleAnimLock);
6948
5897
  window.removeEventListener("message", handleCanvasHeight);
@@ -6957,7 +5906,7 @@ function OhhwellsBridge() {
6957
5906
  if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
6958
5907
  };
6959
5908
  }, [isEditMode, refreshStateRules]);
6960
- useEffect3(() => {
5909
+ useEffect2(() => {
6961
5910
  if (!isEditMode) return;
6962
5911
  document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
6963
5912
  el.removeAttribute("data-ohw-active-state");
@@ -6986,7 +5935,7 @@ function OhhwellsBridge() {
6986
5935
  clearTimeout(timer);
6987
5936
  };
6988
5937
  }, [pathname, isEditMode, refreshStateRules, postToParent]);
6989
- useEffect3(() => {
5938
+ useEffect2(() => {
6990
5939
  scrollToHashSectionWhenReady();
6991
5940
  const onHashChange = () => scrollToHashSectionWhenReady();
6992
5941
  window.addEventListener("hashchange", onHashChange);
@@ -7036,10 +5985,10 @@ function OhhwellsBridge() {
7036
5985
  const currentSections = sectionsByPath[pathname] ?? [];
7037
5986
  linkPopoverOpenRef.current = linkPopover !== null;
7038
5987
  return bridgeRoot ? createPortal(
7039
- /* @__PURE__ */ jsxs8(Fragment3, { children: [
7040
- toolbarRect && /* @__PURE__ */ jsxs8(Fragment3, { children: [
7041
- /* @__PURE__ */ jsx16(GlowFrame, { rect: toolbarRect, elRef: glowElRef }),
7042
- /* @__PURE__ */ jsx16(
5988
+ /* @__PURE__ */ jsxs6(Fragment2, { children: [
5989
+ toolbarRect && /* @__PURE__ */ jsxs6(Fragment2, { children: [
5990
+ /* @__PURE__ */ jsx13(GlowFrame, { rect: toolbarRect, elRef: glowElRef }),
5991
+ /* @__PURE__ */ jsx13(
7043
5992
  FloatingToolbar,
7044
5993
  {
7045
5994
  rect: toolbarRect,
@@ -7052,7 +6001,7 @@ function OhhwellsBridge() {
7052
6001
  }
7053
6002
  )
7054
6003
  ] }),
7055
- maxBadge && /* @__PURE__ */ jsxs8(
6004
+ maxBadge && /* @__PURE__ */ jsxs6(
7056
6005
  "div",
7057
6006
  {
7058
6007
  "data-ohw-max-badge": "",
@@ -7078,7 +6027,7 @@ function OhhwellsBridge() {
7078
6027
  ]
7079
6028
  }
7080
6029
  ),
7081
- toggleState && /* @__PURE__ */ jsx16(
6030
+ toggleState && /* @__PURE__ */ jsx13(
7082
6031
  StateToggle,
7083
6032
  {
7084
6033
  rect: toggleState.rect,
@@ -7087,7 +6036,7 @@ function OhhwellsBridge() {
7087
6036
  onStateChange: handleStateChange
7088
6037
  }
7089
6038
  ),
7090
- linkPopover ? /* @__PURE__ */ jsx16(
6039
+ linkPopover ? /* @__PURE__ */ jsx13(
7091
6040
  LinkPopover,
7092
6041
  {
7093
6042
  rect: linkPopover.rect,
@@ -7102,32 +6051,7 @@ function OhhwellsBridge() {
7102
6051
  onClose: closeLinkPopover,
7103
6052
  onSubmit: handleLinkPopoverSubmit
7104
6053
  }
7105
- ) : null,
7106
- sectionGap && /* @__PURE__ */ jsxs8(
7107
- "div",
7108
- {
7109
- "data-ohw-section-insert-line": "",
7110
- className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
7111
- style: { top: sectionGap.y, transform: "translateY(-50%)" },
7112
- children: [
7113
- /* @__PURE__ */ jsx16("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
7114
- /* @__PURE__ */ jsx16(
7115
- Badge,
7116
- {
7117
- 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",
7118
- onClick: () => {
7119
- window.parent.postMessage(
7120
- { type: "ow:add-section", insertAfter: sectionGap.insertAfter, insertBefore: sectionGap.insertBefore },
7121
- "*"
7122
- );
7123
- },
7124
- children: "Add Section"
7125
- }
7126
- ),
7127
- /* @__PURE__ */ jsx16("div", { className: "flex-1 bg-primary", style: { height: 3 } })
7128
- ]
7129
- }
7130
- )
6054
+ ) : null
7131
6055
  ] }),
7132
6056
  bridgeRoot
7133
6057
  ) : null;
@@ -7136,7 +6060,6 @@ export {
7136
6060
  LinkEditorPanel,
7137
6061
  LinkPopover,
7138
6062
  OhhwellsBridge,
7139
- SchedulingWidget,
7140
6063
  Toggle,
7141
6064
  ToggleGroup,
7142
6065
  ToggleGroupItem,