@povio/ui 2.2.12 → 2.3.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/dist/components/buttons/InlineIconButton/InlineIconButton.d.ts +2 -1
  2. package/dist/components/buttons/InlineIconButton/InlineIconButton.js +2 -2
  3. package/dist/components/inputs/Checkbox/Checkbox.js +6 -1
  4. package/dist/components/inputs/Checkbox/checkbox.cva.d.ts +3 -0
  5. package/dist/components/inputs/Checkbox/checkbox.cva.js +2 -1
  6. package/dist/components/inputs/DateTime/DatePicker/DatePicker.d.ts +10 -5
  7. package/dist/components/inputs/DateTime/DatePicker/DatePicker.js +88 -9
  8. package/dist/components/inputs/DateTime/DateRangePicker/DateRangePicker.d.ts +10 -5
  9. package/dist/components/inputs/DateTime/DateRangePicker/DateRangePicker.js +94 -7
  10. package/dist/components/inputs/DateTime/DateTimePicker/DateTimePicker.d.ts +11 -5
  11. package/dist/components/inputs/DateTime/DateTimePicker/DateTimePicker.js +94 -9
  12. package/dist/components/inputs/DateTime/TimePicker/TimePicker.d.ts +5 -3
  13. package/dist/components/inputs/DateTime/TimePicker/TimePicker.js +76 -7
  14. package/dist/components/inputs/DateTime/shared/Calendar.d.ts +5 -2
  15. package/dist/components/inputs/DateTime/shared/Calendar.js +23 -6
  16. package/dist/components/inputs/DateTime/shared/CalendarCell.d.ts +1 -1
  17. package/dist/components/inputs/DateTime/shared/CalendarCell.js +3 -3
  18. package/dist/components/inputs/DateTime/shared/CalendarGrid.d.ts +1 -1
  19. package/dist/components/inputs/DateTime/shared/DatePickerInput.d.ts +6 -3
  20. package/dist/components/inputs/DateTime/shared/DatePickerInput.js +78 -61
  21. package/dist/components/inputs/DateTime/shared/DateSegmentItem.d.ts +14 -0
  22. package/dist/components/inputs/DateTime/shared/DateSegmentItem.js +19 -6
  23. package/dist/components/inputs/DateTime/shared/TimePickerInput.d.ts +2 -1
  24. package/dist/components/inputs/DateTime/shared/TimePickerInput.js +11 -4
  25. package/dist/components/inputs/DateTime/shared/datePicker.types.d.ts +4 -0
  26. package/dist/components/inputs/DateTime/shared/datePickerInput.cva.d.ts +7 -0
  27. package/dist/components/inputs/DateTime/shared/datePickerInput.cva.js +13 -0
  28. package/dist/components/inputs/DateTime/shared/datePickerTodayIcon.d.ts +6 -0
  29. package/dist/components/inputs/DateTime/shared/datePickerTodayIcon.js +21 -0
  30. package/dist/components/inputs/DateTime/shared/dateSegment.utils.d.ts +2 -0
  31. package/dist/components/inputs/DateTime/shared/dateSegment.utils.spec.d.ts +1 -0
  32. package/dist/components/inputs/DateTime/shared/staticDateTimeSegments.d.ts +31 -0
  33. package/dist/components/inputs/DateTime/shared/staticDateTimeSegments.js +80 -0
  34. package/dist/components/inputs/DateTime/shared/staticDateTimeSegments.spec.d.ts +1 -0
  35. package/dist/components/inputs/File/FileUpload.js +1 -0
  36. package/dist/components/inputs/File/shared/InputUploadContent.js +1 -0
  37. package/dist/components/inputs/FormField/FormField.d.ts +3 -3
  38. package/dist/components/inputs/FormField/FormFieldHeader.d.ts +2 -2
  39. package/dist/components/inputs/FormField/FormFieldHeader.js +3 -1
  40. package/dist/components/inputs/FormField/FormFieldLabel.d.ts +2 -2
  41. package/dist/components/inputs/FormField/formFieldHeader.cva.d.ts +6 -0
  42. package/dist/components/inputs/FormField/formFieldHeader.cva.js +11 -0
  43. package/dist/components/inputs/Input/NumberInput/NumberInput.d.ts +5 -2
  44. package/dist/components/inputs/Input/NumberInput/NumberInput.js +81 -7
  45. package/dist/components/inputs/Input/NumberRangeInput/NumberRangeField.d.ts +45 -0
  46. package/dist/components/inputs/Input/NumberRangeInput/NumberRangeField.js +146 -0
  47. package/dist/components/inputs/Input/NumberRangeInput/NumberRangeInput.d.ts +35 -0
  48. package/dist/components/inputs/Input/NumberRangeInput/NumberRangeInput.js +235 -0
  49. package/dist/components/inputs/Input/TextArea/TextArea.cva.d.ts +4 -0
  50. package/dist/components/inputs/Input/TextArea/TextArea.cva.js +5 -0
  51. package/dist/components/inputs/Input/TextArea/TextArea.js +3 -1
  52. package/dist/components/inputs/Input/TextInput/TextInput.d.ts +3 -1
  53. package/dist/components/inputs/Input/TextInput/TextInput.js +82 -7
  54. package/dist/components/inputs/Input/shared/InputContent.js +7 -6
  55. package/dist/components/inputs/Input/shared/numberStatic.utils.d.ts +1 -0
  56. package/dist/components/inputs/Input/shared/numberStatic.utils.js +7 -0
  57. package/dist/components/inputs/Inputs/InputItem.d.ts +16 -21
  58. package/dist/components/inputs/Inputs/InputItem.js +6 -0
  59. package/dist/components/inputs/RadioGroup/RadioGroup.d.ts +2 -1
  60. package/dist/components/inputs/RadioGroup/RadioGroup.js +106 -25
  61. package/dist/components/inputs/RadioGroup/radio.cva.d.ts +17 -0
  62. package/dist/components/inputs/RadioGroup/radio.cva.js +42 -1
  63. package/dist/components/inputs/Selection/Autocomplete/Autocomplete.d.ts +6 -2
  64. package/dist/components/inputs/Selection/Autocomplete/Autocomplete.js +102 -7
  65. package/dist/components/inputs/Selection/Autocomplete/QueryAutocomplete.d.ts +3 -18
  66. package/dist/components/inputs/Selection/Autocomplete/QueryAutocomplete.js +33 -8
  67. package/dist/components/inputs/Selection/Autocomplete/queryAutocomplete.types.d.ts +36 -0
  68. package/dist/components/inputs/Selection/Select/QuerySelect.d.ts +14 -0
  69. package/dist/components/inputs/Selection/Select/QuerySelect.js +42 -0
  70. package/dist/components/inputs/Selection/Select/Select.d.ts +7 -3
  71. package/dist/components/inputs/Selection/Select/Select.js +115 -5
  72. package/dist/components/inputs/Selection/shared/SelectBase.d.ts +8 -1
  73. package/dist/components/inputs/Selection/shared/SelectBase.js +4 -2
  74. package/dist/components/inputs/Selection/shared/SelectDesktop.d.ts +1 -1
  75. package/dist/components/inputs/Selection/shared/SelectDesktop.js +11 -3
  76. package/dist/components/inputs/Selection/shared/SelectInput.d.ts +2 -2
  77. package/dist/components/inputs/Selection/shared/SelectInput.js +27 -4
  78. package/dist/components/inputs/Selection/shared/SelectListBox.d.ts +2 -2
  79. package/dist/components/inputs/Selection/shared/SelectListBox.js +3 -3
  80. package/dist/components/inputs/Selection/shared/SelectMobile.d.ts +1 -1
  81. package/dist/components/inputs/Selection/shared/SelectMobile.js +9 -3
  82. package/dist/components/inputs/Selection/shared/querySelect.utils.d.ts +6 -0
  83. package/dist/components/inputs/Selection/shared/querySelect.utils.js +13 -0
  84. package/dist/components/inputs/Selection/shared/select.context.d.ts +3 -2
  85. package/dist/components/inputs/Selection/shared/select.context.js +27 -4
  86. package/dist/components/inputs/Selection/shared/select.types.d.ts +3 -2
  87. package/dist/components/inputs/Selection/shared/selectDesktop.cva.d.ts +3 -0
  88. package/dist/components/inputs/Selection/shared/selectDesktop.cva.js +5 -0
  89. package/dist/components/inputs/Selection/shared/staticSelect.utils.d.ts +23 -0
  90. package/dist/components/inputs/Selection/shared/staticSelect.utils.js +37 -0
  91. package/dist/components/inputs/Selection/shared/staticSelect.utils.spec.d.ts +1 -0
  92. package/dist/components/inputs/Skeleton/InputFrame.d.ts +77 -0
  93. package/dist/components/inputs/Skeleton/InputFrame.js +200 -0
  94. package/dist/components/inputs/TextEditor/TextEditor.d.ts +1 -0
  95. package/dist/components/inputs/TextEditor/TextEditor.js +8 -3
  96. package/dist/components/inputs/Toggle/Toggle.js +6 -1
  97. package/dist/components/inputs/Toggle/toggle.cva.d.ts +3 -0
  98. package/dist/components/inputs/Toggle/toggle.cva.js +2 -1
  99. package/dist/components/inputs/shared/CheckContent.d.ts +2 -1
  100. package/dist/components/inputs/shared/CheckContent.js +3 -4
  101. package/dist/components/inputs/shared/InputClear.d.ts +2 -1
  102. package/dist/components/inputs/shared/InputClear.js +13 -1
  103. package/dist/components/inputs/shared/StaticInput.d.ts +38 -0
  104. package/dist/components/inputs/shared/TooltipWrapper.js +5 -1
  105. package/dist/components/inputs/shared/input.cva.d.ts +10 -0
  106. package/dist/components/inputs/shared/input.cva.js +19 -1
  107. package/dist/components/inputs/shared/tooltipWrapper.cva.d.ts +4 -0
  108. package/dist/components/inputs/shared/tooltipWrapper.cva.js +5 -0
  109. package/dist/components/inputs/shared/useStaticInputHandoff.d.ts +13 -0
  110. package/dist/components/inputs/shared/useStaticInputHandoff.js +47 -0
  111. package/dist/config/router.context.d.ts +3 -4
  112. package/dist/config/router.context.js +1 -3
  113. package/dist/config/uiConfig.context.d.ts +15 -3
  114. package/dist/config/uiConfig.context.js +16 -3
  115. package/dist/config/uiStyle.context.d.ts +27 -4
  116. package/dist/helpers/dynamicInputs.d.ts +5 -5
  117. package/dist/helpers/dynamicInputs.js +3 -0
  118. package/dist/hooks/useFilters.js +27 -23
  119. package/dist/hooks/useIntersectionObserver.d.ts +1 -1
  120. package/dist/hooks/useIntersectionObserver.js +27 -14
  121. package/dist/hooks/usePagination.js +8 -4
  122. package/dist/hooks/useQueryAutocomplete.d.ts +14 -0
  123. package/dist/hooks/useQueryAutocomplete.js +56 -0
  124. package/dist/hooks/useSorting.js +7 -4
  125. package/dist/index.d.ts +7 -0
  126. package/dist/index.js +5 -3
  127. package/dist/tw-ui-plugin.js +2 -0
  128. package/dist/utils/date-time.utils.d.ts +31 -10
  129. package/dist/utils/date-time.utils.js +123 -22
  130. package/dist/utils/query.utils.d.ts +4 -0
  131. package/dist/utils/query.utils.js +8 -0
  132. package/dist/utils/routing.utils.d.ts +1 -0
  133. package/dist/utils/routing.utils.js +14 -0
  134. package/package.json +2 -2
@@ -1,22 +1,30 @@
1
+ import { UIStyle } from "../../../../config/uiStyle.context.js";
1
2
  import { UIConfig } from "../../../../config/uiConfig.context.js";
2
3
  import { Calendar } from "../shared/Calendar.js";
3
4
  import { DateTimeUtils } from "../../../../utils/date-time.utils.js";
5
+ import { datePickerInputContentRow } from "../shared/datePickerInput.cva.js";
6
+ import { renderDatePickerTodayIcon } from "../shared/datePickerTodayIcon.js";
4
7
  import { DatePickerInput } from "../shared/DatePickerInput.js";
5
8
  import { DateTimeDialog } from "../shared/DateTimeDialog.js";
6
9
  import { DateTimeDialogFooter } from "../shared/DateTimeDialogFooter.js";
10
+ import { getStaticCalendarDateTimeSegments } from "../shared/staticDateTimeSegments.js";
7
11
  import { FormField } from "../../FormField/FormField.js";
8
12
  import { TooltipWrapper } from "../../shared/TooltipWrapper.js";
13
+ import { InputFrame } from "../../Skeleton/InputFrame.js";
14
+ import { useStaticInputHandoff } from "../../shared/useStaticInputHandoff.js";
15
+ import { useDebounceCallback } from "../../../../hooks/useDebounceCallback.js";
9
16
  import { jsx, jsxs } from "react/jsx-runtime";
10
- import { useEffect, useImperativeHandle, useMemo, useRef } from "react";
17
+ import { clsx } from "clsx";
18
+ import { useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
11
19
  import { useDatePicker, useLocale } from "react-aria";
12
20
  import { mergeRefs } from "@react-aria/utils";
13
- import { Controller } from "react-hook-form";
21
+ import { Controller, useWatch } from "react-hook-form";
14
22
  import { Time, createCalendar, getLocalTimeZone, now, toCalendarDateTime, today } from "@internationalized/date";
15
23
  import { useCalendarState, useDatePickerState } from "react-stately";
16
24
  //#region src/components/inputs/DateTime/DateTimePicker/DateTimePicker.tsx
17
25
  var DateTimePickerBase = (props) => {
18
26
  const ui = UIConfig.useConfig();
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, format, ...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;
20
28
  let effectiveTimeZone = getLocalTimeZone();
21
29
  if (timeZone) effectiveTimeZone = timeZone;
22
30
  const formFieldProps = {
@@ -39,6 +47,10 @@ var DateTimePickerBase = (props) => {
39
47
  useImperativeHandle(ref, () => ({ clear: () => {
40
48
  datePickerInputRef.current?.clear();
41
49
  } }));
50
+ const handleBlur = (val) => {
51
+ onBlur?.({ target: { value: val } });
52
+ };
53
+ const { callback: debouncedBlur } = useDebounceCallback(handleBlur, { delay: 500 });
42
54
  const dialogState = useDatePickerState({
43
55
  ...rest,
44
56
  defaultValue: value || rest.defaultValue,
@@ -57,7 +69,8 @@ var DateTimePickerBase = (props) => {
57
69
  onChange: (val) => {
58
70
  onChange?.(val);
59
71
  dialogState.setValue(val);
60
- calendarState.setFocusedDate(val || today(effectiveTimeZone));
72
+ calendarState.setFocusedDate(val || today(getLocalTimeZone()));
73
+ debouncedBlur(val);
61
74
  },
62
75
  shouldCloseOnSelect: false,
63
76
  granularity: "minute",
@@ -93,8 +106,10 @@ var DateTimePickerBase = (props) => {
93
106
  labelProps
94
107
  };
95
108
  const onApply = () => {
96
- state.setValue(dialogState.value);
109
+ const newValue = dialogState.value;
110
+ state.setValue(newValue);
97
111
  state.toggle();
112
+ handleBlur(newValue);
98
113
  };
99
114
  const onMonthYearChange = (selectedDate) => {
100
115
  if (!shouldUpdateDateOnMonthYearChange) return;
@@ -166,13 +181,15 @@ var DateTimePickerBase = (props) => {
166
181
  isClearable,
167
182
  headerProps,
168
183
  todayIcon,
184
+ todayIconButtonSize,
185
+ todayIconPlacement,
169
186
  isRequired,
170
187
  disableManualEntry,
188
+ autoFixYear,
171
189
  placeholder,
172
190
  onOpenDropdown: () => state.toggle(),
173
191
  className: inputClassName,
174
192
  timeZone: effectiveTimeZone,
175
- autoFixYear,
176
193
  isTimeOptional,
177
194
  format
178
195
  }), (!disableDropdown || disableManualEntry) && /* @__PURE__ */ jsx(DateTimeDialog, {
@@ -194,13 +211,35 @@ var DateTimePickerBase = (props) => {
194
211
  datePickerState: dialogState,
195
212
  onApply,
196
213
  onMonthYearChange,
197
- granularity: "day"
214
+ granularity: "day",
215
+ setDateValueOnDateSelection
198
216
  })
199
217
  })]
200
218
  })
201
219
  });
202
220
  };
203
- var DateTimePicker = ({ fullIso = true, ...props }) => {
221
+ var DateTimePicker = ({ fullIso = true, renderStaticInput, ...props }) => {
222
+ const ui = UIConfig.useConfig();
223
+ const datePickerInputContentRowCva = UIStyle.useCva("datePickerInput.contentRowCva", datePickerInputContentRow);
224
+ const { locale } = useLocale();
225
+ const shouldForceLeadingZeros = props.shouldForceLeadingZeros ?? ui.dateInput.shouldForceLeadingZeros;
226
+ const [renderInput, setRenderInput] = useState(!(renderStaticInput ?? ui.renderStaticInput));
227
+ const inputRef = useRef(null);
228
+ const { renderRealInput } = useStaticInputHandoff({
229
+ inputRef,
230
+ renderInput,
231
+ setRenderInput,
232
+ getFocusTarget: (input) => {
233
+ return (input.getContainer?.() ?? input).querySelector("input, button, [tabindex]:not([tabindex='-1'])");
234
+ }
235
+ });
236
+ const watchedValue = "formControl" in props && props.formControl ? useWatch({
237
+ control: props.formControl.control,
238
+ name: props.formControl.name
239
+ }) : props.value;
240
+ let isFormControlDisabled = false;
241
+ if ("formControl" in props && props.formControl) isFormControlDisabled = !!props.formControl.control._options?.disabled;
242
+ const rawValue = watchedValue ?? props.value ?? null;
204
243
  let effectiveTimeZone = getLocalTimeZone();
205
244
  if (props.timeZone) effectiveTimeZone = props.timeZone;
206
245
  const formatDateValue = (dateValue) => {
@@ -212,6 +251,51 @@ var DateTimePicker = ({ fullIso = true, ...props }) => {
212
251
  if (isoString == null) return isoString;
213
252
  return DateTimeUtils.fromUTCISOToCalendarDateTime(isoString, effectiveTimeZone);
214
253
  };
254
+ if (!renderInput) {
255
+ const dateTimeValue = rawValue ? parseDateValue(rawValue) : null;
256
+ const as = props.as ?? ui.input.as;
257
+ const size = props.size ?? ui.input.size;
258
+ const isDisabled = isFormControlDisabled || !!props.isDisabled;
259
+ const todayIcon = props.todayIcon ?? ui.dateInput.todayIcon;
260
+ const todayIconButtonSize = props.todayIconButtonSize ?? ui.dateInput.todayIconButtonSize;
261
+ const todayIconPlacement = props.todayIconPlacement ?? ui.dateInput.todayIconPlacement;
262
+ const staticTodayIcon = renderDatePickerTodayIcon(todayIcon, todayIconButtonSize);
263
+ const disableManualEntry = props.disableManualEntry ?? ui.dateInput.disableManualEntry;
264
+ const showDropdown = !props.disableDropdown || disableManualEntry;
265
+ const staticSegments = getStaticCalendarDateTimeSegments({
266
+ value: dateTimeValue,
267
+ locale,
268
+ shouldForceLeadingZeros,
269
+ isDisabled,
270
+ hidePlaceholder: as === "floating" && !dateTimeValue
271
+ });
272
+ return /* @__PURE__ */ jsx(InputFrame, {
273
+ ...props,
274
+ isDisabled,
275
+ className: clsx("relative inline-flex w-full flex-col text-left", props.className),
276
+ inputClassName: clsx("min-w-input-width-min-width", props.inputClassName),
277
+ contentClassName: "pr-0!",
278
+ contentWrapperClassName: datePickerInputContentRowCva({ size }),
279
+ labelPlacement: "content-row",
280
+ dataAttributes: {
281
+ dataIsEmpty: dateTimeValue === null,
282
+ dataIsFilled: dateTimeValue !== null,
283
+ dataIsDirty: props.isDirty,
284
+ dataIsRequired: props.isRequired,
285
+ dataIsDisabled: isDisabled,
286
+ dataDisabled: isDisabled,
287
+ dataInvalid: !!props.error,
288
+ dataHasSelection: dateTimeValue !== null
289
+ },
290
+ renderStatic: true,
291
+ onStaticInteract: renderRealInput,
292
+ actionContent: staticTodayIcon,
293
+ actionContentPlacement: todayIconPlacement === "fieldLabel" ? "content-row" : "content-wrapper",
294
+ trailingClassName: "py-0! pl-0!",
295
+ trailingContent: showDropdown ? ui.dateInput.dateTimeIcon : void 0,
296
+ children: staticSegments
297
+ });
298
+ }
215
299
  if ("formControl" in props && props.formControl) {
216
300
  const { formControl, ref, ...innerProps } = props;
217
301
  return /* @__PURE__ */ jsx(Controller, {
@@ -219,7 +303,7 @@ var DateTimePicker = ({ fullIso = true, ...props }) => {
219
303
  name: formControl.name,
220
304
  render: ({ field, fieldState: { error, isDirty } }) => /* @__PURE__ */ jsx(DateTimePickerBase, {
221
305
  ...innerProps,
222
- ref: mergeRefs(ref, field.ref),
306
+ ref: mergeRefs(ref, field.ref, inputRef),
223
307
  value: parseDateValue(field.value),
224
308
  onChange: (value) => field.onChange(formatDateValue(value)),
225
309
  onBlur: field.onBlur,
@@ -231,6 +315,7 @@ var DateTimePicker = ({ fullIso = true, ...props }) => {
231
315
  }
232
316
  return /* @__PURE__ */ jsx(DateTimePickerBase, {
233
317
  ...props,
318
+ ref: mergeRefs(props.ref, inputRef),
234
319
  value: parseDateValue(props.value),
235
320
  onChange: (value) => props.onChange?.(formatDateValue(value))
236
321
  });
@@ -1,10 +1,10 @@
1
- import { Ref } from 'react';
1
+ import { Ref, FocusEvent } 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"> {
7
+ interface TimePickerBaseProps extends FormFieldProps, InputVariantProps, Omit<AriaTimeFieldProps<TimeValue>, "label" | "onBlur"> {
8
8
  ref?: Ref<HTMLDivElement>;
9
9
  disableDropdown?: boolean;
10
10
  date?: string | null;
@@ -13,13 +13,15 @@ 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;
16
17
  }
17
18
  export interface TimePickerProps extends Omit<TimePickerBaseProps, "value" | "onChange"> {
18
19
  value?: string | null;
19
20
  onChange?: (value: string | null) => void;
20
21
  fullIso?: boolean;
21
22
  timeZone?: string;
23
+ renderStaticInput?: boolean;
22
24
  }
23
25
  export type ControlledTimePickerProps<TFieldValues extends FieldValues> = ControlProps<TimePickerProps, TFieldValues>;
24
- export declare const TimePicker: <TFieldValues extends FieldValues>(props: ControlledTimePickerProps<TFieldValues>) => import("react/jsx-runtime").JSX.Element;
26
+ export declare const TimePicker: <TFieldValues extends FieldValues>({ renderStaticInput, ...props }: ControlledTimePickerProps<TFieldValues>) => import("react/jsx-runtime").JSX.Element;
25
27
  export {};
@@ -3,22 +3,26 @@ import { TimePickerForm } from "../shared/TimePickerForm.js";
3
3
  import { DateTimeUtils } from "../../../../utils/date-time.utils.js";
4
4
  import { DateTimeDialog } from "../shared/DateTimeDialog.js";
5
5
  import { DateTimeDialogFooter } from "../shared/DateTimeDialogFooter.js";
6
+ import { getStaticTimeSegments } from "../shared/staticDateTimeSegments.js";
6
7
  import { FormField } from "../../FormField/FormField.js";
7
8
  import { TooltipWrapper } from "../../shared/TooltipWrapper.js";
9
+ import { InputFrame } from "../../Skeleton/InputFrame.js";
10
+ import { useStaticInputHandoff } from "../../shared/useStaticInputHandoff.js";
11
+ import { useDebounceCallback } from "../../../../hooks/useDebounceCallback.js";
8
12
  import { TimePickerInput } from "../shared/TimePickerInput.js";
9
13
  import { jsx, jsxs } from "react/jsx-runtime";
10
14
  import { clsx } from "clsx";
11
15
  import { useEffect, useRef, useState } from "react";
12
16
  import { useLocale, useTimeField } from "react-aria";
13
17
  import { mergeRefs } from "@react-aria/utils";
14
- import { Controller } from "react-hook-form";
18
+ import { Controller, useWatch } from "react-hook-form";
15
19
  import { getLocalTimeZone, now, toTime } from "@internationalized/date";
16
20
  import { DateTime } from "luxon";
17
21
  import { useTimeFieldState } from "react-stately";
18
22
  //#region src/components/inputs/DateTime/TimePicker/TimePicker.tsx
19
23
  var TimePickerBase = (props) => {
20
24
  const ui = UIConfig.useConfig();
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;
25
+ 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;
22
26
  const formFieldProps = {
23
27
  error,
24
28
  label,
@@ -40,11 +44,18 @@ var TimePickerBase = (props) => {
40
44
  defaultValue: value || rest.defaultValue,
41
45
  locale
42
46
  });
47
+ const handleBlur = (val) => {
48
+ onBlur?.({ target: { value: val } });
49
+ };
50
+ const { callback: debouncedBlur } = useDebounceCallback(handleBlur, { delay: 500 });
43
51
  const state = useTimeFieldState({
44
52
  ...rest,
45
53
  isDisabled,
46
54
  value,
47
- onChange,
55
+ onChange: (val) => {
56
+ onChange?.(val);
57
+ debouncedBlur(val);
58
+ },
48
59
  locale
49
60
  });
50
61
  useEffect(() => {
@@ -72,8 +83,10 @@ var TimePickerBase = (props) => {
72
83
  labelProps
73
84
  };
74
85
  const onApply = () => {
75
- state.setValue(dialogState.value);
86
+ const newValue = dialogState.value;
87
+ state.setValue(newValue);
76
88
  setIsOpen(false);
89
+ handleBlur(newValue);
77
90
  };
78
91
  const onOpenChange = (open) => {
79
92
  setIsOpen(open);
@@ -101,6 +114,7 @@ var TimePickerBase = (props) => {
101
114
  onPress: onOpen,
102
115
  isDisabled,
103
116
  isDirty,
117
+ isRequired,
104
118
  isInvalid: !!error,
105
119
  disableDropdown,
106
120
  variant,
@@ -125,9 +139,26 @@ var TimePickerBase = (props) => {
125
139
  })
126
140
  });
127
141
  };
128
- var TimePicker = (props) => {
142
+ var TimePicker = ({ renderStaticInput, ...props }) => {
143
+ const ui = UIConfig.useConfig();
129
144
  let effectiveTimeZone = getLocalTimeZone();
130
145
  if (props.timeZone) effectiveTimeZone = props.timeZone;
146
+ const { locale } = useLocale();
147
+ const [renderInput, setRenderInput] = useState(!(renderStaticInput ?? ui.renderStaticInput));
148
+ const inputRef = useRef(null);
149
+ const { renderRealInput } = useStaticInputHandoff({
150
+ inputRef,
151
+ renderInput,
152
+ setRenderInput,
153
+ getFocusTarget: (input) => input.querySelector("input, button, [tabindex]:not([tabindex='-1'])")
154
+ });
155
+ const watchedValue = "formControl" in props && props.formControl ? useWatch({
156
+ control: props.formControl.control,
157
+ name: props.formControl.name
158
+ }) : props.value;
159
+ let isFormControlDisabled = false;
160
+ if ("formControl" in props && props.formControl) isFormControlDisabled = !!props.formControl.control._options?.disabled;
161
+ const rawValue = watchedValue ?? props.value ?? null;
131
162
  const formatTimeValue = (timeValue) => {
132
163
  if (timeValue === null) return null;
133
164
  let parsedDate;
@@ -141,17 +172,54 @@ var TimePicker = (props) => {
141
172
  if (isoString == null) return isoString;
142
173
  return toTime(DateTimeUtils.fromISOtoZonedDateTime(isoString, effectiveTimeZone));
143
174
  };
175
+ if (!renderInput) {
176
+ const timeValue = rawValue ? parseTimeValue(rawValue) : null;
177
+ const as = props.as ?? ui.input.as;
178
+ const isDisabled = isFormControlDisabled || !!props.isDisabled;
179
+ const disableManualEntry = props.disableManualEntry ?? ui.dateInput.disableManualEntry;
180
+ const showDropdown = !props.disableDropdown || disableManualEntry;
181
+ const staticSegments = getStaticTimeSegments({
182
+ value: timeValue,
183
+ locale,
184
+ isDisabled,
185
+ hidePlaceholder: as === "floating" && !timeValue
186
+ });
187
+ return /* @__PURE__ */ jsx(InputFrame, {
188
+ ...props,
189
+ isDisabled,
190
+ className: clsx("relative inline-flex w-full flex-col text-left", props.className),
191
+ inputClassName: clsx("min-w-input-width-min-width", props.inputClassName),
192
+ contentClassName: "pr-0!",
193
+ labelPlacement: "content-row",
194
+ dataAttributes: {
195
+ dataIsEmpty: timeValue === null,
196
+ dataIsFilled: timeValue !== null,
197
+ dataIsDirty: props.isDirty,
198
+ dataIsRequired: props.isRequired,
199
+ dataIsDisabled: isDisabled,
200
+ dataDisabled: isDisabled,
201
+ dataInvalid: !!props.error,
202
+ dataHasSelection: timeValue !== null
203
+ },
204
+ renderStatic: true,
205
+ onStaticInteract: renderRealInput,
206
+ trailingClassName: "py-0! pl-0!",
207
+ trailingContent: showDropdown ? ui.dateInput.timeIcon : void 0,
208
+ children: staticSegments
209
+ });
210
+ }
144
211
  if ("formControl" in props && props.formControl) {
145
212
  const { formControl, ref, ...innerProps } = props;
146
213
  return /* @__PURE__ */ jsx(Controller, {
147
214
  control: formControl.control,
148
215
  name: formControl.name,
149
- render: ({ field, fieldState: { error } }) => /* @__PURE__ */ jsx(TimePickerBase, {
216
+ render: ({ field, fieldState: { error, isDirty } }) => /* @__PURE__ */ jsx(TimePickerBase, {
150
217
  ...innerProps,
151
- ref: mergeRefs(ref, field.ref),
218
+ ref: mergeRefs(ref, field.ref, inputRef),
152
219
  value: parseTimeValue(field.value),
153
220
  onChange: (value) => field.onChange(formatTimeValue(value)),
154
221
  onBlur: field.onBlur,
222
+ isDirty,
155
223
  isDisabled: field.disabled || props.isDisabled,
156
224
  error: props.error ?? error?.message
157
225
  })
@@ -159,6 +227,7 @@ var TimePicker = (props) => {
159
227
  }
160
228
  return /* @__PURE__ */ jsx(TimePickerBase, {
161
229
  ...props,
230
+ ref: mergeRefs(props.ref, inputRef),
162
231
  value: parseTimeValue(props.value),
163
232
  onChange: (value) => props.onChange?.(formatTimeValue(value))
164
233
  });
@@ -1,5 +1,6 @@
1
1
  import { CalendarDate } from '@internationalized/date';
2
2
  import { CalendarState, CalendarStateOptions } from '@react-stately/calendar';
3
+ import { DateValue } from 'react-aria';
3
4
  import { DatePickerState } from 'react-stately';
4
5
  type DateTimeCalendarProps = {
5
6
  includesTime?: false;
@@ -14,12 +15,14 @@ type CalendarProps = DateTimeCalendarProps & {
14
15
  className?: string;
15
16
  state: CalendarState;
16
17
  calendarProps: Omit<CalendarStateOptions, "locale" | "createCalendar">;
17
- onApply: () => void;
18
+ onApply: (selectedDate?: DateValue) => void;
19
+ onDateSelectionChange?: (selectedDate: DateValue) => void;
20
+ setDateValueOnDateSelection?: boolean;
18
21
  onMonthYearChange?: (selectedDate: CalendarDate) => void;
19
22
  onMonthYearCommit?: () => void;
20
23
  selectedDate?: CalendarDate | null;
21
24
  granularity?: "day" | "month" | "year";
22
25
  };
23
26
  export type ToggleState = "month" | "year" | "time";
24
- export declare const Calendar: ({ className, includesTime, datePickerState, hourCycle, onApply, onMonthYearChange, onMonthYearCommit, selectedDate, granularity, ...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;
25
28
  export {};
@@ -5,10 +5,10 @@ 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 { useEffect, 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, onMonthYearChange, onMonthYearCommit, selectedDate, granularity = "day", ...props }) => {
11
+ var Calendar = ({ className, includesTime, datePickerState, hourCycle, onApply, onMonthYearChange, onMonthYearCommit, selectedDate, granularity = "day", setDateValueOnDateSelection = false, onDateSelectionChange, ...props }) => {
12
12
  const [toggleState, setToggleState] = useState(() => {
13
13
  if (granularity === "year") return "year";
14
14
  if (granularity === "month") return "month";
@@ -76,9 +76,25 @@ var Calendar = ({ className, includesTime, datePickerState, hourCycle, onApply,
76
76
  handleHeaderMonthNavigation(1);
77
77
  }
78
78
  };
79
- const handleDateChange = () => {
80
- if (includesTime && !datePickerState.value) setToggleState("time");
81
- else onApply();
79
+ const onDateSelection = useCallback((date) => {
80
+ if (!includesTime || !setDateValueOnDateSelection) return;
81
+ datePickerState.setDateValue(date);
82
+ }, [
83
+ includesTime,
84
+ datePickerState,
85
+ setDateValueOnDateSelection
86
+ ]);
87
+ const handleDateChange = (selectedDate) => {
88
+ const resolvedDate = selectedDate ?? props.state.focusedDate;
89
+ if (includesTime && resolvedDate && setDateValueOnDateSelection) {
90
+ datePickerState.setDateValue(resolvedDate);
91
+ onDateSelectionChange?.(resolvedDate);
92
+ }
93
+ if (includesTime && toggleState !== "time") {
94
+ setToggleState("time");
95
+ return;
96
+ }
97
+ if (datePickerState?.value && !setDateValueOnDateSelection) onApply(resolvedDate);
82
98
  };
83
99
  const getContent = () => {
84
100
  if (!toggleState) {
@@ -98,7 +114,8 @@ var Calendar = ({ className, includesTime, datePickerState, hourCycle, onApply,
98
114
  });
99
115
  return /* @__PURE__ */ jsx(CalendarGrid, {
100
116
  state: props.state,
101
- onApply: handleDateChange
117
+ onApply: handleDateChange,
118
+ onDateSelection
102
119
  });
103
120
  }
104
121
  if (toggleState === "month") {
@@ -4,7 +4,7 @@ import { KeyboardEvent } from 'react';
4
4
  import { DateValue } from 'react-aria';
5
5
  interface CalendarCellProps extends AriaCalendarCellProps {
6
6
  state: CalendarState | RangeCalendarState;
7
- onApply?: () => void;
7
+ onApply?: (selectedDate?: DateValue) => void;
8
8
  shouldCloseOnSelect?: boolean;
9
9
  onDateSelection?: (date: DateValue) => void;
10
10
  onDateHover?: (date: DateValue | null) => void;
@@ -17,12 +17,12 @@ var CalendarCell = ({ state, onApply, shouldCloseOnSelect = true, onDateSelectio
17
17
  const onClick = useCallback((event) => {
18
18
  buttonProps.onClick?.(event);
19
19
  if (onDateSelection) onDateSelection(props.date);
20
- if (isSelected && shouldCloseOnSelect) onApply?.();
20
+ if (shouldCloseOnSelect && !isDisabled) onApply?.(props.date);
21
21
  }, [
22
22
  buttonProps,
23
23
  onDateSelection,
24
24
  props.date,
25
- isSelected,
25
+ isDisabled,
26
26
  shouldCloseOnSelect,
27
27
  onApply
28
28
  ]);
@@ -87,7 +87,7 @@ var CalendarCell = ({ state, onApply, shouldCloseOnSelect = true, onDateSelectio
87
87
  state.setFocusedDate(props.date);
88
88
  }
89
89
  eventHandler?.(event);
90
- if (isSelected && shouldCloseOnSelect) onApply?.();
90
+ if (isSelected && shouldCloseOnSelect) onApply?.(props.date);
91
91
  };
92
92
  const onMouseEnter = useCallback(() => {
93
93
  if (onDateHover && selectionState.isSelectingMode) onDateHover(props.date);
@@ -4,7 +4,7 @@ import { KeyboardEvent } from 'react';
4
4
  import { DateValue } from 'react-aria';
5
5
  interface CalendarGridProps extends AriaCalendarGridProps {
6
6
  state: CalendarState | RangeCalendarState;
7
- onApply?: () => void;
7
+ onApply?: (selectedDate?: DateValue) => void;
8
8
  offset?: {
9
9
  months?: number;
10
10
  };
@@ -1,5 +1,6 @@
1
1
  import { Ref } from 'react';
2
2
  import { DatePickerAria } from 'react-aria';
3
+ import { DatePickerTodayIcon, DatePickerTodayIconButtonSize, DatePickerTodayIconPlacement } from './datePicker.types';
3
4
  import { FormFieldHeaderProps } from '../../FormField/FormFieldHeader';
4
5
  import { InputVariantProps } from '../../shared/input.cva';
5
6
  export interface DatePickerInputHandle {
@@ -18,18 +19,20 @@ interface DatePickerInputProps extends InputVariantProps {
18
19
  isDateTime?: boolean;
19
20
  isClearable?: boolean;
20
21
  headerProps?: FormFieldHeaderProps;
21
- todayIcon?: boolean;
22
+ todayIcon?: DatePickerTodayIcon;
23
+ todayIconButtonSize?: DatePickerTodayIconButtonSize;
24
+ todayIconPlacement?: DatePickerTodayIconPlacement;
22
25
  isDirty?: boolean;
23
26
  isRequired?: boolean;
24
27
  disableManualEntry?: boolean;
28
+ autoFixYear?: boolean;
25
29
  placeholder?: string;
26
30
  className?: string;
27
31
  onOpenDropdown?: () => void;
28
32
  dateGranularity?: "day" | "month" | "year";
29
33
  timeZone?: string;
30
- autoFixYear?: boolean;
31
34
  isTimeOptional?: boolean;
32
35
  format?: string;
33
36
  }
34
- 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, format, ...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;
35
38
  export {};