react-aria-components 1.0.0-beta.0 → 1.0.0-beta.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.
- package/dist/import.mjs +1160 -855
- package/dist/main.js +1181 -852
- package/dist/main.js.map +1 -1
- package/dist/module.js +1160 -855
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +180 -226
- package/dist/types.d.ts.map +1 -1
- package/package.json +12 -12
- package/src/Breadcrumbs.tsx +2 -2
- package/src/Button.tsx +1 -1
- package/src/Calendar.tsx +15 -8
- package/src/Checkbox.tsx +5 -5
- package/src/Collection.tsx +14 -7
- package/src/ComboBox.tsx +19 -12
- package/src/DateField.tsx +95 -49
- package/src/DatePicker.tsx +34 -64
- package/src/Dialog.tsx +15 -15
- package/src/DropZone.tsx +6 -3
- package/src/FileTrigger.tsx +11 -10
- package/src/GridList.tsx +9 -13
- package/src/Group.tsx +36 -6
- package/src/Link.tsx +17 -24
- package/src/ListBox.tsx +31 -39
- package/src/Menu.tsx +17 -15
- package/src/Meter.tsx +1 -1
- package/src/Modal.tsx +14 -13
- package/src/NumberField.tsx +5 -3
- package/src/OverlayArrow.tsx +7 -10
- package/src/Popover.tsx +7 -11
- package/src/ProgressBar.tsx +1 -1
- package/src/RadioGroup.tsx +6 -6
- package/src/SearchField.tsx +3 -3
- package/src/Select.tsx +28 -23
- package/src/Separator.tsx +1 -1
- package/src/Slider.tsx +24 -23
- package/src/Switch.tsx +3 -3
- package/src/Table.tsx +30 -30
- package/src/Tabs.tsx +24 -31
- package/src/TagGroup.tsx +18 -21
- package/src/TextField.tsx +3 -3
- package/src/ToggleButton.tsx +1 -1
- package/src/Tooltip.tsx +33 -27
- package/src/index.ts +18 -18
- package/src/useDragAndDrop.tsx +8 -0
- package/src/utils.tsx +37 -10
package/src/GridList.tsx
CHANGED
|
@@ -15,8 +15,9 @@ import {CheckboxContext} from './Checkbox';
|
|
|
15
15
|
import {Collection, DraggableCollectionState, DroppableCollectionState, ListState, Node, SelectionBehavior, useListState} from 'react-stately';
|
|
16
16
|
import {CollectionProps, ItemProps, useCachedChildren, useCollection} from './Collection';
|
|
17
17
|
import {ContextValue, defaultSlot, forwardRefType, Provider, SlotProps, StyleRenderProps, useContextProps, useRenderProps} from './utils';
|
|
18
|
-
import {DragAndDropHooks, DropIndicator, DropIndicatorContext, DropIndicatorProps} from './useDragAndDrop';
|
|
18
|
+
import {DragAndDropContext, DragAndDropHooks, DropIndicator, DropIndicatorContext, DropIndicatorProps} from './useDragAndDrop';
|
|
19
19
|
import {filterDOMProps, isIOS, isWebKit, useObjectRef} from '@react-aria/utils';
|
|
20
|
+
import {ListStateContext} from './ListBox';
|
|
20
21
|
import React, {createContext, ForwardedRef, forwardRef, HTMLAttributes, ReactNode, RefObject, useContext, useEffect, useRef} from 'react';
|
|
21
22
|
import {TextContext} from './Text';
|
|
22
23
|
|
|
@@ -56,15 +57,8 @@ export interface GridListProps<T> extends Omit<AriaGridListProps<T>, 'children'>
|
|
|
56
57
|
renderEmptyState?: () => ReactNode
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
interface InternalGridListContextValue {
|
|
60
|
-
state: ListState<unknown>,
|
|
61
|
-
dragAndDropHooks?: DragAndDropHooks,
|
|
62
|
-
dragState?: DraggableCollectionState,
|
|
63
|
-
dropState?: DroppableCollectionState
|
|
64
|
-
}
|
|
65
60
|
|
|
66
61
|
export const GridListContext = createContext<ContextValue<GridListProps<any>, HTMLDivElement>>(null);
|
|
67
|
-
const InternalGridListContext = createContext<InternalGridListContextValue | null>(null);
|
|
68
62
|
|
|
69
63
|
function GridList<T extends object>(props: GridListProps<T>, ref: ForwardedRef<HTMLDivElement>) {
|
|
70
64
|
// Render the portal first so that we have the collection by the time we render the DOM in SSR.
|
|
@@ -220,14 +214,15 @@ function GridListInner<T extends object>({props, collection, gridListRef: ref}:
|
|
|
220
214
|
{...renderProps}
|
|
221
215
|
{...mergeProps(gridProps, focusProps, droppableCollection?.collectionProps, emptyStatePropOverrides)}
|
|
222
216
|
ref={ref}
|
|
223
|
-
slot={props.slot}
|
|
217
|
+
slot={props.slot || undefined}
|
|
224
218
|
data-drop-target={isRootDropTarget || undefined}
|
|
225
219
|
data-empty={state.collection.size === 0 || undefined}
|
|
226
220
|
data-focused={isFocused || undefined}
|
|
227
221
|
data-focus-visible={isFocusVisible || undefined}>
|
|
228
222
|
<Provider
|
|
229
223
|
values={[
|
|
230
|
-
[
|
|
224
|
+
[ListStateContext, state],
|
|
225
|
+
[DragAndDropContext, {dragAndDropHooks, dragState, dropState}],
|
|
231
226
|
[DropIndicatorContext, {render: GridListDropIndicatorWrapper}]
|
|
232
227
|
]}>
|
|
233
228
|
{isListDroppable && <RootDropIndicator />}
|
|
@@ -248,7 +243,8 @@ const _GridList = /*#__PURE__*/ (forwardRef as forwardRefType)(GridList);
|
|
|
248
243
|
export {_GridList as GridList};
|
|
249
244
|
|
|
250
245
|
function GridListItem({item}) {
|
|
251
|
-
let
|
|
246
|
+
let state = useContext(ListStateContext)!;
|
|
247
|
+
let {dragAndDropHooks, dragState, dropState} = useContext(DragAndDropContext);
|
|
252
248
|
let ref = useObjectRef<HTMLDivElement>(item.props.ref);
|
|
253
249
|
let {rowProps, gridCellProps, descriptionProps, ...states} = useGridListItem(
|
|
254
250
|
{
|
|
@@ -382,7 +378,7 @@ function GridListItem({item}) {
|
|
|
382
378
|
|
|
383
379
|
function GridListDropIndicatorWrapper(props: DropIndicatorProps, ref: ForwardedRef<HTMLElement>) {
|
|
384
380
|
ref = useObjectRef(ref);
|
|
385
|
-
let {dragAndDropHooks, dropState} = useContext(
|
|
381
|
+
let {dragAndDropHooks, dropState} = useContext(DragAndDropContext);
|
|
386
382
|
let buttonRef = useRef<HTMLDivElement>(null);
|
|
387
383
|
let {dropIndicatorProps, isHidden, isDropTarget} = dragAndDropHooks!.useDropIndicator!(
|
|
388
384
|
props,
|
|
@@ -438,7 +434,7 @@ function GridListDropIndicator(props: GridListDropIndicatorProps, ref: Forwarded
|
|
|
438
434
|
const GridListDropIndicatorForwardRef = forwardRef(GridListDropIndicator);
|
|
439
435
|
|
|
440
436
|
function RootDropIndicator() {
|
|
441
|
-
let {dragAndDropHooks, dropState} = useContext(
|
|
437
|
+
let {dragAndDropHooks, dropState} = useContext(DragAndDropContext);
|
|
442
438
|
let ref = useRef<HTMLDivElement>(null);
|
|
443
439
|
let {dropIndicatorProps} = dragAndDropHooks!.useDropIndicator!({
|
|
444
440
|
target: {type: 'root'}
|
package/src/Group.tsx
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import {AriaLabelingProps} from '@react-types/shared';
|
|
13
14
|
import {ContextValue, StyleRenderProps, useContextProps, useRenderProps} from './utils';
|
|
14
15
|
import {mergeProps, useFocusRing, useHover} from 'react-aria';
|
|
15
16
|
import React, {createContext, ForwardedRef, forwardRef, HTMLAttributes} from 'react';
|
|
@@ -29,10 +30,33 @@ export interface GroupRenderProps {
|
|
|
29
30
|
* Whether an element within the group is keyboard focused.
|
|
30
31
|
* @selector [data-focus-visible]
|
|
31
32
|
*/
|
|
32
|
-
isFocusVisible: boolean
|
|
33
|
+
isFocusVisible: boolean,
|
|
34
|
+
/**
|
|
35
|
+
* Whether the group is disabled.
|
|
36
|
+
* @selector [data-disabled]
|
|
37
|
+
*/
|
|
38
|
+
isDisabled: boolean,
|
|
39
|
+
/**
|
|
40
|
+
* Whether the group is invalid.
|
|
41
|
+
* @selector [data-invalid]
|
|
42
|
+
*/
|
|
43
|
+
isInvalid: boolean
|
|
33
44
|
}
|
|
34
45
|
|
|
35
|
-
export interface GroupProps extends Omit<HTMLAttributes<HTMLElement>, 'className' | 'style'>, StyleRenderProps<GroupRenderProps> {
|
|
46
|
+
export interface GroupProps extends AriaLabelingProps, Omit<HTMLAttributes<HTMLElement>, 'className' | 'style' | 'role'>, StyleRenderProps<GroupRenderProps> {
|
|
47
|
+
/** Whether the group is disabled. */
|
|
48
|
+
isDisabled?: boolean,
|
|
49
|
+
/** Whether the group is invalid. */
|
|
50
|
+
isInvalid?: boolean,
|
|
51
|
+
/**
|
|
52
|
+
* An accessibility role for the group. By default, this is set to `'group'`.
|
|
53
|
+
* Use `'region'` when the contents of the group is important enough to be
|
|
54
|
+
* included in the page table of contents. Use `'presentation'` if the group
|
|
55
|
+
* is visual only and does not represent a semantic grouping of controls.
|
|
56
|
+
* @default 'group'
|
|
57
|
+
*/
|
|
58
|
+
role?: 'group' | 'region' | 'presentation'
|
|
59
|
+
}
|
|
36
60
|
|
|
37
61
|
export const GroupContext = createContext<ContextValue<GroupProps, HTMLDivElement>>({});
|
|
38
62
|
|
|
@@ -44,27 +68,33 @@ function Group(props: GroupProps, ref: ForwardedRef<HTMLDivElement>) {
|
|
|
44
68
|
within: true
|
|
45
69
|
});
|
|
46
70
|
|
|
71
|
+
let {isDisabled, isInvalid, ...otherProps} = props;
|
|
72
|
+
isDisabled ??= !!props['aria-disabled'] && props['aria-disabled'] !== 'false';
|
|
73
|
+
isInvalid ??= !!props['aria-invalid'] && props['aria-invalid'] !== 'false';
|
|
47
74
|
let renderProps = useRenderProps({
|
|
48
75
|
...props,
|
|
49
|
-
values: {isHovered, isFocusWithin: isFocused, isFocusVisible},
|
|
76
|
+
values: {isHovered, isFocusWithin: isFocused, isFocusVisible, isDisabled, isInvalid},
|
|
50
77
|
defaultClassName: 'react-aria-Group'
|
|
51
78
|
});
|
|
52
79
|
|
|
53
80
|
return (
|
|
54
81
|
<div
|
|
55
|
-
{...mergeProps(
|
|
82
|
+
{...mergeProps(otherProps, focusProps, hoverProps)}
|
|
56
83
|
{...renderProps}
|
|
57
84
|
ref={ref}
|
|
85
|
+
role={props.role ?? 'group'}
|
|
58
86
|
data-focus-within={isFocused || undefined}
|
|
59
87
|
data-hovered={isHovered || undefined}
|
|
60
|
-
data-focus-visible={isFocusVisible || undefined}
|
|
88
|
+
data-focus-visible={isFocusVisible || undefined}
|
|
89
|
+
data-disabled={isDisabled || undefined}
|
|
90
|
+
data-invalid={isInvalid || undefined}>
|
|
61
91
|
{props.children}
|
|
62
92
|
</div>
|
|
63
93
|
);
|
|
64
94
|
}
|
|
65
95
|
|
|
66
96
|
/**
|
|
67
|
-
*
|
|
97
|
+
* A group represents a set of related UI controls, and supports interactive states for styling.
|
|
68
98
|
*/
|
|
69
99
|
const _Group = forwardRef(Group);
|
|
70
100
|
export {_Group as Group};
|
package/src/Link.tsx
CHANGED
|
@@ -12,8 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
import {AriaLinkOptions, mergeProps, useFocusRing, useHover, useLink} from 'react-aria';
|
|
14
14
|
import {ContextValue, forwardRefType, RenderProps, SlotProps, useContextProps, useRenderProps} from './utils';
|
|
15
|
-
import {
|
|
16
|
-
import React, {createContext, ForwardedRef, forwardRef, useMemo} from 'react';
|
|
15
|
+
import React, {createContext, ElementType, ForwardedRef, forwardRef} from 'react';
|
|
17
16
|
|
|
18
17
|
export interface LinkProps extends Omit<AriaLinkOptions, 'elementType'>, RenderProps<LinkRenderProps>, SlotProps {}
|
|
19
18
|
|
|
@@ -55,8 +54,8 @@ export const LinkContext = createContext<ContextValue<LinkProps, HTMLAnchorEleme
|
|
|
55
54
|
function Link(props: LinkProps, ref: ForwardedRef<HTMLAnchorElement>) {
|
|
56
55
|
[props, ref] = useContextProps(props, ref, LinkContext);
|
|
57
56
|
|
|
58
|
-
let
|
|
59
|
-
let {linkProps, isPressed} = useLink({...props, elementType}, ref);
|
|
57
|
+
let ElementType: ElementType = props.href ? 'a' : 'span';
|
|
58
|
+
let {linkProps, isPressed} = useLink({...props, elementType: ElementType}, ref);
|
|
60
59
|
|
|
61
60
|
let {hoverProps, isHovered} = useHover(props);
|
|
62
61
|
let {focusProps, isFocused, isFocusVisible} = useFocusRing();
|
|
@@ -74,26 +73,20 @@ function Link(props: LinkProps, ref: ForwardedRef<HTMLAnchorElement>) {
|
|
|
74
73
|
}
|
|
75
74
|
});
|
|
76
75
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
'data-pressed': isPressed || undefined,
|
|
92
|
-
'data-focus-visible': isFocusVisible || undefined,
|
|
93
|
-
'data-current': !!props['aria-current'] || undefined,
|
|
94
|
-
'data-disabled': props.isDisabled || undefined
|
|
95
|
-
}, element.props)
|
|
96
|
-
});
|
|
76
|
+
return (
|
|
77
|
+
<ElementType
|
|
78
|
+
ref={ref}
|
|
79
|
+
slot={props.slot || undefined}
|
|
80
|
+
{...mergeProps(renderProps, linkProps, hoverProps, focusProps)}
|
|
81
|
+
data-focused={isFocused || undefined}
|
|
82
|
+
data-hovered={isHovered || undefined}
|
|
83
|
+
data-pressed={isPressed || undefined}
|
|
84
|
+
data-focus-visible={isFocusVisible || undefined}
|
|
85
|
+
data-current={!!props['aria-current'] || undefined}
|
|
86
|
+
data-disabled={props.isDisabled || undefined}>
|
|
87
|
+
{renderProps.children}
|
|
88
|
+
</ElementType>
|
|
89
|
+
);
|
|
97
90
|
}
|
|
98
91
|
|
|
99
92
|
/**
|
package/src/ListBox.tsx
CHANGED
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {AriaListBoxOptions, AriaListBoxProps, DraggableItemResult, DragPreviewRenderer, DroppableCollectionResult, DroppableItemResult, FocusScope, ListKeyboardDelegate, mergeProps, useFocusRing, useHover, useListBox, useListBoxSection, useLocale, useOption} from 'react-aria';
|
|
14
|
-
import {
|
|
15
|
-
import {ContextValue, forwardRefType, HiddenContext, Provider, SlotProps, StyleProps, StyleRenderProps, useContextProps, useRenderProps, useSlot} from './utils';
|
|
16
|
-
import {DragAndDropHooks, DropIndicator, DropIndicatorContext, DropIndicatorProps} from './useDragAndDrop';
|
|
13
|
+
import {AriaListBoxOptions, AriaListBoxProps, DraggableItemResult, DragPreviewRenderer, DroppableCollectionResult, DroppableItemResult, FocusScope, ListKeyboardDelegate, mergeProps, useCollator, useFocusRing, useHover, useListBox, useListBoxSection, useLocale, useOption} from 'react-aria';
|
|
14
|
+
import {CollectionDocumentContext, CollectionPortal, CollectionProps, ItemProps, useCachedChildren, useCollection} from './Collection';
|
|
15
|
+
import {ContextValue, forwardRefType, HiddenContext, Provider, SlotProps, StyleProps, StyleRenderProps, useContextProps, useRenderProps, useSlot, useSlottedContext} from './utils';
|
|
16
|
+
import {DragAndDropContext, DragAndDropHooks, DropIndicator, DropIndicatorContext, DropIndicatorProps} from './useDragAndDrop';
|
|
17
17
|
import {DraggableCollectionState, DroppableCollectionState, ListState, Node, Orientation, SelectionBehavior, useListState} from 'react-stately';
|
|
18
18
|
import {filterDOMProps, mergeRefs, useObjectRef} from '@react-aria/utils';
|
|
19
19
|
import {Header} from './Header';
|
|
@@ -73,26 +73,14 @@ export interface ListBoxProps<T> extends Omit<AriaListBoxProps<T>, 'children' |
|
|
|
73
73
|
orientation?: Orientation
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
document?: Document<any, any>
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
interface InternalListBoxContextValue {
|
|
82
|
-
state: ListState<unknown>,
|
|
83
|
-
shouldFocusOnHover?: boolean,
|
|
84
|
-
dragAndDropHooks?: DragAndDropHooks,
|
|
85
|
-
dragState?: DraggableCollectionState,
|
|
86
|
-
dropState?: DroppableCollectionState
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export const ListBoxContext = createContext<ContextValue<ListBoxContextValue<any>, HTMLDivElement>>(null);
|
|
90
|
-
const InternalListBoxContext = createContext<InternalListBoxContextValue | null>(null);
|
|
76
|
+
export const ListBoxContext = createContext<ContextValue<ListBoxProps<any>, HTMLDivElement>>(null);
|
|
77
|
+
export const ListStateContext = createContext<ListState<any> | null>(null);
|
|
91
78
|
|
|
92
|
-
function ListBox<T>(props: ListBoxProps<T>, ref: ForwardedRef<HTMLDivElement>) {
|
|
79
|
+
function ListBox<T extends object>(props: ListBoxProps<T>, ref: ForwardedRef<HTMLDivElement>) {
|
|
93
80
|
[props, ref] = useContextProps(props, ref, ListBoxContext);
|
|
94
|
-
let ctx = props as ListBoxContextValue<T>;
|
|
95
81
|
let isHidden = useContext(HiddenContext);
|
|
82
|
+
let state = useContext(ListStateContext);
|
|
83
|
+
let document = useContext(CollectionDocumentContext);
|
|
96
84
|
|
|
97
85
|
// The structure of ListBox is a bit strange because it needs to work inside other components like ComboBox and Select.
|
|
98
86
|
// Those components render two copies of their children so that the collection can be built even when the popover is closed.
|
|
@@ -100,12 +88,12 @@ function ListBox<T>(props: ListBoxProps<T>, ref: ForwardedRef<HTMLDivElement>) {
|
|
|
100
88
|
// The second copy sends a ListState object via context which we use to render the ListBox without rebuilding the state.
|
|
101
89
|
// Otherwise, we have a standalone ListBox, so we need to create a collection and state ourselves.
|
|
102
90
|
|
|
103
|
-
if (
|
|
104
|
-
return <
|
|
91
|
+
if (document) {
|
|
92
|
+
return <CollectionPortal {...props} />;
|
|
105
93
|
}
|
|
106
94
|
|
|
107
|
-
if (
|
|
108
|
-
return isHidden ? null : <ListBoxInner state={
|
|
95
|
+
if (state) {
|
|
96
|
+
return isHidden ? null : <ListBoxInner state={state} props={props} listBoxRef={ref} />;
|
|
109
97
|
}
|
|
110
98
|
|
|
111
99
|
return <StandaloneListBox props={props} listBoxRef={ref} />;
|
|
@@ -123,10 +111,6 @@ function StandaloneListBox({props, listBoxRef}) {
|
|
|
123
111
|
);
|
|
124
112
|
}
|
|
125
113
|
|
|
126
|
-
function ListBoxPortal(props) {
|
|
127
|
-
return <>{useCollectionPortal(props, props.document)}</>;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
114
|
/**
|
|
131
115
|
* A listbox displays a list of options and allows a user to select one or more of them.
|
|
132
116
|
*/
|
|
@@ -146,16 +130,18 @@ function ListBoxInner<T>({state, props, listBoxRef}: ListBoxInnerProps<T>) {
|
|
|
146
130
|
let isListDroppable = !!dragAndDropHooks?.useDroppableCollectionState;
|
|
147
131
|
let {direction} = useLocale();
|
|
148
132
|
let {disabledBehavior, disabledKeys} = selectionManager;
|
|
133
|
+
let collator = useCollator({usage: 'search', sensitivity: 'base'});
|
|
149
134
|
let keyboardDelegate = useMemo(() => (
|
|
150
135
|
props.keyboardDelegate || new ListKeyboardDelegate({
|
|
151
136
|
collection,
|
|
137
|
+
collator,
|
|
152
138
|
ref: listBoxRef,
|
|
153
139
|
disabledKeys: disabledBehavior === 'selection' ? new Set<React.Key>() : disabledKeys,
|
|
154
140
|
layout,
|
|
155
141
|
orientation,
|
|
156
142
|
direction
|
|
157
143
|
})
|
|
158
|
-
), [collection, listBoxRef, disabledBehavior, disabledKeys, orientation, direction, props.keyboardDelegate, layout]);
|
|
144
|
+
), [collection, collator, listBoxRef, disabledBehavior, disabledKeys, orientation, direction, props.keyboardDelegate, layout]);
|
|
159
145
|
|
|
160
146
|
let {listBoxProps} = useListBox({
|
|
161
147
|
...props,
|
|
@@ -260,7 +246,7 @@ function ListBoxInner<T>({state, props, listBoxRef}: ListBoxInnerProps<T>) {
|
|
|
260
246
|
{...mergeProps(listBoxProps, focusProps, droppableCollection?.collectionProps)}
|
|
261
247
|
{...renderProps}
|
|
262
248
|
ref={listBoxRef}
|
|
263
|
-
slot={props.slot}
|
|
249
|
+
slot={props.slot || undefined}
|
|
264
250
|
data-drop-target={isRootDropTarget || undefined}
|
|
265
251
|
data-empty={state.collection.size === 0 || undefined}
|
|
266
252
|
data-focused={isFocused || undefined}
|
|
@@ -269,7 +255,9 @@ function ListBoxInner<T>({state, props, listBoxRef}: ListBoxInnerProps<T>) {
|
|
|
269
255
|
data-orientation={props.orientation || 'vertical'}>
|
|
270
256
|
<Provider
|
|
271
257
|
values={[
|
|
272
|
-
[
|
|
258
|
+
[ListBoxContext, props],
|
|
259
|
+
[ListStateContext, state],
|
|
260
|
+
[DragAndDropContext, {dragAndDropHooks, dragState, dropState}],
|
|
273
261
|
[SeparatorContext, {elementType: 'div'}],
|
|
274
262
|
[DropIndicatorContext, {render: ListBoxDropIndicatorWrapper}]
|
|
275
263
|
]}>
|
|
@@ -287,7 +275,7 @@ interface ListBoxSectionProps<T> extends StyleProps {
|
|
|
287
275
|
}
|
|
288
276
|
|
|
289
277
|
function ListBoxSection<T>({section, className, style}: ListBoxSectionProps<T>) {
|
|
290
|
-
let
|
|
278
|
+
let state = useContext(ListStateContext)!;
|
|
291
279
|
let [headingRef, heading] = useSlot();
|
|
292
280
|
let {headingProps, groupProps} = useListBoxSection({
|
|
293
281
|
heading,
|
|
@@ -344,8 +332,10 @@ interface OptionProps<T> {
|
|
|
344
332
|
}
|
|
345
333
|
|
|
346
334
|
function Option<T>({item}: OptionProps<T>) {
|
|
347
|
-
let ref = useObjectRef<
|
|
348
|
-
let
|
|
335
|
+
let ref = useObjectRef<any>(item.props.ref);
|
|
336
|
+
let state = useContext(ListStateContext)!;
|
|
337
|
+
let {shouldFocusOnHover} = useSlottedContext(ListBoxContext)! as AriaListBoxOptions<T>;
|
|
338
|
+
let {dragAndDropHooks, dragState, dropState} = useContext(DragAndDropContext)!;
|
|
349
339
|
let {optionProps, labelProps, descriptionProps, ...states} = useOption(
|
|
350
340
|
{key: item.key},
|
|
351
341
|
state,
|
|
@@ -399,13 +389,15 @@ function Option<T>({item}: OptionProps<T>) {
|
|
|
399
389
|
}
|
|
400
390
|
}, [item.textValue]);
|
|
401
391
|
|
|
392
|
+
let ElementType: React.ElementType = props.href ? 'a' : 'div';
|
|
393
|
+
|
|
402
394
|
return (
|
|
403
395
|
<>
|
|
404
396
|
{dragAndDropHooks?.useDropIndicator &&
|
|
405
397
|
renderDropIndicator({type: 'item', key: item.key, dropPosition: 'before'})
|
|
406
398
|
}
|
|
407
|
-
<
|
|
408
|
-
{...mergeProps(
|
|
399
|
+
<ElementType
|
|
400
|
+
{...mergeProps(optionProps, hoverProps, draggableItem?.dragProps, droppableItem?.dropProps)}
|
|
409
401
|
{...renderProps}
|
|
410
402
|
ref={ref}
|
|
411
403
|
data-allows-dragging={!!dragState || undefined}
|
|
@@ -429,7 +421,7 @@ function Option<T>({item}: OptionProps<T>) {
|
|
|
429
421
|
]}>
|
|
430
422
|
{renderProps.children}
|
|
431
423
|
</Provider>
|
|
432
|
-
</
|
|
424
|
+
</ElementType>
|
|
433
425
|
{dragAndDropHooks?.useDropIndicator && state.collection.getKeyAfter(item.key) == null &&
|
|
434
426
|
renderDropIndicator({type: 'item', key: item.key, dropPosition: 'after'})
|
|
435
427
|
}
|
|
@@ -439,7 +431,7 @@ function Option<T>({item}: OptionProps<T>) {
|
|
|
439
431
|
|
|
440
432
|
function ListBoxDropIndicatorWrapper(props: DropIndicatorProps, ref: ForwardedRef<HTMLElement>) {
|
|
441
433
|
ref = useObjectRef(ref);
|
|
442
|
-
let {dragAndDropHooks, dropState} = useContext(
|
|
434
|
+
let {dragAndDropHooks, dropState} = useContext(DragAndDropContext)!;
|
|
443
435
|
let {dropIndicatorProps, isHidden, isDropTarget} = dragAndDropHooks!.useDropIndicator!(
|
|
444
436
|
props,
|
|
445
437
|
dropState!,
|
package/src/Menu.tsx
CHANGED
|
@@ -14,18 +14,19 @@
|
|
|
14
14
|
import {AriaMenuProps, mergeProps, useFocusRing, useMenu, useMenuItem, useMenuSection, useMenuTrigger} from 'react-aria';
|
|
15
15
|
import {BaseCollection, CollectionProps, ItemProps, useCachedChildren, useCollection} from './Collection';
|
|
16
16
|
import {MenuTriggerProps as BaseMenuTriggerProps, Node, TreeState, useMenuTriggerState, useTreeState} from 'react-stately';
|
|
17
|
-
import {ButtonContext} from './Button';
|
|
18
17
|
import {ContextValue, forwardRefType, Provider, SlotProps, StyleProps, useContextProps, useRenderProps, useSlot} from './utils';
|
|
19
18
|
import {filterDOMProps, mergeRefs, useObjectRef} from '@react-aria/utils';
|
|
20
19
|
import {Header} from './Header';
|
|
21
20
|
import {KeyboardContext} from './Keyboard';
|
|
21
|
+
import {OverlayTriggerStateContext} from './Dialog';
|
|
22
22
|
import {PopoverContext} from './Popover';
|
|
23
|
+
import {PressResponder} from '@react-aria/interactions';
|
|
23
24
|
import React, {createContext, ForwardedRef, forwardRef, ReactNode, RefObject, useContext, useRef} from 'react';
|
|
24
25
|
import {Separator, SeparatorContext} from './Separator';
|
|
25
26
|
import {TextContext} from './Text';
|
|
26
27
|
|
|
27
28
|
export const MenuContext = createContext<ContextValue<MenuProps<any>, HTMLDivElement>>(null);
|
|
28
|
-
const
|
|
29
|
+
export const MenuStateContext = createContext<TreeState<unknown> | null>(null);
|
|
29
30
|
|
|
30
31
|
export interface MenuTriggerProps extends BaseMenuTriggerProps {
|
|
31
32
|
children?: ReactNode
|
|
@@ -44,10 +45,12 @@ export function MenuTrigger(props: MenuTriggerProps) {
|
|
|
44
45
|
<Provider
|
|
45
46
|
values={[
|
|
46
47
|
[MenuContext, menuProps],
|
|
47
|
-
[
|
|
48
|
-
[PopoverContext, {
|
|
48
|
+
[OverlayTriggerStateContext, state],
|
|
49
|
+
[PopoverContext, {triggerRef: ref, placement: 'bottom start'}]
|
|
49
50
|
]}>
|
|
50
|
-
{
|
|
51
|
+
<PressResponder {...menuTriggerProps} ref={ref} isPressed={state.isOpen}>
|
|
52
|
+
{props.children}
|
|
53
|
+
</PressResponder>
|
|
51
54
|
</Provider>
|
|
52
55
|
);
|
|
53
56
|
}
|
|
@@ -102,12 +105,12 @@ function MenuInner<T extends object>({props, collection, menuRef: ref}: MenuInne
|
|
|
102
105
|
{...filterDOMProps(props)}
|
|
103
106
|
{...menuProps}
|
|
104
107
|
ref={ref}
|
|
105
|
-
slot={props.slot}
|
|
108
|
+
slot={props.slot || undefined}
|
|
106
109
|
style={props.style}
|
|
107
110
|
className={props.className ?? 'react-aria-Menu'}>
|
|
108
111
|
<Provider
|
|
109
112
|
values={[
|
|
110
|
-
[
|
|
113
|
+
[MenuStateContext, state],
|
|
111
114
|
[SeparatorContext, {elementType: 'div'}]
|
|
112
115
|
]}>
|
|
113
116
|
{children}
|
|
@@ -127,7 +130,7 @@ interface MenuSectionProps<T> extends StyleProps {
|
|
|
127
130
|
}
|
|
128
131
|
|
|
129
132
|
function MenuSection<T>({section, className, style, ...otherProps}: MenuSectionProps<T>) {
|
|
130
|
-
let state = useContext(
|
|
133
|
+
let state = useContext(MenuStateContext)!;
|
|
131
134
|
let [headingRef, heading] = useSlot();
|
|
132
135
|
let {headingProps, groupProps} = useMenuSection({
|
|
133
136
|
heading,
|
|
@@ -174,8 +177,8 @@ interface MenuItemProps<T> {
|
|
|
174
177
|
}
|
|
175
178
|
|
|
176
179
|
function MenuItem<T>({item}: MenuItemProps<T>) {
|
|
177
|
-
let state = useContext(
|
|
178
|
-
let ref = useObjectRef<
|
|
180
|
+
let state = useContext(MenuStateContext)!;
|
|
181
|
+
let ref = useObjectRef<any>(item.props.ref);
|
|
179
182
|
let {menuItemProps, labelProps, descriptionProps, keyboardShortcutProps, ...states} = useMenuItem({key: item.key}, state, ref);
|
|
180
183
|
|
|
181
184
|
let props: ItemProps<T> = item.props;
|
|
@@ -194,12 +197,11 @@ function MenuItem<T>({item}: MenuItemProps<T>) {
|
|
|
194
197
|
}
|
|
195
198
|
});
|
|
196
199
|
|
|
197
|
-
let
|
|
198
|
-
delete DOMProps.id;
|
|
200
|
+
let ElementType: React.ElementType = props.href ? 'a' : 'div';
|
|
199
201
|
|
|
200
202
|
return (
|
|
201
|
-
<
|
|
202
|
-
{...mergeProps(
|
|
203
|
+
<ElementType
|
|
204
|
+
{...mergeProps(menuItemProps, focusProps)}
|
|
203
205
|
{...renderProps}
|
|
204
206
|
ref={ref}
|
|
205
207
|
data-disabled={states.isDisabled || undefined}
|
|
@@ -221,6 +223,6 @@ function MenuItem<T>({item}: MenuItemProps<T>) {
|
|
|
221
223
|
]}>
|
|
222
224
|
{renderProps.children}
|
|
223
225
|
</Provider>
|
|
224
|
-
</
|
|
226
|
+
</ElementType>
|
|
225
227
|
);
|
|
226
228
|
}
|
package/src/Meter.tsx
CHANGED
|
@@ -58,7 +58,7 @@ function Meter(props: MeterProps, ref: ForwardedRef<HTMLDivElement>) {
|
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
return (
|
|
61
|
-
<div {...meterProps} {...renderProps} ref={ref} slot={props.slot}>
|
|
61
|
+
<div {...meterProps} {...renderProps} ref={ref} slot={props.slot || undefined}>
|
|
62
62
|
<LabelContext.Provider value={{...labelProps, ref: labelRef, elementType: 'span'}}>
|
|
63
63
|
{renderProps.children}
|
|
64
64
|
</LabelContext.Provider>
|
package/src/Modal.tsx
CHANGED
|
@@ -11,27 +11,23 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import {AriaModalOverlayProps, DismissButton, Overlay, useIsSSR, useModalOverlay} from 'react-aria';
|
|
14
|
-
import {ContextValue, forwardRefType, RenderProps, SlotProps, useContextProps, useEnterAnimation, useExitAnimation, useRenderProps} from './utils';
|
|
14
|
+
import {ContextValue, forwardRefType, Provider, RenderProps, SlotProps, useContextProps, useEnterAnimation, useExitAnimation, useRenderProps} from './utils';
|
|
15
15
|
import {DOMAttributes} from '@react-types/shared';
|
|
16
16
|
import {filterDOMProps, mergeProps, mergeRefs, useObjectRef, useViewportSize} from '@react-aria/utils';
|
|
17
17
|
import {OverlayTriggerProps, OverlayTriggerState, useOverlayTriggerState} from 'react-stately';
|
|
18
|
+
import {OverlayTriggerStateContext} from './Dialog';
|
|
18
19
|
import React, {createContext, ForwardedRef, forwardRef, RefObject, useContext, useMemo, useRef} from 'react';
|
|
19
20
|
|
|
20
21
|
export interface ModalOverlayProps extends AriaModalOverlayProps, OverlayTriggerProps, RenderProps<ModalRenderProps>, SlotProps {}
|
|
21
22
|
|
|
22
|
-
interface ModalContextValue extends ModalOverlayProps {
|
|
23
|
-
state?: OverlayTriggerState
|
|
24
|
-
}
|
|
25
|
-
|
|
26
23
|
interface InternalModalContextValue {
|
|
27
24
|
modalProps: DOMAttributes,
|
|
28
25
|
modalRef: RefObject<HTMLDivElement>,
|
|
29
26
|
isExiting: boolean,
|
|
30
|
-
isDismissable?: boolean
|
|
31
|
-
state: OverlayTriggerState
|
|
27
|
+
isDismissable?: boolean
|
|
32
28
|
}
|
|
33
29
|
|
|
34
|
-
export const ModalContext = createContext<ContextValue<
|
|
30
|
+
export const ModalContext = createContext<ContextValue<ModalOverlayProps, HTMLDivElement>>(null);
|
|
35
31
|
const InternalModalContext = createContext<InternalModalContextValue | null>(null);
|
|
36
32
|
|
|
37
33
|
export interface ModalRenderProps {
|
|
@@ -97,9 +93,9 @@ export {_Modal as Modal};
|
|
|
97
93
|
|
|
98
94
|
function ModalOverlayWithForwardRef(props: ModalOverlayProps, ref: ForwardedRef<HTMLDivElement>) {
|
|
99
95
|
[props, ref] = useContextProps(props, ref, ModalContext);
|
|
100
|
-
let
|
|
96
|
+
let contextState = useContext(OverlayTriggerStateContext);
|
|
101
97
|
let localState = useOverlayTriggerState(props);
|
|
102
|
-
let state = props.isOpen != null || props.defaultOpen != null || !
|
|
98
|
+
let state = props.isOpen != null || props.defaultOpen != null || !contextState ? localState : contextState;
|
|
103
99
|
|
|
104
100
|
let objectRef = useObjectRef(ref);
|
|
105
101
|
let modalRef = useRef<HTMLDivElement>(null);
|
|
@@ -158,9 +154,13 @@ function ModalOverlayInner(props: ModalOverlayInnerProps) {
|
|
|
158
154
|
ref={props.overlayRef}
|
|
159
155
|
data-entering={entering || undefined}
|
|
160
156
|
data-exiting={props.isExiting || undefined}>
|
|
161
|
-
<
|
|
157
|
+
<Provider
|
|
158
|
+
values={[
|
|
159
|
+
[InternalModalContext, {modalProps, modalRef, isExiting: props.isExiting, isDismissable: props.isDismissable}],
|
|
160
|
+
[OverlayTriggerStateContext, state]
|
|
161
|
+
]}>
|
|
162
162
|
{renderProps.children}
|
|
163
|
-
</
|
|
163
|
+
</Provider>
|
|
164
164
|
</div>
|
|
165
165
|
</Overlay>
|
|
166
166
|
);
|
|
@@ -171,7 +171,8 @@ interface ModalContentProps extends RenderProps<ModalRenderProps> {
|
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
function ModalContent(props: ModalContentProps) {
|
|
174
|
-
let {modalProps, modalRef, isExiting, isDismissable
|
|
174
|
+
let {modalProps, modalRef, isExiting, isDismissable} = useContext(InternalModalContext)!;
|
|
175
|
+
let state = useContext(OverlayTriggerStateContext)!;
|
|
175
176
|
let mergedRefs = useMemo(() => mergeRefs(props.modalRef, modalRef), [props.modalRef, modalRef]);
|
|
176
177
|
|
|
177
178
|
let ref = useObjectRef(mergedRefs);
|
package/src/NumberField.tsx
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
import {AriaNumberFieldProps, useLocale, useNumberField} from 'react-aria';
|
|
14
14
|
import {ButtonContext} from './Button';
|
|
15
|
-
import {ContextValue, forwardRefType, Provider, RenderProps, SlotProps, useContextProps, useRenderProps, useSlot} from './utils';
|
|
15
|
+
import {ContextValue, forwardRefType, Provider, removeDataAttributes, RenderProps, SlotProps, useContextProps, useRenderProps, useSlot} from './utils';
|
|
16
16
|
import {filterDOMProps} from '@react-aria/utils';
|
|
17
17
|
import {GroupContext} from './Group';
|
|
18
18
|
import {InputContext} from './Input';
|
|
@@ -42,6 +42,7 @@ export interface NumberFieldRenderProps {
|
|
|
42
42
|
export interface NumberFieldProps extends Omit<AriaNumberFieldProps, 'label' | 'placeholder' | 'description' | 'errorMessage' | 'validationState'>, InputDOMProps, RenderProps<NumberFieldRenderProps>, SlotProps {}
|
|
43
43
|
|
|
44
44
|
export const NumberFieldContext = createContext<ContextValue<NumberFieldProps, HTMLDivElement>>(null);
|
|
45
|
+
export const NumberFieldStateContext = createContext<NumberFieldState | null>(null);
|
|
45
46
|
|
|
46
47
|
function NumberField(props: NumberFieldProps, ref: ForwardedRef<HTMLDivElement>) {
|
|
47
48
|
[props, ref] = useContextProps(props, ref, NumberFieldContext);
|
|
@@ -57,7 +58,7 @@ function NumberField(props: NumberFieldProps, ref: ForwardedRef<HTMLDivElement>)
|
|
|
57
58
|
decrementButtonProps,
|
|
58
59
|
descriptionProps,
|
|
59
60
|
errorMessageProps
|
|
60
|
-
} = useNumberField({...props, label}, state, inputRef);
|
|
61
|
+
} = useNumberField({...removeDataAttributes(props), label}, state, inputRef);
|
|
61
62
|
|
|
62
63
|
let renderProps = useRenderProps({
|
|
63
64
|
...props,
|
|
@@ -75,6 +76,7 @@ function NumberField(props: NumberFieldProps, ref: ForwardedRef<HTMLDivElement>)
|
|
|
75
76
|
return (
|
|
76
77
|
<Provider
|
|
77
78
|
values={[
|
|
79
|
+
[NumberFieldStateContext, state],
|
|
78
80
|
[GroupContext, groupProps],
|
|
79
81
|
[InputContext, {...inputProps, ref: inputRef}],
|
|
80
82
|
[LabelContext, {...labelProps, ref: labelRef}],
|
|
@@ -95,7 +97,7 @@ function NumberField(props: NumberFieldProps, ref: ForwardedRef<HTMLDivElement>)
|
|
|
95
97
|
{...DOMProps}
|
|
96
98
|
{...renderProps}
|
|
97
99
|
ref={ref}
|
|
98
|
-
slot={props.slot}
|
|
100
|
+
slot={props.slot || undefined}
|
|
99
101
|
data-disabled={props.isDisabled || undefined}
|
|
100
102
|
data-invalid={props.isInvalid || undefined} />
|
|
101
103
|
{props.name && <input type="hidden" name={props.name} value={isNaN(state.numberValue) ? '' : state.numberValue} />}
|
package/src/OverlayArrow.tsx
CHANGED
|
@@ -10,18 +10,15 @@
|
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {forwardRefType, RenderProps, useRenderProps} from './utils';
|
|
14
|
-
import {mergeProps} from '@react-aria/utils';
|
|
13
|
+
import {ContextValue, forwardRefType, RenderProps, useContextProps, useRenderProps} from './utils';
|
|
15
14
|
import {PlacementAxis} from 'react-aria';
|
|
16
|
-
import React, {createContext, CSSProperties, ForwardedRef, forwardRef, HTMLAttributes
|
|
15
|
+
import React, {createContext, CSSProperties, ForwardedRef, forwardRef, HTMLAttributes} from 'react';
|
|
17
16
|
|
|
18
|
-
interface OverlayArrowContextValue {
|
|
19
|
-
arrowProps: HTMLAttributes<HTMLElement>,
|
|
17
|
+
interface OverlayArrowContextValue extends OverlayArrowProps {
|
|
20
18
|
placement: PlacementAxis
|
|
21
19
|
}
|
|
22
20
|
|
|
23
|
-
export const OverlayArrowContext = createContext<OverlayArrowContextValue
|
|
24
|
-
arrowProps: {},
|
|
21
|
+
export const OverlayArrowContext = createContext<ContextValue<OverlayArrowContextValue, HTMLDivElement>>({
|
|
25
22
|
placement: 'bottom'
|
|
26
23
|
});
|
|
27
24
|
|
|
@@ -36,9 +33,9 @@ export interface OverlayArrowRenderProps {
|
|
|
36
33
|
}
|
|
37
34
|
|
|
38
35
|
function OverlayArrow(props: OverlayArrowProps, ref: ForwardedRef<HTMLDivElement>) {
|
|
39
|
-
|
|
36
|
+
[props, ref] = useContextProps(props, ref, OverlayArrowContext);
|
|
37
|
+
let placement = (props as OverlayArrowContextValue).placement;
|
|
40
38
|
let style: CSSProperties = {
|
|
41
|
-
...arrowProps.style,
|
|
42
39
|
position: 'absolute',
|
|
43
40
|
[placement]: '100%',
|
|
44
41
|
transform: placement === 'top' || placement === 'bottom' ? 'translateX(-50%)' : 'translateY(-50%)'
|
|
@@ -54,7 +51,7 @@ function OverlayArrow(props: OverlayArrowProps, ref: ForwardedRef<HTMLDivElement
|
|
|
54
51
|
|
|
55
52
|
return (
|
|
56
53
|
<div
|
|
57
|
-
{...
|
|
54
|
+
{...props}
|
|
58
55
|
{...renderProps}
|
|
59
56
|
style={{
|
|
60
57
|
...renderProps.style,
|