@ohhwells/bridge 0.1.18 → 0.1.19
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 +646 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +621 -49
- package/dist/index.js.map +1 -1
- package/dist/styles.css +262 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -32,6 +32,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
32
32
|
var index_exports = {};
|
|
33
33
|
__export(index_exports, {
|
|
34
34
|
OhhwellsBridge: () => OhhwellsBridge,
|
|
35
|
+
SchedulingWidget: () => SchedulingWidget,
|
|
35
36
|
Toggle: () => Toggle,
|
|
36
37
|
ToggleGroup: () => ToggleGroup,
|
|
37
38
|
ToggleGroupItem: () => ToggleGroupItem,
|
|
@@ -40,10 +41,428 @@ __export(index_exports, {
|
|
|
40
41
|
module.exports = __toCommonJS(index_exports);
|
|
41
42
|
|
|
42
43
|
// src/OhhwellsBridge.tsx
|
|
44
|
+
var import_react2 = __toESM(require("react"), 1);
|
|
45
|
+
var import_client = require("react-dom/client");
|
|
46
|
+
|
|
47
|
+
// src/ui/SchedulingWidget.tsx
|
|
43
48
|
var import_react = __toESM(require("react"), 1);
|
|
49
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
50
|
+
var API_URL = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
51
|
+
var DAY_ABBR = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
|
|
52
|
+
function getApiDomain() {
|
|
53
|
+
const h = window.location.hostname;
|
|
54
|
+
for (const base of ["ohhwells.site", "theflowops-staging.com", "theflowops.com"]) {
|
|
55
|
+
if (h.endsWith(`.${base}`)) return h.slice(0, -(base.length + 1));
|
|
56
|
+
}
|
|
57
|
+
return h;
|
|
58
|
+
}
|
|
59
|
+
function classRunsOnDate(cls, date, type) {
|
|
60
|
+
if (type === "FIXED") {
|
|
61
|
+
const d = String(date.getDate()).padStart(2, "0");
|
|
62
|
+
const m = String(date.getMonth() + 1).padStart(2, "0");
|
|
63
|
+
return cls.fixedDates?.some((fd) => fd.date === `${d}-${m}-${date.getFullYear()}`) ?? false;
|
|
64
|
+
}
|
|
65
|
+
return cls.weekdays?.some((w) => w.weekday === date.getDay()) ?? false;
|
|
66
|
+
}
|
|
67
|
+
function formatClassTime(cls) {
|
|
68
|
+
let h = parseInt(cls.startTime.hour, 10);
|
|
69
|
+
const m = parseInt(cls.startTime.minutes, 10);
|
|
70
|
+
if (cls.startTime.time === "PM" && h !== 12) h += 12;
|
|
71
|
+
if (cls.startTime.time === "AM" && h === 12) h = 0;
|
|
72
|
+
const endTotal = h * 60 + m + cls.duration;
|
|
73
|
+
const eh = Math.floor(endTotal / 60) % 24;
|
|
74
|
+
const em = endTotal % 60;
|
|
75
|
+
return `${h}:${cls.startTime.minutes}-${eh}:${String(em).padStart(2, "0")}`;
|
|
76
|
+
}
|
|
77
|
+
function getBookingsOnDate(cls, date) {
|
|
78
|
+
if (!cls.bookings?.length) return 0;
|
|
79
|
+
const ds = date.toISOString().split("T")[0];
|
|
80
|
+
return cls.bookings.filter((b) => {
|
|
81
|
+
try {
|
|
82
|
+
return new Date(b.classDate).toISOString().split("T")[0] === ds;
|
|
83
|
+
} catch {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}).length;
|
|
87
|
+
}
|
|
88
|
+
function buildTimezoneLabel(tz) {
|
|
89
|
+
try {
|
|
90
|
+
const now = /* @__PURE__ */ new Date();
|
|
91
|
+
const timeStr = new Intl.DateTimeFormat("en-US", {
|
|
92
|
+
hour: "2-digit",
|
|
93
|
+
minute: "2-digit",
|
|
94
|
+
hour12: false,
|
|
95
|
+
timeZone: tz
|
|
96
|
+
}).format(now);
|
|
97
|
+
const offsetPart = new Intl.DateTimeFormat("en-US", { timeZoneName: "short", timeZone: tz }).formatToParts(now).find((p) => p.type === "timeZoneName")?.value ?? "";
|
|
98
|
+
const city = tz.split("/").pop()?.replace(/_/g, " ") ?? tz;
|
|
99
|
+
return `${timeStr} (${offsetPart}) ${city} time`;
|
|
100
|
+
} catch {
|
|
101
|
+
return tz;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function EmptyState({ inEditor }) {
|
|
105
|
+
const handleAddSchedule = () => {
|
|
106
|
+
if (inEditor) {
|
|
107
|
+
window.parent.postMessage({ type: "ow:scheduling-not-connected" }, "*");
|
|
108
|
+
}
|
|
109
|
+
};
|
|
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)(
|
|
112
|
+
"svg",
|
|
113
|
+
{
|
|
114
|
+
width: "20",
|
|
115
|
+
height: "20",
|
|
116
|
+
viewBox: "0 0 24 24",
|
|
117
|
+
fill: "none",
|
|
118
|
+
stroke: "var(--color-accent, #A89B83)",
|
|
119
|
+
strokeWidth: "1.5",
|
|
120
|
+
strokeLinecap: "round",
|
|
121
|
+
strokeLinejoin: "round",
|
|
122
|
+
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" })
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
) }),
|
|
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." })
|
|
135
|
+
] }),
|
|
136
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
137
|
+
"button",
|
|
138
|
+
{
|
|
139
|
+
onClick: handleAddSchedule,
|
|
140
|
+
className: "h-9 px-2 py-1.5 flex items-center justify-center bg-white border border-[#E7E5E4] rounded-md font-body text-sm font-medium text-(--color-dark,#200C02) cursor-pointer",
|
|
141
|
+
children: "Add Schedule"
|
|
142
|
+
}
|
|
143
|
+
)
|
|
144
|
+
] });
|
|
145
|
+
}
|
|
146
|
+
function LoadingSkeleton() {
|
|
147
|
+
const shimmer = {
|
|
148
|
+
background: "linear-gradient(90deg,#f0f0f0 25%,#e8e8e8 50%,#f0f0f0 75%)",
|
|
149
|
+
backgroundSize: "200% 100%",
|
|
150
|
+
animation: "ohw-shimmer 1.5s infinite"
|
|
151
|
+
};
|
|
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%" } })
|
|
157
|
+
] }, 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" } })
|
|
164
|
+
] }),
|
|
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 } })
|
|
167
|
+
] }),
|
|
168
|
+
i < 2 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-px bg-black/20" })
|
|
169
|
+
] }, i))
|
|
170
|
+
] });
|
|
171
|
+
}
|
|
172
|
+
function ScheduleView({ schedule, dates, selectedIdx, onSelectDate }) {
|
|
173
|
+
const todayMs = (0, import_react.useMemo)(() => {
|
|
174
|
+
const d = /* @__PURE__ */ new Date();
|
|
175
|
+
d.setHours(0, 0, 0, 0);
|
|
176
|
+
return d.getTime();
|
|
177
|
+
}, []);
|
|
178
|
+
const datesWithClasses = (0, import_react.useMemo)(
|
|
179
|
+
() => new Set(dates.map(
|
|
180
|
+
(d, i) => schedule.classes?.some((c) => classRunsOnDate(c, d, schedule.type)) ? i : -1
|
|
181
|
+
).filter((i) => i >= 0)),
|
|
182
|
+
[dates, schedule]
|
|
183
|
+
);
|
|
184
|
+
const selectedDate = dates[selectedIdx];
|
|
185
|
+
const selectedClasses = (0, import_react.useMemo)(
|
|
186
|
+
() => (schedule.classes ?? []).filter((c) => selectedDate && classRunsOnDate(c, selectedDate, schedule.type)),
|
|
187
|
+
[schedule, selectedDate]
|
|
188
|
+
);
|
|
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)(
|
|
196
|
+
"div",
|
|
197
|
+
{
|
|
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)(
|
|
203
|
+
"div",
|
|
204
|
+
{
|
|
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) => {
|
|
223
|
+
const booked = getBookingsOnDate(cls, selectedDate);
|
|
224
|
+
const available = cls.maxParticipants - booked;
|
|
225
|
+
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 })
|
|
232
|
+
] }),
|
|
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
|
|
238
|
+
] }),
|
|
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
|
+
)
|
|
257
|
+
] }),
|
|
258
|
+
i < selectedClasses.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-px bg-black/20" })
|
|
259
|
+
] }, cls.id ?? i);
|
|
260
|
+
}) })
|
|
261
|
+
] });
|
|
262
|
+
}
|
|
263
|
+
function CalendarFoldIcon() {
|
|
264
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
265
|
+
"svg",
|
|
266
|
+
{
|
|
267
|
+
width: "16",
|
|
268
|
+
height: "16",
|
|
269
|
+
viewBox: "0 0 24 24",
|
|
270
|
+
fill: "none",
|
|
271
|
+
stroke: "currentColor",
|
|
272
|
+
strokeWidth: "2",
|
|
273
|
+
strokeLinecap: "round",
|
|
274
|
+
strokeLinejoin: "round",
|
|
275
|
+
style: { flexShrink: 0 },
|
|
276
|
+
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" })
|
|
282
|
+
]
|
|
283
|
+
}
|
|
284
|
+
);
|
|
285
|
+
}
|
|
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)(() => {
|
|
293
|
+
const today = /* @__PURE__ */ new Date();
|
|
294
|
+
today.setHours(0, 0, 0, 0);
|
|
295
|
+
return Array.from({ length: 14 }, (_, i) => {
|
|
296
|
+
const d = new Date(today);
|
|
297
|
+
d.setDate(today.getDate() + i);
|
|
298
|
+
return d;
|
|
299
|
+
});
|
|
300
|
+
}, []);
|
|
301
|
+
const [selectedIdx, setSelectedIdx] = (0, import_react.useState)(0);
|
|
302
|
+
(0, import_react.useEffect)(() => {
|
|
303
|
+
if (!schedule?.classes) return;
|
|
304
|
+
for (let i = 0; i < dates.length; i++) {
|
|
305
|
+
if (schedule.classes.some((c) => classRunsOnDate(c, dates[i], schedule.type))) {
|
|
306
|
+
setSelectedIdx(i);
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}, [schedule, dates]);
|
|
311
|
+
(0, import_react.useEffect)(() => {
|
|
312
|
+
if (typeof window === "undefined") return;
|
|
313
|
+
const isInEditor = window.self !== window.top;
|
|
314
|
+
setInEditor(isInEditor);
|
|
315
|
+
if (isInEditor) {
|
|
316
|
+
const startEmpty = initialScheduleId === null;
|
|
317
|
+
if (startEmpty) setLoading(false);
|
|
318
|
+
let initialized = startEmpty;
|
|
319
|
+
const timer = !startEmpty ? setTimeout(() => {
|
|
320
|
+
if (!initialized) {
|
|
321
|
+
initialized = true;
|
|
322
|
+
setLoading(false);
|
|
323
|
+
}
|
|
324
|
+
}, 5e3) : null;
|
|
325
|
+
const handler = (e) => {
|
|
326
|
+
if (e.data?.type === "ow:clear-scheduling-widget") {
|
|
327
|
+
setSchedule(null);
|
|
328
|
+
setLoading(false);
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
if (e.data?.type === "ow:switch-schedule") {
|
|
332
|
+
switchScheduleIdRef.current = e.data.scheduleId ?? null;
|
|
333
|
+
initialized = false;
|
|
334
|
+
setLoading(true);
|
|
335
|
+
window.parent.postMessage({ type: "ow:request-user-schedules" }, "*");
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
if (e.data?.type !== "ow:user-schedules-response") return;
|
|
339
|
+
if (initialized && switchScheduleIdRef.current === null) return;
|
|
340
|
+
initialized = true;
|
|
341
|
+
if (timer) clearTimeout(timer);
|
|
342
|
+
const schedules = e.data.schedules ?? [];
|
|
343
|
+
const isSwitching = switchScheduleIdRef.current !== null;
|
|
344
|
+
const target = isSwitching ? schedules.find((s) => s.id === switchScheduleIdRef.current) ?? schedules[0] ?? null : initialScheduleId ? schedules.find((s) => s.id === initialScheduleId) ?? schedules[0] ?? null : schedules[0] ?? null;
|
|
345
|
+
switchScheduleIdRef.current = null;
|
|
346
|
+
setSchedule(target);
|
|
347
|
+
setLoading(false);
|
|
348
|
+
if (notifyOnConnect && target && !isSwitching) {
|
|
349
|
+
window.parent.postMessage({ type: "ow:schedule-connected", schedule: { id: target.id, name: target.name } }, "*");
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
window.addEventListener("message", handler);
|
|
353
|
+
if (!startEmpty) window.parent.postMessage({ type: "ow:request-user-schedules" }, "*");
|
|
354
|
+
return () => {
|
|
355
|
+
window.removeEventListener("message", handler);
|
|
356
|
+
if (timer) clearTimeout(timer);
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
if (initialScheduleId === null) {
|
|
360
|
+
setLoading(false);
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
;
|
|
364
|
+
(async () => {
|
|
365
|
+
try {
|
|
366
|
+
if (initialScheduleId) {
|
|
367
|
+
const res = await fetch(`${API_URL}/api/schedule/id/${initialScheduleId}`);
|
|
368
|
+
const data = await res.json();
|
|
369
|
+
setSchedule(data?.id ? data : null);
|
|
370
|
+
} else {
|
|
371
|
+
const domain = getApiDomain();
|
|
372
|
+
const sitemapRes = await fetch(`${API_URL}/api/schedule/sitemap/${domain}`);
|
|
373
|
+
const slugs = await sitemapRes.json();
|
|
374
|
+
if (!Array.isArray(slugs) || !slugs.length) {
|
|
375
|
+
setLoading(false);
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
const { slug } = [...slugs].sort(
|
|
379
|
+
(a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime()
|
|
380
|
+
)[0];
|
|
381
|
+
const res = await fetch(`${API_URL}/api/schedule/${domain}/${slug}`);
|
|
382
|
+
const data = await res.json();
|
|
383
|
+
setSchedule(data?.id ? data : null);
|
|
384
|
+
}
|
|
385
|
+
} catch {
|
|
386
|
+
}
|
|
387
|
+
setLoading(false);
|
|
388
|
+
})();
|
|
389
|
+
}, []);
|
|
390
|
+
const timezoneLabel = schedule?.timezone ? (() => {
|
|
391
|
+
try {
|
|
392
|
+
return buildTimezoneLabel(schedule.timezone);
|
|
393
|
+
} catch {
|
|
394
|
+
return void 0;
|
|
395
|
+
}
|
|
396
|
+
})() : void 0;
|
|
397
|
+
const handleReplaceSchedule = () => {
|
|
398
|
+
setIsHovered(false);
|
|
399
|
+
if (schedule) {
|
|
400
|
+
window.parent.postMessage({ type: "ow:schedule-connected", schedule: { id: schedule.id, name: schedule.name } }, "*");
|
|
401
|
+
} else {
|
|
402
|
+
window.parent.postMessage({ type: "ow:scheduling-not-connected" }, "*");
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
406
|
+
"section",
|
|
407
|
+
{
|
|
408
|
+
"data-ohw-section": "scheduling",
|
|
409
|
+
className: "w-full box-border py-20 px-16 font-body bg-(--color-light,#FEFFF0) relative",
|
|
410
|
+
onMouseEnter: () => inEditor && setIsHovered(true),
|
|
411
|
+
onMouseLeave: () => setIsHovered(false),
|
|
412
|
+
children: [
|
|
413
|
+
inEditor && isHovered && !!schedule && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
414
|
+
"div",
|
|
415
|
+
{
|
|
416
|
+
className: "absolute inset-0 z-10 pointer-events-auto cursor-pointer",
|
|
417
|
+
onClick: handleReplaceSchedule,
|
|
418
|
+
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)(
|
|
422
|
+
"div",
|
|
423
|
+
{
|
|
424
|
+
className: "bg-white border border-[#E7E5E4] rounded-md px-3 py-1.5 flex items-center gap-1.5",
|
|
425
|
+
style: {
|
|
426
|
+
fontSize: 14,
|
|
427
|
+
lineHeight: "24px",
|
|
428
|
+
fontFamily: "'Figtree', system-ui, sans-serif",
|
|
429
|
+
fontWeight: 500,
|
|
430
|
+
color: "#0C0A09"
|
|
431
|
+
},
|
|
432
|
+
children: [
|
|
433
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CalendarFoldIcon, {}),
|
|
434
|
+
"Replace schedule"
|
|
435
|
+
]
|
|
436
|
+
}
|
|
437
|
+
) })
|
|
438
|
+
]
|
|
439
|
+
}
|
|
440
|
+
),
|
|
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 })
|
|
445
|
+
] }),
|
|
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)(
|
|
449
|
+
ScheduleView,
|
|
450
|
+
{
|
|
451
|
+
schedule,
|
|
452
|
+
dates,
|
|
453
|
+
selectedIdx,
|
|
454
|
+
onSelectDate: setSelectedIdx
|
|
455
|
+
}
|
|
456
|
+
) })
|
|
457
|
+
] })
|
|
458
|
+
] })
|
|
459
|
+
]
|
|
460
|
+
}
|
|
461
|
+
);
|
|
462
|
+
}
|
|
44
463
|
|
|
45
464
|
// src/ui/toggle-group.tsx
|
|
46
|
-
var
|
|
465
|
+
var React2 = __toESM(require("react"), 1);
|
|
47
466
|
|
|
48
467
|
// node_modules/clsx/dist/clsx.mjs
|
|
49
468
|
function r(e) {
|
|
@@ -3363,7 +3782,7 @@ var cva = (base, config) => (props) => {
|
|
|
3363
3782
|
|
|
3364
3783
|
// src/ui/toggle.tsx
|
|
3365
3784
|
var import_radix_ui = require("radix-ui");
|
|
3366
|
-
var
|
|
3785
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
3367
3786
|
var toggleVariants = cva(
|
|
3368
3787
|
"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",
|
|
3369
3788
|
{
|
|
@@ -3390,7 +3809,7 @@ function Toggle({
|
|
|
3390
3809
|
size,
|
|
3391
3810
|
...props
|
|
3392
3811
|
}) {
|
|
3393
|
-
return /* @__PURE__ */ (0,
|
|
3812
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
3394
3813
|
import_radix_ui.Toggle.Root,
|
|
3395
3814
|
{
|
|
3396
3815
|
"data-slot": "toggle",
|
|
@@ -3401,8 +3820,8 @@ function Toggle({
|
|
|
3401
3820
|
}
|
|
3402
3821
|
|
|
3403
3822
|
// src/ui/toggle-group.tsx
|
|
3404
|
-
var
|
|
3405
|
-
var ToggleGroupContext =
|
|
3823
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
3824
|
+
var ToggleGroupContext = React2.createContext({
|
|
3406
3825
|
value: "",
|
|
3407
3826
|
onValueChange: () => {
|
|
3408
3827
|
}
|
|
@@ -3414,13 +3833,13 @@ function ToggleGroup({
|
|
|
3414
3833
|
children,
|
|
3415
3834
|
...props
|
|
3416
3835
|
}) {
|
|
3417
|
-
return /* @__PURE__ */ (0,
|
|
3836
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3418
3837
|
"div",
|
|
3419
3838
|
{
|
|
3420
3839
|
role: "group",
|
|
3421
3840
|
className: cn("flex items-center gap-1 p-1 bg-muted rounded-md", className),
|
|
3422
3841
|
...props,
|
|
3423
|
-
children: /* @__PURE__ */ (0,
|
|
3842
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ToggleGroupContext.Provider, { value: { value, onValueChange }, children })
|
|
3424
3843
|
}
|
|
3425
3844
|
);
|
|
3426
3845
|
}
|
|
@@ -3430,8 +3849,8 @@ function ToggleGroupItem({
|
|
|
3430
3849
|
children,
|
|
3431
3850
|
...props
|
|
3432
3851
|
}) {
|
|
3433
|
-
const { value: groupValue, onValueChange } =
|
|
3434
|
-
return /* @__PURE__ */ (0,
|
|
3852
|
+
const { value: groupValue, onValueChange } = React2.useContext(ToggleGroupContext);
|
|
3853
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3435
3854
|
Toggle,
|
|
3436
3855
|
{
|
|
3437
3856
|
pressed: groupValue === value,
|
|
@@ -3473,7 +3892,7 @@ function isEditSessionActive() {
|
|
|
3473
3892
|
}
|
|
3474
3893
|
|
|
3475
3894
|
// src/ui/badge.tsx
|
|
3476
|
-
var
|
|
3895
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
3477
3896
|
var badgeVariants = cva(
|
|
3478
3897
|
"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",
|
|
3479
3898
|
{
|
|
@@ -3491,11 +3910,11 @@ var badgeVariants = cva(
|
|
|
3491
3910
|
}
|
|
3492
3911
|
);
|
|
3493
3912
|
function Badge({ className, variant, ...props }) {
|
|
3494
|
-
return /* @__PURE__ */ (0,
|
|
3913
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
3495
3914
|
}
|
|
3496
3915
|
|
|
3497
3916
|
// src/OhhwellsBridge.tsx
|
|
3498
|
-
var
|
|
3917
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
3499
3918
|
var PRIMARY = "#0885FE";
|
|
3500
3919
|
var IMAGE_FADE_MS = 300;
|
|
3501
3920
|
function runOpacityFade(el, onDone) {
|
|
@@ -3546,6 +3965,41 @@ function fadeInBgImage(el, url, onReady) {
|
|
|
3546
3965
|
if (!prevPos || prevPos === "static") el.style.position = prevPos;
|
|
3547
3966
|
});
|
|
3548
3967
|
}
|
|
3968
|
+
function getSectionsTracker() {
|
|
3969
|
+
let el = document.querySelector("[data-ohw-sections-tracker]");
|
|
3970
|
+
if (!el) {
|
|
3971
|
+
el = document.createElement("div");
|
|
3972
|
+
el.setAttribute("data-ohw-sections-tracker", "");
|
|
3973
|
+
el.style.display = "none";
|
|
3974
|
+
document.body.appendChild(el);
|
|
3975
|
+
}
|
|
3976
|
+
return el;
|
|
3977
|
+
}
|
|
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;
|
|
3982
|
+
const container = document.createElement("div");
|
|
3983
|
+
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 }));
|
|
3986
|
+
const tracker = getSectionsTracker();
|
|
3987
|
+
let sections = [];
|
|
3988
|
+
try {
|
|
3989
|
+
sections = JSON.parse(tracker.textContent || "[]");
|
|
3990
|
+
} catch {
|
|
3991
|
+
}
|
|
3992
|
+
if (!sections.find((s) => s.type === "scheduling" && s.insertAfter === insertAfter)) {
|
|
3993
|
+
sections.push({
|
|
3994
|
+
type: "scheduling",
|
|
3995
|
+
insertAfter,
|
|
3996
|
+
pagePath: window.location.pathname,
|
|
3997
|
+
...scheduleId ? { scheduleId } : {}
|
|
3998
|
+
});
|
|
3999
|
+
tracker.textContent = JSON.stringify(sections);
|
|
4000
|
+
}
|
|
4001
|
+
return true;
|
|
4002
|
+
}
|
|
3549
4003
|
function collectEditableNodes() {
|
|
3550
4004
|
return Array.from(document.querySelectorAll("[data-ohw-editable]")).map((el) => {
|
|
3551
4005
|
if (el.dataset.ohwEditable === "image") {
|
|
@@ -3703,7 +4157,7 @@ var TOOLBAR_GROUPS = [
|
|
|
3703
4157
|
];
|
|
3704
4158
|
function GlowFrame({ rect, elRef }) {
|
|
3705
4159
|
const GAP = 6;
|
|
3706
|
-
return /* @__PURE__ */ (0,
|
|
4160
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3707
4161
|
"div",
|
|
3708
4162
|
{
|
|
3709
4163
|
ref: elRef,
|
|
@@ -3754,7 +4208,7 @@ function FloatingToolbar({
|
|
|
3754
4208
|
activeCommands
|
|
3755
4209
|
}) {
|
|
3756
4210
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll);
|
|
3757
|
-
return /* @__PURE__ */ (0,
|
|
4211
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3758
4212
|
"div",
|
|
3759
4213
|
{
|
|
3760
4214
|
ref: elRef,
|
|
@@ -3777,11 +4231,11 @@ function FloatingToolbar({
|
|
|
3777
4231
|
pointerEvents: "auto",
|
|
3778
4232
|
whiteSpace: "nowrap"
|
|
3779
4233
|
},
|
|
3780
|
-
children: TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0,
|
|
3781
|
-
gi > 0 && /* @__PURE__ */ (0,
|
|
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 } }),
|
|
3782
4236
|
btns.map((btn) => {
|
|
3783
4237
|
const isActive = activeCommands.has(btn.cmd);
|
|
3784
|
-
return /* @__PURE__ */ (0,
|
|
4238
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3785
4239
|
"button",
|
|
3786
4240
|
{
|
|
3787
4241
|
title: btn.title,
|
|
@@ -3807,7 +4261,7 @@ function FloatingToolbar({
|
|
|
3807
4261
|
flexShrink: 0,
|
|
3808
4262
|
padding: 6
|
|
3809
4263
|
},
|
|
3810
|
-
children: /* @__PURE__ */ (0,
|
|
4264
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3811
4265
|
"svg",
|
|
3812
4266
|
{
|
|
3813
4267
|
width: "16",
|
|
@@ -3840,7 +4294,7 @@ function StateToggle({
|
|
|
3840
4294
|
states,
|
|
3841
4295
|
onStateChange
|
|
3842
4296
|
}) {
|
|
3843
|
-
return /* @__PURE__ */ (0,
|
|
4297
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3844
4298
|
ToggleGroup,
|
|
3845
4299
|
{
|
|
3846
4300
|
"data-ohw-state-toggle": "",
|
|
@@ -3854,7 +4308,7 @@ function StateToggle({
|
|
|
3854
4308
|
left: rect.right - 8,
|
|
3855
4309
|
transform: "translateX(-100%)"
|
|
3856
4310
|
},
|
|
3857
|
-
children: states.map((state) => /* @__PURE__ */ (0,
|
|
4311
|
+
children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
3858
4312
|
}
|
|
3859
4313
|
);
|
|
3860
4314
|
}
|
|
@@ -3864,8 +4318,8 @@ function OhhwellsBridge() {
|
|
|
3864
4318
|
const router = (0, import_navigation.useRouter)();
|
|
3865
4319
|
const searchParams = (0, import_navigation.useSearchParams)();
|
|
3866
4320
|
const isEditMode = isEditSessionActive();
|
|
3867
|
-
const [bridgeRoot, setBridgeRoot] = (0,
|
|
3868
|
-
(0,
|
|
4321
|
+
const [bridgeRoot, setBridgeRoot] = (0, import_react2.useState)(null);
|
|
4322
|
+
(0, import_react2.useEffect)(() => {
|
|
3869
4323
|
const figtreeFontId = "ohw-figtree-font";
|
|
3870
4324
|
if (!document.getElementById(figtreeFontId)) {
|
|
3871
4325
|
const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
|
|
@@ -3893,39 +4347,39 @@ function OhhwellsBridge() {
|
|
|
3893
4347
|
const parts = window.location.hostname.split(".");
|
|
3894
4348
|
return parts.length >= 3 && parts[0] !== "www" ? parts[0] : "";
|
|
3895
4349
|
})();
|
|
3896
|
-
const postToParent = (0,
|
|
4350
|
+
const postToParent = (0, import_react2.useCallback)((data) => {
|
|
3897
4351
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
3898
4352
|
window.parent.postMessage(data, "*");
|
|
3899
4353
|
}
|
|
3900
4354
|
}, []);
|
|
3901
|
-
const [fetchState, setFetchState] = (0,
|
|
3902
|
-
const autoSaveTimers = (0,
|
|
3903
|
-
const activeElRef = (0,
|
|
3904
|
-
const originalContentRef = (0,
|
|
3905
|
-
const activeStateElRef = (0,
|
|
3906
|
-
const parentScrollRef = (0,
|
|
3907
|
-
const toolbarElRef = (0,
|
|
3908
|
-
const glowElRef = (0,
|
|
3909
|
-
const hoveredImageRef = (0,
|
|
3910
|
-
const hoveredImageHasTextOverlapRef = (0,
|
|
3911
|
-
const hoveredGapRef = (0,
|
|
3912
|
-
const imageUnhoverTimerRef = (0,
|
|
3913
|
-
const imageShowTimerRef = (0,
|
|
3914
|
-
const editStylesRef = (0,
|
|
3915
|
-
const activateRef = (0,
|
|
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)(() => {
|
|
3916
4370
|
});
|
|
3917
|
-
const deactivateRef = (0,
|
|
4371
|
+
const deactivateRef = (0, import_react2.useRef)(() => {
|
|
3918
4372
|
});
|
|
3919
|
-
const refreshActiveCommandsRef = (0,
|
|
4373
|
+
const refreshActiveCommandsRef = (0, import_react2.useRef)(() => {
|
|
3920
4374
|
});
|
|
3921
|
-
const postToParentRef = (0,
|
|
4375
|
+
const postToParentRef = (0, import_react2.useRef)(postToParent);
|
|
3922
4376
|
postToParentRef.current = postToParent;
|
|
3923
|
-
const [toolbarRect, setToolbarRect] = (0,
|
|
3924
|
-
const [toggleState, setToggleState] = (0,
|
|
3925
|
-
const [maxBadge, setMaxBadge] = (0,
|
|
3926
|
-
const [activeCommands, setActiveCommands] = (0,
|
|
3927
|
-
const [sectionGap, setSectionGap] = (0,
|
|
3928
|
-
(0,
|
|
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)(() => {
|
|
3929
4383
|
const update = () => {
|
|
3930
4384
|
const el = activeElRef.current;
|
|
3931
4385
|
if (el) setToolbarRect(el.getBoundingClientRect());
|
|
@@ -3949,10 +4403,10 @@ function OhhwellsBridge() {
|
|
|
3949
4403
|
vvp.removeEventListener("resize", update);
|
|
3950
4404
|
};
|
|
3951
4405
|
}, []);
|
|
3952
|
-
const refreshStateRules = (0,
|
|
4406
|
+
const refreshStateRules = (0, import_react2.useCallback)(() => {
|
|
3953
4407
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
3954
4408
|
}, []);
|
|
3955
|
-
const deactivate = (0,
|
|
4409
|
+
const deactivate = (0, import_react2.useCallback)(() => {
|
|
3956
4410
|
const el = activeElRef.current;
|
|
3957
4411
|
if (!el) return;
|
|
3958
4412
|
const key = el.dataset.ohwKey;
|
|
@@ -3977,7 +4431,7 @@ function OhhwellsBridge() {
|
|
|
3977
4431
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
3978
4432
|
postToParent({ type: "ow:exit-edit" });
|
|
3979
4433
|
}, [postToParent]);
|
|
3980
|
-
const activate = (0,
|
|
4434
|
+
const activate = (0, import_react2.useCallback)((el) => {
|
|
3981
4435
|
if (activeElRef.current === el) return;
|
|
3982
4436
|
deactivate();
|
|
3983
4437
|
if (hoveredImageRef.current) {
|
|
@@ -3995,14 +4449,27 @@ function OhhwellsBridge() {
|
|
|
3995
4449
|
}, [deactivate, postToParent]);
|
|
3996
4450
|
activateRef.current = activate;
|
|
3997
4451
|
deactivateRef.current = deactivate;
|
|
3998
|
-
(0,
|
|
4452
|
+
(0, import_react2.useLayoutEffect)(() => {
|
|
3999
4453
|
if (!subdomain || isEditMode) {
|
|
4000
4454
|
setFetchState("done");
|
|
4001
4455
|
return;
|
|
4002
4456
|
}
|
|
4003
4457
|
const applyContent = (content) => {
|
|
4004
4458
|
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
|
+
}
|
|
4005
4471
|
for (const [key, val] of Object.entries(content)) {
|
|
4472
|
+
if (key === "__ohw_sections") continue;
|
|
4006
4473
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
4007
4474
|
if (el.dataset.ohwEditable === "image") {
|
|
4008
4475
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -4045,12 +4512,24 @@ function OhhwellsBridge() {
|
|
|
4045
4512
|
cancelled = true;
|
|
4046
4513
|
};
|
|
4047
4514
|
}, [subdomain, isEditMode, pathname]);
|
|
4048
|
-
(0,
|
|
4515
|
+
(0, import_react2.useEffect)(() => {
|
|
4049
4516
|
if (!subdomain || isEditMode) return;
|
|
4050
4517
|
const applyFromCache = () => {
|
|
4051
4518
|
const content = contentCache.get(subdomain);
|
|
4052
4519
|
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
|
+
}
|
|
4053
4531
|
for (const [key, val] of Object.entries(content)) {
|
|
4532
|
+
if (key === "__ohw_sections") continue;
|
|
4054
4533
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
4055
4534
|
if (el.dataset.ohwEditable === "image") {
|
|
4056
4535
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -4069,16 +4548,16 @@ function OhhwellsBridge() {
|
|
|
4069
4548
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
4070
4549
|
return () => observer.disconnect();
|
|
4071
4550
|
}, [subdomain, isEditMode]);
|
|
4072
|
-
(0,
|
|
4551
|
+
(0, import_react2.useLayoutEffect)(() => {
|
|
4073
4552
|
const el = document.getElementById("ohw-loader");
|
|
4074
4553
|
if (!el) return;
|
|
4075
4554
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
4076
4555
|
el.style.display = visible ? "flex" : "none";
|
|
4077
4556
|
}, [subdomain, fetchState]);
|
|
4078
|
-
(0,
|
|
4557
|
+
(0, import_react2.useEffect)(() => {
|
|
4079
4558
|
postToParent({ type: "ow:navigation", path: pathname });
|
|
4080
4559
|
}, [pathname, postToParent]);
|
|
4081
|
-
(0,
|
|
4560
|
+
(0, import_react2.useEffect)(() => {
|
|
4082
4561
|
if (!isEditMode) return;
|
|
4083
4562
|
const measure = () => {
|
|
4084
4563
|
const h = document.body.scrollHeight;
|
|
@@ -4102,7 +4581,7 @@ function OhhwellsBridge() {
|
|
|
4102
4581
|
window.removeEventListener("resize", handleResize);
|
|
4103
4582
|
};
|
|
4104
4583
|
}, [pathname, isEditMode, postToParent]);
|
|
4105
|
-
(0,
|
|
4584
|
+
(0, import_react2.useEffect)(() => {
|
|
4106
4585
|
if (!subdomainFromQuery || isEditMode) return;
|
|
4107
4586
|
const handleClick = (e) => {
|
|
4108
4587
|
const anchor = e.target.closest("a");
|
|
@@ -4118,7 +4597,7 @@ function OhhwellsBridge() {
|
|
|
4118
4597
|
document.addEventListener("click", handleClick, true);
|
|
4119
4598
|
return () => document.removeEventListener("click", handleClick, true);
|
|
4120
4599
|
}, [subdomainFromQuery, isEditMode, router]);
|
|
4121
|
-
(0,
|
|
4600
|
+
(0, import_react2.useEffect)(() => {
|
|
4122
4601
|
if (!isEditMode) {
|
|
4123
4602
|
editStylesRef.current?.base.remove();
|
|
4124
4603
|
editStylesRef.current?.forceHover.remove();
|
|
@@ -4378,6 +4857,15 @@ function OhhwellsBridge() {
|
|
|
4378
4857
|
textEditable.setAttribute("data-ohw-hovered", "");
|
|
4379
4858
|
return;
|
|
4380
4859
|
}
|
|
4860
|
+
if (hoveredGapRef.current) {
|
|
4861
|
+
if (hoveredImageRef.current) {
|
|
4862
|
+
hoveredImageRef.current = null;
|
|
4863
|
+
resumeAnimTracks();
|
|
4864
|
+
postToParentRef.current({ type: "ow:image-unhover" });
|
|
4865
|
+
}
|
|
4866
|
+
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
4867
|
+
return;
|
|
4868
|
+
}
|
|
4381
4869
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
4382
4870
|
if (imgEl !== hoveredImageRef.current || hoveredImageHasTextOverlapRef.current) {
|
|
4383
4871
|
hoveredImageRef.current = imgEl;
|
|
@@ -4466,17 +4954,17 @@ function OhhwellsBridge() {
|
|
|
4466
4954
|
};
|
|
4467
4955
|
const handleMouseMove = (e) => {
|
|
4468
4956
|
const { clientX, clientY } = e;
|
|
4957
|
+
probeSectionGapAt(clientX, clientY);
|
|
4469
4958
|
probeImageAt(clientX, clientY);
|
|
4470
4959
|
probeHoverCardsAt(clientX, clientY);
|
|
4471
|
-
probeSectionGapAt(clientX, clientY);
|
|
4472
4960
|
};
|
|
4473
4961
|
const handlePointerSync = (e) => {
|
|
4474
4962
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
4475
4963
|
const { clientX, clientY } = e.data;
|
|
4476
4964
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
4965
|
+
probeSectionGapAt(clientX, clientY);
|
|
4477
4966
|
probeImageAt(clientX, clientY);
|
|
4478
4967
|
probeHoverCardsAt(clientX, clientY);
|
|
4479
|
-
probeSectionGapAt(clientX, clientY);
|
|
4480
4968
|
};
|
|
4481
4969
|
const handleDragOver = (e) => {
|
|
4482
4970
|
e.preventDefault();
|
|
@@ -4633,6 +5121,18 @@ function OhhwellsBridge() {
|
|
|
4633
5121
|
const content = e.data.content;
|
|
4634
5122
|
if (!content) return;
|
|
4635
5123
|
for (const [key, val] of Object.entries(content)) {
|
|
5124
|
+
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
|
+
}
|
|
5134
|
+
continue;
|
|
5135
|
+
}
|
|
4636
5136
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
4637
5137
|
if (el.dataset.ohwEditable === "image") {
|
|
4638
5138
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -4687,7 +5187,71 @@ function OhhwellsBridge() {
|
|
|
4687
5187
|
};
|
|
4688
5188
|
const handleSave = (e) => {
|
|
4689
5189
|
if (e.data?.type !== "ow:save") return;
|
|
4690
|
-
|
|
5190
|
+
const nodes = collectEditableNodes();
|
|
5191
|
+
const tracker = document.querySelector("[data-ohw-sections-tracker]");
|
|
5192
|
+
if (tracker?.textContent) nodes.push({ key: "__ohw_sections", type: "sections", text: tracker.textContent });
|
|
5193
|
+
postToParentRef.current({ type: "ow:save-result", nodes });
|
|
5194
|
+
};
|
|
5195
|
+
const handleInsertSection = (e) => {
|
|
5196
|
+
if (e.data?.type !== "ow:insert-section") return;
|
|
5197
|
+
const { widgetType, insertAfter } = e.data;
|
|
5198
|
+
if (widgetType !== "scheduling") return;
|
|
5199
|
+
const inserted = mountSchedulingWidget(insertAfter, true);
|
|
5200
|
+
if (inserted) {
|
|
5201
|
+
const tracker = getSectionsTracker();
|
|
5202
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
|
|
5203
|
+
const h = document.documentElement.scrollHeight;
|
|
5204
|
+
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
5205
|
+
}
|
|
5206
|
+
};
|
|
5207
|
+
const handleSwitchSchedule = (e) => {
|
|
5208
|
+
if (e.data?.type !== "ow:switch-schedule") return;
|
|
5209
|
+
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 }] });
|
|
5223
|
+
};
|
|
5224
|
+
const handleClearSchedulingWidget = (e) => {
|
|
5225
|
+
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 }] });
|
|
5238
|
+
};
|
|
5239
|
+
const handleRemoveSchedulingSection = (e) => {
|
|
5240
|
+
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));
|
|
5243
|
+
const tracker = getSectionsTracker();
|
|
5244
|
+
let sections = [];
|
|
5245
|
+
try {
|
|
5246
|
+
sections = JSON.parse(tracker.textContent || "[]");
|
|
5247
|
+
} catch {
|
|
5248
|
+
}
|
|
5249
|
+
const currentPath = window.location.pathname;
|
|
5250
|
+
const updated = sections.filter((s) => !(s.type === "scheduling" && s.pagePath === currentPath));
|
|
5251
|
+
tracker.textContent = JSON.stringify(updated);
|
|
5252
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent }] });
|
|
5253
|
+
const h = document.documentElement.scrollHeight;
|
|
5254
|
+
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
4691
5255
|
};
|
|
4692
5256
|
const handleSelectionChange = () => {
|
|
4693
5257
|
if (!activeElRef.current) return;
|
|
@@ -4792,6 +5356,10 @@ function OhhwellsBridge() {
|
|
|
4792
5356
|
deactivateRef.current();
|
|
4793
5357
|
};
|
|
4794
5358
|
window.addEventListener("message", handleSave);
|
|
5359
|
+
window.addEventListener("message", handleInsertSection);
|
|
5360
|
+
window.addEventListener("message", handleSwitchSchedule);
|
|
5361
|
+
window.addEventListener("message", handleClearSchedulingWidget);
|
|
5362
|
+
window.addEventListener("message", handleRemoveSchedulingSection);
|
|
4795
5363
|
window.addEventListener("message", handleImageUrl);
|
|
4796
5364
|
window.addEventListener("message", handleAnimLock);
|
|
4797
5365
|
window.addEventListener("message", handleCanvasHeight);
|
|
@@ -4826,6 +5394,10 @@ function OhhwellsBridge() {
|
|
|
4826
5394
|
document.removeEventListener("selectionchange", handleSelectionChange);
|
|
4827
5395
|
window.removeEventListener("scroll", handleScroll, true);
|
|
4828
5396
|
window.removeEventListener("message", handleSave);
|
|
5397
|
+
window.removeEventListener("message", handleInsertSection);
|
|
5398
|
+
window.removeEventListener("message", handleSwitchSchedule);
|
|
5399
|
+
window.removeEventListener("message", handleClearSchedulingWidget);
|
|
5400
|
+
window.removeEventListener("message", handleRemoveSchedulingSection);
|
|
4829
5401
|
window.removeEventListener("message", handleImageUrl);
|
|
4830
5402
|
window.removeEventListener("message", handleAnimLock);
|
|
4831
5403
|
window.removeEventListener("message", handleCanvasHeight);
|
|
@@ -4840,7 +5412,7 @@ function OhhwellsBridge() {
|
|
|
4840
5412
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
4841
5413
|
};
|
|
4842
5414
|
}, [isEditMode, refreshStateRules]);
|
|
4843
|
-
(0,
|
|
5415
|
+
(0, import_react2.useEffect)(() => {
|
|
4844
5416
|
if (!isEditMode) return;
|
|
4845
5417
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|
|
4846
5418
|
el.removeAttribute("data-ohw-active-state");
|
|
@@ -4862,13 +5434,13 @@ function OhhwellsBridge() {
|
|
|
4862
5434
|
clearTimeout(timer);
|
|
4863
5435
|
};
|
|
4864
5436
|
}, [pathname, isEditMode, refreshStateRules, postToParent]);
|
|
4865
|
-
const handleCommand = (0,
|
|
5437
|
+
const handleCommand = (0, import_react2.useCallback)((cmd) => {
|
|
4866
5438
|
document.execCommand(cmd, false);
|
|
4867
5439
|
activeElRef.current?.focus();
|
|
4868
5440
|
if (activeElRef.current) setToolbarRect(activeElRef.current.getBoundingClientRect());
|
|
4869
5441
|
refreshActiveCommandsRef.current();
|
|
4870
5442
|
}, []);
|
|
4871
|
-
const handleStateChange = (0,
|
|
5443
|
+
const handleStateChange = (0, import_react2.useCallback)((state) => {
|
|
4872
5444
|
if (!activeStateElRef.current) return;
|
|
4873
5445
|
const el = activeStateElRef.current;
|
|
4874
5446
|
if (state === "Default") {
|
|
@@ -4882,12 +5454,12 @@ function OhhwellsBridge() {
|
|
|
4882
5454
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
4883
5455
|
}, [deactivate]);
|
|
4884
5456
|
return bridgeRoot ? (0, import_react_dom.createPortal)(
|
|
4885
|
-
/* @__PURE__ */ (0,
|
|
4886
|
-
toolbarRect && /* @__PURE__ */ (0,
|
|
4887
|
-
/* @__PURE__ */ (0,
|
|
4888
|
-
/* @__PURE__ */ (0,
|
|
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 })
|
|
4889
5461
|
] }),
|
|
4890
|
-
maxBadge && /* @__PURE__ */ (0,
|
|
5462
|
+
maxBadge && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
4891
5463
|
"div",
|
|
4892
5464
|
{
|
|
4893
5465
|
"data-ohw-max-badge": "",
|
|
@@ -4913,7 +5485,7 @@ function OhhwellsBridge() {
|
|
|
4913
5485
|
]
|
|
4914
5486
|
}
|
|
4915
5487
|
),
|
|
4916
|
-
toggleState && /* @__PURE__ */ (0,
|
|
5488
|
+
toggleState && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
4917
5489
|
StateToggle,
|
|
4918
5490
|
{
|
|
4919
5491
|
rect: toggleState.rect,
|
|
@@ -4922,15 +5494,15 @@ function OhhwellsBridge() {
|
|
|
4922
5494
|
onStateChange: handleStateChange
|
|
4923
5495
|
}
|
|
4924
5496
|
),
|
|
4925
|
-
sectionGap && /* @__PURE__ */ (0,
|
|
5497
|
+
sectionGap && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
4926
5498
|
"div",
|
|
4927
5499
|
{
|
|
4928
5500
|
"data-ohw-section-insert-line": "",
|
|
4929
5501
|
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
4930
5502
|
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
4931
5503
|
children: [
|
|
4932
|
-
/* @__PURE__ */ (0,
|
|
4933
|
-
/* @__PURE__ */ (0,
|
|
5504
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
5505
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
4934
5506
|
Badge,
|
|
4935
5507
|
{
|
|
4936
5508
|
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",
|
|
@@ -4943,7 +5515,7 @@ function OhhwellsBridge() {
|
|
|
4943
5515
|
children: "Add Section"
|
|
4944
5516
|
}
|
|
4945
5517
|
),
|
|
4946
|
-
/* @__PURE__ */ (0,
|
|
5518
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
4947
5519
|
]
|
|
4948
5520
|
}
|
|
4949
5521
|
)
|
|
@@ -4954,6 +5526,7 @@ function OhhwellsBridge() {
|
|
|
4954
5526
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4955
5527
|
0 && (module.exports = {
|
|
4956
5528
|
OhhwellsBridge,
|
|
5529
|
+
SchedulingWidget,
|
|
4957
5530
|
Toggle,
|
|
4958
5531
|
ToggleGroup,
|
|
4959
5532
|
ToggleGroupItem,
|