@ecohouse/ui 0.1.52 → 0.1.53

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.d.cts CHANGED
@@ -958,6 +958,15 @@ type DatePickerBaseProps = Omit<ViewProps, "style" | "children"> & {
958
958
  closeOnSelect?: boolean;
959
959
  minDate?: Date;
960
960
  maxDate?: Date;
961
+ /** Calendar days that cannot be selected, such as dates already booked. */
962
+ unavailableDates?: readonly Date[];
963
+ /**
964
+ * When true, unavailable days cannot be selected and a range cannot include them.
965
+ * Defaults to false so booked days can stay visual-only.
966
+ */
967
+ blockUnavailableDates?: boolean;
968
+ /** Accessibility label for an unavailable day. */
969
+ unavailableDateLabel?: string;
961
970
  /** First visible month when the calendar opens; defaults to the selected value's month, else today. */
962
971
  defaultVisibleMonth?: Date;
963
972
  /** Monday-first full month names. Defaults to Armenian. */
package/dist/index.d.ts CHANGED
@@ -958,6 +958,15 @@ type DatePickerBaseProps = Omit<ViewProps, "style" | "children"> & {
958
958
  closeOnSelect?: boolean;
959
959
  minDate?: Date;
960
960
  maxDate?: Date;
961
+ /** Calendar days that cannot be selected, such as dates already booked. */
962
+ unavailableDates?: readonly Date[];
963
+ /**
964
+ * When true, unavailable days cannot be selected and a range cannot include them.
965
+ * Defaults to false so booked days can stay visual-only.
966
+ */
967
+ blockUnavailableDates?: boolean;
968
+ /** Accessibility label for an unavailable day. */
969
+ unavailableDateLabel?: string;
961
970
  /** First visible month when the calendar opens; defaults to the selected value's month, else today. */
962
971
  defaultVisibleMonth?: Date;
963
972
  /** Monday-first full month names. Defaults to Armenian. */
package/dist/index.js CHANGED
@@ -34240,6 +34240,16 @@ var DEFAULT_MONTH_NAMES = [
34240
34240
  "\u0534\u0565\u056F\u057F\u0565\u0574\u0562\u0565\u0580"
34241
34241
  ];
34242
34242
  var DEFAULT_WEEKDAY_LABELS = ["\u0535\u0550", "\u0535\u0554", "\u0549\u0550", "\u0540\u0546", "\u0548\u0552\u0550", "\u0547\u0532", "\u053F\u0550"];
34243
+ function rangeIncludesUnavailable(start, end, isUnavailable) {
34244
+ const cursor = startOfDay(start);
34245
+ const last = startOfDay(end);
34246
+ const step = isBefore(last, cursor) ? -1 : 1;
34247
+ while (true) {
34248
+ if (isUnavailable(cursor)) return true;
34249
+ if (isSameDay(cursor, last)) return false;
34250
+ cursor.setDate(cursor.getDate() + step);
34251
+ }
34252
+ }
34243
34253
  var EMPTY_RANGE = { start: null, end: null };
34244
34254
  var DEFAULT_WIDTH = 320;
34245
34255
  var DEFAULT_MENU_HEIGHT = 388;
@@ -34293,6 +34303,9 @@ var DatePicker = forwardRef(
34293
34303
  closeOnSelect = true,
34294
34304
  minDate,
34295
34305
  maxDate,
34306
+ unavailableDates,
34307
+ unavailableDateLabel = "Booked",
34308
+ blockUnavailableDates = false,
34296
34309
  defaultVisibleMonth,
34297
34310
  monthNames = DEFAULT_MONTH_NAMES,
34298
34311
  weekdayLabels = DEFAULT_WEEKDAY_LABELS,
@@ -34311,6 +34324,17 @@ var DatePicker = forwardRef(
34311
34324
  onValueChange: _onValueChange,
34312
34325
  ...rest
34313
34326
  } = props;
34327
+ const unavailableDayKeys = useMemo(() => {
34328
+ const keys = /* @__PURE__ */ new Set();
34329
+ for (const date of unavailableDates ?? []) {
34330
+ keys.add(startOfDay(date).getTime());
34331
+ }
34332
+ return keys;
34333
+ }, [unavailableDates]);
34334
+ const isUnavailable = useCallback(
34335
+ (day) => unavailableDayKeys.has(startOfDay(day).getTime()),
34336
+ [unavailableDayKeys]
34337
+ );
34314
34338
  const isRange = props.range === true;
34315
34339
  const usesRangeTrigger = isRange && variant !== "default";
34316
34340
  const formatValue = formatValueProp ?? (usesRangeTrigger ? (date) => formatDateDayShortMonth(date, monthNames) : formatDate);
@@ -34413,6 +34437,7 @@ var DatePicker = forwardRef(
34413
34437
  const handleDayPress = useCallback(
34414
34438
  (day) => {
34415
34439
  if (disabled || isDateDisabled(day, minDate, maxDate)) return;
34440
+ if (blockUnavailableDates && isUnavailable(day)) return;
34416
34441
  const picked = startOfDay(day);
34417
34442
  if (!isRange) {
34418
34443
  if (!isValueControlled) setUncontrolledSingle(picked);
@@ -34423,14 +34448,19 @@ var DatePicker = forwardRef(
34423
34448
  const { start, end } = rangeValue;
34424
34449
  const startingNewRange = !start || start && end;
34425
34450
  const nextRange = startingNewRange ? { start: picked, end: null } : isBefore(picked, start) ? { start: picked, end: null } : { start, end: picked };
34451
+ if (blockUnavailableDates && nextRange.start && nextRange.end && rangeIncludesUnavailable(nextRange.start, nextRange.end, isUnavailable)) {
34452
+ return;
34453
+ }
34426
34454
  if (!isValueControlled) setUncontrolledRange(nextRange);
34427
34455
  props.onValueChange?.(nextRange);
34428
34456
  if (closeOnSelect && nextRange.start && nextRange.end) setOpen(false);
34429
34457
  },
34430
34458
  [
34459
+ blockUnavailableDates,
34431
34460
  closeOnSelect,
34432
34461
  disabled,
34433
34462
  isRange,
34463
+ isUnavailable,
34434
34464
  isValueControlled,
34435
34465
  maxDate,
34436
34466
  minDate,
@@ -34509,7 +34539,8 @@ var DatePicker = forwardRef(
34509
34539
  styles26.menu,
34510
34540
  usesRangeTrigger && styles26.rangeMenu,
34511
34541
  hideTrigger ? styles26.menuInline : menuAlignEnd ? styles26.menuAlignEnd : styles26.menuAlignStart,
34512
- calendarStyle
34542
+ calendarStyle,
34543
+ styles26.menuFitContent
34513
34544
  ],
34514
34545
  children: [
34515
34546
  /* @__PURE__ */ jsxs(View, { style: styles26.calendarHeader, children: [
@@ -34541,7 +34572,7 @@ var DatePicker = forwardRef(
34541
34572
  }
34542
34573
  )
34543
34574
  ] }),
34544
- /* @__PURE__ */ jsxs(View, { children: [
34575
+ /* @__PURE__ */ jsxs(View, { style: styles26.calendarGrid, children: [
34545
34576
  /* @__PURE__ */ jsx(View, { style: styles26.weekdayRow, children: weekdayLabels.map((weekdayLabel, index) => /* @__PURE__ */ jsx(View, { style: styles26.weekdayCell, children: /* @__PURE__ */ jsx(Text, { style: styles26.weekdayText, children: weekdayLabel }) }, `${weekdayLabel}-${index}`)) }),
34546
34577
  weeks.map((week, weekIndex) => {
34547
34578
  let rangeHighlightStyle = null;
@@ -34596,24 +34627,26 @@ var DatePicker = forwardRef(
34596
34627
  const isRangeStart = isRange && isSameDay(day, rangeValue.start);
34597
34628
  const isRangeEnd = isRange && isSameDay(day, rangeValue.end);
34598
34629
  const isSelectedEndpoint = isSelectedSingle || isRangeStart || isRangeEnd;
34630
+ const dayUnavailable = isUnavailable(day);
34631
+ const dayBlocked = blockUnavailableDates && dayUnavailable;
34599
34632
  const dayDisabled = disabled || isDateDisabled(day, minDate, maxDate);
34600
34633
  const dayKey = startOfDay(day).getTime();
34601
- const isHovered = !dayDisabled && !isSelectedEndpoint && hoveredDayKey === dayKey;
34634
+ const isHovered = !dayDisabled && !dayBlocked && !isSelectedEndpoint && hoveredDayKey === dayKey;
34602
34635
  const dayTextColor = isSelectedEndpoint ? colors.white : dayDisabled ? colors.grey400 : isToday ? colors.primary : !inCurrentMonth ? colors.grey300 : colors.white;
34603
34636
  return /* @__PURE__ */ jsxs(
34604
34637
  Pressable,
34605
34638
  {
34606
34639
  onPress: () => handleDayPress(day),
34607
- disabled: dayDisabled,
34640
+ disabled: dayDisabled || dayBlocked,
34608
34641
  onHoverIn: () => setHoveredDayKey(dayKey),
34609
34642
  onHoverOut: () => setHoveredDayKey((current) => current === dayKey ? null : current),
34610
34643
  onPressIn: () => setHoveredDayKey(dayKey),
34611
34644
  onPressOut: () => setHoveredDayKey((current) => current === dayKey ? null : current),
34612
34645
  style: styles26.dayCellWrap,
34613
34646
  accessibilityRole: "button",
34614
- accessibilityLabel: formatValue(day),
34647
+ accessibilityLabel: dayUnavailable ? `${formatValue(day)}, ${unavailableDateLabel}` : formatValue(day),
34615
34648
  accessibilityState: {
34616
- disabled: dayDisabled,
34649
+ disabled: dayDisabled || dayBlocked,
34617
34650
  selected: isSelectedEndpoint
34618
34651
  },
34619
34652
  children: [
@@ -34623,9 +34656,20 @@ var DatePicker = forwardRef(
34623
34656
  style: [
34624
34657
  styles26.dayCircle,
34625
34658
  isSelectedEndpoint && styles26.dayCircleSelected,
34659
+ dayUnavailable && styles26.dayCircleBooked,
34626
34660
  isHovered && styles26.dayCircleHovered
34627
34661
  ],
34628
- children: /* @__PURE__ */ jsx(Text, { style: [styles26.dayText, { color: dayTextColor }], children: day.getDate() })
34662
+ children: /* @__PURE__ */ jsx(
34663
+ Text,
34664
+ {
34665
+ style: [
34666
+ styles26.dayText,
34667
+ { color: dayTextColor },
34668
+ dayUnavailable && styles26.dayTextBooked
34669
+ ],
34670
+ children: day.getDate()
34671
+ }
34672
+ )
34629
34673
  }
34630
34674
  ),
34631
34675
  isToday && !isSelectedEndpoint ? /* @__PURE__ */ jsx(View, { style: styles26.todayDot }) : null
@@ -34763,7 +34807,7 @@ var styles26 = StyleSheet.create({
34763
34807
  menu: {
34764
34808
  position: "absolute",
34765
34809
  top: "100%",
34766
- width: DEFAULT_WIDTH,
34810
+ alignSelf: "flex-start",
34767
34811
  height: DEFAULT_MENU_HEIGHT,
34768
34812
  marginTop: 8,
34769
34813
  zIndex: 10,
@@ -34797,10 +34841,26 @@ var styles26 = StyleSheet.create({
34797
34841
  right: "auto",
34798
34842
  marginTop: 0
34799
34843
  },
34800
- rangeMenu: {
34801
- width: RANGE_TRIGGER_WIDTH
34844
+ rangeMenu: {},
34845
+ menuFitContent: {
34846
+ width: MENU_CONTENT_WIDTH + MENU_PADDING * 2,
34847
+ maxWidth: MENU_CONTENT_WIDTH + MENU_PADDING * 2,
34848
+ alignSelf: "flex-start",
34849
+ alignItems: "flex-start",
34850
+ ...Platform.select({
34851
+ web: {
34852
+ width: "fit-content",
34853
+ maxWidth: "fit-content"
34854
+ },
34855
+ default: {}
34856
+ })
34857
+ },
34858
+ calendarGrid: {
34859
+ width: MENU_CONTENT_WIDTH,
34860
+ alignSelf: "flex-start"
34802
34861
  },
34803
34862
  calendarHeader: {
34863
+ width: MENU_CONTENT_WIDTH,
34804
34864
  height: HEADER_HEIGHT3,
34805
34865
  paddingTop: 8,
34806
34866
  paddingBottom: 8,
@@ -34834,9 +34894,8 @@ var styles26 = StyleSheet.create({
34834
34894
  weekdayCell: {
34835
34895
  width: DAY_CELL_WIDTH,
34836
34896
  height: WEEKDAY_ROW_HEIGHT,
34837
- flexGrow: 1,
34838
- flexShrink: 1,
34839
- flexBasis: 0,
34897
+ flexGrow: 0,
34898
+ flexShrink: 0,
34840
34899
  alignItems: "center",
34841
34900
  justifyContent: "center"
34842
34901
  },
@@ -34864,9 +34923,8 @@ var styles26 = StyleSheet.create({
34864
34923
  dayCellWrap: {
34865
34924
  width: DAY_CELL_WIDTH,
34866
34925
  height: DAY_CELL_HEIGHT,
34867
- flexGrow: 1,
34868
- flexShrink: 1,
34869
- flexBasis: 0,
34926
+ flexGrow: 0,
34927
+ flexShrink: 0,
34870
34928
  alignItems: "center",
34871
34929
  justifyContent: "center",
34872
34930
  opacity: 1
@@ -34883,6 +34941,12 @@ var styles26 = StyleSheet.create({
34883
34941
  dayCircleSelected: {
34884
34942
  backgroundColor: colors.primary
34885
34943
  },
34944
+ dayCircleBooked: {
34945
+ backgroundColor: colors.grey700
34946
+ },
34947
+ dayTextBooked: {
34948
+ textDecorationLine: "line-through"
34949
+ },
34886
34950
  dayCircleHovered: {
34887
34951
  backgroundColor: colors.grey600
34888
34952
  },