@idkwebsites/components 0.1.8 → 0.1.14

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.js CHANGED
@@ -344,8 +344,62 @@ function ServicesList({
344
344
  );
345
345
  }
346
346
 
347
+ // src/lib/linkify.tsx
348
+ import { jsx as jsx4 } from "react/jsx-runtime";
349
+ var LINK_REGEX = /((https?:\/\/|www\.)[^\s]+|[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}|(?:[a-z0-9-]+\.)+[a-z]{2,}(?:\/[^\s]*)?)/gi;
350
+ function buildHref(raw) {
351
+ if (raw.includes("@") && !raw.startsWith("http")) {
352
+ return `mailto:${raw}`;
353
+ }
354
+ if (raw.startsWith("http://") || raw.startsWith("https://")) {
355
+ return raw;
356
+ }
357
+ if (raw.startsWith("www.")) {
358
+ return `https://${raw}`;
359
+ }
360
+ return `https://${raw}`;
361
+ }
362
+ function trimTrailingPunctuation(value) {
363
+ let text = value;
364
+ let trailing = "";
365
+ while (text && /[),.!?:;]+$/.test(text)) {
366
+ trailing = text.slice(-1) + trailing;
367
+ text = text.slice(0, -1);
368
+ }
369
+ return { text, trailing };
370
+ }
371
+ function renderLinkedText(text) {
372
+ if (!text) return null;
373
+ const matches = Array.from(text.matchAll(LINK_REGEX));
374
+ if (matches.length === 0) return text;
375
+ const nodes = [];
376
+ let lastIndex = 0;
377
+ matches.forEach((match, index) => {
378
+ const matchText = match[0];
379
+ const start = match.index ?? 0;
380
+ if (start > lastIndex) {
381
+ nodes.push(text.slice(lastIndex, start));
382
+ }
383
+ const { text: cleanText, trailing } = trimTrailingPunctuation(matchText);
384
+ if (cleanText) {
385
+ const href = buildHref(cleanText);
386
+ nodes.push(
387
+ /* @__PURE__ */ jsx4("a", { href, target: "_blank", rel: "noopener noreferrer", children: cleanText }, `link-${start}-${index}`)
388
+ );
389
+ }
390
+ if (trailing) {
391
+ nodes.push(trailing);
392
+ }
393
+ lastIndex = start + matchText.length;
394
+ });
395
+ if (lastIndex < text.length) {
396
+ nodes.push(text.slice(lastIndex));
397
+ }
398
+ return nodes;
399
+ }
400
+
347
401
  // src/components/TeamMember.tsx
348
- import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
402
+ import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
349
403
  function TeamMember({
350
404
  member,
351
405
  className,
@@ -356,32 +410,32 @@ function TeamMember({
356
410
  imagePosition = "left"
357
411
  }) {
358
412
  const initials = member.name?.split(" ").map((part) => part[0]).slice(0, 2).join("").toUpperCase();
359
- const avatar = /* @__PURE__ */ jsx4("div", { className: "idk-team__avatar", children: member.photo?.url ? /* @__PURE__ */ jsx4("img", { src: member.photo.url, alt: member.name }) : /* @__PURE__ */ jsx4("span", { children: initials }) });
413
+ const avatar = /* @__PURE__ */ jsx5("div", { className: "idk-team__avatar", children: member.photo?.url ? /* @__PURE__ */ jsx5("img", { src: member.photo.url, alt: member.name }) : /* @__PURE__ */ jsx5("span", { children: initials }) });
360
414
  if (layout === "profile") {
361
415
  return /* @__PURE__ */ jsxs2("div", { className: ["idk-team__profile", className].filter(Boolean).join(" "), children: [
362
416
  imagePosition === "left" ? avatar : null,
363
417
  /* @__PURE__ */ jsxs2("div", { className: "idk-team__info", children: [
364
- /* @__PURE__ */ jsx4("h3", { className: "idk-card__title", children: member.name }),
365
- showRole ? /* @__PURE__ */ jsx4("p", { className: "idk-card__description", children: member.role || "Staff" }) : null,
366
- showBio && member.bio ? /* @__PURE__ */ jsx4("p", { className: "idk-team__bio", children: member.bio }) : null,
367
- showEmail ? /* @__PURE__ */ jsx4("p", { className: "idk-card__meta", children: member.email }) : null
418
+ /* @__PURE__ */ jsx5("h3", { className: "idk-card__title", children: member.name }),
419
+ showRole ? /* @__PURE__ */ jsx5("p", { className: "idk-card__description", children: member.role || "Staff" }) : null,
420
+ showBio && member.bio ? /* @__PURE__ */ jsx5("p", { className: "idk-team__bio", children: renderLinkedText(member.bio) }) : null,
421
+ showEmail ? /* @__PURE__ */ jsx5("p", { className: "idk-card__meta", children: member.email }) : null
368
422
  ] }),
369
423
  imagePosition === "right" ? avatar : null
370
424
  ] });
371
425
  }
372
426
  return /* @__PURE__ */ jsxs2("div", { className: ["idk-card", className].filter(Boolean).join(" "), children: [
373
- /* @__PURE__ */ jsx4("div", { className: "idk-team__avatar", children: member.photo?.url ? /* @__PURE__ */ jsx4("img", { src: member.photo.url, alt: member.name }) : /* @__PURE__ */ jsx4("span", { children: initials }) }),
427
+ /* @__PURE__ */ jsx5("div", { className: "idk-team__avatar", children: member.photo?.url ? /* @__PURE__ */ jsx5("img", { src: member.photo.url, alt: member.name }) : /* @__PURE__ */ jsx5("span", { children: initials }) }),
374
428
  /* @__PURE__ */ jsxs2("div", { className: "idk-team__info", children: [
375
- /* @__PURE__ */ jsx4("h3", { className: "idk-card__title", children: member.name }),
376
- showRole ? /* @__PURE__ */ jsx4("p", { className: "idk-card__description", children: member.role || "Staff" }) : null,
377
- showBio && member.bio ? /* @__PURE__ */ jsx4("p", { className: "idk-team__bio", children: member.bio }) : null,
378
- showEmail ? /* @__PURE__ */ jsx4("p", { className: "idk-card__meta", children: member.email }) : null
429
+ /* @__PURE__ */ jsx5("h3", { className: "idk-card__title", children: member.name }),
430
+ showRole ? /* @__PURE__ */ jsx5("p", { className: "idk-card__description", children: member.role || "Staff" }) : null,
431
+ showBio && member.bio ? /* @__PURE__ */ jsx5("p", { className: "idk-team__bio", children: renderLinkedText(member.bio) }) : null,
432
+ showEmail ? /* @__PURE__ */ jsx5("p", { className: "idk-card__meta", children: member.email }) : null
379
433
  ] })
380
434
  ] });
381
435
  }
382
436
 
383
437
  // src/components/TeamGrid.tsx
384
- import { jsx as jsx5 } from "react/jsx-runtime";
438
+ import { jsx as jsx6 } from "react/jsx-runtime";
385
439
  function TeamGrid({
386
440
  columns = 3,
387
441
  className,
@@ -399,7 +453,7 @@ function TeamGrid({
399
453
  }) {
400
454
  const { data, isLoading, error } = useTeam(query);
401
455
  if (isLoading) {
402
- return /* @__PURE__ */ jsx5("div", { className: "idk-state", children: loadingMessage });
456
+ return /* @__PURE__ */ jsx6("div", { className: "idk-state", children: loadingMessage });
403
457
  }
404
458
  let members = data?.team ? [...data.team] : [];
405
459
  if (filter) {
@@ -412,15 +466,15 @@ function TeamGrid({
412
466
  members = members.slice(0, Math.max(0, limit));
413
467
  }
414
468
  if (error || members.length === 0) {
415
- return /* @__PURE__ */ jsx5("div", { className: "idk-state", children: emptyMessage });
469
+ return /* @__PURE__ */ jsx6("div", { className: "idk-state", children: emptyMessage });
416
470
  }
417
471
  const gridStyle = { gridTemplateColumns: `repeat(${Math.max(1, columns)}, minmax(0, 1fr))` };
418
- return /* @__PURE__ */ jsx5(
472
+ return /* @__PURE__ */ jsx6(
419
473
  "div",
420
474
  {
421
475
  className: ["idk-team", className].filter(Boolean).join(" "),
422
476
  style: gridStyle,
423
- children: members.map((member) => /* @__PURE__ */ jsx5(
477
+ children: members.map((member) => /* @__PURE__ */ jsx6(
424
478
  TeamMember,
425
479
  {
426
480
  member,
@@ -439,7 +493,7 @@ function TeamGrid({
439
493
  // src/components/ContactForm.tsx
440
494
  import { useState as useState2 } from "react";
441
495
  import { useMutation as useMutation2 } from "@tanstack/react-query";
442
- import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
496
+ import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
443
497
  var DEFAULT_FIELDS = ["name", "email", "phone", "message"];
444
498
  function ContactForm({
445
499
  fields = DEFAULT_FIELDS,
@@ -487,8 +541,8 @@ function ContactForm({
487
541
  };
488
542
  return /* @__PURE__ */ jsxs3("form", { className: ["idk-form", className].filter(Boolean).join(" "), onSubmit: handleSubmit, children: [
489
543
  fields.includes("name") && /* @__PURE__ */ jsxs3("label", { className: "idk-form__field", children: [
490
- /* @__PURE__ */ jsx6("span", { children: "Name" }),
491
- /* @__PURE__ */ jsx6(
544
+ /* @__PURE__ */ jsx7("span", { children: "Name" }),
545
+ /* @__PURE__ */ jsx7(
492
546
  "input",
493
547
  {
494
548
  value: formState.name,
@@ -498,8 +552,8 @@ function ContactForm({
498
552
  )
499
553
  ] }),
500
554
  fields.includes("email") && /* @__PURE__ */ jsxs3("label", { className: "idk-form__field", children: [
501
- /* @__PURE__ */ jsx6("span", { children: "Email" }),
502
- /* @__PURE__ */ jsx6(
555
+ /* @__PURE__ */ jsx7("span", { children: "Email" }),
556
+ /* @__PURE__ */ jsx7(
503
557
  "input",
504
558
  {
505
559
  type: "email",
@@ -510,8 +564,8 @@ function ContactForm({
510
564
  )
511
565
  ] }),
512
566
  fields.includes("phone") && /* @__PURE__ */ jsxs3("label", { className: "idk-form__field", children: [
513
- /* @__PURE__ */ jsx6("span", { children: "Phone" }),
514
- /* @__PURE__ */ jsx6(
567
+ /* @__PURE__ */ jsx7("span", { children: "Phone" }),
568
+ /* @__PURE__ */ jsx7(
515
569
  "input",
516
570
  {
517
571
  value: formState.phone,
@@ -520,8 +574,8 @@ function ContactForm({
520
574
  )
521
575
  ] }),
522
576
  fields.includes("subject") && /* @__PURE__ */ jsxs3("label", { className: "idk-form__field", children: [
523
- /* @__PURE__ */ jsx6("span", { children: "Subject" }),
524
- /* @__PURE__ */ jsx6(
577
+ /* @__PURE__ */ jsx7("span", { children: "Subject" }),
578
+ /* @__PURE__ */ jsx7(
525
579
  "input",
526
580
  {
527
581
  value: formState.subject,
@@ -530,8 +584,8 @@ function ContactForm({
530
584
  )
531
585
  ] }),
532
586
  fields.includes("message") && /* @__PURE__ */ jsxs3("label", { className: "idk-form__field", children: [
533
- /* @__PURE__ */ jsx6("span", { children: "Message" }),
534
- /* @__PURE__ */ jsx6(
587
+ /* @__PURE__ */ jsx7("span", { children: "Message" }),
588
+ /* @__PURE__ */ jsx7(
535
589
  "textarea",
536
590
  {
537
591
  value: formState.message,
@@ -541,15 +595,27 @@ function ContactForm({
541
595
  }
542
596
  )
543
597
  ] }),
544
- /* @__PURE__ */ jsx6("button", { type: "submit", className: "idk-button", disabled: mutation.isPending, children: mutation.isPending ? "Sending..." : submitLabel }),
545
- mutation.isError ? /* @__PURE__ */ jsx6("p", { className: "idk-form__error", children: "Something went wrong. Please try again." }) : null,
546
- mutation.isSuccess ? /* @__PURE__ */ jsx6("p", { className: "idk-form__success", children: "Thanks! We'll be in touch soon." }) : null
598
+ /* @__PURE__ */ jsx7("button", { type: "submit", className: "idk-button", disabled: mutation.isPending, children: mutation.isPending ? "Sending..." : submitLabel }),
599
+ mutation.isError ? /* @__PURE__ */ jsx7("p", { className: "idk-form__error", children: "Something went wrong. Please try again." }) : null,
600
+ mutation.isSuccess ? /* @__PURE__ */ jsx7("p", { className: "idk-form__success", children: "Thanks! We'll be in touch soon." }) : null
547
601
  ] });
548
602
  }
549
603
 
550
604
  // src/components/BookingWidget.tsx
551
605
  import { useCallback, useEffect, useMemo as useMemo4, useRef, useState as useState3 } from "react";
552
- import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
606
+ import { Fragment, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
607
+ var parseDateOnly = (value) => {
608
+ if (!value) return null;
609
+ const normalized = value.includes("T") ? value.split("T")[0] : value;
610
+ const parsed = /* @__PURE__ */ new Date(`${normalized}T00:00:00`);
611
+ return Number.isNaN(parsed.getTime()) ? null : parsed;
612
+ };
613
+ var addDays = (dateStr, days) => {
614
+ const parsed = parseDateOnly(dateStr);
615
+ if (!parsed) return dateStr;
616
+ parsed.setDate(parsed.getDate() + days);
617
+ return parsed.toISOString().slice(0, 10);
618
+ };
553
619
  function BookingWidget({
554
620
  className,
555
621
  showStaffSelection = true,
@@ -576,7 +642,16 @@ function BookingWidget({
576
642
  staffLayout = "grid",
577
643
  staffColumns = 2,
578
644
  showAnyStaffOption = true,
579
- timeLayout = "split"
645
+ staffPageSize = 8,
646
+ showStaffPagination,
647
+ timeLayout = "split",
648
+ availabilityDays: availabilityDaysProp = 7,
649
+ enableDatePaging = true,
650
+ datePickerMode = "list",
651
+ calendarVariant = "default",
652
+ maxAdvanceMonths = 3,
653
+ disabledWeekdays = [],
654
+ showFullyBookedLabel = true
580
655
  }) {
581
656
  const resolvedServicesQuery = useMemo4(
582
657
  () => services ? { ...servicesQuery, enabled: false } : servicesQuery,
@@ -595,6 +670,17 @@ function BookingWidget({
595
670
  const [serviceSearch, setServiceSearch] = useState3("");
596
671
  const [categoryFilter, setCategoryFilter] = useState3("all");
597
672
  const [servicePage, setServicePage] = useState3(1);
673
+ const [staffPage, setStaffPage] = useState3(1);
674
+ const [availabilityDays, setAvailabilityDays] = useState3(
675
+ Math.max(1, availabilityDaysProp)
676
+ );
677
+ const [availabilityStartDate, setAvailabilityStartDate] = useState3(
678
+ () => (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)
679
+ );
680
+ const [calendarMonth, setCalendarMonth] = useState3(() => {
681
+ const now = /* @__PURE__ */ new Date();
682
+ return new Date(now.getFullYear(), now.getMonth(), 1);
683
+ });
598
684
  const [bookingError, setBookingError] = useState3(null);
599
685
  const [details, setDetails] = useState3({
600
686
  name: "",
@@ -626,6 +712,9 @@ function BookingWidget({
626
712
  useEffect(() => {
627
713
  setServicePage(1);
628
714
  }, [serviceSearch, categoryFilter]);
715
+ useEffect(() => {
716
+ setStaffPage(1);
717
+ }, [selectedService?.id, teamData, teamFilter]);
629
718
  const pagedServices = useMemo4(() => {
630
719
  const pageSize = Math.max(1, servicePageSize);
631
720
  return filteredServices.slice(0, pageSize * servicePage);
@@ -641,10 +730,21 @@ function BookingWidget({
641
730
  const teamList = teamData?.team || [];
642
731
  return teamFilter ? teamList.filter(teamFilter) : teamList;
643
732
  }, [selectedService, teamData, teamFilter]);
733
+ const pagedStaff = useMemo4(() => {
734
+ const pageSize = Math.max(1, staffPageSize);
735
+ return staffOptions.slice(0, pageSize * staffPage);
736
+ }, [staffOptions, staffPage, staffPageSize]);
737
+ const hasMoreStaff = staffOptions.length > pagedStaff.length;
738
+ const shouldPaginateStaff = showStaffPagination ?? hasMoreStaff;
739
+ const availabilityEndDate = useMemo4(
740
+ () => addDays(availabilityStartDate, Math.max(1, availabilityDays) - 1),
741
+ [availabilityStartDate, availabilityDays]
742
+ );
644
743
  const availability = useAvailability({
645
744
  serviceId: selectedService?.id || "",
646
745
  staffId: selectedStaff?.id,
647
- days: 7,
746
+ startDate: availabilityStartDate,
747
+ endDate: availabilityEndDate,
648
748
  enabled: Boolean(selectedService)
649
749
  });
650
750
  const timeZone = availability.data?.timeZone || "America/Chicago";
@@ -714,18 +814,6 @@ function BookingWidget({
714
814
  setSelectedEndTime(null);
715
815
  setBookingError(null);
716
816
  };
717
- useEffect(() => {
718
- if (step !== "time") return;
719
- if (!availability.data?.dates?.length) return;
720
- if (selectedDate) return;
721
- setSelectedDate(availability.data.dates[0].date);
722
- }, [step, availability.data, selectedDate]);
723
- const parseDateOnly = (value) => {
724
- if (!value) return null;
725
- const normalized = value.includes("T") ? value.split("T")[0] : value;
726
- const parsed = /* @__PURE__ */ new Date(`${normalized}T00:00:00`);
727
- return Number.isNaN(parsed.getTime()) ? null : parsed;
728
- };
729
817
  const parseDateTime = (value, fallbackDate) => {
730
818
  if (!value) return null;
731
819
  const direct = new Date(value);
@@ -771,6 +859,118 @@ function BookingWidget({
771
859
  const remaining = minutes % 60;
772
860
  return remaining === 0 ? `${hours} hr${hours > 1 ? "s" : ""}` : `${hours} hr ${remaining} min`;
773
861
  };
862
+ const todayString = useMemo4(() => (/* @__PURE__ */ new Date()).toISOString().slice(0, 10), []);
863
+ const todayDate = useMemo4(() => {
864
+ const now = /* @__PURE__ */ new Date();
865
+ now.setHours(0, 0, 0, 0);
866
+ return now;
867
+ }, []);
868
+ const disabledWeekdaysSet = useMemo4(() => new Set(disabledWeekdays), [disabledWeekdays]);
869
+ const getMonthStart = useCallback((date) => {
870
+ return new Date(date.getFullYear(), date.getMonth(), 1);
871
+ }, []);
872
+ const getMonthEnd = useCallback((date) => {
873
+ return new Date(date.getFullYear(), date.getMonth() + 1, 0);
874
+ }, []);
875
+ const getMonthDays = useCallback(
876
+ (date) => {
877
+ const start = getMonthStart(date);
878
+ const end = getMonthEnd(date);
879
+ const days = [];
880
+ const startDay = start.getDay();
881
+ for (let i = startDay; i > 0; i -= 1) {
882
+ const d = new Date(start);
883
+ d.setDate(start.getDate() - i);
884
+ days.push({ date: d.toISOString().slice(0, 10), isCurrentMonth: false });
885
+ }
886
+ for (let day = 1; day <= end.getDate(); day += 1) {
887
+ const d = new Date(date.getFullYear(), date.getMonth(), day);
888
+ days.push({ date: d.toISOString().slice(0, 10), isCurrentMonth: true });
889
+ }
890
+ const remainder = 7 - (days.length % 7 || 7);
891
+ for (let i = 1; i <= remainder; i += 1) {
892
+ const d = new Date(end);
893
+ d.setDate(end.getDate() + i);
894
+ days.push({ date: d.toISOString().slice(0, 10), isCurrentMonth: false });
895
+ }
896
+ return days;
897
+ },
898
+ [getMonthEnd, getMonthStart]
899
+ );
900
+ const maxAdvanceDate = useMemo4(() => {
901
+ if (!maxAdvanceMonths || maxAdvanceMonths <= 0) return null;
902
+ const maxMonth = new Date(todayDate.getFullYear(), todayDate.getMonth() + maxAdvanceMonths - 1, 1);
903
+ return getMonthEnd(maxMonth);
904
+ }, [getMonthEnd, maxAdvanceMonths, todayDate]);
905
+ const maxAdvanceMonthStart = useMemo4(() => {
906
+ if (!maxAdvanceMonths || maxAdvanceMonths <= 0) return null;
907
+ return new Date(todayDate.getFullYear(), todayDate.getMonth() + maxAdvanceMonths - 1, 1);
908
+ }, [maxAdvanceMonths, todayDate]);
909
+ const handlePrevDates = () => {
910
+ if (availabilityStartDate <= todayString) return;
911
+ setAvailabilityStartDate((prev) => addDays(prev, -availabilityDays));
912
+ setSelectedDate(null);
913
+ setSelectedTime(null);
914
+ setSelectedEndTime(null);
915
+ setBookingError(null);
916
+ };
917
+ const handleNextDates = () => {
918
+ if (maxAdvanceDate) {
919
+ const nextStart = parseDateOnly(addDays(availabilityStartDate, availabilityDays));
920
+ if (nextStart && nextStart > maxAdvanceDate) {
921
+ return;
922
+ }
923
+ }
924
+ setAvailabilityStartDate((prev) => addDays(prev, availabilityDays));
925
+ setSelectedDate(null);
926
+ setSelectedTime(null);
927
+ setSelectedEndTime(null);
928
+ setBookingError(null);
929
+ };
930
+ const handlePrevMonth = () => {
931
+ setCalendarMonth((prev) => new Date(prev.getFullYear(), prev.getMonth() - 1, 1));
932
+ setSelectedDate(null);
933
+ setSelectedTime(null);
934
+ setSelectedEndTime(null);
935
+ setBookingError(null);
936
+ };
937
+ const handleNextMonth = () => {
938
+ if (maxAdvanceMonthStart) {
939
+ const nextMonth = new Date(calendarMonth.getFullYear(), calendarMonth.getMonth() + 1, 1);
940
+ if (nextMonth > maxAdvanceMonthStart) return;
941
+ }
942
+ setCalendarMonth((prev) => new Date(prev.getFullYear(), prev.getMonth() + 1, 1));
943
+ setSelectedDate(null);
944
+ setSelectedTime(null);
945
+ setSelectedEndTime(null);
946
+ setBookingError(null);
947
+ };
948
+ useEffect(() => {
949
+ if (step !== "time") return;
950
+ if (!availability.data?.dates?.length) return;
951
+ const matches = selectedDate ? availability.data.dates.some((entry) => entry.date === selectedDate) : false;
952
+ if (matches) return;
953
+ setSelectedDate(availability.data.dates[0].date);
954
+ }, [step, availability.data, selectedDate]);
955
+ useEffect(() => {
956
+ if (!selectedService) return;
957
+ if (datePickerMode === "calendar") {
958
+ const now = /* @__PURE__ */ new Date();
959
+ setCalendarMonth(new Date(now.getFullYear(), now.getMonth(), 1));
960
+ return;
961
+ }
962
+ setAvailabilityStartDate((/* @__PURE__ */ new Date()).toISOString().slice(0, 10));
963
+ setAvailabilityDays(Math.max(1, availabilityDaysProp));
964
+ }, [selectedService?.id, selectedStaff?.id, availabilityDaysProp, datePickerMode]);
965
+ useEffect(() => {
966
+ if (datePickerMode !== "calendar") return;
967
+ const start = getMonthStart(calendarMonth);
968
+ const end = getMonthEnd(calendarMonth);
969
+ const startString = start.toISOString().slice(0, 10);
970
+ const daysInMonth = end.getDate();
971
+ setAvailabilityStartDate(startString);
972
+ setAvailabilityDays(daysInMonth);
973
+ }, [calendarMonth, datePickerMode, getMonthEnd, getMonthStart]);
774
974
  const handleBack = () => {
775
975
  if (step === "service") return;
776
976
  if (step === "staff") {
@@ -840,10 +1040,10 @@ function BookingWidget({
840
1040
  };
841
1041
  const isServicesLoading = services ? false : servicesLoading;
842
1042
  if (isServicesLoading) {
843
- return /* @__PURE__ */ jsx7("div", { className: "idk-state", children: "Loading booking options..." });
1043
+ return /* @__PURE__ */ jsx8("div", { className: "idk-state", children: "Loading booking options..." });
844
1044
  }
845
1045
  if (!servicesList.length) {
846
- return /* @__PURE__ */ jsx7("div", { className: "idk-state", children: "No services available." });
1046
+ return /* @__PURE__ */ jsx8("div", { className: "idk-state", children: "No services available." });
847
1047
  }
848
1048
  return /* @__PURE__ */ jsxs4(
849
1049
  "div",
@@ -853,10 +1053,10 @@ function BookingWidget({
853
1053
  children: [
854
1054
  /* @__PURE__ */ jsxs4("div", { className: "idk-booking__header", children: [
855
1055
  /* @__PURE__ */ jsxs4("div", { className: "idk-booking__title-wrap", children: [
856
- /* @__PURE__ */ jsx7("h3", { className: "idk-booking__title", children: title }),
857
- subtitle ? /* @__PURE__ */ jsx7("p", { className: "idk-booking__subtitle", children: subtitle }) : null
1056
+ /* @__PURE__ */ jsx8("h3", { className: "idk-booking__title", children: title }),
1057
+ subtitle ? /* @__PURE__ */ jsx8("p", { className: "idk-booking__subtitle", children: subtitle }) : null
858
1058
  ] }),
859
- step !== "service" && step !== "done" ? /* @__PURE__ */ jsx7("button", { type: "button", className: "idk-link", onClick: handleBack, children: "Back" }) : null
1059
+ step !== "service" && step !== "done" ? /* @__PURE__ */ jsx8("button", { type: "button", className: "idk-link", onClick: handleBack, children: "Back" }) : null
860
1060
  ] }),
861
1061
  step !== "done" ? /* @__PURE__ */ jsxs4("div", { className: "idk-booking__progress", children: [
862
1062
  /* @__PURE__ */ jsxs4("span", { children: [
@@ -865,7 +1065,7 @@ function BookingWidget({
865
1065
  " of ",
866
1066
  totalSteps
867
1067
  ] }),
868
- /* @__PURE__ */ jsx7("div", { className: "idk-booking__bar", children: /* @__PURE__ */ jsx7(
1068
+ /* @__PURE__ */ jsx8("div", { className: "idk-booking__bar", children: /* @__PURE__ */ jsx8(
869
1069
  "div",
870
1070
  {
871
1071
  className: "idk-booking__bar-fill",
@@ -874,9 +1074,9 @@ function BookingWidget({
874
1074
  ) })
875
1075
  ] }) : null,
876
1076
  step === "service" && /* @__PURE__ */ jsxs4("div", { className: "idk-booking__step", children: [
877
- /* @__PURE__ */ jsx7("h4", { children: "Select a service" }),
1077
+ /* @__PURE__ */ jsx8("h4", { children: "Select a service" }),
878
1078
  enableServiceSearch || enableCategoryFilter ? /* @__PURE__ */ jsxs4("div", { className: "idk-booking__filters", children: [
879
- enableServiceSearch ? /* @__PURE__ */ jsx7(
1079
+ enableServiceSearch ? /* @__PURE__ */ jsx8(
880
1080
  "input",
881
1081
  {
882
1082
  type: "search",
@@ -891,13 +1091,13 @@ function BookingWidget({
891
1091
  value: categoryFilter,
892
1092
  onChange: (event) => setCategoryFilter(event.target.value),
893
1093
  children: [
894
- /* @__PURE__ */ jsx7("option", { value: "all", children: categoryLabel }),
895
- categories.map((category) => /* @__PURE__ */ jsx7("option", { value: category, children: category }, category))
1094
+ /* @__PURE__ */ jsx8("option", { value: "all", children: categoryLabel }),
1095
+ categories.map((category) => /* @__PURE__ */ jsx8("option", { value: category, children: category }, category))
896
1096
  ]
897
1097
  }
898
1098
  ) : null
899
1099
  ] }) : null,
900
- filteredServices.length === 0 ? /* @__PURE__ */ jsx7("div", { className: "idk-state", children: "No services match your filters." }) : /* @__PURE__ */ jsx7(
1100
+ filteredServices.length === 0 ? /* @__PURE__ */ jsx8("div", { className: "idk-state", children: "No services match your filters." }) : /* @__PURE__ */ jsx8(
901
1101
  "div",
902
1102
  {
903
1103
  className: [
@@ -929,19 +1129,19 @@ function BookingWidget({
929
1129
  },
930
1130
  children: [
931
1131
  /* @__PURE__ */ jsxs4("div", { className: "idk-card__header", children: [
932
- /* @__PURE__ */ jsx7("span", { className: "idk-card__title", children: service.name }),
1132
+ /* @__PURE__ */ jsx8("span", { className: "idk-card__title", children: service.name }),
933
1133
  /* @__PURE__ */ jsxs4("span", { className: "idk-card__aside", children: [
934
- isSelected ? /* @__PURE__ */ jsx7("span", { className: "idk-card__check", children: "\u2713" }) : null,
1134
+ isSelected ? /* @__PURE__ */ jsx8("span", { className: "idk-card__check", children: "\u2713" }) : null,
935
1135
  typeof service.price === "number" && service.price > 0 ? /* @__PURE__ */ jsxs4("span", { className: "idk-card__price", children: [
936
1136
  "$",
937
1137
  (service.price / 100).toFixed(2)
938
1138
  ] }) : null
939
1139
  ] })
940
1140
  ] }),
941
- service.description ? /* @__PURE__ */ jsx7("div", { className: "idk-card__description", children: service.description }) : null,
1141
+ service.description ? /* @__PURE__ */ jsx8("div", { className: "idk-card__description", children: service.description }) : null,
942
1142
  /* @__PURE__ */ jsxs4("div", { className: "idk-card__meta", children: [
943
- /* @__PURE__ */ jsx7("span", { children: formatDuration(service.duration) }),
944
- service.category ? /* @__PURE__ */ jsx7("span", { className: "idk-pill", children: service.category }) : null
1143
+ /* @__PURE__ */ jsx8("span", { children: formatDuration(service.duration) }),
1144
+ service.category ? /* @__PURE__ */ jsx8("span", { className: "idk-pill", children: service.category }) : null
945
1145
  ] })
946
1146
  ]
947
1147
  },
@@ -951,7 +1151,7 @@ function BookingWidget({
951
1151
  }
952
1152
  ),
953
1153
  /* @__PURE__ */ jsxs4("div", { className: "idk-booking__actions", children: [
954
- shouldPaginate ? /* @__PURE__ */ jsx7(
1154
+ shouldPaginate ? /* @__PURE__ */ jsx8(
955
1155
  "button",
956
1156
  {
957
1157
  type: "button",
@@ -961,12 +1161,12 @@ function BookingWidget({
961
1161
  children: hasMoreServices ? "Show more services" : "All services shown"
962
1162
  }
963
1163
  ) : null,
964
- selectedService && !autoAdvanceOnSelect ? /* @__PURE__ */ jsx7("button", { type: "button", className: "idk-button", onClick: handleServiceContinue, children: "Continue" }) : null
1164
+ selectedService && !autoAdvanceOnSelect ? /* @__PURE__ */ jsx8("button", { type: "button", className: "idk-button", onClick: handleServiceContinue, children: "Continue" }) : null
965
1165
  ] })
966
1166
  ] }),
967
1167
  step === "staff" && /* @__PURE__ */ jsxs4("div", { className: "idk-booking__step", children: [
968
- /* @__PURE__ */ jsx7("h4", { children: "Select a team member" }),
969
- staffOptions.length === 0 ? /* @__PURE__ */ jsx7("div", { className: "idk-state", children: "No team members available." }) : /* @__PURE__ */ jsxs4(
1168
+ /* @__PURE__ */ jsx8("h4", { children: "Select a team member" }),
1169
+ staffOptions.length === 0 ? /* @__PURE__ */ jsx8("div", { className: "idk-state", children: "No team members available." }) : /* @__PURE__ */ jsxs4(
970
1170
  "div",
971
1171
  {
972
1172
  className: [
@@ -992,15 +1192,15 @@ function BookingWidget({
992
1192
  },
993
1193
  children: [
994
1194
  /* @__PURE__ */ jsxs4("div", { className: "idk-card__header", children: [
995
- /* @__PURE__ */ jsx7("span", { className: "idk-card__title", children: "Any Available" }),
996
- /* @__PURE__ */ jsx7("span", { className: "idk-card__badge", children: "Recommended" })
1195
+ /* @__PURE__ */ jsx8("span", { className: "idk-card__title", children: "Any Available" }),
1196
+ /* @__PURE__ */ jsx8("span", { className: "idk-card__badge", children: "Recommended" })
997
1197
  ] }),
998
- /* @__PURE__ */ jsx7("p", { className: "idk-card__description", children: "We'll match you with the first available stylist." })
1198
+ /* @__PURE__ */ jsx8("p", { className: "idk-card__description", children: "We'll match you with the first available stylist." })
999
1199
  ]
1000
1200
  },
1001
1201
  "any-staff"
1002
1202
  ) : null,
1003
- staffOptions.map((staff) => /* @__PURE__ */ jsx7(
1203
+ pagedStaff.map((staff) => /* @__PURE__ */ jsx8(
1004
1204
  "button",
1005
1205
  {
1006
1206
  type: "button",
@@ -1017,11 +1217,11 @@ function BookingWidget({
1017
1217
  }
1018
1218
  },
1019
1219
  children: /* @__PURE__ */ jsxs4("div", { className: "idk-team__card", children: [
1020
- /* @__PURE__ */ jsx7("div", { className: "idk-team__avatar", children: staff.photo?.url ? /* @__PURE__ */ jsx7("img", { src: staff.photo.url, alt: staff.name }) : /* @__PURE__ */ jsx7("span", { children: staff.name.split(" ").map((part) => part[0]).slice(0, 2).join("").toUpperCase() }) }),
1220
+ /* @__PURE__ */ jsx8("div", { className: "idk-team__avatar", children: staff.photo?.url ? /* @__PURE__ */ jsx8("img", { src: staff.photo.url, alt: staff.name }) : /* @__PURE__ */ jsx8("span", { children: staff.name.split(" ").map((part) => part[0]).slice(0, 2).join("").toUpperCase() }) }),
1021
1221
  /* @__PURE__ */ jsxs4("div", { children: [
1022
- /* @__PURE__ */ jsx7("span", { className: "idk-card__title", children: staff.name }),
1023
- /* @__PURE__ */ jsx7("span", { className: "idk-card__meta", children: staff.role || "Staff" }),
1024
- staff.bio ? /* @__PURE__ */ jsx7("p", { className: "idk-card__description", children: staff.bio }) : null
1222
+ /* @__PURE__ */ jsx8("span", { className: "idk-card__title", children: staff.name }),
1223
+ /* @__PURE__ */ jsx8("span", { className: "idk-card__meta", children: staff.role || "Staff" }),
1224
+ staff.bio ? /* @__PURE__ */ jsx8("p", { className: "idk-card__description", children: renderLinkedText(staff.bio) }) : null
1025
1225
  ] })
1026
1226
  ] })
1027
1227
  },
@@ -1031,7 +1231,17 @@ function BookingWidget({
1031
1231
  }
1032
1232
  ),
1033
1233
  /* @__PURE__ */ jsxs4("div", { className: "idk-booking__actions", children: [
1034
- canSkipStaff ? /* @__PURE__ */ jsx7(
1234
+ shouldPaginateStaff ? /* @__PURE__ */ jsx8(
1235
+ "button",
1236
+ {
1237
+ type: "button",
1238
+ className: "idk-button idk-button--ghost",
1239
+ onClick: () => setStaffPage((prev) => hasMoreStaff ? prev + 1 : 1),
1240
+ disabled: !hasMoreStaff && staffPage === 1,
1241
+ children: hasMoreStaff ? "Show more staff" : staffPage > 1 ? "Show fewer staff" : "All staff shown"
1242
+ }
1243
+ ) : null,
1244
+ canSkipStaff ? /* @__PURE__ */ jsx8(
1035
1245
  "button",
1036
1246
  {
1037
1247
  type: "button",
@@ -1044,7 +1254,7 @@ function BookingWidget({
1044
1254
  children: "Continue without selecting"
1045
1255
  }
1046
1256
  ) : null,
1047
- !autoAdvanceOnSelect ? /* @__PURE__ */ jsx7(
1257
+ !autoAdvanceOnSelect ? /* @__PURE__ */ jsx8(
1048
1258
  "button",
1049
1259
  {
1050
1260
  type: "button",
@@ -1057,36 +1267,136 @@ function BookingWidget({
1057
1267
  ] })
1058
1268
  ] }),
1059
1269
  step === "time" && /* @__PURE__ */ jsxs4("div", { className: "idk-booking__step", children: [
1060
- /* @__PURE__ */ jsx7("h4", { children: "Select a time" }),
1061
- availability.isLoading ? /* @__PURE__ */ jsx7("div", { className: "idk-state", children: "Loading availability..." }) : availability.data ? /* @__PURE__ */ jsxs4("div", { className: ["idk-availability", timeLayout === "split" ? "idk-availability--split" : ""].join(" "), children: [
1062
- /* @__PURE__ */ jsx7("div", { className: "idk-availability__dates", children: availability.data.dates.map((entry) => /* @__PURE__ */ jsx7(
1063
- "button",
1270
+ /* @__PURE__ */ jsx8("h4", { children: "Select a time" }),
1271
+ availability.isLoading ? /* @__PURE__ */ jsx8("div", { className: "idk-state", children: "Loading availability..." }) : availability.data ? /* @__PURE__ */ jsxs4("div", { className: ["idk-availability", timeLayout === "split" ? "idk-availability--split" : ""].join(" "), children: [
1272
+ /* @__PURE__ */ jsx8("div", { className: "idk-availability__dates", children: datePickerMode === "calendar" ? /* @__PURE__ */ jsxs4(
1273
+ "div",
1064
1274
  {
1065
- type: "button",
1066
- className: entry.date === selectedDate ? "is-active" : void 0,
1067
- onClick: () => {
1068
- setSelectedDate(entry.date);
1069
- setSelectedTime(null);
1070
- setSelectedEndTime(null);
1071
- setBookingError(null);
1275
+ className: [
1276
+ "idk-calendar",
1277
+ calendarVariant === "compact" ? "idk-calendar--compact" : ""
1278
+ ].filter(Boolean).join(" "),
1279
+ children: [
1280
+ /* @__PURE__ */ jsxs4("div", { className: "idk-calendar__header", children: [
1281
+ /* @__PURE__ */ jsx8(
1282
+ "button",
1283
+ {
1284
+ type: "button",
1285
+ className: "idk-button idk-button--ghost",
1286
+ onClick: handlePrevMonth,
1287
+ disabled: calendarMonth <= getMonthStart(todayDate),
1288
+ children: "Previous"
1289
+ }
1290
+ ),
1291
+ /* @__PURE__ */ jsx8("div", { className: "idk-calendar__title", children: new Intl.DateTimeFormat("en-US", {
1292
+ month: "long",
1293
+ year: "numeric"
1294
+ }).format(calendarMonth) }),
1295
+ /* @__PURE__ */ jsx8(
1296
+ "button",
1297
+ {
1298
+ type: "button",
1299
+ className: "idk-button idk-button--ghost",
1300
+ onClick: handleNextMonth,
1301
+ disabled: Boolean(maxAdvanceMonthStart && calendarMonth >= maxAdvanceMonthStart),
1302
+ children: "Next"
1303
+ }
1304
+ )
1305
+ ] }),
1306
+ /* @__PURE__ */ jsx8("div", { className: "idk-calendar__weekdays", children: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].map((label) => /* @__PURE__ */ jsx8("span", { children: label }, label)) }),
1307
+ /* @__PURE__ */ jsx8("div", { className: "idk-calendar__grid", children: getMonthDays(calendarMonth).map((day) => {
1308
+ const entry = availability.data?.dates?.find(
1309
+ (item) => item.date === day.date
1310
+ );
1311
+ const hasAvailable = entry?.slots?.some((slot) => slot.available) ?? false;
1312
+ const dateValue = parseDateOnly(day.date);
1313
+ const isPast = dateValue ? dateValue < todayDate : false;
1314
+ const isBeyondMax = maxAdvanceDate ? dateValue ? dateValue > maxAdvanceDate : false : false;
1315
+ const weekday = dateValue ? dateValue.getDay() : null;
1316
+ const isDisabledWeekday = weekday !== null ? disabledWeekdaysSet.has(weekday) : false;
1317
+ const isBlocked = Boolean(entry) && !hasAvailable;
1318
+ const isDisabled = !entry || isPast || isBeyondMax || isBlocked || isDisabledWeekday;
1319
+ const isActive = selectedDate === day.date;
1320
+ return /* @__PURE__ */ jsxs4(
1321
+ "button",
1322
+ {
1323
+ type: "button",
1324
+ className: [
1325
+ "idk-calendar__day",
1326
+ day.isCurrentMonth ? "" : "is-muted",
1327
+ hasAvailable ? "is-available" : "",
1328
+ isBlocked ? "is-blocked" : "",
1329
+ isDisabledWeekday ? "is-disabled" : "",
1330
+ isActive ? "is-active" : ""
1331
+ ].filter(Boolean).join(" "),
1332
+ disabled: isDisabled,
1333
+ onClick: () => {
1334
+ setSelectedDate(day.date);
1335
+ setSelectedTime(null);
1336
+ setSelectedEndTime(null);
1337
+ setBookingError(null);
1338
+ },
1339
+ children: [
1340
+ /* @__PURE__ */ jsx8("span", { children: day.date.split("-")[2] }),
1341
+ showFullyBookedLabel && isBlocked && day.isCurrentMonth ? /* @__PURE__ */ jsx8("span", { className: "idk-calendar__label", children: calendarVariant === "compact" ? "Full" : "Fully booked" }) : null
1342
+ ]
1343
+ },
1344
+ day.date
1345
+ );
1346
+ }) })
1347
+ ]
1348
+ }
1349
+ ) : /* @__PURE__ */ jsxs4(Fragment, { children: [
1350
+ enableDatePaging ? /* @__PURE__ */ jsxs4("div", { className: "idk-availability__nav", children: [
1351
+ /* @__PURE__ */ jsx8(
1352
+ "button",
1353
+ {
1354
+ type: "button",
1355
+ className: "idk-button idk-button--ghost",
1356
+ onClick: handlePrevDates,
1357
+ disabled: availabilityStartDate <= todayString,
1358
+ children: "Previous"
1359
+ }
1360
+ ),
1361
+ /* @__PURE__ */ jsx8(
1362
+ "button",
1363
+ {
1364
+ type: "button",
1365
+ className: "idk-button idk-button--ghost",
1366
+ onClick: handleNextDates,
1367
+ children: "Next"
1368
+ }
1369
+ )
1370
+ ] }) : null,
1371
+ availability.data.dates.map((entry) => /* @__PURE__ */ jsx8(
1372
+ "button",
1373
+ {
1374
+ type: "button",
1375
+ className: entry.date === selectedDate ? "is-active" : void 0,
1376
+ onClick: () => {
1377
+ setSelectedDate(entry.date);
1378
+ setSelectedTime(null);
1379
+ setSelectedEndTime(null);
1380
+ setBookingError(null);
1381
+ },
1382
+ children: /* @__PURE__ */ jsx8("span", { className: "idk-date-chip__day", children: formatDateLabel(entry.date) })
1072
1383
  },
1073
- children: /* @__PURE__ */ jsx7("span", { className: "idk-date-chip__day", children: formatDateLabel(entry.date) })
1074
- },
1075
- entry.date
1076
- )) }),
1384
+ entry.date
1385
+ ))
1386
+ ] }) }),
1077
1387
  /* @__PURE__ */ jsxs4("div", { className: "idk-availability__panel", children: [
1078
- /* @__PURE__ */ jsx7("div", { className: "idk-availability__panel-header", children: /* @__PURE__ */ jsxs4("div", { children: [
1079
- /* @__PURE__ */ jsx7("div", { className: "idk-availability__panel-title", children: selectedDate ? formatDateHeading(selectedDate) : availability.data.dates[0]?.date ? formatDateHeading(availability.data.dates[0].date) : "Select a date" }),
1080
- /* @__PURE__ */ jsx7("div", { className: "idk-availability__panel-subtitle", children: timeZoneLabel })
1388
+ /* @__PURE__ */ jsx8("div", { className: "idk-availability__panel-header", children: /* @__PURE__ */ jsxs4("div", { children: [
1389
+ /* @__PURE__ */ jsx8("div", { className: "idk-availability__panel-title", children: selectedDate ? formatDateHeading(selectedDate) : availability.data.dates[0]?.date ? formatDateHeading(availability.data.dates[0].date) : "Select a date" }),
1390
+ /* @__PURE__ */ jsx8("div", { className: "idk-availability__panel-subtitle", children: timeZoneLabel })
1081
1391
  ] }) }),
1082
- /* @__PURE__ */ jsx7("div", { className: "idk-availability__slots", children: (() => {
1083
- const activeEntry = availability.data.dates.find((entry) => entry.date === selectedDate) || availability.data.dates[0];
1084
- if (!activeEntry) return /* @__PURE__ */ jsx7("div", { className: "idk-state", children: "Select a date to see times." });
1392
+ /* @__PURE__ */ jsx8("div", { className: "idk-availability__slots", children: (() => {
1393
+ const activeEntry = selectedDate ? availability.data.dates.find((entry) => entry.date === selectedDate) : availability.data.dates[0];
1394
+ if (!activeEntry) return /* @__PURE__ */ jsx8("div", { className: "idk-state", children: "Select a date to see times." });
1085
1395
  const slots = (activeEntry.slots || []).filter((slot) => slot.available);
1086
1396
  if (slots.length === 0) {
1087
- return /* @__PURE__ */ jsx7("div", { className: "idk-state", children: "No available times for this date." });
1397
+ return /* @__PURE__ */ jsx8("div", { className: "idk-state", children: "No available times for this date." });
1088
1398
  }
1089
- return slots.map((slot) => /* @__PURE__ */ jsx7(
1399
+ return slots.map((slot, index) => /* @__PURE__ */ jsx8(
1090
1400
  "button",
1091
1401
  {
1092
1402
  type: "button",
@@ -1104,12 +1414,12 @@ function BookingWidget({
1104
1414
  },
1105
1415
  children: formatTimeLabel(slot.time)
1106
1416
  },
1107
- `${slot.time}-${slot.endTime}`
1417
+ `${activeEntry.date}-${slot.time}-${slot.endTime}-${index}`
1108
1418
  ));
1109
1419
  })() })
1110
1420
  ] })
1111
- ] }) : /* @__PURE__ */ jsx7("div", { className: "idk-state", children: "No availability found." }),
1112
- !autoAdvanceOnSelect ? /* @__PURE__ */ jsx7("div", { className: "idk-booking__actions", children: /* @__PURE__ */ jsx7(
1421
+ ] }) : /* @__PURE__ */ jsx8("div", { className: "idk-state", children: "No availability found." }),
1422
+ !autoAdvanceOnSelect ? /* @__PURE__ */ jsx8("div", { className: "idk-booking__actions", children: /* @__PURE__ */ jsx8(
1113
1423
  "button",
1114
1424
  {
1115
1425
  type: "button",
@@ -1121,19 +1431,19 @@ function BookingWidget({
1121
1431
  ) }) : null
1122
1432
  ] }),
1123
1433
  step === "details" && /* @__PURE__ */ jsxs4("form", { className: "idk-form", onSubmit: handleSubmit, children: [
1124
- /* @__PURE__ */ jsx7("h4", { children: "Your details" }),
1125
- bookingError ? /* @__PURE__ */ jsx7("div", { className: "idk-booking__error", children: bookingError }) : null,
1434
+ /* @__PURE__ */ jsx8("h4", { children: "Your details" }),
1435
+ bookingError ? /* @__PURE__ */ jsx8("div", { className: "idk-booking__error", children: bookingError }) : null,
1126
1436
  selectedService && selectedTime ? /* @__PURE__ */ jsxs4("div", { className: "idk-booking__summary", children: [
1127
1437
  /* @__PURE__ */ jsxs4("div", { children: [
1128
- /* @__PURE__ */ jsx7("span", { className: "idk-booking__summary-label", children: "Service" }),
1129
- /* @__PURE__ */ jsx7("p", { children: selectedService.name })
1438
+ /* @__PURE__ */ jsx8("span", { className: "idk-booking__summary-label", children: "Service" }),
1439
+ /* @__PURE__ */ jsx8("p", { children: selectedService.name })
1130
1440
  ] }),
1131
1441
  selectedStaff ? /* @__PURE__ */ jsxs4("div", { children: [
1132
- /* @__PURE__ */ jsx7("span", { className: "idk-booking__summary-label", children: "Staff" }),
1133
- /* @__PURE__ */ jsx7("p", { children: selectedStaff.name })
1442
+ /* @__PURE__ */ jsx8("span", { className: "idk-booking__summary-label", children: "Staff" }),
1443
+ /* @__PURE__ */ jsx8("p", { children: selectedStaff.name })
1134
1444
  ] }) : null,
1135
1445
  /* @__PURE__ */ jsxs4("div", { children: [
1136
- /* @__PURE__ */ jsx7("span", { className: "idk-booking__summary-label", children: "When" }),
1446
+ /* @__PURE__ */ jsx8("span", { className: "idk-booking__summary-label", children: "When" }),
1137
1447
  /* @__PURE__ */ jsxs4("p", { children: [
1138
1448
  formatDateHeading(selectedDate || ""),
1139
1449
  " \xB7 ",
@@ -1141,7 +1451,7 @@ function BookingWidget({
1141
1451
  ] })
1142
1452
  ] }),
1143
1453
  selectedService.price ? /* @__PURE__ */ jsxs4("div", { children: [
1144
- /* @__PURE__ */ jsx7("span", { className: "idk-booking__summary-label", children: "Price" }),
1454
+ /* @__PURE__ */ jsx8("span", { className: "idk-booking__summary-label", children: "Price" }),
1145
1455
  /* @__PURE__ */ jsxs4("p", { children: [
1146
1456
  "$",
1147
1457
  (selectedService.price / 100).toFixed(2)
@@ -1149,8 +1459,8 @@ function BookingWidget({
1149
1459
  ] }) : null
1150
1460
  ] }) : null,
1151
1461
  /* @__PURE__ */ jsxs4("label", { className: "idk-form__field", children: [
1152
- /* @__PURE__ */ jsx7("span", { children: "Name" }),
1153
- /* @__PURE__ */ jsx7(
1462
+ /* @__PURE__ */ jsx8("span", { children: "Name" }),
1463
+ /* @__PURE__ */ jsx8(
1154
1464
  "input",
1155
1465
  {
1156
1466
  value: details.name,
@@ -1160,8 +1470,8 @@ function BookingWidget({
1160
1470
  )
1161
1471
  ] }),
1162
1472
  /* @__PURE__ */ jsxs4("label", { className: "idk-form__field", children: [
1163
- /* @__PURE__ */ jsx7("span", { children: "Email" }),
1164
- /* @__PURE__ */ jsx7(
1473
+ /* @__PURE__ */ jsx8("span", { children: "Email" }),
1474
+ /* @__PURE__ */ jsx8(
1165
1475
  "input",
1166
1476
  {
1167
1477
  type: "email",
@@ -1172,8 +1482,8 @@ function BookingWidget({
1172
1482
  )
1173
1483
  ] }),
1174
1484
  /* @__PURE__ */ jsxs4("label", { className: "idk-form__field", children: [
1175
- /* @__PURE__ */ jsx7("span", { children: "Phone" }),
1176
- /* @__PURE__ */ jsx7(
1485
+ /* @__PURE__ */ jsx8("span", { children: "Phone" }),
1486
+ /* @__PURE__ */ jsx8(
1177
1487
  "input",
1178
1488
  {
1179
1489
  value: details.phone,
@@ -1182,8 +1492,8 @@ function BookingWidget({
1182
1492
  )
1183
1493
  ] }),
1184
1494
  /* @__PURE__ */ jsxs4("label", { className: "idk-form__field", children: [
1185
- /* @__PURE__ */ jsx7("span", { children: "Notes" }),
1186
- /* @__PURE__ */ jsx7(
1495
+ /* @__PURE__ */ jsx8("span", { children: "Notes" }),
1496
+ /* @__PURE__ */ jsx8(
1187
1497
  "textarea",
1188
1498
  {
1189
1499
  rows: 4,
@@ -1192,12 +1502,12 @@ function BookingWidget({
1192
1502
  }
1193
1503
  )
1194
1504
  ] }),
1195
- /* @__PURE__ */ jsx7("button", { type: "submit", className: "idk-button", disabled: createBooking.isPending, children: createBooking.isPending ? "Booking..." : "Confirm booking" })
1505
+ /* @__PURE__ */ jsx8("button", { type: "submit", className: "idk-button", disabled: createBooking.isPending, children: createBooking.isPending ? "Booking..." : "Confirm booking" })
1196
1506
  ] }),
1197
1507
  step === "done" && /* @__PURE__ */ jsxs4("div", { className: "idk-booking__done", children: [
1198
- /* @__PURE__ */ jsx7("div", { className: "idk-booking__done-title", children: "Booking confirmed!" }),
1199
- /* @__PURE__ */ jsx7("p", { className: "idk-booking__done-text", children: "We'll send a confirmation email shortly with your appointment details." }),
1200
- /* @__PURE__ */ jsx7(
1508
+ /* @__PURE__ */ jsx8("div", { className: "idk-booking__done-title", children: "Booking confirmed!" }),
1509
+ /* @__PURE__ */ jsx8("p", { className: "idk-booking__done-text", children: "We'll send a confirmation email shortly with your appointment details." }),
1510
+ /* @__PURE__ */ jsx8(
1201
1511
  "button",
1202
1512
  {
1203
1513
  type: "button",
@@ -1220,7 +1530,7 @@ function BookingWidget({
1220
1530
 
1221
1531
  // src/components/AvailabilityPicker.tsx
1222
1532
  import { useState as useState4 } from "react";
1223
- import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
1533
+ import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
1224
1534
  function AvailabilityPicker({
1225
1535
  serviceId,
1226
1536
  staffId,
@@ -1238,15 +1548,15 @@ function AvailabilityPicker({
1238
1548
  days
1239
1549
  });
1240
1550
  if (isLoading) {
1241
- return /* @__PURE__ */ jsx8("div", { className: "idk-state", children: "Loading availability..." });
1551
+ return /* @__PURE__ */ jsx9("div", { className: "idk-state", children: "Loading availability..." });
1242
1552
  }
1243
1553
  if (!data?.dates?.length) {
1244
- return /* @__PURE__ */ jsx8("div", { className: "idk-state", children: "No availability found." });
1554
+ return /* @__PURE__ */ jsx9("div", { className: "idk-state", children: "No availability found." });
1245
1555
  }
1246
1556
  const activeDate = selectedDate || data.dates[0]?.date;
1247
1557
  const activeSlots = data.dates.find((entry) => entry.date === activeDate)?.slots || [];
1248
1558
  return /* @__PURE__ */ jsxs5("div", { className: ["idk-availability", className].filter(Boolean).join(" "), children: [
1249
- /* @__PURE__ */ jsx8("div", { className: "idk-availability__dates", children: data.dates.map((entry) => /* @__PURE__ */ jsx8(
1559
+ /* @__PURE__ */ jsx9("div", { className: "idk-availability__dates", children: data.dates.map((entry) => /* @__PURE__ */ jsx9(
1250
1560
  "button",
1251
1561
  {
1252
1562
  type: "button",
@@ -1259,7 +1569,7 @@ function AvailabilityPicker({
1259
1569
  },
1260
1570
  entry.date
1261
1571
  )) }),
1262
- /* @__PURE__ */ jsx8("div", { className: "idk-availability__slots", children: activeSlots.filter((slot) => slot.available).length === 0 ? /* @__PURE__ */ jsx8("div", { className: "idk-state", children: "No slots available." }) : activeSlots.filter((slot) => slot.available).map((slot) => /* @__PURE__ */ jsx8(
1572
+ /* @__PURE__ */ jsx9("div", { className: "idk-availability__slots", children: activeSlots.filter((slot) => slot.available).length === 0 ? /* @__PURE__ */ jsx9("div", { className: "idk-state", children: "No slots available." }) : activeSlots.filter((slot) => slot.available).map((slot) => /* @__PURE__ */ jsx9(
1263
1573
  "button",
1264
1574
  {
1265
1575
  type: "button",
@@ -1282,21 +1592,21 @@ function AvailabilityPicker({
1282
1592
  }
1283
1593
 
1284
1594
  // src/components/ServicePicker.tsx
1285
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
1595
+ import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
1286
1596
  function ServicePicker({
1287
1597
  services,
1288
1598
  selectedId,
1289
1599
  onSelect,
1290
1600
  className
1291
1601
  }) {
1292
- return /* @__PURE__ */ jsx9("div", { className: ["idk-picker", className].filter(Boolean).join(" "), children: services.map((service) => /* @__PURE__ */ jsxs6(
1602
+ return /* @__PURE__ */ jsx10("div", { className: ["idk-picker", className].filter(Boolean).join(" "), children: services.map((service) => /* @__PURE__ */ jsxs6(
1293
1603
  "button",
1294
1604
  {
1295
1605
  type: "button",
1296
1606
  className: selectedId === service.id ? "is-active" : void 0,
1297
1607
  onClick: () => onSelect?.(service),
1298
1608
  children: [
1299
- /* @__PURE__ */ jsx9("span", { children: service.name }),
1609
+ /* @__PURE__ */ jsx10("span", { children: service.name }),
1300
1610
  /* @__PURE__ */ jsxs6("small", { children: [
1301
1611
  service.duration,
1302
1612
  " min"
@@ -1308,22 +1618,22 @@ function ServicePicker({
1308
1618
  }
1309
1619
 
1310
1620
  // src/components/StaffPicker.tsx
1311
- import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
1621
+ import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
1312
1622
  function StaffPicker({
1313
1623
  staff,
1314
1624
  selectedId,
1315
1625
  onSelect,
1316
1626
  className
1317
1627
  }) {
1318
- return /* @__PURE__ */ jsx10("div", { className: ["idk-picker", className].filter(Boolean).join(" "), children: staff.map((member) => /* @__PURE__ */ jsxs7(
1628
+ return /* @__PURE__ */ jsx11("div", { className: ["idk-picker", className].filter(Boolean).join(" "), children: staff.map((member) => /* @__PURE__ */ jsxs7(
1319
1629
  "button",
1320
1630
  {
1321
1631
  type: "button",
1322
1632
  className: selectedId === member.id ? "is-active" : void 0,
1323
1633
  onClick: () => onSelect?.(member),
1324
1634
  children: [
1325
- /* @__PURE__ */ jsx10("span", { children: member.name }),
1326
- /* @__PURE__ */ jsx10("small", { children: member.role || "Staff" })
1635
+ /* @__PURE__ */ jsx11("span", { children: member.name }),
1636
+ /* @__PURE__ */ jsx11("small", { children: member.role || "Staff" })
1327
1637
  ]
1328
1638
  },
1329
1639
  member.id
@@ -1331,14 +1641,14 @@ function StaffPicker({
1331
1641
  }
1332
1642
 
1333
1643
  // src/components/DatePicker.tsx
1334
- import { jsx as jsx11 } from "react/jsx-runtime";
1644
+ import { jsx as jsx12 } from "react/jsx-runtime";
1335
1645
  function DatePicker({
1336
1646
  dates,
1337
1647
  selectedDate,
1338
1648
  onSelect,
1339
1649
  className
1340
1650
  }) {
1341
- return /* @__PURE__ */ jsx11("div", { className: ["idk-picker", className].filter(Boolean).join(" "), children: dates.map((date) => /* @__PURE__ */ jsx11(
1651
+ return /* @__PURE__ */ jsx12("div", { className: ["idk-picker", className].filter(Boolean).join(" "), children: dates.map((date) => /* @__PURE__ */ jsx12(
1342
1652
  "button",
1343
1653
  {
1344
1654
  type: "button",
@@ -1351,14 +1661,14 @@ function DatePicker({
1351
1661
  }
1352
1662
 
1353
1663
  // src/components/TimePicker.tsx
1354
- import { jsx as jsx12 } from "react/jsx-runtime";
1664
+ import { jsx as jsx13 } from "react/jsx-runtime";
1355
1665
  function TimePicker({
1356
1666
  slots,
1357
1667
  selectedTime,
1358
1668
  onSelect,
1359
1669
  className
1360
1670
  }) {
1361
- return /* @__PURE__ */ jsx12("div", { className: ["idk-picker", className].filter(Boolean).join(" "), children: slots.map((slot) => /* @__PURE__ */ jsx12(
1671
+ return /* @__PURE__ */ jsx13("div", { className: ["idk-picker", className].filter(Boolean).join(" "), children: slots.map((slot) => /* @__PURE__ */ jsx13(
1362
1672
  "button",
1363
1673
  {
1364
1674
  type: "button",