@bloomreach/react-banana-ui 1.31.2 → 1.32.0

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 (82) hide show
  1. package/dist/bloomreach-react-banana-ui.es.js +7413 -15720
  2. package/dist/bloomreach-react-banana-ui.es.js.map +1 -1
  3. package/dist/bloomreach-react-banana-ui.umd.js +22 -28
  4. package/dist/bloomreach-react-banana-ui.umd.js.map +1 -1
  5. package/dist/components/{inputs → date}/calendar-grid/calendar-grid.types.d.ts +7 -0
  6. package/dist/components/date/date-time-picker/date-time-picker.d.ts +74 -0
  7. package/dist/components/date/date-time-picker/date-time-picker.stories.d.ts +19 -0
  8. package/dist/components/date/date-time-picker/date-time-picker.types.d.ts +245 -0
  9. package/dist/components/date/date-time-picker/index.d.ts +3 -0
  10. package/dist/components/date/date-time-picker/use-date-time-picker.d.ts +35 -0
  11. package/dist/components/date/date-time-range-picker/date-time-range-picker.d.ts +94 -0
  12. package/dist/components/date/date-time-range-picker/date-time-range-picker.stories.d.ts +19 -0
  13. package/dist/components/date/date-time-range-picker/date-time-range-picker.types.d.ts +268 -0
  14. package/dist/components/date/date-time-range-picker/index.d.ts +2 -0
  15. package/dist/components/date/date-time-range-picker/use-date-time-range-picker.d.ts +19 -0
  16. package/dist/components/date/index.d.ts +2 -0
  17. package/dist/components/date/internal.d.ts +5 -0
  18. package/dist/components/date/time-selector/index.d.ts +2 -0
  19. package/dist/components/date/time-selector/time-selector.d.ts +24 -0
  20. package/dist/components/date/time-selector/time-selector.types.d.ts +52 -0
  21. package/dist/components/deprecated/date-time-input/date-time-input.d.ts +89 -0
  22. package/dist/components/deprecated/date-time-input/date-time-input.stories.d.ts +26 -0
  23. package/dist/components/deprecated/date-time-input/date-time-input.types.d.ts +142 -0
  24. package/dist/components/deprecated/date-time-input/index.d.ts +3 -0
  25. package/dist/components/deprecated/date-time-input/use-date-time-input.d.ts +23 -0
  26. package/dist/components/deprecated/index.d.ts +6 -0
  27. package/dist/components/feedback/toast/toast-function/toast.d.ts +1 -1
  28. package/dist/components/inputs/base-input/base-input.types.d.ts +5 -1
  29. package/dist/components/inputs/index.d.ts +0 -4
  30. package/dist/react-banana-ui.css +1 -1
  31. package/dist/utils/date/aria-date-conversion.d.ts +11 -0
  32. package/dist/utils/date/date-utils.d.ts +34 -0
  33. package/dist/utils/date/index.d.ts +1 -0
  34. package/dist/utils/extract-data-aria-attributes.d.ts +59 -0
  35. package/dist/utils/index.d.ts +1 -0
  36. package/package.json +56 -53
  37. /package/dist/components/{inputs → date}/calendar-cell/calendar-cell.d.ts +0 -0
  38. /package/dist/components/{inputs → date}/calendar-cell/calendar-cell.types.d.ts +0 -0
  39. /package/dist/components/{inputs → date}/calendar-cell/index.d.ts +0 -0
  40. /package/dist/components/{inputs → date}/calendar-grid/calendar-grid.d.ts +0 -0
  41. /package/dist/components/{inputs → date}/calendar-grid/index.d.ts +0 -0
  42. /package/dist/components/{inputs → date}/date-segment/date-segment.d.ts +0 -0
  43. /package/dist/components/{inputs → date}/date-segment/date-segment.types.d.ts +0 -0
  44. /package/dist/components/{inputs → date}/date-segment/index.d.ts +0 -0
  45. /package/dist/components/{inputs → date}/date-segments/date-segments.d.ts +0 -0
  46. /package/dist/components/{inputs → date}/date-segments/date-segments.types.d.ts +0 -0
  47. /package/dist/components/{inputs → date}/date-segments/index.d.ts +0 -0
  48. /package/dist/components/{inputs → deprecated}/calendar/calendar-base.d.ts +0 -0
  49. /package/dist/components/{inputs → deprecated}/calendar/calendar.d.ts +0 -0
  50. /package/dist/components/{inputs → deprecated}/calendar/calendar.qa.stories.d.ts +0 -0
  51. /package/dist/components/{inputs → deprecated}/calendar/calendar.stories.d.ts +0 -0
  52. /package/dist/components/{inputs → deprecated}/calendar/calendar.types.d.ts +0 -0
  53. /package/dist/components/{inputs → deprecated}/calendar/index.d.ts +0 -0
  54. /package/dist/components/{inputs → deprecated}/calendar/use-calendar-state.d.ts +0 -0
  55. /package/dist/components/{inputs → deprecated}/calendar/use-calendar.d.ts +0 -0
  56. /package/dist/components/{inputs → deprecated}/date-input/date-input.d.ts +0 -0
  57. /package/dist/components/{inputs → deprecated}/date-input/date-input.qa.stories.d.ts +0 -0
  58. /package/dist/components/{inputs → deprecated}/date-input/date-input.stories.d.ts +0 -0
  59. /package/dist/components/{inputs → deprecated}/date-input/date-input.types.d.ts +0 -0
  60. /package/dist/components/{inputs → deprecated}/date-input/index.d.ts +0 -0
  61. /package/dist/components/{inputs → deprecated}/date-input/use-date-input-state.d.ts +0 -0
  62. /package/dist/components/{inputs → deprecated}/date-input/use-date-input.d.ts +0 -0
  63. /package/dist/components/{inputs → deprecated}/date-picker/date-picker.d.ts +0 -0
  64. /package/dist/components/{inputs → deprecated}/date-picker/date-picker.qa.stories.d.ts +0 -0
  65. /package/dist/components/{inputs → deprecated}/date-picker/date-picker.stories.d.ts +0 -0
  66. /package/dist/components/{inputs → deprecated}/date-picker/date-picker.types.d.ts +0 -0
  67. /package/dist/components/{inputs → deprecated}/date-picker/index.d.ts +0 -0
  68. /package/dist/components/{inputs → deprecated}/date-picker/use-date-picker-state.d.ts +0 -0
  69. /package/dist/components/{inputs → deprecated}/date-picker/use-date-picker.d.ts +0 -0
  70. /package/dist/components/{inputs → deprecated}/date-range-picker/date-range-picker.d.ts +0 -0
  71. /package/dist/components/{inputs → deprecated}/date-range-picker/date-range-picker.qa.stories.d.ts +0 -0
  72. /package/dist/components/{inputs → deprecated}/date-range-picker/date-range-picker.stories.d.ts +0 -0
  73. /package/dist/components/{inputs → deprecated}/date-range-picker/date-range-picker.types.d.ts +0 -0
  74. /package/dist/components/{inputs → deprecated}/date-range-picker/index.d.ts +0 -0
  75. /package/dist/components/{inputs → deprecated}/date-range-picker/use-date-range-picker-state.d.ts +0 -0
  76. /package/dist/components/{inputs → deprecated}/date-range-picker/use-date-range-picker.d.ts +0 -0
  77. /package/dist/components/{inputs → deprecated}/range-calendar/index.d.ts +0 -0
  78. /package/dist/components/{inputs → deprecated}/range-calendar/range-calendar-base.d.ts +0 -0
  79. /package/dist/components/{inputs → deprecated}/range-calendar/range-calendar.d.ts +0 -0
  80. /package/dist/components/{inputs → deprecated}/range-calendar/range-calendar.types.d.ts +0 -0
  81. /package/dist/components/{inputs → deprecated}/range-calendar/use-range-calendar-state.d.ts +0 -0
  82. /package/dist/components/{inputs → deprecated}/range-calendar/use-range-calendar.d.ts +0 -0
@@ -0,0 +1,268 @@
1
+ import { DateFieldAria, DateRangePickerAria } from '@react-aria/datepicker';
2
+ import { RangeCalendarState } from '@react-stately/calendar';
3
+ import { DateFieldState, DateRangePickerState } from '@react-stately/datepicker';
4
+ import { GroupDOMAttributes } from '@react-types/shared';
5
+ import { DOMAttributes, FocusEventHandler, InputHTMLAttributes, KeyboardEventHandler, MouseEventHandler, RefObject } from 'react';
6
+ import { DateValidationResult } from '../../../utils/date';
7
+ import { DateRangeValue } from '../../../utils/types/date.types';
8
+ import { ButtonProps } from '../../buttons';
9
+ /**
10
+ * Context object passed to the onChange handler of DateTimeRangePicker.
11
+ * Contains validation information and state for error handling.
12
+ */
13
+ export interface DateTimeRangePickerChangeHandlerContext extends DateValidationResult {
14
+ /**
15
+ * Whether the current date/time range value is valid.
16
+ */
17
+ valid: boolean;
18
+ }
19
+ /**
20
+ * Props for the DateTimeRangePicker component.
21
+ *
22
+ * The DateTimeRangePicker combines date and time range selection in a single component.
23
+ * It uses DateTimeInput components for both start and end inputs and provides a popup with both
24
+ * calendar for date selection and time selectors for hour, minute, and second.
25
+ */
26
+ export interface DateTimeRangePickerProps {
27
+ /**
28
+ * Custom class name for the container of the component.
29
+ */
30
+ className?: string;
31
+ /**
32
+ * The date and time range that is selected when the component first mounts (uncontrolled).
33
+ * Should be an object with start and end Date objects representing the initial range.
34
+ */
35
+ defaultValue?: DateRangeValue;
36
+ /**
37
+ * Whether the date-time range picker is disabled.
38
+ * When disabled, the user cannot interact with the picker and it appears grayed out.
39
+ * @default false
40
+ */
41
+ disabled?: boolean;
42
+ /**
43
+ * Whether the date-time range picker is in an error state.
44
+ * When true, the picker will display error styling to indicate validation issues.
45
+ * @default false
46
+ */
47
+ error?: boolean;
48
+ /**
49
+ * The <form> element to associate the input with.
50
+ * The value of this attribute must be the id of a <form> in the same document.
51
+ */
52
+ form?: string;
53
+ /**
54
+ * Determines which date and time segments are displayed and editable.
55
+ * - `'day'`: Shows only date segments (year, month, day)
56
+ * - `'hour'`: Shows date and hour segments
57
+ * - `'minute'`: Shows date, hour, and minute segments
58
+ * - `'second'`: Shows date, hour, minute, and second segments
59
+ * @default 'minute'
60
+ */
61
+ granularity?: 'day' | 'hour' | 'minute' | 'second';
62
+ /**
63
+ * The hour cycle to use for formatting the date and time.
64
+ * @default 12
65
+ */
66
+ hourCycle?: 12 | 24;
67
+ /**
68
+ * The ID of the input element.
69
+ * Used for accessibility and form association.
70
+ */
71
+ id?: string;
72
+ /**
73
+ * The locale to use for formatting the date and time.
74
+ * Follows BCP 47 language tag format (e.g., 'en-US', 'de-DE', 'ja-JP').
75
+ * When not provided, uses the user's browser locale.
76
+ * @example 'en-US', 'de-DE', 'fr-FR'
77
+ */
78
+ locale?: string;
79
+ /**
80
+ * The maximum date and time that a user can enter.
81
+ * Dates after this value will be considered invalid.
82
+ * Should be a JavaScript Date object.
83
+ */
84
+ maxDate?: Date;
85
+ /**
86
+ * The minimum date and time that a user can enter.
87
+ * Dates before this value will be considered invalid.
88
+ * Should be a JavaScript Date object.
89
+ */
90
+ minDate?: Date;
91
+ /**
92
+ * The name of the input element, used when submitting an HTML form.
93
+ * See @link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#name.
94
+ */
95
+ name?: string;
96
+ /**
97
+ * Handler that is called when the input loses focus.
98
+ * Receives the blur event from the date/time range inputs.
99
+ */
100
+ onBlur?: FocusEventHandler<Element>;
101
+ /**
102
+ * Handler that is called when the date/time range value changes.
103
+ * Receives the new DateRangeValue object or null if the input is cleared,
104
+ * along with a context object containing validation information.
105
+ *
106
+ * @param value - The new date/time range value as a DateRangeValue object, or null if cleared
107
+ * @param context - Validation context with validity state and messages
108
+ *
109
+ * @example
110
+ * ```tsx
111
+ * const handleChange = (value: DateRangeValue | null, context: DateTimeRangePickerChangeHandlerContext) => {
112
+ * if (context.valid && value) {
113
+ * console.log('Valid date/time range selected:', {
114
+ * start: value.start.toISOString(),
115
+ * end: value.end.toISOString()
116
+ * });
117
+ * } else {
118
+ * console.log('Invalid date/time range or validation errors:', context.validationMessage);
119
+ * }
120
+ * };
121
+ * ```
122
+ */
123
+ onChange?: (value: DateRangeValue | null, context: DateTimeRangePickerChangeHandlerContext) => void;
124
+ /**
125
+ * Handler that is called when the input is clicked.
126
+ * Can be used to programmatically open the picker.
127
+ */
128
+ onClick?: MouseEventHandler<Element>;
129
+ /**
130
+ * Handler that is called when the input receives focus.
131
+ * Receives the focus event from the date/time range inputs.
132
+ */
133
+ onFocus?: FocusEventHandler<Element>;
134
+ /**
135
+ * Handler that is called when a key is pressed within the input.
136
+ * Receives keyboard events from the date/time range inputs.
137
+ */
138
+ onKeyDown?: KeyboardEventHandler<Element>;
139
+ /**
140
+ * Handler that is called when a key is released within the input.
141
+ * Receives keyboard events from the date/time range inputs.
142
+ */
143
+ onKeyUp?: KeyboardEventHandler<Element>;
144
+ /**
145
+ * Handler that is called when the popup with calendar and time selectors changes state.
146
+ * Use this to track when the picker is opened or closed.
147
+ *
148
+ * @param open - Whether the popup is currently open
149
+ *
150
+ * @example
151
+ * ```tsx
152
+ * const handleOpenChange = (open: boolean) => {
153
+ * console.log(open ? 'Picker opened' : 'Picker closed');
154
+ * };
155
+ * ```
156
+ */
157
+ onOpenChange?: (open: boolean) => void;
158
+ /**
159
+ * A placeholder date that influences the format and default values of empty segments.
160
+ * This date is used to determine the format and structure but is not the actual value.
161
+ * Useful for setting the year when only month/day are relevant, or timezone context.
162
+ * Defaults to today's date.
163
+ *
164
+ * @default new Date()
165
+ * @example new Date('2024-12-31T23:59:59') // Shows full format structure
166
+ */
167
+ placeholderValue?: Date;
168
+ /**
169
+ * Whether the date-time range picker is read-only.
170
+ * When true, the user can see the value but cannot edit it.
171
+ * The picker will still be focusable and the popup can be opened to view the calendar.
172
+ * @default false
173
+ */
174
+ readOnly?: boolean;
175
+ /**
176
+ * Whether the date-time range picker is required for form submission.
177
+ * When true, the picker must have a value for the form to be valid.
178
+ * @default false
179
+ */
180
+ required?: boolean;
181
+ /**
182
+ * Whether to show the timezone in the date and time range picker.
183
+ * @default false
184
+ */
185
+ showTimezone?: boolean;
186
+ /**
187
+ * The current date and time range value (controlled).
188
+ * Should be a DateRangeValue object with start and end Date objects,
189
+ * or null if no range is selected.
190
+ *
191
+ * @example
192
+ * ```tsx
193
+ * const [value, setValue] = useState<DateRangeValue | null>({
194
+ * start: new Date('2024-01-01T09:00:00'),
195
+ * end: new Date('2024-01-01T17:00:00')
196
+ * });
197
+ * return <DateTimeRangePicker value={value} onChange={(newValue) => setValue(newValue)} />;
198
+ * ```
199
+ */
200
+ value?: DateRangeValue | null;
201
+ }
202
+ /**
203
+ * Return type for the useDateTimeRangePicker hook.
204
+ * Contains all the props, state, and handlers needed to render the DateTimeRangePicker component.
205
+ */
206
+ export interface UseDateTimeRangePickerReturn {
207
+ /** Calendar-related props and state for the date range selection */
208
+ calendarProps: {
209
+ /** Props for the calendar component */
210
+ calendarProps: DOMAttributes<HTMLElement>;
211
+ /** Ref for the calendar component */
212
+ calendarRef: RefObject<HTMLDivElement>;
213
+ /** Range calendar state object for date range selection */
214
+ calendarState: RangeCalendarState;
215
+ /** Title for the left calendar month */
216
+ leftTitle: string;
217
+ /** Props for the next month button */
218
+ nextButtonProps: Omit<ButtonProps, 'type'>;
219
+ /** Props for the previous month button */
220
+ prevButtonProps: Omit<ButtonProps, 'type'>;
221
+ /** Title for the right calendar month */
222
+ rightTitle: string;
223
+ };
224
+ /** Date field-related props and state for both start and end inputs */
225
+ dateFieldProps: {
226
+ /** Ref for the end date field hidden input component */
227
+ dateFieldEndInputRef: RefObject<HTMLInputElement>;
228
+ /** Props for the end date field component */
229
+ dateFieldEndProps: DateFieldAria['fieldProps'];
230
+ /** Ref for the end date field component */
231
+ dateFieldEndRef: RefObject<HTMLElement>;
232
+ /** End date field state object */
233
+ dateFieldEndState: DateFieldState;
234
+ /** Props for the hidden end input element */
235
+ hiddenInputEndProps: InputHTMLAttributes<HTMLInputElement>;
236
+ /** Ref for the start date field hidden input component */
237
+ dateFieldStartInputRef: RefObject<HTMLInputElement>;
238
+ /** Props for the start date field component */
239
+ dateFieldStartProps: DateFieldAria['fieldProps'];
240
+ /** Ref for the start date field component */
241
+ dateFieldStartRef: RefObject<HTMLElement>;
242
+ /** Start date field state object */
243
+ dateFieldStartState: DateFieldState;
244
+ /** Props for the hidden start input element */
245
+ hiddenInputStartProps: InputHTMLAttributes<HTMLInputElement>;
246
+ /** Props for the input group container */
247
+ groupProps: GroupDOMAttributes;
248
+ };
249
+ /** The React Aria date range picker state object */
250
+ dateRangePickerState: DateRangePickerState;
251
+ /** Props for the popup component */
252
+ popupProps: {
253
+ /** Props for the popup dialog container */
254
+ dialogProps: DateRangePickerAria['dialogProps'];
255
+ };
256
+ /** Time field-related props and handlers for both start and end times */
257
+ timeFieldProps: {
258
+ /** Handler for time value changes */
259
+ onTimeChange: (part: 'end' | 'start', newTime: Date) => void;
260
+ /** Current time values as Date objects for start and end */
261
+ timeValue: {
262
+ /** End time value */
263
+ end: Date | null;
264
+ /** Start time value */
265
+ start: Date | null;
266
+ };
267
+ };
268
+ }
@@ -0,0 +1,2 @@
1
+ export { default as DateTimeRangePicker } from './date-time-range-picker';
2
+ export type { DateTimeRangePickerChangeHandlerContext, DateTimeRangePickerProps } from './date-time-range-picker.types';
@@ -0,0 +1,19 @@
1
+ import { RefObject } from 'react';
2
+ import { DateTimeRangePickerProps, UseDateTimeRangePickerReturn } from './date-time-range-picker.types';
3
+ /**
4
+ * Custom hook that manages the state and behavior for the DateTimeRangePicker component.
5
+ * Combines React Aria's date range picker functionality with time selection capabilities.
6
+ *
7
+ * This hook handles:
8
+ * - Date range picker state management via React Aria
9
+ * - Start and end date/time input states
10
+ * - Calendar state for the popup
11
+ * - Time selection integration
12
+ * - Focus management and keyboard navigation
13
+ * - Form integration with hidden inputs
14
+ *
15
+ * @param props - DateTimeRangePicker component props
16
+ * @param ref - React ref to the container element
17
+ * @returns Object containing state, props, and handlers for the component
18
+ */
19
+ export declare const useDateTimeRangePicker: (props: DateTimeRangePickerProps, ref: RefObject<Element>) => UseDateTimeRangePickerReturn;
@@ -0,0 +1,2 @@
1
+ export * from './date-time-picker';
2
+ export * from './date-time-range-picker';
@@ -0,0 +1,5 @@
1
+ export * from './calendar-cell';
2
+ export * from './calendar-grid';
3
+ export * from './date-segment';
4
+ export * from './date-segments';
5
+ export * from './time-selector';
@@ -0,0 +1,2 @@
1
+ export { default as TimeSelector } from './time-selector';
2
+ export type { TimeSelectorProps } from './time-selector.types';
@@ -0,0 +1,24 @@
1
+ import { ReactElement } from 'react';
2
+ import { TimeSelectorProps } from './time-selector.types';
3
+ /**
4
+ * TimeSelector provides hour, minute, and second selection using Select dropdowns.
5
+ *
6
+ * This component is used within the DateTimePicker popup to allow users to select
7
+ * specific time values. It shows different selectors based on the granularity prop
8
+ * and maintains the current date while updating only the time components.
9
+ *
10
+ * ## Features
11
+ *
12
+ * - **Granular Control**: Shows appropriate selectors based on granularity
13
+ * - **24-hour Format**: Uses 24-hour time format (0-23 for hours)
14
+ * - **Current Value Preservation**: Maintains existing date when updating time
15
+ * - **Accessibility**: Uses semantic Select components with proper labeling
16
+ *
17
+ * @param props - The props for the TimeSelector component
18
+ * @returns A time selection panel with appropriate selectors
19
+ */
20
+ declare const TimeSelector: {
21
+ (props: TimeSelectorProps): null | ReactElement;
22
+ displayName: string;
23
+ };
24
+ export default TimeSelector;
@@ -0,0 +1,52 @@
1
+ import { TimeGranularity, TimeRangeType } from '../../../utils';
2
+ /**
3
+ * Props for the TimeSelectorPanel component.
4
+ */
5
+ export interface TimeSelectorProps {
6
+ /**
7
+ * The current date/time value. Used to extract current hour, minute, and second.
8
+ */
9
+ value?: Date | null;
10
+ /**
11
+ * Determines which time components are shown based on granularity.
12
+ * - `'day'`: No time selectors shown
13
+ * - `'hour'`: Show hour selector only
14
+ * - `'minute'`: Show hour and minute selectors
15
+ * - `'second'`: Show hour, minute, and second selectors
16
+ */
17
+ granularity?: TimeGranularity;
18
+ /**
19
+ * Whether to display time in 12 or 24 hour format.
20
+ * - `12`: Shows time in 12-hour format with AM/PM selector
21
+ * - `24`: Shows time in 24-hour format without AM/PM
22
+ * @default 12
23
+ */
24
+ hourCycle?: 12 | 24;
25
+ /**
26
+ * Called when any time component changes.
27
+ * @param newValue - The updated Date object with new time values
28
+ */
29
+ onChange?: (newValue: Date) => void;
30
+ /**
31
+ * Whether the time selectors are disabled.
32
+ * @default false
33
+ */
34
+ disabled?: boolean;
35
+ /**
36
+ * Whether the time selectors are read-only.
37
+ * @default false
38
+ */
39
+ readOnly?: boolean;
40
+ /**
41
+ * Specifies which part of a date/time range this TimeSelector represents.
42
+ * - `'end'`: End of range, defaults to end-of-day time (23:59:59) based on granularity
43
+ * - `'single'`: Single date/time picker, defaults to beginning-of-day time (00:00:00)
44
+ * - `'start'`: Start of range, defaults to beginning-of-day time (00:00:00)
45
+ * @default 'single'
46
+ */
47
+ rangeType?: TimeRangeType;
48
+ /**
49
+ * Additional CSS class names to apply to the time selector container.
50
+ */
51
+ className?: string;
52
+ }
@@ -0,0 +1,89 @@
1
+ import { DateTimeInputProps } from './date-time-input.types';
2
+ /**
3
+ * DateTimeInput allows users to enter and edit date and time values using a keyboard.
4
+ * Each part of a date/time value is displayed in an individually editable segment.
5
+ * The component supports various granularities from day-level to second-level precision.
6
+ *
7
+ * Built on top of React Aria's `useDateField` hook for accessibility and internationalization support.
8
+ * Automatically formats the displayed date/time based on the locale and provides proper keyboard navigation.
9
+ *
10
+ * ## Features
11
+ *
12
+ * - **Keyboard Navigation**: Arrow keys, Tab, and direct typing
13
+ * - **Accessibility**: Full screen reader and keyboard support via React Aria
14
+ * - **Internationalization**: Automatic formatting based on locale
15
+ * - **Validation**: Built-in min/max date validation
16
+ * - **Granularity Control**: Support for day, hour, minute, and second precision
17
+ * - **Controlled/Uncontrolled**: Supports both controlled and uncontrolled usage
18
+ *
19
+ * ## Usage
20
+ *
21
+ * ### Basic Usage
22
+ * ```tsx
23
+ * import { DateTimeInput } from '@bloomreach/react-banana-ui';
24
+ *
25
+ * function MyComponent() {
26
+ * const [value, setValue] = useState<Date | null>(new Date());
27
+ *
28
+ * return (
29
+ * <DateTimeInput
30
+ * value={value}
31
+ * onChange={setValue}
32
+ * granularity="minute"
33
+ * />
34
+ * );
35
+ * }
36
+ * ```
37
+ *
38
+ * ### With Validation
39
+ * ```tsx
40
+ * <DateTimeInput
41
+ * value={value}
42
+ * onChange={setValue}
43
+ * minDate={new Date('2024-01-01')}
44
+ * maxDate={new Date('2024-12-31')}
45
+ * granularity="hour"
46
+ * error={!isValid}
47
+ * required
48
+ * />
49
+ * ```
50
+ *
51
+ * ### Different Granularities
52
+ * ```tsx
53
+ * // Date only
54
+ * <DateTimeInput granularity="day" />
55
+ *
56
+ * // Date and hour
57
+ * <DateTimeInput granularity="hour" />
58
+ *
59
+ * // Date, hour, and minute (default)
60
+ * <DateTimeInput granularity="minute" />
61
+ *
62
+ * // Full precision including seconds
63
+ * <DateTimeInput granularity="second" />
64
+ * ```
65
+ *
66
+ * ### Localization
67
+ * ```tsx
68
+ * <DateTimeInput
69
+ * locale="de-DE"
70
+ * value={value}
71
+ * onChange={setValue}
72
+ * placeholderValue={new Date('2024-12-31T23:59:59')}
73
+ * />
74
+ * ```
75
+ *
76
+ * ## Accessibility
77
+ *
78
+ * The component follows WAI-ARIA guidelines and provides:
79
+ * - Proper focus management between segments
80
+ * - Screen reader announcements for value changes
81
+ * - Keyboard navigation with arrow keys
82
+ * - Support for assistive technologies
83
+ *
84
+ * @param props - The props for the DateTimeInput component
85
+ * @param forwardedRef - Ref to be forwarded to the underlying input element
86
+ * @returns A date/time input component with editable segments
87
+ */
88
+ declare const DateTimeInput: import('react').ForwardRefExoticComponent<DateTimeInputProps & import('react').RefAttributes<HTMLElement>>;
89
+ export default DateTimeInput;
@@ -0,0 +1,26 @@
1
+ import { default as DateTimeInput } from './date-time-input';
2
+ import { Meta, StoryObj } from '@storybook/react-vite';
3
+ declare const meta: Meta<typeof DateTimeInput>;
4
+ export default meta;
5
+ export type Story = StoryObj<typeof DateTimeInput>;
6
+ export declare const Basic: Story;
7
+ export declare const WithDefaultValue: Story;
8
+ export declare const Controlled: Story;
9
+ export declare const GranularityDay: Story;
10
+ export declare const GranularityHour: Story;
11
+ export declare const GranularityMinute: Story;
12
+ export declare const GranularitySecond: Story;
13
+ export declare const AllGranularities: Story;
14
+ export declare const PlaceholderValue: Story;
15
+ export declare const MinDateTime: Story;
16
+ export declare const MaxDateTime: Story;
17
+ export declare const MinMaxDateTime: Story;
18
+ export declare const ErrorState: Story;
19
+ export declare const ValidationWithErrorHandling: Story;
20
+ export declare const DisabledState: Story;
21
+ export declare const ReadOnlyState: Story;
22
+ export declare const RequiredField: Story;
23
+ export declare const MultipleLocales: Story;
24
+ export declare const EventHandling: Story;
25
+ export declare const FormIntegration: Story;
26
+ export declare const RealWorldScenarios: Story;
@@ -0,0 +1,142 @@
1
+ import { FocusEventHandler, KeyboardEventHandler, MouseEventHandler } from 'react';
2
+ /**
3
+ * Props for the DateTimeInput component.
4
+ *
5
+ * The DateTimeInput allows users to enter and edit date and time values using a keyboard.
6
+ * Each part of a date/time value is displayed in an individually editable segment.
7
+ * The component supports various granularities from day-level to second-level precision.
8
+ */
9
+ export interface DateTimeInputProps {
10
+ /**
11
+ * Custom class name for the container of the component.
12
+ */
13
+ className?: string;
14
+ /**
15
+ * The date and time that is selected when the input first mounts (uncontrolled).
16
+ * Should be a JavaScript Date object representing the initial value.
17
+ */
18
+ defaultValue?: Date;
19
+ /**
20
+ * Whether the input is disabled.
21
+ * When disabled, the user cannot interact with the input and it appears grayed out.
22
+ * @default false
23
+ */
24
+ disabled?: boolean;
25
+ /**
26
+ * Whether the input is in an error state.
27
+ * When true, the input will display error styling to indicate validation issues.
28
+ * @default false
29
+ */
30
+ error?: boolean;
31
+ /**
32
+ * Determines which date and time segments are displayed and editable.
33
+ * - `'day'`: Shows only date segments (year, month, day)
34
+ * - `'hour'`: Shows date and hour segments
35
+ * - `'minute'`: Shows date, hour, and minute segments
36
+ * - `'second'`: Shows date, hour, minute, and second segments
37
+ * @default 'minute'
38
+ */
39
+ granularity?: 'day' | 'hour' | 'minute' | 'second';
40
+ /**
41
+ * Whether to display time in 12 or 24 hour format.
42
+ * By default, this is determined by the user's locale.
43
+ * - `12`: Shows time in 12-hour format with AM/PM
44
+ * - `24`: Shows time in 24-hour format
45
+ * @default 12
46
+ */
47
+ hourCycle?: 12 | 24;
48
+ /**
49
+ * The ID of the input element.
50
+ * Used for accessibility and form association.
51
+ */
52
+ id?: string;
53
+ /**
54
+ * The locale to use for formatting the date and time.
55
+ * Follows BCP 47 language tag format (e.g., 'en-US', 'de-DE', 'ja-JP').
56
+ * When not provided, uses the user's browser locale.
57
+ * @example 'en-US', 'de-DE', 'fr-FR'
58
+ */
59
+ locale?: string;
60
+ /**
61
+ * The maximum date and time that a user can enter.
62
+ * Dates after this value will be considered invalid.
63
+ * Should be a JavaScript Date object.
64
+ */
65
+ maxDate?: Date;
66
+ /**
67
+ * The minimum date and time that a user can enter.
68
+ * Dates before this value will be considered invalid.
69
+ * Should be a JavaScript Date object.
70
+ */
71
+ minDate?: Date;
72
+ /**
73
+ * Handler that is called when the input loses focus.
74
+ * Receives the blur event from any of the date/time segments.
75
+ */
76
+ onBlur?: FocusEventHandler<Element>;
77
+ /**
78
+ * Handler that is called when the date/time value changes.
79
+ * Receives the new Date object or null if the input is cleared.
80
+ *
81
+ * @param value - The new date/time value as a Date object, or null if cleared
82
+ *
83
+ * @example
84
+ * ```tsx
85
+ * const handleChange = (value: Date | null) => {
86
+ * if (value) {
87
+ * console.log('Selected date/time:', value.toISOString());
88
+ * } else {
89
+ * console.log('Input cleared');
90
+ * }
91
+ * };
92
+ * ```
93
+ */
94
+ onChange?: (value: Date | null) => void;
95
+ /**
96
+ * Handler that is called when the input is clicked.
97
+ */
98
+ onClick?: MouseEventHandler<Element>;
99
+ /**
100
+ * Handler that is called when the input receives focus.
101
+ * Receives the focus event from any of the date/time segments.
102
+ */
103
+ onFocus?: FocusEventHandler<Element>;
104
+ /**
105
+ * Handler that is called when a key is pressed within the input.
106
+ * Receives keyboard events from any of the date/time segments.
107
+ */
108
+ onKeyDown?: KeyboardEventHandler<Element>;
109
+ /**
110
+ * A placeholder date that influences the format and default values of empty segments.
111
+ * This date is used to determine the format and structure but is not the actual value.
112
+ * Useful for setting the year when only month/day are relevant, or timezone context.
113
+ *
114
+ * @example new Date('2024-12-31T23:59:59') // Shows full format structure
115
+ */
116
+ placeholderValue?: Date;
117
+ /**
118
+ * Whether the input is read-only.
119
+ * When true, the user can see the value but cannot edit it.
120
+ * The input will still be focusable and selectable.
121
+ * @default false
122
+ */
123
+ readOnly?: boolean;
124
+ /**
125
+ * Whether the input is required for form submission.
126
+ * When true, the input must have a value for the form to be valid.
127
+ * @default false
128
+ */
129
+ required?: boolean;
130
+ /**
131
+ * The current date and time value (controlled).
132
+ * Should be a JavaScript Date object representing the current value,
133
+ * or null if no value is selected.
134
+ *
135
+ * @example
136
+ * ```tsx
137
+ * const [value, setValue] = useState<Date | null>(new Date());
138
+ * return <DateTimeInput value={value} onChange={setValue} />;
139
+ * ```
140
+ */
141
+ value?: Date | null;
142
+ }
@@ -0,0 +1,3 @@
1
+ export { default as DateTimeInput } from './date-time-input';
2
+ export { useDateTimeInput } from './use-date-time-input';
3
+ export type { DateTimeInputProps } from './date-time-input.types';
@@ -0,0 +1,23 @@
1
+ import { DateFieldAria } from '@react-aria/datepicker';
2
+ import { DateFieldState } from '@react-stately/datepicker';
3
+ import { InputHTMLAttributes, RefObject } from 'react';
4
+ import { DateTimeInputProps } from './date-time-input.types';
5
+ /**
6
+ * Combined hook that provides both state management and behavior for a date-time input component.
7
+ * Handles the conversion between Date objects and React Aria's internal date representation,
8
+ * manages locale settings, and provides accessibility implementation.
9
+ *
10
+ * Built on top of React Aria's useDateField and useDateFieldState hooks to provide proper
11
+ * keyboard navigation, screen reader support, and ARIA attributes for date-time input segments.
12
+ *
13
+ * @param props - The props for the DateTimeInput component
14
+ * @param forwardedRef - Optional ref to be forwarded to the input element
15
+ * @returns Object containing state, field props, hidden input props, and internal ref
16
+ * @internal
17
+ */
18
+ export declare function useDateTimeInput(props: DateTimeInputProps, forwardedRef?: null | RefObject<Element>): {
19
+ fieldProps: DateFieldAria['fieldProps'];
20
+ hiddenInputProps: InputHTMLAttributes<HTMLInputElement>;
21
+ ref: RefObject<Element>;
22
+ state: DateFieldState;
23
+ };
@@ -0,0 +1,6 @@
1
+ export * from './calendar';
2
+ export * from './date-input';
3
+ export * from './date-picker';
4
+ export * from './date-range-picker';
5
+ export * from './date-time-input';
6
+ export * from './range-calendar';