@povio/ui 2.2.9-rc.8 → 2.2.10

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.
Files changed (88) hide show
  1. package/dist/components/buttons/Button/Button.d.ts +2 -2
  2. package/dist/components/buttons/Button/Button.js +1 -1
  3. package/dist/components/buttons/PillButton/PillButton.d.ts +2 -2
  4. package/dist/components/buttons/PillButton/PillButton.js +1 -1
  5. package/dist/components/buttons/TextButton/TextButton.d.ts +2 -1
  6. package/dist/components/buttons/ToggleButton/ToggleButton.d.ts +2 -1
  7. package/dist/components/buttons/shared/ButtonContent.d.ts +3 -3
  8. package/dist/components/buttons/shared/ButtonContent.js +2 -2
  9. package/dist/components/inputs/Checkbox/Checkbox.js +1 -6
  10. package/dist/components/inputs/Checkbox/checkbox.cva.d.ts +0 -3
  11. package/dist/components/inputs/Checkbox/checkbox.cva.js +1 -2
  12. package/dist/components/inputs/DateTime/DatePicker/DatePicker.d.ts +8 -8
  13. package/dist/components/inputs/DateTime/DatePicker/DatePicker.js +59 -33
  14. package/dist/components/inputs/DateTime/DateRangePicker/DateRangePicker.d.ts +4 -7
  15. package/dist/components/inputs/DateTime/DateRangePicker/DateRangePicker.js +4 -14
  16. package/dist/components/inputs/DateTime/DateTimePicker/DateTimePicker.d.ts +7 -7
  17. package/dist/components/inputs/DateTime/DateTimePicker/DateTimePicker.js +40 -22
  18. package/dist/components/inputs/DateTime/TimePicker/TimePicker.d.ts +3 -3
  19. package/dist/components/inputs/DateTime/TimePicker/TimePicker.js +13 -20
  20. package/dist/components/inputs/DateTime/shared/Calendar.d.ts +4 -1
  21. package/dist/components/inputs/DateTime/shared/Calendar.js +75 -12
  22. package/dist/components/inputs/DateTime/shared/CalendarHeader.d.ts +2 -1
  23. package/dist/components/inputs/DateTime/shared/CalendarHeader.js +28 -4
  24. package/dist/components/inputs/DateTime/shared/DateField.d.ts +3 -1
  25. package/dist/components/inputs/DateTime/shared/DateField.js +41 -7
  26. package/dist/components/inputs/DateTime/shared/DatePickerInput.d.ts +6 -5
  27. package/dist/components/inputs/DateTime/shared/DatePickerInput.js +16 -18
  28. package/dist/components/inputs/DateTime/shared/MonthPicker.d.ts +3 -1
  29. package/dist/components/inputs/DateTime/shared/MonthPicker.js +4 -3
  30. package/dist/components/inputs/DateTime/shared/TimePickerInput.d.ts +1 -2
  31. package/dist/components/inputs/DateTime/shared/TimePickerInput.js +2 -7
  32. package/dist/components/inputs/DateTime/shared/YearPicker.d.ts +3 -1
  33. package/dist/components/inputs/DateTime/shared/YearPicker.js +4 -3
  34. package/dist/components/inputs/FormField/FormFieldHeader.js +1 -3
  35. package/dist/components/inputs/Input/NumberInput/NumberInput.js +0 -1
  36. package/dist/components/inputs/Input/TextInput/TextInput.js +0 -3
  37. package/dist/components/inputs/Inputs/InputItem.d.ts +16 -10
  38. package/dist/components/inputs/Inputs/InputItem.js +0 -4
  39. package/dist/components/inputs/RadioGroup/RadioGroup.js +1 -6
  40. package/dist/components/inputs/RadioGroup/radio.cva.d.ts +0 -3
  41. package/dist/components/inputs/RadioGroup/radio.cva.js +1 -2
  42. package/dist/components/inputs/Selection/Autocomplete/Autocomplete.d.ts +1 -3
  43. package/dist/components/inputs/Selection/Autocomplete/Autocomplete.js +3 -4
  44. package/dist/components/inputs/Selection/Autocomplete/QueryAutocomplete.d.ts +18 -3
  45. package/dist/components/inputs/Selection/Autocomplete/QueryAutocomplete.js +7 -23
  46. package/dist/components/inputs/Selection/Select/Select.d.ts +2 -4
  47. package/dist/components/inputs/Selection/Select/Select.js +3 -4
  48. package/dist/components/inputs/Selection/shared/SelectBase.d.ts +1 -8
  49. package/dist/components/inputs/Selection/shared/SelectBase.js +1 -3
  50. package/dist/components/inputs/Selection/shared/SelectDesktop.d.ts +1 -1
  51. package/dist/components/inputs/Selection/shared/SelectDesktop.js +2 -8
  52. package/dist/components/inputs/Selection/shared/SelectInput.d.ts +2 -2
  53. package/dist/components/inputs/Selection/shared/SelectInput.js +3 -23
  54. package/dist/components/inputs/Selection/shared/SelectMobile.d.ts +1 -1
  55. package/dist/components/inputs/Selection/shared/SelectMobile.js +5 -10
  56. package/dist/components/inputs/Selection/shared/select.context.d.ts +2 -3
  57. package/dist/components/inputs/Selection/shared/select.context.js +4 -22
  58. package/dist/components/inputs/Selection/shared/select.types.d.ts +2 -2
  59. package/dist/components/inputs/TextEditor/TextEditor.d.ts +0 -1
  60. package/dist/components/inputs/TextEditor/TextEditor.js +3 -7
  61. package/dist/components/inputs/Toggle/Toggle.js +1 -6
  62. package/dist/components/inputs/Toggle/toggle.cva.d.ts +0 -3
  63. package/dist/components/inputs/Toggle/toggle.cva.js +1 -2
  64. package/dist/components/inputs/shared/CheckContent.d.ts +1 -2
  65. package/dist/components/inputs/shared/CheckContent.js +4 -3
  66. package/dist/components/overlays/BottomSheet/BottomSheet.js +1 -2
  67. package/dist/components/overlays/Tooltip/TooltipEllipsis.d.ts +2 -2
  68. package/dist/config/link.context.js +4 -2
  69. package/dist/config/uiConfig.context.d.ts +2 -8
  70. package/dist/config/uiConfig.context.js +3 -5
  71. package/dist/config/uiStyle.context.d.ts +0 -5
  72. package/dist/helpers/dynamicInputs.d.ts +5 -5
  73. package/dist/helpers/dynamicInputs.js +0 -3
  74. package/dist/index.d.ts +0 -4
  75. package/dist/index.js +3 -4
  76. package/dist/utils/date-time.utils.d.ts +7 -6
  77. package/dist/utils/date-time.utils.js +66 -16
  78. package/package.json +1 -1
  79. package/dist/components/inputs/DateTime/shared/datePicker.types.d.ts +0 -3
  80. package/dist/components/inputs/FormField/formFieldHeader.cva.d.ts +0 -6
  81. package/dist/components/inputs/FormField/formFieldHeader.cva.js +0 -11
  82. package/dist/components/inputs/Selection/Autocomplete/queryAutocomplete.types.d.ts +0 -30
  83. package/dist/components/inputs/Selection/Select/QuerySelect.d.ts +0 -14
  84. package/dist/components/inputs/Selection/Select/QuerySelect.js +0 -56
  85. package/dist/components/inputs/Selection/shared/querySelect.utils.d.ts +0 -6
  86. package/dist/components/inputs/Selection/shared/querySelect.utils.js +0 -13
  87. package/dist/hooks/useQueryAutocomplete.d.ts +0 -25
  88. package/dist/hooks/useQueryAutocomplete.js +0 -41
@@ -5,7 +5,6 @@ import { DateTimeDialog } from "../shared/DateTimeDialog.js";
5
5
  import { DateTimeDialogFooter } from "../shared/DateTimeDialogFooter.js";
6
6
  import { FormField } from "../../FormField/FormField.js";
7
7
  import { TooltipWrapper } from "../../shared/TooltipWrapper.js";
8
- import { useDebounceCallback } from "../../../../hooks/useDebounceCallback.js";
9
8
  import { DateTimeUtils } from "../../../../utils/date-time.utils.js";
10
9
  import { jsx, jsxs } from "react/jsx-runtime";
11
10
  import { useEffect, useImperativeHandle, useMemo, useRef } from "react";
@@ -17,7 +16,9 @@ import { useCalendarState, useDatePickerState } from "react-stately";
17
16
  //#region src/components/inputs/DateTime/DateTimePicker/DateTimePicker.tsx
18
17
  var DateTimePickerBase = (props) => {
19
18
  const ui = UIConfig.useConfig();
20
- const { ref, label, tooltipText, helperText, isRequired, rightContent, isDisabled, isDirty, headerClassName, errorClassName, isHeaderHidden, error, onChange, onBlur, value, disableDropdown, isTimeOptional, placeholder, inputClassName, hideLabel = ui.input.hideLabel, variant = ui.input.variant, as = ui.input.as, size = ui.input.size, isClearable = ui.input.isClearable, todayIcon = ui.dateInput.todayIcon, todayIconButtonSize = ui.dateInput.todayIconButtonSize, shouldForceLeadingZeros = ui.dateInput.shouldForceLeadingZeros, disableManualEntry = ui.dateInput.disableManualEntry, autoFixYear = ui.dateInput.autoFixYear, ...rest } = props;
19
+ const { ref, label, tooltipText, helperText, isRequired, rightContent, isDisabled, isDirty, headerClassName, errorClassName, isHeaderHidden, error, onChange, value, disableDropdown, isTimeOptional, placeholder, inputClassName, hideLabel = ui.input.hideLabel, variant = ui.input.variant, as = ui.input.as, size = ui.input.size, isClearable = ui.input.isClearable, todayIcon = ui.dateInput.todayIcon, shouldForceLeadingZeros = ui.dateInput.shouldForceLeadingZeros, disableManualEntry = ui.dateInput.disableManualEntry, shouldUpdateDateOnMonthYearChange = ui.dateInput.shouldUpdateDateOnMonthYearChange, timeZone, autoFixYear = ui.dateInput.autoFixYear, ...rest } = props;
20
+ let effectiveTimeZone = getLocalTimeZone();
21
+ if (timeZone) effectiveTimeZone = timeZone;
21
22
  const formFieldProps = {
22
23
  error,
23
24
  label,
@@ -38,10 +39,6 @@ var DateTimePickerBase = (props) => {
38
39
  useImperativeHandle(ref, () => ({ clear: () => {
39
40
  datePickerInputRef.current?.clear();
40
41
  } }));
41
- const handleBlur = (val) => {
42
- onBlur?.({ target: { value: val } });
43
- };
44
- const { callback: debouncedBlur } = useDebounceCallback(handleBlur, { delay: 500 });
45
42
  const dialogState = useDatePickerState({
46
43
  ...rest,
47
44
  defaultValue: value || rest.defaultValue,
@@ -60,8 +57,7 @@ var DateTimePickerBase = (props) => {
60
57
  onChange: (val) => {
61
58
  onChange?.(val);
62
59
  dialogState.setValue(val);
63
- calendarState.setFocusedDate(val || today(getLocalTimeZone()));
64
- debouncedBlur(val);
60
+ calendarState.setFocusedDate(val || today(effectiveTimeZone));
65
61
  },
66
62
  shouldCloseOnSelect: false,
67
63
  granularity: "minute",
@@ -97,24 +93,41 @@ var DateTimePickerBase = (props) => {
97
93
  labelProps
98
94
  };
99
95
  const onApply = () => {
100
- const newValue = dialogState.value;
101
- state.setValue(newValue);
96
+ state.setValue(dialogState.value);
102
97
  state.toggle();
103
- handleBlur(newValue);
98
+ };
99
+ const onMonthYearChange = (selectedDate) => {
100
+ if (!shouldUpdateDateOnMonthYearChange) return;
101
+ const baseDate = dialogState.value || state.value;
102
+ if (baseDate) {
103
+ const updatedDate = baseDate.set({
104
+ year: selectedDate.year,
105
+ month: selectedDate.month
106
+ });
107
+ dialogState.setValue(updatedDate);
108
+ calendarState.setFocusedDate(updatedDate);
109
+ return;
110
+ }
111
+ dialogState.setValue(toCalendarDateTime(selectedDate));
112
+ calendarState.setFocusedDate(selectedDate);
104
113
  };
105
114
  const onTodayPress = () => {
106
- dialogState.setValue(toCalendarDateTime(now(getLocalTimeZone())));
107
- calendarState.setFocusedDate(today(getLocalTimeZone()));
115
+ dialogState.setValue(toCalendarDateTime(now(effectiveTimeZone)));
116
+ calendarState.setFocusedDate(today(effectiveTimeZone));
108
117
  };
109
118
  const onOpenChange = (isOpen) => {
110
119
  state.toggle();
111
- calendarState.setFocusedDate(state.value || today(getLocalTimeZone()));
120
+ calendarState.setFocusedDate(state.value || today(effectiveTimeZone));
112
121
  if (!isOpen) dialogState.setValue(state.value);
113
122
  };
114
123
  const onInputBlur = (e) => {
115
124
  if (!isTimeOptional) return;
125
+ if (state.value) {
126
+ dialogState.setValue(state.value);
127
+ return;
128
+ }
116
129
  const textValue = e.currentTarget.textContent;
117
- const dateTimeValue = DateTimeUtils.formatTextDateToCalendarDateTime(textValue);
130
+ const dateTimeValue = DateTimeUtils.formatTextDateToCalendarDateTime(textValue, effectiveTimeZone, locale);
118
131
  if (dateTimeValue) {
119
132
  state.setValue(dateTimeValue);
120
133
  dialogState.setValue(dateTimeValue);
@@ -153,13 +166,14 @@ var DateTimePickerBase = (props) => {
153
166
  isClearable,
154
167
  headerProps,
155
168
  todayIcon,
156
- todayIconButtonSize,
157
169
  isRequired,
158
170
  disableManualEntry,
159
- autoFixYear,
160
171
  placeholder,
161
172
  onOpenDropdown: () => state.toggle(),
162
- className: inputClassName
173
+ className: inputClassName,
174
+ timeZone: effectiveTimeZone,
175
+ autoFixYear,
176
+ isTimeOptional
163
177
  }), (!disableDropdown || disableManualEntry) && /* @__PURE__ */ jsx(DateTimeDialog, {
164
178
  footer: /* @__PURE__ */ jsx(DateTimeDialogFooter, {
165
179
  isDisabled,
@@ -177,21 +191,25 @@ var DateTimePickerBase = (props) => {
177
191
  calendarProps,
178
192
  includesTime: true,
179
193
  datePickerState: dialogState,
180
- onApply
194
+ onApply,
195
+ onMonthYearChange,
196
+ granularity: "day"
181
197
  })
182
198
  })]
183
199
  })
184
200
  });
185
201
  };
186
202
  var DateTimePicker = ({ fullIso = true, ...props }) => {
203
+ let effectiveTimeZone = getLocalTimeZone();
204
+ if (props.timeZone) effectiveTimeZone = props.timeZone;
187
205
  const formatDateValue = (dateValue) => {
188
206
  if (dateValue === null) return null;
189
- if (fullIso) return DateTimeUtils.fromCalendarDateTimeToUTCISO(dateValue);
190
- return DateTimeUtils.fromDateValueToISO(dateValue);
207
+ if (fullIso) return DateTimeUtils.fromDateValueToISO(dateValue, effectiveTimeZone);
208
+ return DateTimeUtils.fromDateValueToISO(dateValue, effectiveTimeZone);
191
209
  };
192
210
  const parseDateValue = (isoString) => {
193
211
  if (isoString == null) return isoString;
194
- return DateTimeUtils.fromUTCISOToCalendarDateTime(isoString);
212
+ return DateTimeUtils.fromUTCISOToCalendarDateTime(isoString, effectiveTimeZone);
195
213
  };
196
214
  if ("formControl" in props && props.formControl) {
197
215
  const { formControl, ref, ...innerProps } = props;
@@ -1,10 +1,10 @@
1
- import { Ref, FocusEvent } from 'react';
1
+ import { Ref } from 'react';
2
2
  import { AriaTimeFieldProps, TimeValue } from 'react-aria';
3
3
  import { FieldValues } from 'react-hook-form';
4
4
  import { FormFieldProps } from '../../FormField/FormField';
5
5
  import { ControlProps } from '../../shared/form.types';
6
6
  import { InputVariantProps } from '../../shared/input.cva';
7
- interface TimePickerBaseProps extends FormFieldProps, InputVariantProps, Omit<AriaTimeFieldProps<TimeValue>, "label" | "onBlur"> {
7
+ interface TimePickerBaseProps extends FormFieldProps, InputVariantProps, Omit<AriaTimeFieldProps<TimeValue>, "label"> {
8
8
  ref?: Ref<HTMLDivElement>;
9
9
  disableDropdown?: boolean;
10
10
  date?: string | null;
@@ -13,12 +13,12 @@ interface TimePickerBaseProps extends FormFieldProps, InputVariantProps, Omit<Ar
13
13
  disableManualEntry?: boolean;
14
14
  placeholder?: string;
15
15
  inputClassName?: string;
16
- onBlur?: (e: FocusEvent<HTMLInputElement>) => void;
17
16
  }
18
17
  export interface TimePickerProps extends Omit<TimePickerBaseProps, "value" | "onChange"> {
19
18
  value?: string | null;
20
19
  onChange?: (value: string | null) => void;
21
20
  fullIso?: boolean;
21
+ timeZone?: string;
22
22
  }
23
23
  export type ControlledTimePickerProps<TFieldValues extends FieldValues> = ControlProps<TimePickerProps, TFieldValues>;
24
24
  export declare const TimePicker: <TFieldValues extends FieldValues>(props: ControlledTimePickerProps<TFieldValues>) => import("react/jsx-runtime").JSX.Element;
@@ -4,7 +4,6 @@ import { DateTimeDialog } from "../shared/DateTimeDialog.js";
4
4
  import { DateTimeDialogFooter } from "../shared/DateTimeDialogFooter.js";
5
5
  import { FormField } from "../../FormField/FormField.js";
6
6
  import { TooltipWrapper } from "../../shared/TooltipWrapper.js";
7
- import { useDebounceCallback } from "../../../../hooks/useDebounceCallback.js";
8
7
  import { DateTimeUtils } from "../../../../utils/date-time.utils.js";
9
8
  import { TimePickerInput } from "../shared/TimePickerInput.js";
10
9
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -19,7 +18,7 @@ import { useTimeFieldState } from "react-stately";
19
18
  //#region src/components/inputs/DateTime/TimePicker/TimePicker.tsx
20
19
  var TimePickerBase = (props) => {
21
20
  const ui = UIConfig.useConfig();
22
- const { ref, label, tooltipText, helperText, isRequired, rightContent, isDisabled, isDirty, headerClassName, errorClassName, isHeaderHidden, error, onChange, onBlur, value, disableDropdown, placeholder, className, inputClassName, variant = ui.input.variant, as = ui.input.as, size = ui.input.size, hideLabel = ui.input.hideLabel, isClearable = ui.input.isClearable, disableManualEntry = ui.dateInput.disableManualEntry, ...rest } = props;
21
+ const { ref, label, tooltipText, helperText, isRequired, rightContent, isDisabled, isDirty, headerClassName, errorClassName, isHeaderHidden, error, onChange, value, disableDropdown, placeholder, className, inputClassName, variant = ui.input.variant, as = ui.input.as, size = ui.input.size, hideLabel = ui.input.hideLabel, isClearable = ui.input.isClearable, disableManualEntry = ui.dateInput.disableManualEntry, ...rest } = props;
23
22
  const formFieldProps = {
24
23
  error,
25
24
  label,
@@ -41,18 +40,11 @@ var TimePickerBase = (props) => {
41
40
  defaultValue: value || rest.defaultValue,
42
41
  locale
43
42
  });
44
- const handleBlur = (val) => {
45
- onBlur?.({ target: { value: val } });
46
- };
47
- const { callback: debouncedBlur } = useDebounceCallback(handleBlur, { delay: 500 });
48
43
  const state = useTimeFieldState({
49
44
  ...rest,
50
45
  isDisabled,
51
46
  value,
52
- onChange: (val) => {
53
- onChange?.(val);
54
- debouncedBlur(val);
55
- },
47
+ onChange,
56
48
  locale
57
49
  });
58
50
  useEffect(() => {
@@ -80,10 +72,8 @@ var TimePickerBase = (props) => {
80
72
  labelProps
81
73
  };
82
74
  const onApply = () => {
83
- const newValue = dialogState.value;
84
- state.setValue(newValue);
75
+ state.setValue(dialogState.value);
85
76
  setIsOpen(false);
86
- handleBlur(newValue);
87
77
  };
88
78
  const onOpenChange = (open) => {
89
79
  setIsOpen(open);
@@ -111,7 +101,6 @@ var TimePickerBase = (props) => {
111
101
  onPress: onOpen,
112
102
  isDisabled,
113
103
  isDirty,
114
- isRequired,
115
104
  isInvalid: !!error,
116
105
  disableDropdown,
117
106
  variant,
@@ -137,28 +126,32 @@ var TimePickerBase = (props) => {
137
126
  });
138
127
  };
139
128
  var TimePicker = (props) => {
129
+ let effectiveTimeZone = getLocalTimeZone();
130
+ if (props.timeZone) effectiveTimeZone = props.timeZone;
140
131
  const formatTimeValue = (timeValue) => {
141
132
  if (timeValue === null) return null;
142
- const parsedDate = props.date ? DateTime.fromISO(props.date).toJSDate() : void 0;
143
- const dateTimeValue = (parsedDate ? DateTimeUtils.fromLocalToZonedDateTime(parsedDate) : now(getLocalTimeZone())).set(timeValue);
144
- return DateTimeUtils.fromDateValueToISO(dateTimeValue);
133
+ let parsedDate;
134
+ if (props.date) parsedDate = DateTime.fromISO(props.date, { zone: effectiveTimeZone }).toJSDate();
135
+ let dateValue = now(effectiveTimeZone);
136
+ if (parsedDate) dateValue = DateTimeUtils.fromLocalToZonedDateTime(parsedDate, effectiveTimeZone);
137
+ const dateTimeValue = dateValue.set(timeValue);
138
+ return DateTimeUtils.fromDateValueToISO(dateTimeValue, effectiveTimeZone);
145
139
  };
146
140
  const parseTimeValue = (isoString) => {
147
141
  if (isoString == null) return isoString;
148
- return toTime(DateTimeUtils.fromISOtoZonedDateTime(isoString));
142
+ return toTime(DateTimeUtils.fromISOtoZonedDateTime(isoString, effectiveTimeZone));
149
143
  };
150
144
  if ("formControl" in props && props.formControl) {
151
145
  const { formControl, ref, ...innerProps } = props;
152
146
  return /* @__PURE__ */ jsx(Controller, {
153
147
  control: formControl.control,
154
148
  name: formControl.name,
155
- render: ({ field, fieldState: { error, isDirty } }) => /* @__PURE__ */ jsx(TimePickerBase, {
149
+ render: ({ field, fieldState: { error } }) => /* @__PURE__ */ jsx(TimePickerBase, {
156
150
  ...innerProps,
157
151
  ref: mergeRefs(ref, field.ref),
158
152
  value: parseTimeValue(field.value),
159
153
  onChange: (value) => field.onChange(formatTimeValue(value)),
160
154
  onBlur: field.onBlur,
161
- isDirty,
162
155
  isDisabled: field.disabled || props.isDisabled,
163
156
  error: props.error ?? error?.message
164
157
  })
@@ -1,3 +1,4 @@
1
+ import { CalendarDate } from '@internationalized/date';
1
2
  import { CalendarState, CalendarStateOptions } from '@react-stately/calendar';
2
3
  import { DatePickerState } from 'react-stately';
3
4
  type DateTimeCalendarProps = {
@@ -14,7 +15,9 @@ type CalendarProps = DateTimeCalendarProps & {
14
15
  state: CalendarState;
15
16
  calendarProps: Omit<CalendarStateOptions, "locale" | "createCalendar">;
16
17
  onApply: () => void;
18
+ onMonthYearChange?: (selectedDate: CalendarDate) => void;
19
+ granularity?: "day" | "month" | "year";
17
20
  };
18
21
  export type ToggleState = "month" | "year" | "time";
19
- export declare const Calendar: ({ className, includesTime, datePickerState, hourCycle, onApply, ...props }: CalendarProps) => import("react/jsx-runtime").JSX.Element;
22
+ export declare const Calendar: ({ className, includesTime, datePickerState, hourCycle, onApply, onMonthYearChange, granularity, ...props }: CalendarProps) => import("react/jsx-runtime").JSX.Element;
20
23
  export {};
@@ -5,28 +5,90 @@ import { TimePickerForm } from "./TimePickerForm.js";
5
5
  import { YearPicker } from "./YearPicker.js";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
  import { clsx } from "clsx";
8
- import { useState } from "react";
8
+ import { useEffect, useState } from "react";
9
9
  import { useCalendar } from "@react-aria/calendar";
10
10
  //#region src/components/inputs/DateTime/shared/Calendar.tsx
11
- var Calendar = ({ className, includesTime, datePickerState, hourCycle, onApply, ...props }) => {
12
- const [toggleState, setToggleState] = useState(null);
11
+ var Calendar = ({ className, includesTime, datePickerState, hourCycle, onApply, onMonthYearChange, granularity = "day", ...props }) => {
12
+ const [toggleState, setToggleState] = useState(() => {
13
+ if (granularity === "year") return "year";
14
+ if (granularity === "month") return "month";
15
+ return null;
16
+ });
13
17
  const { calendarProps, prevButtonProps, nextButtonProps } = useCalendar(props.calendarProps, props.state);
18
+ useEffect(() => {
19
+ if (granularity === "year" && toggleState !== "year") {
20
+ setToggleState("year");
21
+ return;
22
+ }
23
+ if (granularity === "month" && toggleState === null) {
24
+ setToggleState("month");
25
+ return;
26
+ }
27
+ if (granularity === "month" && toggleState === "time") {
28
+ setToggleState("month");
29
+ return;
30
+ }
31
+ if (granularity === "day" && toggleState === "time" && !includesTime) setToggleState(null);
32
+ }, [
33
+ granularity,
34
+ toggleState,
35
+ includesTime
36
+ ]);
37
+ const onMonthSelectionChange = () => {
38
+ if (granularity === "day") {
39
+ setToggleState(null);
40
+ return;
41
+ }
42
+ setToggleState("month");
43
+ };
44
+ const onYearSelectionChange = () => {
45
+ if (granularity === "day") {
46
+ setToggleState(null);
47
+ return;
48
+ }
49
+ if (granularity === "month") {
50
+ setToggleState("month");
51
+ return;
52
+ }
53
+ setToggleState("year");
54
+ };
14
55
  const handleDateChange = () => {
15
56
  if (includesTime && !datePickerState.value) setToggleState("time");
16
57
  else onApply();
17
58
  };
18
59
  const getContent = () => {
19
- if (!toggleState) return /* @__PURE__ */ jsx(CalendarGrid, {
20
- state: props.state,
21
- onApply: handleDateChange
22
- });
23
- if (toggleState === "month") return /* @__PURE__ */ jsx(MonthPicker, {
24
- state: props.state,
25
- onSelectionChange: () => setToggleState(null)
26
- });
60
+ if (!toggleState) {
61
+ if (granularity === "month") return /* @__PURE__ */ jsx(MonthPicker, {
62
+ state: props.state,
63
+ onSelectionChange: onMonthSelectionChange,
64
+ onDateChange: onMonthYearChange
65
+ });
66
+ if (granularity === "year") return /* @__PURE__ */ jsx(YearPicker, {
67
+ state: props.state,
68
+ onSelectionChange: onYearSelectionChange,
69
+ onDateChange: onMonthYearChange
70
+ });
71
+ return /* @__PURE__ */ jsx(CalendarGrid, {
72
+ state: props.state,
73
+ onApply: handleDateChange
74
+ });
75
+ }
76
+ if (toggleState === "month") {
77
+ if (granularity === "year") return /* @__PURE__ */ jsx(YearPicker, {
78
+ state: props.state,
79
+ onSelectionChange: onYearSelectionChange,
80
+ onDateChange: onMonthYearChange
81
+ });
82
+ return /* @__PURE__ */ jsx(MonthPicker, {
83
+ state: props.state,
84
+ onSelectionChange: onMonthSelectionChange,
85
+ onDateChange: onMonthYearChange
86
+ });
87
+ }
27
88
  if (toggleState === "year") return /* @__PURE__ */ jsx(YearPicker, {
28
89
  state: props.state,
29
- onSelectionChange: () => setToggleState(null)
90
+ onSelectionChange: onYearSelectionChange,
91
+ onDateChange: onMonthYearChange
30
92
  });
31
93
  if (toggleState === "time" && includesTime) return /* @__PURE__ */ jsx("div", {
32
94
  className: "flex h-72 w-80 items-center justify-center",
@@ -44,6 +106,7 @@ var Calendar = ({ className, includesTime, datePickerState, hourCycle, onApply,
44
106
  nextButtonProps,
45
107
  includesTime,
46
108
  hourCycle,
109
+ granularity,
47
110
  toggleState,
48
111
  setToggleState
49
112
  }), /* @__PURE__ */ jsx("div", {
@@ -9,8 +9,9 @@ interface CalendarProps {
9
9
  nextButtonProps: AriaButtonProps;
10
10
  includesTime?: boolean;
11
11
  hourCycle?: 12 | 24;
12
+ granularity?: "day" | "month" | "year";
12
13
  toggleState: ToggleState | null;
13
14
  setToggleState: (state: ToggleState | null) => void;
14
15
  }
15
- export declare const CalendarHeader: ({ calendarState, datePickerState, prevButtonProps, nextButtonProps, includesTime, hourCycle, toggleState, setToggleState, }: CalendarProps) => import("react/jsx-runtime").JSX.Element;
16
+ export declare const CalendarHeader: ({ calendarState, datePickerState, prevButtonProps, nextButtonProps, includesTime, hourCycle, granularity, toggleState, setToggleState, }: CalendarProps) => import("react/jsx-runtime").JSX.Element;
16
17
  export {};
@@ -13,7 +13,7 @@ var HourCycle = {
13
13
  12: "h12",
14
14
  24: "h23"
15
15
  };
16
- var CalendarHeader = ({ calendarState, datePickerState, prevButtonProps, nextButtonProps, includesTime, hourCycle, toggleState, setToggleState }) => {
16
+ var CalendarHeader = ({ calendarState, datePickerState, prevButtonProps, nextButtonProps, includesTime, hourCycle, granularity = "day", toggleState, setToggleState }) => {
17
17
  const formatter = useDateFormatter({
18
18
  month: "long",
19
19
  timeZone: calendarState.timeZone
@@ -43,14 +43,24 @@ var CalendarHeader = ({ calendarState, datePickerState, prevButtonProps, nextBut
43
43
  /* @__PURE__ */ jsxs(ToggleButtonGroup, {
44
44
  className: "flex gap-2",
45
45
  children: [
46
- /* @__PURE__ */ jsx(PillButton, {
46
+ granularity !== "year" && /* @__PURE__ */ jsx(PillButton, {
47
47
  color: "secondary",
48
48
  variant: "subtle",
49
49
  iconPosition: "right",
50
50
  icon: toggleState === "month" ? ArrowDropUpIcon : ArrowDropDownIcon,
51
51
  toggle: true,
52
52
  isSelected: toggleState === "month",
53
- onChange: (isSelected) => setToggleState(isSelected ? "month" : null),
53
+ onChange: (isSelected) => {
54
+ if (!isSelected) {
55
+ if (granularity === "day") {
56
+ setToggleState(null);
57
+ return;
58
+ }
59
+ setToggleState("month");
60
+ return;
61
+ }
62
+ setToggleState("month");
63
+ },
54
64
  children: month
55
65
  }),
56
66
  /* @__PURE__ */ jsx(PillButton, {
@@ -60,7 +70,21 @@ var CalendarHeader = ({ calendarState, datePickerState, prevButtonProps, nextBut
60
70
  icon: toggleState === "year" ? ArrowDropUpIcon : ArrowDropDownIcon,
61
71
  toggle: true,
62
72
  isSelected: toggleState === "year",
63
- onChange: (isSelected) => setToggleState(isSelected ? "year" : null),
73
+ onChange: (isSelected) => {
74
+ if (isSelected) {
75
+ setToggleState("year");
76
+ return;
77
+ }
78
+ if (granularity === "day") {
79
+ setToggleState(null);
80
+ return;
81
+ }
82
+ if (granularity === "month") {
83
+ setToggleState("month");
84
+ return;
85
+ }
86
+ setToggleState("year");
87
+ },
64
88
  children: year
65
89
  }),
66
90
  includesTime && /* @__PURE__ */ jsx(PillButton, {
@@ -9,6 +9,8 @@ interface DateFieldProps extends Omit<DateFieldStateOptions, "locale" | "createC
9
9
  onClearChange?: (canClear: boolean) => void;
10
10
  hidePlaceholder?: boolean;
11
11
  disableManualEntry?: boolean;
12
+ dateGranularity?: "day" | "month" | "year";
13
+ isTimeOptional?: boolean;
12
14
  }
13
- export declare const DateField: ({ ref, onClearChange, hidePlaceholder, isDisabled, disableManualEntry, ...props }: DateFieldProps) => import("react/jsx-runtime").JSX.Element;
15
+ export declare const DateField: ({ ref, onClearChange, hidePlaceholder, isDisabled, disableManualEntry, dateGranularity, isTimeOptional, ...props }: DateFieldProps) => import("react/jsx-runtime").JSX.Element;
14
16
  export {};
@@ -6,7 +6,7 @@ import { useDateField, useLocale } from "react-aria";
6
6
  import { createCalendar } from "@internationalized/date";
7
7
  import { useDateFieldState } from "react-stately";
8
8
  //#region src/components/inputs/DateTime/shared/DateField.tsx
9
- var DateField = ({ ref, onClearChange, hidePlaceholder, isDisabled, disableManualEntry, ...props }) => {
9
+ var DateField = ({ ref, onClearChange, hidePlaceholder, isDisabled, disableManualEntry, dateGranularity = "day", isTimeOptional = false, ...props }) => {
10
10
  const { locale } = useLocale();
11
11
  const state = useDateFieldState({
12
12
  ...props,
@@ -21,6 +21,31 @@ var DateField = ({ ref, onClearChange, hidePlaceholder, isDisabled, disableManua
21
21
  isDisabled,
22
22
  isReadOnly: disableManualEntry
23
23
  }, state, dataFieldRef);
24
+ const isSegmentVisible = (segmentType) => {
25
+ if (dateGranularity === "day") return true;
26
+ if (dateGranularity === "month") return segmentType !== "day";
27
+ if (dateGranularity === "year") return segmentType === "year";
28
+ return true;
29
+ };
30
+ const segmentsToRender = state.segments.filter((segment, index, segments) => {
31
+ if (segment.type !== "literal") return isSegmentVisible(segment.type);
32
+ let hasVisiblePrevious = false;
33
+ for (let i = index - 1; i >= 0; i--) {
34
+ const previousSegment = segments[i];
35
+ if (previousSegment.type === "literal") continue;
36
+ hasVisiblePrevious = isSegmentVisible(previousSegment.type);
37
+ break;
38
+ }
39
+ if (!hasVisiblePrevious) return false;
40
+ let hasVisibleNext = false;
41
+ for (let i = index + 1; i < segments.length; i++) {
42
+ const nextSegment = segments[i];
43
+ if (nextSegment.type === "literal") continue;
44
+ hasVisibleNext = isSegmentVisible(nextSegment.type);
45
+ break;
46
+ }
47
+ return hasVisibleNext;
48
+ });
24
49
  const autoFixYear = () => {
25
50
  const monthSegment = state.segments.find((segment) => segment.type === "month");
26
51
  const daySegment = state.segments.find((segment) => segment.type === "day");
@@ -29,16 +54,25 @@ var DateField = ({ ref, onClearChange, hidePlaceholder, isDisabled, disableManua
29
54
  const minuteSegment = state.segments.find((segment) => segment.type === "minute");
30
55
  const isMonthFilled = monthSegment && !monthSegment.isPlaceholder;
31
56
  const isDayFilled = daySegment && !daySegment.isPlaceholder;
57
+ const isYearFilled = yearSegment && !yearSegment.isPlaceholder && yearSegment.text?.length > 0;
32
58
  const isYearEmpty = yearSegment && !(parseInt(yearSegment.text) && yearSegment.text?.length === 4);
33
- const isHourEmpty = hourSegment && !parseInt(hourSegment.text);
34
- if (minuteSegment && !parseInt(minuteSegment.text)) {
59
+ const isDateFilled = isMonthFilled && isDayFilled && isYearFilled;
60
+ const isHourEmpty = hourSegment && (hourSegment.isPlaceholder || Number.isNaN(parseInt(hourSegment.text ?? "", 10)));
61
+ const isMinuteEmpty = minuteSegment && (minuteSegment.isPlaceholder || Number.isNaN(parseInt(minuteSegment.text ?? "", 10)));
62
+ if (!isTimeOptional && isDateFilled && minuteSegment && isMinuteEmpty) {
35
63
  let minute = minuteSegment?.value || 0;
36
- if (minuteSegment?.text?.length && minuteSegment?.text?.length > 0) minute = parseInt(minuteSegment?.text ?? "00");
64
+ if (minuteSegment?.text?.length && minuteSegment?.text?.length > 0) {
65
+ minute = parseInt(minuteSegment?.text ?? "00");
66
+ if (isNaN(minute)) minute = 0;
67
+ }
37
68
  state.setSegment("minute", minute);
38
69
  }
39
- if (isHourEmpty) {
70
+ if (!isTimeOptional && isDateFilled && hourSegment && isHourEmpty) {
40
71
  let hour = hourSegment?.value || 0;
41
- if (hourSegment?.text?.length && hourSegment?.text?.length > 0) hour = parseInt(hourSegment?.text ?? "00");
72
+ if (hourSegment?.text?.length && hourSegment?.text?.length > 0) {
73
+ hour = parseInt(hourSegment?.text ?? "00");
74
+ if (isNaN(hour)) hour = 0;
75
+ }
42
76
  state.setSegment("hour", hour);
43
77
  }
44
78
  if (isMonthFilled && isDayFilled && isYearEmpty) {
@@ -78,7 +112,7 @@ var DateField = ({ ref, onClearChange, hidePlaceholder, isDisabled, disableManua
78
112
  className: clsx("relative w-full", disableManualEntry && "pointer-events-none"),
79
113
  children: /* @__PURE__ */ jsx("div", {
80
114
  className: "flex",
81
- children: state.segments.map((segment, i) => /* @__PURE__ */ jsx(DateSegmentItem, {
115
+ children: segmentsToRender.map((segment, i) => /* @__PURE__ */ jsx(DateSegmentItem, {
82
116
  segment,
83
117
  state,
84
118
  isDisabled,
@@ -1,6 +1,5 @@
1
1
  import { Ref } from 'react';
2
2
  import { DatePickerAria } from 'react-aria';
3
- import { DatePickerTodayIcon, DatePickerTodayIconButtonSize } from './datePicker.types';
4
3
  import { FormFieldHeaderProps } from '../../FormField/FormFieldHeader';
5
4
  import { InputVariantProps } from '../../shared/input.cva';
6
5
  export interface DatePickerInputHandle {
@@ -19,15 +18,17 @@ interface DatePickerInputProps extends InputVariantProps {
19
18
  isDateTime?: boolean;
20
19
  isClearable?: boolean;
21
20
  headerProps?: FormFieldHeaderProps;
22
- todayIcon?: DatePickerTodayIcon;
23
- todayIconButtonSize?: DatePickerTodayIconButtonSize;
21
+ todayIcon?: boolean;
24
22
  isDirty?: boolean;
25
23
  isRequired?: boolean;
26
24
  disableManualEntry?: boolean;
27
- autoFixYear?: boolean;
28
25
  placeholder?: string;
29
26
  className?: string;
30
27
  onOpenDropdown?: () => void;
28
+ dateGranularity?: "day" | "month" | "year";
29
+ timeZone?: string;
30
+ autoFixYear?: boolean;
31
+ isTimeOptional?: boolean;
31
32
  }
32
- export declare const DatePickerInput: ({ ref, as, groupProps, fieldProps, endFieldProps, buttonProps, isDisabled, isInvalid, disableDropdown, variant, size, isDateTime, isClearable, headerProps, todayIcon, todayIconButtonSize, isDirty, isRequired, disableManualEntry, autoFixYear, placeholder, className, onOpenDropdown, ...props }: DatePickerInputProps) => import("react/jsx-runtime").JSX.Element;
33
+ export declare const DatePickerInput: ({ ref, as, groupProps, fieldProps, endFieldProps, buttonProps, isDisabled, isInvalid, disableDropdown, variant, size, isDateTime, isClearable, headerProps, todayIcon, isDirty, isRequired, disableManualEntry, placeholder, className, onOpenDropdown, dateGranularity, timeZone, autoFixYear, isTimeOptional, ...props }: DatePickerInputProps) => import("react/jsx-runtime").JSX.Element;
33
34
  export {};