@ohhwells/bridge 0.1.19 → 0.1.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -41,12 +41,167 @@ __export(index_exports, {
41
41
  module.exports = __toCommonJS(index_exports);
42
42
 
43
43
  // src/OhhwellsBridge.tsx
44
- var import_react2 = __toESM(require("react"), 1);
44
+ var import_react3 = __toESM(require("react"), 1);
45
45
  var import_client = require("react-dom/client");
46
+ var import_react_dom = require("react-dom");
46
47
 
47
48
  // src/ui/SchedulingWidget.tsx
48
- var import_react = __toESM(require("react"), 1);
49
+ var import_react2 = require("react");
50
+
51
+ // src/ui/EmailCaptureModal.tsx
52
+ var import_react = require("react");
53
+ var import_radix_ui = require("radix-ui");
49
54
  var import_jsx_runtime = require("react/jsx-runtime");
55
+ function Spinner() {
56
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
57
+ "svg",
58
+ {
59
+ width: "32",
60
+ height: "32",
61
+ viewBox: "0 0 32 32",
62
+ fill: "none",
63
+ style: { animation: "ohw-spin 0.75s linear infinite" },
64
+ children: [
65
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `@keyframes ohw-spin { to { transform: rotate(360deg); } }` }),
66
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "16", cy: "16", r: "12", stroke: "#e5e7eb", strokeWidth: "3" }),
67
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
68
+ "path",
69
+ {
70
+ d: "M16 4a12 12 0 0 1 12 12",
71
+ stroke: "#3b82f6",
72
+ strokeWidth: "3",
73
+ strokeLinecap: "round"
74
+ }
75
+ )
76
+ ]
77
+ }
78
+ );
79
+ }
80
+ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
81
+ const [email, setEmail] = (0, import_react.useState)("");
82
+ const [submittedEmail, setSubmittedEmail] = (0, import_react.useState)("");
83
+ const [loading, setLoading] = (0, import_react.useState)(false);
84
+ const [success, setSuccess] = (0, import_react.useState)(false);
85
+ const [error, setError] = (0, import_react.useState)(null);
86
+ const isBook = title === "Confirm your spot";
87
+ const handleSubmit = async () => {
88
+ if (!email.trim()) return;
89
+ setLoading(true);
90
+ setError(null);
91
+ try {
92
+ await onSubmit(email.trim());
93
+ setSubmittedEmail(email.trim());
94
+ setSuccess(true);
95
+ } catch (e) {
96
+ setError(e instanceof Error ? e.message : "Something went wrong. Please try again.");
97
+ } finally {
98
+ setLoading(false);
99
+ }
100
+ };
101
+ const handleKeyDown = (e) => {
102
+ if (e.key === "Enter" && !loading) handleSubmit();
103
+ };
104
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_radix_ui.Dialog.Root, { open: true, onOpenChange: (open) => {
105
+ if (!open) onClose();
106
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_radix_ui.Dialog.Portal, { children: [
107
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
108
+ import_radix_ui.Dialog.Overlay,
109
+ {
110
+ className: "fixed inset-0 z-50",
111
+ style: { background: "rgba(0,0,0,0.45)" }
112
+ }
113
+ ),
114
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
115
+ import_radix_ui.Dialog.Content,
116
+ {
117
+ 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",
118
+ style: { maxWidth: 400 },
119
+ children: [
120
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-start justify-between gap-3 p-6", children: [
121
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-1", children: [
122
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
123
+ import_radix_ui.Dialog.Title,
124
+ {
125
+ className: "font-body text-xl font-bold m-0 leading-tight",
126
+ style: { color: "var(--color-dark,#200C02)" },
127
+ children: success ? isBook ? "Reservation confirmed!" : "You're on the waitlist!" : title
128
+ }
129
+ ),
130
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
131
+ import_radix_ui.Dialog.Description,
132
+ {
133
+ className: "font-body text-sm m-0",
134
+ style: { color: "#6B7280" },
135
+ children: success ? isBook ? `A confirmation email has been sent to ${submittedEmail}.` : "We'll let you know via email if someone cancels." : subtitle
136
+ }
137
+ )
138
+ ] }),
139
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
140
+ import_radix_ui.Dialog.Close,
141
+ {
142
+ 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",
143
+ style: { color: "#6B7280" },
144
+ "aria-label": "Close",
145
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
146
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
147
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
148
+ ] })
149
+ }
150
+ )
151
+ ] }),
152
+ !success && (loading ? (
153
+ /* Loading state — full body replaced */
154
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col items-center justify-center gap-3 px-7 py-12", children: [
155
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {}),
156
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "font-body text-sm m-0", style: { color: "#6B7280" }, children: "Please wait" })
157
+ ] })
158
+ ) : (
159
+ /* Email form */
160
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "px-7 pt-2 pb-6", children: [
161
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-1.5 mb-8", children: [
162
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "font-body text-sm font-medium", style: { color: "var(--color-dark,#200C02)" }, children: "Email" }),
163
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
164
+ "input",
165
+ {
166
+ type: "email",
167
+ value: email,
168
+ onChange: (e) => setEmail(e.target.value),
169
+ onKeyDown: handleKeyDown,
170
+ placeholder: "hello@gmail.com",
171
+ autoFocus: true,
172
+ className: "w-full h-10 px-3 rounded-lg border font-body text-sm outline-none box-border",
173
+ style: {
174
+ borderColor: "#E7E5E4",
175
+ background: "#fff",
176
+ color: "var(--color-dark,#200C02)"
177
+ }
178
+ }
179
+ ),
180
+ error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "font-body text-xs text-red-500 m-0", children: error })
181
+ ] }),
182
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
183
+ "button",
184
+ {
185
+ onClick: handleSubmit,
186
+ disabled: !email.trim(),
187
+ className: "h-9 px-5 rounded-lg font-body text-sm font-semibold cursor-pointer border-none disabled:opacity-50 disabled:cursor-not-allowed",
188
+ style: {
189
+ background: "var(--color-primary,#3D312B)",
190
+ color: "var(--color-light,#FEFFF0)"
191
+ },
192
+ children: "Send"
193
+ }
194
+ ) })
195
+ ] })
196
+ ))
197
+ ]
198
+ }
199
+ )
200
+ ] }) });
201
+ }
202
+
203
+ // src/ui/SchedulingWidget.tsx
204
+ var import_jsx_runtime2 = require("react/jsx-runtime");
50
205
  var API_URL = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
51
206
  var DAY_ABBR = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
52
207
  function getApiDomain() {
@@ -107,8 +262,8 @@ function EmptyState({ inEditor }) {
107
262
  window.parent.postMessage({ type: "ow:scheduling-not-connected" }, "*");
108
263
  }
109
264
  };
110
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("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: [
111
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-10 h-10 bg-[#F5F5F4] rounded-[10px] flex items-center justify-center shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
265
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("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: [
266
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "w-10 h-10 bg-[#F5F5F4] rounded-[10px] flex items-center justify-center shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
112
267
  "svg",
113
268
  {
114
269
  width: "20",
@@ -120,20 +275,20 @@ function EmptyState({ inEditor }) {
120
275
  strokeLinecap: "round",
121
276
  strokeLinejoin: "round",
122
277
  children: [
123
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2" }),
124
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "16", y1: "2", x2: "16", y2: "6" }),
125
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "8", y1: "2", x2: "8", y2: "6" }),
126
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "3", y1: "10", x2: "21", y2: "10" }),
127
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", y1: "14", x2: "12", y2: "18" }),
128
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "10", y1: "16", x2: "14", y2: "16" })
278
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2" }),
279
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "16", y1: "2", x2: "16", y2: "6" }),
280
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "8", y1: "2", x2: "8", y2: "6" }),
281
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "3", y1: "10", x2: "21", y2: "10" }),
282
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "12", y1: "14", x2: "12", y2: "18" }),
283
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "10", y1: "16", x2: "14", y2: "16" })
129
284
  ]
130
285
  }
131
286
  ) }),
132
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col items-center gap-2", children: [
133
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "font-body text-lg font-medium text-center text-[#0A0A0A] m-0", children: "No schedule yet" }),
134
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("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." })
287
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-col items-center gap-2", children: [
288
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "font-body text-lg font-medium text-center text-[#0A0A0A] m-0", children: "No schedule yet" }),
289
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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." })
135
290
  ] }),
136
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
291
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
137
292
  "button",
138
293
  {
139
294
  onClick: handleAddSchedule,
@@ -149,119 +304,249 @@ function LoadingSkeleton() {
149
304
  backgroundSize: "200% 100%",
150
305
  animation: "ohw-shimmer 1.5s infinite"
151
306
  };
152
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "w-full flex flex-col gap-10", children: [
153
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `@keyframes ohw-shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}` }),
154
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex h-[70px] items-stretch", children: Array.from({ length: 7 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-1 flex flex-col justify-between items-center px-1", children: [
155
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...shimmer, width: "32px", height: "14px", borderRadius: "4px" } }),
156
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...shimmer, width: "40px", height: "40px", borderRadius: "50%" } })
307
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "w-full flex flex-col gap-10", children: [
308
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: `@keyframes ohw-shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}` }),
309
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex h-[70px] items-stretch", children: Array.from({ length: 7 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex-1 flex flex-col justify-between items-center px-1", children: [
310
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { ...shimmer, width: "32px", height: "14px", borderRadius: "4px" } }),
311
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { ...shimmer, width: "40px", height: "40px", borderRadius: "50%" } })
157
312
  ] }, i)) }),
158
- [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
159
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-[60px] py-4", children: [
160
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...shimmer, width: "120px", height: "16px", borderRadius: "4px", flexShrink: 0 } }),
161
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-1 flex flex-col gap-2", children: [
162
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...shimmer, width: "55%", height: "16px", borderRadius: "4px" } }),
163
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...shimmer, width: "38%", height: "14px", borderRadius: "4px" } })
313
+ [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
314
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-4 py-4 sm:hidden", children: [
315
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-col gap-2 shrink-0", children: [
316
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { ...shimmer, width: "100px", height: "16px", borderRadius: "4px" } }),
317
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { ...shimmer, width: "52px", height: "20px", borderRadius: "999px" } }),
318
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { ...shimmer, width: "60px", height: "14px", borderRadius: "4px" } })
164
319
  ] }),
165
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...shimmer, width: "56px", height: "32px", borderRadius: "4px", flexShrink: 0 } }),
166
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...shimmer, width: "200px", height: "44px", borderRadius: "8px", flexShrink: 0 } })
320
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-1 flex-col gap-2", children: [
321
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { ...shimmer, width: "75%", height: "16px", borderRadius: "4px" } }),
322
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { ...shimmer, width: "50%", height: "14px", borderRadius: "4px" } }),
323
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { ...shimmer, width: "100%", height: "44px", borderRadius: "8px" } })
324
+ ] })
167
325
  ] }),
168
- i < 2 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-px bg-black/20" })
326
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "hidden sm:flex items-center gap-[60px] py-4", children: [
327
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { ...shimmer, width: "120px", height: "16px", borderRadius: "4px", flexShrink: 0 } }),
328
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex-1 flex flex-col gap-2", children: [
329
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { ...shimmer, width: "55%", height: "16px", borderRadius: "4px" } }),
330
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { ...shimmer, width: "38%", height: "14px", borderRadius: "4px" } })
331
+ ] }),
332
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { ...shimmer, width: "56px", height: "32px", borderRadius: "4px", flexShrink: 0 } }),
333
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { ...shimmer, width: "200px", height: "44px", borderRadius: "8px", flexShrink: 0 } })
334
+ ] }),
335
+ i < 2 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-px bg-black/20" })
169
336
  ] }, i))
170
337
  ] });
171
338
  }
172
- function ScheduleView({ schedule, dates, selectedIdx, onSelectDate }) {
173
- const todayMs = (0, import_react.useMemo)(() => {
339
+ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal }) {
340
+ const todayMs = (0, import_react2.useMemo)(() => {
174
341
  const d = /* @__PURE__ */ new Date();
175
342
  d.setHours(0, 0, 0, 0);
176
343
  return d.getTime();
177
344
  }, []);
178
- const datesWithClasses = (0, import_react.useMemo)(
345
+ const scrollRef = (0, import_react2.useRef)(null);
346
+ const [canScrollLeft, setCanScrollLeft] = (0, import_react2.useState)(false);
347
+ const [canScrollRight, setCanScrollRight] = (0, import_react2.useState)(false);
348
+ const updateScrollState = () => {
349
+ const el = scrollRef.current;
350
+ if (!el) return;
351
+ setCanScrollLeft(el.scrollLeft > 0);
352
+ setCanScrollRight(el.scrollLeft + el.clientWidth < el.scrollWidth - 1);
353
+ };
354
+ (0, import_react2.useEffect)(() => {
355
+ const el = scrollRef.current;
356
+ if (!el) return;
357
+ updateScrollState();
358
+ el.addEventListener("scroll", updateScrollState);
359
+ const ro = new ResizeObserver(updateScrollState);
360
+ ro.observe(el);
361
+ return () => {
362
+ el.removeEventListener("scroll", updateScrollState);
363
+ ro.disconnect();
364
+ };
365
+ }, [dates]);
366
+ const scroll = (dir) => {
367
+ scrollRef.current?.scrollBy({ left: dir === "left" ? -216 : 216, behavior: "smooth" });
368
+ };
369
+ const isDragging = (0, import_react2.useRef)(false);
370
+ const dragStartX = (0, import_react2.useRef)(0);
371
+ const dragStartScrollLeft = (0, import_react2.useRef)(0);
372
+ const onDragStart = (e) => {
373
+ if (!scrollRef.current) return;
374
+ isDragging.current = true;
375
+ dragStartX.current = e.clientX;
376
+ dragStartScrollLeft.current = scrollRef.current.scrollLeft;
377
+ scrollRef.current.style.cursor = "grabbing";
378
+ scrollRef.current.style.userSelect = "none";
379
+ };
380
+ const onDragMove = (e) => {
381
+ if (!isDragging.current || !scrollRef.current) return;
382
+ const delta = e.clientX - dragStartX.current;
383
+ scrollRef.current.scrollLeft = dragStartScrollLeft.current - delta;
384
+ };
385
+ const onDragEnd = () => {
386
+ if (!scrollRef.current) return;
387
+ isDragging.current = false;
388
+ scrollRef.current.style.cursor = "grab";
389
+ scrollRef.current.style.userSelect = "";
390
+ };
391
+ const datesWithClasses = (0, import_react2.useMemo)(
179
392
  () => new Set(dates.map(
180
393
  (d, i) => schedule.classes?.some((c) => classRunsOnDate(c, d, schedule.type)) ? i : -1
181
394
  ).filter((i) => i >= 0)),
182
395
  [dates, schedule]
183
396
  );
184
397
  const selectedDate = dates[selectedIdx];
185
- const selectedClasses = (0, import_react.useMemo)(
398
+ const selectedClasses = (0, import_react2.useMemo)(
186
399
  () => (schedule.classes ?? []).filter((c) => selectedDate && classRunsOnDate(c, selectedDate, schedule.type)),
187
400
  [schedule, selectedDate]
188
401
  );
189
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "w-full flex flex-col gap-10", children: [
190
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "overflow-x-auto w-full", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex min-w-max", children: dates.map((date, i) => {
191
- const isToday = date.getTime() === todayMs;
192
- const isSelected = i === selectedIdx;
193
- const clickable = datesWithClasses.has(i);
194
- const label = isToday ? "TODAY" : DAY_ABBR[date.getDay()];
195
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
402
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "w-full flex flex-col gap-10", children: [
403
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "relative w-full", children: [
404
+ canScrollLeft && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
405
+ "button",
406
+ {
407
+ onClick: () => scroll("left"),
408
+ 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",
409
+ style: { background: "var(--color-light,#FEFFF0)", boxShadow: "0 1px 4px rgba(0,0,0,0.15)" },
410
+ "aria-label": "Scroll left",
411
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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__ */ (0, import_jsx_runtime2.jsx)("polyline", { points: "15 18 9 12 15 6" }) })
412
+ }
413
+ ),
414
+ canScrollRight && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
415
+ "button",
416
+ {
417
+ onClick: () => scroll("right"),
418
+ 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",
419
+ style: { background: "var(--color-light,#FEFFF0)", boxShadow: "0 1px 4px rgba(0,0,0,0.15)" },
420
+ "aria-label": "Scroll right",
421
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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__ */ (0, import_jsx_runtime2.jsx)("polyline", { points: "9 18 15 12 9 6" }) })
422
+ }
423
+ ),
424
+ canScrollLeft && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
196
425
  "div",
197
426
  {
198
- onClick: () => clickable && onSelectDate(i),
199
- className: `flex-none w-[72px] h-[70px] flex flex-col justify-between items-center ${clickable ? "cursor-pointer opacity-100" : "cursor-default opacity-50"}`,
200
- children: [
201
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-body text-base font-normal text-center text-(--color-dark,#200C02)", children: label }),
202
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
427
+ className: "sm:hidden absolute left-0 top-0 bottom-0 w-10 z-10 pointer-events-none",
428
+ style: { background: "linear-gradient(to right, var(--color-light,#FEFFF0), transparent)" }
429
+ }
430
+ ),
431
+ canScrollRight && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
432
+ "div",
433
+ {
434
+ className: "sm:hidden absolute right-0 top-0 bottom-0 w-10 z-10 pointer-events-none",
435
+ style: { background: "linear-gradient(to left, var(--color-light,#FEFFF0), transparent)" }
436
+ }
437
+ ),
438
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
439
+ "div",
440
+ {
441
+ ref: scrollRef,
442
+ className: "overflow-x-auto w-full",
443
+ style: { scrollbarWidth: "none", msOverflowStyle: "none", touchAction: "pan-x", cursor: "grab" },
444
+ onMouseDown: onDragStart,
445
+ onMouseMove: onDragMove,
446
+ onMouseUp: onDragEnd,
447
+ onMouseLeave: onDragEnd,
448
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex", style: { width: `max(100%, ${dates.length * 60}px)` }, children: dates.map((date, i) => {
449
+ const isToday = date.getTime() === todayMs;
450
+ const isSelected = i === selectedIdx;
451
+ const clickable = datesWithClasses.has(i);
452
+ const label = isToday ? "TODAY" : DAY_ABBR[date.getDay()];
453
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
203
454
  "div",
204
455
  {
205
- className: "w-10 h-10 rounded-full flex items-center justify-center",
206
- style: { background: isSelected ? "var(--color-primary, #3D312B)" : "transparent" },
207
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
208
- "span",
209
- {
210
- className: "font-body text-xl font-bold text-center tracking-display-tight",
211
- style: { color: isSelected ? "var(--color-light, #FEFFF0)" : "var(--color-dark, #200C02)" },
212
- children: date.getDate()
213
- }
214
- )
215
- }
216
- )
217
- ]
218
- },
219
- i
220
- );
221
- }) }) }),
222
- selectedClasses.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "font-body text-base text-(--color-accent,#A89B83) text-center py-8 m-0", children: "No classes scheduled for this day." }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-col", children: selectedClasses.map((cls, i) => {
456
+ onClick: () => clickable && onSelectDate(i),
457
+ className: `flex-1 h-[70px] flex flex-col justify-between items-center ${clickable ? "cursor-pointer opacity-100" : "cursor-default opacity-50"}`,
458
+ children: [
459
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-base font-normal text-center text-(--color-dark,#200C02)", children: label }),
460
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
461
+ "div",
462
+ {
463
+ className: "w-10 h-10 rounded-full flex items-center justify-center",
464
+ style: { background: isSelected ? "var(--color-primary, #3D312B)" : "transparent" },
465
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
466
+ "span",
467
+ {
468
+ className: "font-body text-xl font-bold text-center tracking-display-tight",
469
+ style: { color: isSelected ? "var(--color-light, #FEFFF0)" : "var(--color-dark, #200C02)" },
470
+ children: date.getDate()
471
+ }
472
+ )
473
+ }
474
+ )
475
+ ]
476
+ },
477
+ i
478
+ );
479
+ }) })
480
+ }
481
+ )
482
+ ] }),
483
+ selectedClasses.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "font-body text-base text-(--color-accent,#A89B83) text-center py-8 m-0", children: "No classes scheduled for this day." }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex flex-col", children: selectedClasses.map((cls, i) => {
223
484
  const booked = getBookingsOnDate(cls, selectedDate);
224
485
  const available = cls.maxParticipants - booked;
225
486
  const isFull = available <= 0;
226
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
227
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-[60px] py-4 box-border", children: [
228
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-[120px] shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block", children: formatClassTime(cls) }) }),
229
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-1 flex flex-col gap-3 min-w-0", children: [
230
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block truncate", children: cls.name }),
231
- cls.hostName && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName })
487
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
488
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-4 py-4 sm:items-center sm:gap-[60px] box-border", children: [
489
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-col gap-2 shrink-0 sm:contents", children: [
490
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "sm:w-[120px] sm:shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block", children: formatClassTime(cls) }) }),
491
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
492
+ "span",
493
+ {
494
+ className: "inline-flex items-center px-2 py-0.5 rounded-full border text-xs font-medium sm:hidden",
495
+ style: { borderColor: "#0885FE", color: "#0885FE" },
496
+ children: "GROUP"
497
+ }
498
+ ),
499
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "sm:hidden flex flex-col gap-px", children: isFull ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
500
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
501
+ available,
502
+ "/",
503
+ cls.maxParticipants
504
+ ] }),
505
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "available" })
506
+ ] }) })
232
507
  ] }),
233
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-14 shrink-0 flex flex-col gap-px", children: isFull ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
234
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
235
- available,
236
- "/",
237
- cls.maxParticipants
508
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-1 flex-col gap-2 min-w-0 sm:contents", children: [
509
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex-1 flex flex-col gap-2 min-w-0", children: [
510
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block truncate", children: cls.name }),
511
+ cls.hostName && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName })
238
512
  ] }),
239
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "available" })
240
- ] }) }),
241
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
242
- "button",
243
- {
244
- className: "shrink-0 w-[200px] px-5 py-[10px] flex items-center justify-center rounded-lg font-body text-base font-bold cursor-pointer box-border",
245
- style: isFull ? {
246
- background: "transparent",
247
- border: "1px solid var(--color-dark, #200C02)",
248
- color: "var(--color-dark, #200C02)"
249
- } : {
250
- background: "var(--color-primary, #3D312B)",
251
- border: "none",
252
- color: "var(--color-light, #FEFFF0)"
253
- },
254
- children: isFull ? "Join Waitlist" : "Book Now"
255
- }
256
- )
513
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "hidden sm:flex w-14 shrink-0 flex-col gap-px", children: isFull ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
514
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
515
+ available,
516
+ "/",
517
+ cls.maxParticipants
518
+ ] }),
519
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "available" })
520
+ ] }) }),
521
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
522
+ "button",
523
+ {
524
+ 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",
525
+ style: isFull ? {
526
+ background: "transparent",
527
+ border: "1px solid var(--color-dark, #200C02)",
528
+ color: "var(--color-dark, #200C02)"
529
+ } : {
530
+ background: "var(--color-primary, #3D312B)",
531
+ border: "none",
532
+ color: "var(--color-light, #FEFFF0)"
533
+ },
534
+ onClick: () => {
535
+ if (!cls.id) return;
536
+ onOpenModal?.(isFull ? "waitlist" : "book", cls.id, selectedDate);
537
+ },
538
+ children: isFull ? "Join Waitlist" : "Book Now"
539
+ }
540
+ )
541
+ ] })
257
542
  ] }),
258
- i < selectedClasses.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-px bg-black/20" })
543
+ i < selectedClasses.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-px bg-black/20" })
259
544
  ] }, cls.id ?? i);
260
545
  }) })
261
546
  ] });
262
547
  }
263
548
  function CalendarFoldIcon() {
264
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
549
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
265
550
  "svg",
266
551
  {
267
552
  width: "16",
@@ -274,22 +559,23 @@ function CalendarFoldIcon() {
274
559
  strokeLinejoin: "round",
275
560
  style: { flexShrink: 0 },
276
561
  children: [
277
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8 2v4" }),
278
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M16 2v4" }),
279
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M21 17V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h11Z" }),
280
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 10h18" }),
281
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M15 22v-4a2 2 0 0 1 2-2h4" })
562
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M8 2v4" }),
563
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M16 2v4" }),
564
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M21 17V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h11Z" }),
565
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M3 10h18" }),
566
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M15 22v-4a2 2 0 0 1 2-2h4" })
282
567
  ]
283
568
  }
284
569
  );
285
570
  }
286
- function SchedulingWidget({ notifyOnConnect = false, initialScheduleId }) {
287
- const [schedule, setSchedule] = (0, import_react.useState)(null);
288
- const [loading, setLoading] = (0, import_react.useState)(true);
289
- const [inEditor, setInEditor] = (0, import_react.useState)(false);
290
- const [isHovered, setIsHovered] = (0, import_react.useState)(false);
291
- const switchScheduleIdRef = import_react.default.useRef(null);
292
- const dates = (0, import_react.useMemo)(() => {
571
+ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAfter }) {
572
+ const [schedule, setSchedule] = (0, import_react2.useState)(null);
573
+ const [loading, setLoading] = (0, import_react2.useState)(true);
574
+ const [inEditor, setInEditor] = (0, import_react2.useState)(false);
575
+ const [isHovered, setIsHovered] = (0, import_react2.useState)(false);
576
+ const [modalState, setModalState] = (0, import_react2.useState)(null);
577
+ const switchScheduleIdRef = (0, import_react2.useRef)(null);
578
+ const dates = (0, import_react2.useMemo)(() => {
293
579
  const today = /* @__PURE__ */ new Date();
294
580
  today.setHours(0, 0, 0, 0);
295
581
  return Array.from({ length: 14 }, (_, i) => {
@@ -298,8 +584,8 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId }) {
298
584
  return d;
299
585
  });
300
586
  }, []);
301
- const [selectedIdx, setSelectedIdx] = (0, import_react.useState)(0);
302
- (0, import_react.useEffect)(() => {
587
+ const [selectedIdx, setSelectedIdx] = (0, import_react2.useState)(0);
588
+ (0, import_react2.useEffect)(() => {
303
589
  if (!schedule?.classes) return;
304
590
  for (let i = 0; i < dates.length; i++) {
305
591
  if (schedule.classes.some((c) => classRunsOnDate(c, dates[i], schedule.type))) {
@@ -308,7 +594,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId }) {
308
594
  }
309
595
  }
310
596
  }, [schedule, dates]);
311
- (0, import_react.useEffect)(() => {
597
+ (0, import_react2.useEffect)(() => {
312
598
  if (typeof window === "undefined") return;
313
599
  const isInEditor = window.self !== window.top;
314
600
  setInEditor(isInEditor);
@@ -324,18 +610,21 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId }) {
324
610
  }, 5e3) : null;
325
611
  const handler = (e) => {
326
612
  if (e.data?.type === "ow:clear-scheduling-widget") {
613
+ if (!e.data.insertAfter || e.data.insertAfter !== insertAfter) return;
327
614
  setSchedule(null);
328
615
  setLoading(false);
329
616
  return;
330
617
  }
331
618
  if (e.data?.type === "ow:switch-schedule") {
619
+ if (!e.data.insertAfter || e.data.insertAfter !== insertAfter) return;
332
620
  switchScheduleIdRef.current = e.data.scheduleId ?? null;
333
621
  initialized = false;
334
622
  setLoading(true);
335
- window.parent.postMessage({ type: "ow:request-user-schedules" }, "*");
623
+ window.parent.postMessage({ type: "ow:request-user-schedules", insertAfter }, "*");
336
624
  return;
337
625
  }
338
626
  if (e.data?.type !== "ow:user-schedules-response") return;
627
+ if (e.data.insertAfter && e.data.insertAfter !== insertAfter) return;
339
628
  if (initialized && switchScheduleIdRef.current === null) return;
340
629
  initialized = true;
341
630
  if (timer) clearTimeout(timer);
@@ -346,11 +635,16 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId }) {
346
635
  setSchedule(target);
347
636
  setLoading(false);
348
637
  if (notifyOnConnect && target && !isSwitching) {
349
- window.parent.postMessage({ type: "ow:schedule-connected", schedule: { id: target.id, name: target.name } }, "*");
638
+ window.parent.postMessage({
639
+ type: "ow:schedule-connected",
640
+ schedule: { id: target.id, name: target.name },
641
+ insertAfter
642
+ }, "*");
643
+ window.postMessage({ type: "ow:schedule-linked", scheduleId: target.id, insertAfter }, "*");
350
644
  }
351
645
  };
352
646
  window.addEventListener("message", handler);
353
- if (!startEmpty) window.parent.postMessage({ type: "ow:request-user-schedules" }, "*");
647
+ if (!startEmpty) window.parent.postMessage({ type: "ow:request-user-schedules", insertAfter }, "*");
354
648
  return () => {
355
649
  window.removeEventListener("message", handler);
356
650
  if (timer) clearTimeout(timer);
@@ -394,31 +688,51 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId }) {
394
688
  return void 0;
395
689
  }
396
690
  })() : void 0;
691
+ const handleModalSubmit = async (email) => {
692
+ if (!modalState) return;
693
+ const { mode, classId, classDate } = modalState;
694
+ const endpoint = mode === "book" ? `${API_URL}/api/schedule/class/${classId}/booking` : `${API_URL}/api/schedule/class/${classId}/waitlist`;
695
+ const res = await fetch(endpoint, {
696
+ method: "POST",
697
+ headers: { "Content-Type": "application/json" },
698
+ body: JSON.stringify({ classDate: classDate.toISOString(), email })
699
+ });
700
+ if (!res.ok) {
701
+ const data = await res.json().catch(() => ({}));
702
+ throw new Error(data?.message ?? "Something went wrong. Please try again.");
703
+ }
704
+ };
397
705
  const handleReplaceSchedule = () => {
398
706
  setIsHovered(false);
399
707
  if (schedule) {
400
- window.parent.postMessage({ type: "ow:schedule-connected", schedule: { id: schedule.id, name: schedule.name } }, "*");
708
+ window.parent.postMessage({
709
+ type: "ow:schedule-connected",
710
+ schedule: { id: schedule.id, name: schedule.name },
711
+ insertAfter
712
+ }, "*");
401
713
  } else {
402
- window.parent.postMessage({ type: "ow:scheduling-not-connected" }, "*");
714
+ window.parent.postMessage({ type: "ow:scheduling-not-connected", insertAfter }, "*");
403
715
  }
404
716
  };
405
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
717
+ const sectionId = `scheduling-${insertAfter}`;
718
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
406
719
  "section",
407
720
  {
408
- "data-ohw-section": "scheduling",
409
- className: "w-full box-border py-20 px-16 font-body bg-(--color-light,#FEFFF0) relative",
721
+ "data-ohw-section": sectionId,
722
+ "data-ohw-scheduling-anchor": insertAfter,
723
+ className: "w-full box-border py-10 px-5 sm:py-20 sm:px-16 font-body bg-(--color-light,#FEFFF0) relative",
410
724
  onMouseEnter: () => inEditor && setIsHovered(true),
411
725
  onMouseLeave: () => setIsHovered(false),
412
726
  children: [
413
- inEditor && isHovered && !!schedule && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
727
+ inEditor && isHovered && !!schedule && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
414
728
  "div",
415
729
  {
416
730
  className: "absolute inset-0 z-10 pointer-events-auto cursor-pointer",
417
731
  onClick: handleReplaceSchedule,
418
732
  children: [
419
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute inset-0", style: { background: "#0885FE", opacity: 0.18 } }),
420
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute inset-0", style: { boxShadow: "inset 0 0 0 1.5px #0885FE" } }),
421
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute inset-0 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
733
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "absolute inset-0", style: { background: "#0885FE", opacity: 0.18 } }),
734
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "absolute inset-0", style: { boxShadow: "inset 0 0 0 1.5px #0885FE" } }),
735
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "absolute inset-0 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
422
736
  "div",
423
737
  {
424
738
  className: "bg-white border border-[#E7E5E4] rounded-md px-3 py-1.5 flex items-center gap-1.5",
@@ -430,7 +744,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId }) {
430
744
  color: "#0C0A09"
431
745
  },
432
746
  children: [
433
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CalendarFoldIcon, {}),
747
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CalendarFoldIcon, {}),
434
748
  "Replace schedule"
435
749
  ]
436
750
  }
@@ -438,24 +752,34 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId }) {
438
752
  ]
439
753
  }
440
754
  ),
441
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
442
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col items-center gap-4", children: [
443
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "font-display text-5xl font-bold text-center m-0 text-(--color-dark,#200C02)", children: schedule?.name ?? "Book an appointment" }),
444
- schedule?.description && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "font-body text-body text-center m-0 text-(--color-accent,#A89B83)", children: schedule.description })
755
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
756
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-col items-center gap-4", children: [
757
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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" }),
758
+ schedule?.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "font-body text-body text-center m-0 text-(--color-accent,#A89B83)", children: schedule.description })
445
759
  ] }),
446
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "w-full flex flex-col items-end gap-3", children: [
447
- timezoneLabel && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-body text-sm font-normal text-(--color-accent,#A89B83)", children: timezoneLabel }),
448
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-full p-10 box-border", children: loading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoadingSkeleton, {}) : !schedule ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmptyState, { inEditor }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
760
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "w-full flex flex-col items-end gap-3", children: [
761
+ timezoneLabel && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-sm font-normal text-(--color-accent,#A89B83)", children: timezoneLabel }),
762
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "w-full p-0 sm:p-10 box-border", children: loading ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LoadingSkeleton, {}) : !schedule ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(EmptyState, { inEditor }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
449
763
  ScheduleView,
450
764
  {
451
765
  schedule,
452
766
  dates,
453
767
  selectedIdx,
454
- onSelectDate: setSelectedIdx
768
+ onSelectDate: setSelectedIdx,
769
+ onOpenModal: inEditor ? void 0 : (mode, classId, classDate) => setModalState({ mode, classId, classDate })
455
770
  }
456
771
  ) })
457
772
  ] })
458
- ] })
773
+ ] }),
774
+ modalState && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
775
+ EmailCaptureModal,
776
+ {
777
+ title: modalState.mode === "book" ? "Confirm your spot" : "Leave your email",
778
+ subtitle: modalState.mode === "book" ? "We'll send your booking confirmation here." : "We'll let you know when spots open up!",
779
+ onSubmit: handleModalSubmit,
780
+ onClose: () => setModalState(null)
781
+ }
782
+ )
459
783
  ]
460
784
  }
461
785
  );
@@ -3781,8 +4105,8 @@ var cva = (base, config) => (props) => {
3781
4105
  };
3782
4106
 
3783
4107
  // src/ui/toggle.tsx
3784
- var import_radix_ui = require("radix-ui");
3785
- var import_jsx_runtime2 = require("react/jsx-runtime");
4108
+ var import_radix_ui2 = require("radix-ui");
4109
+ var import_jsx_runtime3 = require("react/jsx-runtime");
3786
4110
  var toggleVariants = cva(
3787
4111
  "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",
3788
4112
  {
@@ -3809,8 +4133,8 @@ function Toggle({
3809
4133
  size,
3810
4134
  ...props
3811
4135
  }) {
3812
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3813
- import_radix_ui.Toggle.Root,
4136
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
4137
+ import_radix_ui2.Toggle.Root,
3814
4138
  {
3815
4139
  "data-slot": "toggle",
3816
4140
  className: cn(toggleVariants({ variant, size, className })),
@@ -3820,7 +4144,7 @@ function Toggle({
3820
4144
  }
3821
4145
 
3822
4146
  // src/ui/toggle-group.tsx
3823
- var import_jsx_runtime3 = require("react/jsx-runtime");
4147
+ var import_jsx_runtime4 = require("react/jsx-runtime");
3824
4148
  var ToggleGroupContext = React2.createContext({
3825
4149
  value: "",
3826
4150
  onValueChange: () => {
@@ -3833,13 +4157,13 @@ function ToggleGroup({
3833
4157
  children,
3834
4158
  ...props
3835
4159
  }) {
3836
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
4160
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3837
4161
  "div",
3838
4162
  {
3839
4163
  role: "group",
3840
4164
  className: cn("flex items-center gap-1 p-1 bg-muted rounded-md", className),
3841
4165
  ...props,
3842
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ToggleGroupContext.Provider, { value: { value, onValueChange }, children })
4166
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ToggleGroupContext.Provider, { value: { value, onValueChange }, children })
3843
4167
  }
3844
4168
  );
3845
4169
  }
@@ -3850,7 +4174,7 @@ function ToggleGroupItem({
3850
4174
  ...props
3851
4175
  }) {
3852
4176
  const { value: groupValue, onValueChange } = React2.useContext(ToggleGroupContext);
3853
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
4177
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3854
4178
  Toggle,
3855
4179
  {
3856
4180
  pressed: groupValue === value,
@@ -3870,7 +4194,7 @@ function ToggleGroupItem({
3870
4194
  }
3871
4195
 
3872
4196
  // src/OhhwellsBridge.tsx
3873
- var import_react_dom = require("react-dom");
4197
+ var import_react_dom2 = require("react-dom");
3874
4198
  var import_navigation = require("next/navigation");
3875
4199
 
3876
4200
  // src/lib/session-search.ts
@@ -3892,7 +4216,7 @@ function isEditSessionActive() {
3892
4216
  }
3893
4217
 
3894
4218
  // src/ui/badge.tsx
3895
- var import_jsx_runtime4 = require("react/jsx-runtime");
4219
+ var import_jsx_runtime5 = require("react/jsx-runtime");
3896
4220
  var badgeVariants = cva(
3897
4221
  "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",
3898
4222
  {
@@ -3910,11 +4234,11 @@ var badgeVariants = cva(
3910
4234
  }
3911
4235
  );
3912
4236
  function Badge({ className, variant, ...props }) {
3913
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
4237
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
3914
4238
  }
3915
4239
 
3916
4240
  // src/OhhwellsBridge.tsx
3917
- var import_jsx_runtime5 = require("react/jsx-runtime");
4241
+ var import_jsx_runtime6 = require("react/jsx-runtime");
3918
4242
  var PRIMARY = "#0885FE";
3919
4243
  var IMAGE_FADE_MS = 300;
3920
4244
  function runOpacityFade(el, onDone) {
@@ -3975,24 +4299,135 @@ function getSectionsTracker() {
3975
4299
  }
3976
4300
  return el;
3977
4301
  }
3978
- function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId) {
3979
- const anchor = document.querySelector(`[data-ohw-section="${insertAfter}"]`);
3980
- if (!anchor) return false;
3981
- if (anchor.nextElementSibling?.dataset.ohwSectionContainer) return false;
4302
+ function updateSectionScheduleId(insertAfter, scheduleId) {
4303
+ const tracker = getSectionsTracker();
4304
+ let sections = [];
4305
+ try {
4306
+ sections = JSON.parse(tracker.textContent || "[]");
4307
+ } catch {
4308
+ }
4309
+ const currentPath = window.location.pathname;
4310
+ const updated = sections.map((s) => {
4311
+ if (s.type !== "scheduling" || s.insertAfter !== insertAfter) return s;
4312
+ if (s.pagePath && s.pagePath !== currentPath) return s;
4313
+ return { ...s, scheduleId };
4314
+ });
4315
+ tracker.textContent = JSON.stringify(updated);
4316
+ return tracker.textContent ?? "[]";
4317
+ }
4318
+ function schedulingSectionId(insertAfter) {
4319
+ return `scheduling-${insertAfter}`;
4320
+ }
4321
+ var INSERT_BEFORE_MARKER = ":before:";
4322
+ function parseSchedulingInsertAfter(insertAfter) {
4323
+ const idx = insertAfter.indexOf(INSERT_BEFORE_MARKER);
4324
+ if (idx < 0) return { anchor: insertAfter, insertBefore: null };
4325
+ return {
4326
+ anchor: insertAfter.slice(0, idx),
4327
+ insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
4328
+ };
4329
+ }
4330
+ function resolveSchedulingInsert(insertAfter, explicitInsertBefore) {
4331
+ const parsed = parseSchedulingInsertAfter(insertAfter);
4332
+ const insertBefore = explicitInsertBefore ?? parsed.insertBefore;
4333
+ const effectiveInsertAfter = insertBefore && parsed.insertBefore === null ? `${insertAfter}${INSERT_BEFORE_MARKER}${insertBefore}` : insertAfter;
4334
+ return { effectiveInsertAfter, insertBefore };
4335
+ }
4336
+ function getSchedulingMountPoint(insertAfter) {
4337
+ const { anchor } = parseSchedulingInsertAfter(insertAfter);
4338
+ let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
4339
+ if (!anchorEl && anchor === "scheduling") {
4340
+ const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
4341
+ anchorEl = widgets.at(-1) ?? null;
4342
+ }
4343
+ if (!anchorEl) return null;
4344
+ return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
4345
+ }
4346
+ function schedulingMountDepth(insertAfter) {
4347
+ if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
4348
+ return insertAfter.split(INSERT_BEFORE_MARKER).length - 1;
4349
+ }
4350
+ function getPageSchedulingEntries(raw) {
4351
+ if (!raw) return [];
4352
+ try {
4353
+ const entries = JSON.parse(raw);
4354
+ const currentPath = window.location.pathname;
4355
+ return entries.filter((e) => e.type === "scheduling" && (!e.pagePath || e.pagePath === currentPath));
4356
+ } catch {
4357
+ return [];
4358
+ }
4359
+ }
4360
+ function isSchedulingWidgetMissing(entry) {
4361
+ const { effectiveInsertAfter } = resolveSchedulingInsert(entry.insertAfter);
4362
+ return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
4363
+ }
4364
+ function hasMissingSchedulingWidgets(entries) {
4365
+ return entries.some(isSchedulingWidgetMissing);
4366
+ }
4367
+ function retryMissingSchedulingMounts(entries, notifyOnConnect = false) {
4368
+ if (!hasMissingSchedulingWidgets(entries)) return;
4369
+ mountSchedulingEntries(entries, notifyOnConnect);
4370
+ }
4371
+ function initSectionsFromContent(content, removeExisting = false) {
4372
+ const raw = content["__ohw_sections"];
4373
+ if (!raw) return;
4374
+ try {
4375
+ if (removeExisting) {
4376
+ document.querySelectorAll('[data-ohw-section-container="scheduling"]').forEach((el) => el.remove());
4377
+ }
4378
+ const inEditor = typeof window !== "undefined" && window.self !== window.top;
4379
+ if (inEditor) getSectionsTracker().textContent = raw;
4380
+ const pageEntries = getPageSchedulingEntries(raw);
4381
+ mountSchedulingEntries(pageEntries, false);
4382
+ requestAnimationFrame(() => retryMissingSchedulingMounts(pageEntries, false));
4383
+ setTimeout(() => retryMissingSchedulingMounts(pageEntries, false), 250);
4384
+ } catch {
4385
+ }
4386
+ }
4387
+ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId, explicitInsertBefore) {
4388
+ const { effectiveInsertAfter, insertBefore } = resolveSchedulingInsert(insertAfter, explicitInsertBefore);
4389
+ const sectionId = schedulingSectionId(effectiveInsertAfter);
4390
+ if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
4391
+ const mountPoint = getSchedulingMountPoint(effectiveInsertAfter);
4392
+ if (!mountPoint) return false;
3982
4393
  const container = document.createElement("div");
3983
4394
  container.dataset.ohwSectionContainer = "scheduling";
3984
- anchor.insertAdjacentElement("afterend", container);
3985
- (0, import_client.createRoot)(container).render(/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SchedulingWidget, { notifyOnConnect, initialScheduleId: scheduleId }));
4395
+ if (insertBefore) {
4396
+ const beforeAnchor = document.querySelector(`[data-ohw-section="${insertBefore}"]`);
4397
+ const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
4398
+ if (!beforePoint) return false;
4399
+ beforePoint.insertAdjacentElement("beforebegin", container);
4400
+ } else {
4401
+ let tail = mountPoint;
4402
+ while (tail.nextElementSibling?.dataset.ohwSectionContainer === "scheduling") {
4403
+ tail = tail.nextElementSibling;
4404
+ }
4405
+ tail.insertAdjacentElement("afterend", container);
4406
+ }
4407
+ const root = (0, import_client.createRoot)(container);
4408
+ (0, import_react_dom.flushSync)(() => {
4409
+ root.render(
4410
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4411
+ SchedulingWidget,
4412
+ {
4413
+ notifyOnConnect,
4414
+ initialScheduleId: scheduleId,
4415
+ insertAfter: effectiveInsertAfter
4416
+ }
4417
+ )
4418
+ );
4419
+ });
3986
4420
  const tracker = getSectionsTracker();
3987
4421
  let sections = [];
3988
4422
  try {
3989
4423
  sections = JSON.parse(tracker.textContent || "[]");
3990
4424
  } catch {
3991
4425
  }
3992
- if (!sections.find((s) => s.type === "scheduling" && s.insertAfter === insertAfter)) {
4426
+ const inEditor = typeof window !== "undefined" && window.self !== window.top;
4427
+ if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === effectiveInsertAfter)) {
3993
4428
  sections.push({
3994
4429
  type: "scheduling",
3995
- insertAfter,
4430
+ insertAfter: effectiveInsertAfter,
3996
4431
  pagePath: window.location.pathname,
3997
4432
  ...scheduleId ? { scheduleId } : {}
3998
4433
  });
@@ -4000,6 +4435,17 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId)
4000
4435
  }
4001
4436
  return true;
4002
4437
  }
4438
+ function mountSchedulingEntries(entries, notifyOnConnect = false) {
4439
+ const pending = entries.filter((e) => e.type === "scheduling").sort((a, b) => schedulingMountDepth(a.insertAfter) - schedulingMountDepth(b.insertAfter));
4440
+ for (let attempt = 0; attempt < pending.length + 1 && pending.length > 0; attempt++) {
4441
+ for (let i = pending.length - 1; i >= 0; i--) {
4442
+ const { insertAfter, scheduleId } = pending[i];
4443
+ if (mountSchedulingWidget(insertAfter, notifyOnConnect, scheduleId)) {
4444
+ pending.splice(i, 1);
4445
+ }
4446
+ }
4447
+ }
4448
+ }
4003
4449
  function collectEditableNodes() {
4004
4450
  return Array.from(document.querySelectorAll("[data-ohw-editable]")).map((el) => {
4005
4451
  if (el.dataset.ohwEditable === "image") {
@@ -4157,7 +4603,7 @@ var TOOLBAR_GROUPS = [
4157
4603
  ];
4158
4604
  function GlowFrame({ rect, elRef }) {
4159
4605
  const GAP = 6;
4160
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4606
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4161
4607
  "div",
4162
4608
  {
4163
4609
  ref: elRef,
@@ -4208,7 +4654,7 @@ function FloatingToolbar({
4208
4654
  activeCommands
4209
4655
  }) {
4210
4656
  const { top, left, transform } = calcToolbarPos(rect, parentScroll);
4211
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4657
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4212
4658
  "div",
4213
4659
  {
4214
4660
  ref: elRef,
@@ -4231,11 +4677,11 @@ function FloatingToolbar({
4231
4677
  pointerEvents: "auto",
4232
4678
  whiteSpace: "nowrap"
4233
4679
  },
4234
- children: TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react2.default.Fragment, { children: [
4235
- gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
4680
+ children: TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react3.default.Fragment, { children: [
4681
+ gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
4236
4682
  btns.map((btn) => {
4237
4683
  const isActive = activeCommands.has(btn.cmd);
4238
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4684
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4239
4685
  "button",
4240
4686
  {
4241
4687
  title: btn.title,
@@ -4261,7 +4707,7 @@ function FloatingToolbar({
4261
4707
  flexShrink: 0,
4262
4708
  padding: 6
4263
4709
  },
4264
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4710
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4265
4711
  "svg",
4266
4712
  {
4267
4713
  width: "16",
@@ -4294,7 +4740,7 @@ function StateToggle({
4294
4740
  states,
4295
4741
  onStateChange
4296
4742
  }) {
4297
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4743
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4298
4744
  ToggleGroup,
4299
4745
  {
4300
4746
  "data-ohw-state-toggle": "",
@@ -4308,18 +4754,35 @@ function StateToggle({
4308
4754
  left: rect.right - 8,
4309
4755
  transform: "translateX(-100%)"
4310
4756
  },
4311
- children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
4757
+ children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
4312
4758
  }
4313
4759
  );
4314
4760
  }
4315
4761
  var contentCache = /* @__PURE__ */ new Map();
4762
+ function resolveSubdomain(subdomainFromQuery) {
4763
+ if (subdomainFromQuery) return subdomainFromQuery;
4764
+ if (typeof window !== "undefined") {
4765
+ const parts = window.location.hostname.split(".");
4766
+ if (parts.length >= 3 && parts[0] !== "www") return parts[0];
4767
+ }
4768
+ const siteUrl = process.env.NEXT_PUBLIC_SITE_URL;
4769
+ if (siteUrl) {
4770
+ try {
4771
+ const host = new URL(siteUrl).hostname;
4772
+ const siteParts = host.split(".");
4773
+ if (siteParts.length >= 3 && siteParts[0] !== "www") return siteParts[0];
4774
+ } catch {
4775
+ }
4776
+ }
4777
+ return "";
4778
+ }
4316
4779
  function OhhwellsBridge() {
4317
4780
  const pathname = (0, import_navigation.usePathname)();
4318
4781
  const router = (0, import_navigation.useRouter)();
4319
4782
  const searchParams = (0, import_navigation.useSearchParams)();
4320
4783
  const isEditMode = isEditSessionActive();
4321
- const [bridgeRoot, setBridgeRoot] = (0, import_react2.useState)(null);
4322
- (0, import_react2.useEffect)(() => {
4784
+ const [bridgeRoot, setBridgeRoot] = (0, import_react3.useState)(null);
4785
+ (0, import_react3.useEffect)(() => {
4323
4786
  const figtreeFontId = "ohw-figtree-font";
4324
4787
  if (!document.getElementById(figtreeFontId)) {
4325
4788
  const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
@@ -4342,44 +4805,40 @@ function OhhwellsBridge() {
4342
4805
  };
4343
4806
  }, []);
4344
4807
  const subdomainFromQuery = searchParams.get("subdomain");
4345
- const subdomain = subdomainFromQuery ?? (() => {
4346
- if (typeof window === "undefined") return "";
4347
- const parts = window.location.hostname.split(".");
4348
- return parts.length >= 3 && parts[0] !== "www" ? parts[0] : "";
4349
- })();
4350
- const postToParent = (0, import_react2.useCallback)((data) => {
4808
+ const subdomain = resolveSubdomain(subdomainFromQuery);
4809
+ const postToParent = (0, import_react3.useCallback)((data) => {
4351
4810
  if (typeof window !== "undefined" && window.parent !== window) {
4352
4811
  window.parent.postMessage(data, "*");
4353
4812
  }
4354
4813
  }, []);
4355
- const [fetchState, setFetchState] = (0, import_react2.useState)("idle");
4356
- const autoSaveTimers = (0, import_react2.useRef)(/* @__PURE__ */ new Map());
4357
- const activeElRef = (0, import_react2.useRef)(null);
4358
- const originalContentRef = (0, import_react2.useRef)(null);
4359
- const activeStateElRef = (0, import_react2.useRef)(null);
4360
- const parentScrollRef = (0, import_react2.useRef)(null);
4361
- const toolbarElRef = (0, import_react2.useRef)(null);
4362
- const glowElRef = (0, import_react2.useRef)(null);
4363
- const hoveredImageRef = (0, import_react2.useRef)(null);
4364
- const hoveredImageHasTextOverlapRef = (0, import_react2.useRef)(false);
4365
- const hoveredGapRef = (0, import_react2.useRef)(null);
4366
- const imageUnhoverTimerRef = (0, import_react2.useRef)(null);
4367
- const imageShowTimerRef = (0, import_react2.useRef)(null);
4368
- const editStylesRef = (0, import_react2.useRef)(null);
4369
- const activateRef = (0, import_react2.useRef)(() => {
4814
+ const [fetchState, setFetchState] = (0, import_react3.useState)("idle");
4815
+ const autoSaveTimers = (0, import_react3.useRef)(/* @__PURE__ */ new Map());
4816
+ const activeElRef = (0, import_react3.useRef)(null);
4817
+ const originalContentRef = (0, import_react3.useRef)(null);
4818
+ const activeStateElRef = (0, import_react3.useRef)(null);
4819
+ const parentScrollRef = (0, import_react3.useRef)(null);
4820
+ const toolbarElRef = (0, import_react3.useRef)(null);
4821
+ const glowElRef = (0, import_react3.useRef)(null);
4822
+ const hoveredImageRef = (0, import_react3.useRef)(null);
4823
+ const hoveredImageHasTextOverlapRef = (0, import_react3.useRef)(false);
4824
+ const hoveredGapRef = (0, import_react3.useRef)(null);
4825
+ const imageUnhoverTimerRef = (0, import_react3.useRef)(null);
4826
+ const imageShowTimerRef = (0, import_react3.useRef)(null);
4827
+ const editStylesRef = (0, import_react3.useRef)(null);
4828
+ const activateRef = (0, import_react3.useRef)(() => {
4370
4829
  });
4371
- const deactivateRef = (0, import_react2.useRef)(() => {
4830
+ const deactivateRef = (0, import_react3.useRef)(() => {
4372
4831
  });
4373
- const refreshActiveCommandsRef = (0, import_react2.useRef)(() => {
4832
+ const refreshActiveCommandsRef = (0, import_react3.useRef)(() => {
4374
4833
  });
4375
- const postToParentRef = (0, import_react2.useRef)(postToParent);
4834
+ const postToParentRef = (0, import_react3.useRef)(postToParent);
4376
4835
  postToParentRef.current = postToParent;
4377
- const [toolbarRect, setToolbarRect] = (0, import_react2.useState)(null);
4378
- const [toggleState, setToggleState] = (0, import_react2.useState)(null);
4379
- const [maxBadge, setMaxBadge] = (0, import_react2.useState)(null);
4380
- const [activeCommands, setActiveCommands] = (0, import_react2.useState)(/* @__PURE__ */ new Set());
4381
- const [sectionGap, setSectionGap] = (0, import_react2.useState)(null);
4382
- (0, import_react2.useEffect)(() => {
4836
+ const [toolbarRect, setToolbarRect] = (0, import_react3.useState)(null);
4837
+ const [toggleState, setToggleState] = (0, import_react3.useState)(null);
4838
+ const [maxBadge, setMaxBadge] = (0, import_react3.useState)(null);
4839
+ const [activeCommands, setActiveCommands] = (0, import_react3.useState)(/* @__PURE__ */ new Set());
4840
+ const [sectionGap, setSectionGap] = (0, import_react3.useState)(null);
4841
+ (0, import_react3.useEffect)(() => {
4383
4842
  const update = () => {
4384
4843
  const el = activeElRef.current;
4385
4844
  if (el) setToolbarRect(el.getBoundingClientRect());
@@ -4403,10 +4862,10 @@ function OhhwellsBridge() {
4403
4862
  vvp.removeEventListener("resize", update);
4404
4863
  };
4405
4864
  }, []);
4406
- const refreshStateRules = (0, import_react2.useCallback)(() => {
4865
+ const refreshStateRules = (0, import_react3.useCallback)(() => {
4407
4866
  editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
4408
4867
  }, []);
4409
- const deactivate = (0, import_react2.useCallback)(() => {
4868
+ const deactivate = (0, import_react3.useCallback)(() => {
4410
4869
  const el = activeElRef.current;
4411
4870
  if (!el) return;
4412
4871
  const key = el.dataset.ohwKey;
@@ -4431,7 +4890,7 @@ function OhhwellsBridge() {
4431
4890
  setActiveCommands(/* @__PURE__ */ new Set());
4432
4891
  postToParent({ type: "ow:exit-edit" });
4433
4892
  }, [postToParent]);
4434
- const activate = (0, import_react2.useCallback)((el) => {
4893
+ const activate = (0, import_react3.useCallback)((el) => {
4435
4894
  if (activeElRef.current === el) return;
4436
4895
  deactivate();
4437
4896
  if (hoveredImageRef.current) {
@@ -4449,25 +4908,13 @@ function OhhwellsBridge() {
4449
4908
  }, [deactivate, postToParent]);
4450
4909
  activateRef.current = activate;
4451
4910
  deactivateRef.current = deactivate;
4452
- (0, import_react2.useLayoutEffect)(() => {
4911
+ (0, import_react3.useLayoutEffect)(() => {
4453
4912
  if (!subdomain || isEditMode) {
4454
4913
  setFetchState("done");
4455
4914
  return;
4456
4915
  }
4457
4916
  const applyContent = (content) => {
4458
4917
  const imageLoads = [];
4459
- document.querySelectorAll("[data-ohw-section-container]").forEach((el) => el.remove());
4460
- if (content["__ohw_sections"]) {
4461
- try {
4462
- const entries = JSON.parse(content["__ohw_sections"]);
4463
- const currentPath = window.location.pathname;
4464
- entries.forEach(({ type, insertAfter, scheduleId, pagePath }) => {
4465
- if (pagePath && pagePath !== currentPath) return;
4466
- if (type === "scheduling") mountSchedulingWidget(insertAfter, false, scheduleId);
4467
- });
4468
- } catch {
4469
- }
4470
- }
4471
4918
  for (const [key, val] of Object.entries(content)) {
4472
4919
  if (key === "__ohw_sections") continue;
4473
4920
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -4488,6 +4935,7 @@ function OhhwellsBridge() {
4488
4935
  }
4489
4936
  });
4490
4937
  }
4938
+ initSectionsFromContent(content, true);
4491
4939
  return imageLoads.length > 0 ? Promise.all(imageLoads).then(() => {
4492
4940
  }) : Promise.resolve();
4493
4941
  };
@@ -4512,22 +4960,13 @@ function OhhwellsBridge() {
4512
4960
  cancelled = true;
4513
4961
  };
4514
4962
  }, [subdomain, isEditMode, pathname]);
4515
- (0, import_react2.useEffect)(() => {
4963
+ (0, import_react3.useEffect)(() => {
4516
4964
  if (!subdomain || isEditMode) return;
4965
+ let debounceTimer = null;
4517
4966
  const applyFromCache = () => {
4518
4967
  const content = contentCache.get(subdomain);
4519
4968
  if (!content) return;
4520
- if (content["__ohw_sections"]) {
4521
- try {
4522
- const entries = JSON.parse(content["__ohw_sections"]);
4523
- const currentPath = window.location.pathname;
4524
- entries.forEach(({ type, insertAfter, scheduleId, pagePath }) => {
4525
- if (pagePath && pagePath !== currentPath) return;
4526
- if (type === "scheduling") mountSchedulingWidget(insertAfter, false, scheduleId);
4527
- });
4528
- } catch {
4529
- }
4530
- }
4969
+ retryMissingSchedulingMounts(getPageSchedulingEntries(content["__ohw_sections"]), false);
4531
4970
  for (const [key, val] of Object.entries(content)) {
4532
4971
  if (key === "__ohw_sections") continue;
4533
4972
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -4543,21 +4982,28 @@ function OhhwellsBridge() {
4543
4982
  });
4544
4983
  }
4545
4984
  };
4546
- applyFromCache();
4547
- const observer = new MutationObserver(applyFromCache);
4985
+ const scheduleApply = () => {
4986
+ if (debounceTimer) clearTimeout(debounceTimer);
4987
+ debounceTimer = setTimeout(applyFromCache, 150);
4988
+ };
4989
+ scheduleApply();
4990
+ const observer = new MutationObserver(scheduleApply);
4548
4991
  observer.observe(document.body, { childList: true, subtree: true });
4549
- return () => observer.disconnect();
4550
- }, [subdomain, isEditMode]);
4551
- (0, import_react2.useLayoutEffect)(() => {
4992
+ return () => {
4993
+ observer.disconnect();
4994
+ if (debounceTimer) clearTimeout(debounceTimer);
4995
+ };
4996
+ }, [subdomain, isEditMode, pathname]);
4997
+ (0, import_react3.useLayoutEffect)(() => {
4552
4998
  const el = document.getElementById("ohw-loader");
4553
4999
  if (!el) return;
4554
5000
  const visible = Boolean(subdomain) && fetchState !== "done";
4555
5001
  el.style.display = visible ? "flex" : "none";
4556
5002
  }, [subdomain, fetchState]);
4557
- (0, import_react2.useEffect)(() => {
5003
+ (0, import_react3.useEffect)(() => {
4558
5004
  postToParent({ type: "ow:navigation", path: pathname });
4559
5005
  }, [pathname, postToParent]);
4560
- (0, import_react2.useEffect)(() => {
5006
+ (0, import_react3.useEffect)(() => {
4561
5007
  if (!isEditMode) return;
4562
5008
  const measure = () => {
4563
5009
  const h = document.body.scrollHeight;
@@ -4581,7 +5027,7 @@ function OhhwellsBridge() {
4581
5027
  window.removeEventListener("resize", handleResize);
4582
5028
  };
4583
5029
  }, [pathname, isEditMode, postToParent]);
4584
- (0, import_react2.useEffect)(() => {
5030
+ (0, import_react3.useEffect)(() => {
4585
5031
  if (!subdomainFromQuery || isEditMode) return;
4586
5032
  const handleClick = (e) => {
4587
5033
  const anchor = e.target.closest("a");
@@ -4597,7 +5043,7 @@ function OhhwellsBridge() {
4597
5043
  document.addEventListener("click", handleClick, true);
4598
5044
  return () => document.removeEventListener("click", handleClick, true);
4599
5045
  }, [subdomainFromQuery, isEditMode, router]);
4600
- (0, import_react2.useEffect)(() => {
5046
+ (0, import_react3.useEffect)(() => {
4601
5047
  if (!isEditMode) {
4602
5048
  editStylesRef.current?.base.remove();
4603
5049
  editStylesRef.current?.forceHover.remove();
@@ -5120,17 +5566,10 @@ function OhhwellsBridge() {
5120
5566
  if (e.data?.type !== "ow:hydrate") return;
5121
5567
  const content = e.data.content;
5122
5568
  if (!content) return;
5569
+ let sectionsJson = null;
5123
5570
  for (const [key, val] of Object.entries(content)) {
5124
5571
  if (key === "__ohw_sections") {
5125
- try {
5126
- const entries = JSON.parse(val);
5127
- const tracker = getSectionsTracker();
5128
- tracker.textContent = val;
5129
- entries.forEach(({ type, insertAfter, scheduleId }) => {
5130
- if (type === "scheduling") mountSchedulingWidget(insertAfter, false, scheduleId);
5131
- });
5132
- } catch {
5133
- }
5572
+ sectionsJson = val;
5134
5573
  continue;
5135
5574
  }
5136
5575
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -5144,6 +5583,9 @@ function OhhwellsBridge() {
5144
5583
  }
5145
5584
  });
5146
5585
  }
5586
+ if (sectionsJson) {
5587
+ initSectionsFromContent({ __ohw_sections: sectionsJson }, true);
5588
+ }
5147
5589
  postToParentRef.current({ type: "ow:hydrate-done" });
5148
5590
  };
5149
5591
  window.addEventListener("message", handleHydrate);
@@ -5194,9 +5636,9 @@ function OhhwellsBridge() {
5194
5636
  };
5195
5637
  const handleInsertSection = (e) => {
5196
5638
  if (e.data?.type !== "ow:insert-section") return;
5197
- const { widgetType, insertAfter } = e.data;
5639
+ const { widgetType, insertAfter, insertBefore } = e.data;
5198
5640
  if (widgetType !== "scheduling") return;
5199
- const inserted = mountSchedulingWidget(insertAfter, true);
5641
+ const inserted = mountSchedulingWidget(insertAfter, true, void 0, insertBefore ?? null);
5200
5642
  if (inserted) {
5201
5643
  const tracker = getSectionsTracker();
5202
5644
  postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
@@ -5207,39 +5649,31 @@ function OhhwellsBridge() {
5207
5649
  const handleSwitchSchedule = (e) => {
5208
5650
  if (e.data?.type !== "ow:switch-schedule") return;
5209
5651
  const scheduleId = e.data.scheduleId;
5210
- if (!scheduleId) return;
5211
- const tracker = getSectionsTracker();
5212
- let sections = [];
5213
- try {
5214
- sections = JSON.parse(tracker.textContent || "[]");
5215
- } catch {
5216
- }
5217
- const currentPath = window.location.pathname;
5218
- const updated = sections.map(
5219
- (s) => s.type === "scheduling" && s.pagePath === currentPath ? { ...s, scheduleId } : s
5220
- );
5221
- tracker.textContent = JSON.stringify(updated);
5222
- postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent }] });
5652
+ const insertAfter = e.data.insertAfter;
5653
+ if (!scheduleId || !insertAfter) return;
5654
+ const text = updateSectionScheduleId(insertAfter, scheduleId);
5655
+ postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text }] });
5656
+ };
5657
+ const handleScheduleLinked = (e) => {
5658
+ if (e.data?.type !== "ow:schedule-linked") return;
5659
+ const scheduleId = e.data.scheduleId;
5660
+ const insertAfter = e.data.insertAfter;
5661
+ if (!scheduleId || !insertAfter) return;
5662
+ const text = updateSectionScheduleId(insertAfter, scheduleId);
5663
+ postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text }] });
5223
5664
  };
5224
5665
  const handleClearSchedulingWidget = (e) => {
5225
5666
  if (e.data?.type !== "ow:clear-scheduling-widget") return;
5226
- const tracker = getSectionsTracker();
5227
- let sections = [];
5228
- try {
5229
- sections = JSON.parse(tracker.textContent || "[]");
5230
- } catch {
5231
- }
5232
- const currentPath = window.location.pathname;
5233
- const updated = sections.map(
5234
- (s) => s.type === "scheduling" && s.pagePath === currentPath ? { ...s, scheduleId: null } : s
5235
- );
5236
- tracker.textContent = JSON.stringify(updated);
5237
- postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent }] });
5667
+ const insertAfter = e.data.insertAfter;
5668
+ if (!insertAfter) return;
5669
+ const text = updateSectionScheduleId(insertAfter, null);
5670
+ postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text }] });
5238
5671
  };
5239
5672
  const handleRemoveSchedulingSection = (e) => {
5240
5673
  if (e.data?.type !== "ow:remove-scheduling-section") return;
5241
- const els = document.querySelectorAll('[data-ohw-section="scheduling"]');
5242
- els.forEach((el) => el.parentElement?.removeChild(el));
5674
+ document.querySelectorAll('[data-ohw-section-container="scheduling"]').forEach((el) => {
5675
+ el.remove();
5676
+ });
5243
5677
  const tracker = getSectionsTracker();
5244
5678
  let sections = [];
5245
5679
  try {
@@ -5358,6 +5792,7 @@ function OhhwellsBridge() {
5358
5792
  window.addEventListener("message", handleSave);
5359
5793
  window.addEventListener("message", handleInsertSection);
5360
5794
  window.addEventListener("message", handleSwitchSchedule);
5795
+ window.addEventListener("message", handleScheduleLinked);
5361
5796
  window.addEventListener("message", handleClearSchedulingWidget);
5362
5797
  window.addEventListener("message", handleRemoveSchedulingSection);
5363
5798
  window.addEventListener("message", handleImageUrl);
@@ -5396,6 +5831,7 @@ function OhhwellsBridge() {
5396
5831
  window.removeEventListener("message", handleSave);
5397
5832
  window.removeEventListener("message", handleInsertSection);
5398
5833
  window.removeEventListener("message", handleSwitchSchedule);
5834
+ window.removeEventListener("message", handleScheduleLinked);
5399
5835
  window.removeEventListener("message", handleClearSchedulingWidget);
5400
5836
  window.removeEventListener("message", handleRemoveSchedulingSection);
5401
5837
  window.removeEventListener("message", handleImageUrl);
@@ -5412,7 +5848,7 @@ function OhhwellsBridge() {
5412
5848
  if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
5413
5849
  };
5414
5850
  }, [isEditMode, refreshStateRules]);
5415
- (0, import_react2.useEffect)(() => {
5851
+ (0, import_react3.useEffect)(() => {
5416
5852
  if (!isEditMode) return;
5417
5853
  document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
5418
5854
  el.removeAttribute("data-ohw-active-state");
@@ -5434,13 +5870,13 @@ function OhhwellsBridge() {
5434
5870
  clearTimeout(timer);
5435
5871
  };
5436
5872
  }, [pathname, isEditMode, refreshStateRules, postToParent]);
5437
- const handleCommand = (0, import_react2.useCallback)((cmd) => {
5873
+ const handleCommand = (0, import_react3.useCallback)((cmd) => {
5438
5874
  document.execCommand(cmd, false);
5439
5875
  activeElRef.current?.focus();
5440
5876
  if (activeElRef.current) setToolbarRect(activeElRef.current.getBoundingClientRect());
5441
5877
  refreshActiveCommandsRef.current();
5442
5878
  }, []);
5443
- const handleStateChange = (0, import_react2.useCallback)((state) => {
5879
+ const handleStateChange = (0, import_react3.useCallback)((state) => {
5444
5880
  if (!activeStateElRef.current) return;
5445
5881
  const el = activeStateElRef.current;
5446
5882
  if (state === "Default") {
@@ -5453,13 +5889,13 @@ function OhhwellsBridge() {
5453
5889
  }
5454
5890
  setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
5455
5891
  }, [deactivate]);
5456
- return bridgeRoot ? (0, import_react_dom.createPortal)(
5457
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
5458
- toolbarRect && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
5459
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(GlowFrame, { rect: toolbarRect, elRef: glowElRef }),
5460
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FloatingToolbar, { rect: toolbarRect, parentScroll: parentScrollRef.current, elRef: toolbarElRef, onCommand: handleCommand, activeCommands })
5892
+ return bridgeRoot ? (0, import_react_dom2.createPortal)(
5893
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
5894
+ toolbarRect && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
5895
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(GlowFrame, { rect: toolbarRect, elRef: glowElRef }),
5896
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FloatingToolbar, { rect: toolbarRect, parentScroll: parentScrollRef.current, elRef: toolbarElRef, onCommand: handleCommand, activeCommands })
5461
5897
  ] }),
5462
- maxBadge && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
5898
+ maxBadge && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
5463
5899
  "div",
5464
5900
  {
5465
5901
  "data-ohw-max-badge": "",
@@ -5485,7 +5921,7 @@ function OhhwellsBridge() {
5485
5921
  ]
5486
5922
  }
5487
5923
  ),
5488
- toggleState && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
5924
+ toggleState && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5489
5925
  StateToggle,
5490
5926
  {
5491
5927
  rect: toggleState.rect,
@@ -5494,15 +5930,15 @@ function OhhwellsBridge() {
5494
5930
  onStateChange: handleStateChange
5495
5931
  }
5496
5932
  ),
5497
- sectionGap && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
5933
+ sectionGap && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
5498
5934
  "div",
5499
5935
  {
5500
5936
  "data-ohw-section-insert-line": "",
5501
5937
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
5502
5938
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
5503
5939
  children: [
5504
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
5505
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
5940
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
5941
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5506
5942
  Badge,
5507
5943
  {
5508
5944
  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",
@@ -5515,7 +5951,7 @@ function OhhwellsBridge() {
5515
5951
  children: "Add Section"
5516
5952
  }
5517
5953
  ),
5518
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
5954
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
5519
5955
  ]
5520
5956
  }
5521
5957
  )