@idkwebsites/components 0.1.14 → 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
@@ -945,6 +945,35 @@ function BookingWidget({
945
945
  if (!maxAdvanceMonths || maxAdvanceMonths <= 0) return null;
946
946
  return new Date(todayDate.getFullYear(), todayDate.getMonth() + maxAdvanceMonths - 1, 1);
947
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]);
948
977
  const handlePrevDates = () => {
949
978
  if (availabilityStartDate <= todayString) return;
950
979
  setAvailabilityStartDate((prev) => addDays(prev, -availabilityDays));
@@ -984,6 +1013,15 @@ function BookingWidget({
984
1013
  setSelectedEndTime(null);
985
1014
  setBookingError(null);
986
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
+ };
987
1025
  (0, import_react7.useEffect)(() => {
988
1026
  if (step !== "time") return;
989
1027
  if (!availability.data?.dates?.length) return;
@@ -1316,7 +1354,39 @@ function BookingWidget({
1316
1354
  calendarVariant === "compact" ? "idk-calendar--compact" : ""
1317
1355
  ].filter(Boolean).join(" "),
1318
1356
  children: [
1319
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "idk-calendar__header", 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: [
1320
1390
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1321
1391
  "button",
1322
1392
  {
@@ -1324,7 +1394,7 @@ function BookingWidget({
1324
1394
  className: "idk-button idk-button--ghost",
1325
1395
  onClick: handlePrevMonth,
1326
1396
  disabled: calendarMonth <= getMonthStart(todayDate),
1327
- children: "Previous"
1397
+ children: "Prev"
1328
1398
  }
1329
1399
  ),
1330
1400
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-calendar__title", children: new Intl.DateTimeFormat("en-US", {
@@ -1341,12 +1411,10 @@ function BookingWidget({
1341
1411
  children: "Next"
1342
1412
  }
1343
1413
  )
1344
- ] }),
1414
+ ] }) }),
1345
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)) }),
1346
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-calendar__grid", children: getMonthDays(calendarMonth).map((day) => {
1347
- const entry = availability.data?.dates?.find(
1348
- (item) => item.date === day.date
1349
- );
1416
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "idk-calendar__grid", children: calendarDays.map((day) => {
1417
+ const entry = availabilityByDate.get(day.date);
1350
1418
  const hasAvailable = entry?.slots?.some((slot) => slot.available) ?? false;
1351
1419
  const dateValue = parseDateOnly(day.date);
1352
1420
  const isPast = dateValue ? dateValue < todayDate : false;
@@ -1377,12 +1445,16 @@ function BookingWidget({
1377
1445
  },
1378
1446
  children: [
1379
1447
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: day.date.split("-")[2] }),
1380
- showFullyBookedLabel && isBlocked && day.isCurrentMonth ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "idk-calendar__label", children: calendarVariant === "compact" ? "Full" : "Fully booked" }) : null
1448
+ showFullyBookedLabel && isBlocked && day.isCurrentMonth ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "idk-calendar__label", children: calendarVariant === "compact" ? "\u2022" : "Fully booked" }) : null
1381
1449
  ]
1382
1450
  },
1383
1451
  day.date
1384
1452
  );
1385
- }) })
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
1386
1458
  ]
1387
1459
  }
1388
1460
  ) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [