@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,4 +1,4 @@
1
- import { FC, ReactElement, Ref, SVGProps } from 'react';
1
+ import { FC, ReactElement, ReactNode, Ref, SVGProps } from 'react';
2
2
  import { ButtonProps as AriaButtonProps, ToggleButtonProps as AriaToggleButtonProps } from 'react-aria-components';
3
3
  import { ButtonContentVariantProps } from '../shared/buttonContent.cva';
4
4
  import { LinkNavigationProps } from '../../text/Link/Link';
@@ -17,13 +17,12 @@ type ToggleButtonProps = {
17
17
  isSelected?: boolean;
18
18
  } & AriaToggleButtonProps);
19
19
  export type ButtonProps<IconOnly extends boolean = false> = ButtonVariantProps & ButtonContentVariantProps & AriaButtonProps & ButtonIconProps<IconOnly> & ToggleButtonProps & {
20
- children: string;
20
+ children: ReactNode;
21
21
  isLoading?: boolean;
22
22
  link?: LinkNavigationProps;
23
23
  noDisableWhenLoading?: boolean;
24
24
  iconClassName?: string;
25
25
  contentRef?: Ref<HTMLElement>;
26
- staticRender?: boolean;
27
26
  };
28
- export declare const Button: <IconOnly extends boolean = false>({ icon: Icon, iconPosition, children, isLoading, className, link, iconClassName, noDisableWhenLoading, contentRef, staticRender, ...props }: ButtonProps<IconOnly>) => import("react/jsx-runtime").JSX.Element;
27
+ export declare const Button: <IconOnly extends boolean = false>({ icon: Icon, iconPosition, children, isLoading, className, link, iconClassName, noDisableWhenLoading, contentRef, ...props }: ButtonProps<IconOnly>) => import("react/jsx-runtime").JSX.Element;
29
28
  export {};
@@ -7,11 +7,10 @@ import { jsx } from "react/jsx-runtime";
7
7
  import { clsx } from "clsx";
8
8
  import { Button, Link, ToggleButton } from "react-aria-components";
9
9
  //#region src/components/buttons/Button/Button.tsx
10
- var Button$1 = ({ icon: Icon, iconPosition, children, isLoading, className, link, iconClassName, noDisableWhenLoading, contentRef, staticRender, ...props }) => {
10
+ var Button$1 = ({ icon: Icon, iconPosition, children, isLoading, className, link, iconClassName, noDisableWhenLoading, contentRef, ...props }) => {
11
11
  const linkContext = LinkContext.useLinkContext();
12
12
  const uiConfig = UIConfig.useConfig();
13
- const variant = props.variant ?? uiConfig.button.variant;
14
- const size = props.size ?? uiConfig.button.size;
13
+ const { variant = uiConfig.button.variant, size = uiConfig.button.size } = props;
15
14
  const buttonCva = UIStyle.useCva("button.cva", button);
16
15
  const buttonSizeCva = UIStyle.useCva("button.sizeCva", buttonSize);
17
16
  const buttonContentCva = UIStyle.useCva("button.contentCva", buttonContent);
@@ -23,53 +22,45 @@ var Button$1 = ({ icon: Icon, iconPosition, children, isLoading, className, link
23
22
  return Button;
24
23
  })();
25
24
  if (link && !link.to && link.href) link.to = link.href;
26
- const resolvedClassName = clsx(buttonCva({
27
- ...props,
28
- variant,
29
- size,
30
- className
31
- }), buttonSizeCva({
32
- ...props,
33
- variant,
34
- size
35
- }), buttonContentCva({
25
+ return /* @__PURE__ */ jsx(Component, {
36
26
  ...props,
37
- variant,
38
- size,
39
- iconPosition: !Icon ? "none" : iconPosition
40
- }));
41
- const content = /* @__PURE__ */ jsx(ButtonContent, {
42
- ref: contentRef,
43
- isLoading,
44
- icon: Icon,
45
- text: children,
46
- hideText: props.iconOnly,
47
- iconPosition,
48
- iconClassName: buttonIconSizeCva({
27
+ ...link,
28
+ isDisabled: props.isDisabled || isLoading && !noDisableWhenLoading,
29
+ className: clsx(buttonCva({
49
30
  ...props,
50
31
  variant,
51
32
  size,
52
- className: iconClassName
53
- }),
54
- typography: typographyMap({
33
+ className
34
+ }), buttonSizeCva({
55
35
  ...props,
56
36
  variant,
57
37
  size
38
+ }), buttonContentCva({
39
+ ...props,
40
+ variant,
41
+ size,
42
+ iconPosition: !Icon ? "none" : iconPosition
43
+ })),
44
+ children: /* @__PURE__ */ jsx(ButtonContent, {
45
+ ref: contentRef,
46
+ isLoading,
47
+ icon: Icon,
48
+ content: children,
49
+ hideText: props.iconOnly,
50
+ iconPosition,
51
+ iconClassName: buttonIconSizeCva({
52
+ ...props,
53
+ variant,
54
+ size,
55
+ className: iconClassName
56
+ }),
57
+ typography: typographyMap({
58
+ ...props,
59
+ variant,
60
+ size
61
+ })
58
62
  })
59
63
  });
60
- if (staticRender) return /* @__PURE__ */ jsx("div", {
61
- "aria-label": props.iconOnly ? children : void 0,
62
- "aria-disabled": props.isDisabled || void 0,
63
- className: resolvedClassName,
64
- children: content
65
- });
66
- return /* @__PURE__ */ jsx(Component, {
67
- ...props,
68
- ...link,
69
- isDisabled: props.isDisabled || isLoading && !noDisableWhenLoading,
70
- className: resolvedClassName,
71
- children: content
72
- });
73
64
  };
74
65
  //#endregion
75
66
  export { Button$1 as Button };
@@ -1,9 +1,9 @@
1
- import { FC, Ref, SVGProps } from 'react';
1
+ import { FC, ReactNode, Ref, SVGProps } from 'react';
2
2
  import { ButtonProps as AriaButtonProps, ToggleButtonProps as AriaToggleButtonProps } from 'react-aria-components';
3
3
  import { PillButtonVariants } from './pillButton.cva';
4
4
  import { ButtonContentVariantProps } from '../shared/buttonContent.cva';
5
5
  export interface PillButtonProps extends AriaButtonProps, Omit<AriaToggleButtonProps, keyof AriaButtonProps>, ButtonContentVariantProps, PillButtonVariants {
6
- children: string;
6
+ children: ReactNode;
7
7
  dismissable?: boolean;
8
8
  toggle?: boolean;
9
9
  icon?: FC<SVGProps<SVGSVGElement>>;
@@ -22,7 +22,7 @@ var PillButton = ({ children, dismissable, toggle, icon, iconPosition, contentRe
22
22
  }), pillButtonContent({ iconPosition: getIconPosition() })),
23
23
  children: /* @__PURE__ */ jsx(ButtonContent, {
24
24
  ref: contentRef,
25
- text: children,
25
+ content: children,
26
26
  icon: dismissable ? CloseIcon : icon,
27
27
  iconPosition: dismissable ? "right" : iconPosition,
28
28
  iconClassName: pillButtonIconSize,
@@ -1,10 +1,11 @@
1
1
  import { ButtonProps as AriaButtonProps } from 'react-aria-components';
2
+ import { ReactNode } from 'react';
2
3
  import { ButtonIconProps } from '../Button/Button';
3
4
  import { ButtonVariantProps } from '../Button/button.cva';
4
5
  import { ButtonContentVariantProps } from '../shared/buttonContent.cva';
5
6
  import { LinkNavigationProps } from '../../text/Link/Link';
6
7
  export type TextButtonProps = Omit<ButtonVariantProps, "variant"> & ButtonContentVariantProps & AriaButtonProps & ButtonIconProps<true | false> & {
7
- children: string;
8
+ children: ReactNode;
8
9
  isLoading?: boolean;
9
10
  link?: LinkNavigationProps;
10
11
  };
@@ -1,8 +1,9 @@
1
1
  import { ToggleButtonProps as AriaToggleButtonProps } from 'react-aria-components';
2
+ import { ReactNode } from 'react';
2
3
  import { ButtonIconProps } from '../Button/Button';
3
4
  import { ButtonVariantProps } from '../Button/button.cva';
4
5
  import { ButtonContentVariantProps } from '../shared/buttonContent.cva';
5
6
  export type ToggleButtonProps = ButtonVariantProps & ButtonContentVariantProps & AriaToggleButtonProps & ButtonIconProps<true | false> & {
6
- children: string;
7
+ children: ReactNode;
7
8
  };
8
9
  export declare const ToggleButton: ({ children, ...props }: ToggleButtonProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,14 +1,14 @@
1
- import { FC, ReactElement, Ref, SVGProps } from 'react';
1
+ import { FC, ReactElement, ReactNode, Ref, SVGProps } from 'react';
2
2
  import { ButtonContentVariantProps } from './buttonContent.cva';
3
3
  import { TypographyVariantProps } from '../../text/Typography/typography.cva';
4
4
  interface ButtonContentProps extends ButtonContentVariantProps {
5
5
  ref?: Ref<HTMLElement>;
6
- text: string;
6
+ content: ReactNode;
7
7
  isLoading?: boolean;
8
8
  icon?: FC<SVGProps<SVGSVGElement>> | ReactElement;
9
9
  iconClassName?: string;
10
10
  hideText?: boolean;
11
11
  typography?: TypographyVariantProps;
12
12
  }
13
- export declare const ButtonContent: ({ ref, text, isLoading, icon: Icon, iconClassName, hideText, iconPosition, typography: typographyOverrides, }: ButtonContentProps) => import("react/jsx-runtime").JSX.Element;
13
+ export declare const ButtonContent: ({ ref, content, isLoading, icon: Icon, iconClassName, hideText, iconPosition, typography: typographyOverrides, }: ButtonContentProps) => import("react/jsx-runtime").JSX.Element;
14
14
  export {};
@@ -6,7 +6,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
6
  import { clsx } from "clsx";
7
7
  import { isValidElement } from "react";
8
8
  //#region src/components/buttons/shared/ButtonContent.tsx
9
- var ButtonContent = ({ ref, text, isLoading, icon: Icon, iconClassName, hideText, iconPosition = "left", typography: typographyOverrides }) => {
9
+ var ButtonContent = ({ ref, content, isLoading, icon: Icon, iconClassName, hideText, iconPosition = "left", typography: typographyOverrides }) => {
10
10
  const typographyCva = UIStyle.useCva("typography.cva", typography);
11
11
  let iconOrLoader = null;
12
12
  if (isLoading) iconOrLoader = /* @__PURE__ */ jsx(Loader, { className: "shrink-0" });
@@ -28,7 +28,7 @@ var ButtonContent = ({ ref, text, isLoading, icon: Icon, iconClassName, hideText
28
28
  hideText: !!hideText
29
29
  })),
30
30
  ref,
31
- children: text
31
+ children: content
32
32
  }),
33
33
  iconOrLoader && iconPosition === "right" && iconOrLoader
34
34
  ] });
@@ -7,6 +7,7 @@ import { DatePickerTodayIcon, DatePickerTodayIconButtonSize, DatePickerTodayIcon
7
7
  import { FormFieldProps } from '../../FormField/FormField';
8
8
  import { ControlProps } from '../../shared/form.types';
9
9
  import { InputVariantProps } from '../../shared/input.cva';
10
+ type DatePickerGranularity = "day" | "month" | "year";
10
11
  interface DatePickerBaseProps extends FormFieldProps, InputVariantProps, Omit<DatePickerStateOptions<CalendarDate>, "granularity" | "shouldCloseOnSelect" | "label" | "onBlur"> {
11
12
  ref?: Ref<DatePickerInputHandle & HTMLDivElement>;
12
13
  disableDropdown?: boolean;
@@ -21,6 +22,9 @@ interface DatePickerBaseProps extends FormFieldProps, InputVariantProps, Omit<Da
21
22
  placeholder?: string;
22
23
  inputClassName?: string;
23
24
  onBlur?: (e: FocusEvent<HTMLInputElement>) => void;
25
+ shouldUpdateDateOnMonthYearChange?: boolean;
26
+ granularity?: DatePickerGranularity;
27
+ format?: string;
24
28
  }
25
29
  export interface DatePickerProps extends Omit<DatePickerBaseProps, "value" | "onChange" | "minValue" | "maxValue"> {
26
30
  value?: string | null;
@@ -31,5 +35,5 @@ export interface DatePickerProps extends Omit<DatePickerBaseProps, "value" | "on
31
35
  renderStaticInput?: boolean;
32
36
  }
33
37
  export type ControlledDatePickerProps<TFieldValues extends FieldValues> = ControlProps<DatePickerProps, TFieldValues>;
34
- export declare const DatePicker: <TFieldValues extends FieldValues>({ fullIso, minValue, maxValue, renderStaticInput, ...props }: ControlledDatePickerProps<TFieldValues>) => import("react/jsx-runtime").JSX.Element;
38
+ export declare const DatePicker: <TFieldValues extends FieldValues>({ fullIso, granularity, minValue, maxValue, renderStaticInput, ...props }: ControlledDatePickerProps<TFieldValues>) => import("react/jsx-runtime").JSX.Element;
35
39
  export {};
@@ -1,32 +1,38 @@
1
1
  import { UIStyle } from "../../../../config/uiStyle.context.js";
2
2
  import { UIConfig } from "../../../../config/uiConfig.context.js";
3
3
  import { Calendar } from "../shared/Calendar.js";
4
+ import { DateTimeUtils } from "../../../../utils/date-time.utils.js";
4
5
  import { datePickerInputContentRow } from "../shared/datePickerInput.cva.js";
5
6
  import { renderDatePickerTodayIcon } from "../shared/datePickerTodayIcon.js";
6
7
  import { DatePickerInput } from "../shared/DatePickerInput.js";
7
8
  import { DateTimeDialog } from "../shared/DateTimeDialog.js";
8
9
  import { DateTimeDialogFooter } from "../shared/DateTimeDialogFooter.js";
9
- import { DateTimeUtils } from "../../../../utils/date-time.utils.js";
10
10
  import { getStaticCalendarDateSegments } from "../shared/staticDateTimeSegments.js";
11
11
  import { FormField } from "../../FormField/FormField.js";
12
12
  import { TooltipWrapper } from "../../shared/TooltipWrapper.js";
13
13
  import { InputFrame } from "../../Skeleton/InputFrame.js";
14
14
  import { useStaticInputHandoff } from "../../shared/useStaticInputHandoff.js";
15
- import { useDebounceCallback } from "../../../../hooks/useDebounceCallback.js";
16
15
  import { jsx, jsxs } from "react/jsx-runtime";
17
16
  import { clsx } from "clsx";
18
- import { useImperativeHandle, useMemo, useRef, useState } from "react";
17
+ import { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
19
18
  import { useDatePicker, useLocale } from "react-aria";
20
19
  import { mergeRefs } from "@react-aria/utils";
21
20
  import { Controller, useWatch } from "react-hook-form";
22
- import { CalendarDate, createCalendar, getLocalTimeZone, toCalendarDate, today } from "@internationalized/date";
21
+ import { createCalendar, getLocalTimeZone, toCalendarDate, today } from "@internationalized/date";
23
22
  import { DateTime } from "luxon";
24
23
  import { useCalendarState, useDatePickerState } from "react-stately";
25
24
  //#region src/components/inputs/DateTime/DatePicker/DatePicker.tsx
26
- var PLACEHOLDER_VALUE = new CalendarDate(2024, 1, 1);
27
25
  var DatePickerBase = (props) => {
28
26
  const ui = UIConfig.useConfig();
29
- const { ref, label, tooltipText, helperText, isRequired, rightContent, isDirty, isDisabled, headerClassName, errorClassName, isHeaderHidden, error, onChange, onBlur, value, disableDropdown, className, placeholder, inputClassName, as = ui.input.as, hideLabel = ui.input.hideLabel, variant = ui.input.variant, size = ui.input.size, isClearable = ui.input.isClearable, todayIcon = ui.dateInput.todayIcon, todayIconButtonSize = ui.dateInput.todayIconButtonSize, todayIconPlacement = ui.dateInput.todayIconPlacement, shouldForceLeadingZeros = ui.dateInput.shouldForceLeadingZeros, disableManualEntry = ui.dateInput.disableManualEntry, autoFixYear = ui.dateInput.autoFixYear, ...rest } = props;
27
+ const { ref, label, tooltipText, helperText, isRequired, rightContent, isDirty, isDisabled, headerClassName, errorClassName, isHeaderHidden, error, onChange, onBlur, value, disableDropdown, className, placeholder, inputClassName, as = ui.input.as, hideLabel = ui.input.hideLabel, variant = ui.input.variant, size = ui.input.size, isClearable = ui.input.isClearable, todayIcon = ui.dateInput.todayIcon, todayIconButtonSize = ui.dateInput.todayIconButtonSize, todayIconPlacement = ui.dateInput.todayIconPlacement, shouldForceLeadingZeros = ui.dateInput.shouldForceLeadingZeros, disableManualEntry = ui.dateInput.disableManualEntry, shouldUpdateDateOnMonthYearChange = ui.dateInput.shouldUpdateDateOnMonthYearChange, granularity = ui.dateInput.granularity, autoFixYear = ui.dateInput.autoFixYear, format, ...rest } = props;
28
+ const normalizeByGranularity = useCallback((date) => {
29
+ if (granularity === "year") return date.set({
30
+ month: 1,
31
+ day: 1
32
+ });
33
+ if (granularity === "month") return date.set({ day: 1 });
34
+ return date;
35
+ }, [granularity]);
30
36
  const formFieldProps = {
31
37
  error,
32
38
  label,
@@ -50,7 +56,6 @@ var DatePickerBase = (props) => {
50
56
  const handleBlur = (val) => {
51
57
  onBlur?.({ target: { value: val } });
52
58
  };
53
- const { callback: debouncedBlur } = useDebounceCallback(handleBlur, { delay: 500 });
54
59
  const dialogState = useDatePickerState({
55
60
  ...rest,
56
61
  defaultValue: value || rest.defaultValue,
@@ -62,14 +67,19 @@ var DatePickerBase = (props) => {
62
67
  shouldForceLeadingZeros,
63
68
  value,
64
69
  onChange: (val) => {
65
- if (val && (rest.minValue && val < rest?.minValue || rest?.maxValue && val > rest?.maxValue)) {
70
+ let normalizedValue = val;
71
+ if (val) normalizedValue = normalizeByGranularity(val);
72
+ if (normalizedValue && (rest.minValue && normalizedValue < rest?.minValue || rest?.maxValue && normalizedValue > rest?.maxValue)) {
66
73
  state.setValue(state.value);
67
74
  return;
68
75
  }
69
- onChange?.(val);
70
- dialogState.setValue(val);
71
- calendarState.setFocusedDate(val || today(getLocalTimeZone()));
72
- debouncedBlur(val);
76
+ onChange?.(normalizedValue);
77
+ dialogState.setValue(normalizedValue);
78
+ if (normalizedValue) {
79
+ calendarState.setFocusedDate(normalizedValue);
80
+ return;
81
+ }
82
+ calendarState.setFocusedDate(today(getLocalTimeZone()));
73
83
  },
74
84
  shouldCloseOnSelect: false
75
85
  });
@@ -101,18 +111,47 @@ var DatePickerBase = (props) => {
101
111
  labelProps
102
112
  };
103
113
  const onApply = () => {
104
- const newValue = dialogState.value;
105
- state.setValue(newValue);
114
+ if (dialogState.value) state.setValue(normalizeByGranularity(dialogState.value));
115
+ else state.setValue(dialogState.value);
106
116
  state.toggle();
107
117
  handleBlur(newValue);
108
118
  };
119
+ const onMonthYearChange = (selectedDate) => {
120
+ if (!(shouldUpdateDateOnMonthYearChange || granularity !== "day")) return;
121
+ const updatedDate = normalizeByGranularity((dialogState.value || state.value || today(getLocalTimeZone())).set({
122
+ year: selectedDate.year,
123
+ month: selectedDate.month
124
+ }));
125
+ dialogState.setValue(updatedDate);
126
+ calendarState.setFocusedDate(updatedDate);
127
+ };
128
+ const onMonthYearCommit = () => {
129
+ onApply();
130
+ };
109
131
  const onTodayPress = () => {
110
- dialogState.setValue(today(getLocalTimeZone()));
111
- calendarState.setFocusedDate(today(getLocalTimeZone()));
132
+ const todayValue = normalizeByGranularity(today(getLocalTimeZone()));
133
+ dialogState.setValue(todayValue);
134
+ calendarState.setFocusedDate(todayValue);
112
135
  };
136
+ useEffect(() => {
137
+ if (!state.isOpen) return;
138
+ if (granularity !== "year") return;
139
+ if (dialogState.value) return;
140
+ const defaultYearValue = normalizeByGranularity(today(getLocalTimeZone()));
141
+ dialogState.setValue(defaultYearValue);
142
+ calendarState.setFocusedDate(defaultYearValue);
143
+ }, [
144
+ state.isOpen,
145
+ granularity,
146
+ dialogState.value,
147
+ dialogState,
148
+ calendarState,
149
+ normalizeByGranularity
150
+ ]);
113
151
  const onOpenChange = (isOpen) => {
114
152
  state.toggle();
115
- calendarState.setFocusedDate(state.value || today(getLocalTimeZone()));
153
+ if (state.value) calendarState.setFocusedDate(normalizeByGranularity(state.value));
154
+ if (!state.value) calendarState.setFocusedDate(today(getLocalTimeZone()));
116
155
  if (!isOpen) dialogState.setValue(state.value);
117
156
  };
118
157
  return /* @__PURE__ */ jsx(TooltipWrapper, {
@@ -129,10 +168,7 @@ var DatePickerBase = (props) => {
129
168
  ref: mergeRefs(ref, datePickerInputRef),
130
169
  as,
131
170
  groupProps,
132
- fieldProps: {
133
- ...fieldProps,
134
- placeholderValue: PLACEHOLDER_VALUE
135
- },
171
+ fieldProps,
136
172
  buttonProps,
137
173
  isDirty,
138
174
  isDisabled,
@@ -149,7 +185,9 @@ var DatePickerBase = (props) => {
149
185
  todayIconPlacement,
150
186
  onOpenDropdown: () => state.toggle(),
151
187
  placeholder,
152
- className: inputClassName
188
+ className: inputClassName,
189
+ dateGranularity: granularity,
190
+ format
153
191
  }), (!disableDropdown || disableManualEntry) && state.isOpen && /* @__PURE__ */ jsx(DateTimeDialog, {
154
192
  footer: /* @__PURE__ */ jsx(DateTimeDialogFooter, {
155
193
  isDisabled,
@@ -165,13 +203,17 @@ var DatePickerBase = (props) => {
165
203
  children: /* @__PURE__ */ jsx(Calendar, {
166
204
  state: calendarState,
167
205
  calendarProps,
168
- onApply
206
+ onApply,
207
+ onMonthYearChange,
208
+ onMonthYearCommit,
209
+ selectedDate: dialogState.value ?? null,
210
+ granularity
169
211
  })
170
212
  })]
171
213
  })
172
214
  });
173
215
  };
174
- var DatePicker = ({ fullIso = true, minValue, maxValue, renderStaticInput, ...props }) => {
216
+ var DatePicker = ({ fullIso = true, granularity = "day", minValue, maxValue, renderStaticInput, ...props }) => {
175
217
  const ui = UIConfig.useConfig();
176
218
  const datePickerInputContentRowCva = UIStyle.useCva("datePickerInput.contentRowCva", datePickerInputContentRow);
177
219
  const { locale } = useLocale();
@@ -193,17 +235,26 @@ var DatePicker = ({ fullIso = true, minValue, maxValue, renderStaticInput, ...pr
193
235
  let isFormControlDisabled = false;
194
236
  if ("formControl" in props && props.formControl) isFormControlDisabled = !!props.formControl.control._options?.disabled;
195
237
  const rawValue = watchedValue ?? props.value ?? null;
238
+ const normalizeByGranularity = (date) => {
239
+ if (granularity === "year") return date.set({
240
+ month: 1,
241
+ day: 1
242
+ });
243
+ if (granularity === "month") return date.set({ day: 1 });
244
+ return date;
245
+ };
196
246
  const formatCalendarDate = (calendarDate) => {
197
247
  if (calendarDate === null) return null;
198
- if (fullIso) return DateTimeUtils.fromCalendarDateToUTCISO(calendarDate);
199
- const date = DateTimeUtils.fromDateValueToLocal(calendarDate);
248
+ const normalizedDate = normalizeByGranularity(calendarDate);
249
+ if (fullIso) return DateTimeUtils.fromCalendarDateToUTCISO(normalizedDate);
250
+ const date = DateTimeUtils.fromDateValueToLocal(normalizedDate);
200
251
  return DateTime.fromJSDate(date).toISODate();
201
252
  };
202
253
  const parseCalendarDate = (formattedDate) => {
203
254
  if (formattedDate == null) return formattedDate;
204
- if (fullIso) return DateTimeUtils.fromUTCISOToCalendarDate(formattedDate);
255
+ if (fullIso) return normalizeByGranularity(DateTimeUtils.fromUTCISOToCalendarDate(formattedDate));
205
256
  const date = DateTime.fromISO(formattedDate).toJSDate();
206
- return toCalendarDate(DateTimeUtils.fromLocalToZonedDateTime(date));
257
+ return normalizeByGranularity(toCalendarDate(DateTimeUtils.fromLocalToZonedDateTime(date)));
207
258
  };
208
259
  const dateLimits = {
209
260
  minValue: typeof minValue === "string" ? parseCalendarDate(minValue) : minValue,
@@ -233,6 +284,7 @@ var DatePicker = ({ fullIso = true, minValue, maxValue, renderStaticInput, ...pr
233
284
  isDisabled,
234
285
  className: clsx("relative inline-flex w-full flex-col text-left", props.className),
235
286
  inputClassName: clsx("min-w-input-width-min-width", props.inputClassName),
287
+ contentClassName: "pr-0!",
236
288
  contentWrapperClassName: datePickerInputContentRowCva({ size }),
237
289
  labelPlacement: "content-row",
238
290
  dataAttributes: {
@@ -249,6 +301,7 @@ var DatePicker = ({ fullIso = true, minValue, maxValue, renderStaticInput, ...pr
249
301
  onStaticInteract: renderRealInput,
250
302
  actionContent: staticTodayIcon,
251
303
  actionContentPlacement: todayIconPlacement === "fieldLabel" ? "content-row" : "content-wrapper",
304
+ trailingClassName: "py-0! pl-0!",
252
305
  trailingContent: showDropdown ? ui.dateInput.calendarIcon : void 0,
253
306
  children: staticSegments
254
307
  });
@@ -275,6 +328,7 @@ var DatePicker = ({ fullIso = true, minValue, maxValue, renderStaticInput, ...pr
275
328
  ...props,
276
329
  ...dateLimits,
277
330
  ref: mergeRefs(props.ref, inputRef),
331
+ granularity,
278
332
  value: parseCalendarDate(props.value),
279
333
  onChange: (value) => props.onChange?.(formatCalendarDate(value))
280
334
  });
@@ -2,12 +2,12 @@ import { UIStyle } from "../../../../config/uiStyle.context.js";
2
2
  import { Typography } from "../../../text/Typography/Typography.js";
3
3
  import { UIConfig } from "../../../../config/uiConfig.context.js";
4
4
  import "../../../../config/i18n.js";
5
+ import { DateTimeUtils } from "../../../../utils/date-time.utils.js";
5
6
  import { datePickerInputContentRow } from "../shared/datePickerInput.cva.js";
6
7
  import { renderDatePickerTodayIcon } from "../shared/datePickerTodayIcon.js";
7
8
  import { DatePickerInput } from "../shared/DatePickerInput.js";
8
9
  import { DateTimeDialog } from "../shared/DateTimeDialog.js";
9
10
  import { DateTimeDialogFooter } from "../shared/DateTimeDialogFooter.js";
10
- import { DateTimeUtils } from "../../../../utils/date-time.utils.js";
11
11
  import { getStaticDateRangeSegments } from "../shared/staticDateTimeSegments.js";
12
12
  import { FormField } from "../../FormField/FormField.js";
13
13
  import { TooltipWrapper } from "../../shared/TooltipWrapper.js";
@@ -634,6 +634,7 @@ var DateRangePicker = ({ fullIso = true, minValue, maxValue, renderStaticInput,
634
634
  isDisabled,
635
635
  className: clsx("relative inline-flex w-full flex-col text-left", props.className),
636
636
  inputClassName: clsx("min-w-input-width-min-width", props.inputClassName),
637
+ contentClassName: "pr-0!",
637
638
  contentWrapperClassName: datePickerInputContentRowCva({ size }),
638
639
  labelPlacement: "content-row",
639
640
  dataAttributes: {
@@ -650,6 +651,7 @@ var DateRangePicker = ({ fullIso = true, minValue, maxValue, renderStaticInput,
650
651
  onStaticInteract: renderRealInput,
651
652
  actionContent: staticTodayIcon,
652
653
  actionContentPlacement: todayIconPlacement === "fieldLabel" ? "content-row" : "content-wrapper",
654
+ trailingClassName: "py-0! pl-0!",
653
655
  trailingContent: showDropdown ? ui.dateInput.calendarIcon : void 0,
654
656
  children: staticSegments
655
657
  });
@@ -21,6 +21,9 @@ interface DateTimePickerBaseProps extends FormFieldProps, InputVariantProps, Omi
21
21
  setDateValueOnDateSelection?: boolean;
22
22
  placeholder?: string;
23
23
  inputClassName?: string;
24
+ shouldUpdateDateOnMonthYearChange?: boolean;
25
+ timeZone?: string;
26
+ format?: string;
24
27
  onBlur?: (e: FocusEvent<HTMLInputElement>) => void;
25
28
  }
26
29
  export interface DateTimePickerProps extends Omit<DateTimePickerBaseProps, "value" | "onChange"> {
@@ -28,6 +31,7 @@ export interface DateTimePickerProps extends Omit<DateTimePickerBaseProps, "valu
28
31
  onChange?: (value: string | null) => void;
29
32
  fullIso?: boolean;
30
33
  renderStaticInput?: boolean;
34
+ timeZone?: string;
31
35
  }
32
36
  export type ControlledDateTimePickerProps<TFieldValues extends FieldValues> = ControlProps<DateTimePickerProps, TFieldValues>;
33
37
  export declare const DateTimePicker: <TFieldValues extends FieldValues>({ fullIso, renderStaticInput, ...props }: ControlledDateTimePickerProps<TFieldValues>) => import("react/jsx-runtime").JSX.Element;
@@ -1,12 +1,12 @@
1
1
  import { UIStyle } from "../../../../config/uiStyle.context.js";
2
2
  import { UIConfig } from "../../../../config/uiConfig.context.js";
3
3
  import { Calendar } from "../shared/Calendar.js";
4
+ import { DateTimeUtils } from "../../../../utils/date-time.utils.js";
4
5
  import { datePickerInputContentRow } from "../shared/datePickerInput.cva.js";
5
6
  import { renderDatePickerTodayIcon } from "../shared/datePickerTodayIcon.js";
6
7
  import { DatePickerInput } from "../shared/DatePickerInput.js";
7
8
  import { DateTimeDialog } from "../shared/DateTimeDialog.js";
8
9
  import { DateTimeDialogFooter } from "../shared/DateTimeDialogFooter.js";
9
- import { DateTimeUtils } from "../../../../utils/date-time.utils.js";
10
10
  import { getStaticCalendarDateTimeSegments } from "../shared/staticDateTimeSegments.js";
11
11
  import { FormField } from "../../FormField/FormField.js";
12
12
  import { TooltipWrapper } from "../../shared/TooltipWrapper.js";
@@ -24,7 +24,9 @@ import { useCalendarState, useDatePickerState } from "react-stately";
24
24
  //#region src/components/inputs/DateTime/DateTimePicker/DateTimePicker.tsx
25
25
  var DateTimePickerBase = (props) => {
26
26
  const ui = UIConfig.useConfig();
27
- 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, todayIconPlacement = ui.dateInput.todayIconPlacement, shouldForceLeadingZeros = ui.dateInput.shouldForceLeadingZeros, disableManualEntry = ui.dateInput.disableManualEntry, autoFixYear = ui.dateInput.autoFixYear, setDateValueOnDateSelection = ui.dateInput.setDateValueOnDateSelection, ...rest } = props;
27
+ 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, todayIconPlacement = ui.dateInput.todayIconPlacement, shouldForceLeadingZeros = ui.dateInput.shouldForceLeadingZeros, disableManualEntry = ui.dateInput.disableManualEntry, shouldUpdateDateOnMonthYearChange = ui.dateInput.shouldUpdateDateOnMonthYearChange, timeZone, autoFixYear = ui.dateInput.autoFixYear, format, setDateValueOnDateSelection = ui.dateInput.setDateValueOnDateSelection, ...rest } = props;
28
+ let effectiveTimeZone = getLocalTimeZone();
29
+ if (timeZone) effectiveTimeZone = timeZone;
28
30
  const formFieldProps = {
29
31
  error,
30
32
  label,
@@ -109,19 +111,38 @@ var DateTimePickerBase = (props) => {
109
111
  state.toggle();
110
112
  handleBlur(newValue);
111
113
  };
114
+ const onMonthYearChange = (selectedDate) => {
115
+ if (!shouldUpdateDateOnMonthYearChange) return;
116
+ const baseDate = dialogState.value || state.value;
117
+ if (baseDate) {
118
+ const updatedDate = baseDate.set({
119
+ year: selectedDate.year,
120
+ month: selectedDate.month
121
+ });
122
+ dialogState.setValue(updatedDate);
123
+ calendarState.setFocusedDate(updatedDate);
124
+ return;
125
+ }
126
+ dialogState.setValue(toCalendarDateTime(selectedDate));
127
+ calendarState.setFocusedDate(selectedDate);
128
+ };
112
129
  const onTodayPress = () => {
113
- dialogState.setValue(toCalendarDateTime(now(getLocalTimeZone())));
114
- calendarState.setFocusedDate(today(getLocalTimeZone()));
130
+ dialogState.setValue(toCalendarDateTime(now(effectiveTimeZone)));
131
+ calendarState.setFocusedDate(today(effectiveTimeZone));
115
132
  };
116
133
  const onOpenChange = (isOpen) => {
117
134
  state.toggle();
118
- calendarState.setFocusedDate(state.value || today(getLocalTimeZone()));
135
+ calendarState.setFocusedDate(state.value || today(effectiveTimeZone));
119
136
  if (!isOpen) dialogState.setValue(state.value);
120
137
  };
121
138
  const onInputBlur = (e) => {
122
139
  if (!isTimeOptional) return;
140
+ if (state.value) {
141
+ dialogState.setValue(state.value);
142
+ return;
143
+ }
123
144
  const textValue = e.currentTarget.textContent;
124
- const dateTimeValue = DateTimeUtils.formatTextDateToCalendarDateTime(textValue);
145
+ const dateTimeValue = DateTimeUtils.formatTextDateToCalendarDateTime(textValue, effectiveTimeZone, locale);
125
146
  if (dateTimeValue) {
126
147
  state.setValue(dateTimeValue);
127
148
  dialogState.setValue(dateTimeValue);
@@ -167,7 +188,10 @@ var DateTimePickerBase = (props) => {
167
188
  autoFixYear,
168
189
  placeholder,
169
190
  onOpenDropdown: () => state.toggle(),
170
- className: inputClassName
191
+ className: inputClassName,
192
+ timeZone: effectiveTimeZone,
193
+ isTimeOptional,
194
+ format
171
195
  }), (!disableDropdown || disableManualEntry) && /* @__PURE__ */ jsx(DateTimeDialog, {
172
196
  footer: /* @__PURE__ */ jsx(DateTimeDialogFooter, {
173
197
  isDisabled,
@@ -186,6 +210,8 @@ var DateTimePickerBase = (props) => {
186
210
  includesTime: true,
187
211
  datePickerState: dialogState,
188
212
  onApply,
213
+ onMonthYearChange,
214
+ granularity: "day",
189
215
  setDateValueOnDateSelection
190
216
  })
191
217
  })]
@@ -214,14 +240,16 @@ var DateTimePicker = ({ fullIso = true, renderStaticInput, ...props }) => {
214
240
  let isFormControlDisabled = false;
215
241
  if ("formControl" in props && props.formControl) isFormControlDisabled = !!props.formControl.control._options?.disabled;
216
242
  const rawValue = watchedValue ?? props.value ?? null;
243
+ let effectiveTimeZone = getLocalTimeZone();
244
+ if (props.timeZone) effectiveTimeZone = props.timeZone;
217
245
  const formatDateValue = (dateValue) => {
218
246
  if (dateValue === null) return null;
219
- if (fullIso) return DateTimeUtils.fromCalendarDateTimeToUTCISO(dateValue);
220
- return DateTimeUtils.fromDateValueToISO(dateValue);
247
+ if (fullIso) return DateTimeUtils.fromDateValueToISO(dateValue, effectiveTimeZone);
248
+ return DateTimeUtils.fromDateValueToISO(dateValue, effectiveTimeZone);
221
249
  };
222
250
  const parseDateValue = (isoString) => {
223
251
  if (isoString == null) return isoString;
224
- return DateTimeUtils.fromUTCISOToCalendarDateTime(isoString);
252
+ return DateTimeUtils.fromUTCISOToCalendarDateTime(isoString, effectiveTimeZone);
225
253
  };
226
254
  if (!renderInput) {
227
255
  const dateTimeValue = rawValue ? parseDateValue(rawValue) : null;
@@ -247,6 +275,7 @@ var DateTimePicker = ({ fullIso = true, renderStaticInput, ...props }) => {
247
275
  isDisabled,
248
276
  className: clsx("relative inline-flex w-full flex-col text-left", props.className),
249
277
  inputClassName: clsx("min-w-input-width-min-width", props.inputClassName),
278
+ contentClassName: "pr-0!",
250
279
  contentWrapperClassName: datePickerInputContentRowCva({ size }),
251
280
  labelPlacement: "content-row",
252
281
  dataAttributes: {
@@ -263,6 +292,7 @@ var DateTimePicker = ({ fullIso = true, renderStaticInput, ...props }) => {
263
292
  onStaticInteract: renderRealInput,
264
293
  actionContent: staticTodayIcon,
265
294
  actionContentPlacement: todayIconPlacement === "fieldLabel" ? "content-row" : "content-wrapper",
295
+ trailingClassName: "py-0! pl-0!",
266
296
  trailingContent: showDropdown ? ui.dateInput.dateTimeIcon : void 0,
267
297
  children: staticSegments
268
298
  });
@@ -19,6 +19,7 @@ export interface TimePickerProps extends Omit<TimePickerBaseProps, "value" | "on
19
19
  value?: string | null;
20
20
  onChange?: (value: string | null) => void;
21
21
  fullIso?: boolean;
22
+ timeZone?: string;
22
23
  renderStaticInput?: boolean;
23
24
  }
24
25
  export type ControlledTimePickerProps<TFieldValues extends FieldValues> = ControlProps<TimePickerProps, TFieldValues>;