@povio/ui 2.2.9-rc.41 → 2.2.9-rc.44

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 (50) hide show
  1. package/dist/components/buttons/Button/Button.d.ts +3 -4
  2. package/dist/components/buttons/Button/Button.js +32 -41
  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/DateTime/DatePicker/DatePicker.d.ts +5 -1
  10. package/dist/components/inputs/DateTime/DatePicker/DatePicker.js +82 -28
  11. package/dist/components/inputs/DateTime/DateRangePicker/DateRangePicker.js +3 -1
  12. package/dist/components/inputs/DateTime/DateTimePicker/DateTimePicker.d.ts +4 -0
  13. package/dist/components/inputs/DateTime/DateTimePicker/DateTimePicker.js +40 -10
  14. package/dist/components/inputs/DateTime/TimePicker/TimePicker.d.ts +1 -0
  15. package/dist/components/inputs/DateTime/TimePicker/TimePicker.js +12 -5
  16. package/dist/components/inputs/DateTime/shared/Calendar.d.ts +6 -1
  17. package/dist/components/inputs/DateTime/shared/Calendar.js +112 -15
  18. package/dist/components/inputs/DateTime/shared/CalendarHeader.d.ts +2 -1
  19. package/dist/components/inputs/DateTime/shared/CalendarHeader.js +28 -4
  20. package/dist/components/inputs/DateTime/shared/DateField.d.ts +5 -1
  21. package/dist/components/inputs/DateTime/shared/DateField.js +60 -13
  22. package/dist/components/inputs/DateTime/shared/DatePickerInput.d.ts +5 -1
  23. package/dist/components/inputs/DateTime/shared/DatePickerInput.js +15 -6
  24. package/dist/components/inputs/DateTime/shared/MonthPicker.d.ts +5 -1
  25. package/dist/components/inputs/DateTime/shared/MonthPicker.js +40 -8
  26. package/dist/components/inputs/DateTime/shared/YearPicker.d.ts +5 -1
  27. package/dist/components/inputs/DateTime/shared/YearPicker.js +42 -8
  28. package/dist/components/inputs/Input/NumberInput/NumberInput.js +2 -0
  29. package/dist/components/inputs/Input/NumberRangeInput/NumberRangeInput.js +2 -0
  30. package/dist/components/inputs/Input/TextInput/TextInput.js +2 -0
  31. package/dist/components/inputs/Inputs/InputItem.d.ts +1 -1
  32. package/dist/components/inputs/Selection/Autocomplete/Autocomplete.js +5 -0
  33. package/dist/components/inputs/Selection/Select/Select.js +5 -0
  34. package/dist/components/inputs/Selection/shared/SelectMobile.js +2 -1
  35. package/dist/components/inputs/Selection/shared/select.context.js +1 -1
  36. package/dist/components/inputs/Skeleton/InputFrame.js +2 -2
  37. package/dist/components/overlays/BottomSheet/BottomSheet.js +2 -3
  38. package/dist/components/overlays/Tooltip/TooltipEllipsis.d.ts +2 -2
  39. package/dist/components/segment/Segment.js +2 -1
  40. package/dist/components/segment/SegmentItem.d.ts +1 -1
  41. package/dist/components/segment/SegmentItem.js +5 -2
  42. package/dist/components/segment/segment.types.d.ts +1 -0
  43. package/dist/config/link.context.js +4 -2
  44. package/dist/config/uiConfig.context.d.ts +1 -1
  45. package/dist/config/uiConfig.context.js +3 -1
  46. package/dist/index.js +1 -1
  47. package/dist/utils/date-time.utils.d.ts +7 -6
  48. package/dist/utils/date-time.utils.js +55 -16
  49. package/package.json +4 -4
  50. package/dist/components/inputs/DateTime/shared/dateSegment.utils.js +0 -9
@@ -1,8 +1,8 @@
1
1
  import { UIConfig } from "../../../../config/uiConfig.context.js";
2
2
  import { TimePickerForm } from "../shared/TimePickerForm.js";
3
+ import { DateTimeUtils } from "../../../../utils/date-time.utils.js";
3
4
  import { DateTimeDialog } from "../shared/DateTimeDialog.js";
4
5
  import { DateTimeDialogFooter } from "../shared/DateTimeDialogFooter.js";
5
- import { DateTimeUtils } from "../../../../utils/date-time.utils.js";
6
6
  import { getStaticTimeSegments } from "../shared/staticDateTimeSegments.js";
7
7
  import { FormField } from "../../FormField/FormField.js";
8
8
  import { TooltipWrapper } from "../../shared/TooltipWrapper.js";
@@ -141,6 +141,8 @@ var TimePickerBase = (props) => {
141
141
  };
142
142
  var TimePicker = ({ renderStaticInput, ...props }) => {
143
143
  const ui = UIConfig.useConfig();
144
+ let effectiveTimeZone = getLocalTimeZone();
145
+ if (props.timeZone) effectiveTimeZone = props.timeZone;
144
146
  const { locale } = useLocale();
145
147
  const [renderInput, setRenderInput] = useState(!(renderStaticInput ?? ui.renderStaticInput));
146
148
  const inputRef = useRef(null);
@@ -159,13 +161,16 @@ var TimePicker = ({ renderStaticInput, ...props }) => {
159
161
  const rawValue = watchedValue ?? props.value ?? null;
160
162
  const formatTimeValue = (timeValue) => {
161
163
  if (timeValue === null) return null;
162
- const parsedDate = props.date ? DateTime.fromISO(props.date).toJSDate() : void 0;
163
- const dateTimeValue = (parsedDate ? DateTimeUtils.fromLocalToZonedDateTime(parsedDate) : now(getLocalTimeZone())).set(timeValue);
164
- return DateTimeUtils.fromDateValueToISO(dateTimeValue);
164
+ let parsedDate;
165
+ if (props.date) parsedDate = DateTime.fromISO(props.date, { zone: effectiveTimeZone }).toJSDate();
166
+ let dateValue = now(effectiveTimeZone);
167
+ if (parsedDate) dateValue = DateTimeUtils.fromLocalToZonedDateTime(parsedDate, effectiveTimeZone);
168
+ const dateTimeValue = dateValue.set(timeValue);
169
+ return DateTimeUtils.fromDateValueToISO(dateTimeValue, effectiveTimeZone);
165
170
  };
166
171
  const parseTimeValue = (isoString) => {
167
172
  if (isoString == null) return isoString;
168
- return toTime(DateTimeUtils.fromISOtoZonedDateTime(isoString));
173
+ return toTime(DateTimeUtils.fromISOtoZonedDateTime(isoString, effectiveTimeZone));
169
174
  };
170
175
  if (!renderInput) {
171
176
  const timeValue = rawValue ? parseTimeValue(rawValue) : null;
@@ -185,6 +190,7 @@ var TimePicker = ({ renderStaticInput, ...props }) => {
185
190
  isDisabled,
186
191
  className: clsx("relative inline-flex w-full flex-col text-left", props.className),
187
192
  inputClassName: clsx("min-w-input-width-min-width", props.inputClassName),
193
+ contentClassName: "pr-0!",
188
194
  labelPlacement: "content-row",
189
195
  dataAttributes: {
190
196
  dataIsEmpty: timeValue === null,
@@ -198,6 +204,7 @@ var TimePicker = ({ renderStaticInput, ...props }) => {
198
204
  },
199
205
  renderStatic: true,
200
206
  onStaticInteract: renderRealInput,
207
+ trailingClassName: "py-0! pl-0!",
201
208
  trailingContent: showDropdown ? ui.dateInput.timeIcon : void 0,
202
209
  children: staticSegments
203
210
  });
@@ -1,3 +1,4 @@
1
+ import { CalendarDate } from '@internationalized/date';
1
2
  import { CalendarState, CalendarStateOptions } from '@react-stately/calendar';
2
3
  import { DateValue } from 'react-aria';
3
4
  import { DatePickerState } from 'react-stately';
@@ -17,7 +18,11 @@ type CalendarProps = DateTimeCalendarProps & {
17
18
  onApply: (selectedDate?: DateValue) => void;
18
19
  onDateSelectionChange?: (selectedDate: DateValue) => void;
19
20
  setDateValueOnDateSelection?: boolean;
21
+ onMonthYearChange?: (selectedDate: CalendarDate) => void;
22
+ onMonthYearCommit?: () => void;
23
+ selectedDate?: CalendarDate | null;
24
+ granularity?: "day" | "month" | "year";
20
25
  };
21
26
  export type ToggleState = "month" | "year" | "time";
22
- export declare const Calendar: ({ className, includesTime, datePickerState, hourCycle, onApply, onDateSelectionChange, setDateValueOnDateSelection, ...props }: CalendarProps) => import("react/jsx-runtime").JSX.Element;
27
+ export declare const Calendar: ({ className, includesTime, datePickerState, hourCycle, onApply, onMonthYearChange, onMonthYearCommit, selectedDate, granularity, setDateValueOnDateSelection, onDateSelectionChange, ...props }: CalendarProps) => import("react/jsx-runtime").JSX.Element;
23
28
  export {};
@@ -5,12 +5,77 @@ 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 { useCallback, useState } from "react";
8
+ import { useCallback, 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, onDateSelectionChange, setDateValueOnDateSelection = false, ...props }) => {
12
- const [toggleState, setToggleState] = useState(null);
11
+ var Calendar = ({ className, includesTime, datePickerState, hourCycle, onApply, onMonthYearChange, onMonthYearCommit, selectedDate, granularity = "day", setDateValueOnDateSelection = false, onDateSelectionChange, ...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
+ };
55
+ const handleHeaderMonthNavigation = (months) => {
56
+ if (toggleState) return;
57
+ if (!onMonthYearChange) return;
58
+ const focusedDate = props.state.focusedDate;
59
+ if (months === -1) {
60
+ onMonthYearChange(focusedDate.subtract({ months: 1 }));
61
+ return;
62
+ }
63
+ onMonthYearChange(focusedDate.add({ months: 1 }));
64
+ };
65
+ const headerPrevButtonProps = {
66
+ ...prevButtonProps,
67
+ onPress: (event) => {
68
+ prevButtonProps.onPress?.(event);
69
+ handleHeaderMonthNavigation(-1);
70
+ }
71
+ };
72
+ const headerNextButtonProps = {
73
+ ...nextButtonProps,
74
+ onPress: (event) => {
75
+ nextButtonProps.onPress?.(event);
76
+ handleHeaderMonthNavigation(1);
77
+ }
78
+ };
14
79
  const onDateSelection = useCallback((date) => {
15
80
  if (!includesTime || !setDateValueOnDateSelection) return;
16
81
  datePickerState.setDateValue(date);
@@ -32,18 +97,49 @@ var Calendar = ({ className, includesTime, datePickerState, hourCycle, onApply,
32
97
  if (datePickerState?.value && !setDateValueOnDateSelection) onApply(resolvedDate);
33
98
  };
34
99
  const getContent = () => {
35
- if (!toggleState) return /* @__PURE__ */ jsx(CalendarGrid, {
36
- state: props.state,
37
- onApply: handleDateChange,
38
- onDateSelection
39
- });
40
- if (toggleState === "month") return /* @__PURE__ */ jsx(MonthPicker, {
41
- state: props.state,
42
- onSelectionChange: () => setToggleState(null)
43
- });
100
+ if (!toggleState) {
101
+ if (granularity === "month") return /* @__PURE__ */ jsx(MonthPicker, {
102
+ state: props.state,
103
+ onSelectionChange: onMonthSelectionChange,
104
+ onDateChange: onMonthYearChange,
105
+ onCommit: onMonthYearCommit,
106
+ selectedDate
107
+ });
108
+ if (granularity === "year") return /* @__PURE__ */ jsx(YearPicker, {
109
+ state: props.state,
110
+ onSelectionChange: onYearSelectionChange,
111
+ onDateChange: onMonthYearChange,
112
+ onCommit: onMonthYearCommit,
113
+ selectedDate
114
+ });
115
+ return /* @__PURE__ */ jsx(CalendarGrid, {
116
+ state: props.state,
117
+ onApply: handleDateChange,
118
+ onDateSelection
119
+ });
120
+ }
121
+ if (toggleState === "month") {
122
+ if (granularity === "year") return /* @__PURE__ */ jsx(YearPicker, {
123
+ state: props.state,
124
+ onSelectionChange: onYearSelectionChange,
125
+ onDateChange: onMonthYearChange,
126
+ onCommit: onMonthYearCommit,
127
+ selectedDate
128
+ });
129
+ return /* @__PURE__ */ jsx(MonthPicker, {
130
+ state: props.state,
131
+ onSelectionChange: onMonthSelectionChange,
132
+ onDateChange: onMonthYearChange,
133
+ onCommit: onMonthYearCommit,
134
+ selectedDate
135
+ });
136
+ }
44
137
  if (toggleState === "year") return /* @__PURE__ */ jsx(YearPicker, {
45
138
  state: props.state,
46
- onSelectionChange: () => setToggleState(null)
139
+ onSelectionChange: onYearSelectionChange,
140
+ onDateChange: onMonthYearChange,
141
+ onCommit: onMonthYearCommit,
142
+ selectedDate
47
143
  });
48
144
  if (toggleState === "time" && includesTime) return /* @__PURE__ */ jsx("div", {
49
145
  className: "flex h-72 w-80 items-center justify-center",
@@ -57,10 +153,11 @@ var Calendar = ({ className, includesTime, datePickerState, hourCycle, onApply,
57
153
  children: [/* @__PURE__ */ jsx(CalendarHeader, {
58
154
  calendarState: props.state,
59
155
  datePickerState,
60
- prevButtonProps,
61
- nextButtonProps,
156
+ prevButtonProps: headerPrevButtonProps,
157
+ nextButtonProps: headerNextButtonProps,
62
158
  includesTime,
63
159
  hourCycle,
160
+ granularity,
64
161
  toggleState,
65
162
  setToggleState
66
163
  }), /* @__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,10 @@ 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;
14
+ format?: string;
15
+ timeZone?: string;
12
16
  }
13
- export declare const DateField: ({ ref, onClearChange, hidePlaceholder, isDisabled, disableManualEntry, ...props }: DateFieldProps) => import("react/jsx-runtime").JSX.Element;
17
+ export declare const DateField: ({ ref, onClearChange, hidePlaceholder, isDisabled, disableManualEntry, dateGranularity, isTimeOptional, format, timeZone, ...props }: DateFieldProps) => import("react/jsx-runtime").JSX.Element;
14
18
  export {};
@@ -1,13 +1,14 @@
1
1
  import { DateSegmentItem } from "./DateSegmentItem.js";
2
- import { getTimeSegmentValue } from "./dateSegment.utils.js";
3
- import { jsx } from "react/jsx-runtime";
2
+ import { DateTimeUtils } from "../../../../utils/date-time.utils.js";
3
+ import { Fragment, jsx } from "react/jsx-runtime";
4
4
  import { clsx } from "clsx";
5
- import { useEffect, useImperativeHandle, useRef } from "react";
5
+ import { useCallback, useEffect, useImperativeHandle, useMemo, useRef } from "react";
6
6
  import { useDateField, useLocale } from "react-aria";
7
7
  import { createCalendar } from "@internationalized/date";
8
+ import { DateTime } from "luxon";
8
9
  import { useDateFieldState } from "react-stately";
9
10
  //#region src/components/inputs/DateTime/shared/DateField.tsx
10
- var DateField = ({ ref, onClearChange, hidePlaceholder, isDisabled, disableManualEntry, ...props }) => {
11
+ var DateField = ({ ref, onClearChange, hidePlaceholder, isDisabled, disableManualEntry, dateGranularity = "day", isTimeOptional = false, format, timeZone, ...props }) => {
11
12
  const { locale } = useLocale();
12
13
  const state = useDateFieldState({
13
14
  ...props,
@@ -22,6 +23,20 @@ var DateField = ({ ref, onClearChange, hidePlaceholder, isDisabled, disableManua
22
23
  isDisabled,
23
24
  isReadOnly: disableManualEntry
24
25
  }, state, dataFieldRef);
26
+ const isSegmentVisible = useCallback((segmentType) => {
27
+ if (dateGranularity === "day") return true;
28
+ if (dateGranularity === "month") return segmentType !== "day";
29
+ if (dateGranularity === "year") return segmentType === "year";
30
+ return true;
31
+ }, [dateGranularity]);
32
+ const getSegmentsToRender = useCallback(() => {
33
+ const segments = [];
34
+ for (const segment of state.segments) if (segment.type !== "literal") {
35
+ if (isSegmentVisible(segment.type)) segments.push(segment);
36
+ } else if (segments.length > 0 && segments.at(-1)?.type !== "literal") segments.push(segment);
37
+ return segments;
38
+ }, [state.segments, isSegmentVisible]);
39
+ const segmentsToRender = useMemo(() => getSegmentsToRender(), [getSegmentsToRender]);
25
40
  const autoFixYear = () => {
26
41
  const monthSegment = state.segments.find((segment) => segment.type === "month");
27
42
  const daySegment = state.segments.find((segment) => segment.type === "day");
@@ -30,10 +45,27 @@ var DateField = ({ ref, onClearChange, hidePlaceholder, isDisabled, disableManua
30
45
  const minuteSegment = state.segments.find((segment) => segment.type === "minute");
31
46
  const isMonthFilled = monthSegment && !monthSegment.isPlaceholder;
32
47
  const isDayFilled = daySegment && !daySegment.isPlaceholder;
48
+ const isYearFilled = yearSegment && !yearSegment.isPlaceholder && yearSegment.text?.length > 0;
33
49
  const isYearEmpty = yearSegment && !(parseInt(yearSegment.text) && yearSegment.text?.length === 4);
34
- const isHourEmpty = hourSegment && !parseInt(hourSegment.text);
35
- if (minuteSegment && !parseInt(minuteSegment.text)) state.setSegment("minute", getTimeSegmentValue(minuteSegment));
36
- if (isHourEmpty) state.setSegment("hour", getTimeSegmentValue(hourSegment));
50
+ const isDateFilled = isMonthFilled && isDayFilled && isYearFilled;
51
+ const isHourEmpty = hourSegment && (hourSegment.isPlaceholder || Number.isNaN(parseInt(hourSegment.text ?? "", 10)));
52
+ const isMinuteEmpty = minuteSegment && (minuteSegment.isPlaceholder || Number.isNaN(parseInt(minuteSegment.text ?? "", 10)));
53
+ if (!isTimeOptional && isDateFilled && minuteSegment && isMinuteEmpty) {
54
+ let minute = minuteSegment?.value || 0;
55
+ if (minuteSegment?.text?.length && minuteSegment?.text?.length > 0) {
56
+ minute = parseInt(minuteSegment?.text ?? "00");
57
+ if (isNaN(minute)) minute = 0;
58
+ }
59
+ state.setSegment("minute", minute);
60
+ }
61
+ if (!isTimeOptional && isDateFilled && hourSegment && isHourEmpty) {
62
+ let hour = hourSegment?.value || 0;
63
+ if (hourSegment?.text?.length && hourSegment?.text?.length > 0) {
64
+ hour = parseInt(hourSegment?.text ?? "00");
65
+ if (isNaN(hour)) hour = 0;
66
+ }
67
+ state.setSegment("hour", hour);
68
+ }
37
69
  if (isMonthFilled && isDayFilled && isYearEmpty) {
38
70
  let year = (/* @__PURE__ */ new Date()).getFullYear();
39
71
  if (yearSegment?.text?.length && yearSegment?.text?.length === 2) year = parseInt(`20${yearSegment?.text}`);
@@ -64,6 +96,26 @@ var DateField = ({ ref, onClearChange, hidePlaceholder, isDisabled, disableManua
64
96
  useEffect(() => {
65
97
  onClearChange?.(state.segments.some((segment) => segment.type !== "literal" && segment.isPlaceholder === false));
66
98
  }, [state.segments, onClearChange]);
99
+ const getFormattedDisplayValue = () => {
100
+ if (!disableManualEntry) return null;
101
+ if (!format) return null;
102
+ if (!state.value) return null;
103
+ const jsDate = DateTimeUtils.fromDateValueToLocal(state.value, timeZone);
104
+ const formattedDate = DateTime.fromJSDate(jsDate);
105
+ if (!formattedDate.isValid) return null;
106
+ return formattedDate.toFormat(format);
107
+ };
108
+ const formattedDisplayValue = getFormattedDisplayValue();
109
+ let fieldContent = /* @__PURE__ */ jsx(Fragment, { children: segmentsToRender.map((segment, i) => /* @__PURE__ */ jsx(DateSegmentItem, {
110
+ segment,
111
+ state,
112
+ isDisabled,
113
+ hidePlaceholder
114
+ }, i)) });
115
+ if (formattedDisplayValue) fieldContent = /* @__PURE__ */ jsx("span", {
116
+ className: clsx("select-none", isDisabled && "text-interactive-text-secondary-disabled"),
117
+ children: formattedDisplayValue
118
+ });
67
119
  return /* @__PURE__ */ jsx("div", {
68
120
  ...fieldProps,
69
121
  ref: dataFieldRef,
@@ -71,12 +123,7 @@ var DateField = ({ ref, onClearChange, hidePlaceholder, isDisabled, disableManua
71
123
  className: clsx("relative w-full", disableManualEntry && "pointer-events-none"),
72
124
  children: /* @__PURE__ */ jsx("div", {
73
125
  className: "flex",
74
- children: state.segments.map((segment, i) => /* @__PURE__ */ jsx(DateSegmentItem, {
75
- segment,
76
- state,
77
- isDisabled,
78
- hidePlaceholder
79
- }, i))
126
+ children: fieldContent
80
127
  })
81
128
  });
82
129
  };
@@ -29,6 +29,10 @@ interface DatePickerInputProps extends InputVariantProps {
29
29
  placeholder?: string;
30
30
  className?: string;
31
31
  onOpenDropdown?: () => void;
32
+ dateGranularity?: "day" | "month" | "year";
33
+ timeZone?: string;
34
+ isTimeOptional?: boolean;
35
+ format?: string;
32
36
  }
33
- export declare const DatePickerInput: ({ ref, as, groupProps, fieldProps, endFieldProps, buttonProps, isDisabled, isInvalid, disableDropdown, variant, size, isDateTime, isClearable, headerProps, todayIcon, todayIconButtonSize, todayIconPlacement, isDirty, isRequired, disableManualEntry, autoFixYear, placeholder, className, onOpenDropdown, ...props }: DatePickerInputProps) => import("react/jsx-runtime").JSX.Element;
37
+ export declare const DatePickerInput: ({ ref, as, groupProps, fieldProps, endFieldProps, buttonProps, isDisabled, isInvalid, disableDropdown, variant, size, isDateTime, isClearable, headerProps, todayIcon, todayIconButtonSize, todayIconPlacement, isDirty, isRequired, disableManualEntry, autoFixYear, placeholder, className, onOpenDropdown, dateGranularity, timeZone, isTimeOptional, format, ...props }: DatePickerInputProps) => import("react/jsx-runtime").JSX.Element;
34
38
  export {};
@@ -15,8 +15,10 @@ import { Button } from "react-aria-components";
15
15
  import { useFocusVisible, useFocusWithin, useHover } from "react-aria";
16
16
  import { getLocalTimeZone, now, toCalendarDateTime, today } from "@internationalized/date";
17
17
  //#region src/components/inputs/DateTime/shared/DatePickerInput.tsx
18
- var DatePickerInput = ({ ref, as, groupProps, fieldProps, endFieldProps, buttonProps, isDisabled, isInvalid, disableDropdown, variant, size, isDateTime, isClearable, headerProps, todayIcon, todayIconButtonSize = "none", todayIconPlacement = "content", isDirty, isRequired, disableManualEntry, autoFixYear = false, placeholder, className, onOpenDropdown, ...props }) => {
18
+ var DatePickerInput = ({ ref, as, groupProps, fieldProps, endFieldProps, buttonProps, isDisabled, isInvalid, disableDropdown, variant, size, isDateTime, isClearable, headerProps, todayIcon, todayIconButtonSize = "none", todayIconPlacement = "content", isDirty, isRequired, disableManualEntry, autoFixYear = false, placeholder, className, onOpenDropdown, dateGranularity = "day", timeZone, isTimeOptional = false, format, ...props }) => {
19
19
  const uiConfig = UIConfig.useConfig();
20
+ let effectiveTimeZone = getLocalTimeZone();
21
+ if (timeZone) effectiveTimeZone = timeZone;
20
22
  const inputBaseCva = UIStyle.useCva("input.baseCva", inputBase);
21
23
  const inputSizeCva = UIStyle.useCva("input.sizeCva", inputSize);
22
24
  const datePickerInputContentRowCva = UIStyle.useCva("datePickerInput.contentRowCva", datePickerInputContentRow);
@@ -60,12 +62,12 @@ var DatePickerInput = ({ ref, as, groupProps, fieldProps, endFieldProps, buttonP
60
62
  };
61
63
  const onToday = () => {
62
64
  if (isDateTime) {
63
- const calendarDateTime = toCalendarDateTime(now(getLocalTimeZone()));
65
+ const calendarDateTime = toCalendarDateTime(now(effectiveTimeZone));
64
66
  fieldProps.onChange?.(calendarDateTime);
65
67
  if (endFieldProps) endFieldProps.onChange?.(calendarDateTime);
66
68
  } else {
67
- fieldProps.onChange?.(today(getLocalTimeZone()));
68
- if (endFieldProps) endFieldProps.onChange?.(today(getLocalTimeZone()));
69
+ fieldProps.onChange?.(today(effectiveTimeZone));
70
+ if (endFieldProps) endFieldProps.onChange?.(today(effectiveTimeZone));
69
71
  }
70
72
  fieldProps.onBlur?.(null);
71
73
  endFieldProps?.onBlur?.(null);
@@ -135,7 +137,11 @@ var DatePickerInput = ({ ref, as, groupProps, fieldProps, endFieldProps, buttonP
135
137
  isInvalid,
136
138
  onClearChange,
137
139
  hidePlaceholder,
138
- disableManualEntry
140
+ disableManualEntry,
141
+ dateGranularity,
142
+ isTimeOptional,
143
+ format,
144
+ timeZone: effectiveTimeZone
139
145
  }), endFieldProps && /* @__PURE__ */ jsxs(Fragment, { children: [!((as === "floating" || as === "filter") && hidePlaceholder) && /* @__PURE__ */ jsx("span", {
140
146
  className: clsx("pointer-events-none select-none", isDisabled && "text-interactive-text-secondary-disabled"),
141
147
  children: "–"
@@ -146,7 +152,10 @@ var DatePickerInput = ({ ref, as, groupProps, fieldProps, endFieldProps, buttonP
146
152
  isInvalid,
147
153
  onClearChange,
148
154
  hidePlaceholder,
149
- disableManualEntry
155
+ disableManualEntry,
156
+ isTimeOptional,
157
+ format,
158
+ timeZone: effectiveTimeZone
150
159
  })] })] })
151
160
  ]
152
161
  })
@@ -1,7 +1,11 @@
1
+ import { CalendarDate } from '@internationalized/date';
1
2
  import { CalendarState, RangeCalendarState } from '@react-stately/calendar';
2
3
  import { Key } from 'react-aria-components';
3
4
  export interface MonthPickerProps {
4
5
  state: CalendarState | RangeCalendarState;
5
6
  onSelectionChange: (key: Set<Key>) => void;
7
+ onDateChange?: (selectedDate: CalendarDate) => void;
8
+ onCommit?: () => void;
9
+ selectedDate?: CalendarDate | null;
6
10
  }
7
- export declare const MonthPicker: ({ state, onSelectionChange }: MonthPickerProps) => import("react/jsx-runtime").JSX.Element;
11
+ export declare const MonthPicker: ({ state, onSelectionChange, onDateChange, onCommit, selectedDate }: MonthPickerProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,10 +1,11 @@
1
1
  import { Typography } from "../../../text/Typography/Typography.js";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  import { clsx } from "clsx";
4
+ import { useRef } from "react";
4
5
  import { ListBox, ListBoxItem } from "react-aria-components";
5
6
  import { useDateFormatter } from "@react-aria/i18n";
6
7
  //#region src/components/inputs/DateTime/shared/MonthPicker.tsx
7
- var MonthPicker = ({ state, onSelectionChange }) => {
8
+ var MonthPicker = ({ state, onSelectionChange, onDateChange, onCommit, selectedDate }) => {
8
9
  const formatter = useDateFormatter({
9
10
  month: "long",
10
11
  timeZone: state.timeZone
@@ -23,34 +24,65 @@ var MonthPicker = ({ state, onSelectionChange }) => {
23
24
  if (state.maxValue && state.focusedDate.set({ month }) > state.maxValue) return true;
24
25
  return false;
25
26
  };
27
+ const getSelectedMonth = () => {
28
+ if (!selectedDate) return null;
29
+ return selectedDate.month;
30
+ };
31
+ const selectedMonth = getSelectedMonth();
32
+ const lastPressedMonthRef = useRef(null);
33
+ const listBoxSelectionProps = {};
34
+ if (selectedMonth !== null) listBoxSelectionProps.selectedKeys = [selectedMonth];
35
+ const parseMonthFromKey = (key) => {
36
+ if (typeof key === "number") return key;
37
+ if (typeof key === "string") {
38
+ const parsedMonth = Number.parseInt(key, 10);
39
+ if (!Number.isNaN(parsedMonth)) return parsedMonth;
40
+ }
41
+ return null;
42
+ };
26
43
  return /* @__PURE__ */ jsx(ListBox, {
27
44
  autoFocus: true,
28
45
  "aria-label": "Month",
29
46
  selectionMode: "single",
30
47
  layout: "grid",
31
- selectedKeys: [state.focusedDate.month],
48
+ ...listBoxSelectionProps,
32
49
  onSelectionChange: (key) => {
33
50
  if (key === "all") return;
34
- if (typeof [...key][0] === "number") {
35
- const date = state.focusedDate.set({ month: [...key][0] });
36
- state.setFocusedDate(date);
51
+ const selectedKey = [...key][0];
52
+ const selectedMonthValue = parseMonthFromKey(selectedKey);
53
+ if (selectedMonthValue !== null) {
54
+ const nextSelectedDate = state.focusedDate.set({ month: selectedMonthValue });
55
+ state.setFocusedDate(nextSelectedDate);
56
+ onDateChange?.(nextSelectedDate);
37
57
  }
38
58
  onSelectionChange(key);
39
59
  },
40
60
  className: "grid size-full min-h-72 grid-cols-3 grid-rows-4 gap-2 p-3 md:w-80",
41
61
  children: getMonths().map((month, index) => {
42
- const isDisabled = isMonthDisabled(index + 1);
62
+ const monthNumber = index + 1;
63
+ const isDisabled = isMonthDisabled(monthNumber);
43
64
  return /* @__PURE__ */ jsx(ListBoxItem, {
44
- id: index + 1,
65
+ id: monthNumber,
45
66
  textValue: month,
46
67
  isDisabled,
68
+ onPress: () => {
69
+ const isSecondConsecutivePress = lastPressedMonthRef.current === monthNumber;
70
+ lastPressedMonthRef.current = monthNumber;
71
+ const nextSelectedDate = state.focusedDate.set({ month: monthNumber });
72
+ state.setFocusedDate(nextSelectedDate);
73
+ onDateChange?.(nextSelectedDate);
74
+ if (!isSecondConsecutivePress) return;
75
+ if (selectedMonth === null) return;
76
+ if (monthNumber !== selectedMonth) return;
77
+ onCommit?.();
78
+ },
47
79
  className: clsx("flex items-center justify-center text-interactive-text-secondary-idle", "rounded-button-rounding-m border border-elevation-outline-default-1 border-solid bg-elevation-fill-default-1", "hover:text-interactive-text-secondary-hover", "selected:border-interactive-contained-primary-idle selected:bg-interactive-contained-primary-idle selected:text-interactive-text-secondary-idle-inverted", "focus:outline-none focus-visible:outline-1 focus-visible:outline-interactive-contained-primary-focus focus-visible:outline-offset-1", isDisabled ? "cursor-default opacity-50" : "cursor-pointer"),
48
80
  children: /* @__PURE__ */ jsx(Typography, {
49
81
  as: "span",
50
82
  size: "label-2",
51
83
  children: month
52
84
  })
53
- }, month);
85
+ }, monthNumber);
54
86
  })
55
87
  });
56
88
  };
@@ -1,8 +1,12 @@
1
+ import { CalendarDate } from '@internationalized/date';
1
2
  import { CalendarState, RangeCalendarState } from '@react-stately/calendar';
2
3
  import { Key } from 'react-aria-components';
3
4
  interface YearPickerProps {
4
5
  state: CalendarState | RangeCalendarState;
5
6
  onSelectionChange: (key: Set<Key>) => void;
7
+ onDateChange?: (selectedDate: CalendarDate) => void;
8
+ onCommit?: () => void;
9
+ selectedDate?: CalendarDate | null;
6
10
  }
7
- export declare const YearPicker: ({ state, onSelectionChange }: YearPickerProps) => import("react/jsx-runtime").JSX.Element;
11
+ export declare const YearPicker: ({ state, onSelectionChange, onDateChange, onCommit, selectedDate }: YearPickerProps) => import("react/jsx-runtime").JSX.Element;
8
12
  export {};