@ostack.tech/ui 0.11.1 → 0.11.2

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/ostack-ui.js CHANGED
@@ -2,7 +2,7 @@ import * as React from "react";
2
2
  import { forwardRef, createContext, useContext, useCallback, useRef, useEffect, useId, useMemo, useState, memo, Fragment as Fragment$1, isValidElement, cloneElement, Children, useImperativeHandle, startTransition, useLayoutEffect as useLayoutEffect$2, useSyncExternalStore, useDeferredValue } from "react";
3
3
  import { parseKeybinding, tinykeys } from "tinykeys";
4
4
  import fromExponential from "from-exponential";
5
- import { isValid, isDate, addMonths, isAfter, isBefore, startOfMonth, setMonth, getYear, setYear, startOfYear, format, isSameYear, getMonth, max, min, isSameDay, lastDayOfMonth, isEqual, parseISO, parse, isWithinInterval } from "date-fns";
5
+ import { isValid, isDate, addMonths, isAfter, isBefore, startOfMonth, setMonth, getYear, setYear, startOfYear, format, isSameYear, getMonth, max, min, endOfMonth, isWithinInterval, lastDayOfMonth, isSameDay, isEqual, parseISO, parse } from "date-fns";
6
6
  import { createStore, useStore as useStore$1, create } from "zustand";
7
7
  import { shallow } from "zustand/shallow";
8
8
  import { numericFormatter, removeNumericFormat, NumericFormat } from "react-number-format";
@@ -8787,18 +8787,24 @@ const CalendarHeader = memo(function CalendarHeader2({
8787
8787
  }
8788
8788
  return months2;
8789
8789
  }, []);
8790
+ const displayYear = getYear(displayDate);
8791
+ const curYear = getYear(/* @__PURE__ */ new Date());
8792
+ const nearestCentury = curYear + 50 - (curYear + 50) % 100;
8793
+ const minYear = minAllowedDate ? getYear(minAllowedDate) : Math.min(displayYear, nearestCentury - 100);
8794
+ const maxYear = maxAllowedDate ? getYear(maxAllowedDate) : Math.max(displayYear, nearestCentury + 99);
8790
8795
  const yearDates = useMemo(() => {
8791
- const displayYear = getYear(displayDate);
8792
- const curYear = getYear(/* @__PURE__ */ new Date());
8793
- const nearestCentury = curYear + 50 - (curYear + 50) % 100;
8794
- const minYear = minAllowedDate ? getYear(minAllowedDate) : Math.min(displayYear, nearestCentury - 100);
8795
- const maxYear = maxAllowedDate ? getYear(maxAllowedDate) : Math.max(displayYear, nearestCentury + 99);
8796
8796
  const years = [];
8797
+ if (displayYear < minYear) {
8798
+ years.push(setYear(startOfYear(/* @__PURE__ */ new Date()), displayYear));
8799
+ }
8797
8800
  for (let year = minYear; year <= maxYear; year++) {
8798
8801
  years.push(setYear(startOfYear(/* @__PURE__ */ new Date()), year));
8799
8802
  }
8803
+ if (displayYear > maxYear) {
8804
+ years.push(setYear(startOfYear(/* @__PURE__ */ new Date()), displayYear));
8805
+ }
8800
8806
  return years;
8801
- }, [displayDate, minAllowedDate, maxAllowedDate]);
8807
+ }, [displayYear, minYear, maxYear]);
8802
8808
  const handleMonthChange = useCallback(
8803
8809
  (value) => goToMonth(
8804
8810
  addMonths(
@@ -8868,20 +8874,33 @@ const CalendarHeader = memo(function CalendarHeader2({
8868
8874
  }
8869
8875
  );
8870
8876
  const monthOptions = useMemo(
8871
- () => monthDates.map((monthDate) => /* @__PURE__ */ jsx(
8872
- Option,
8873
- {
8874
- value: getMonth(monthDate),
8875
- disabled: minAllowedDate && maxAllowedDate && isSameYear(minAllowedDate, maxAllowedDate) && (getMonth(monthDate) < getMonth(minAllowedDate) || getMonth(monthDate) > getMonth(maxAllowedDate)),
8876
- children: format(monthDate, MONTH_FORMAT, { locale: locale7 })
8877
- },
8878
- getMonth(monthDate)
8879
- )),
8877
+ () => monthDates.map((monthDate) => {
8878
+ return /* @__PURE__ */ jsx(
8879
+ Option,
8880
+ {
8881
+ value: getMonth(monthDate),
8882
+ disabled: minAllowedDate && maxAllowedDate && isSameYear(minAllowedDate, maxAllowedDate) && (getMonth(monthDate) < getMonth(minAllowedDate) || getMonth(monthDate) > getMonth(maxAllowedDate)),
8883
+ children: format(monthDate, MONTH_FORMAT, { locale: locale7 })
8884
+ },
8885
+ getMonth(monthDate)
8886
+ );
8887
+ }),
8880
8888
  [locale7, maxAllowedDate, minAllowedDate, monthDates]
8881
8889
  );
8882
8890
  const yearOptions = useMemo(
8883
- () => yearDates.map((yearDate) => /* @__PURE__ */ jsx(Option, { value: getYear(yearDate), children: format(yearDate, YEAR_FORMAT, { locale: locale7 }) }, getYear(yearDate))),
8884
- [locale7, yearDates]
8891
+ () => yearDates.map((yearDate) => {
8892
+ const year = getYear(yearDate);
8893
+ return /* @__PURE__ */ jsx(
8894
+ Option,
8895
+ {
8896
+ value: year,
8897
+ disabled: year < minYear || year > maxYear,
8898
+ children: format(yearDate, YEAR_FORMAT, { locale: locale7 })
8899
+ },
8900
+ year
8901
+ );
8902
+ }),
8903
+ [locale7, maxYear, minYear, yearDates]
8885
8904
  );
8886
8905
  return /* @__PURE__ */ jsxs(
8887
8906
  "header",
@@ -8981,6 +9000,7 @@ function Calendar({
8981
9000
  disableNavigation,
8982
9001
  disabled,
8983
9002
  modifiers,
9003
+ apiRef,
8984
9004
  headerProps,
8985
9005
  headerLabelProps,
8986
9006
  previousButtonProps,
@@ -9038,15 +9058,16 @@ function Calendar({
9038
9058
  return normalizedValue === null ? { start: null, end: null } : isDate(normalizedValue) ? { start: normalizedValue, end: null } : Array.isArray(normalizedValue) ? normalizedValue.length === 0 ? { start: null, end: null } : { start: min(normalizedValue), end: max(normalizedValue) } : normalizedValue;
9039
9059
  }
9040
9060
  }, [normalizedValue, selectionMode]);
9041
- const firstSelectedDate = selectionMode === "none" ? void 0 : selectionMode === "single" ? value ?? void 0 : selectionMode === "multiple" ? value[0] : value.start ?? value.end ?? void 0;
9042
9061
  const [focusedRange, setFocusedRange] = useState({
9043
9062
  start: null,
9044
9063
  end: null
9045
9064
  });
9065
+ minMonth = useMemo(() => toValidDate(minMonth), [minMonth]);
9066
+ maxMonth = useMemo(() => toValidDate(maxMonth), [maxMonth]);
9046
9067
  const minAllowedDate = useMemo(() => {
9047
9068
  const minDates = [
9048
9069
  toValidDate(minDate),
9049
- toValidDate(minMonth),
9070
+ minMonth && startOfMonth(minMonth),
9050
9071
  minYear != null && new Date(minYear, 0, 1)
9051
9072
  ].filter((d) => d);
9052
9073
  return minDates.length > 0 ? max(minDates) : void 0;
@@ -9054,16 +9075,70 @@ function Calendar({
9054
9075
  const maxAllowedDate = useMemo(() => {
9055
9076
  const maxDates = [
9056
9077
  toValidDate(maxDate),
9057
- toValidDate(maxMonth),
9078
+ maxMonth && endOfMonth(maxMonth),
9058
9079
  maxYear != null && new Date(maxYear, 11, 31)
9059
9080
  ].filter((d) => d);
9060
9081
  return maxDates.length > 0 ? min(maxDates) : void 0;
9061
9082
  }, [maxDate, maxMonth, maxYear]);
9062
- const curMonth = startOfMonth(/* @__PURE__ */ new Date());
9063
- const [month, setMonth2] = useControllableState(
9064
- defaultMonth ?? firstSelectedDate ?? ((!minAllowedDate || !isBefore(curMonth, minAllowedDate)) && (!maxAllowedDate || !isAfter(curMonth, maxAllowedDate)) ? curMonth : minAllowedDate ?? maxAllowedDate ?? curMonth),
9083
+ const curDateStr = (/* @__PURE__ */ new Date()).toISOString();
9084
+ const curMonth = useMemo(
9085
+ () => startOfMonth(new Date(curDateStr)),
9086
+ [curDateStr]
9087
+ );
9088
+ const initialMonth = useMemo(() => {
9089
+ if (controlledMonth !== void 0) {
9090
+ return controlledMonth;
9091
+ }
9092
+ if (defaultMonth !== void 0) {
9093
+ return defaultMonth;
9094
+ }
9095
+ const selectedMonth = selectionMode === "none" ? null : selectionMode === "single" ? value : selectionMode === "multiple" ? value[0] : selectionMode === "range-end" ? value.end ?? value.start : value.start ?? value.end;
9096
+ if (selectedMonth != null) {
9097
+ return selectedMonth;
9098
+ }
9099
+ const minAllowedMonth = minAllowedDate && startOfMonth(minAllowedDate);
9100
+ const maxAllowedMonth = maxAllowedDate && startOfMonth(maxAllowedDate);
9101
+ return (!minAllowedMonth || !isBefore(curMonth, minAllowedMonth)) && (!maxAllowedMonth || !isAfter(curMonth, maxAllowedMonth)) ? curMonth : minAllowedMonth ?? maxAllowedMonth ?? curMonth;
9102
+ }, [
9103
+ controlledMonth,
9104
+ curMonth,
9105
+ defaultMonth,
9106
+ maxAllowedDate,
9107
+ minAllowedDate,
9108
+ selectionMode,
9109
+ value
9110
+ ]);
9111
+ const [unnormalizedMonth, setMonth2] = useControllableState(
9112
+ initialMonth,
9065
9113
  controlledMonth
9066
9114
  );
9115
+ const month = useMemo(
9116
+ () => toValidDate(unnormalizedMonth) ?? curMonth,
9117
+ [curMonth, unnormalizedMonth]
9118
+ );
9119
+ const latest = useLatestValues({ value, month, numberOfMonths });
9120
+ useImperativeHandle(
9121
+ apiRef,
9122
+ () => ({
9123
+ getValue: () => latest.value,
9124
+ setValue,
9125
+ getMonth: () => latest.month,
9126
+ setMonth: setMonth2,
9127
+ isVisible: (date) => {
9128
+ const validDate = toValidDate(date);
9129
+ if (!validDate) {
9130
+ throw new Error(`Invalid date argument: ${date.toString()}`);
9131
+ }
9132
+ return isWithinInterval(validDate, {
9133
+ start: latest.month,
9134
+ end: lastDayOfMonth(
9135
+ addMonths(latest.month, (latest.numberOfMonths ?? 1) - 1)
9136
+ )
9137
+ });
9138
+ }
9139
+ }),
9140
+ [latest, setMonth2, setValue]
9141
+ );
9067
9142
  const handleMonthChange = useCallback(
9068
9143
  (date) => {
9069
9144
  onMonthChange?.(date);
@@ -9117,7 +9192,7 @@ function Calendar({
9117
9192
  }
9118
9193
  }
9119
9194
  if (modifiers2.outside) {
9120
- const firstDay = startOfMonth(month);
9195
+ const firstDay = startOfMonth(unnormalizedMonth);
9121
9196
  const lastDay = lastDayOfMonth(addMonths(firstDay, numberOfMonths - 1));
9122
9197
  if (isBefore(date, firstDay)) {
9123
9198
  handleMonthChange(
@@ -9132,7 +9207,7 @@ function Calendar({
9132
9207
  },
9133
9208
  [
9134
9209
  handleMonthChange,
9135
- month,
9210
+ unnormalizedMonth,
9136
9211
  numberOfMonths,
9137
9212
  onDayClick,
9138
9213
  onValueChange,
@@ -9225,7 +9300,6 @@ function Calendar({
9225
9300
  locale: locale7.dayPickerLocale,
9226
9301
  required,
9227
9302
  disabled: composedDisabled,
9228
- selected: firstSelectedDate,
9229
9303
  components: {
9230
9304
  MonthCaption: CalendarHeader,
9231
9305
  MonthGrid: CalendarMonthGrid,
@@ -9698,6 +9772,7 @@ const DateInput = forwardRef(
9698
9772
  open: false,
9699
9773
  modal: false
9700
9774
  });
9775
+ const calendarApiRef = useRef(null);
9701
9776
  const inputRef = useRef(null);
9702
9777
  const clearButtonRef = useRef(null);
9703
9778
  const addonButtonRef = useRef(null);
@@ -9713,60 +9788,27 @@ const DateInput = forwardRef(
9713
9788
  },
9714
9789
  [onPopoverOpenChange, popoverState.open]
9715
9790
  );
9716
- const monthToDisplay = useCallback(
9717
- () => startOfMonth(calendarProps?.defaultMonth ?? dateValue ?? /* @__PURE__ */ new Date()),
9718
- [calendarProps?.defaultMonth, dateValue]
9719
- );
9720
- const [month, setMonth2] = useControllableState(
9721
- () => monthToDisplay(),
9722
- calendarProps?.month
9723
- );
9724
- const dateIsVisible = useCallback(
9725
- (date) => isWithinInterval(date, {
9726
- start: month,
9727
- end: lastDayOfMonth(
9728
- addMonths(month, (calendarProps?.numberOfMonths ?? 1) - 1)
9729
- )
9730
- }),
9731
- [calendarProps?.numberOfMonths, month]
9732
- );
9733
- const handleMonthChange = combineEventHandlers(
9734
- calendarProps?.onMonthChange,
9735
- setMonth2
9736
- );
9737
9791
  const handleInputChange = useCallback(
9738
9792
  (evt) => {
9739
9793
  const formattedValue2 = evt.currentTarget.value;
9740
9794
  const dateValue2 = parseDate(formattedValue2);
9741
9795
  onValueChange?.({ formattedValue: formattedValue2, dateValue: dateValue2 });
9742
9796
  setFormattedValue(formattedValue2);
9743
- if (!evt.defaultPrevented && dateValue2 && !dateIsVisible(dateValue2)) {
9744
- handleMonthChange(startOfMonth(dateValue2));
9797
+ const calendarApi = calendarApiRef.current;
9798
+ if (!evt.defaultPrevented && dateValue2 && calendarApi && !calendarApi?.isVisible(dateValue2)) {
9799
+ const month = startOfMonth(dateValue2);
9800
+ calendarProps?.onMonthChange?.(month);
9801
+ calendarApi.setMonth(month);
9745
9802
  }
9746
9803
  },
9747
- [
9748
- dateIsVisible,
9749
- handleMonthChange,
9750
- onValueChange,
9751
- parseDate,
9752
- setFormattedValue
9753
- ]
9804
+ [calendarProps, onValueChange, parseDate, setFormattedValue]
9754
9805
  );
9755
9806
  const handleInputFocus = useCallback(() => {
9756
- if (!popoverState.open) {
9757
- handleMonthChange(monthToDisplay());
9758
- }
9759
9807
  changePopoverState({ open: true, modal: false });
9760
- }, [
9761
- popoverState.open,
9762
- changePopoverState,
9763
- handleMonthChange,
9764
- monthToDisplay
9765
- ]);
9808
+ }, [changePopoverState]);
9766
9809
  const handleAddonButtonClick = useCallback(() => {
9767
- handleMonthChange(monthToDisplay());
9768
9810
  changePopoverState({ open: true, modal: true });
9769
- }, [changePopoverState, handleMonthChange, monthToDisplay]);
9811
+ }, [changePopoverState]);
9770
9812
  const handleCalendarValueChange = useCallback(
9771
9813
  (date) => {
9772
9814
  const formattedValue2 = formatDate(date);
@@ -9931,8 +9973,6 @@ const DateInput = forwardRef(
9931
9973
  selectionMode: "single",
9932
9974
  value: deferredDateValue,
9933
9975
  onValueChange: handleCalendarValueChange,
9934
- month,
9935
- onMonthChange: handleMonthChange,
9936
9976
  disabled: disabled || softDisabled || readOnly || calendarProps?.disabled,
9937
9977
  minDate,
9938
9978
  maxDate,
@@ -9940,6 +9980,7 @@ const DateInput = forwardRef(
9940
9980
  maxMonth,
9941
9981
  minYear,
9942
9982
  maxYear,
9983
+ apiRef: calendarApiRef,
9943
9984
  monthSelectProps: {
9944
9985
  ...calendarProps?.monthSelectProps,
9945
9986
  popoverProps: {
@@ -10102,6 +10143,7 @@ const DateRangeInput = forwardRef(function DateRangeInput2({
10102
10143
  open: false,
10103
10144
  modal: false
10104
10145
  });
10146
+ const calendarApiRef = useRef(null);
10105
10147
  const startContainerRef = useRef(null);
10106
10148
  const endContainerRef = useRef(null);
10107
10149
  const startInputRef = useRef(null);
@@ -10121,43 +10163,6 @@ const DateRangeInput = forwardRef(function DateRangeInput2({
10121
10163
  },
10122
10164
  [onPopoverOpenChange, popoverState.open, selectionMode]
10123
10165
  );
10124
- const monthToDisplay = useCallback(
10125
- (input) => {
10126
- let toDisplay;
10127
- if (calendarProps?.defaultMonth) {
10128
- toDisplay = calendarProps.defaultMonth;
10129
- } else if (input === "start" && dateValue.start) {
10130
- toDisplay = dateValue.start;
10131
- } else {
10132
- const relevantForEnd = dateValue.end && addMonths(dateValue.end, -(calendarProps?.numberOfMonths ?? 1) + 1);
10133
- toDisplay = relevantForEnd ?? dateValue.start ?? /* @__PURE__ */ new Date();
10134
- }
10135
- return startOfMonth(toDisplay);
10136
- },
10137
- [
10138
- dateValue.end,
10139
- dateValue.start,
10140
- calendarProps?.defaultMonth,
10141
- calendarProps?.numberOfMonths
10142
- ]
10143
- );
10144
- const [month, setMonth2] = useControllableState(
10145
- () => monthToDisplay("start"),
10146
- calendarProps?.month
10147
- );
10148
- const dateIsVisible = useCallback(
10149
- (date) => isWithinInterval(date, {
10150
- start: month,
10151
- end: lastDayOfMonth(
10152
- addMonths(month, (calendarProps?.numberOfMonths ?? 1) - 1)
10153
- )
10154
- }),
10155
- [calendarProps?.numberOfMonths, month]
10156
- );
10157
- const handleMonthChange = combineEventHandlers(
10158
- calendarProps?.onMonthChange,
10159
- setMonth2
10160
- );
10161
10166
  const handleStartInputChange = useCallback(
10162
10167
  (evt) => {
10163
10168
  const formattedStart = evt.currentTarget.value;
@@ -10172,18 +10177,20 @@ const DateRangeInput = forwardRef(function DateRangeInput2({
10172
10177
  dateValue: newDateValue
10173
10178
  });
10174
10179
  setFormattedValue(newFormattedValue);
10175
- if (!evt.defaultPrevented && dateStart && !dateIsVisible(dateStart)) {
10176
- handleMonthChange(startOfMonth(dateStart));
10180
+ const calendarApi = calendarApiRef.current;
10181
+ if (!evt.defaultPrevented && dateStart && calendarApi && !calendarApi.isVisible(dateStart)) {
10182
+ const month = startOfMonth(dateStart);
10183
+ calendarProps?.onMonthChange?.(month);
10184
+ calendarApi.setMonth(month);
10177
10185
  }
10178
10186
  },
10179
10187
  [
10180
- dateIsVisible,
10188
+ parseDate,
10189
+ formattedValue.end,
10181
10190
  dateValue.end,
10182
- handleMonthChange,
10183
10191
  onValueChange,
10184
- parseDate,
10185
10192
  setFormattedValue,
10186
- formattedValue.end
10193
+ calendarProps
10187
10194
  ]
10188
10195
  );
10189
10196
  const handleEndInputChange = useCallback(
@@ -10200,24 +10207,23 @@ const DateRangeInput = forwardRef(function DateRangeInput2({
10200
10207
  dateValue: newDateValue
10201
10208
  });
10202
10209
  setFormattedValue(newFormattedValue);
10203
- if (!evt.defaultPrevented && dateEnd && !dateIsVisible(dateEnd)) {
10204
- handleMonthChange(
10205
- addMonths(
10206
- startOfMonth(dateEnd),
10207
- -(calendarProps?.numberOfMonths ?? 1) + 1
10208
- )
10210
+ const calendarApi = calendarApiRef.current;
10211
+ if (!evt.defaultPrevented && dateEnd && calendarApi && !calendarApi.isVisible(dateEnd)) {
10212
+ const month = addMonths(
10213
+ startOfMonth(dateEnd),
10214
+ -(calendarProps?.numberOfMonths ?? 1) + 1
10209
10215
  );
10216
+ calendarProps?.onMonthChange?.(month);
10217
+ calendarApi.setMonth(month);
10210
10218
  }
10211
10219
  },
10212
10220
  [
10213
- dateIsVisible,
10221
+ parseDate,
10222
+ formattedValue.start,
10214
10223
  dateValue.start,
10215
- calendarProps?.numberOfMonths,
10216
- handleMonthChange,
10217
10224
  onValueChange,
10218
- parseDate,
10219
10225
  setFormattedValue,
10220
- formattedValue.start
10226
+ calendarProps
10221
10227
  ]
10222
10228
  );
10223
10229
  const handleInputFocus = useCallback(
@@ -10225,19 +10231,10 @@ const DateRangeInput = forwardRef(function DateRangeInput2({
10225
10231
  setFieldControlFocused(true);
10226
10232
  setSelectionMode(input);
10227
10233
  if (!evt.defaultPrevented) {
10228
- if (!popoverState.open) {
10229
- handleMonthChange(monthToDisplay(input));
10230
- }
10231
10234
  changePopoverState({ open: true, modal: false });
10232
10235
  }
10233
10236
  },
10234
- [
10235
- setFieldControlFocused,
10236
- popoverState.open,
10237
- changePopoverState,
10238
- handleMonthChange,
10239
- monthToDisplay
10240
- ]
10237
+ [setFieldControlFocused, changePopoverState]
10241
10238
  );
10242
10239
  const handleClearButtonClick = useCallback(
10243
10240
  (ref) => () => {
@@ -10272,9 +10269,8 @@ const DateRangeInput = forwardRef(function DateRangeInput2({
10272
10269
  );
10273
10270
  const handleAddonButtonClick = useCallback(() => {
10274
10271
  setSelectionMode("start");
10275
- handleMonthChange(monthToDisplay("start"));
10276
10272
  changePopoverState({ open: true, modal: true });
10277
- }, [handleMonthChange, monthToDisplay, changePopoverState]);
10273
+ }, [changePopoverState]);
10278
10274
  const handleCalendarValueChange = useCallback(
10279
10275
  (range) => {
10280
10276
  const newFormattedValue = {
@@ -10745,8 +10741,6 @@ const DateRangeInput = forwardRef(function DateRangeInput2({
10745
10741
  selectionMode: `range-${selectionMode}`,
10746
10742
  value: deferredDateValue,
10747
10743
  onValueChange: handleCalendarValueChange,
10748
- month,
10749
- onMonthChange: handleMonthChange,
10750
10744
  disabled: bothDisabled || bothSoftDisabled || bothReadOnly || (startDisabled || startSoftDisabled || startReadOnly) && (endDisabled || endSoftDisabled || endReadOnly) || calendarProps?.disabled,
10751
10745
  minDate,
10752
10746
  maxDate,
@@ -10754,6 +10748,7 @@ const DateRangeInput = forwardRef(function DateRangeInput2({
10754
10748
  maxMonth,
10755
10749
  minYear,
10756
10750
  maxYear,
10751
+ apiRef: calendarApiRef,
10757
10752
  monthSelectProps: {
10758
10753
  ...calendarProps?.monthSelectProps,
10759
10754
  popoverProps: {