@idkwebsites/components 0.1.8 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -383,8 +383,62 @@ function ServicesList({
383
383
  );
384
384
  }
385
385
 
386
- // src/components/TeamMember.tsx
386
+ // src/lib/linkify.tsx
387
387
  var import_jsx_runtime4 = require("react/jsx-runtime");
388
+ var LINK_REGEX = /((https?:\/\/|www\.)[^\s]+|[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}|(?:[a-z0-9-]+\.)+[a-z]{2,}(?:\/[^\s]*)?)/gi;
389
+ function buildHref(raw) {
390
+ if (raw.includes("@") && !raw.startsWith("http")) {
391
+ return `mailto:${raw}`;
392
+ }
393
+ if (raw.startsWith("http://") || raw.startsWith("https://")) {
394
+ return raw;
395
+ }
396
+ if (raw.startsWith("www.")) {
397
+ return `https://${raw}`;
398
+ }
399
+ return `https://${raw}`;
400
+ }
401
+ function trimTrailingPunctuation(value) {
402
+ let text = value;
403
+ let trailing = "";
404
+ while (text && /[),.!?:;]+$/.test(text)) {
405
+ trailing = text.slice(-1) + trailing;
406
+ text = text.slice(0, -1);
407
+ }
408
+ return { text, trailing };
409
+ }
410
+ function renderLinkedText(text) {
411
+ if (!text) return null;
412
+ const matches = Array.from(text.matchAll(LINK_REGEX));
413
+ if (matches.length === 0) return text;
414
+ const nodes = [];
415
+ let lastIndex = 0;
416
+ matches.forEach((match, index) => {
417
+ const matchText = match[0];
418
+ const start = match.index ?? 0;
419
+ if (start > lastIndex) {
420
+ nodes.push(text.slice(lastIndex, start));
421
+ }
422
+ const { text: cleanText, trailing } = trimTrailingPunctuation(matchText);
423
+ if (cleanText) {
424
+ const href = buildHref(cleanText);
425
+ nodes.push(
426
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", children: cleanText }, `link-${start}-${index}`)
427
+ );
428
+ }
429
+ if (trailing) {
430
+ nodes.push(trailing);
431
+ }
432
+ lastIndex = start + matchText.length;
433
+ });
434
+ if (lastIndex < text.length) {
435
+ nodes.push(text.slice(lastIndex));
436
+ }
437
+ return nodes;
438
+ }
439
+
440
+ // src/components/TeamMember.tsx
441
+ var import_jsx_runtime5 = require("react/jsx-runtime");
388
442
  function TeamMember({
389
443
  member,
390
444
  className,
@@ -395,32 +449,32 @@ function TeamMember({
395
449
  imagePosition = "left"
396
450
  }) {
397
451
  const initials = member.name?.split(" ").map((part) => part[0]).slice(0, 2).join("").toUpperCase();
398
- const avatar = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "idk-team__avatar", children: member.photo?.url ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("img", { src: member.photo.url, alt: member.name }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: initials }) });
452
+ const avatar = /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "idk-team__avatar", children: member.photo?.url ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("img", { src: member.photo.url, alt: member.name }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: initials }) });
399
453
  if (layout === "profile") {
400
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: ["idk-team__profile", className].filter(Boolean).join(" "), children: [
454
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: ["idk-team__profile", className].filter(Boolean).join(" "), children: [
401
455
  imagePosition === "left" ? avatar : null,
402
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "idk-team__info", children: [
403
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { className: "idk-card__title", children: member.name }),
404
- showRole ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "idk-card__description", children: member.role || "Staff" }) : null,
405
- showBio && member.bio ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "idk-team__bio", children: member.bio }) : null,
406
- showEmail ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "idk-card__meta", children: member.email }) : null
456
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "idk-team__info", children: [
457
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { className: "idk-card__title", children: member.name }),
458
+ showRole ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "idk-card__description", children: member.role || "Staff" }) : null,
459
+ showBio && member.bio ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "idk-team__bio", children: renderLinkedText(member.bio) }) : null,
460
+ showEmail ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "idk-card__meta", children: member.email }) : null
407
461
  ] }),
408
462
  imagePosition === "right" ? avatar : null
409
463
  ] });
410
464
  }
411
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: ["idk-card", className].filter(Boolean).join(" "), children: [
412
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "idk-team__avatar", children: member.photo?.url ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("img", { src: member.photo.url, alt: member.name }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: initials }) }),
413
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "idk-team__info", children: [
414
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { className: "idk-card__title", children: member.name }),
415
- showRole ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "idk-card__description", children: member.role || "Staff" }) : null,
416
- showBio && member.bio ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "idk-team__bio", children: member.bio }) : null,
417
- showEmail ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "idk-card__meta", children: member.email }) : null
465
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: ["idk-card", className].filter(Boolean).join(" "), children: [
466
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "idk-team__avatar", children: member.photo?.url ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("img", { src: member.photo.url, alt: member.name }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: initials }) }),
467
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "idk-team__info", children: [
468
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { className: "idk-card__title", children: member.name }),
469
+ showRole ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "idk-card__description", children: member.role || "Staff" }) : null,
470
+ showBio && member.bio ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "idk-team__bio", children: renderLinkedText(member.bio) }) : null,
471
+ showEmail ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "idk-card__meta", children: member.email }) : null
418
472
  ] })
419
473
  ] });
420
474
  }
421
475
 
422
476
  // src/components/TeamGrid.tsx
423
- var import_jsx_runtime5 = require("react/jsx-runtime");
477
+ var import_jsx_runtime6 = require("react/jsx-runtime");
424
478
  function TeamGrid({
425
479
  columns = 3,
426
480
  className,
@@ -438,7 +492,7 @@ function TeamGrid({
438
492
  }) {
439
493
  const { data, isLoading, error } = useTeam(query);
440
494
  if (isLoading) {
441
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "idk-state", children: loadingMessage });
495
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "idk-state", children: loadingMessage });
442
496
  }
443
497
  let members = data?.team ? [...data.team] : [];
444
498
  if (filter) {
@@ -451,15 +505,15 @@ function TeamGrid({
451
505
  members = members.slice(0, Math.max(0, limit));
452
506
  }
453
507
  if (error || members.length === 0) {
454
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "idk-state", children: emptyMessage });
508
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "idk-state", children: emptyMessage });
455
509
  }
456
510
  const gridStyle = { gridTemplateColumns: `repeat(${Math.max(1, columns)}, minmax(0, 1fr))` };
457
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
511
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
458
512
  "div",
459
513
  {
460
514
  className: ["idk-team", className].filter(Boolean).join(" "),
461
515
  style: gridStyle,
462
- children: members.map((member) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
516
+ children: members.map((member) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
463
517
  TeamMember,
464
518
  {
465
519
  member,
@@ -478,7 +532,7 @@ function TeamGrid({
478
532
  // src/components/ContactForm.tsx
479
533
  var import_react6 = require("react");
480
534
  var import_react_query7 = require("@tanstack/react-query");
481
- var import_jsx_runtime6 = require("react/jsx-runtime");
535
+ var import_jsx_runtime7 = require("react/jsx-runtime");
482
536
  var DEFAULT_FIELDS = ["name", "email", "phone", "message"];
483
537
  function ContactForm({
484
538
  fields = DEFAULT_FIELDS,
@@ -524,10 +578,10 @@ function ContactForm({
524
578
  formType
525
579
  });
526
580
  };
527
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("form", { className: ["idk-form", className].filter(Boolean).join(" "), onSubmit: handleSubmit, children: [
528
- fields.includes("name") && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "idk-form__field", children: [
529
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Name" }),
530
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
581
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("form", { className: ["idk-form", className].filter(Boolean).join(" "), onSubmit: handleSubmit, children: [
582
+ fields.includes("name") && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "idk-form__field", children: [
583
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Name" }),
584
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
531
585
  "input",
532
586
  {
533
587
  value: formState.name,
@@ -536,9 +590,9 @@ function ContactForm({
536
590
  }
537
591
  )
538
592
  ] }),
539
- fields.includes("email") && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "idk-form__field", children: [
540
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Email" }),
541
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
593
+ fields.includes("email") && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "idk-form__field", children: [
594
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Email" }),
595
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
542
596
  "input",
543
597
  {
544
598
  type: "email",
@@ -548,9 +602,9 @@ function ContactForm({
548
602
  }
549
603
  )
550
604
  ] }),
551
- fields.includes("phone") && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "idk-form__field", children: [
552
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Phone" }),
553
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
605
+ fields.includes("phone") && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "idk-form__field", children: [
606
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Phone" }),
607
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
554
608
  "input",
555
609
  {
556
610
  value: formState.phone,
@@ -558,9 +612,9 @@ function ContactForm({
558
612
  }
559
613
  )
560
614
  ] }),
561
- fields.includes("subject") && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "idk-form__field", children: [
562
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Subject" }),
563
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
615
+ fields.includes("subject") && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "idk-form__field", children: [
616
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Subject" }),
617
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
564
618
  "input",
565
619
  {
566
620
  value: formState.subject,
@@ -568,9 +622,9 @@ function ContactForm({
568
622
  }
569
623
  )
570
624
  ] }),
571
- fields.includes("message") && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "idk-form__field", children: [
572
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Message" }),
573
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
625
+ fields.includes("message") && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "idk-form__field", children: [
626
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Message" }),
627
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
574
628
  "textarea",
575
629
  {
576
630
  value: formState.message,
@@ -580,15 +634,27 @@ function ContactForm({
580
634
  }
581
635
  )
582
636
  ] }),
583
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "submit", className: "idk-button", disabled: mutation.isPending, children: mutation.isPending ? "Sending..." : submitLabel }),
584
- mutation.isError ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "idk-form__error", children: "Something went wrong. Please try again." }) : null,
585
- mutation.isSuccess ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "idk-form__success", children: "Thanks! We'll be in touch soon." }) : null
637
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "submit", className: "idk-button", disabled: mutation.isPending, children: mutation.isPending ? "Sending..." : submitLabel }),
638
+ mutation.isError ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "idk-form__error", children: "Something went wrong. Please try again." }) : null,
639
+ mutation.isSuccess ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "idk-form__success", children: "Thanks! We'll be in touch soon." }) : null
586
640
  ] });
587
641
  }
588
642
 
589
643
  // src/components/BookingWidget.tsx
590
644
  var import_react7 = require("react");
591
- var import_jsx_runtime7 = require("react/jsx-runtime");
645
+ var import_jsx_runtime8 = require("react/jsx-runtime");
646
+ var parseDateOnly = (value) => {
647
+ if (!value) return null;
648
+ const normalized = value.includes("T") ? value.split("T")[0] : value;
649
+ const parsed = /* @__PURE__ */ new Date(`${normalized}T00:00:00`);
650
+ return Number.isNaN(parsed.getTime()) ? null : parsed;
651
+ };
652
+ var addDays = (dateStr, days) => {
653
+ const parsed = parseDateOnly(dateStr);
654
+ if (!parsed) return dateStr;
655
+ parsed.setDate(parsed.getDate() + days);
656
+ return parsed.toISOString().slice(0, 10);
657
+ };
592
658
  function BookingWidget({
593
659
  className,
594
660
  showStaffSelection = true,
@@ -615,7 +681,16 @@ function BookingWidget({
615
681
  staffLayout = "grid",
616
682
  staffColumns = 2,
617
683
  showAnyStaffOption = true,
618
- timeLayout = "split"
684
+ staffPageSize = 8,
685
+ showStaffPagination,
686
+ timeLayout = "split",
687
+ availabilityDays: availabilityDaysProp = 7,
688
+ enableDatePaging = true,
689
+ datePickerMode = "list",
690
+ calendarVariant = "default",
691
+ maxAdvanceMonths = 3,
692
+ disabledWeekdays = [],
693
+ showFullyBookedLabel = true
619
694
  }) {
620
695
  const resolvedServicesQuery = (0, import_react7.useMemo)(
621
696
  () => services ? { ...servicesQuery, enabled: false } : servicesQuery,
@@ -634,6 +709,17 @@ function BookingWidget({
634
709
  const [serviceSearch, setServiceSearch] = (0, import_react7.useState)("");
635
710
  const [categoryFilter, setCategoryFilter] = (0, import_react7.useState)("all");
636
711
  const [servicePage, setServicePage] = (0, import_react7.useState)(1);
712
+ const [staffPage, setStaffPage] = (0, import_react7.useState)(1);
713
+ const [availabilityDays, setAvailabilityDays] = (0, import_react7.useState)(
714
+ Math.max(1, availabilityDaysProp)
715
+ );
716
+ const [availabilityStartDate, setAvailabilityStartDate] = (0, import_react7.useState)(
717
+ () => (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)
718
+ );
719
+ const [calendarMonth, setCalendarMonth] = (0, import_react7.useState)(() => {
720
+ const now = /* @__PURE__ */ new Date();
721
+ return new Date(now.getFullYear(), now.getMonth(), 1);
722
+ });
637
723
  const [bookingError, setBookingError] = (0, import_react7.useState)(null);
638
724
  const [details, setDetails] = (0, import_react7.useState)({
639
725
  name: "",
@@ -665,6 +751,9 @@ function BookingWidget({
665
751
  (0, import_react7.useEffect)(() => {
666
752
  setServicePage(1);
667
753
  }, [serviceSearch, categoryFilter]);
754
+ (0, import_react7.useEffect)(() => {
755
+ setStaffPage(1);
756
+ }, [selectedService?.id, teamData, teamFilter]);
668
757
  const pagedServices = (0, import_react7.useMemo)(() => {
669
758
  const pageSize = Math.max(1, servicePageSize);
670
759
  return filteredServices.slice(0, pageSize * servicePage);
@@ -680,10 +769,21 @@ function BookingWidget({
680
769
  const teamList = teamData?.team || [];
681
770
  return teamFilter ? teamList.filter(teamFilter) : teamList;
682
771
  }, [selectedService, teamData, teamFilter]);
772
+ const pagedStaff = (0, import_react7.useMemo)(() => {
773
+ const pageSize = Math.max(1, staffPageSize);
774
+ return staffOptions.slice(0, pageSize * staffPage);
775
+ }, [staffOptions, staffPage, staffPageSize]);
776
+ const hasMoreStaff = staffOptions.length > pagedStaff.length;
777
+ const shouldPaginateStaff = showStaffPagination ?? hasMoreStaff;
778
+ const availabilityEndDate = (0, import_react7.useMemo)(
779
+ () => addDays(availabilityStartDate, Math.max(1, availabilityDays) - 1),
780
+ [availabilityStartDate, availabilityDays]
781
+ );
683
782
  const availability = useAvailability({
684
783
  serviceId: selectedService?.id || "",
685
784
  staffId: selectedStaff?.id,
686
- days: 7,
785
+ startDate: availabilityStartDate,
786
+ endDate: availabilityEndDate,
687
787
  enabled: Boolean(selectedService)
688
788
  });
689
789
  const timeZone = availability.data?.timeZone || "America/Chicago";
@@ -753,18 +853,6 @@ function BookingWidget({
753
853
  setSelectedEndTime(null);
754
854
  setBookingError(null);
755
855
  };
756
- (0, import_react7.useEffect)(() => {
757
- if (step !== "time") return;
758
- if (!availability.data?.dates?.length) return;
759
- if (selectedDate) return;
760
- setSelectedDate(availability.data.dates[0].date);
761
- }, [step, availability.data, selectedDate]);
762
- const parseDateOnly = (value) => {
763
- if (!value) return null;
764
- const normalized = value.includes("T") ? value.split("T")[0] : value;
765
- const parsed = /* @__PURE__ */ new Date(`${normalized}T00:00:00`);
766
- return Number.isNaN(parsed.getTime()) ? null : parsed;
767
- };
768
856
  const parseDateTime = (value, fallbackDate) => {
769
857
  if (!value) return null;
770
858
  const direct = new Date(value);
@@ -810,6 +898,156 @@ function BookingWidget({
810
898
  const remaining = minutes % 60;
811
899
  return remaining === 0 ? `${hours} hr${hours > 1 ? "s" : ""}` : `${hours} hr ${remaining} min`;
812
900
  };
901
+ const todayString = (0, import_react7.useMemo)(() => (/* @__PURE__ */ new Date()).toISOString().slice(0, 10), []);
902
+ const todayDate = (0, import_react7.useMemo)(() => {
903
+ const now = /* @__PURE__ */ new Date();
904
+ now.setHours(0, 0, 0, 0);
905
+ return now;
906
+ }, []);
907
+ const disabledWeekdaysSet = (0, import_react7.useMemo)(() => new Set(disabledWeekdays), [disabledWeekdays]);
908
+ const getMonthStart = (0, import_react7.useCallback)((date) => {
909
+ return new Date(date.getFullYear(), date.getMonth(), 1);
910
+ }, []);
911
+ const getMonthEnd = (0, import_react7.useCallback)((date) => {
912
+ return new Date(date.getFullYear(), date.getMonth() + 1, 0);
913
+ }, []);
914
+ const getMonthDays = (0, import_react7.useCallback)(
915
+ (date) => {
916
+ const start = getMonthStart(date);
917
+ const end = getMonthEnd(date);
918
+ const days = [];
919
+ const startDay = start.getDay();
920
+ for (let i = startDay; i > 0; i -= 1) {
921
+ const d = new Date(start);
922
+ d.setDate(start.getDate() - i);
923
+ days.push({ date: d.toISOString().slice(0, 10), isCurrentMonth: false });
924
+ }
925
+ for (let day = 1; day <= end.getDate(); day += 1) {
926
+ const d = new Date(date.getFullYear(), date.getMonth(), day);
927
+ days.push({ date: d.toISOString().slice(0, 10), isCurrentMonth: true });
928
+ }
929
+ const remainder = 7 - (days.length % 7 || 7);
930
+ for (let i = 1; i <= remainder; i += 1) {
931
+ const d = new Date(end);
932
+ d.setDate(end.getDate() + i);
933
+ days.push({ date: d.toISOString().slice(0, 10), isCurrentMonth: false });
934
+ }
935
+ return days;
936
+ },
937
+ [getMonthEnd, getMonthStart]
938
+ );
939
+ const maxAdvanceDate = (0, import_react7.useMemo)(() => {
940
+ if (!maxAdvanceMonths || maxAdvanceMonths <= 0) return null;
941
+ const maxMonth = new Date(todayDate.getFullYear(), todayDate.getMonth() + maxAdvanceMonths - 1, 1);
942
+ return getMonthEnd(maxMonth);
943
+ }, [getMonthEnd, maxAdvanceMonths, todayDate]);
944
+ const maxAdvanceMonthStart = (0, import_react7.useMemo)(() => {
945
+ if (!maxAdvanceMonths || maxAdvanceMonths <= 0) return null;
946
+ return new Date(todayDate.getFullYear(), todayDate.getMonth() + maxAdvanceMonths - 1, 1);
947
+ }, [maxAdvanceMonths, todayDate]);
948
+ const monthOptionCount = (0, import_react7.useMemo)(() => {
949
+ if (!maxAdvanceMonths || maxAdvanceMonths <= 0) return 12;
950
+ return maxAdvanceMonths;
951
+ }, [maxAdvanceMonths]);
952
+ const monthOptions = (0, import_react7.useMemo)(() => {
953
+ return Array.from({ length: monthOptionCount }, (_, index) => {
954
+ const date = new Date(todayDate.getFullYear(), todayDate.getMonth() + index, 1);
955
+ return {
956
+ value: `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}`,
957
+ label: new Intl.DateTimeFormat("en-US", { month: "long", year: "numeric" }).format(date),
958
+ date
959
+ };
960
+ });
961
+ }, [monthOptionCount, todayDate]);
962
+ const calendarDays = (0, import_react7.useMemo)(() => getMonthDays(calendarMonth), [getMonthDays, calendarMonth]);
963
+ const availabilityByDate = (0, import_react7.useMemo)(() => {
964
+ const map = /* @__PURE__ */ new Map();
965
+ (availability.data?.dates || []).forEach((entry) => {
966
+ map.set(entry.date, entry);
967
+ });
968
+ return map;
969
+ }, [availability.data]);
970
+ const hasBlockedInCalendarView = (0, import_react7.useMemo)(() => {
971
+ return calendarDays.some((day) => {
972
+ const entry = availabilityByDate.get(day.date);
973
+ if (!entry) return false;
974
+ return !entry.slots.some((slot) => slot.available);
975
+ });
976
+ }, [calendarDays, availabilityByDate]);
977
+ const handlePrevDates = () => {
978
+ if (availabilityStartDate <= todayString) return;
979
+ setAvailabilityStartDate((prev) => addDays(prev, -availabilityDays));
980
+ setSelectedDate(null);
981
+ setSelectedTime(null);
982
+ setSelectedEndTime(null);
983
+ setBookingError(null);
984
+ };
985
+ const handleNextDates = () => {
986
+ if (maxAdvanceDate) {
987
+ const nextStart = parseDateOnly(addDays(availabilityStartDate, availabilityDays));
988
+ if (nextStart && nextStart > maxAdvanceDate) {
989
+ return;
990
+ }
991
+ }
992
+ setAvailabilityStartDate((prev) => addDays(prev, availabilityDays));
993
+ setSelectedDate(null);
994
+ setSelectedTime(null);
995
+ setSelectedEndTime(null);
996
+ setBookingError(null);
997
+ };
998
+ const handlePrevMonth = () => {
999
+ setCalendarMonth((prev) => new Date(prev.getFullYear(), prev.getMonth() - 1, 1));
1000
+ setSelectedDate(null);
1001
+ setSelectedTime(null);
1002
+ setSelectedEndTime(null);
1003
+ setBookingError(null);
1004
+ };
1005
+ const handleNextMonth = () => {
1006
+ if (maxAdvanceMonthStart) {
1007
+ const nextMonth = new Date(calendarMonth.getFullYear(), calendarMonth.getMonth() + 1, 1);
1008
+ if (nextMonth > maxAdvanceMonthStart) return;
1009
+ }
1010
+ setCalendarMonth((prev) => new Date(prev.getFullYear(), prev.getMonth() + 1, 1));
1011
+ setSelectedDate(null);
1012
+ setSelectedTime(null);
1013
+ setSelectedEndTime(null);
1014
+ setBookingError(null);
1015
+ };
1016
+ const handleMonthSelect = (value) => {
1017
+ const [year, month] = value.split("-").map(Number);
1018
+ if (!year || !month) return;
1019
+ setCalendarMonth(new Date(year, month - 1, 1));
1020
+ setSelectedDate(null);
1021
+ setSelectedTime(null);
1022
+ setSelectedEndTime(null);
1023
+ setBookingError(null);
1024
+ };
1025
+ (0, import_react7.useEffect)(() => {
1026
+ if (step !== "time") return;
1027
+ if (!availability.data?.dates?.length) return;
1028
+ const matches = selectedDate ? availability.data.dates.some((entry) => entry.date === selectedDate) : false;
1029
+ if (matches) return;
1030
+ setSelectedDate(availability.data.dates[0].date);
1031
+ }, [step, availability.data, selectedDate]);
1032
+ (0, import_react7.useEffect)(() => {
1033
+ if (!selectedService) return;
1034
+ if (datePickerMode === "calendar") {
1035
+ const now = /* @__PURE__ */ new Date();
1036
+ setCalendarMonth(new Date(now.getFullYear(), now.getMonth(), 1));
1037
+ return;
1038
+ }
1039
+ setAvailabilityStartDate((/* @__PURE__ */ new Date()).toISOString().slice(0, 10));
1040
+ setAvailabilityDays(Math.max(1, availabilityDaysProp));
1041
+ }, [selectedService?.id, selectedStaff?.id, availabilityDaysProp, datePickerMode]);
1042
+ (0, import_react7.useEffect)(() => {
1043
+ if (datePickerMode !== "calendar") return;
1044
+ const start = getMonthStart(calendarMonth);
1045
+ const end = getMonthEnd(calendarMonth);
1046
+ const startString = start.toISOString().slice(0, 10);
1047
+ const daysInMonth = end.getDate();
1048
+ setAvailabilityStartDate(startString);
1049
+ setAvailabilityDays(daysInMonth);
1050
+ }, [calendarMonth, datePickerMode, getMonthEnd, getMonthStart]);
813
1051
  const handleBack = () => {
814
1052
  if (step === "service") return;
815
1053
  if (step === "staff") {
@@ -879,32 +1117,32 @@ function BookingWidget({
879
1117
  };
880
1118
  const isServicesLoading = services ? false : servicesLoading;
881
1119
  if (isServicesLoading) {
882
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "idk-state", children: "Loading booking options..." });
1120
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-state", children: "Loading booking options..." });
883
1121
  }
884
1122
  if (!servicesList.length) {
885
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "idk-state", children: "No services available." });
1123
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-state", children: "No services available." });
886
1124
  }
887
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1125
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
888
1126
  "div",
889
1127
  {
890
1128
  ref: widgetRef,
891
1129
  className: ["idk-booking", className].filter(Boolean).join(" "),
892
1130
  children: [
893
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "idk-booking__header", children: [
894
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "idk-booking__title-wrap", children: [
895
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h3", { className: "idk-booking__title", children: title }),
896
- subtitle ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "idk-booking__subtitle", children: subtitle }) : null
1131
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-booking__header", children: [
1132
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-booking__title-wrap", children: [
1133
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { className: "idk-booking__title", children: title }),
1134
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "idk-booking__subtitle", children: subtitle }) : null
897
1135
  ] }),
898
- step !== "service" && step !== "done" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "idk-link", onClick: handleBack, children: "Back" }) : null
1136
+ step !== "service" && step !== "done" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", className: "idk-link", onClick: handleBack, children: "Back" }) : null
899
1137
  ] }),
900
- step !== "done" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "idk-booking__progress", children: [
901
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
1138
+ step !== "done" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-booking__progress", children: [
1139
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { children: [
902
1140
  "Step ",
903
1141
  stepNumber,
904
1142
  " of ",
905
1143
  totalSteps
906
1144
  ] }),
907
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "idk-booking__bar", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1145
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-booking__bar", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
908
1146
  "div",
909
1147
  {
910
1148
  className: "idk-booking__bar-fill",
@@ -912,10 +1150,10 @@ function BookingWidget({
912
1150
  }
913
1151
  ) })
914
1152
  ] }) : null,
915
- step === "service" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "idk-booking__step", children: [
916
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h4", { children: "Select a service" }),
917
- enableServiceSearch || enableCategoryFilter ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "idk-booking__filters", children: [
918
- enableServiceSearch ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1153
+ step === "service" && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-booking__step", children: [
1154
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h4", { children: "Select a service" }),
1155
+ enableServiceSearch || enableCategoryFilter ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-booking__filters", children: [
1156
+ enableServiceSearch ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
919
1157
  "input",
920
1158
  {
921
1159
  type: "search",
@@ -924,19 +1162,19 @@ function BookingWidget({
924
1162
  placeholder: serviceSearchPlaceholder
925
1163
  }
926
1164
  ) : null,
927
- enableCategoryFilter && categories.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1165
+ enableCategoryFilter && categories.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
928
1166
  "select",
929
1167
  {
930
1168
  value: categoryFilter,
931
1169
  onChange: (event) => setCategoryFilter(event.target.value),
932
1170
  children: [
933
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "all", children: categoryLabel }),
934
- categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: category, children: category }, category))
1171
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "all", children: categoryLabel }),
1172
+ categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: category, children: category }, category))
935
1173
  ]
936
1174
  }
937
1175
  ) : null
938
1176
  ] }) : null,
939
- filteredServices.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "idk-state", children: "No services match your filters." }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1177
+ filteredServices.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-state", children: "No services match your filters." }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
940
1178
  "div",
941
1179
  {
942
1180
  className: [
@@ -949,7 +1187,7 @@ function BookingWidget({
949
1187
  },
950
1188
  children: pagedServices.map((service) => {
951
1189
  const isSelected = selectedService?.id === service.id;
952
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1190
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
953
1191
  "button",
954
1192
  {
955
1193
  type: "button",
@@ -967,20 +1205,20 @@ function BookingWidget({
967
1205
  }
968
1206
  },
969
1207
  children: [
970
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "idk-card__header", children: [
971
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "idk-card__title", children: service.name }),
972
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "idk-card__aside", children: [
973
- isSelected ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "idk-card__check", children: "\u2713" }) : null,
974
- typeof service.price === "number" && service.price > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "idk-card__price", children: [
1208
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-card__header", children: [
1209
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "idk-card__title", children: service.name }),
1210
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "idk-card__aside", children: [
1211
+ isSelected ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "idk-card__check", children: "\u2713" }) : null,
1212
+ typeof service.price === "number" && service.price > 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "idk-card__price", children: [
975
1213
  "$",
976
1214
  (service.price / 100).toFixed(2)
977
1215
  ] }) : null
978
1216
  ] })
979
1217
  ] }),
980
- service.description ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "idk-card__description", children: service.description }) : null,
981
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "idk-card__meta", children: [
982
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: formatDuration(service.duration) }),
983
- service.category ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "idk-pill", children: service.category }) : null
1218
+ service.description ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-card__description", children: service.description }) : null,
1219
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-card__meta", children: [
1220
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: formatDuration(service.duration) }),
1221
+ service.category ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "idk-pill", children: service.category }) : null
984
1222
  ] })
985
1223
  ]
986
1224
  },
@@ -989,8 +1227,8 @@ function BookingWidget({
989
1227
  })
990
1228
  }
991
1229
  ),
992
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "idk-booking__actions", children: [
993
- shouldPaginate ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1230
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-booking__actions", children: [
1231
+ shouldPaginate ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
994
1232
  "button",
995
1233
  {
996
1234
  type: "button",
@@ -1000,12 +1238,12 @@ function BookingWidget({
1000
1238
  children: hasMoreServices ? "Show more services" : "All services shown"
1001
1239
  }
1002
1240
  ) : null,
1003
- selectedService && !autoAdvanceOnSelect ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "idk-button", onClick: handleServiceContinue, children: "Continue" }) : null
1241
+ selectedService && !autoAdvanceOnSelect ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", className: "idk-button", onClick: handleServiceContinue, children: "Continue" }) : null
1004
1242
  ] })
1005
1243
  ] }),
1006
- step === "staff" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "idk-booking__step", children: [
1007
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h4", { children: "Select a team member" }),
1008
- staffOptions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "idk-state", children: "No team members available." }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1244
+ step === "staff" && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-booking__step", children: [
1245
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h4", { children: "Select a team member" }),
1246
+ staffOptions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-state", children: "No team members available." }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1009
1247
  "div",
1010
1248
  {
1011
1249
  className: [
@@ -1014,7 +1252,7 @@ function BookingWidget({
1014
1252
  ].join(" "),
1015
1253
  style: staffLayout === "grid" ? { gridTemplateColumns: `repeat(${Math.max(1, staffColumns)}, minmax(0, 1fr))` } : void 0,
1016
1254
  children: [
1017
- showAnyStaffOption && canSkipStaff ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1255
+ showAnyStaffOption && canSkipStaff ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1018
1256
  "button",
1019
1257
  {
1020
1258
  type: "button",
@@ -1030,16 +1268,16 @@ function BookingWidget({
1030
1268
  }
1031
1269
  },
1032
1270
  children: [
1033
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "idk-card__header", children: [
1034
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "idk-card__title", children: "Any Available" }),
1035
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "idk-card__badge", children: "Recommended" })
1271
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-card__header", children: [
1272
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "idk-card__title", children: "Any Available" }),
1273
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "idk-card__badge", children: "Recommended" })
1036
1274
  ] }),
1037
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "idk-card__description", children: "We'll match you with the first available stylist." })
1275
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "idk-card__description", children: "We'll match you with the first available stylist." })
1038
1276
  ]
1039
1277
  },
1040
1278
  "any-staff"
1041
1279
  ) : null,
1042
- staffOptions.map((staff) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1280
+ pagedStaff.map((staff) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1043
1281
  "button",
1044
1282
  {
1045
1283
  type: "button",
@@ -1055,12 +1293,12 @@ function BookingWidget({
1055
1293
  scrollToTop();
1056
1294
  }
1057
1295
  },
1058
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "idk-team__card", children: [
1059
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "idk-team__avatar", children: staff.photo?.url ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { src: staff.photo.url, alt: staff.name }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: staff.name.split(" ").map((part) => part[0]).slice(0, 2).join("").toUpperCase() }) }),
1060
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
1061
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "idk-card__title", children: staff.name }),
1062
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "idk-card__meta", children: staff.role || "Staff" }),
1063
- staff.bio ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "idk-card__description", children: staff.bio }) : null
1296
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-team__card", children: [
1297
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-team__avatar", children: staff.photo?.url ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("img", { src: staff.photo.url, alt: staff.name }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: staff.name.split(" ").map((part) => part[0]).slice(0, 2).join("").toUpperCase() }) }),
1298
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
1299
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "idk-card__title", children: staff.name }),
1300
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "idk-card__meta", children: staff.role || "Staff" }),
1301
+ staff.bio ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "idk-card__description", children: renderLinkedText(staff.bio) }) : null
1064
1302
  ] })
1065
1303
  ] })
1066
1304
  },
@@ -1069,8 +1307,18 @@ function BookingWidget({
1069
1307
  ]
1070
1308
  }
1071
1309
  ),
1072
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "idk-booking__actions", children: [
1073
- canSkipStaff ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1310
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-booking__actions", children: [
1311
+ shouldPaginateStaff ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1312
+ "button",
1313
+ {
1314
+ type: "button",
1315
+ className: "idk-button idk-button--ghost",
1316
+ onClick: () => setStaffPage((prev) => hasMoreStaff ? prev + 1 : 1),
1317
+ disabled: !hasMoreStaff && staffPage === 1,
1318
+ children: hasMoreStaff ? "Show more staff" : staffPage > 1 ? "Show fewer staff" : "All staff shown"
1319
+ }
1320
+ ) : null,
1321
+ canSkipStaff ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1074
1322
  "button",
1075
1323
  {
1076
1324
  type: "button",
@@ -1083,7 +1331,7 @@ function BookingWidget({
1083
1331
  children: "Continue without selecting"
1084
1332
  }
1085
1333
  ) : null,
1086
- !autoAdvanceOnSelect ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1334
+ !autoAdvanceOnSelect ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1087
1335
  "button",
1088
1336
  {
1089
1337
  type: "button",
@@ -1095,37 +1343,171 @@ function BookingWidget({
1095
1343
  ) : null
1096
1344
  ] })
1097
1345
  ] }),
1098
- step === "time" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "idk-booking__step", children: [
1099
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h4", { children: "Select a time" }),
1100
- availability.isLoading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "idk-state", children: "Loading availability..." }) : availability.data ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: ["idk-availability", timeLayout === "split" ? "idk-availability--split" : ""].join(" "), children: [
1101
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "idk-availability__dates", children: availability.data.dates.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1102
- "button",
1346
+ step === "time" && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-booking__step", children: [
1347
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h4", { children: "Select a time" }),
1348
+ availability.isLoading ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-state", children: "Loading availability..." }) : availability.data ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: ["idk-availability", timeLayout === "split" ? "idk-availability--split" : ""].join(" "), children: [
1349
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-availability__dates", children: datePickerMode === "calendar" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1350
+ "div",
1103
1351
  {
1104
- type: "button",
1105
- className: entry.date === selectedDate ? "is-active" : void 0,
1106
- onClick: () => {
1107
- setSelectedDate(entry.date);
1108
- setSelectedTime(null);
1109
- setSelectedEndTime(null);
1110
- setBookingError(null);
1352
+ className: [
1353
+ "idk-calendar",
1354
+ calendarVariant === "compact" ? "idk-calendar--compact" : ""
1355
+ ].filter(Boolean).join(" "),
1356
+ children: [
1357
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-calendar__header", children: calendarVariant === "compact" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-calendar__header idk-calendar__header--compact", children: [
1358
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1359
+ "button",
1360
+ {
1361
+ type: "button",
1362
+ className: "idk-calendar__nav-btn",
1363
+ onClick: handlePrevMonth,
1364
+ disabled: calendarMonth <= getMonthStart(todayDate),
1365
+ "aria-label": "Previous month",
1366
+ children: "<"
1367
+ }
1368
+ ),
1369
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1370
+ "select",
1371
+ {
1372
+ className: "idk-calendar__month-select",
1373
+ value: `${calendarMonth.getFullYear()}-${String(calendarMonth.getMonth() + 1).padStart(2, "0")}`,
1374
+ onChange: (event) => handleMonthSelect(event.target.value),
1375
+ children: monthOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: option.value, children: option.label }, option.value))
1376
+ }
1377
+ ),
1378
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1379
+ "button",
1380
+ {
1381
+ type: "button",
1382
+ className: "idk-calendar__nav-btn",
1383
+ onClick: handleNextMonth,
1384
+ disabled: Boolean(maxAdvanceMonthStart && calendarMonth >= maxAdvanceMonthStart),
1385
+ "aria-label": "Next month",
1386
+ children: ">"
1387
+ }
1388
+ )
1389
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
1390
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1391
+ "button",
1392
+ {
1393
+ type: "button",
1394
+ className: "idk-button idk-button--ghost",
1395
+ onClick: handlePrevMonth,
1396
+ disabled: calendarMonth <= getMonthStart(todayDate),
1397
+ children: "Prev"
1398
+ }
1399
+ ),
1400
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-calendar__title", children: new Intl.DateTimeFormat("en-US", {
1401
+ month: "long",
1402
+ year: "numeric"
1403
+ }).format(calendarMonth) }),
1404
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1405
+ "button",
1406
+ {
1407
+ type: "button",
1408
+ className: "idk-button idk-button--ghost",
1409
+ onClick: handleNextMonth,
1410
+ disabled: Boolean(maxAdvanceMonthStart && calendarMonth >= maxAdvanceMonthStart),
1411
+ children: "Next"
1412
+ }
1413
+ )
1414
+ ] }) }),
1415
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-calendar__weekdays", children: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].map((label) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: label }, label)) }),
1416
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-calendar__grid", children: calendarDays.map((day) => {
1417
+ const entry = availabilityByDate.get(day.date);
1418
+ const hasAvailable = entry?.slots?.some((slot) => slot.available) ?? false;
1419
+ const dateValue = parseDateOnly(day.date);
1420
+ const isPast = dateValue ? dateValue < todayDate : false;
1421
+ const isBeyondMax = maxAdvanceDate ? dateValue ? dateValue > maxAdvanceDate : false : false;
1422
+ const weekday = dateValue ? dateValue.getDay() : null;
1423
+ const isDisabledWeekday = weekday !== null ? disabledWeekdaysSet.has(weekday) : false;
1424
+ const isBlocked = Boolean(entry) && !hasAvailable;
1425
+ const isDisabled = !entry || isPast || isBeyondMax || isBlocked || isDisabledWeekday;
1426
+ const isActive = selectedDate === day.date;
1427
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1428
+ "button",
1429
+ {
1430
+ type: "button",
1431
+ className: [
1432
+ "idk-calendar__day",
1433
+ day.isCurrentMonth ? "" : "is-muted",
1434
+ hasAvailable ? "is-available" : "",
1435
+ isBlocked ? "is-blocked" : "",
1436
+ isDisabledWeekday ? "is-disabled" : "",
1437
+ isActive ? "is-active" : ""
1438
+ ].filter(Boolean).join(" "),
1439
+ disabled: isDisabled,
1440
+ onClick: () => {
1441
+ setSelectedDate(day.date);
1442
+ setSelectedTime(null);
1443
+ setSelectedEndTime(null);
1444
+ setBookingError(null);
1445
+ },
1446
+ children: [
1447
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: day.date.split("-")[2] }),
1448
+ showFullyBookedLabel && isBlocked && day.isCurrentMonth ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "idk-calendar__label", children: calendarVariant === "compact" ? "\u2022" : "Fully booked" }) : null
1449
+ ]
1450
+ },
1451
+ day.date
1452
+ );
1453
+ }) }),
1454
+ showFullyBookedLabel && calendarVariant === "compact" && hasBlockedInCalendarView ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-calendar__legend", children: [
1455
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "idk-calendar__legend-dot", children: "\u2022" }),
1456
+ " Fully booked"
1457
+ ] }) : null
1458
+ ]
1459
+ }
1460
+ ) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
1461
+ enableDatePaging ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-availability__nav", children: [
1462
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1463
+ "button",
1464
+ {
1465
+ type: "button",
1466
+ className: "idk-button idk-button--ghost",
1467
+ onClick: handlePrevDates,
1468
+ disabled: availabilityStartDate <= todayString,
1469
+ children: "Previous"
1470
+ }
1471
+ ),
1472
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1473
+ "button",
1474
+ {
1475
+ type: "button",
1476
+ className: "idk-button idk-button--ghost",
1477
+ onClick: handleNextDates,
1478
+ children: "Next"
1479
+ }
1480
+ )
1481
+ ] }) : null,
1482
+ availability.data.dates.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1483
+ "button",
1484
+ {
1485
+ type: "button",
1486
+ className: entry.date === selectedDate ? "is-active" : void 0,
1487
+ onClick: () => {
1488
+ setSelectedDate(entry.date);
1489
+ setSelectedTime(null);
1490
+ setSelectedEndTime(null);
1491
+ setBookingError(null);
1492
+ },
1493
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "idk-date-chip__day", children: formatDateLabel(entry.date) })
1111
1494
  },
1112
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "idk-date-chip__day", children: formatDateLabel(entry.date) })
1113
- },
1114
- entry.date
1115
- )) }),
1116
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "idk-availability__panel", children: [
1117
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "idk-availability__panel-header", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
1118
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "idk-availability__panel-title", children: selectedDate ? formatDateHeading(selectedDate) : availability.data.dates[0]?.date ? formatDateHeading(availability.data.dates[0].date) : "Select a date" }),
1119
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "idk-availability__panel-subtitle", children: timeZoneLabel })
1495
+ entry.date
1496
+ ))
1497
+ ] }) }),
1498
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-availability__panel", children: [
1499
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-availability__panel-header", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
1500
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-availability__panel-title", children: selectedDate ? formatDateHeading(selectedDate) : availability.data.dates[0]?.date ? formatDateHeading(availability.data.dates[0].date) : "Select a date" }),
1501
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-availability__panel-subtitle", children: timeZoneLabel })
1120
1502
  ] }) }),
1121
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "idk-availability__slots", children: (() => {
1122
- const activeEntry = availability.data.dates.find((entry) => entry.date === selectedDate) || availability.data.dates[0];
1123
- if (!activeEntry) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "idk-state", children: "Select a date to see times." });
1503
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-availability__slots", children: (() => {
1504
+ const activeEntry = selectedDate ? availability.data.dates.find((entry) => entry.date === selectedDate) : availability.data.dates[0];
1505
+ if (!activeEntry) return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-state", children: "Select a date to see times." });
1124
1506
  const slots = (activeEntry.slots || []).filter((slot) => slot.available);
1125
1507
  if (slots.length === 0) {
1126
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "idk-state", children: "No available times for this date." });
1508
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-state", children: "No available times for this date." });
1127
1509
  }
1128
- return slots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1510
+ return slots.map((slot, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1129
1511
  "button",
1130
1512
  {
1131
1513
  type: "button",
@@ -1143,12 +1525,12 @@ function BookingWidget({
1143
1525
  },
1144
1526
  children: formatTimeLabel(slot.time)
1145
1527
  },
1146
- `${slot.time}-${slot.endTime}`
1528
+ `${activeEntry.date}-${slot.time}-${slot.endTime}-${index}`
1147
1529
  ));
1148
1530
  })() })
1149
1531
  ] })
1150
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "idk-state", children: "No availability found." }),
1151
- !autoAdvanceOnSelect ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "idk-booking__actions", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1532
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-state", children: "No availability found." }),
1533
+ !autoAdvanceOnSelect ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-booking__actions", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1152
1534
  "button",
1153
1535
  {
1154
1536
  type: "button",
@@ -1159,37 +1541,37 @@ function BookingWidget({
1159
1541
  }
1160
1542
  ) }) : null
1161
1543
  ] }),
1162
- step === "details" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("form", { className: "idk-form", onSubmit: handleSubmit, children: [
1163
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h4", { children: "Your details" }),
1164
- bookingError ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "idk-booking__error", children: bookingError }) : null,
1165
- selectedService && selectedTime ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "idk-booking__summary", children: [
1166
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
1167
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "idk-booking__summary-label", children: "Service" }),
1168
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { children: selectedService.name })
1544
+ step === "details" && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("form", { className: "idk-form", onSubmit: handleSubmit, children: [
1545
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h4", { children: "Your details" }),
1546
+ bookingError ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-booking__error", children: bookingError }) : null,
1547
+ selectedService && selectedTime ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-booking__summary", children: [
1548
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
1549
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "idk-booking__summary-label", children: "Service" }),
1550
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { children: selectedService.name })
1169
1551
  ] }),
1170
- selectedStaff ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
1171
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "idk-booking__summary-label", children: "Staff" }),
1172
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { children: selectedStaff.name })
1552
+ selectedStaff ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
1553
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "idk-booking__summary-label", children: "Staff" }),
1554
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { children: selectedStaff.name })
1173
1555
  ] }) : null,
1174
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
1175
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "idk-booking__summary-label", children: "When" }),
1176
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { children: [
1556
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
1557
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "idk-booking__summary-label", children: "When" }),
1558
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("p", { children: [
1177
1559
  formatDateHeading(selectedDate || ""),
1178
1560
  " \xB7 ",
1179
1561
  formatTimeLabel(selectedTime)
1180
1562
  ] })
1181
1563
  ] }),
1182
- selectedService.price ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
1183
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "idk-booking__summary-label", children: "Price" }),
1184
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { children: [
1564
+ selectedService.price ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
1565
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "idk-booking__summary-label", children: "Price" }),
1566
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("p", { children: [
1185
1567
  "$",
1186
1568
  (selectedService.price / 100).toFixed(2)
1187
1569
  ] })
1188
1570
  ] }) : null
1189
1571
  ] }) : null,
1190
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "idk-form__field", children: [
1191
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Name" }),
1192
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1572
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "idk-form__field", children: [
1573
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Name" }),
1574
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1193
1575
  "input",
1194
1576
  {
1195
1577
  value: details.name,
@@ -1198,9 +1580,9 @@ function BookingWidget({
1198
1580
  }
1199
1581
  )
1200
1582
  ] }),
1201
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "idk-form__field", children: [
1202
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Email" }),
1203
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1583
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "idk-form__field", children: [
1584
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Email" }),
1585
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1204
1586
  "input",
1205
1587
  {
1206
1588
  type: "email",
@@ -1210,9 +1592,9 @@ function BookingWidget({
1210
1592
  }
1211
1593
  )
1212
1594
  ] }),
1213
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "idk-form__field", children: [
1214
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Phone" }),
1215
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1595
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "idk-form__field", children: [
1596
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Phone" }),
1597
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1216
1598
  "input",
1217
1599
  {
1218
1600
  value: details.phone,
@@ -1220,9 +1602,9 @@ function BookingWidget({
1220
1602
  }
1221
1603
  )
1222
1604
  ] }),
1223
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "idk-form__field", children: [
1224
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Notes" }),
1225
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1605
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "idk-form__field", children: [
1606
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Notes" }),
1607
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1226
1608
  "textarea",
1227
1609
  {
1228
1610
  rows: 4,
@@ -1231,12 +1613,12 @@ function BookingWidget({
1231
1613
  }
1232
1614
  )
1233
1615
  ] }),
1234
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "submit", className: "idk-button", disabled: createBooking.isPending, children: createBooking.isPending ? "Booking..." : "Confirm booking" })
1616
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "submit", className: "idk-button", disabled: createBooking.isPending, children: createBooking.isPending ? "Booking..." : "Confirm booking" })
1235
1617
  ] }),
1236
- step === "done" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "idk-booking__done", children: [
1237
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "idk-booking__done-title", children: "Booking confirmed!" }),
1238
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "idk-booking__done-text", children: "We'll send a confirmation email shortly with your appointment details." }),
1239
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1618
+ step === "done" && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-booking__done", children: [
1619
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-booking__done-title", children: "Booking confirmed!" }),
1620
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "idk-booking__done-text", children: "We'll send a confirmation email shortly with your appointment details." }),
1621
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1240
1622
  "button",
1241
1623
  {
1242
1624
  type: "button",
@@ -1259,7 +1641,7 @@ function BookingWidget({
1259
1641
 
1260
1642
  // src/components/AvailabilityPicker.tsx
1261
1643
  var import_react8 = require("react");
1262
- var import_jsx_runtime8 = require("react/jsx-runtime");
1644
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1263
1645
  function AvailabilityPicker({
1264
1646
  serviceId,
1265
1647
  staffId,
@@ -1277,15 +1659,15 @@ function AvailabilityPicker({
1277
1659
  days
1278
1660
  });
1279
1661
  if (isLoading) {
1280
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-state", children: "Loading availability..." });
1662
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "idk-state", children: "Loading availability..." });
1281
1663
  }
1282
1664
  if (!data?.dates?.length) {
1283
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-state", children: "No availability found." });
1665
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "idk-state", children: "No availability found." });
1284
1666
  }
1285
1667
  const activeDate = selectedDate || data.dates[0]?.date;
1286
1668
  const activeSlots = data.dates.find((entry) => entry.date === activeDate)?.slots || [];
1287
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: ["idk-availability", className].filter(Boolean).join(" "), children: [
1288
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-availability__dates", children: data.dates.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1669
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: ["idk-availability", className].filter(Boolean).join(" "), children: [
1670
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "idk-availability__dates", children: data.dates.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1289
1671
  "button",
1290
1672
  {
1291
1673
  type: "button",
@@ -1298,7 +1680,7 @@ function AvailabilityPicker({
1298
1680
  },
1299
1681
  entry.date
1300
1682
  )) }),
1301
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-availability__slots", children: activeSlots.filter((slot) => slot.available).length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-state", children: "No slots available." }) : activeSlots.filter((slot) => slot.available).map((slot) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1683
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "idk-availability__slots", children: activeSlots.filter((slot) => slot.available).length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "idk-state", children: "No slots available." }) : activeSlots.filter((slot) => slot.available).map((slot) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1302
1684
  "button",
1303
1685
  {
1304
1686
  type: "button",
@@ -1321,22 +1703,22 @@ function AvailabilityPicker({
1321
1703
  }
1322
1704
 
1323
1705
  // src/components/ServicePicker.tsx
1324
- var import_jsx_runtime9 = require("react/jsx-runtime");
1706
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1325
1707
  function ServicePicker({
1326
1708
  services,
1327
1709
  selectedId,
1328
1710
  onSelect,
1329
1711
  className
1330
1712
  }) {
1331
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: ["idk-picker", className].filter(Boolean).join(" "), children: services.map((service) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1713
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: ["idk-picker", className].filter(Boolean).join(" "), children: services.map((service) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1332
1714
  "button",
1333
1715
  {
1334
1716
  type: "button",
1335
1717
  className: selectedId === service.id ? "is-active" : void 0,
1336
1718
  onClick: () => onSelect?.(service),
1337
1719
  children: [
1338
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: service.name }),
1339
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("small", { children: [
1720
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: service.name }),
1721
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("small", { children: [
1340
1722
  service.duration,
1341
1723
  " min"
1342
1724
  ] })
@@ -1347,22 +1729,22 @@ function ServicePicker({
1347
1729
  }
1348
1730
 
1349
1731
  // src/components/StaffPicker.tsx
1350
- var import_jsx_runtime10 = require("react/jsx-runtime");
1732
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1351
1733
  function StaffPicker({
1352
1734
  staff,
1353
1735
  selectedId,
1354
1736
  onSelect,
1355
1737
  className
1356
1738
  }) {
1357
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: ["idk-picker", className].filter(Boolean).join(" "), children: staff.map((member) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1739
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: ["idk-picker", className].filter(Boolean).join(" "), children: staff.map((member) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1358
1740
  "button",
1359
1741
  {
1360
1742
  type: "button",
1361
1743
  className: selectedId === member.id ? "is-active" : void 0,
1362
1744
  onClick: () => onSelect?.(member),
1363
1745
  children: [
1364
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: member.name }),
1365
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("small", { children: member.role || "Staff" })
1746
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: member.name }),
1747
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("small", { children: member.role || "Staff" })
1366
1748
  ]
1367
1749
  },
1368
1750
  member.id
@@ -1370,14 +1752,14 @@ function StaffPicker({
1370
1752
  }
1371
1753
 
1372
1754
  // src/components/DatePicker.tsx
1373
- var import_jsx_runtime11 = require("react/jsx-runtime");
1755
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1374
1756
  function DatePicker({
1375
1757
  dates,
1376
1758
  selectedDate,
1377
1759
  onSelect,
1378
1760
  className
1379
1761
  }) {
1380
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: ["idk-picker", className].filter(Boolean).join(" "), children: dates.map((date) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1762
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: ["idk-picker", className].filter(Boolean).join(" "), children: dates.map((date) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1381
1763
  "button",
1382
1764
  {
1383
1765
  type: "button",
@@ -1390,14 +1772,14 @@ function DatePicker({
1390
1772
  }
1391
1773
 
1392
1774
  // src/components/TimePicker.tsx
1393
- var import_jsx_runtime12 = require("react/jsx-runtime");
1775
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1394
1776
  function TimePicker({
1395
1777
  slots,
1396
1778
  selectedTime,
1397
1779
  onSelect,
1398
1780
  className
1399
1781
  }) {
1400
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: ["idk-picker", className].filter(Boolean).join(" "), children: slots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1782
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: ["idk-picker", className].filter(Boolean).join(" "), children: slots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1401
1783
  "button",
1402
1784
  {
1403
1785
  type: "button",