@sonordev/site-kit 1.2.10 → 1.3.1
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/{chunk-SQSBAPWA.mjs → chunk-3QKTOTWS.mjs} +5 -5
- package/dist/chunk-3QKTOTWS.mjs.map +1 -0
- package/dist/{chunk-BFJDUTXK.js → chunk-5NXUENL3.js} +3 -3
- package/dist/{chunk-BFJDUTXK.js.map → chunk-5NXUENL3.js.map} +1 -1
- package/dist/{chunk-6TFGPXXK.mjs → chunk-5TTTX6NN.mjs} +2 -2
- package/dist/{chunk-6TFGPXXK.mjs.map → chunk-5TTTX6NN.mjs.map} +1 -1
- package/dist/{chunk-5F7FFUPJ.mjs → chunk-J4K335PQ.mjs} +12 -5
- package/dist/chunk-J4K335PQ.mjs.map +1 -0
- package/dist/chunk-JB6I5PYV.js +939 -0
- package/dist/chunk-JB6I5PYV.js.map +1 -0
- package/dist/{chunk-7ROZJDXE.js → chunk-JKPJ2QCC.js} +2 -2
- package/dist/{chunk-7ROZJDXE.js.map → chunk-JKPJ2QCC.js.map} +1 -1
- package/dist/{chunk-JMNSED4O.mjs → chunk-KMLCQYEV.mjs} +3 -3
- package/dist/{chunk-JMNSED4O.mjs.map → chunk-KMLCQYEV.mjs.map} +1 -1
- package/dist/{chunk-2XOW276O.js → chunk-LTTTIJPN.js} +14 -7
- package/dist/chunk-LTTTIJPN.js.map +1 -0
- package/dist/{chunk-742WMKQC.js → chunk-NZHVGBAF.js} +2 -2
- package/dist/{chunk-742WMKQC.js.map → chunk-NZHVGBAF.js.map} +1 -1
- package/dist/{chunk-RMOL4TZ6.js → chunk-PJKHCYI5.js} +5 -5
- package/dist/chunk-PJKHCYI5.js.map +1 -0
- package/dist/{chunk-47Y3YSES.mjs → chunk-QBFTBORL.mjs} +2 -2
- package/dist/{chunk-47Y3YSES.mjs.map → chunk-QBFTBORL.mjs.map} +1 -1
- package/dist/{chunk-2RHO4KSK.mjs → chunk-RJTBSSZB.mjs} +4 -4
- package/dist/{chunk-2RHO4KSK.mjs.map → chunk-RJTBSSZB.mjs.map} +1 -1
- package/dist/{chunk-CFEOOJUT.js → chunk-RRBBMEDL.js} +7 -7
- package/dist/{chunk-CFEOOJUT.js.map → chunk-RRBBMEDL.js.map} +1 -1
- package/dist/chunk-W2TZYAUL.mjs +925 -0
- package/dist/chunk-W2TZYAUL.mjs.map +1 -0
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.mjs +1 -1
- package/dist/index.js +60 -938
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -917
- package/dist/index.mjs.map +1 -1
- package/dist/layout/client.js +2 -2
- package/dist/layout/client.mjs +1 -1
- package/dist/layout/index.js +6 -6
- package/dist/layout/index.mjs +3 -3
- package/dist/llms/index.js +12 -12
- package/dist/llms/index.mjs +2 -2
- package/dist/seo/index.d.mts +19 -198
- package/dist/seo/index.d.ts +19 -198
- package/dist/seo/index.js +68 -69
- package/dist/seo/index.js.map +1 -1
- package/dist/seo/index.mjs +36 -37
- package/dist/seo/index.mjs.map +1 -1
- package/dist/seo/server.js +4 -4
- package/dist/seo/server.mjs +2 -2
- package/dist/{server-api-HTSLBT6F.mjs → server-api-FCTEQOTK.mjs} +3 -3
- package/dist/{server-api-HTSLBT6F.mjs.map → server-api-FCTEQOTK.mjs.map} +1 -1
- package/dist/{server-api-C5JXIROA.js → server-api-SYINXTN7.js} +21 -21
- package/dist/{server-api-C5JXIROA.js.map → server-api-SYINXTN7.js.map} +1 -1
- package/dist/setup/index.js +2 -2
- package/dist/setup/index.mjs +1 -1
- package/dist/setup/server.js +2 -2
- package/dist/setup/server.mjs +1 -1
- package/dist/sitemap/index.js +2 -2
- package/dist/sitemap/index.mjs +1 -1
- package/dist/sync/index.js +63 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/index.mjs +4 -0
- package/dist/sync/index.mjs.map +1 -0
- package/package.json +6 -1
- package/dist/chunk-2XOW276O.js.map +0 -1
- package/dist/chunk-5F7FFUPJ.mjs.map +0 -1
- package/dist/chunk-RMOL4TZ6.js.map +0 -1
- package/dist/chunk-SQSBAPWA.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { SignalBridge, useSignalExperiment, useSignalEvent } from './chunk-4QHHFCAA.mjs';
|
|
2
2
|
export { SignalBridge, useSignal, useSignalConfig, useSignalEvent, useSignalExperiment, useSignalOutcome } from './chunk-4QHHFCAA.mjs';
|
|
3
|
+
export { clearRedirectCache, fetchRedirectRules, generateNextRedirects, handleManagedRedirects } from './chunk-XFOL6JDF.mjs';
|
|
3
4
|
export { ManagedImage, assignImageToSlot, clearImageSlot, fetchManagedImage, fetchManagedImages, listImageFiles, uploadImage } from './chunk-36Y7OWES.mjs';
|
|
4
5
|
export { TestimonialSection, fetchReviewStats, fetchReviews } from './chunk-APZMXRI3.mjs';
|
|
5
6
|
import './chunk-N24BPFF6.mjs';
|
|
6
7
|
export { CalendarView, CheckoutForm, EventCalendar, EventEmbed, EventModal, EventTile, OfferingCard, OfferingList, ProductEmbed, RegistrationForm, UpcomingEvents, createCheckoutSession, fetchNextEvent, fetchOffering, fetchOfferings, fetchProducts, fetchServices, fetchUpcomingEvents, formatDate, formatDateTime, formatPrice, getOfferingUrl, registerForEvent, useEventModal } from './chunk-6YXRLC6W.mjs';
|
|
8
|
+
export { BookingWidget, createBooking, createSlotHold, detectTimezone, fetchAvailability, fetchAvailableDates, fetchBookingTypeDetails, fetchBookingTypes, formatDate as formatBookingDate, formatTime as formatBookingTime, formatDuration, releaseSlotHold } from './chunk-W2TZYAUL.mjs';
|
|
7
9
|
export { SetupWizard } from './chunk-IKIJEKU3.mjs';
|
|
8
|
-
export { clearRedirectCache, fetchRedirectRules, generateNextRedirects, handleManagedRedirects } from './chunk-XFOL6JDF.mjs';
|
|
9
10
|
import './chunk-VZMDH3R4.mjs';
|
|
10
11
|
import { SitemapSync } from './chunk-EGZEZR2I.mjs';
|
|
11
12
|
import { AnalyticsProvider } from './chunk-TK76624B.mjs';
|
|
@@ -1496,921 +1497,6 @@ ${moduleConfigs.join("\n")}
|
|
|
1496
1497
|
}`;
|
|
1497
1498
|
}
|
|
1498
1499
|
|
|
1499
|
-
|
|
1500
|
-
var DEFAULT_API_URL = "https://api.sonor.io";
|
|
1501
|
-
function getApiConfig2() {
|
|
1502
|
-
const apiUrl = typeof window !== "undefined" ? window.__SITE_KIT_API_URL__ || DEFAULT_API_URL : DEFAULT_API_URL;
|
|
1503
|
-
const apiKey = typeof window !== "undefined" ? window.__SITE_KIT_API_KEY__ : void 0;
|
|
1504
|
-
return { apiUrl, apiKey };
|
|
1505
|
-
}
|
|
1506
|
-
function buildHeaders(apiKey, isPost = false) {
|
|
1507
|
-
const headers = {};
|
|
1508
|
-
if (isPost) headers["Content-Type"] = "application/json";
|
|
1509
|
-
if (apiKey) headers["x-api-key"] = apiKey;
|
|
1510
|
-
return headers;
|
|
1511
|
-
}
|
|
1512
|
-
async function fetchBookingTypes(orgSlug, apiUrl, apiKey) {
|
|
1513
|
-
const cfg = getApiConfig2();
|
|
1514
|
-
const url = apiUrl || cfg.apiUrl;
|
|
1515
|
-
const key = apiKey || cfg.apiKey;
|
|
1516
|
-
const endpoint = key ? `${url}/sync/widget/types` : `${url}/sync/public/${orgSlug}/types`;
|
|
1517
|
-
const response = await fetch(endpoint, { headers: buildHeaders(key) });
|
|
1518
|
-
if (!response.ok) {
|
|
1519
|
-
const msg = await response.json().catch(() => ({ message: response.statusText }));
|
|
1520
|
-
const detail = msg && typeof msg.message === "string" ? msg.message : response.statusText;
|
|
1521
|
-
throw new Error(`Failed to fetch booking types: ${response.status} ${detail}`);
|
|
1522
|
-
}
|
|
1523
|
-
const data = await response.json();
|
|
1524
|
-
return data.types || [];
|
|
1525
|
-
}
|
|
1526
|
-
async function fetchBookingTypeDetails(typeSlug, orgSlug, apiUrl, apiKey) {
|
|
1527
|
-
const cfg = getApiConfig2();
|
|
1528
|
-
const url = apiUrl || cfg.apiUrl;
|
|
1529
|
-
const key = apiKey || cfg.apiKey;
|
|
1530
|
-
const endpoint = key ? `${url}/sync/widget/types/${typeSlug}` : `${url}/sync/public/${orgSlug}/types/${typeSlug}`;
|
|
1531
|
-
const response = await fetch(endpoint, { headers: buildHeaders(key) });
|
|
1532
|
-
if (!response.ok) {
|
|
1533
|
-
const msg = await response.json().catch(() => ({ message: response.statusText }));
|
|
1534
|
-
const detail = msg && typeof msg.message === "string" ? msg.message : response.statusText;
|
|
1535
|
-
throw new Error(`Failed to fetch booking type: ${response.status} ${detail}`);
|
|
1536
|
-
}
|
|
1537
|
-
return response.json();
|
|
1538
|
-
}
|
|
1539
|
-
async function fetchAvailability(typeSlug, date, orgSlug, apiUrl, apiKey, timezone, hostId) {
|
|
1540
|
-
const cfg = getApiConfig2();
|
|
1541
|
-
const url = apiUrl || cfg.apiUrl;
|
|
1542
|
-
const key = apiKey || cfg.apiKey;
|
|
1543
|
-
const params = new URLSearchParams({ date });
|
|
1544
|
-
if (timezone) params.append("timezone", timezone);
|
|
1545
|
-
if (hostId) params.append("hostId", hostId);
|
|
1546
|
-
const endpoint = key ? `${url}/sync/widget/availability/${typeSlug}?${params}` : `${url}/sync/public/${orgSlug}/availability/${typeSlug}?${params}`;
|
|
1547
|
-
const response = await fetch(endpoint, { headers: buildHeaders(key) });
|
|
1548
|
-
if (!response.ok) {
|
|
1549
|
-
const msg = await response.json().catch(() => ({ message: response.statusText }));
|
|
1550
|
-
let detail = msg && typeof msg.message === "string" ? String(msg.message).trim() : (response.statusText || "").trim();
|
|
1551
|
-
if (detail === String(response.status) || /^\d+$/.test(detail)) detail = "";
|
|
1552
|
-
const rest = detail ? `${response.status} ${detail}` : String(response.status);
|
|
1553
|
-
const fallback = response.status === 404 && !detail ? "No times available. In the Portal, check Sync \u2192 Booking Types (Schedule a Tour) has a host assigned and the project API key is set for this site." : null;
|
|
1554
|
-
throw new Error(fallback || `Failed to fetch availability: ${rest}`.trim());
|
|
1555
|
-
}
|
|
1556
|
-
const data = await response.json();
|
|
1557
|
-
const raw = data.slots || [];
|
|
1558
|
-
return raw.map((slot) => ({
|
|
1559
|
-
start: slot.startTime ?? slot.start,
|
|
1560
|
-
end: slot.endTime ?? slot.end,
|
|
1561
|
-
hostId: slot.hostId,
|
|
1562
|
-
available: slot.available !== false
|
|
1563
|
-
}));
|
|
1564
|
-
}
|
|
1565
|
-
async function createSlotHold(holdData, apiUrl, apiKey) {
|
|
1566
|
-
const cfg = getApiConfig2();
|
|
1567
|
-
const url = apiUrl || cfg.apiUrl;
|
|
1568
|
-
const key = apiKey || cfg.apiKey;
|
|
1569
|
-
const endpoint = key ? `${url}/sync/widget/hold` : `${url}/sync/public/hold`;
|
|
1570
|
-
const response = await fetch(endpoint, {
|
|
1571
|
-
method: "POST",
|
|
1572
|
-
headers: buildHeaders(key, true),
|
|
1573
|
-
body: JSON.stringify(holdData)
|
|
1574
|
-
});
|
|
1575
|
-
if (!response.ok) {
|
|
1576
|
-
throw new Error(`Failed to hold slot: ${response.statusText}`);
|
|
1577
|
-
}
|
|
1578
|
-
return response.json();
|
|
1579
|
-
}
|
|
1580
|
-
async function releaseSlotHold(holdId, apiUrl, apiKey) {
|
|
1581
|
-
const cfg = getApiConfig2();
|
|
1582
|
-
const url = apiUrl || cfg.apiUrl;
|
|
1583
|
-
const key = apiKey || cfg.apiKey;
|
|
1584
|
-
const endpoint = key ? `${url}/sync/widget/hold/${holdId}` : `${url}/sync/public/hold/${holdId}`;
|
|
1585
|
-
await fetch(endpoint, {
|
|
1586
|
-
method: "DELETE",
|
|
1587
|
-
headers: buildHeaders(key)
|
|
1588
|
-
});
|
|
1589
|
-
}
|
|
1590
|
-
async function createBooking(bookingData, apiUrl, apiKey) {
|
|
1591
|
-
const cfg = getApiConfig2();
|
|
1592
|
-
const url = apiUrl || cfg.apiUrl;
|
|
1593
|
-
const key = apiKey || cfg.apiKey;
|
|
1594
|
-
const endpoint = key ? `${url}/sync/widget/booking` : `${url}/sync/public/booking`;
|
|
1595
|
-
const response = await fetch(endpoint, {
|
|
1596
|
-
method: "POST",
|
|
1597
|
-
headers: buildHeaders(key, true),
|
|
1598
|
-
body: JSON.stringify(bookingData)
|
|
1599
|
-
});
|
|
1600
|
-
if (!response.ok) {
|
|
1601
|
-
const errorData = await response.json().catch(() => ({}));
|
|
1602
|
-
throw new Error(errorData.message || `Failed to create booking: ${response.statusText}`);
|
|
1603
|
-
}
|
|
1604
|
-
return response.json();
|
|
1605
|
-
}
|
|
1606
|
-
async function fetchAvailableDates(typeSlug, startDate, endDate, orgSlug, apiUrl, apiKey, timezone) {
|
|
1607
|
-
const availableDates = [];
|
|
1608
|
-
const start = new Date(startDate);
|
|
1609
|
-
const end = new Date(endDate);
|
|
1610
|
-
const current = new Date(start);
|
|
1611
|
-
while (current <= end) {
|
|
1612
|
-
const dateStr = current.toISOString().split("T")[0];
|
|
1613
|
-
try {
|
|
1614
|
-
const slots = await fetchAvailability(typeSlug, dateStr, orgSlug, apiUrl, apiKey, timezone);
|
|
1615
|
-
if (slots.some((s) => s.available)) {
|
|
1616
|
-
availableDates.push(dateStr);
|
|
1617
|
-
}
|
|
1618
|
-
} catch {
|
|
1619
|
-
}
|
|
1620
|
-
current.setDate(current.getDate() + 1);
|
|
1621
|
-
}
|
|
1622
|
-
return availableDates;
|
|
1623
|
-
}
|
|
1624
|
-
function detectTimezone() {
|
|
1625
|
-
try {
|
|
1626
|
-
return Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
1627
|
-
} catch {
|
|
1628
|
-
return "America/New_York";
|
|
1629
|
-
}
|
|
1630
|
-
}
|
|
1631
|
-
function formatTime(isoString, timezone) {
|
|
1632
|
-
const date = new Date(isoString);
|
|
1633
|
-
return date.toLocaleTimeString("en-US", {
|
|
1634
|
-
hour: "numeric",
|
|
1635
|
-
minute: "2-digit",
|
|
1636
|
-
hour12: true,
|
|
1637
|
-
timeZone: timezone
|
|
1638
|
-
});
|
|
1639
|
-
}
|
|
1640
|
-
function formatDate2(isoString, timezone) {
|
|
1641
|
-
const date = new Date(isoString);
|
|
1642
|
-
return date.toLocaleDateString("en-US", {
|
|
1643
|
-
weekday: "long",
|
|
1644
|
-
month: "long",
|
|
1645
|
-
day: "numeric",
|
|
1646
|
-
year: "numeric",
|
|
1647
|
-
timeZone: timezone
|
|
1648
|
-
});
|
|
1649
|
-
}
|
|
1650
|
-
function formatDuration(minutes) {
|
|
1651
|
-
if (minutes < 60) {
|
|
1652
|
-
return `${minutes} min`;
|
|
1653
|
-
}
|
|
1654
|
-
const hours = Math.floor(minutes / 60);
|
|
1655
|
-
const mins = minutes % 60;
|
|
1656
|
-
if (mins === 0) {
|
|
1657
|
-
return `${hours} hour${hours > 1 ? "s" : ""}`;
|
|
1658
|
-
}
|
|
1659
|
-
return `${hours}h ${mins}m`;
|
|
1660
|
-
}
|
|
1661
|
-
var DEFAULT_API_URL2 = "https://api.sonor.io";
|
|
1662
|
-
var DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
1663
|
-
var MONTHS = [
|
|
1664
|
-
"January",
|
|
1665
|
-
"February",
|
|
1666
|
-
"March",
|
|
1667
|
-
"April",
|
|
1668
|
-
"May",
|
|
1669
|
-
"June",
|
|
1670
|
-
"July",
|
|
1671
|
-
"August",
|
|
1672
|
-
"September",
|
|
1673
|
-
"October",
|
|
1674
|
-
"November",
|
|
1675
|
-
"December"
|
|
1676
|
-
];
|
|
1677
|
-
function isSameDay(a, b) {
|
|
1678
|
-
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
1679
|
-
}
|
|
1680
|
-
function isBeforeDay(a, b) {
|
|
1681
|
-
const ac = new Date(a.getFullYear(), a.getMonth(), a.getDate());
|
|
1682
|
-
const bc = new Date(b.getFullYear(), b.getMonth(), b.getDate());
|
|
1683
|
-
return ac < bc;
|
|
1684
|
-
}
|
|
1685
|
-
function calendarDays(year, month) {
|
|
1686
|
-
const first = new Date(year, month, 1);
|
|
1687
|
-
const last = new Date(year, month + 1, 0);
|
|
1688
|
-
const cells = [];
|
|
1689
|
-
for (let i = 0; i < first.getDay(); i++) cells.push(null);
|
|
1690
|
-
for (let d = 1; d <= last.getDate(); d++) cells.push(new Date(year, month, d));
|
|
1691
|
-
return cells;
|
|
1692
|
-
}
|
|
1693
|
-
function ChevronLeft() {
|
|
1694
|
-
return /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx("path", { d: "M12.5 15L7.5 10L12.5 5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
1695
|
-
}
|
|
1696
|
-
function ChevronRight() {
|
|
1697
|
-
return /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx("path", { d: "M7.5 5L12.5 10L7.5 15", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
1698
|
-
}
|
|
1699
|
-
function ClockIcon() {
|
|
1700
|
-
return /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
1701
|
-
/* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "6.5", stroke: "currentColor", strokeWidth: "1.2" }),
|
|
1702
|
-
/* @__PURE__ */ jsx("path", { d: "M8 4.5V8L10 10", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
1703
|
-
] });
|
|
1704
|
-
}
|
|
1705
|
-
function GlobeIcon() {
|
|
1706
|
-
return /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
1707
|
-
/* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "6.5", stroke: "currentColor", strokeWidth: "1.2" }),
|
|
1708
|
-
/* @__PURE__ */ jsx("path", { d: "M1.5 8H14.5", stroke: "currentColor", strokeWidth: "1.2" }),
|
|
1709
|
-
/* @__PURE__ */ jsx("path", { d: "M8 1.5C9.66 3.34 10.61 5.62 10.61 8C10.61 10.38 9.66 12.66 8 14.5C6.34 12.66 5.39 10.38 5.39 8C5.39 5.62 6.34 3.34 8 1.5Z", stroke: "currentColor", strokeWidth: "1.2" })
|
|
1710
|
-
] });
|
|
1711
|
-
}
|
|
1712
|
-
function CheckCircleIcon() {
|
|
1713
|
-
return /* @__PURE__ */ jsxs("svg", { width: "56", height: "56", viewBox: "0 0 56 56", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
1714
|
-
/* @__PURE__ */ jsx("circle", { cx: "28", cy: "28", r: "28", fill: "var(--bw-primary)" }),
|
|
1715
|
-
/* @__PURE__ */ jsx("path", { d: "M18 28.5L24.5 35L38 21.5", stroke: "white", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
1716
|
-
] });
|
|
1717
|
-
}
|
|
1718
|
-
function CalendarPlusIcon() {
|
|
1719
|
-
return /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
1720
|
-
/* @__PURE__ */ jsx("rect", { x: "1.5", y: "2.5", width: "13", height: "12", rx: "1.5", stroke: "currentColor", strokeWidth: "1.2" }),
|
|
1721
|
-
/* @__PURE__ */ jsx("path", { d: "M1.5 6.5H14.5", stroke: "currentColor", strokeWidth: "1.2" }),
|
|
1722
|
-
/* @__PURE__ */ jsx("path", { d: "M5 1V4M11 1V4", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" }),
|
|
1723
|
-
/* @__PURE__ */ jsx("path", { d: "M8 9V12M6.5 10.5H9.5", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" })
|
|
1724
|
-
] });
|
|
1725
|
-
}
|
|
1726
|
-
function ArrowLeftIcon() {
|
|
1727
|
-
return /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx("path", { d: "M10 3L5 8L10 13", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
1728
|
-
}
|
|
1729
|
-
function SpinnerIcon() {
|
|
1730
|
-
return /* @__PURE__ */ jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: "bw-spinner", children: [
|
|
1731
|
-
/* @__PURE__ */ jsx("circle", { cx: "10", cy: "10", r: "8", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeDasharray: "50.265", strokeDashoffset: "25", opacity: "0.3" }),
|
|
1732
|
-
/* @__PURE__ */ jsx("circle", { cx: "10", cy: "10", r: "8", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeDasharray: "50.265", strokeDashoffset: "37.7" })
|
|
1733
|
-
] });
|
|
1734
|
-
}
|
|
1735
|
-
function BookingWidget({
|
|
1736
|
-
orgSlug,
|
|
1737
|
-
apiKey: propApiKey,
|
|
1738
|
-
apiUrl: propApiUrl,
|
|
1739
|
-
bookingTypeSlug,
|
|
1740
|
-
timezone: propTimezone,
|
|
1741
|
-
className = "",
|
|
1742
|
-
daysToShow = 60,
|
|
1743
|
-
onBookingComplete,
|
|
1744
|
-
onError,
|
|
1745
|
-
hideTypeSelector = false,
|
|
1746
|
-
styles: styles2 = {}
|
|
1747
|
-
}) {
|
|
1748
|
-
const apiKey = propApiKey || (typeof window !== "undefined" ? window.__SITE_KIT_API_KEY__ : void 0);
|
|
1749
|
-
const apiUrl = propApiUrl || (typeof window !== "undefined" ? window.__SITE_KIT_API_URL__ : void 0) || DEFAULT_API_URL2;
|
|
1750
|
-
const [step, setStep] = useState(bookingTypeSlug ? "datetime" : "type");
|
|
1751
|
-
const [loading, setLoading] = useState(false);
|
|
1752
|
-
const [slotsLoading, setSlotsLoading] = useState(false);
|
|
1753
|
-
const [error, setError] = useState(null);
|
|
1754
|
-
const [bookingTypes, setBookingTypes] = useState([]);
|
|
1755
|
-
const [selectedType, setSelectedType] = useState(null);
|
|
1756
|
-
const [viewMonth, setViewMonth] = useState(() => /* @__PURE__ */ new Date());
|
|
1757
|
-
const [selectedDate, setSelectedDate] = useState(null);
|
|
1758
|
-
const [slots, setSlots] = useState([]);
|
|
1759
|
-
const [selectedSlot, setSelectedSlot] = useState(null);
|
|
1760
|
-
const [confirmedSlot, setConfirmedSlot] = useState(false);
|
|
1761
|
-
const [hold, setHold] = useState(null);
|
|
1762
|
-
const [guestInfo, setGuestInfo] = useState({ name: "", email: "" });
|
|
1763
|
-
const [bookingResult, setBookingResult] = useState(null);
|
|
1764
|
-
const [submitting, setSubmitting] = useState(false);
|
|
1765
|
-
const slotsRef = useRef(null);
|
|
1766
|
-
const today = useMemo(() => {
|
|
1767
|
-
const d = /* @__PURE__ */ new Date();
|
|
1768
|
-
d.setHours(0, 0, 0, 0);
|
|
1769
|
-
return d;
|
|
1770
|
-
}, []);
|
|
1771
|
-
const timezone = useMemo(() => propTimezone || detectTimezone(), [propTimezone]);
|
|
1772
|
-
const shortTz = useMemo(() => {
|
|
1773
|
-
try {
|
|
1774
|
-
const parts = Intl.DateTimeFormat("en-US", { timeZone: timezone, timeZoneName: "short" }).formatToParts(/* @__PURE__ */ new Date());
|
|
1775
|
-
return parts.find((p) => p.type === "timeZoneName")?.value || timezone;
|
|
1776
|
-
} catch {
|
|
1777
|
-
return timezone;
|
|
1778
|
-
}
|
|
1779
|
-
}, [timezone]);
|
|
1780
|
-
const days = useMemo(() => calendarDays(viewMonth.getFullYear(), viewMonth.getMonth()), [viewMonth]);
|
|
1781
|
-
const maxDate = useMemo(() => {
|
|
1782
|
-
const d = new Date(today);
|
|
1783
|
-
d.setDate(d.getDate() + daysToShow);
|
|
1784
|
-
return d;
|
|
1785
|
-
}, [today, daysToShow]);
|
|
1786
|
-
useEffect(() => {
|
|
1787
|
-
if (bookingTypeSlug) {
|
|
1788
|
-
setLoading(true);
|
|
1789
|
-
fetchBookingTypeDetails(bookingTypeSlug, orgSlug, apiUrl, apiKey).then((type) => {
|
|
1790
|
-
setSelectedType(type);
|
|
1791
|
-
setStep("datetime");
|
|
1792
|
-
}).catch((err) => {
|
|
1793
|
-
setError(err.message);
|
|
1794
|
-
onError?.(err);
|
|
1795
|
-
}).finally(() => setLoading(false));
|
|
1796
|
-
} else {
|
|
1797
|
-
setLoading(true);
|
|
1798
|
-
fetchBookingTypes(orgSlug, apiUrl, apiKey).then((types) => setBookingTypes(types.filter((t) => t.is_active))).catch((err) => {
|
|
1799
|
-
setError(err.message);
|
|
1800
|
-
onError?.(err);
|
|
1801
|
-
}).finally(() => setLoading(false));
|
|
1802
|
-
}
|
|
1803
|
-
}, [orgSlug, apiKey, bookingTypeSlug, apiUrl, onError]);
|
|
1804
|
-
useEffect(() => {
|
|
1805
|
-
if (!selectedDate || !selectedType) return;
|
|
1806
|
-
const dateStr = selectedDate.toISOString().split("T")[0];
|
|
1807
|
-
setSlotsLoading(true);
|
|
1808
|
-
setSlots([]);
|
|
1809
|
-
setSelectedSlot(null);
|
|
1810
|
-
setConfirmedSlot(false);
|
|
1811
|
-
fetchAvailability(selectedType.slug, dateStr, orgSlug, apiUrl, apiKey, timezone).then((s) => setSlots(s.filter((slot) => slot.available))).catch((err) => {
|
|
1812
|
-
setError(err.message);
|
|
1813
|
-
onError?.(err);
|
|
1814
|
-
}).finally(() => setSlotsLoading(false));
|
|
1815
|
-
}, [selectedDate, selectedType, orgSlug, apiKey, apiUrl, timezone, onError]);
|
|
1816
|
-
const handleSlotSelect = useCallback((slot) => {
|
|
1817
|
-
setSelectedSlot(slot);
|
|
1818
|
-
setConfirmedSlot(false);
|
|
1819
|
-
}, []);
|
|
1820
|
-
const handleSlotConfirm = useCallback(async () => {
|
|
1821
|
-
if (!selectedType || !selectedSlot) return;
|
|
1822
|
-
if (hold) await releaseSlotHold(hold.holdId, apiUrl, apiKey).catch(() => {
|
|
1823
|
-
});
|
|
1824
|
-
setLoading(true);
|
|
1825
|
-
try {
|
|
1826
|
-
const newHold = await createSlotHold(
|
|
1827
|
-
{
|
|
1828
|
-
bookingType: selectedType.slug,
|
|
1829
|
-
slotStart: selectedSlot.start,
|
|
1830
|
-
slotEnd: selectedSlot.end,
|
|
1831
|
-
hostId: selectedSlot.hostId || "",
|
|
1832
|
-
sessionId: `bw-${Date.now()}`
|
|
1833
|
-
},
|
|
1834
|
-
apiUrl,
|
|
1835
|
-
apiKey
|
|
1836
|
-
);
|
|
1837
|
-
setHold(newHold);
|
|
1838
|
-
setConfirmedSlot(true);
|
|
1839
|
-
setStep("form");
|
|
1840
|
-
} catch (err) {
|
|
1841
|
-
setError(err.message);
|
|
1842
|
-
onError?.(err);
|
|
1843
|
-
} finally {
|
|
1844
|
-
setLoading(false);
|
|
1845
|
-
}
|
|
1846
|
-
}, [selectedType, selectedSlot, hold, timezone, apiUrl, apiKey, onError]);
|
|
1847
|
-
const handleBookingSubmit = useCallback(async (e) => {
|
|
1848
|
-
e.preventDefault();
|
|
1849
|
-
if (!selectedType || !selectedSlot) return;
|
|
1850
|
-
setSubmitting(true);
|
|
1851
|
-
setError(null);
|
|
1852
|
-
try {
|
|
1853
|
-
const result = await createBooking(
|
|
1854
|
-
{
|
|
1855
|
-
bookingType: selectedType.slug,
|
|
1856
|
-
scheduledAt: selectedSlot.start,
|
|
1857
|
-
hostId: selectedSlot.hostId || "",
|
|
1858
|
-
name: guestInfo.name,
|
|
1859
|
-
email: guestInfo.email,
|
|
1860
|
-
phone: guestInfo.phone,
|
|
1861
|
-
message: guestInfo.notes,
|
|
1862
|
-
source: "main-site",
|
|
1863
|
-
timezone,
|
|
1864
|
-
holdId: hold?.holdId,
|
|
1865
|
-
sessionId: `bw-${Date.now()}`,
|
|
1866
|
-
sourceUrl: typeof window !== "undefined" ? window.location.href : void 0
|
|
1867
|
-
},
|
|
1868
|
-
apiUrl,
|
|
1869
|
-
apiKey
|
|
1870
|
-
);
|
|
1871
|
-
setBookingResult(result);
|
|
1872
|
-
setStep("success");
|
|
1873
|
-
onBookingComplete?.(result);
|
|
1874
|
-
} catch (err) {
|
|
1875
|
-
setError(err.message);
|
|
1876
|
-
onError?.(err);
|
|
1877
|
-
} finally {
|
|
1878
|
-
setSubmitting(false);
|
|
1879
|
-
}
|
|
1880
|
-
}, [selectedType, selectedSlot, guestInfo, timezone, hold, apiUrl, apiKey, onBookingComplete, onError]);
|
|
1881
|
-
useEffect(() => {
|
|
1882
|
-
return () => {
|
|
1883
|
-
if (hold) releaseSlotHold(hold.holdId, apiUrl, apiKey).catch(() => {
|
|
1884
|
-
});
|
|
1885
|
-
};
|
|
1886
|
-
}, [hold, apiUrl, apiKey]);
|
|
1887
|
-
const canGoPrev = viewMonth.getFullYear() > today.getFullYear() || viewMonth.getMonth() > today.getMonth();
|
|
1888
|
-
const canGoNext = viewMonth < maxDate;
|
|
1889
|
-
const goMonth = (dir) => {
|
|
1890
|
-
setViewMonth((prev) => new Date(prev.getFullYear(), prev.getMonth() + dir, 1));
|
|
1891
|
-
};
|
|
1892
|
-
const groupedSlots = useMemo(() => {
|
|
1893
|
-
const morning = [];
|
|
1894
|
-
const afternoon = [];
|
|
1895
|
-
const evening = [];
|
|
1896
|
-
for (const s of slots) {
|
|
1897
|
-
const h = new Date(s.start).getHours();
|
|
1898
|
-
if (h < 12) morning.push(s);
|
|
1899
|
-
else if (h < 17) afternoon.push(s);
|
|
1900
|
-
else evening.push(s);
|
|
1901
|
-
}
|
|
1902
|
-
return { morning, afternoon, evening };
|
|
1903
|
-
}, [slots]);
|
|
1904
|
-
const cssVars = {
|
|
1905
|
-
"--bw-primary": styles2.primaryColor || "#0069ff",
|
|
1906
|
-
"--bw-primary-light": styles2.primaryColor ? `color-mix(in srgb, ${styles2.primaryColor} 12%, white)` : "#e8f1ff",
|
|
1907
|
-
"--bw-primary-hover": styles2.primaryColor ? `color-mix(in srgb, ${styles2.primaryColor} 90%, black)` : "#0055d4",
|
|
1908
|
-
"--bw-radius": styles2.borderRadius || "8px",
|
|
1909
|
-
"--bw-font": styles2.fontFamily || "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"
|
|
1910
|
-
};
|
|
1911
|
-
return /* @__PURE__ */ jsxs("div", { className: `bw-root ${className}`, style: cssVars, children: [
|
|
1912
|
-
error && /* @__PURE__ */ jsxs("div", { className: "bw-error", role: "alert", children: [
|
|
1913
|
-
/* @__PURE__ */ jsx("span", { children: error }),
|
|
1914
|
-
/* @__PURE__ */ jsx("button", { onClick: () => setError(null), "aria-label": "Dismiss error", children: "\xD7" })
|
|
1915
|
-
] }),
|
|
1916
|
-
step === "type" && !hideTypeSelector && /* @__PURE__ */ jsxs("div", { className: "bw-step bw-fade-in", children: [
|
|
1917
|
-
/* @__PURE__ */ jsx("h2", { className: "bw-heading", children: "Select a Service" }),
|
|
1918
|
-
loading ? /* @__PURE__ */ jsxs("div", { className: "bw-loading", children: [
|
|
1919
|
-
/* @__PURE__ */ jsx(SpinnerIcon, {}),
|
|
1920
|
-
" Loading services..."
|
|
1921
|
-
] }) : /* @__PURE__ */ jsx("div", { className: "bw-type-list", children: bookingTypes.map((type) => /* @__PURE__ */ jsxs(
|
|
1922
|
-
"button",
|
|
1923
|
-
{
|
|
1924
|
-
className: "bw-type-card",
|
|
1925
|
-
onClick: () => {
|
|
1926
|
-
setSelectedType(type);
|
|
1927
|
-
setStep("datetime");
|
|
1928
|
-
},
|
|
1929
|
-
children: [
|
|
1930
|
-
/* @__PURE__ */ jsx("span", { className: "bw-type-name", children: type.name }),
|
|
1931
|
-
type.description && /* @__PURE__ */ jsx("span", { className: "bw-type-desc", children: type.description }),
|
|
1932
|
-
/* @__PURE__ */ jsxs("span", { className: "bw-type-meta", children: [
|
|
1933
|
-
/* @__PURE__ */ jsx(ClockIcon, {}),
|
|
1934
|
-
" ",
|
|
1935
|
-
formatDuration(type.duration_minutes),
|
|
1936
|
-
type.price_cents ? ` \xB7 $${(type.price_cents / 100).toFixed(2)}` : " \xB7 Free"
|
|
1937
|
-
] })
|
|
1938
|
-
]
|
|
1939
|
-
},
|
|
1940
|
-
type.id
|
|
1941
|
-
)) })
|
|
1942
|
-
] }),
|
|
1943
|
-
step === "datetime" && selectedType && /* @__PURE__ */ jsxs("div", { className: "bw-step bw-fade-in", children: [
|
|
1944
|
-
/* @__PURE__ */ jsxs("div", { className: "bw-info-header", children: [
|
|
1945
|
-
!bookingTypeSlug && /* @__PURE__ */ jsx("button", { className: "bw-back", onClick: () => {
|
|
1946
|
-
setSelectedType(null);
|
|
1947
|
-
setStep("type");
|
|
1948
|
-
}, children: /* @__PURE__ */ jsx(ArrowLeftIcon, {}) }),
|
|
1949
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
1950
|
-
/* @__PURE__ */ jsx("h2", { className: "bw-heading", children: selectedType.name }),
|
|
1951
|
-
/* @__PURE__ */ jsxs("div", { className: "bw-meta-row", children: [
|
|
1952
|
-
/* @__PURE__ */ jsxs("span", { className: "bw-badge", children: [
|
|
1953
|
-
/* @__PURE__ */ jsx(ClockIcon, {}),
|
|
1954
|
-
" ",
|
|
1955
|
-
formatDuration(selectedType.duration_minutes)
|
|
1956
|
-
] }),
|
|
1957
|
-
/* @__PURE__ */ jsxs("span", { className: "bw-badge", children: [
|
|
1958
|
-
/* @__PURE__ */ jsx(GlobeIcon, {}),
|
|
1959
|
-
" ",
|
|
1960
|
-
shortTz
|
|
1961
|
-
] })
|
|
1962
|
-
] })
|
|
1963
|
-
] })
|
|
1964
|
-
] }),
|
|
1965
|
-
/* @__PURE__ */ jsxs("div", { className: "bw-datetime-layout", children: [
|
|
1966
|
-
/* @__PURE__ */ jsxs("div", { className: "bw-calendar", children: [
|
|
1967
|
-
/* @__PURE__ */ jsxs("div", { className: "bw-cal-header", children: [
|
|
1968
|
-
/* @__PURE__ */ jsx("button", { className: "bw-cal-nav", onClick: () => goMonth(-1), disabled: !canGoPrev, "aria-label": "Previous month", children: /* @__PURE__ */ jsx(ChevronLeft, {}) }),
|
|
1969
|
-
/* @__PURE__ */ jsxs("span", { className: "bw-cal-title", children: [
|
|
1970
|
-
MONTHS[viewMonth.getMonth()],
|
|
1971
|
-
" ",
|
|
1972
|
-
viewMonth.getFullYear()
|
|
1973
|
-
] }),
|
|
1974
|
-
/* @__PURE__ */ jsx("button", { className: "bw-cal-nav", onClick: () => goMonth(1), disabled: !canGoNext, "aria-label": "Next month", children: /* @__PURE__ */ jsx(ChevronRight, {}) })
|
|
1975
|
-
] }),
|
|
1976
|
-
/* @__PURE__ */ jsx("div", { className: "bw-cal-weekdays", children: DAYS.map((d) => /* @__PURE__ */ jsx("span", { className: "bw-cal-wd", children: d }, d)) }),
|
|
1977
|
-
/* @__PURE__ */ jsx("div", { className: "bw-cal-grid", children: days.map((date, i) => {
|
|
1978
|
-
if (!date) return /* @__PURE__ */ jsx("span", { className: "bw-cal-empty" }, `e-${i}`);
|
|
1979
|
-
const past = isBeforeDay(date, today);
|
|
1980
|
-
const future = date > maxDate;
|
|
1981
|
-
const disabled = past || future;
|
|
1982
|
-
const sel = selectedDate && isSameDay(date, selectedDate);
|
|
1983
|
-
const isToday = isSameDay(date, today);
|
|
1984
|
-
return /* @__PURE__ */ jsx(
|
|
1985
|
-
"button",
|
|
1986
|
-
{
|
|
1987
|
-
className: `bw-cal-day${sel ? " selected" : ""}${isToday ? " today" : ""}${disabled ? " disabled" : ""}`,
|
|
1988
|
-
onClick: () => !disabled && setSelectedDate(date),
|
|
1989
|
-
disabled,
|
|
1990
|
-
"aria-label": date.toLocaleDateString("en-US", { weekday: "long", month: "long", day: "numeric" }),
|
|
1991
|
-
"aria-pressed": sel || void 0,
|
|
1992
|
-
children: date.getDate()
|
|
1993
|
-
},
|
|
1994
|
-
date.toISOString()
|
|
1995
|
-
);
|
|
1996
|
-
}) })
|
|
1997
|
-
] }),
|
|
1998
|
-
/* @__PURE__ */ jsx("div", { className: `bw-times${selectedDate ? " visible" : ""}`, ref: slotsRef, children: !selectedDate ? /* @__PURE__ */ jsxs("div", { className: "bw-times-placeholder", children: [
|
|
1999
|
-
/* @__PURE__ */ jsx(CalendarPlusIcon, {}),
|
|
2000
|
-
/* @__PURE__ */ jsx("span", { children: "Select a date to view available times" })
|
|
2001
|
-
] }) : slotsLoading ? /* @__PURE__ */ jsxs("div", { className: "bw-loading", children: [
|
|
2002
|
-
/* @__PURE__ */ jsx(SpinnerIcon, {}),
|
|
2003
|
-
" Loading times..."
|
|
2004
|
-
] }) : slots.length === 0 ? /* @__PURE__ */ jsx("div", { className: "bw-times-empty", children: "No available times on this date. Try another day." }) : /* @__PURE__ */ jsxs("div", { className: "bw-times-scroll", children: [
|
|
2005
|
-
/* @__PURE__ */ jsx("p", { className: "bw-times-date", children: selectedDate.toLocaleDateString("en-US", { weekday: "long", month: "short", day: "numeric" }) }),
|
|
2006
|
-
groupedSlots.morning.length > 0 && /* @__PURE__ */ jsxs("div", { className: "bw-time-group", children: [
|
|
2007
|
-
/* @__PURE__ */ jsx("span", { className: "bw-time-label", children: "Morning" }),
|
|
2008
|
-
groupedSlots.morning.map((slot) => /* @__PURE__ */ jsx(TimeButton, { slot, selected: selectedSlot?.start === slot.start, confirmed: confirmedSlot && selectedSlot?.start === slot.start, onClick: () => handleSlotSelect(slot), onConfirm: handleSlotConfirm, timezone, loading }, slot.start))
|
|
2009
|
-
] }),
|
|
2010
|
-
groupedSlots.afternoon.length > 0 && /* @__PURE__ */ jsxs("div", { className: "bw-time-group", children: [
|
|
2011
|
-
/* @__PURE__ */ jsx("span", { className: "bw-time-label", children: "Afternoon" }),
|
|
2012
|
-
groupedSlots.afternoon.map((slot) => /* @__PURE__ */ jsx(TimeButton, { slot, selected: selectedSlot?.start === slot.start, confirmed: confirmedSlot && selectedSlot?.start === slot.start, onClick: () => handleSlotSelect(slot), onConfirm: handleSlotConfirm, timezone, loading }, slot.start))
|
|
2013
|
-
] }),
|
|
2014
|
-
groupedSlots.evening.length > 0 && /* @__PURE__ */ jsxs("div", { className: "bw-time-group", children: [
|
|
2015
|
-
/* @__PURE__ */ jsx("span", { className: "bw-time-label", children: "Evening" }),
|
|
2016
|
-
groupedSlots.evening.map((slot) => /* @__PURE__ */ jsx(TimeButton, { slot, selected: selectedSlot?.start === slot.start, confirmed: confirmedSlot && selectedSlot?.start === slot.start, onClick: () => handleSlotSelect(slot), onConfirm: handleSlotConfirm, timezone, loading }, slot.start))
|
|
2017
|
-
] }),
|
|
2018
|
-
(groupedSlots.afternoon.length > 0 || groupedSlots.evening.length > 0) && /* @__PURE__ */ jsx("p", { className: "bw-times-scroll-hint", children: "Scroll for more times" })
|
|
2019
|
-
] }) })
|
|
2020
|
-
] })
|
|
2021
|
-
] }),
|
|
2022
|
-
step === "form" && selectedType && selectedSlot && /* @__PURE__ */ jsxs("div", { className: "bw-step bw-fade-in", children: [
|
|
2023
|
-
/* @__PURE__ */ jsxs("div", { className: "bw-info-header", children: [
|
|
2024
|
-
/* @__PURE__ */ jsx("button", { className: "bw-back", onClick: () => setStep("datetime"), children: /* @__PURE__ */ jsx(ArrowLeftIcon, {}) }),
|
|
2025
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
2026
|
-
/* @__PURE__ */ jsx("h2", { className: "bw-heading", children: "Your Details" }),
|
|
2027
|
-
/* @__PURE__ */ jsxs("div", { className: "bw-meta-row", children: [
|
|
2028
|
-
/* @__PURE__ */ jsxs("span", { className: "bw-badge", children: [
|
|
2029
|
-
/* @__PURE__ */ jsx(ClockIcon, {}),
|
|
2030
|
-
" ",
|
|
2031
|
-
formatDuration(selectedType.duration_minutes)
|
|
2032
|
-
] }),
|
|
2033
|
-
/* @__PURE__ */ jsxs("span", { className: "bw-badge-accent", children: [
|
|
2034
|
-
formatDate2(selectedSlot.start, timezone),
|
|
2035
|
-
" \xB7 ",
|
|
2036
|
-
formatTime(selectedSlot.start, timezone)
|
|
2037
|
-
] })
|
|
2038
|
-
] })
|
|
2039
|
-
] })
|
|
2040
|
-
] }),
|
|
2041
|
-
hold && /* @__PURE__ */ jsxs("div", { className: "bw-hold-notice", children: [
|
|
2042
|
-
/* @__PURE__ */ jsx(SpinnerIcon, {}),
|
|
2043
|
-
" Slot held for you \u2014 complete your details to confirm."
|
|
2044
|
-
] }),
|
|
2045
|
-
/* @__PURE__ */ jsxs("form", { onSubmit: handleBookingSubmit, className: "bw-form", children: [
|
|
2046
|
-
/* @__PURE__ */ jsxs("div", { className: "bw-field", children: [
|
|
2047
|
-
/* @__PURE__ */ jsxs("label", { htmlFor: "bw-name", children: [
|
|
2048
|
-
"Name ",
|
|
2049
|
-
/* @__PURE__ */ jsx("span", { className: "bw-req", children: "*" })
|
|
2050
|
-
] }),
|
|
2051
|
-
/* @__PURE__ */ jsx(
|
|
2052
|
-
"input",
|
|
2053
|
-
{
|
|
2054
|
-
id: "bw-name",
|
|
2055
|
-
type: "text",
|
|
2056
|
-
required: true,
|
|
2057
|
-
value: guestInfo.name,
|
|
2058
|
-
onChange: (e) => setGuestInfo((p) => ({ ...p, name: e.target.value })),
|
|
2059
|
-
placeholder: "Jane Smith",
|
|
2060
|
-
autoComplete: "name"
|
|
2061
|
-
}
|
|
2062
|
-
)
|
|
2063
|
-
] }),
|
|
2064
|
-
/* @__PURE__ */ jsxs("div", { className: "bw-field", children: [
|
|
2065
|
-
/* @__PURE__ */ jsxs("label", { htmlFor: "bw-email", children: [
|
|
2066
|
-
"Email ",
|
|
2067
|
-
/* @__PURE__ */ jsx("span", { className: "bw-req", children: "*" })
|
|
2068
|
-
] }),
|
|
2069
|
-
/* @__PURE__ */ jsx(
|
|
2070
|
-
"input",
|
|
2071
|
-
{
|
|
2072
|
-
id: "bw-email",
|
|
2073
|
-
type: "email",
|
|
2074
|
-
required: true,
|
|
2075
|
-
value: guestInfo.email,
|
|
2076
|
-
onChange: (e) => setGuestInfo((p) => ({ ...p, email: e.target.value })),
|
|
2077
|
-
placeholder: "jane@example.com",
|
|
2078
|
-
autoComplete: "email"
|
|
2079
|
-
}
|
|
2080
|
-
)
|
|
2081
|
-
] }),
|
|
2082
|
-
/* @__PURE__ */ jsxs("div", { className: "bw-field", children: [
|
|
2083
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "bw-phone", children: "Phone" }),
|
|
2084
|
-
/* @__PURE__ */ jsx(
|
|
2085
|
-
"input",
|
|
2086
|
-
{
|
|
2087
|
-
id: "bw-phone",
|
|
2088
|
-
type: "tel",
|
|
2089
|
-
value: guestInfo.phone || "",
|
|
2090
|
-
onChange: (e) => setGuestInfo((p) => ({ ...p, phone: e.target.value })),
|
|
2091
|
-
placeholder: "(555) 123-4567",
|
|
2092
|
-
autoComplete: "tel"
|
|
2093
|
-
}
|
|
2094
|
-
)
|
|
2095
|
-
] }),
|
|
2096
|
-
/* @__PURE__ */ jsxs("div", { className: "bw-field", children: [
|
|
2097
|
-
/* @__PURE__ */ jsx("label", { htmlFor: "bw-notes", children: "Notes" }),
|
|
2098
|
-
/* @__PURE__ */ jsx(
|
|
2099
|
-
"textarea",
|
|
2100
|
-
{
|
|
2101
|
-
id: "bw-notes",
|
|
2102
|
-
value: guestInfo.notes || "",
|
|
2103
|
-
onChange: (e) => setGuestInfo((p) => ({ ...p, notes: e.target.value })),
|
|
2104
|
-
placeholder: "Anything you'd like us to know...",
|
|
2105
|
-
rows: 3
|
|
2106
|
-
}
|
|
2107
|
-
)
|
|
2108
|
-
] }),
|
|
2109
|
-
/* @__PURE__ */ jsx("button", { type: "submit", className: "bw-submit", disabled: submitting || !guestInfo.name || !guestInfo.email, children: submitting ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2110
|
-
/* @__PURE__ */ jsx(SpinnerIcon, {}),
|
|
2111
|
-
" Confirming..."
|
|
2112
|
-
] }) : "Confirm Booking" })
|
|
2113
|
-
] })
|
|
2114
|
-
] }),
|
|
2115
|
-
step === "success" && bookingResult && /* @__PURE__ */ jsxs("div", { className: "bw-step bw-fade-in bw-success", children: [
|
|
2116
|
-
/* @__PURE__ */ jsx("div", { className: "bw-success-icon", children: /* @__PURE__ */ jsx(CheckCircleIcon, {}) }),
|
|
2117
|
-
/* @__PURE__ */ jsx("h2", { className: "bw-heading", children: "You\u2019re Booked!" }),
|
|
2118
|
-
/* @__PURE__ */ jsxs("div", { className: "bw-details-card", children: [
|
|
2119
|
-
/* @__PURE__ */ jsxs("div", { className: "bw-detail-row", children: [
|
|
2120
|
-
/* @__PURE__ */ jsx("span", { className: "bw-detail-label", children: "When" }),
|
|
2121
|
-
/* @__PURE__ */ jsxs("span", { className: "bw-detail-value", children: [
|
|
2122
|
-
formatDate2(bookingResult.booking.scheduledAt, timezone),
|
|
2123
|
-
/* @__PURE__ */ jsx("br", {}),
|
|
2124
|
-
formatTime(bookingResult.booking.scheduledAt, timezone),
|
|
2125
|
-
" (",
|
|
2126
|
-
shortTz,
|
|
2127
|
-
")"
|
|
2128
|
-
] })
|
|
2129
|
-
] }),
|
|
2130
|
-
/* @__PURE__ */ jsxs("div", { className: "bw-detail-row", children: [
|
|
2131
|
-
/* @__PURE__ */ jsx("span", { className: "bw-detail-label", children: "Duration" }),
|
|
2132
|
-
/* @__PURE__ */ jsx("span", { className: "bw-detail-value", children: formatDuration(bookingResult.booking.durationMinutes) })
|
|
2133
|
-
] }),
|
|
2134
|
-
bookingResult.booking.hostName && /* @__PURE__ */ jsxs("div", { className: "bw-detail-row", children: [
|
|
2135
|
-
/* @__PURE__ */ jsx("span", { className: "bw-detail-label", children: "With" }),
|
|
2136
|
-
/* @__PURE__ */ jsx("span", { className: "bw-detail-value", children: bookingResult.booking.hostName })
|
|
2137
|
-
] })
|
|
2138
|
-
] }),
|
|
2139
|
-
/* @__PURE__ */ jsx("p", { className: "bw-cal-links-label", children: "Add to your calendar" }),
|
|
2140
|
-
/* @__PURE__ */ jsxs("div", { className: "bw-cal-links", children: [
|
|
2141
|
-
/* @__PURE__ */ jsxs("a", { href: bookingResult.calendarLinks.google, target: "_blank", rel: "noopener noreferrer", className: "bw-cal-link", children: [
|
|
2142
|
-
/* @__PURE__ */ jsx(CalendarPlusIcon, {}),
|
|
2143
|
-
" Google"
|
|
2144
|
-
] }),
|
|
2145
|
-
/* @__PURE__ */ jsxs("a", { href: bookingResult.calendarLinks.outlook, target: "_blank", rel: "noopener noreferrer", className: "bw-cal-link", children: [
|
|
2146
|
-
/* @__PURE__ */ jsx(CalendarPlusIcon, {}),
|
|
2147
|
-
" Outlook"
|
|
2148
|
-
] }),
|
|
2149
|
-
/* @__PURE__ */ jsxs("a", { href: bookingResult.calendarLinks.ics, download: true, className: "bw-cal-link", children: [
|
|
2150
|
-
/* @__PURE__ */ jsx(CalendarPlusIcon, {}),
|
|
2151
|
-
" iCal"
|
|
2152
|
-
] })
|
|
2153
|
-
] }),
|
|
2154
|
-
/* @__PURE__ */ jsxs("p", { className: "bw-email-notice", children: [
|
|
2155
|
-
"If your host uses Google Calendar, a calendar invite will be sent to ",
|
|
2156
|
-
/* @__PURE__ */ jsx("strong", { children: guestInfo.email }),
|
|
2157
|
-
"."
|
|
2158
|
-
] })
|
|
2159
|
-
] }),
|
|
2160
|
-
loading && step === "datetime" && !selectedType && /* @__PURE__ */ jsxs("div", { className: "bw-loading", children: [
|
|
2161
|
-
/* @__PURE__ */ jsx(SpinnerIcon, {}),
|
|
2162
|
-
" Loading..."
|
|
2163
|
-
] }),
|
|
2164
|
-
/* @__PURE__ */ jsx("style", { children: WIDGET_CSS })
|
|
2165
|
-
] });
|
|
2166
|
-
}
|
|
2167
|
-
function TimeButton({
|
|
2168
|
-
slot,
|
|
2169
|
-
selected,
|
|
2170
|
-
confirmed,
|
|
2171
|
-
onClick,
|
|
2172
|
-
onConfirm,
|
|
2173
|
-
timezone,
|
|
2174
|
-
loading
|
|
2175
|
-
}) {
|
|
2176
|
-
if (selected && !confirmed) {
|
|
2177
|
-
return /* @__PURE__ */ jsxs("div", { className: "bw-time-btn-wrap selected", children: [
|
|
2178
|
-
/* @__PURE__ */ jsx("span", { className: "bw-time-text", children: formatTime(slot.start, timezone) }),
|
|
2179
|
-
/* @__PURE__ */ jsx("button", { className: "bw-time-confirm", onClick: onConfirm, disabled: loading, children: loading ? /* @__PURE__ */ jsx(SpinnerIcon, {}) : "Confirm" })
|
|
2180
|
-
] });
|
|
2181
|
-
}
|
|
2182
|
-
return /* @__PURE__ */ jsx("button", { className: `bw-time-btn${selected ? " selected" : ""}`, onClick, disabled: loading, children: formatTime(slot.start, timezone) });
|
|
2183
|
-
}
|
|
2184
|
-
var WIDGET_CSS = `
|
|
2185
|
-
/* \u2500\u2500 Base \u2500\u2500 */
|
|
2186
|
-
.bw-root {
|
|
2187
|
-
font-family: var(--bw-font);
|
|
2188
|
-
color: #1a1a1a;
|
|
2189
|
-
line-height: 1.5;
|
|
2190
|
-
-webkit-font-smoothing: antialiased;
|
|
2191
|
-
box-sizing: border-box;
|
|
2192
|
-
}
|
|
2193
|
-
.bw-root *, .bw-root *::before, .bw-root *::after { box-sizing: border-box; }
|
|
2194
|
-
|
|
2195
|
-
/* \u2500\u2500 Animation \u2500\u2500 */
|
|
2196
|
-
@keyframes bw-fade-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
|
|
2197
|
-
@keyframes bw-spin { to { transform: rotate(360deg); } }
|
|
2198
|
-
.bw-fade-in { animation: bw-fade-in 0.25s ease-out; }
|
|
2199
|
-
.bw-spinner { animation: bw-spin 0.8s linear infinite; }
|
|
2200
|
-
|
|
2201
|
-
/* \u2500\u2500 Error \u2500\u2500 */
|
|
2202
|
-
.bw-error {
|
|
2203
|
-
display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
|
2204
|
-
background: #fef2f2; border: 1px solid #fecaca; color: #b91c1c;
|
|
2205
|
-
padding: 10px 14px; border-radius: var(--bw-radius); margin-bottom: 16px; font-size: 0.875rem;
|
|
2206
|
-
}
|
|
2207
|
-
.bw-error button { background: none; border: none; color: inherit; cursor: pointer; font-size: 1.25rem; line-height: 1; padding: 0; }
|
|
2208
|
-
|
|
2209
|
-
/* \u2500\u2500 Headings \u2500\u2500 */
|
|
2210
|
-
.bw-heading { font-size: 1.125rem; font-weight: 600; margin: 0; letter-spacing: -0.01em; }
|
|
2211
|
-
.bw-meta-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
|
|
2212
|
-
.bw-badge {
|
|
2213
|
-
display: inline-flex; align-items: center; gap: 4px;
|
|
2214
|
-
font-size: 0.8125rem; color: #6b7280; font-weight: 400;
|
|
2215
|
-
}
|
|
2216
|
-
.bw-badge-accent {
|
|
2217
|
-
display: inline-flex; align-items: center; gap: 4px;
|
|
2218
|
-
font-size: 0.8125rem; color: var(--bw-primary); font-weight: 500;
|
|
2219
|
-
}
|
|
2220
|
-
|
|
2221
|
-
/* \u2500\u2500 Info Header \u2500\u2500 */
|
|
2222
|
-
.bw-info-header { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 20px; }
|
|
2223
|
-
.bw-back {
|
|
2224
|
-
display: inline-flex; align-items: center; justify-content: center;
|
|
2225
|
-
width: 32px; height: 32px; border-radius: 50%; border: 1px solid #e5e7eb;
|
|
2226
|
-
background: #fff; cursor: pointer; color: #4b5563; flex-shrink: 0; margin-top: 1px;
|
|
2227
|
-
transition: all 0.15s;
|
|
2228
|
-
}
|
|
2229
|
-
.bw-back:hover { background: #f3f4f6; border-color: #d1d5db; }
|
|
2230
|
-
|
|
2231
|
-
/* \u2500\u2500 Loading \u2500\u2500 */
|
|
2232
|
-
.bw-loading {
|
|
2233
|
-
display: flex; align-items: center; justify-content: center; gap: 8px;
|
|
2234
|
-
padding: 32px; color: #6b7280; font-size: 0.875rem;
|
|
2235
|
-
}
|
|
2236
|
-
|
|
2237
|
-
/* \u2500\u2500 Type Selection \u2500\u2500 */
|
|
2238
|
-
.bw-type-list { display: flex; flex-direction: column; gap: 10px; }
|
|
2239
|
-
.bw-type-card {
|
|
2240
|
-
display: flex; flex-direction: column; text-align: left; gap: 4px;
|
|
2241
|
-
padding: 16px; border: 1.5px solid #e5e7eb; border-radius: var(--bw-radius);
|
|
2242
|
-
background: #fff; cursor: pointer; transition: all 0.15s;
|
|
2243
|
-
}
|
|
2244
|
-
.bw-type-card:hover { border-color: var(--bw-primary); box-shadow: 0 0 0 3px var(--bw-primary-light); }
|
|
2245
|
-
.bw-type-name { font-weight: 600; font-size: 0.9375rem; }
|
|
2246
|
-
.bw-type-desc { color: #6b7280; font-size: 0.8125rem; }
|
|
2247
|
-
.bw-type-meta { display: flex; align-items: center; gap: 4px; font-size: 0.8125rem; color: #9ca3af; margin-top: 4px; }
|
|
2248
|
-
|
|
2249
|
-
/* \u2500\u2500 Date-Time Layout \u2500\u2500 */
|
|
2250
|
-
.bw-datetime-layout {
|
|
2251
|
-
display: flex; gap: 0; border-top: 1px solid #f0f0f0; padding-top: 16px;
|
|
2252
|
-
}
|
|
2253
|
-
@media (max-width: 559px) {
|
|
2254
|
-
.bw-datetime-layout { flex-direction: column; }
|
|
2255
|
-
}
|
|
2256
|
-
@media (min-width: 560px) {
|
|
2257
|
-
.bw-datetime-layout { min-height: 400px; }
|
|
2258
|
-
.bw-calendar { flex: 1 1 auto; padding-right: 16px; border-right: 1px solid #f0f0f0; }
|
|
2259
|
-
.bw-times { width: 180px; flex-shrink: 0; padding-left: 16px; }
|
|
2260
|
-
}
|
|
2261
|
-
|
|
2262
|
-
/* \u2500\u2500 Calendar \u2500\u2500 */
|
|
2263
|
-
.bw-cal-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
|
|
2264
|
-
.bw-cal-title { font-weight: 600; font-size: 0.9375rem; }
|
|
2265
|
-
.bw-cal-nav {
|
|
2266
|
-
display: inline-flex; align-items: center; justify-content: center;
|
|
2267
|
-
width: 32px; height: 32px; border-radius: 50%; border: none;
|
|
2268
|
-
background: transparent; cursor: pointer; color: #374151; transition: background 0.15s;
|
|
2269
|
-
}
|
|
2270
|
-
.bw-cal-nav:hover:not(:disabled) { background: #f3f4f6; }
|
|
2271
|
-
.bw-cal-nav:disabled { opacity: 0.25; cursor: default; }
|
|
2272
|
-
|
|
2273
|
-
.bw-cal-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: 0; text-align: center; margin-bottom: 4px; }
|
|
2274
|
-
.bw-cal-wd { font-size: 0.6875rem; font-weight: 600; color: #9ca3af; text-transform: uppercase; letter-spacing: 0.04em; padding: 4px 0; }
|
|
2275
|
-
|
|
2276
|
-
.bw-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
|
|
2277
|
-
.bw-cal-empty { aspect-ratio: 1; }
|
|
2278
|
-
.bw-cal-day {
|
|
2279
|
-
aspect-ratio: 1; display: flex; align-items: center; justify-content: center;
|
|
2280
|
-
border: none; background: none; border-radius: 50%;
|
|
2281
|
-
font-size: 0.8125rem; font-weight: 500; cursor: pointer;
|
|
2282
|
-
color: #1a1a1a; transition: all 0.15s; position: relative;
|
|
2283
|
-
}
|
|
2284
|
-
.bw-cal-day:hover:not(.disabled):not(.selected) { background: #f3f4f6; }
|
|
2285
|
-
.bw-cal-day.today:not(.selected)::after {
|
|
2286
|
-
content: ''; position: absolute; bottom: 3px; left: 50%; transform: translateX(-50%);
|
|
2287
|
-
width: 4px; height: 4px; border-radius: 50%; background: var(--bw-primary);
|
|
2288
|
-
}
|
|
2289
|
-
.bw-cal-day.selected {
|
|
2290
|
-
background: var(--bw-primary); color: #fff; font-weight: 600;
|
|
2291
|
-
}
|
|
2292
|
-
.bw-cal-day.disabled { color: #d1d5db; cursor: default; }
|
|
2293
|
-
|
|
2294
|
-
/* \u2500\u2500 Time Slots \u2500\u2500 */
|
|
2295
|
-
.bw-times { transition: opacity 0.2s; }
|
|
2296
|
-
.bw-times:not(.visible) { opacity: 0.5; }
|
|
2297
|
-
.bw-times.visible { opacity: 1; }
|
|
2298
|
-
.bw-times-placeholder {
|
|
2299
|
-
display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
|
|
2300
|
-
height: 100%; min-height: 160px; color: #9ca3af; font-size: 0.8125rem; text-align: center; padding: 16px;
|
|
2301
|
-
}
|
|
2302
|
-
.bw-times-empty {
|
|
2303
|
-
display: flex; align-items: center; justify-content: center;
|
|
2304
|
-
height: 100%; min-height: 160px; color: #9ca3af; font-size: 0.8125rem; text-align: center; padding: 16px;
|
|
2305
|
-
}
|
|
2306
|
-
.bw-times-scroll { overflow-y: auto; max-height: 400px; overflow-x: hidden; }
|
|
2307
|
-
.bw-times-date { font-weight: 600; font-size: 0.8125rem; color: #374151; margin: 0 0 12px 0; }
|
|
2308
|
-
.bw-time-group { margin-bottom: 16px; }
|
|
2309
|
-
.bw-times-scroll-hint {
|
|
2310
|
-
font-size: 0.6875rem; color: #9ca3af; text-align: center; margin: 8px 0 0 0; padding-bottom: 8px;
|
|
2311
|
-
}
|
|
2312
|
-
.bw-time-label { display: block; font-size: 0.6875rem; font-weight: 600; color: #9ca3af; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 6px; }
|
|
2313
|
-
|
|
2314
|
-
.bw-time-btn {
|
|
2315
|
-
display: block; width: 100%;
|
|
2316
|
-
padding: 10px 12px; margin-bottom: 6px;
|
|
2317
|
-
border: 1.5px solid #e5e7eb; border-radius: var(--bw-radius);
|
|
2318
|
-
background: #fff; cursor: pointer;
|
|
2319
|
-
font-size: 0.875rem; font-weight: 500; color: var(--bw-primary); text-align: center;
|
|
2320
|
-
transition: all 0.15s;
|
|
2321
|
-
}
|
|
2322
|
-
.bw-time-btn:hover:not(:disabled) {
|
|
2323
|
-
border-color: var(--bw-primary); background: var(--bw-primary-light);
|
|
2324
|
-
}
|
|
2325
|
-
.bw-time-btn.selected {
|
|
2326
|
-
border-color: var(--bw-primary); background: var(--bw-primary); color: #fff;
|
|
2327
|
-
}
|
|
2328
|
-
.bw-time-btn:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
2329
|
-
|
|
2330
|
-
.bw-time-btn-wrap {
|
|
2331
|
-
display: flex; align-items: center; gap: 6px; margin-bottom: 6px;
|
|
2332
|
-
border: 1.5px solid var(--bw-primary); border-radius: var(--bw-radius); overflow: hidden;
|
|
2333
|
-
animation: bw-fade-in 0.15s ease-out;
|
|
2334
|
-
}
|
|
2335
|
-
.bw-time-btn-wrap .bw-time-text {
|
|
2336
|
-
flex: 1; padding: 10px 12px; font-size: 0.875rem; font-weight: 500; color: #374151; text-align: center;
|
|
2337
|
-
background: var(--bw-primary-light);
|
|
2338
|
-
}
|
|
2339
|
-
.bw-time-confirm {
|
|
2340
|
-
display: inline-flex; align-items: center; justify-content: center; gap: 4px;
|
|
2341
|
-
padding: 10px 16px; border: none;
|
|
2342
|
-
background: var(--bw-primary); color: #fff;
|
|
2343
|
-
font-size: 0.8125rem; font-weight: 600; cursor: pointer;
|
|
2344
|
-
transition: background 0.15s;
|
|
2345
|
-
}
|
|
2346
|
-
.bw-time-confirm:hover:not(:disabled) { background: var(--bw-primary-hover); }
|
|
2347
|
-
.bw-time-confirm:disabled { opacity: 0.7; cursor: not-allowed; }
|
|
2348
|
-
|
|
2349
|
-
/* \u2500\u2500 Form \u2500\u2500 */
|
|
2350
|
-
.bw-hold-notice {
|
|
2351
|
-
display: flex; align-items: center; gap: 8px;
|
|
2352
|
-
background: var(--bw-primary-light); color: var(--bw-primary);
|
|
2353
|
-
padding: 10px 14px; border-radius: var(--bw-radius);
|
|
2354
|
-
font-size: 0.8125rem; font-weight: 500; margin-bottom: 20px;
|
|
2355
|
-
}
|
|
2356
|
-
.bw-form { display: flex; flex-direction: column; gap: 16px; }
|
|
2357
|
-
.bw-field label {
|
|
2358
|
-
display: block; font-size: 0.8125rem; font-weight: 500; color: #374151; margin-bottom: 4px;
|
|
2359
|
-
}
|
|
2360
|
-
.bw-req { color: #ef4444; }
|
|
2361
|
-
.bw-field input, .bw-field textarea {
|
|
2362
|
-
display: block; width: 100%;
|
|
2363
|
-
padding: 10px 12px; border: 1.5px solid #e5e7eb; border-radius: var(--bw-radius);
|
|
2364
|
-
font-size: 0.9375rem; font-family: inherit; color: #1a1a1a; background: #fff;
|
|
2365
|
-
transition: border-color 0.15s, box-shadow 0.15s;
|
|
2366
|
-
}
|
|
2367
|
-
.bw-field input::placeholder, .bw-field textarea::placeholder { color: #c0c5cc; }
|
|
2368
|
-
.bw-field input:focus, .bw-field textarea:focus {
|
|
2369
|
-
outline: none; border-color: var(--bw-primary);
|
|
2370
|
-
box-shadow: 0 0 0 3px var(--bw-primary-light);
|
|
2371
|
-
}
|
|
2372
|
-
.bw-submit {
|
|
2373
|
-
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
|
|
2374
|
-
width: 100%; padding: 14px; margin-top: 4px;
|
|
2375
|
-
background: var(--bw-primary); color: #fff; border: none;
|
|
2376
|
-
border-radius: var(--bw-radius); font-size: 0.9375rem; font-weight: 600;
|
|
2377
|
-
cursor: pointer; transition: background 0.15s;
|
|
2378
|
-
}
|
|
2379
|
-
.bw-submit:hover:not(:disabled) { background: var(--bw-primary-hover); }
|
|
2380
|
-
.bw-submit:disabled { opacity: 0.55; cursor: not-allowed; }
|
|
2381
|
-
|
|
2382
|
-
/* \u2500\u2500 Success \u2500\u2500 */
|
|
2383
|
-
.bw-success { text-align: center; }
|
|
2384
|
-
.bw-success-icon { margin: 0 auto 16px; width: 56px; height: 56px; animation: bw-fade-in 0.4s ease-out; }
|
|
2385
|
-
.bw-conf-code {
|
|
2386
|
-
display: inline-block; font-family: 'SF Mono', 'Fira Code', monospace;
|
|
2387
|
-
background: #f3f4f6; padding: 6px 14px; border-radius: 6px;
|
|
2388
|
-
font-size: 0.8125rem; color: #6b7280; margin: 4px 0 20px; letter-spacing: 0.04em;
|
|
2389
|
-
}
|
|
2390
|
-
|
|
2391
|
-
.bw-details-card {
|
|
2392
|
-
text-align: left; background: #f9fafb; border: 1px solid #f0f0f0;
|
|
2393
|
-
border-radius: var(--bw-radius); padding: 16px; margin-bottom: 20px;
|
|
2394
|
-
}
|
|
2395
|
-
.bw-detail-row { display: flex; gap: 12px; padding: 8px 0; border-bottom: 1px solid #f0f0f0; }
|
|
2396
|
-
.bw-detail-row:last-child { border-bottom: none; }
|
|
2397
|
-
.bw-detail-label { width: 70px; flex-shrink: 0; font-size: 0.8125rem; color: #9ca3af; font-weight: 500; }
|
|
2398
|
-
.bw-detail-value { font-size: 0.875rem; font-weight: 500; color: #374151; }
|
|
2399
|
-
|
|
2400
|
-
.bw-cal-links-label { font-size: 0.8125rem; color: #6b7280; margin: 0 0 8px 0; }
|
|
2401
|
-
.bw-cal-links { display: flex; gap: 8px; justify-content: center; margin-bottom: 20px; flex-wrap: wrap; }
|
|
2402
|
-
.bw-cal-link {
|
|
2403
|
-
display: inline-flex; align-items: center; gap: 6px;
|
|
2404
|
-
padding: 8px 14px; border: 1.5px solid #e5e7eb; border-radius: var(--bw-radius);
|
|
2405
|
-
text-decoration: none; color: #374151; font-size: 0.8125rem; font-weight: 500;
|
|
2406
|
-
transition: all 0.15s;
|
|
2407
|
-
}
|
|
2408
|
-
.bw-cal-link:hover { border-color: var(--bw-primary); color: var(--bw-primary); }
|
|
2409
|
-
|
|
2410
|
-
.bw-email-notice { font-size: 0.8125rem; color: #9ca3af; margin: 0; }
|
|
2411
|
-
.bw-email-notice strong { color: #374151; font-weight: 500; }
|
|
2412
|
-
`;
|
|
2413
|
-
|
|
2414
|
-
export { AffiliateCard, AffiliatesWidget, BookingWidget, ExperimentConversion, SetupAssistant, SignalExperiment, SiteKitProvider, createBooking, createSlotHold, detectTimezone, fetchAffiliates, fetchAvailability, fetchAvailableDates, fetchBookingTypeDetails, fetchBookingTypes, formatDate2 as formatBookingDate, formatTime as formatBookingTime, formatDuration, getTrackingUrl, releaseSlotHold, useAffiliates, useExperimentVariant, useSiteKit };
|
|
1500
|
+
export { AffiliateCard, AffiliatesWidget, ExperimentConversion, SetupAssistant, SignalExperiment, SiteKitProvider, fetchAffiliates, getTrackingUrl, useAffiliates, useExperimentVariant, useSiteKit };
|
|
2415
1501
|
//# sourceMappingURL=index.mjs.map
|
|
2416
1502
|
//# sourceMappingURL=index.mjs.map
|