@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.
- package/dist/bloomreach-react-banana-ui.es.js +7413 -15720
- package/dist/bloomreach-react-banana-ui.es.js.map +1 -1
- package/dist/bloomreach-react-banana-ui.umd.js +22 -28
- package/dist/bloomreach-react-banana-ui.umd.js.map +1 -1
- package/dist/components/{inputs → date}/calendar-grid/calendar-grid.types.d.ts +7 -0
- package/dist/components/date/date-time-picker/date-time-picker.d.ts +74 -0
- package/dist/components/date/date-time-picker/date-time-picker.stories.d.ts +19 -0
- package/dist/components/date/date-time-picker/date-time-picker.types.d.ts +245 -0
- package/dist/components/date/date-time-picker/index.d.ts +3 -0
- package/dist/components/date/date-time-picker/use-date-time-picker.d.ts +35 -0
- package/dist/components/date/date-time-range-picker/date-time-range-picker.d.ts +94 -0
- package/dist/components/date/date-time-range-picker/date-time-range-picker.stories.d.ts +19 -0
- package/dist/components/date/date-time-range-picker/date-time-range-picker.types.d.ts +268 -0
- package/dist/components/date/date-time-range-picker/index.d.ts +2 -0
- package/dist/components/date/date-time-range-picker/use-date-time-range-picker.d.ts +19 -0
- package/dist/components/date/index.d.ts +2 -0
- package/dist/components/date/internal.d.ts +5 -0
- package/dist/components/date/time-selector/index.d.ts +2 -0
- package/dist/components/date/time-selector/time-selector.d.ts +24 -0
- package/dist/components/date/time-selector/time-selector.types.d.ts +52 -0
- package/dist/components/deprecated/date-time-input/date-time-input.d.ts +89 -0
- package/dist/components/deprecated/date-time-input/date-time-input.stories.d.ts +26 -0
- package/dist/components/deprecated/date-time-input/date-time-input.types.d.ts +142 -0
- package/dist/components/deprecated/date-time-input/index.d.ts +3 -0
- package/dist/components/deprecated/date-time-input/use-date-time-input.d.ts +23 -0
- package/dist/components/deprecated/index.d.ts +6 -0
- package/dist/components/feedback/toast/toast-function/toast.d.ts +1 -1
- package/dist/components/inputs/base-input/base-input.types.d.ts +5 -1
- package/dist/components/inputs/index.d.ts +0 -4
- package/dist/react-banana-ui.css +1 -1
- package/dist/utils/date/aria-date-conversion.d.ts +11 -0
- package/dist/utils/date/date-utils.d.ts +34 -0
- package/dist/utils/date/index.d.ts +1 -0
- package/dist/utils/extract-data-aria-attributes.d.ts +59 -0
- package/dist/utils/index.d.ts +1 -0
- package/package.json +56 -53
- /package/dist/components/{inputs → date}/calendar-cell/calendar-cell.d.ts +0 -0
- /package/dist/components/{inputs → date}/calendar-cell/calendar-cell.types.d.ts +0 -0
- /package/dist/components/{inputs → date}/calendar-cell/index.d.ts +0 -0
- /package/dist/components/{inputs → date}/calendar-grid/calendar-grid.d.ts +0 -0
- /package/dist/components/{inputs → date}/calendar-grid/index.d.ts +0 -0
- /package/dist/components/{inputs → date}/date-segment/date-segment.d.ts +0 -0
- /package/dist/components/{inputs → date}/date-segment/date-segment.types.d.ts +0 -0
- /package/dist/components/{inputs → date}/date-segment/index.d.ts +0 -0
- /package/dist/components/{inputs → date}/date-segments/date-segments.d.ts +0 -0
- /package/dist/components/{inputs → date}/date-segments/date-segments.types.d.ts +0 -0
- /package/dist/components/{inputs → date}/date-segments/index.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/calendar/calendar-base.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/calendar/calendar.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/calendar/calendar.qa.stories.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/calendar/calendar.stories.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/calendar/calendar.types.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/calendar/index.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/calendar/use-calendar-state.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/calendar/use-calendar.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-input/date-input.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-input/date-input.qa.stories.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-input/date-input.stories.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-input/date-input.types.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-input/index.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-input/use-date-input-state.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-input/use-date-input.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-picker/date-picker.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-picker/date-picker.qa.stories.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-picker/date-picker.stories.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-picker/date-picker.types.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-picker/index.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-picker/use-date-picker-state.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-picker/use-date-picker.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-range-picker/date-range-picker.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-range-picker/date-range-picker.qa.stories.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-range-picker/date-range-picker.stories.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-range-picker/date-range-picker.types.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-range-picker/index.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-range-picker/use-date-range-picker-state.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/date-range-picker/use-date-range-picker.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/range-calendar/index.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/range-calendar/range-calendar-base.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/range-calendar/range-calendar.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/range-calendar/range-calendar.types.d.ts +0 -0
- /package/dist/components/{inputs → deprecated}/range-calendar/use-range-calendar-state.d.ts +0 -0
- /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,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,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,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
|
+
};
|