@ohhwells/bridge 0.1.19 → 0.1.20
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 +415 -173
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +392 -150
- package/dist/index.js.map +1 -1
- package/dist/styles.css +114 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,12 +1,166 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/OhhwellsBridge.tsx
|
|
4
|
-
import React3, { useCallback, useEffect as useEffect2, useLayoutEffect, useRef, useState as
|
|
4
|
+
import React3, { useCallback, useEffect as useEffect2, useLayoutEffect, useRef as useRef2, useState as useState3 } from "react";
|
|
5
5
|
import { createRoot } from "react-dom/client";
|
|
6
6
|
|
|
7
7
|
// src/ui/SchedulingWidget.tsx
|
|
8
|
-
import
|
|
9
|
-
|
|
8
|
+
import { useEffect, useMemo, useRef, useState as useState2 } from "react";
|
|
9
|
+
|
|
10
|
+
// src/ui/EmailCaptureModal.tsx
|
|
11
|
+
import { useState } from "react";
|
|
12
|
+
import { Dialog } from "radix-ui";
|
|
13
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
14
|
+
function Spinner() {
|
|
15
|
+
return /* @__PURE__ */ jsxs(
|
|
16
|
+
"svg",
|
|
17
|
+
{
|
|
18
|
+
width: "32",
|
|
19
|
+
height: "32",
|
|
20
|
+
viewBox: "0 0 32 32",
|
|
21
|
+
fill: "none",
|
|
22
|
+
style: { animation: "ohw-spin 0.75s linear infinite" },
|
|
23
|
+
children: [
|
|
24
|
+
/* @__PURE__ */ jsx("style", { children: `@keyframes ohw-spin { to { transform: rotate(360deg); } }` }),
|
|
25
|
+
/* @__PURE__ */ jsx("circle", { cx: "16", cy: "16", r: "12", stroke: "#e5e7eb", strokeWidth: "3" }),
|
|
26
|
+
/* @__PURE__ */ jsx(
|
|
27
|
+
"path",
|
|
28
|
+
{
|
|
29
|
+
d: "M16 4a12 12 0 0 1 12 12",
|
|
30
|
+
stroke: "#3b82f6",
|
|
31
|
+
strokeWidth: "3",
|
|
32
|
+
strokeLinecap: "round"
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
|
|
40
|
+
const [email, setEmail] = useState("");
|
|
41
|
+
const [submittedEmail, setSubmittedEmail] = useState("");
|
|
42
|
+
const [loading, setLoading] = useState(false);
|
|
43
|
+
const [success, setSuccess] = useState(false);
|
|
44
|
+
const [error, setError] = useState(null);
|
|
45
|
+
const isBook = title === "Confirm your spot";
|
|
46
|
+
const handleSubmit = async () => {
|
|
47
|
+
if (!email.trim()) return;
|
|
48
|
+
setLoading(true);
|
|
49
|
+
setError(null);
|
|
50
|
+
try {
|
|
51
|
+
await onSubmit(email.trim());
|
|
52
|
+
setSubmittedEmail(email.trim());
|
|
53
|
+
setSuccess(true);
|
|
54
|
+
} catch (e) {
|
|
55
|
+
setError(e instanceof Error ? e.message : "Something went wrong. Please try again.");
|
|
56
|
+
} finally {
|
|
57
|
+
setLoading(false);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const handleKeyDown = (e) => {
|
|
61
|
+
if (e.key === "Enter" && !loading) handleSubmit();
|
|
62
|
+
};
|
|
63
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: true, onOpenChange: (open) => {
|
|
64
|
+
if (!open) onClose();
|
|
65
|
+
}, children: /* @__PURE__ */ jsxs(Dialog.Portal, { children: [
|
|
66
|
+
/* @__PURE__ */ jsx(
|
|
67
|
+
Dialog.Overlay,
|
|
68
|
+
{
|
|
69
|
+
className: "fixed inset-0 z-50",
|
|
70
|
+
style: { background: "rgba(0,0,0,0.45)" }
|
|
71
|
+
}
|
|
72
|
+
),
|
|
73
|
+
/* @__PURE__ */ jsxs(
|
|
74
|
+
Dialog.Content,
|
|
75
|
+
{
|
|
76
|
+
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",
|
|
77
|
+
style: { maxWidth: 400 },
|
|
78
|
+
children: [
|
|
79
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3 p-6", children: [
|
|
80
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
81
|
+
/* @__PURE__ */ jsx(
|
|
82
|
+
Dialog.Title,
|
|
83
|
+
{
|
|
84
|
+
className: "font-body text-xl font-bold m-0 leading-tight",
|
|
85
|
+
style: { color: "var(--color-dark,#200C02)" },
|
|
86
|
+
children: success ? isBook ? "Reservation confirmed!" : "You're on the waitlist!" : title
|
|
87
|
+
}
|
|
88
|
+
),
|
|
89
|
+
/* @__PURE__ */ jsx(
|
|
90
|
+
Dialog.Description,
|
|
91
|
+
{
|
|
92
|
+
className: "font-body text-sm m-0",
|
|
93
|
+
style: { color: "#6B7280" },
|
|
94
|
+
children: success ? isBook ? `A confirmation email has been sent to ${submittedEmail}.` : "We'll let you know via email if someone cancels." : subtitle
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
] }),
|
|
98
|
+
/* @__PURE__ */ jsx(
|
|
99
|
+
Dialog.Close,
|
|
100
|
+
{
|
|
101
|
+
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",
|
|
102
|
+
style: { color: "#6B7280" },
|
|
103
|
+
"aria-label": "Close",
|
|
104
|
+
children: /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
105
|
+
/* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
106
|
+
/* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
107
|
+
] })
|
|
108
|
+
}
|
|
109
|
+
)
|
|
110
|
+
] }),
|
|
111
|
+
!success && (loading ? (
|
|
112
|
+
/* Loading state — full body replaced */
|
|
113
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center gap-3 px-7 py-12", children: [
|
|
114
|
+
/* @__PURE__ */ jsx(Spinner, {}),
|
|
115
|
+
/* @__PURE__ */ jsx("p", { className: "font-body text-sm m-0", style: { color: "#6B7280" }, children: "Please wait" })
|
|
116
|
+
] })
|
|
117
|
+
) : (
|
|
118
|
+
/* Email form */
|
|
119
|
+
/* @__PURE__ */ jsxs("div", { className: "px-7 pt-2 pb-6", children: [
|
|
120
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5 mb-8", children: [
|
|
121
|
+
/* @__PURE__ */ jsx("label", { className: "font-body text-sm font-medium", style: { color: "var(--color-dark,#200C02)" }, children: "Email" }),
|
|
122
|
+
/* @__PURE__ */ jsx(
|
|
123
|
+
"input",
|
|
124
|
+
{
|
|
125
|
+
type: "email",
|
|
126
|
+
value: email,
|
|
127
|
+
onChange: (e) => setEmail(e.target.value),
|
|
128
|
+
onKeyDown: handleKeyDown,
|
|
129
|
+
placeholder: "hello@gmail.com",
|
|
130
|
+
autoFocus: true,
|
|
131
|
+
className: "w-full h-10 px-3 rounded-lg border font-body text-sm outline-none box-border",
|
|
132
|
+
style: {
|
|
133
|
+
borderColor: "#E7E5E4",
|
|
134
|
+
background: "#fff",
|
|
135
|
+
color: "var(--color-dark,#200C02)"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
),
|
|
139
|
+
error && /* @__PURE__ */ jsx("p", { className: "font-body text-xs text-red-500 m-0", children: error })
|
|
140
|
+
] }),
|
|
141
|
+
/* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(
|
|
142
|
+
"button",
|
|
143
|
+
{
|
|
144
|
+
onClick: handleSubmit,
|
|
145
|
+
disabled: !email.trim(),
|
|
146
|
+
className: "h-9 px-5 rounded-lg font-body text-sm font-semibold cursor-pointer border-none disabled:opacity-50 disabled:cursor-not-allowed",
|
|
147
|
+
style: {
|
|
148
|
+
background: "var(--color-primary,#3D312B)",
|
|
149
|
+
color: "var(--color-light,#FEFFF0)"
|
|
150
|
+
},
|
|
151
|
+
children: "Send"
|
|
152
|
+
}
|
|
153
|
+
) })
|
|
154
|
+
] })
|
|
155
|
+
))
|
|
156
|
+
]
|
|
157
|
+
}
|
|
158
|
+
)
|
|
159
|
+
] }) });
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// src/ui/SchedulingWidget.tsx
|
|
163
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
10
164
|
var API_URL = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
11
165
|
var DAY_ABBR = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
|
|
12
166
|
function getApiDomain() {
|
|
@@ -67,8 +221,8 @@ function EmptyState({ inEditor }) {
|
|
|
67
221
|
window.parent.postMessage({ type: "ow:scheduling-not-connected" }, "*");
|
|
68
222
|
}
|
|
69
223
|
};
|
|
70
|
-
return /* @__PURE__ */
|
|
71
|
-
/* @__PURE__ */
|
|
224
|
+
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: [
|
|
225
|
+
/* @__PURE__ */ jsx2("div", { className: "w-10 h-10 bg-[#F5F5F4] rounded-[10px] flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsxs2(
|
|
72
226
|
"svg",
|
|
73
227
|
{
|
|
74
228
|
width: "20",
|
|
@@ -80,20 +234,20 @@ function EmptyState({ inEditor }) {
|
|
|
80
234
|
strokeLinecap: "round",
|
|
81
235
|
strokeLinejoin: "round",
|
|
82
236
|
children: [
|
|
83
|
-
/* @__PURE__ */
|
|
84
|
-
/* @__PURE__ */
|
|
85
|
-
/* @__PURE__ */
|
|
86
|
-
/* @__PURE__ */
|
|
87
|
-
/* @__PURE__ */
|
|
88
|
-
/* @__PURE__ */
|
|
237
|
+
/* @__PURE__ */ jsx2("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2" }),
|
|
238
|
+
/* @__PURE__ */ jsx2("line", { x1: "16", y1: "2", x2: "16", y2: "6" }),
|
|
239
|
+
/* @__PURE__ */ jsx2("line", { x1: "8", y1: "2", x2: "8", y2: "6" }),
|
|
240
|
+
/* @__PURE__ */ jsx2("line", { x1: "3", y1: "10", x2: "21", y2: "10" }),
|
|
241
|
+
/* @__PURE__ */ jsx2("line", { x1: "12", y1: "14", x2: "12", y2: "18" }),
|
|
242
|
+
/* @__PURE__ */ jsx2("line", { x1: "10", y1: "16", x2: "14", y2: "16" })
|
|
89
243
|
]
|
|
90
244
|
}
|
|
91
245
|
) }),
|
|
92
|
-
/* @__PURE__ */
|
|
93
|
-
/* @__PURE__ */
|
|
94
|
-
/* @__PURE__ */
|
|
246
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center gap-2", children: [
|
|
247
|
+
/* @__PURE__ */ jsx2("p", { className: "font-body text-lg font-medium text-center text-[#0A0A0A] m-0", children: "No schedule yet" }),
|
|
248
|
+
/* @__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." })
|
|
95
249
|
] }),
|
|
96
|
-
/* @__PURE__ */
|
|
250
|
+
/* @__PURE__ */ jsx2(
|
|
97
251
|
"button",
|
|
98
252
|
{
|
|
99
253
|
onClick: handleAddSchedule,
|
|
@@ -109,32 +263,56 @@ function LoadingSkeleton() {
|
|
|
109
263
|
backgroundSize: "200% 100%",
|
|
110
264
|
animation: "ohw-shimmer 1.5s infinite"
|
|
111
265
|
};
|
|
112
|
-
return /* @__PURE__ */
|
|
113
|
-
/* @__PURE__ */
|
|
114
|
-
/* @__PURE__ */
|
|
115
|
-
/* @__PURE__ */
|
|
116
|
-
/* @__PURE__ */
|
|
266
|
+
return /* @__PURE__ */ jsxs2("div", { className: "w-full flex flex-col gap-10", children: [
|
|
267
|
+
/* @__PURE__ */ jsx2("style", { children: `@keyframes ohw-shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}` }),
|
|
268
|
+
/* @__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: [
|
|
269
|
+
/* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "32px", height: "14px", borderRadius: "4px" } }),
|
|
270
|
+
/* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "40px", height: "40px", borderRadius: "50%" } })
|
|
117
271
|
] }, i)) }),
|
|
118
|
-
[0, 1, 2].map((i) => /* @__PURE__ */
|
|
119
|
-
/* @__PURE__ */
|
|
120
|
-
/* @__PURE__ */
|
|
121
|
-
/* @__PURE__ */
|
|
122
|
-
/* @__PURE__ */
|
|
123
|
-
/* @__PURE__ */
|
|
272
|
+
[0, 1, 2].map((i) => /* @__PURE__ */ jsxs2("div", { children: [
|
|
273
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-[60px] py-4", children: [
|
|
274
|
+
/* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "120px", height: "16px", borderRadius: "4px", flexShrink: 0 } }),
|
|
275
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex-1 flex flex-col gap-2", children: [
|
|
276
|
+
/* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "55%", height: "16px", borderRadius: "4px" } }),
|
|
277
|
+
/* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "38%", height: "14px", borderRadius: "4px" } })
|
|
124
278
|
] }),
|
|
125
|
-
/* @__PURE__ */
|
|
126
|
-
/* @__PURE__ */
|
|
279
|
+
/* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "56px", height: "32px", borderRadius: "4px", flexShrink: 0 } }),
|
|
280
|
+
/* @__PURE__ */ jsx2("div", { style: { ...shimmer, width: "200px", height: "44px", borderRadius: "8px", flexShrink: 0 } })
|
|
127
281
|
] }),
|
|
128
|
-
i < 2 && /* @__PURE__ */
|
|
282
|
+
i < 2 && /* @__PURE__ */ jsx2("div", { className: "h-px bg-black/20" })
|
|
129
283
|
] }, i))
|
|
130
284
|
] });
|
|
131
285
|
}
|
|
132
|
-
function ScheduleView({ schedule, dates, selectedIdx, onSelectDate }) {
|
|
286
|
+
function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal }) {
|
|
133
287
|
const todayMs = useMemo(() => {
|
|
134
288
|
const d = /* @__PURE__ */ new Date();
|
|
135
289
|
d.setHours(0, 0, 0, 0);
|
|
136
290
|
return d.getTime();
|
|
137
291
|
}, []);
|
|
292
|
+
const scrollRef = useRef(null);
|
|
293
|
+
const [canScrollLeft, setCanScrollLeft] = useState2(false);
|
|
294
|
+
const [canScrollRight, setCanScrollRight] = useState2(false);
|
|
295
|
+
const updateScrollState = () => {
|
|
296
|
+
const el = scrollRef.current;
|
|
297
|
+
if (!el) return;
|
|
298
|
+
setCanScrollLeft(el.scrollLeft > 0);
|
|
299
|
+
setCanScrollRight(el.scrollLeft + el.clientWidth < el.scrollWidth - 1);
|
|
300
|
+
};
|
|
301
|
+
useEffect(() => {
|
|
302
|
+
const el = scrollRef.current;
|
|
303
|
+
if (!el) return;
|
|
304
|
+
updateScrollState();
|
|
305
|
+
el.addEventListener("scroll", updateScrollState);
|
|
306
|
+
const ro = new ResizeObserver(updateScrollState);
|
|
307
|
+
ro.observe(el);
|
|
308
|
+
return () => {
|
|
309
|
+
el.removeEventListener("scroll", updateScrollState);
|
|
310
|
+
ro.disconnect();
|
|
311
|
+
};
|
|
312
|
+
}, [dates]);
|
|
313
|
+
const scroll = (dir) => {
|
|
314
|
+
scrollRef.current?.scrollBy({ left: dir === "left" ? -216 : 216, behavior: "smooth" });
|
|
315
|
+
};
|
|
138
316
|
const datesWithClasses = useMemo(
|
|
139
317
|
() => new Set(dates.map(
|
|
140
318
|
(d, i) => schedule.classes?.some((c) => classRunsOnDate(c, d, schedule.type)) ? i : -1
|
|
@@ -146,59 +324,94 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate }) {
|
|
|
146
324
|
() => (schedule.classes ?? []).filter((c) => selectedDate && classRunsOnDate(c, selectedDate, schedule.type)),
|
|
147
325
|
[schedule, selectedDate]
|
|
148
326
|
);
|
|
149
|
-
return /* @__PURE__ */
|
|
150
|
-
/* @__PURE__ */
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
327
|
+
return /* @__PURE__ */ jsxs2("div", { className: "w-full flex flex-col gap-10", children: [
|
|
328
|
+
/* @__PURE__ */ jsxs2("div", { className: "relative w-full", children: [
|
|
329
|
+
canScrollLeft && /* @__PURE__ */ jsx2(
|
|
330
|
+
"button",
|
|
331
|
+
{
|
|
332
|
+
onClick: () => scroll("left"),
|
|
333
|
+
className: "absolute left-0 top-1/2 -translate-y-1/2 z-10 w-8 h-8 flex items-center justify-center rounded-full border-none cursor-pointer",
|
|
334
|
+
style: { background: "var(--color-light,#FEFFF0)", boxShadow: "0 1px 4px rgba(0,0,0,0.15)" },
|
|
335
|
+
"aria-label": "Scroll left",
|
|
336
|
+
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" }) })
|
|
337
|
+
}
|
|
338
|
+
),
|
|
339
|
+
canScrollRight && /* @__PURE__ */ jsx2(
|
|
340
|
+
"button",
|
|
341
|
+
{
|
|
342
|
+
onClick: () => scroll("right"),
|
|
343
|
+
className: "absolute right-0 top-1/2 -translate-y-1/2 z-10 w-8 h-8 flex items-center justify-center rounded-full border-none cursor-pointer",
|
|
344
|
+
style: { background: "var(--color-light,#FEFFF0)", boxShadow: "0 1px 4px rgba(0,0,0,0.15)" },
|
|
345
|
+
"aria-label": "Scroll right",
|
|
346
|
+
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" }) })
|
|
347
|
+
}
|
|
348
|
+
),
|
|
349
|
+
/* @__PURE__ */ jsx2(
|
|
156
350
|
"div",
|
|
157
351
|
{
|
|
158
|
-
|
|
159
|
-
className:
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
352
|
+
ref: scrollRef,
|
|
353
|
+
className: "overflow-x-auto w-full",
|
|
354
|
+
style: {
|
|
355
|
+
scrollbarWidth: "none",
|
|
356
|
+
msOverflowStyle: "none",
|
|
357
|
+
paddingLeft: canScrollLeft ? "36px" : 0,
|
|
358
|
+
paddingRight: canScrollRight ? "36px" : 0
|
|
359
|
+
},
|
|
360
|
+
children: /* @__PURE__ */ jsx2("div", { className: "flex", style: { width: `max(100%, ${dates.length * 60}px)` }, children: dates.map((date, i) => {
|
|
361
|
+
const isToday = date.getTime() === todayMs;
|
|
362
|
+
const isSelected = i === selectedIdx;
|
|
363
|
+
const clickable = datesWithClasses.has(i);
|
|
364
|
+
const label = isToday ? "TODAY" : DAY_ABBR[date.getDay()];
|
|
365
|
+
return /* @__PURE__ */ jsxs2(
|
|
163
366
|
"div",
|
|
164
367
|
{
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
children:
|
|
168
|
-
"span",
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
368
|
+
onClick: () => clickable && onSelectDate(i),
|
|
369
|
+
className: `flex-1 h-[70px] flex flex-col justify-between items-center ${clickable ? "cursor-pointer opacity-100" : "cursor-default opacity-50"}`,
|
|
370
|
+
children: [
|
|
371
|
+
/* @__PURE__ */ jsx2("span", { className: "font-body text-base font-normal text-center text-(--color-dark,#200C02)", children: label }),
|
|
372
|
+
/* @__PURE__ */ jsx2(
|
|
373
|
+
"div",
|
|
374
|
+
{
|
|
375
|
+
className: "w-10 h-10 rounded-full flex items-center justify-center",
|
|
376
|
+
style: { background: isSelected ? "var(--color-primary, #3D312B)" : "transparent" },
|
|
377
|
+
children: /* @__PURE__ */ jsx2(
|
|
378
|
+
"span",
|
|
379
|
+
{
|
|
380
|
+
className: "font-body text-xl font-bold text-center tracking-display-tight",
|
|
381
|
+
style: { color: isSelected ? "var(--color-light, #FEFFF0)" : "var(--color-dark, #200C02)" },
|
|
382
|
+
children: date.getDate()
|
|
383
|
+
}
|
|
384
|
+
)
|
|
385
|
+
}
|
|
386
|
+
)
|
|
387
|
+
]
|
|
388
|
+
},
|
|
389
|
+
i
|
|
390
|
+
);
|
|
391
|
+
}) })
|
|
392
|
+
}
|
|
393
|
+
)
|
|
394
|
+
] }),
|
|
395
|
+
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) => {
|
|
183
396
|
const booked = getBookingsOnDate(cls, selectedDate);
|
|
184
397
|
const available = cls.maxParticipants - booked;
|
|
185
398
|
const isFull = available <= 0;
|
|
186
|
-
return /* @__PURE__ */
|
|
187
|
-
/* @__PURE__ */
|
|
188
|
-
/* @__PURE__ */
|
|
189
|
-
/* @__PURE__ */
|
|
190
|
-
/* @__PURE__ */
|
|
191
|
-
cls.hostName && /* @__PURE__ */
|
|
399
|
+
return /* @__PURE__ */ jsxs2("div", { children: [
|
|
400
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-[60px] py-4 box-border", children: [
|
|
401
|
+
/* @__PURE__ */ jsx2("div", { className: "w-[120px] shrink-0", children: /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block", children: formatClassTime(cls) }) }),
|
|
402
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex-1 flex flex-col gap-3 min-w-0", children: [
|
|
403
|
+
/* @__PURE__ */ jsx2("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block truncate", children: cls.name }),
|
|
404
|
+
cls.hostName && /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName })
|
|
192
405
|
] }),
|
|
193
|
-
/* @__PURE__ */
|
|
194
|
-
/* @__PURE__ */
|
|
406
|
+
/* @__PURE__ */ jsx2("div", { className: "w-14 shrink-0 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: [
|
|
407
|
+
/* @__PURE__ */ jsxs2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
|
|
195
408
|
available,
|
|
196
409
|
"/",
|
|
197
410
|
cls.maxParticipants
|
|
198
411
|
] }),
|
|
199
|
-
/* @__PURE__ */
|
|
412
|
+
/* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "available" })
|
|
200
413
|
] }) }),
|
|
201
|
-
/* @__PURE__ */
|
|
414
|
+
/* @__PURE__ */ jsx2(
|
|
202
415
|
"button",
|
|
203
416
|
{
|
|
204
417
|
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",
|
|
@@ -211,17 +424,21 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate }) {
|
|
|
211
424
|
border: "none",
|
|
212
425
|
color: "var(--color-light, #FEFFF0)"
|
|
213
426
|
},
|
|
427
|
+
onClick: () => {
|
|
428
|
+
if (!cls.id) return;
|
|
429
|
+
onOpenModal?.(isFull ? "waitlist" : "book", cls.id, selectedDate);
|
|
430
|
+
},
|
|
214
431
|
children: isFull ? "Join Waitlist" : "Book Now"
|
|
215
432
|
}
|
|
216
433
|
)
|
|
217
434
|
] }),
|
|
218
|
-
i < selectedClasses.length - 1 && /* @__PURE__ */
|
|
435
|
+
i < selectedClasses.length - 1 && /* @__PURE__ */ jsx2("div", { className: "h-px bg-black/20" })
|
|
219
436
|
] }, cls.id ?? i);
|
|
220
437
|
}) })
|
|
221
438
|
] });
|
|
222
439
|
}
|
|
223
440
|
function CalendarFoldIcon() {
|
|
224
|
-
return /* @__PURE__ */
|
|
441
|
+
return /* @__PURE__ */ jsxs2(
|
|
225
442
|
"svg",
|
|
226
443
|
{
|
|
227
444
|
width: "16",
|
|
@@ -234,21 +451,22 @@ function CalendarFoldIcon() {
|
|
|
234
451
|
strokeLinejoin: "round",
|
|
235
452
|
style: { flexShrink: 0 },
|
|
236
453
|
children: [
|
|
237
|
-
/* @__PURE__ */
|
|
238
|
-
/* @__PURE__ */
|
|
239
|
-
/* @__PURE__ */
|
|
240
|
-
/* @__PURE__ */
|
|
241
|
-
/* @__PURE__ */
|
|
454
|
+
/* @__PURE__ */ jsx2("path", { d: "M8 2v4" }),
|
|
455
|
+
/* @__PURE__ */ jsx2("path", { d: "M16 2v4" }),
|
|
456
|
+
/* @__PURE__ */ jsx2("path", { d: "M21 17V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h11Z" }),
|
|
457
|
+
/* @__PURE__ */ jsx2("path", { d: "M3 10h18" }),
|
|
458
|
+
/* @__PURE__ */ jsx2("path", { d: "M15 22v-4a2 2 0 0 1 2-2h4" })
|
|
242
459
|
]
|
|
243
460
|
}
|
|
244
461
|
);
|
|
245
462
|
}
|
|
246
463
|
function SchedulingWidget({ notifyOnConnect = false, initialScheduleId }) {
|
|
247
|
-
const [schedule, setSchedule] =
|
|
248
|
-
const [loading, setLoading] =
|
|
249
|
-
const [inEditor, setInEditor] =
|
|
250
|
-
const [isHovered, setIsHovered] =
|
|
251
|
-
const
|
|
464
|
+
const [schedule, setSchedule] = useState2(null);
|
|
465
|
+
const [loading, setLoading] = useState2(true);
|
|
466
|
+
const [inEditor, setInEditor] = useState2(false);
|
|
467
|
+
const [isHovered, setIsHovered] = useState2(false);
|
|
468
|
+
const [modalState, setModalState] = useState2(null);
|
|
469
|
+
const switchScheduleIdRef = useRef(null);
|
|
252
470
|
const dates = useMemo(() => {
|
|
253
471
|
const today = /* @__PURE__ */ new Date();
|
|
254
472
|
today.setHours(0, 0, 0, 0);
|
|
@@ -258,7 +476,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId }) {
|
|
|
258
476
|
return d;
|
|
259
477
|
});
|
|
260
478
|
}, []);
|
|
261
|
-
const [selectedIdx, setSelectedIdx] =
|
|
479
|
+
const [selectedIdx, setSelectedIdx] = useState2(0);
|
|
262
480
|
useEffect(() => {
|
|
263
481
|
if (!schedule?.classes) return;
|
|
264
482
|
for (let i = 0; i < dates.length; i++) {
|
|
@@ -354,6 +572,20 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId }) {
|
|
|
354
572
|
return void 0;
|
|
355
573
|
}
|
|
356
574
|
})() : void 0;
|
|
575
|
+
const handleModalSubmit = async (email) => {
|
|
576
|
+
if (!modalState) return;
|
|
577
|
+
const { mode, classId, classDate } = modalState;
|
|
578
|
+
const endpoint = mode === "book" ? `${API_URL}/api/schedule/class/${classId}/booking` : `${API_URL}/api/schedule/class/${classId}/waitlist`;
|
|
579
|
+
const res = await fetch(endpoint, {
|
|
580
|
+
method: "POST",
|
|
581
|
+
headers: { "Content-Type": "application/json" },
|
|
582
|
+
body: JSON.stringify({ classDate: classDate.toISOString(), email })
|
|
583
|
+
});
|
|
584
|
+
if (!res.ok) {
|
|
585
|
+
const data = await res.json().catch(() => ({}));
|
|
586
|
+
throw new Error(data?.message ?? "Something went wrong. Please try again.");
|
|
587
|
+
}
|
|
588
|
+
};
|
|
357
589
|
const handleReplaceSchedule = () => {
|
|
358
590
|
setIsHovered(false);
|
|
359
591
|
if (schedule) {
|
|
@@ -362,7 +594,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId }) {
|
|
|
362
594
|
window.parent.postMessage({ type: "ow:scheduling-not-connected" }, "*");
|
|
363
595
|
}
|
|
364
596
|
};
|
|
365
|
-
return /* @__PURE__ */
|
|
597
|
+
return /* @__PURE__ */ jsxs2(
|
|
366
598
|
"section",
|
|
367
599
|
{
|
|
368
600
|
"data-ohw-section": "scheduling",
|
|
@@ -370,15 +602,15 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId }) {
|
|
|
370
602
|
onMouseEnter: () => inEditor && setIsHovered(true),
|
|
371
603
|
onMouseLeave: () => setIsHovered(false),
|
|
372
604
|
children: [
|
|
373
|
-
inEditor && isHovered && !!schedule && /* @__PURE__ */
|
|
605
|
+
inEditor && isHovered && !!schedule && /* @__PURE__ */ jsxs2(
|
|
374
606
|
"div",
|
|
375
607
|
{
|
|
376
608
|
className: "absolute inset-0 z-10 pointer-events-auto cursor-pointer",
|
|
377
609
|
onClick: handleReplaceSchedule,
|
|
378
610
|
children: [
|
|
379
|
-
/* @__PURE__ */
|
|
380
|
-
/* @__PURE__ */
|
|
381
|
-
/* @__PURE__ */
|
|
611
|
+
/* @__PURE__ */ jsx2("div", { className: "absolute inset-0", style: { background: "#0885FE", opacity: 0.18 } }),
|
|
612
|
+
/* @__PURE__ */ jsx2("div", { className: "absolute inset-0", style: { boxShadow: "inset 0 0 0 1.5px #0885FE" } }),
|
|
613
|
+
/* @__PURE__ */ jsx2("div", { className: "absolute inset-0 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxs2(
|
|
382
614
|
"div",
|
|
383
615
|
{
|
|
384
616
|
className: "bg-white border border-[#E7E5E4] rounded-md px-3 py-1.5 flex items-center gap-1.5",
|
|
@@ -390,7 +622,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId }) {
|
|
|
390
622
|
color: "#0C0A09"
|
|
391
623
|
},
|
|
392
624
|
children: [
|
|
393
|
-
/* @__PURE__ */
|
|
625
|
+
/* @__PURE__ */ jsx2(CalendarFoldIcon, {}),
|
|
394
626
|
"Replace schedule"
|
|
395
627
|
]
|
|
396
628
|
}
|
|
@@ -398,24 +630,34 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId }) {
|
|
|
398
630
|
]
|
|
399
631
|
}
|
|
400
632
|
),
|
|
401
|
-
/* @__PURE__ */
|
|
402
|
-
/* @__PURE__ */
|
|
403
|
-
/* @__PURE__ */
|
|
404
|
-
schedule?.description && /* @__PURE__ */
|
|
633
|
+
/* @__PURE__ */ jsxs2("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
|
|
634
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center gap-4", children: [
|
|
635
|
+
/* @__PURE__ */ jsx2("h2", { className: "font-display text-5xl font-bold text-center m-0 text-(--color-dark,#200C02)", children: schedule?.name ?? "Book an appointment" }),
|
|
636
|
+
schedule?.description && /* @__PURE__ */ jsx2("p", { className: "font-body text-body text-center m-0 text-(--color-accent,#A89B83)", children: schedule.description })
|
|
405
637
|
] }),
|
|
406
|
-
/* @__PURE__ */
|
|
407
|
-
timezoneLabel && /* @__PURE__ */
|
|
408
|
-
/* @__PURE__ */
|
|
638
|
+
/* @__PURE__ */ jsxs2("div", { className: "w-full flex flex-col items-end gap-3", children: [
|
|
639
|
+
timezoneLabel && /* @__PURE__ */ jsx2("span", { className: "font-body text-sm font-normal text-(--color-accent,#A89B83)", children: timezoneLabel }),
|
|
640
|
+
/* @__PURE__ */ jsx2("div", { className: "w-full p-10 box-border", children: loading ? /* @__PURE__ */ jsx2(LoadingSkeleton, {}) : !schedule ? /* @__PURE__ */ jsx2(EmptyState, { inEditor }) : /* @__PURE__ */ jsx2(
|
|
409
641
|
ScheduleView,
|
|
410
642
|
{
|
|
411
643
|
schedule,
|
|
412
644
|
dates,
|
|
413
645
|
selectedIdx,
|
|
414
|
-
onSelectDate: setSelectedIdx
|
|
646
|
+
onSelectDate: setSelectedIdx,
|
|
647
|
+
onOpenModal: inEditor ? void 0 : (mode, classId, classDate) => setModalState({ mode, classId, classDate })
|
|
415
648
|
}
|
|
416
649
|
) })
|
|
417
650
|
] })
|
|
418
|
-
] })
|
|
651
|
+
] }),
|
|
652
|
+
modalState && /* @__PURE__ */ jsx2(
|
|
653
|
+
EmailCaptureModal,
|
|
654
|
+
{
|
|
655
|
+
title: modalState.mode === "book" ? "Confirm your spot" : "Leave your email",
|
|
656
|
+
subtitle: modalState.mode === "book" ? "We'll send your booking confirmation here." : "We'll let you know when spots open up!",
|
|
657
|
+
onSubmit: handleModalSubmit,
|
|
658
|
+
onClose: () => setModalState(null)
|
|
659
|
+
}
|
|
660
|
+
)
|
|
419
661
|
]
|
|
420
662
|
}
|
|
421
663
|
);
|
|
@@ -3742,7 +3984,7 @@ var cva = (base, config) => (props) => {
|
|
|
3742
3984
|
|
|
3743
3985
|
// src/ui/toggle.tsx
|
|
3744
3986
|
import { Toggle as TogglePrimitive } from "radix-ui";
|
|
3745
|
-
import { jsx as
|
|
3987
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
3746
3988
|
var toggleVariants = cva(
|
|
3747
3989
|
"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",
|
|
3748
3990
|
{
|
|
@@ -3769,7 +4011,7 @@ function Toggle({
|
|
|
3769
4011
|
size,
|
|
3770
4012
|
...props
|
|
3771
4013
|
}) {
|
|
3772
|
-
return /* @__PURE__ */
|
|
4014
|
+
return /* @__PURE__ */ jsx3(
|
|
3773
4015
|
TogglePrimitive.Root,
|
|
3774
4016
|
{
|
|
3775
4017
|
"data-slot": "toggle",
|
|
@@ -3780,7 +4022,7 @@ function Toggle({
|
|
|
3780
4022
|
}
|
|
3781
4023
|
|
|
3782
4024
|
// src/ui/toggle-group.tsx
|
|
3783
|
-
import { jsx as
|
|
4025
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
3784
4026
|
var ToggleGroupContext = React2.createContext({
|
|
3785
4027
|
value: "",
|
|
3786
4028
|
onValueChange: () => {
|
|
@@ -3793,13 +4035,13 @@ function ToggleGroup({
|
|
|
3793
4035
|
children,
|
|
3794
4036
|
...props
|
|
3795
4037
|
}) {
|
|
3796
|
-
return /* @__PURE__ */
|
|
4038
|
+
return /* @__PURE__ */ jsx4(
|
|
3797
4039
|
"div",
|
|
3798
4040
|
{
|
|
3799
4041
|
role: "group",
|
|
3800
4042
|
className: cn("flex items-center gap-1 p-1 bg-muted rounded-md", className),
|
|
3801
4043
|
...props,
|
|
3802
|
-
children: /* @__PURE__ */
|
|
4044
|
+
children: /* @__PURE__ */ jsx4(ToggleGroupContext.Provider, { value: { value, onValueChange }, children })
|
|
3803
4045
|
}
|
|
3804
4046
|
);
|
|
3805
4047
|
}
|
|
@@ -3810,7 +4052,7 @@ function ToggleGroupItem({
|
|
|
3810
4052
|
...props
|
|
3811
4053
|
}) {
|
|
3812
4054
|
const { value: groupValue, onValueChange } = React2.useContext(ToggleGroupContext);
|
|
3813
|
-
return /* @__PURE__ */
|
|
4055
|
+
return /* @__PURE__ */ jsx4(
|
|
3814
4056
|
Toggle,
|
|
3815
4057
|
{
|
|
3816
4058
|
pressed: groupValue === value,
|
|
@@ -3852,7 +4094,7 @@ function isEditSessionActive() {
|
|
|
3852
4094
|
}
|
|
3853
4095
|
|
|
3854
4096
|
// src/ui/badge.tsx
|
|
3855
|
-
import { jsx as
|
|
4097
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
3856
4098
|
var badgeVariants = cva(
|
|
3857
4099
|
"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",
|
|
3858
4100
|
{
|
|
@@ -3870,11 +4112,11 @@ var badgeVariants = cva(
|
|
|
3870
4112
|
}
|
|
3871
4113
|
);
|
|
3872
4114
|
function Badge({ className, variant, ...props }) {
|
|
3873
|
-
return /* @__PURE__ */
|
|
4115
|
+
return /* @__PURE__ */ jsx5("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
3874
4116
|
}
|
|
3875
4117
|
|
|
3876
4118
|
// src/OhhwellsBridge.tsx
|
|
3877
|
-
import { Fragment as Fragment2, jsx as
|
|
4119
|
+
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
3878
4120
|
var PRIMARY = "#0885FE";
|
|
3879
4121
|
var IMAGE_FADE_MS = 300;
|
|
3880
4122
|
function runOpacityFade(el, onDone) {
|
|
@@ -3942,7 +4184,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId)
|
|
|
3942
4184
|
const container = document.createElement("div");
|
|
3943
4185
|
container.dataset.ohwSectionContainer = "scheduling";
|
|
3944
4186
|
anchor.insertAdjacentElement("afterend", container);
|
|
3945
|
-
createRoot(container).render(/* @__PURE__ */
|
|
4187
|
+
createRoot(container).render(/* @__PURE__ */ jsx6(SchedulingWidget, { notifyOnConnect, initialScheduleId: scheduleId }));
|
|
3946
4188
|
const tracker = getSectionsTracker();
|
|
3947
4189
|
let sections = [];
|
|
3948
4190
|
try {
|
|
@@ -4117,7 +4359,7 @@ var TOOLBAR_GROUPS = [
|
|
|
4117
4359
|
];
|
|
4118
4360
|
function GlowFrame({ rect, elRef }) {
|
|
4119
4361
|
const GAP = 6;
|
|
4120
|
-
return /* @__PURE__ */
|
|
4362
|
+
return /* @__PURE__ */ jsx6(
|
|
4121
4363
|
"div",
|
|
4122
4364
|
{
|
|
4123
4365
|
ref: elRef,
|
|
@@ -4168,7 +4410,7 @@ function FloatingToolbar({
|
|
|
4168
4410
|
activeCommands
|
|
4169
4411
|
}) {
|
|
4170
4412
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll);
|
|
4171
|
-
return /* @__PURE__ */
|
|
4413
|
+
return /* @__PURE__ */ jsx6(
|
|
4172
4414
|
"div",
|
|
4173
4415
|
{
|
|
4174
4416
|
ref: elRef,
|
|
@@ -4191,11 +4433,11 @@ function FloatingToolbar({
|
|
|
4191
4433
|
pointerEvents: "auto",
|
|
4192
4434
|
whiteSpace: "nowrap"
|
|
4193
4435
|
},
|
|
4194
|
-
children: TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */
|
|
4195
|
-
gi > 0 && /* @__PURE__ */
|
|
4436
|
+
children: TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs3(React3.Fragment, { children: [
|
|
4437
|
+
gi > 0 && /* @__PURE__ */ jsx6("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
|
|
4196
4438
|
btns.map((btn) => {
|
|
4197
4439
|
const isActive = activeCommands.has(btn.cmd);
|
|
4198
|
-
return /* @__PURE__ */
|
|
4440
|
+
return /* @__PURE__ */ jsx6(
|
|
4199
4441
|
"button",
|
|
4200
4442
|
{
|
|
4201
4443
|
title: btn.title,
|
|
@@ -4221,7 +4463,7 @@ function FloatingToolbar({
|
|
|
4221
4463
|
flexShrink: 0,
|
|
4222
4464
|
padding: 6
|
|
4223
4465
|
},
|
|
4224
|
-
children: /* @__PURE__ */
|
|
4466
|
+
children: /* @__PURE__ */ jsx6(
|
|
4225
4467
|
"svg",
|
|
4226
4468
|
{
|
|
4227
4469
|
width: "16",
|
|
@@ -4254,7 +4496,7 @@ function StateToggle({
|
|
|
4254
4496
|
states,
|
|
4255
4497
|
onStateChange
|
|
4256
4498
|
}) {
|
|
4257
|
-
return /* @__PURE__ */
|
|
4499
|
+
return /* @__PURE__ */ jsx6(
|
|
4258
4500
|
ToggleGroup,
|
|
4259
4501
|
{
|
|
4260
4502
|
"data-ohw-state-toggle": "",
|
|
@@ -4268,7 +4510,7 @@ function StateToggle({
|
|
|
4268
4510
|
left: rect.right - 8,
|
|
4269
4511
|
transform: "translateX(-100%)"
|
|
4270
4512
|
},
|
|
4271
|
-
children: states.map((state) => /* @__PURE__ */
|
|
4513
|
+
children: states.map((state) => /* @__PURE__ */ jsx6(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
4272
4514
|
}
|
|
4273
4515
|
);
|
|
4274
4516
|
}
|
|
@@ -4278,7 +4520,7 @@ function OhhwellsBridge() {
|
|
|
4278
4520
|
const router = useRouter();
|
|
4279
4521
|
const searchParams = useSearchParams();
|
|
4280
4522
|
const isEditMode = isEditSessionActive();
|
|
4281
|
-
const [bridgeRoot, setBridgeRoot] =
|
|
4523
|
+
const [bridgeRoot, setBridgeRoot] = useState3(null);
|
|
4282
4524
|
useEffect2(() => {
|
|
4283
4525
|
const figtreeFontId = "ohw-figtree-font";
|
|
4284
4526
|
if (!document.getElementById(figtreeFontId)) {
|
|
@@ -4312,33 +4554,33 @@ function OhhwellsBridge() {
|
|
|
4312
4554
|
window.parent.postMessage(data, "*");
|
|
4313
4555
|
}
|
|
4314
4556
|
}, []);
|
|
4315
|
-
const [fetchState, setFetchState] =
|
|
4316
|
-
const autoSaveTimers =
|
|
4317
|
-
const activeElRef =
|
|
4318
|
-
const originalContentRef =
|
|
4319
|
-
const activeStateElRef =
|
|
4320
|
-
const parentScrollRef =
|
|
4321
|
-
const toolbarElRef =
|
|
4322
|
-
const glowElRef =
|
|
4323
|
-
const hoveredImageRef =
|
|
4324
|
-
const hoveredImageHasTextOverlapRef =
|
|
4325
|
-
const hoveredGapRef =
|
|
4326
|
-
const imageUnhoverTimerRef =
|
|
4327
|
-
const imageShowTimerRef =
|
|
4328
|
-
const editStylesRef =
|
|
4329
|
-
const activateRef =
|
|
4557
|
+
const [fetchState, setFetchState] = useState3("idle");
|
|
4558
|
+
const autoSaveTimers = useRef2(/* @__PURE__ */ new Map());
|
|
4559
|
+
const activeElRef = useRef2(null);
|
|
4560
|
+
const originalContentRef = useRef2(null);
|
|
4561
|
+
const activeStateElRef = useRef2(null);
|
|
4562
|
+
const parentScrollRef = useRef2(null);
|
|
4563
|
+
const toolbarElRef = useRef2(null);
|
|
4564
|
+
const glowElRef = useRef2(null);
|
|
4565
|
+
const hoveredImageRef = useRef2(null);
|
|
4566
|
+
const hoveredImageHasTextOverlapRef = useRef2(false);
|
|
4567
|
+
const hoveredGapRef = useRef2(null);
|
|
4568
|
+
const imageUnhoverTimerRef = useRef2(null);
|
|
4569
|
+
const imageShowTimerRef = useRef2(null);
|
|
4570
|
+
const editStylesRef = useRef2(null);
|
|
4571
|
+
const activateRef = useRef2(() => {
|
|
4330
4572
|
});
|
|
4331
|
-
const deactivateRef =
|
|
4573
|
+
const deactivateRef = useRef2(() => {
|
|
4332
4574
|
});
|
|
4333
|
-
const refreshActiveCommandsRef =
|
|
4575
|
+
const refreshActiveCommandsRef = useRef2(() => {
|
|
4334
4576
|
});
|
|
4335
|
-
const postToParentRef =
|
|
4577
|
+
const postToParentRef = useRef2(postToParent);
|
|
4336
4578
|
postToParentRef.current = postToParent;
|
|
4337
|
-
const [toolbarRect, setToolbarRect] =
|
|
4338
|
-
const [toggleState, setToggleState] =
|
|
4339
|
-
const [maxBadge, setMaxBadge] =
|
|
4340
|
-
const [activeCommands, setActiveCommands] =
|
|
4341
|
-
const [sectionGap, setSectionGap] =
|
|
4579
|
+
const [toolbarRect, setToolbarRect] = useState3(null);
|
|
4580
|
+
const [toggleState, setToggleState] = useState3(null);
|
|
4581
|
+
const [maxBadge, setMaxBadge] = useState3(null);
|
|
4582
|
+
const [activeCommands, setActiveCommands] = useState3(/* @__PURE__ */ new Set());
|
|
4583
|
+
const [sectionGap, setSectionGap] = useState3(null);
|
|
4342
4584
|
useEffect2(() => {
|
|
4343
4585
|
const update = () => {
|
|
4344
4586
|
const el = activeElRef.current;
|
|
@@ -5414,12 +5656,12 @@ function OhhwellsBridge() {
|
|
|
5414
5656
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
5415
5657
|
}, [deactivate]);
|
|
5416
5658
|
return bridgeRoot ? createPortal(
|
|
5417
|
-
/* @__PURE__ */
|
|
5418
|
-
toolbarRect && /* @__PURE__ */
|
|
5419
|
-
/* @__PURE__ */
|
|
5420
|
-
/* @__PURE__ */
|
|
5659
|
+
/* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
5660
|
+
toolbarRect && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
5661
|
+
/* @__PURE__ */ jsx6(GlowFrame, { rect: toolbarRect, elRef: glowElRef }),
|
|
5662
|
+
/* @__PURE__ */ jsx6(FloatingToolbar, { rect: toolbarRect, parentScroll: parentScrollRef.current, elRef: toolbarElRef, onCommand: handleCommand, activeCommands })
|
|
5421
5663
|
] }),
|
|
5422
|
-
maxBadge && /* @__PURE__ */
|
|
5664
|
+
maxBadge && /* @__PURE__ */ jsxs3(
|
|
5423
5665
|
"div",
|
|
5424
5666
|
{
|
|
5425
5667
|
"data-ohw-max-badge": "",
|
|
@@ -5445,7 +5687,7 @@ function OhhwellsBridge() {
|
|
|
5445
5687
|
]
|
|
5446
5688
|
}
|
|
5447
5689
|
),
|
|
5448
|
-
toggleState && /* @__PURE__ */
|
|
5690
|
+
toggleState && /* @__PURE__ */ jsx6(
|
|
5449
5691
|
StateToggle,
|
|
5450
5692
|
{
|
|
5451
5693
|
rect: toggleState.rect,
|
|
@@ -5454,15 +5696,15 @@ function OhhwellsBridge() {
|
|
|
5454
5696
|
onStateChange: handleStateChange
|
|
5455
5697
|
}
|
|
5456
5698
|
),
|
|
5457
|
-
sectionGap && /* @__PURE__ */
|
|
5699
|
+
sectionGap && /* @__PURE__ */ jsxs3(
|
|
5458
5700
|
"div",
|
|
5459
5701
|
{
|
|
5460
5702
|
"data-ohw-section-insert-line": "",
|
|
5461
5703
|
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
5462
5704
|
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
5463
5705
|
children: [
|
|
5464
|
-
/* @__PURE__ */
|
|
5465
|
-
/* @__PURE__ */
|
|
5706
|
+
/* @__PURE__ */ jsx6("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
5707
|
+
/* @__PURE__ */ jsx6(
|
|
5466
5708
|
Badge,
|
|
5467
5709
|
{
|
|
5468
5710
|
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",
|
|
@@ -5475,7 +5717,7 @@ function OhhwellsBridge() {
|
|
|
5475
5717
|
children: "Add Section"
|
|
5476
5718
|
}
|
|
5477
5719
|
),
|
|
5478
|
-
/* @__PURE__ */
|
|
5720
|
+
/* @__PURE__ */ jsx6("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
5479
5721
|
]
|
|
5480
5722
|
}
|
|
5481
5723
|
)
|