@northlight/ui 2.43.1 → 2.43.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.
@@ -1,24 +1,44 @@
1
- import React, { useRef } from 'react'
1
+ import React, { KeyboardEventHandler, useRef } from 'react'
2
2
  import { CalendarDuo } from '@northlight/icons'
3
- import { useButton } from '@react-aria/button'
4
3
  import { Button } from '../../../button'
5
4
  import { TriggerProps } from './types'
6
5
  import { Icon } from '../../../icon'
7
6
 
8
7
  export const Trigger = (props: TriggerProps) => {
9
- const { isDisabled, handleClick } = props
8
+ const {
9
+ id,
10
+ 'aria-haspopup': ariaHasPopup,
11
+ 'aria-label': ariaLabel,
12
+ 'aria-labelledby': ariaLabelledBy,
13
+ 'aria-describedby': ariaDescribedBy,
14
+ 'aria-expanded': ariaExpanded,
15
+ isDisabled,
16
+ handleClick,
17
+ } = props
10
18
  const ref = useRef<HTMLButtonElement>(null)
11
- const { buttonProps } = useButton(props, ref)
19
+
20
+ const handleKeyDown: KeyboardEventHandler<HTMLButtonElement> = (e) => {
21
+ if (e.key === 'Enter') {
22
+ e.preventDefault()
23
+ handleClick()
24
+ }
25
+ }
12
26
 
13
27
  return (
14
28
  <Button
15
- { ...buttonProps }
16
29
  ref={ ref }
30
+ id={ id }
31
+ aria-haspopup={ ariaHasPopup }
32
+ aria-label={ ariaLabel }
33
+ aria-labelledby={ ariaLabelledBy }
34
+ aria-describedby={ ariaDescribedBy }
35
+ aria-expanded={ ariaExpanded }
17
36
  size="sm"
18
37
  boxSize={ 8 }
19
38
  variant="ghost"
20
39
  isDisabled={ isDisabled }
21
- onPointerDown={ handleClick }
40
+ onClick={ handleClick }
41
+ onKeyDown={ handleKeyDown }
22
42
  pointerEvents={ isDisabled ? 'none' : 'auto' }
23
43
  >
24
44
  <Icon as={ CalendarDuo } />
@@ -2,7 +2,6 @@ import { HTMLAttributes, ReactNode } from 'react'
2
2
  import { DateValue } from '@internationalized/date'
3
3
  import { AriaDateFieldProps } from '@react-aria/datepicker'
4
4
  import { DateFieldState, DateSegment } from '@react-stately/datepicker'
5
- import { AriaButtonProps } from '@react-aria/button'
6
5
 
7
6
  export type DateSegmentType = DateSegment
8
7
  export interface DateFieldProps extends AriaDateFieldProps<DateValue> {
@@ -20,6 +19,13 @@ export interface StyledFieldProps extends HTMLAttributes<HTMLElement> {
20
19
  children: ReactNode
21
20
  variant?: 'outline' | 'filled'
22
21
  }
23
- export interface TriggerProps extends AriaButtonProps {
22
+ export interface TriggerProps {
23
+ id?: string
24
+ 'aria-haspopup'?: boolean | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | 'true' | 'false'
25
+ 'aria-label'?: string
26
+ 'aria-labelledby'?: string
27
+ 'aria-describedby'?: string
28
+ 'aria-expanded'?: boolean | 'true' | 'false'
29
+ isDisabled?: boolean
24
30
  handleClick: () => void
25
31
  }
@@ -1,5 +1,5 @@
1
1
  import React, { useRef } from 'react'
2
- import { useMultiStyleConfig } from '@chakra-ui/react'
2
+ import { useMultiStyleConfig, useOutsideClick } from '@chakra-ui/react'
3
3
  import { useDatePicker } from '@react-aria/datepicker'
4
4
  import { useDatePickerState } from '@react-stately/datepicker'
5
5
  import { FocusScope } from '@react-aria/focus'
@@ -71,41 +71,229 @@ export const DatePicker = (props: DatePickerProps) => {
71
71
  minValue,
72
72
  variant = 'outline',
73
73
  firstDayOfWeek = 'monday',
74
+ value,
75
+ defaultValue,
76
+ onChange,
77
+ maxValue,
78
+ isReadOnly,
79
+ isRequired,
80
+ placeholderValue,
81
+ isDateUnavailable,
82
+ granularity,
83
+ hourCycle,
84
+ shouldForceLeadingZeros,
85
+ pageBehavior,
86
+ defaultOpen,
87
+ onOpenChange,
88
+ label,
89
+ description,
90
+ errorMessage,
91
+ id,
92
+ name,
93
+ autoFocus,
94
+ onFocus,
95
+ onBlur,
96
+ onFocusChange,
97
+ onKeyDown,
98
+ onKeyUp,
99
+ 'aria-label': ariaLabel,
100
+ 'aria-labelledby': ariaLabelledBy,
101
+ 'aria-describedby': ariaDescribedBy,
102
+ 'aria-details': ariaDetails,
74
103
  } = props
75
104
  const ref = useRef() as React.MutableRefObject<HTMLInputElement>
105
+ const dialogRef = useRef() as React.MutableRefObject<HTMLDivElement>
76
106
  const { group } = useMultiStyleConfig('DatePicker')
77
107
 
78
108
  const state = useDatePickerState({
79
- ...props,
109
+ value,
110
+ defaultValue,
111
+ onChange,
112
+ minValue,
113
+ maxValue,
114
+ isDisabled,
115
+ isReadOnly,
116
+ isRequired,
117
+ isInvalid,
118
+ placeholderValue,
119
+ isDateUnavailable,
120
+ granularity,
121
+ hourCycle,
122
+ shouldForceLeadingZeros,
123
+ defaultOpen,
124
+ onOpenChange,
80
125
  shouldCloseOnSelect: false,
81
126
  hideTimeZone: true,
82
127
  })
83
128
 
84
129
  const { buttonProps, fieldProps, calendarProps, groupProps, dialogProps } =
85
130
  useDatePicker(
86
- { ...props, minValue: minValue || parseDate('1994-03-08') },
131
+ {
132
+ value,
133
+ defaultValue,
134
+ onChange,
135
+ minValue: minValue || parseDate('1994-03-08'),
136
+ maxValue,
137
+ isDisabled,
138
+ isReadOnly,
139
+ isRequired,
140
+ isInvalid,
141
+ placeholderValue,
142
+ isDateUnavailable,
143
+ granularity,
144
+ hourCycle,
145
+ shouldForceLeadingZeros,
146
+ pageBehavior,
147
+ defaultOpen,
148
+ onOpenChange,
149
+ label,
150
+ description,
151
+ errorMessage,
152
+ id,
153
+ name,
154
+ autoFocus,
155
+ onFocus,
156
+ onBlur,
157
+ onFocusChange,
158
+ onKeyDown,
159
+ onKeyUp,
160
+ 'aria-label': ariaLabel,
161
+ 'aria-labelledby': ariaLabelledBy,
162
+ 'aria-describedby': ariaDescribedBy,
163
+ 'aria-details': ariaDetails,
164
+ },
87
165
  state,
88
166
  ref
89
167
  )
90
168
 
91
- const togglePopup = () => state.setOpen(!state.isOpen)
169
+ const {
170
+ id: buttonId,
171
+ 'aria-haspopup': buttonAriaHasPopup,
172
+ 'aria-label': buttonAriaLabel,
173
+ 'aria-labelledby': buttonAriaLabelledBy,
174
+ 'aria-describedby': buttonAriaDescribedBy,
175
+ 'aria-expanded': buttonAriaExpanded,
176
+ } = buttonProps
177
+
178
+ const {
179
+ id: dialogId,
180
+ 'aria-labelledby': dialogAriaLabelledBy,
181
+ } = dialogProps
182
+
183
+ const {
184
+ autoFocus: calAutoFocus,
185
+ value: calValue,
186
+ onChange: calOnChange,
187
+ minValue: calMinValue,
188
+ maxValue: calMaxValue,
189
+ isDisabled: calIsDisabled,
190
+ isReadOnly: calIsReadOnly,
191
+ isDateUnavailable: calIsDateUnavailable,
192
+ defaultFocusedValue: calDefaultFocusedValue,
193
+ isInvalid: calIsInvalid,
194
+ errorMessage: calErrorMessage,
195
+ } = calendarProps
196
+
197
+ const {
198
+ id: fieldId,
199
+ 'aria-describedby': fieldAriaDescribedBy,
200
+ 'aria-labelledby': fieldAriaLabelledBy,
201
+ value: fieldValue,
202
+ onChange: fieldOnChange,
203
+ minValue: fieldMinValue,
204
+ maxValue: fieldMaxValue,
205
+ placeholderValue: fieldPlaceholderValue,
206
+ hideTimeZone: fieldHideTimeZone,
207
+ hourCycle: fieldHourCycle,
208
+ shouldForceLeadingZeros: fieldShouldForceLeadingZeros,
209
+ granularity: fieldGranularity,
210
+ isDisabled: fieldIsDisabled,
211
+ isReadOnly: fieldIsReadOnly,
212
+ isRequired: fieldIsRequired,
213
+ isInvalid: fieldIsInvalid,
214
+ autoFocus: fieldAutoFocus,
215
+ name: fieldName,
216
+ ...restFieldProps
217
+ } = fieldProps
218
+
219
+ const {
220
+ role: groupRole,
221
+ id: groupId,
222
+ 'aria-disabled': groupAriaDisabled,
223
+ 'aria-labelledby': groupAriaLabelledBy,
224
+ 'aria-describedby': groupAriaDescribedBy,
225
+ onKeyDown: groupOnKeyDown,
226
+ onKeyUp: groupOnKeyUp,
227
+ onFocus: groupOnFocus,
228
+ onBlur: groupOnBlur,
229
+ onPointerDown: groupOnPointerDown,
230
+ onClick: groupOnClick,
231
+ } = groupProps
232
+
233
+ const togglePopup = () => {
234
+ state.setOpen(!state.isOpen)
235
+ }
236
+
237
+ useOutsideClick({
238
+ ref: dialogRef,
239
+ handler: (event) => {
240
+ if (ref.current?.contains(event.target as Node)) return
241
+ state.setOpen(false)
242
+ },
243
+ })
92
244
 
93
245
  return (
94
246
  <Popover
95
247
  isOpen={ state.isOpen }
96
248
  onClose={ () => state.setOpen(false) }
249
+ closeOnBlur={ false }
97
250
  placement="bottom-end"
98
251
  >
99
252
  <PopoverAnchor>
100
253
  <HStack minW={ 56 }>
101
- <InputGroup { ...groupProps } ref={ ref } __css={ group }>
254
+ <InputGroup
255
+ role={ groupRole }
256
+ id={ groupId }
257
+ aria-disabled={ groupAriaDisabled }
258
+ aria-labelledby={ groupAriaLabelledBy }
259
+ aria-describedby={ groupAriaDescribedBy }
260
+ onKeyDown={ groupOnKeyDown }
261
+ onKeyUp={ groupOnKeyUp }
262
+ onFocus={ groupOnFocus }
263
+ onBlur={ groupOnBlur }
264
+ onPointerDown={ groupOnPointerDown }
265
+ onClick={ groupOnClick }
266
+ ref={ ref }
267
+ __css={ group }
268
+ >
102
269
  <StyledField
103
270
  isDisabled={ isDisabled }
104
271
  isInvalid={ isInvalid }
105
272
  variant={ variant }
106
273
  >
107
274
  <Box paddingInlineStart="1a" paddingInlineEnd={ 10 }>
108
- <DateField { ...fieldProps } dateFormat={ dateFormat } />
275
+ <DateField
276
+ { ...restFieldProps }
277
+ id={ fieldId }
278
+ aria-describedby={ fieldAriaDescribedBy }
279
+ aria-labelledby={ fieldAriaLabelledBy }
280
+ value={ fieldValue }
281
+ onChange={ fieldOnChange }
282
+ minValue={ fieldMinValue }
283
+ maxValue={ fieldMaxValue }
284
+ placeholderValue={ fieldPlaceholderValue }
285
+ hideTimeZone={ fieldHideTimeZone }
286
+ hourCycle={ fieldHourCycle }
287
+ shouldForceLeadingZeros={ fieldShouldForceLeadingZeros }
288
+ granularity={ fieldGranularity }
289
+ isDisabled={ fieldIsDisabled }
290
+ isReadOnly={ fieldIsReadOnly }
291
+ isRequired={ fieldIsRequired }
292
+ isInvalid={ fieldIsInvalid }
293
+ autoFocus={ fieldAutoFocus }
294
+ name={ fieldName }
295
+ dateFormat={ dateFormat }
296
+ />
109
297
  </Box>
110
298
  </StyledField>
111
299
  <InputRightElement
@@ -113,7 +301,12 @@ export const DatePicker = (props: DatePickerProps) => {
113
301
  zIndex={ 0 }
114
302
  >
115
303
  <Trigger
116
- { ...buttonProps }
304
+ id={ buttonId }
305
+ aria-haspopup={ buttonAriaHasPopup }
306
+ aria-label={ buttonAriaLabel }
307
+ aria-labelledby={ buttonAriaLabelledBy }
308
+ aria-describedby={ buttonAriaDescribedBy }
309
+ aria-expanded={ buttonAriaExpanded }
117
310
  isDisabled={ isDisabled }
118
311
  handleClick={ togglePopup }
119
312
  />
@@ -132,10 +325,29 @@ export const DatePicker = (props: DatePickerProps) => {
132
325
  </HStack>
133
326
  </PopoverAnchor>
134
327
  { state.isOpen && (
135
- <PopoverContent { ...dialogProps } ref={ ref } w={ 64 } border="none">
328
+ <PopoverContent
329
+ id={ dialogId }
330
+ aria-labelledby={ dialogAriaLabelledBy }
331
+ ref={ dialogRef }
332
+ w={ 64 }
333
+ border="none"
334
+ >
136
335
  <FocusScope contain={ true } restoreFocus={ true }>
137
336
  <DatePickerLocaleWrapper firstDayOfWeek={ firstDayOfWeek }>
138
- <Calendar { ...calendarProps } firstDayOfWeek={ firstDayOfWeek } />
337
+ <Calendar
338
+ autoFocus={ calAutoFocus }
339
+ value={ calValue }
340
+ onChange={ calOnChange }
341
+ minValue={ calMinValue }
342
+ maxValue={ calMaxValue }
343
+ isDisabled={ calIsDisabled }
344
+ isReadOnly={ calIsReadOnly }
345
+ isDateUnavailable={ calIsDateUnavailable }
346
+ defaultFocusedValue={ calDefaultFocusedValue }
347
+ isInvalid={ calIsInvalid }
348
+ errorMessage={ calErrorMessage }
349
+ firstDayOfWeek={ firstDayOfWeek }
350
+ />
139
351
  </DatePickerLocaleWrapper>
140
352
  </FocusScope>
141
353
  </PopoverContent>
@@ -1,7 +1,8 @@
1
1
  import React, { useRef } from 'react'
2
+ import { FocusScope } from '@react-aria/focus'
2
3
  import { useDateRangePickerState } from '@react-stately/datepicker'
3
4
  import { useDateRangePicker } from '@react-aria/datepicker'
4
- import { useMultiStyleConfig } from '@chakra-ui/react'
5
+ import { useMultiStyleConfig, useOutsideClick } from '@chakra-ui/react'
5
6
  import { CheckSolid, XCloseSolid } from '@northlight/icons'
6
7
  import { identity, isNil } from 'ramda'
7
8
  import { DateValue, parseDate } from '@internationalized/date'
@@ -116,8 +117,14 @@ export const DateRangePicker = (props: DateRangePickerProps) => {
116
117
  'data-testid': dataTestId,
117
118
  defaultOpen = false,
118
119
  onOpenChange,
120
+ placeholderValue,
121
+ isDateUnavailable,
122
+ allowsNonContiguousRanges,
123
+ startName,
124
+ endName,
119
125
  } = props
120
126
  const ref = useRef() as React.MutableRefObject<HTMLInputElement>
127
+ const dialogRef = useRef() as React.MutableRefObject<HTMLDivElement>
121
128
  const { group } = useMultiStyleConfig('DatePicker')
122
129
  const parsedProps = {
123
130
  onChange: (date: DateRange) => {
@@ -137,9 +144,9 @@ export const DateRangePicker = (props: DateRangePickerProps) => {
137
144
  maxValue: parsedProps.maxValue,
138
145
  isDisabled,
139
146
  isInvalid,
140
- placeholderValue: props.placeholderValue,
141
- isDateUnavailable: props.isDateUnavailable,
142
- allowsNonContiguousRanges: props.allowsNonContiguousRanges,
147
+ placeholderValue,
148
+ isDateUnavailable,
149
+ allowsNonContiguousRanges,
143
150
  shouldCloseOnSelect: false,
144
151
  hideTimeZone: true,
145
152
  defaultOpen,
@@ -164,13 +171,13 @@ export const DateRangePicker = (props: DateRangePickerProps) => {
164
171
  value: parseValue(value) as { start: DateValue, end: DateValue },
165
172
  minValue: parsedProps.minValue || parseDate('1994-03-08'),
166
173
  maxValue: parsedProps.maxValue,
167
- placeholderValue: props.placeholderValue,
168
- isDateUnavailable: props.isDateUnavailable,
169
- allowsNonContiguousRanges: props.allowsNonContiguousRanges,
174
+ placeholderValue,
175
+ isDateUnavailable,
176
+ allowsNonContiguousRanges,
170
177
  isDisabled,
171
178
  isInvalid,
172
- startName: props.startName,
173
- endName: props.endName,
179
+ startName,
180
+ endName,
174
181
  'aria-label': 'Date range picker',
175
182
  ...(!isNil(dataTestId) && { 'data-testid': dataTestId }),
176
183
  },
@@ -178,12 +185,108 @@ export const DateRangePicker = (props: DateRangePickerProps) => {
178
185
  ref
179
186
  )
180
187
 
181
- const togglePopup = () => state.setOpen(!state.isOpen)
188
+ const {
189
+ id: buttonId,
190
+ 'aria-haspopup': buttonAriaHasPopup,
191
+ 'aria-label': buttonAriaLabel,
192
+ 'aria-labelledby': buttonAriaLabelledBy,
193
+ 'aria-describedby': buttonAriaDescribedBy,
194
+ 'aria-expanded': buttonAriaExpanded,
195
+ } = buttonProps
196
+
197
+ const {
198
+ role: groupRole,
199
+ id: groupId,
200
+ 'aria-disabled': groupAriaDisabled,
201
+ 'aria-labelledby': groupAriaLabelledBy,
202
+ 'aria-describedby': groupAriaDescribedBy,
203
+ onKeyDown: groupOnKeyDown,
204
+ onKeyUp: groupOnKeyUp,
205
+ onFocus: groupOnFocus,
206
+ onBlur: groupOnBlur,
207
+ onPointerDown: groupOnPointerDown,
208
+ onClick: groupOnClick,
209
+ } = groupProps
210
+
211
+ const {
212
+ id: startFieldId,
213
+ 'aria-describedby': startFieldAriaDescribedBy,
214
+ 'aria-labelledby': startFieldAriaLabelledBy,
215
+ value: startFieldValue,
216
+ onChange: startFieldOnChange,
217
+ minValue: startFieldMinValue,
218
+ maxValue: startFieldMaxValue,
219
+ placeholderValue: startFieldPlaceholderValue,
220
+ hideTimeZone: startFieldHideTimeZone,
221
+ hourCycle: startFieldHourCycle,
222
+ shouldForceLeadingZeros: startFieldShouldForceLeadingZeros,
223
+ granularity: startFieldGranularity,
224
+ isDisabled: startFieldIsDisabled,
225
+ isReadOnly: startFieldIsReadOnly,
226
+ isRequired: startFieldIsRequired,
227
+ isInvalid: startFieldIsInvalid,
228
+ autoFocus: startFieldAutoFocus,
229
+ name: startFieldName,
230
+ ...restStartFieldProps
231
+ } = startFieldProps
232
+
233
+ const {
234
+ id: endFieldId,
235
+ 'aria-describedby': endFieldAriaDescribedBy,
236
+ 'aria-labelledby': endFieldAriaLabelledBy,
237
+ value: endFieldValue,
238
+ onChange: endFieldOnChange,
239
+ minValue: endFieldMinValue,
240
+ maxValue: endFieldMaxValue,
241
+ placeholderValue: endFieldPlaceholderValue,
242
+ hideTimeZone: endFieldHideTimeZone,
243
+ hourCycle: endFieldHourCycle,
244
+ shouldForceLeadingZeros: endFieldShouldForceLeadingZeros,
245
+ granularity: endFieldGranularity,
246
+ isDisabled: endFieldIsDisabled,
247
+ isReadOnly: endFieldIsReadOnly,
248
+ isRequired: endFieldIsRequired,
249
+ isInvalid: endFieldIsInvalid,
250
+ name: endFieldName,
251
+ ...restEndFieldProps
252
+ } = endFieldProps
253
+
254
+ const {
255
+ id: dialogId,
256
+ 'aria-labelledby': dialogAriaLabelledBy,
257
+ } = dialogProps
258
+
259
+ const {
260
+ autoFocus: calAutoFocus,
261
+ value: calValue,
262
+ onChange: calOnChange,
263
+ minValue: calMinValue,
264
+ maxValue: calMaxValue,
265
+ isDisabled: calIsDisabled,
266
+ isReadOnly: calIsReadOnly,
267
+ isDateUnavailable: calIsDateUnavailable,
268
+ allowsNonContiguousRanges: calAllowsNonContiguousRanges,
269
+ defaultFocusedValue: calDefaultFocusedValue,
270
+ isInvalid: calIsInvalid,
271
+ errorMessage: calErrorMessage,
272
+ } = calendarProps
273
+
274
+ const togglePopup = () => {
275
+ state.setOpen(!state.isOpen)
276
+ }
182
277
 
183
278
  const handleClose = () => {
184
279
  state.setOpen(false)
185
280
  }
186
281
 
282
+ useOutsideClick({
283
+ ref: dialogRef,
284
+ handler: (event) => {
285
+ if (ref.current?.contains(event.target as Node)) return
286
+ state.setOpen(false)
287
+ },
288
+ })
289
+
187
290
  const ResetButton = CustomResetButton || (
188
291
  <IconButton
189
292
  aria-label="reset-date"
@@ -237,25 +340,86 @@ export const DateRangePicker = (props: DateRangePickerProps) => {
237
340
  <Popover
238
341
  isOpen={ state.isOpen }
239
342
  onClose={ handleModalClose }
343
+ closeOnBlur={ false }
240
344
  placement="bottom-start"
241
345
  >
242
346
  <PopoverAnchor>
243
347
  <HStack>
244
- <InputGroup { ...groupProps } ref={ ref } __css={ group }>
348
+ <InputGroup
349
+ role={ groupRole }
350
+ id={ groupId }
351
+ aria-disabled={ groupAriaDisabled }
352
+ aria-labelledby={ groupAriaLabelledBy }
353
+ aria-describedby={ groupAriaDescribedBy }
354
+ onKeyDown={ groupOnKeyDown }
355
+ onKeyUp={ groupOnKeyUp }
356
+ onFocus={ groupOnFocus }
357
+ onBlur={ groupOnBlur }
358
+ onPointerDown={ groupOnPointerDown }
359
+ onClick={ groupOnClick }
360
+ ref={ ref }
361
+ __css={ group }
362
+ >
245
363
  <StyledField
246
364
  isDisabled={ isDisabled }
247
365
  isInvalid={ isInvalid }
248
366
  variant={ variant }
249
367
  >
250
368
  <HStack paddingInlineStart="1a" paddingInlineEnd={ 10 }>
251
- <DateField { ...startFieldProps } dateFormat={ dateFormat } />
369
+ <DateField
370
+ { ...restStartFieldProps }
371
+ id={ startFieldId }
372
+ aria-describedby={ startFieldAriaDescribedBy }
373
+ aria-labelledby={ startFieldAriaLabelledBy }
374
+ value={ startFieldValue }
375
+ onChange={ startFieldOnChange }
376
+ minValue={ startFieldMinValue }
377
+ maxValue={ startFieldMaxValue }
378
+ placeholderValue={ startFieldPlaceholderValue }
379
+ hideTimeZone={ startFieldHideTimeZone }
380
+ hourCycle={ startFieldHourCycle }
381
+ shouldForceLeadingZeros={ startFieldShouldForceLeadingZeros }
382
+ granularity={ startFieldGranularity }
383
+ isDisabled={ startFieldIsDisabled }
384
+ isReadOnly={ startFieldIsReadOnly }
385
+ isRequired={ startFieldIsRequired }
386
+ isInvalid={ startFieldIsInvalid }
387
+ autoFocus={ startFieldAutoFocus }
388
+ name={ startFieldName }
389
+ dateFormat={ dateFormat }
390
+ />
252
391
  <P>-</P>
253
- <DateField { ...endFieldProps } dateFormat={ dateFormat } />
392
+ <DateField
393
+ { ...restEndFieldProps }
394
+ id={ endFieldId }
395
+ aria-describedby={ endFieldAriaDescribedBy }
396
+ aria-labelledby={ endFieldAriaLabelledBy }
397
+ value={ endFieldValue }
398
+ onChange={ endFieldOnChange }
399
+ minValue={ endFieldMinValue }
400
+ maxValue={ endFieldMaxValue }
401
+ placeholderValue={ endFieldPlaceholderValue }
402
+ hideTimeZone={ endFieldHideTimeZone }
403
+ hourCycle={ endFieldHourCycle }
404
+ shouldForceLeadingZeros={ endFieldShouldForceLeadingZeros }
405
+ granularity={ endFieldGranularity }
406
+ isDisabled={ endFieldIsDisabled }
407
+ isReadOnly={ endFieldIsReadOnly }
408
+ isRequired={ endFieldIsRequired }
409
+ isInvalid={ endFieldIsInvalid }
410
+ name={ endFieldName }
411
+ dateFormat={ dateFormat }
412
+ />
254
413
  </HStack>
255
414
  </StyledField>
256
415
  <InputRightElement sx={ { height: '100%', paddingRight: '1' } }>
257
416
  <Trigger
258
- { ...buttonProps }
417
+ id={ buttonId }
418
+ aria-haspopup={ buttonAriaHasPopup }
419
+ aria-label={ buttonAriaLabel }
420
+ aria-labelledby={ buttonAriaLabelledBy }
421
+ aria-describedby={ buttonAriaDescribedBy }
422
+ aria-expanded={ buttonAriaExpanded }
259
423
  isDisabled={ isDisabled }
260
424
  handleClick={ togglePopup }
261
425
  />
@@ -294,21 +458,39 @@ export const DateRangePicker = (props: DateRangePickerProps) => {
294
458
  </PopoverAnchor>
295
459
  <PortalWrapper renderInPortal={ renderInPortal }>
296
460
  { state.isOpen && (
297
- <PopoverContent { ...dialogProps } ref={ ref } w="max-content">
298
- <DatePickerLocaleWrapper firstDayOfWeek={ firstDayOfWeek }>
299
- <RangeCalendar
300
- { ...calendarProps }
301
- resetDate={ cancelOrResetDateChange }
302
- handleClose={ handleModalClose }
303
- fiscalStartMonth={ fiscalStartMonth || 0 }
304
- fiscalStartDay={ fiscalStartDay || 0 }
305
- isClearable={ isClearable }
306
- firstDayOfWeek={ firstDayOfWeek }
307
- onSave={ onSave }
308
- clearButtonLabel={ clearButtonLabel }
309
- buttonLabel={ buttonLabel }
310
- />
311
- </DatePickerLocaleWrapper>
461
+ <PopoverContent
462
+ id={ dialogId }
463
+ aria-labelledby={ dialogAriaLabelledBy }
464
+ ref={ dialogRef }
465
+ w="max-content"
466
+ >
467
+ <FocusScope contain={ true } restoreFocus={ true }>
468
+ <DatePickerLocaleWrapper firstDayOfWeek={ firstDayOfWeek }>
469
+ <RangeCalendar
470
+ autoFocus={ calAutoFocus }
471
+ value={ calValue }
472
+ onChange={ calOnChange }
473
+ minValue={ calMinValue }
474
+ maxValue={ calMaxValue }
475
+ isDisabled={ calIsDisabled }
476
+ isReadOnly={ calIsReadOnly }
477
+ isDateUnavailable={ calIsDateUnavailable }
478
+ allowsNonContiguousRanges={ calAllowsNonContiguousRanges }
479
+ defaultFocusedValue={ calDefaultFocusedValue }
480
+ isInvalid={ calIsInvalid }
481
+ errorMessage={ calErrorMessage }
482
+ resetDate={ cancelOrResetDateChange }
483
+ handleClose={ handleModalClose }
484
+ fiscalStartMonth={ fiscalStartMonth || 0 }
485
+ fiscalStartDay={ fiscalStartDay || 0 }
486
+ isClearable={ isClearable }
487
+ firstDayOfWeek={ firstDayOfWeek }
488
+ onSave={ onSave }
489
+ clearButtonLabel={ clearButtonLabel }
490
+ buttonLabel={ buttonLabel }
491
+ />
492
+ </DatePickerLocaleWrapper>
493
+ </FocusScope>
312
494
  </PopoverContent>
313
495
  ) }
314
496
  </PortalWrapper>
@@ -6,7 +6,7 @@ export const useArrowFocus = (columns: number) => {
6
6
  focusPrevious: previous,
7
7
  focusFirst,
8
8
  focusLast,
9
- } = useFocusManager()
9
+ } = useFocusManager()!
10
10
 
11
11
  const defaultOpts = {
12
12
  ArrowRight: {