@octanejs/aria 0.0.46 → 0.0.48
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/README.md +7 -6
- package/UPSTREAM.md +58 -69
- package/package.json +11 -11
- package/src/calendar/useCalendarGrid.tsx +64 -62
- package/src/collections/Document.ts +3 -0
- package/src/color/useColorArea.tsx +95 -69
- package/src/color/useColorWheel.tsx +38 -37
- package/src/combobox/{useComboBox.ts → useComboBox.tsx} +243 -258
- package/src/components/ComboBox.ts +35 -2
- package/src/components/Dialog.ts +12 -1
- package/src/components/DropZone.tsx +3 -2
- package/src/components/FileTrigger.tsx +1 -0
- package/src/components/GridList.ts +11 -2
- package/src/components/ListBox.ts +1 -1
- package/src/components/Menu.ts +1 -0
- package/src/components/Meter.ts +3 -1
- package/src/components/Popover.ts +20 -8
- package/src/components/PreviewTrigger.tsx +101 -0
- package/src/components/ProgressBar.ts +10 -2
- package/src/components/Select.ts +1 -1
- package/src/components/Table.ts +26 -15
- package/src/components/TokenField.tsx +395 -0
- package/src/components/Tooltip.ts +4 -6
- package/src/components/Tree.ts +14 -7
- package/src/components/Virtualizer.tsx +30 -14
- package/src/components/index.ts +22 -0
- package/src/components/utils.ts +1 -1
- package/src/datepicker/useDateField.tsx +2 -11
- package/src/datepicker/useDatePickerGroup.tsx +44 -33
- package/src/datepicker/useDateSegment.tsx +31 -30
- package/src/dialog/useDialog.ts +8 -1
- package/src/dnd/DragManager.tsx +5 -1
- package/src/dnd/useDrag.tsx +2 -1
- package/src/focus/FocusScope.ts +2 -2
- package/src/grid/useGrid.ts +3 -0
- package/src/grid/{useGridCell.ts → useGridCell.tsx} +128 -66
- package/src/grid/utils.ts +1 -0
- package/src/gridlist/{useGridListItem.ts → useGridListItem.tsx} +154 -112
- package/src/index.ts +22 -0
- package/src/interactions/createEventHandler.ts +11 -8
- package/src/interactions/createKeyboardShortcutHandler.tsx +218 -0
- package/src/interactions/textSelection.ts +3 -3
- package/src/interactions/useContextMenu.tsx +125 -0
- package/src/interactions/useFocusVisible.ts +4 -4
- package/src/interactions/useKeyboard.ts +50 -2
- package/src/interactions/useLongPress.ts +33 -22
- package/src/interactions/useMove.ts +6 -6
- package/src/interactions/usePress.ts +8 -0
- package/src/interactions/utils.ts +10 -10
- package/src/intl/combobox/fi-FI.json +2 -2
- package/src/intl/previewtrigger/ar-AE.json +3 -0
- package/src/intl/previewtrigger/bg-BG.json +3 -0
- package/src/intl/previewtrigger/cs-CZ.json +3 -0
- package/src/intl/previewtrigger/da-DK.json +3 -0
- package/src/intl/previewtrigger/de-DE.json +3 -0
- package/src/intl/previewtrigger/el-GR.json +3 -0
- package/src/intl/previewtrigger/en-US.json +3 -0
- package/src/intl/previewtrigger/es-ES.json +3 -0
- package/src/intl/previewtrigger/et-EE.json +3 -0
- package/src/intl/previewtrigger/fi-FI.json +3 -0
- package/src/intl/previewtrigger/fr-FR.json +3 -0
- package/src/intl/previewtrigger/he-IL.json +3 -0
- package/src/intl/previewtrigger/hr-HR.json +3 -0
- package/src/intl/previewtrigger/hu-HU.json +3 -0
- package/src/intl/previewtrigger/index.ts +73 -0
- package/src/intl/previewtrigger/it-IT.json +3 -0
- package/src/intl/previewtrigger/ja-JP.json +3 -0
- package/src/intl/previewtrigger/ko-KR.json +3 -0
- package/src/intl/previewtrigger/lt-LT.json +3 -0
- package/src/intl/previewtrigger/lv-LV.json +3 -0
- package/src/intl/previewtrigger/nb-NO.json +3 -0
- package/src/intl/previewtrigger/nl-NL.json +3 -0
- package/src/intl/previewtrigger/pl-PL.json +3 -0
- package/src/intl/previewtrigger/pt-BR.json +3 -0
- package/src/intl/previewtrigger/pt-PT.json +3 -0
- package/src/intl/previewtrigger/ro-RO.json +3 -0
- package/src/intl/previewtrigger/ru-RU.json +3 -0
- package/src/intl/previewtrigger/sk-SK.json +3 -0
- package/src/intl/previewtrigger/sl-SI.json +3 -0
- package/src/intl/previewtrigger/sr-SP.json +3 -0
- package/src/intl/previewtrigger/sv-SE.json +3 -0
- package/src/intl/previewtrigger/tr-TR.json +3 -0
- package/src/intl/previewtrigger/uk-UA.json +3 -0
- package/src/intl/previewtrigger/zh-CN.json +3 -0
- package/src/intl/previewtrigger/zh-TW.json +3 -0
- package/src/intl/table/ar-AE.json +3 -3
- package/src/intl/table/bg-BG.json +3 -3
- package/src/intl/table/cs-CZ.json +3 -3
- package/src/intl/table/da-DK.json +3 -3
- package/src/intl/table/de-DE.json +3 -3
- package/src/intl/table/el-GR.json +3 -3
- package/src/intl/table/es-ES.json +3 -3
- package/src/intl/table/et-EE.json +3 -3
- package/src/intl/table/fi-FI.json +3 -3
- package/src/intl/table/fr-FR.json +3 -3
- package/src/intl/table/he-IL.json +3 -3
- package/src/intl/table/hr-HR.json +3 -3
- package/src/intl/table/hu-HU.json +3 -3
- package/src/intl/table/it-IT.json +3 -3
- package/src/intl/table/ja-JP.json +3 -3
- package/src/intl/table/ko-KR.json +3 -3
- package/src/intl/table/lt-LT.json +3 -3
- package/src/intl/table/lv-LV.json +3 -3
- package/src/intl/table/nb-NO.json +3 -3
- package/src/intl/table/nl-NL.json +3 -3
- package/src/intl/table/pl-PL.json +3 -3
- package/src/intl/table/pt-BR.json +3 -3
- package/src/intl/table/pt-PT.json +3 -3
- package/src/intl/table/ro-RO.json +3 -3
- package/src/intl/table/ru-RU.json +3 -3
- package/src/intl/table/sk-SK.json +3 -3
- package/src/intl/table/sl-SI.json +3 -3
- package/src/intl/table/sr-SP.json +3 -3
- package/src/intl/table/sv-SE.json +3 -3
- package/src/intl/table/tr-TR.json +3 -3
- package/src/intl/table/uk-UA.json +3 -3
- package/src/intl/table/zh-CN.json +4 -4
- package/src/intl/table/zh-TW.json +3 -3
- package/src/intl/tree/es-ES.json +1 -1
- package/src/link/useLink.ts +2 -0
- package/src/menu/useMenuItem.ts +33 -36
- package/src/menu/useMenuTrigger.tsx +222 -0
- package/src/menu/{useSubmenuTrigger.ts → useSubmenuTrigger.tsx} +116 -151
- package/src/numberfield/{useNumberField.ts → useNumberField.tsx} +188 -238
- package/src/overlays/Overlay.ts +5 -1
- package/src/overlays/ariaHideOutside.ts +6 -8
- package/src/overlays/useCloseOnScroll.ts +7 -5
- package/src/overlays/{useOverlay.ts → useOverlay.tsx} +76 -83
- package/src/overlays/usePopover.ts +10 -5
- package/src/overlays/usePreventScroll.ts +4 -4
- package/src/progress/useProgressBar.ts +2 -1
- package/src/radio/{useRadioGroup.ts → useRadioGroup.tsx} +87 -79
- package/src/searchfield/useSearchField.tsx +152 -0
- package/src/select/useSelect.ts +20 -20
- package/src/selection/useSelectableCollection.tsx +755 -0
- package/src/selection/useSelectableItem.ts +48 -11
- package/src/slider/{useSliderThumb.ts → useSliderThumb.tsx} +120 -158
- package/src/spinbutton/useSpinButton.tsx +335 -0
- package/src/stately/combobox/useComboBoxState.ts +1 -1
- package/src/stately/grid/useGridState.ts +9 -10
- package/src/stately/index.ts +11 -0
- package/src/stately/menu/useMenuTriggerState.ts +1 -1
- package/src/stately/menu/useSubmenuTriggerState.ts +2 -0
- package/src/stately/overlays/useOverlayTriggerState.ts +12 -1
- package/src/stately/radio/useRadioGroupState.ts +5 -1
- package/src/stately/table/TableUtils.ts +15 -1
- package/src/stately/table/useTableState.ts +7 -0
- package/src/stately/tokenfield/TokenFieldValue.tsx +440 -0
- package/src/stately/tokenfield/useTokenFieldState.tsx +57 -0
- package/src/stately/tooltip/useTooltipTriggerState.ts +16 -7
- package/src/stately/virtualizer/Layout.tsx +2 -0
- package/src/stately/virtualizer/ScrollAnchor.tsx +338 -0
- package/src/stately/virtualizer/Virtualizer.tsx +52 -1
- package/src/stately/virtualizer/types.tsx +2 -0
- package/src/table/useTableCell.ts +12 -0
- package/src/table/useTableColumnHeader.ts +8 -1
- package/src/table/useTableColumnResize.tsx +359 -0
- package/src/tag/useTag.ts +22 -15
- package/src/textfield/useTextField.ts +2 -0
- package/src/tokenfield/useToken.tsx +64 -0
- package/src/tokenfield/useTokenField.tsx +849 -0
- package/src/tooltip/usePreviewTrigger.tsx +266 -0
- package/src/tooltip/useSafeArea.tsx +171 -0
- package/src/upstream-exports/react-aria/mergeRefs.tsx +3 -0
- package/src/upstream-exports/react-aria/usePreviewTrigger.tsx +18 -0
- package/src/upstream-exports/react-aria/useTokenField.tsx +22 -0
- package/src/upstream-exports/react-stately/private/collections/getChildNodes.tsx +8 -0
- package/src/upstream-exports/react-stately/private/collections/getItemCount.tsx +2 -0
- package/src/upstream-exports/react-stately/private/grid/GridCollection.tsx +7 -0
- package/src/upstream-exports/react-stately/private/grid/useGridState.tsx +6 -0
- package/src/upstream-exports/react-stately/private/utils/number.tsx +2 -0
- package/src/upstream-exports/react-stately/useComboBoxState.tsx +23 -0
- package/src/upstream-exports/react-stately/useListState.tsx +15 -0
- package/src/upstream-exports/react-stately/useMenuTriggerState.tsx +26 -0
- package/src/upstream-exports/react-stately/useMultipleSelectionState.tsx +21 -0
- package/src/upstream-exports/react-stately/useNumberFieldState.tsx +20 -0
- package/src/upstream-exports/react-stately/useOverlayTriggerState.tsx +20 -0
- package/src/upstream-exports/react-stately/useRadioGroupState.tsx +16 -0
- package/src/upstream-exports/react-stately/useSearchFieldState.tsx +19 -0
- package/src/upstream-exports/react-stately/useSliderState.tsx +20 -0
- package/src/upstream-exports/react-stately/useTableState.tsx +45 -0
- package/src/upstream-exports/react-stately/useTokenFieldState.tsx +25 -0
- package/src/upstream-exports/react-stately/useTooltipTriggerState.tsx +20 -0
- package/src/upstream-exports/react-stately/useTreeState.tsx +14 -0
- package/src/utils/domHelpers.ts +74 -17
- package/src/utils/isVirtualEvent.ts +2 -1
- package/src/utils/openLink.ts +8 -3
- package/src/utils/platform.ts +7 -3
- package/src/utils/scrollIntoView.ts +4 -4
- package/src/utils/shadowdom/DOMFunctions.ts +42 -2
- package/src/utils/useId.ts +11 -2
- package/src/utils/useLoadMoreSentinel.ts +8 -3
- package/src/utils/useViewportSize.ts +3 -3
- package/src/virtualizer/ScrollView.tsx +13 -4
- package/src/virtualizer/VirtualizerItem.tsx +4 -1
- package/src/virtualizer/useVirtualizerItem.tsx +43 -3
- package/src/menu/useMenuTrigger.ts +0 -189
- package/src/searchfield/useSearchField.ts +0 -156
- package/src/selection/useSelectableCollection.ts +0 -750
- package/src/spinbutton/useSpinButton.ts +0 -380
- package/src/table/useTableColumnResize.ts +0 -374
|
@@ -1,20 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
/** @jsxImportSource octane */
|
|
2
|
+
type DOMAttributes = Record<string, any>;
|
|
3
|
+
// Ported from adobe/react-spectrum@5ecb3333001313e83898cd07644227897e3bae1f (packages/react-aria/src/overlays/useOverlay.ts).
|
|
4
|
+
/*
|
|
5
|
+
* Copyright 2020 Adobe. All rights reserved.
|
|
6
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
8
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
11
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
12
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
13
|
+
* governing permissions and limitations under the License.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { RefObject } from '@react-types/shared';
|
|
17
|
+
import { withSlot } from 'octane';
|
|
7
18
|
import { getEventTarget } from '../utils/shadowdom/DOMFunctions';
|
|
8
19
|
import { isElementInChildOfActiveScope } from '../focus/FocusScope';
|
|
9
|
-
import { useEffect, useRef } from '
|
|
20
|
+
import { useEffect, useRef } from '../compat/react';
|
|
10
21
|
import { useFocusWithin } from '../interactions/useFocusWithin';
|
|
11
22
|
import { useInteractOutside } from '../interactions/useInteractOutside';
|
|
12
|
-
|
|
13
|
-
import { S, splitSlot, subSlot } from '../internal';
|
|
14
|
-
|
|
15
|
-
// octane adaptation: minimal structural DOMAttributes (upstream's drags React's synthetic
|
|
16
|
-
// handler types along).
|
|
17
|
-
type DOMAttributes = Record<string, any>;
|
|
23
|
+
import { useKeyboard } from '../interactions/useKeyboard';
|
|
18
24
|
|
|
19
25
|
export interface AriaOverlayProps {
|
|
20
26
|
/** Whether the overlay is currently open. */
|
|
@@ -63,18 +69,14 @@ const visibleOverlays: RefObject<Element | null>[] = [];
|
|
|
63
69
|
* Hides the overlay when the user interacts outside it, when the Escape key is pressed,
|
|
64
70
|
* or optionally, on blur. Only the top-most overlay will close at once.
|
|
65
71
|
*/
|
|
66
|
-
export function useOverlay(props: AriaOverlayProps, ref: RefObject<Element | null>): OverlayAria;
|
|
67
|
-
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
68
72
|
export function useOverlay(
|
|
69
73
|
props: AriaOverlayProps,
|
|
70
74
|
ref: RefObject<Element | null>,
|
|
71
|
-
|
|
72
|
-
): OverlayAria
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const props = user[0] as AriaOverlayProps;
|
|
77
|
-
const ref = user[1] as RefObject<Element | null>;
|
|
75
|
+
_slot?: symbol,
|
|
76
|
+
): OverlayAria {
|
|
77
|
+
if (_slot !== undefined) {
|
|
78
|
+
return withSlot(_slot, useOverlay, props, ref);
|
|
79
|
+
}
|
|
78
80
|
|
|
79
81
|
let {
|
|
80
82
|
onClose,
|
|
@@ -85,27 +87,20 @@ export function useOverlay(...args: any[]): OverlayAria {
|
|
|
85
87
|
shouldCloseOnInteractOutside,
|
|
86
88
|
} = props;
|
|
87
89
|
|
|
88
|
-
let lastVisibleOverlay = useRef<RefObject<Element | null> | undefined>(
|
|
89
|
-
undefined,
|
|
90
|
-
subSlot(slot, 'lastVisible'),
|
|
91
|
-
);
|
|
90
|
+
let lastVisibleOverlay = useRef<RefObject<Element | null> | undefined>(undefined);
|
|
92
91
|
|
|
93
92
|
// Add the overlay ref to the stack of visible overlays on mount, and remove on unmount.
|
|
94
|
-
useEffect(
|
|
95
|
-
()
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
},
|
|
106
|
-
[isOpen, ref],
|
|
107
|
-
subSlot(slot, 'stack'),
|
|
108
|
-
);
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
if (isOpen && !visibleOverlays.includes(ref)) {
|
|
95
|
+
visibleOverlays.push(ref);
|
|
96
|
+
return () => {
|
|
97
|
+
let index = visibleOverlays.indexOf(ref);
|
|
98
|
+
if (index >= 0) {
|
|
99
|
+
visibleOverlays.splice(index, 1);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}, [isOpen, ref]);
|
|
109
104
|
|
|
110
105
|
// Only hide the overlay when it is the topmost visible overlay in the stack
|
|
111
106
|
let onHide = () => {
|
|
@@ -143,55 +138,53 @@ export function useOverlay(...args: any[]): OverlayAria {
|
|
|
143
138
|
};
|
|
144
139
|
|
|
145
140
|
// Handle the escape key
|
|
146
|
-
let
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
// Handle clicking outside the overlay to close it
|
|
155
|
-
useInteractOutside(
|
|
156
|
-
{
|
|
157
|
-
ref,
|
|
158
|
-
onInteractOutside: isDismissable && isOpen ? onInteractOutside : undefined,
|
|
159
|
-
onInteractOutsideStart,
|
|
160
|
-
},
|
|
161
|
-
subSlot(slot, 'interactOutside'),
|
|
162
|
-
);
|
|
163
|
-
|
|
164
|
-
let { focusWithinProps } = useFocusWithin(
|
|
165
|
-
{
|
|
166
|
-
isDisabled: !shouldCloseOnBlur,
|
|
167
|
-
onBlurWithin: (e) => {
|
|
168
|
-
// Do not close if relatedTarget is null, which means focus is lost to the body.
|
|
169
|
-
// That can happen when switching tabs, or due to a VoiceOver/Chrome bug with Control+Option+Arrow navigation.
|
|
170
|
-
// Clicking on the body to close the overlay should already be handled by useInteractOutside.
|
|
171
|
-
// https://github.com/adobe/react-spectrum/issues/4130
|
|
172
|
-
// https://github.com/adobe/react-spectrum/issues/4922
|
|
173
|
-
//
|
|
174
|
-
// If focus is moving into a child focus scope (e.g. menu inside a dialog),
|
|
175
|
-
// do not close the outer overlay. At this point, the active scope should
|
|
176
|
-
// still be the outer overlay, since blur events run before focus.
|
|
177
|
-
if (!e.relatedTarget || isElementInChildOfActiveScope(e.relatedTarget as Element)) {
|
|
141
|
+
let { keyboardProps } = useKeyboard({
|
|
142
|
+
shortcuts: {
|
|
143
|
+
Escape: () => {
|
|
144
|
+
if (!isKeyboardDismissDisabled) {
|
|
145
|
+
onHide();
|
|
178
146
|
return;
|
|
179
147
|
}
|
|
180
|
-
|
|
181
|
-
if (
|
|
182
|
-
!shouldCloseOnInteractOutside ||
|
|
183
|
-
shouldCloseOnInteractOutside(e.relatedTarget as Element)
|
|
184
|
-
) {
|
|
185
|
-
onClose?.();
|
|
186
|
-
}
|
|
148
|
+
return false;
|
|
187
149
|
},
|
|
188
150
|
},
|
|
189
|
-
|
|
190
|
-
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// Handle clicking outside the overlay to close it
|
|
154
|
+
useInteractOutside({
|
|
155
|
+
ref,
|
|
156
|
+
onInteractOutside: isDismissable && isOpen ? onInteractOutside : undefined,
|
|
157
|
+
onInteractOutsideStart,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
let { focusWithinProps } = useFocusWithin({
|
|
161
|
+
isDisabled: !shouldCloseOnBlur,
|
|
162
|
+
onBlurWithin: (e) => {
|
|
163
|
+
// Do not close if relatedTarget is null, which means focus is lost to the body.
|
|
164
|
+
// That can happen when switching tabs, or due to a VoiceOver/Chrome bug with Control+Option+Arrow navigation.
|
|
165
|
+
// Clicking on the body to close the overlay should already be handled by useInteractOutside.
|
|
166
|
+
// https://github.com/adobe/react-spectrum/issues/4130
|
|
167
|
+
// https://github.com/adobe/react-spectrum/issues/4922
|
|
168
|
+
//
|
|
169
|
+
// If focus is moving into a child focus scope (e.g. menu inside a dialog),
|
|
170
|
+
// do not close the outer overlay. At this point, the active scope should
|
|
171
|
+
// still be the outer overlay, since blur events run before focus.
|
|
172
|
+
if (!e.relatedTarget || isElementInChildOfActiveScope(e.relatedTarget as Element)) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (
|
|
177
|
+
!shouldCloseOnInteractOutside ||
|
|
178
|
+
shouldCloseOnInteractOutside(e.relatedTarget as Element)
|
|
179
|
+
) {
|
|
180
|
+
onClose?.();
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
});
|
|
191
184
|
|
|
192
185
|
return {
|
|
193
186
|
overlayProps: {
|
|
194
|
-
|
|
187
|
+
...keyboardProps,
|
|
195
188
|
...focusWithinProps,
|
|
196
189
|
},
|
|
197
190
|
underlayProps: {},
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { ariaHideOutside, keepVisible } from './ariaHideOutside';
|
|
8
8
|
import { AriaPositionProps, PlacementAxis, useOverlayPosition } from './useOverlayPosition';
|
|
9
9
|
import type { RefObject } from '@react-types/shared';
|
|
10
|
+
import { FocusWithinProps, useFocusWithin } from '../interactions/useFocusWithin';
|
|
10
11
|
import { mergeProps } from '../utils/mergeProps';
|
|
11
12
|
import type { OverlayTriggerState } from '../stately/overlays/useOverlayTriggerState';
|
|
12
13
|
import { useEffect } from 'octane';
|
|
@@ -19,10 +20,10 @@ import { S, splitSlot, subSlot } from '../internal';
|
|
|
19
20
|
// handler types along).
|
|
20
21
|
type DOMAttributes = Record<string, any>;
|
|
21
22
|
|
|
22
|
-
export interface AriaPopoverProps
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
> {
|
|
23
|
+
export interface AriaPopoverProps
|
|
24
|
+
extends
|
|
25
|
+
Omit<AriaPositionProps, 'isOpen' | 'onClose' | 'targetRef' | 'overlayRef'>,
|
|
26
|
+
Omit<FocusWithinProps, 'isDisabled'> {
|
|
26
27
|
/**
|
|
27
28
|
* The ref for the element which the popover positions itself with respect to.
|
|
28
29
|
*/
|
|
@@ -133,6 +134,9 @@ export function usePopover(...args: any[]): PopoverAria {
|
|
|
133
134
|
overlayRef: popoverRef,
|
|
134
135
|
isOpen: state.isOpen,
|
|
135
136
|
onClose: isNonModal && !isSubmenu ? state.close : null,
|
|
137
|
+
getTargetRect:
|
|
138
|
+
otherProps.getTargetRect ??
|
|
139
|
+
(state.point ? () => new DOMRect(state.point!.x, state.point!.y, 0, 0) : undefined),
|
|
136
140
|
},
|
|
137
141
|
subSlot(slot, 'position'),
|
|
138
142
|
);
|
|
@@ -160,8 +164,9 @@ export function usePopover(...args: any[]): PopoverAria {
|
|
|
160
164
|
subSlot(slot, 'hideOutside'),
|
|
161
165
|
);
|
|
162
166
|
|
|
167
|
+
let { focusWithinProps } = useFocusWithin(props, subSlot(slot, 'focusWithin'));
|
|
163
168
|
return {
|
|
164
|
-
popoverProps: mergeProps(overlayProps, positionProps),
|
|
169
|
+
popoverProps: mergeProps(overlayProps, positionProps, focusWithinProps),
|
|
165
170
|
arrowProps,
|
|
166
171
|
underlayProps,
|
|
167
172
|
placement,
|
|
@@ -8,7 +8,7 @@ import { chain } from '../utils/chain';
|
|
|
8
8
|
import { getActiveElement, getEventTarget } from '../utils/shadowdom/DOMFunctions';
|
|
9
9
|
import { getNonce } from '../utils/getNonce';
|
|
10
10
|
import { getScrollParent } from '../utils/getScrollParent';
|
|
11
|
-
import { isIOS } from '../utils/platform';
|
|
11
|
+
import { isIOS, isWebKit } from '../utils/platform';
|
|
12
12
|
import { isScrollable } from '../utils/isScrollable';
|
|
13
13
|
import { useLayoutEffect } from '../utils/useLayoutEffect';
|
|
14
14
|
import { willOpenKeyboard } from '../utils/keyboard';
|
|
@@ -52,8 +52,8 @@ export function usePreventScroll(...args: any[]): void {
|
|
|
52
52
|
|
|
53
53
|
preventScrollCount++;
|
|
54
54
|
if (preventScrollCount === 1) {
|
|
55
|
-
if (isIOS()) {
|
|
56
|
-
restore =
|
|
55
|
+
if (isIOS() && isWebKit()) {
|
|
56
|
+
restore = preventScrollMobileWebKit();
|
|
57
57
|
} else {
|
|
58
58
|
restore = preventScrollStandard();
|
|
59
59
|
}
|
|
@@ -108,7 +108,7 @@ function preventScrollStandard() {
|
|
|
108
108
|
// 4. When focus moves to an input, create an off screen input and focus that temporarily. This prevents
|
|
109
109
|
// Safari from scrolling the page. After a small delay, focus the real input and scroll it into view
|
|
110
110
|
// ourselves, without scrolling the whole page.
|
|
111
|
-
function
|
|
111
|
+
function preventScrollMobileWebKit() {
|
|
112
112
|
// Set overflow hidden so scrollIntoViewport() (useSelectableCollection) sees isScrollPrevented and
|
|
113
113
|
// scrolls only scroll parents instead of calling native scrollIntoView() which moves the window.
|
|
114
114
|
let restoreOverflow = setStyle(document.documentElement, 'overflow', 'hidden');
|
|
@@ -93,7 +93,8 @@ export function useProgressBar(...args: any[]): ProgressBarAria {
|
|
|
93
93
|
);
|
|
94
94
|
|
|
95
95
|
value = clamp(value, minValue, maxValue);
|
|
96
|
-
let
|
|
96
|
+
let range = maxValue - minValue;
|
|
97
|
+
let percentage = range === 0 ? 0 : (value - minValue) / range;
|
|
97
98
|
let formatter = useNumberFormatter(formatOptions, subSlot(slot, 'formatter'));
|
|
98
99
|
|
|
99
100
|
if (!isIndeterminate && !valueLabel) {
|
|
@@ -1,29 +1,40 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
//
|
|
4
|
-
|
|
1
|
+
/** @jsxImportSource octane */
|
|
2
|
+
type DOMAttributes = Record<string, any>;
|
|
3
|
+
// Ported from adobe/react-spectrum@5ecb3333001313e83898cd07644227897e3bae1f (packages/react-aria/src/radio/useRadioGroup.ts).
|
|
4
|
+
/*
|
|
5
|
+
* Copyright 2020 Adobe. All rights reserved.
|
|
6
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
8
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
11
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
12
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
13
|
+
* governing permissions and limitations under the License.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import {
|
|
5
17
|
AriaLabelingProps,
|
|
6
18
|
AriaValidationProps,
|
|
7
19
|
DOMProps,
|
|
8
20
|
InputDOMProps,
|
|
9
21
|
ValidationResult,
|
|
10
22
|
} from '@react-types/shared';
|
|
11
|
-
|
|
12
|
-
// octane adaptation: structural prop bag (upstream's DOMAttributes drags React handler
|
|
13
|
-
// types; the keyboard handler here is a native KeyboardEvent handler).
|
|
14
|
-
type DOMAttributes = Record<string, any>;
|
|
15
|
-
|
|
16
|
-
import { S, splitSlot, subSlot } from '../internal';
|
|
23
|
+
import { withSlot } from 'octane';
|
|
17
24
|
import { filterDOMProps } from '../utils/filterDOMProps';
|
|
18
25
|
import { getEventTarget } from '../utils/shadowdom/DOMFunctions';
|
|
19
26
|
import { getFocusableTreeWalker } from '../focus/FocusScope';
|
|
20
27
|
import { getOwnerWindow } from '../utils/domHelpers';
|
|
21
28
|
import { mergeProps } from '../utils/mergeProps';
|
|
22
29
|
import { radioGroupData } from './utils';
|
|
23
|
-
import
|
|
30
|
+
import {
|
|
31
|
+
RadioGroupProps,
|
|
32
|
+
RadioGroupState,
|
|
33
|
+
} from '../upstream-exports/react-stately/useRadioGroupState';
|
|
24
34
|
import { useField } from '../label/useField';
|
|
25
35
|
import { useFocusWithin } from '../interactions/useFocusWithin';
|
|
26
36
|
import { useId } from '../utils/useId';
|
|
37
|
+
import { useKeyboard } from '../interactions/useKeyboard';
|
|
27
38
|
import { useLocale } from '../i18n/I18nProvider';
|
|
28
39
|
|
|
29
40
|
export interface AriaRadioGroupProps
|
|
@@ -40,18 +51,21 @@ export interface RadioGroupAria extends ValidationResult {
|
|
|
40
51
|
errorMessageProps: DOMAttributes;
|
|
41
52
|
}
|
|
42
53
|
|
|
43
|
-
|
|
44
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Provides the behavior and accessibility implementation for a radio group component.
|
|
56
|
+
* Radio groups allow users to select a single item from a list of mutually exclusive options.
|
|
57
|
+
*
|
|
58
|
+
* @param props - Props for the radio group.
|
|
59
|
+
* @param state - State for the radio group, as returned by `useRadioGroupState`.
|
|
60
|
+
*/
|
|
45
61
|
export function useRadioGroup(
|
|
46
62
|
props: AriaRadioGroupProps,
|
|
47
63
|
state: RadioGroupState,
|
|
48
|
-
|
|
49
|
-
): RadioGroupAria
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const props = user[0] as AriaRadioGroupProps;
|
|
54
|
-
const state = user[1] as RadioGroupState;
|
|
64
|
+
_slot?: symbol,
|
|
65
|
+
): RadioGroupAria {
|
|
66
|
+
if (_slot !== undefined) {
|
|
67
|
+
return withSlot(_slot, useRadioGroup, props, state);
|
|
68
|
+
}
|
|
55
69
|
|
|
56
70
|
let {
|
|
57
71
|
name,
|
|
@@ -62,72 +76,42 @@ export function useRadioGroup(...args: any[]): RadioGroupAria {
|
|
|
62
76
|
orientation = 'vertical',
|
|
63
77
|
validationBehavior = 'aria',
|
|
64
78
|
} = props;
|
|
65
|
-
let { direction } = useLocale(
|
|
79
|
+
let { direction } = useLocale();
|
|
66
80
|
|
|
67
81
|
let { isInvalid, validationErrors, validationDetails } = state.displayValidation;
|
|
68
|
-
let { labelProps, fieldProps, descriptionProps, errorMessageProps } = useField(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
},
|
|
77
|
-
subSlot(slot, 'field'),
|
|
78
|
-
);
|
|
82
|
+
let { labelProps, fieldProps, descriptionProps, errorMessageProps } = useField({
|
|
83
|
+
...props,
|
|
84
|
+
// Radio group is not an HTML input element so it
|
|
85
|
+
// shouldn't be labeled by a <label> element.
|
|
86
|
+
labelElementType: 'span',
|
|
87
|
+
isInvalid: state.isInvalid,
|
|
88
|
+
errorMessage: props.errorMessage || validationErrors,
|
|
89
|
+
});
|
|
79
90
|
|
|
80
91
|
let domProps = filterDOMProps(props, { labelable: true });
|
|
81
92
|
|
|
82
93
|
// When the radio group loses focus, reset the focusable radio to null if
|
|
83
94
|
// there is no selection. This allows tabbing into the group from either
|
|
84
95
|
// direction to go to the first or last radio.
|
|
85
|
-
let { focusWithinProps } = useFocusWithin(
|
|
86
|
-
{
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
onFocusWithin: (props as any).onFocus,
|
|
94
|
-
onFocusWithinChange: (props as any).onFocusChange,
|
|
96
|
+
let { focusWithinProps } = useFocusWithin({
|
|
97
|
+
onBlurWithin(e) {
|
|
98
|
+
props.onBlur?.(e);
|
|
99
|
+
if (!state.selectedValue) {
|
|
100
|
+
state.setLastFocusedValue(null);
|
|
101
|
+
}
|
|
95
102
|
},
|
|
96
|
-
|
|
97
|
-
|
|
103
|
+
onFocusWithin: props.onFocus,
|
|
104
|
+
onFocusWithinChange: props.onFocusChange,
|
|
105
|
+
});
|
|
98
106
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (direction === 'rtl' && orientation !== 'vertical') {
|
|
104
|
-
nextDir = 'prev';
|
|
105
|
-
} else {
|
|
106
|
-
nextDir = 'next';
|
|
107
|
-
}
|
|
108
|
-
break;
|
|
109
|
-
case 'ArrowLeft':
|
|
110
|
-
if (direction === 'rtl' && orientation !== 'vertical') {
|
|
111
|
-
nextDir = 'next';
|
|
112
|
-
} else {
|
|
113
|
-
nextDir = 'prev';
|
|
114
|
-
}
|
|
115
|
-
break;
|
|
116
|
-
case 'ArrowDown':
|
|
117
|
-
nextDir = 'next';
|
|
118
|
-
break;
|
|
119
|
-
case 'ArrowUp':
|
|
120
|
-
nextDir = 'prev';
|
|
121
|
-
break;
|
|
122
|
-
default:
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
e.preventDefault();
|
|
107
|
+
function getNextElement(
|
|
108
|
+
nextDir: 'next' | 'prev',
|
|
109
|
+
e: import('../interactions/createEventHandler').BaseEvent<KeyboardEvent>,
|
|
110
|
+
) {
|
|
126
111
|
let walker = getFocusableTreeWalker(e.currentTarget as Element, {
|
|
127
112
|
from: getEventTarget(e) as Element,
|
|
128
|
-
accept: (node
|
|
129
|
-
node instanceof getOwnerWindow(node).HTMLInputElement &&
|
|
130
|
-
(node as HTMLInputElement).type === 'radio',
|
|
113
|
+
accept: (node) =>
|
|
114
|
+
node instanceof getOwnerWindow(node).HTMLInputElement && node.type === 'radio',
|
|
131
115
|
});
|
|
132
116
|
let nextElem;
|
|
133
117
|
if (nextDir === 'next') {
|
|
@@ -148,15 +132,39 @@ export function useRadioGroup(...args: any[]): RadioGroupAria {
|
|
|
148
132
|
// Call focus on nextElem so that keyboard navigation scrolls the radio into view
|
|
149
133
|
(nextElem as HTMLInputElement).focus();
|
|
150
134
|
state.setSelectedValue((nextElem as HTMLInputElement).value);
|
|
135
|
+
return true;
|
|
151
136
|
}
|
|
152
|
-
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
let { keyboardProps } = useKeyboard({
|
|
141
|
+
shortcuts: {
|
|
142
|
+
ArrowRight: (e) => {
|
|
143
|
+
let nextDir: 'next' | 'prev' =
|
|
144
|
+
direction === 'rtl' && orientation !== 'vertical' ? 'prev' : 'next';
|
|
145
|
+
return getNextElement(nextDir, e);
|
|
146
|
+
},
|
|
147
|
+
ArrowLeft: (e) => {
|
|
148
|
+
let nextDir: 'next' | 'prev' =
|
|
149
|
+
direction === 'rtl' && orientation !== 'vertical' ? 'next' : 'prev';
|
|
150
|
+
return getNextElement(nextDir, e);
|
|
151
|
+
},
|
|
152
|
+
ArrowDown: (e) => {
|
|
153
|
+
return getNextElement('next', e);
|
|
154
|
+
},
|
|
155
|
+
ArrowUp: (e) => {
|
|
156
|
+
return getNextElement('prev', e);
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
allowRepeats: true,
|
|
160
|
+
});
|
|
153
161
|
|
|
154
|
-
let groupName = useId(name
|
|
162
|
+
let groupName = useId(name);
|
|
155
163
|
radioGroupData.set(state, {
|
|
156
164
|
name: groupName,
|
|
157
165
|
form,
|
|
158
|
-
descriptionId:
|
|
159
|
-
errorMessageId:
|
|
166
|
+
descriptionId: descriptionProps.id,
|
|
167
|
+
errorMessageId: errorMessageProps.id,
|
|
160
168
|
validationBehavior,
|
|
161
169
|
});
|
|
162
170
|
|
|
@@ -164,7 +172,7 @@ export function useRadioGroup(...args: any[]): RadioGroupAria {
|
|
|
164
172
|
radioGroupProps: mergeProps(domProps, {
|
|
165
173
|
// https://www.w3.org/TR/wai-aria-1.2/#radiogroup
|
|
166
174
|
role: 'radiogroup',
|
|
167
|
-
|
|
175
|
+
...keyboardProps,
|
|
168
176
|
'aria-invalid': state.isInvalid || undefined,
|
|
169
177
|
'aria-errormessage': props['aria-errormessage'],
|
|
170
178
|
'aria-readonly': isReadOnly || undefined,
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/** @jsxImportSource octane */
|
|
2
|
+
type DOMAttributes = Record<string, any>;
|
|
3
|
+
// Ported from adobe/react-spectrum@5ecb3333001313e83898cd07644227897e3bae1f (packages/react-aria/src/searchfield/useSearchField.ts).
|
|
4
|
+
/*
|
|
5
|
+
* Copyright 2020 Adobe. All rights reserved.
|
|
6
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
8
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
11
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
12
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
13
|
+
* governing permissions and limitations under the License.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { AriaButtonProps } from '../button/useButton';
|
|
17
|
+
import { withSlot } from 'octane';
|
|
18
|
+
import { AriaTextFieldProps, useTextField } from '../textfield/useTextField';
|
|
19
|
+
import { RefObject, ValidationResult } from '@react-types/shared';
|
|
20
|
+
import { InputHTMLAttributes, LabelHTMLAttributes } from '../compat/react';
|
|
21
|
+
import intlMessages from '../intl/searchfield/index';
|
|
22
|
+
// @ts-ignore
|
|
23
|
+
import { mergeProps } from '../utils/mergeProps';
|
|
24
|
+
import {
|
|
25
|
+
SearchFieldProps,
|
|
26
|
+
SearchFieldState,
|
|
27
|
+
} from '../upstream-exports/react-stately/useSearchFieldState';
|
|
28
|
+
import { useKeyboard } from '../interactions/useKeyboard';
|
|
29
|
+
import { useLocalizedStringFormatter } from '../i18n/useLocalizedStringFormatter';
|
|
30
|
+
|
|
31
|
+
export interface AriaSearchFieldProps extends SearchFieldProps, Omit<AriaTextFieldProps, 'type'> {
|
|
32
|
+
/**
|
|
33
|
+
* An enumerated attribute that defines what action label or icon to preset for the enter key on
|
|
34
|
+
* virtual keyboards. See
|
|
35
|
+
* [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/enterkeyhint).
|
|
36
|
+
*/
|
|
37
|
+
enterKeyHint?: 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send';
|
|
38
|
+
/**
|
|
39
|
+
* The type of input to render. See
|
|
40
|
+
* [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdeftype).
|
|
41
|
+
*
|
|
42
|
+
* @default 'search'
|
|
43
|
+
*/
|
|
44
|
+
type?: 'text' | 'search' | 'url' | 'tel' | 'email' | 'password' | (string & {});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface SearchFieldAria extends ValidationResult {
|
|
48
|
+
/** Props for the text field's visible label element (if any). */
|
|
49
|
+
labelProps: LabelHTMLAttributes<HTMLLabelElement>;
|
|
50
|
+
/** Props for the input element. */
|
|
51
|
+
inputProps: InputHTMLAttributes<HTMLInputElement>;
|
|
52
|
+
/** Props for the clear button. */
|
|
53
|
+
clearButtonProps: AriaButtonProps;
|
|
54
|
+
/** Props for the searchfield's description element, if any. */
|
|
55
|
+
descriptionProps: DOMAttributes;
|
|
56
|
+
/** Props for the searchfield's error message element, if any. */
|
|
57
|
+
errorMessageProps: DOMAttributes;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Provides the behavior and accessibility implementation for a search field.
|
|
62
|
+
*
|
|
63
|
+
* @param props - Props for the search field.
|
|
64
|
+
* @param state - State for the search field, as returned by `useSearchFieldState`.
|
|
65
|
+
* @param inputRef - A ref to the input element.
|
|
66
|
+
*/
|
|
67
|
+
export function useSearchField(
|
|
68
|
+
props: AriaSearchFieldProps,
|
|
69
|
+
state: SearchFieldState,
|
|
70
|
+
inputRef: RefObject<HTMLInputElement | null>,
|
|
71
|
+
_slot?: symbol,
|
|
72
|
+
): SearchFieldAria {
|
|
73
|
+
if (_slot !== undefined) {
|
|
74
|
+
return withSlot(_slot, useSearchField, props, state, inputRef);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-aria/searchfield');
|
|
78
|
+
let { isDisabled, isReadOnly, onSubmit, onClear, type = 'search' } = props;
|
|
79
|
+
|
|
80
|
+
let { keyboardProps } = useKeyboard({
|
|
81
|
+
isDisabled: isDisabled || isReadOnly,
|
|
82
|
+
shortcuts: {
|
|
83
|
+
Enter: () => {
|
|
84
|
+
if (onSubmit) {
|
|
85
|
+
// for backward compatibility;
|
|
86
|
+
// otherwise, "Enter" on an input would trigger a form submit, the default browser behavior
|
|
87
|
+
onSubmit(state.value);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
},
|
|
92
|
+
Escape: () => {
|
|
93
|
+
// Also check the inputRef value for the case where the value was set directly on the input element instead of going through
|
|
94
|
+
// the hook
|
|
95
|
+
if (state.value === '' && (!inputRef.current || inputRef.current.value === '')) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
state.setValue('');
|
|
99
|
+
onClear?.();
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
let onClearButtonClick = () => {
|
|
105
|
+
state.setValue('');
|
|
106
|
+
|
|
107
|
+
if (onClear) {
|
|
108
|
+
onClear();
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
let onPressStart = () => {
|
|
113
|
+
// this is in PressStart for mobile so that touching the clear button doesn't remove focus from
|
|
114
|
+
// the input and close the keyboard
|
|
115
|
+
inputRef.current?.focus();
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
let { labelProps, inputProps, descriptionProps, errorMessageProps, ...validation } = useTextField(
|
|
119
|
+
{
|
|
120
|
+
...props,
|
|
121
|
+
value: state.value,
|
|
122
|
+
onChange: state.setValue,
|
|
123
|
+
onKeyDown: props.onKeyDown,
|
|
124
|
+
onKeyUp: props.onKeyUp,
|
|
125
|
+
type,
|
|
126
|
+
},
|
|
127
|
+
inputRef,
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
labelProps,
|
|
132
|
+
// An edge case, in Autocomplete, if the keyboard hanlders are not in this order, then
|
|
133
|
+
// Escape runs autocomplete/listbox first, then the search-field shortcut returns false and
|
|
134
|
+
// continues propagation, leaking Escape to a parent Dialog.
|
|
135
|
+
inputProps: mergeProps(keyboardProps, {
|
|
136
|
+
...inputProps,
|
|
137
|
+
// already handled by useSearchFieldState
|
|
138
|
+
defaultValue: undefined,
|
|
139
|
+
}),
|
|
140
|
+
clearButtonProps: {
|
|
141
|
+
'aria-label': stringFormatter.format('Clear search'),
|
|
142
|
+
excludeFromTabOrder: true,
|
|
143
|
+
preventFocusOnPress: true,
|
|
144
|
+
isDisabled: isDisabled || isReadOnly,
|
|
145
|
+
onPress: onClearButtonClick,
|
|
146
|
+
onPressStart,
|
|
147
|
+
},
|
|
148
|
+
descriptionProps,
|
|
149
|
+
errorMessageProps,
|
|
150
|
+
...validation,
|
|
151
|
+
};
|
|
152
|
+
}
|