react-aria-components 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/Autocomplete.main.js +23 -12
- package/dist/Autocomplete.main.js.map +1 -1
- package/dist/Autocomplete.mjs +23 -12
- package/dist/Autocomplete.module.js +23 -12
- package/dist/Autocomplete.module.js.map +1 -1
- package/dist/Checkbox.main.js +1 -1
- package/dist/Checkbox.main.js.map +1 -1
- package/dist/Checkbox.mjs +1 -1
- package/dist/Checkbox.module.js +1 -1
- package/dist/Checkbox.module.js.map +1 -1
- package/dist/Collection.main.js.map +1 -1
- package/dist/Collection.module.js.map +1 -1
- package/dist/ColorArea.main.js +4 -4
- package/dist/ColorArea.main.js.map +1 -1
- package/dist/ColorArea.mjs +2 -2
- package/dist/ColorArea.module.js +2 -2
- package/dist/ColorArea.module.js.map +1 -1
- package/dist/ColorField.main.js +8 -10
- package/dist/ColorField.main.js.map +1 -1
- package/dist/ColorField.mjs +4 -6
- package/dist/ColorField.module.js +4 -6
- package/dist/ColorField.module.js.map +1 -1
- package/dist/ColorPicker.main.js +2 -2
- package/dist/ColorPicker.main.js.map +1 -1
- package/dist/ColorPicker.mjs +1 -1
- package/dist/ColorPicker.module.js +1 -1
- package/dist/ColorPicker.module.js.map +1 -1
- package/dist/ColorSlider.main.js +5 -7
- package/dist/ColorSlider.main.js.map +1 -1
- package/dist/ColorSlider.mjs +3 -5
- package/dist/ColorSlider.module.js +3 -5
- package/dist/ColorSlider.module.js.map +1 -1
- package/dist/ColorSwatch.main.js +2 -2
- package/dist/ColorSwatch.main.js.map +1 -1
- package/dist/ColorSwatch.mjs +1 -1
- package/dist/ColorSwatch.module.js +1 -1
- package/dist/ColorSwatch.module.js.map +1 -1
- package/dist/ColorSwatchPicker.main.js +3 -3
- package/dist/ColorSwatchPicker.main.js.map +1 -1
- package/dist/ColorSwatchPicker.mjs +1 -1
- package/dist/ColorSwatchPicker.module.js +1 -1
- package/dist/ColorSwatchPicker.module.js.map +1 -1
- package/dist/ColorThumb.main.js +2 -6
- package/dist/ColorThumb.main.js.map +1 -1
- package/dist/ColorThumb.mjs +1 -5
- package/dist/ColorThumb.module.js +1 -5
- package/dist/ColorThumb.module.js.map +1 -1
- package/dist/ColorWheel.main.js +4 -4
- package/dist/ColorWheel.main.js.map +1 -1
- package/dist/ColorWheel.mjs +2 -2
- package/dist/ColorWheel.module.js +2 -2
- package/dist/ColorWheel.module.js.map +1 -1
- package/dist/ComboBox.main.js +1 -1
- package/dist/ComboBox.main.js.map +1 -1
- package/dist/ComboBox.mjs +1 -1
- package/dist/ComboBox.module.js +1 -1
- package/dist/ComboBox.module.js.map +1 -1
- package/dist/DateField.main.js +4 -3
- package/dist/DateField.main.js.map +1 -1
- package/dist/DateField.mjs +4 -3
- package/dist/DateField.module.js +4 -3
- package/dist/DateField.module.js.map +1 -1
- package/dist/DatePicker.main.js +2 -2
- package/dist/DatePicker.main.js.map +1 -1
- package/dist/DatePicker.mjs +2 -2
- package/dist/DatePicker.module.js +2 -2
- package/dist/DatePicker.module.js.map +1 -1
- package/dist/Dialog.main.js +2 -1
- package/dist/Dialog.main.js.map +1 -1
- package/dist/Dialog.mjs +2 -1
- package/dist/Dialog.module.js +2 -1
- package/dist/Dialog.module.js.map +1 -1
- package/dist/Disclosure.main.js +5 -7
- package/dist/Disclosure.main.js.map +1 -1
- package/dist/Disclosure.mjs +2 -4
- package/dist/Disclosure.module.js +2 -4
- package/dist/Disclosure.module.js.map +1 -1
- package/dist/DropZone.main.js +1 -3
- package/dist/DropZone.main.js.map +1 -1
- package/dist/DropZone.mjs +1 -3
- package/dist/DropZone.module.js +1 -3
- package/dist/DropZone.module.js.map +1 -1
- package/dist/GridList.main.js.map +1 -1
- package/dist/GridList.module.js.map +1 -1
- package/dist/Group.main.js.map +1 -1
- package/dist/Group.module.js.map +1 -1
- package/dist/ListBox.main.js +17 -16
- package/dist/ListBox.main.js.map +1 -1
- package/dist/ListBox.mjs +19 -18
- package/dist/ListBox.module.js +19 -18
- package/dist/ListBox.module.js.map +1 -1
- package/dist/Menu.main.js +39 -24
- package/dist/Menu.main.js.map +1 -1
- package/dist/Menu.mjs +40 -25
- package/dist/Menu.module.js +40 -25
- package/dist/Menu.module.js.map +1 -1
- package/dist/Meter.main.js +1 -1
- package/dist/Meter.main.js.map +1 -1
- package/dist/Meter.mjs +1 -1
- package/dist/Meter.module.js +1 -1
- package/dist/Meter.module.js.map +1 -1
- package/dist/NumberField.main.js +4 -2
- package/dist/NumberField.main.js.map +1 -1
- package/dist/NumberField.mjs +4 -2
- package/dist/NumberField.module.js +4 -2
- package/dist/NumberField.module.js.map +1 -1
- package/dist/Popover.main.js +67 -15
- package/dist/Popover.main.js.map +1 -1
- package/dist/Popover.mjs +69 -17
- package/dist/Popover.module.js +69 -17
- package/dist/Popover.module.js.map +1 -1
- package/dist/ProgressBar.main.js +1 -1
- package/dist/ProgressBar.main.js.map +1 -1
- package/dist/ProgressBar.mjs +1 -1
- package/dist/ProgressBar.module.js +1 -1
- package/dist/ProgressBar.module.js.map +1 -1
- package/dist/RadioGroup.main.js +1 -1
- package/dist/RadioGroup.main.js.map +1 -1
- package/dist/RadioGroup.mjs +1 -1
- package/dist/RadioGroup.module.js +1 -1
- package/dist/RadioGroup.module.js.map +1 -1
- package/dist/SearchField.main.js +4 -2
- package/dist/SearchField.main.js.map +1 -1
- package/dist/SearchField.mjs +5 -3
- package/dist/SearchField.module.js +5 -3
- package/dist/SearchField.module.js.map +1 -1
- package/dist/Select.main.js +3 -2
- package/dist/Select.main.js.map +1 -1
- package/dist/Select.mjs +3 -2
- package/dist/Select.module.js +3 -2
- package/dist/Select.module.js.map +1 -1
- package/dist/Slider.main.js +2 -2
- package/dist/Slider.main.js.map +1 -1
- package/dist/Slider.mjs +2 -2
- package/dist/Slider.module.js +2 -2
- package/dist/Slider.module.js.map +1 -1
- package/dist/Table.main.js +15 -6
- package/dist/Table.main.js.map +1 -1
- package/dist/Table.mjs +15 -6
- package/dist/Table.module.js +15 -6
- package/dist/Table.module.js.map +1 -1
- package/dist/TableLayout.main.js.map +1 -1
- package/dist/TableLayout.module.js.map +1 -1
- package/dist/Tabs.main.js +3 -2
- package/dist/Tabs.main.js.map +1 -1
- package/dist/Tabs.mjs +4 -3
- package/dist/Tabs.module.js +4 -3
- package/dist/Tabs.module.js.map +1 -1
- package/dist/TagGroup.main.js +1 -1
- package/dist/TagGroup.main.js.map +1 -1
- package/dist/TagGroup.mjs +1 -1
- package/dist/TagGroup.module.js +1 -1
- package/dist/TagGroup.module.js.map +1 -1
- package/dist/TextField.main.js +4 -2
- package/dist/TextField.main.js.map +1 -1
- package/dist/TextField.mjs +5 -3
- package/dist/TextField.module.js +5 -3
- package/dist/TextField.module.js.map +1 -1
- package/dist/Toast.main.js +148 -0
- package/dist/Toast.main.js.map +1 -0
- package/dist/Toast.mjs +137 -0
- package/dist/Toast.module.js +137 -0
- package/dist/Toast.module.js.map +1 -0
- package/dist/Tree.main.js +38 -34
- package/dist/Tree.main.js.map +1 -1
- package/dist/Tree.mjs +34 -30
- package/dist/Tree.module.js +34 -30
- package/dist/Tree.module.js.map +1 -1
- package/dist/Virtualizer.main.js +4 -1
- package/dist/Virtualizer.main.js.map +1 -1
- package/dist/Virtualizer.mjs +4 -1
- package/dist/Virtualizer.module.js +4 -1
- package/dist/Virtualizer.module.js.map +1 -1
- package/dist/import.mjs +9 -7
- package/dist/main.js +31 -17
- package/dist/main.js.map +1 -1
- package/dist/module.js +9 -7
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +159 -59
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.main.js +9 -7
- package/dist/utils.main.js.map +1 -1
- package/dist/utils.mjs +9 -7
- package/dist/utils.module.js +9 -7
- package/dist/utils.module.js.map +1 -1
- package/i18n/index.js +1 -1
- package/i18n/index.mjs +1 -1
- package/package.json +25 -30
- package/src/Autocomplete.tsx +19 -15
- package/src/Checkbox.tsx +3 -1
- package/src/Collection.tsx +2 -2
- package/src/ColorArea.tsx +2 -3
- package/src/ColorField.tsx +8 -6
- package/src/ColorPicker.tsx +1 -2
- package/src/ColorSlider.tsx +5 -5
- package/src/ColorSwatch.tsx +2 -2
- package/src/ColorSwatchPicker.tsx +1 -1
- package/src/ColorThumb.tsx +2 -4
- package/src/ColorWheel.tsx +2 -2
- package/src/ComboBox.tsx +3 -1
- package/src/DateField.tsx +8 -3
- package/src/DatePicker.tsx +6 -2
- package/src/Dialog.tsx +6 -2
- package/src/Disclosure.tsx +2 -3
- package/src/DropZone.tsx +1 -2
- package/src/GridList.tsx +5 -0
- package/src/Group.tsx +1 -0
- package/src/ListBox.tsx +11 -9
- package/src/Menu.tsx +53 -25
- package/src/Meter.tsx +3 -1
- package/src/NumberField.tsx +11 -2
- package/src/Popover.tsx +77 -25
- package/src/ProgressBar.tsx +3 -1
- package/src/RadioGroup.tsx +3 -1
- package/src/SearchField.tsx +6 -4
- package/src/Select.tsx +5 -2
- package/src/Slider.tsx +6 -2
- package/src/Table.tsx +35 -15
- package/src/TableLayout.ts +1 -1
- package/src/Tabs.tsx +6 -3
- package/src/TagGroup.tsx +3 -1
- package/src/TextField.tsx +6 -4
- package/src/Toast.tsx +184 -0
- package/src/Tree.tsx +67 -49
- package/src/Virtualizer.tsx +18 -3
- package/src/index.ts +16 -16
- package/src/utils.tsx +8 -10
package/src/TableLayout.ts
CHANGED
|
@@ -15,7 +15,7 @@ import {LayoutOptionsDelegate} from './Virtualizer';
|
|
|
15
15
|
import {TableColumnResizeStateContext} from './Table';
|
|
16
16
|
import {useContext, useMemo} from 'react';
|
|
17
17
|
|
|
18
|
-
export class TableLayout<T> extends BaseTableLayout<T> implements LayoutOptionsDelegate<TableLayoutProps> {
|
|
18
|
+
export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> extends BaseTableLayout<T, O> implements LayoutOptionsDelegate<TableLayoutProps> {
|
|
19
19
|
// Invalidate the layout whenever the column widths change.
|
|
20
20
|
useLayoutOptions() {
|
|
21
21
|
// This is not a React class component, just a regular class.
|
package/src/Tabs.tsx
CHANGED
|
@@ -15,7 +15,7 @@ import {AriaTabListProps, AriaTabPanelProps, mergeProps, Orientation, useFocusRi
|
|
|
15
15
|
import {Collection, CollectionBuilder, createHideableComponent, createLeafComponent} from '@react-aria/collections';
|
|
16
16
|
import {CollectionProps, CollectionRendererContext, DefaultCollectionRenderer, usePersistedKeys} from './Collection';
|
|
17
17
|
import {ContextValue, Provider, RenderProps, SlotProps, StyleRenderProps, useContextProps, useRenderProps, useSlottedContext} from './utils';
|
|
18
|
-
import {filterDOMProps, useObjectRef} from '@react-aria/utils';
|
|
18
|
+
import {filterDOMProps, inertValue, useObjectRef} from '@react-aria/utils';
|
|
19
19
|
import {Collection as ICollection, Node, TabListState, useTabListState} from 'react-stately';
|
|
20
20
|
import React, {createContext, ForwardedRef, forwardRef, JSX, useContext, useMemo} from 'react';
|
|
21
21
|
|
|
@@ -255,6 +255,7 @@ export const Tab = /*#__PURE__*/ createLeafComponent('item', (props: TabProps, f
|
|
|
255
255
|
let renderProps = useRenderProps({
|
|
256
256
|
...props,
|
|
257
257
|
id: undefined,
|
|
258
|
+
children: item.rendered,
|
|
258
259
|
defaultClassName: 'react-aria-Tab',
|
|
259
260
|
values: {
|
|
260
261
|
isSelected,
|
|
@@ -277,7 +278,9 @@ export const Tab = /*#__PURE__*/ createLeafComponent('item', (props: TabProps, f
|
|
|
277
278
|
data-focused={isFocused || undefined}
|
|
278
279
|
data-focus-visible={isFocusVisible || undefined}
|
|
279
280
|
data-pressed={isPressed || undefined}
|
|
280
|
-
data-hovered={isHovered || undefined}
|
|
281
|
+
data-hovered={isHovered || undefined}>
|
|
282
|
+
{renderProps.children}
|
|
283
|
+
</ElementType>
|
|
281
284
|
);
|
|
282
285
|
});
|
|
283
286
|
|
|
@@ -320,7 +323,7 @@ export const TabPanel = /*#__PURE__*/ createHideableComponent(function TabPanel(
|
|
|
320
323
|
data-focused={isFocused || undefined}
|
|
321
324
|
data-focus-visible={isFocusVisible || undefined}
|
|
322
325
|
// @ts-ignore
|
|
323
|
-
inert={!isSelected
|
|
326
|
+
inert={inertValue(!isSelected)}
|
|
324
327
|
data-inert={!isSelected ? 'true' : undefined}>
|
|
325
328
|
<Provider
|
|
326
329
|
values={[
|
package/src/TagGroup.tsx
CHANGED
|
@@ -75,7 +75,9 @@ interface TagGroupInnerProps {
|
|
|
75
75
|
|
|
76
76
|
function TagGroupInner({props, forwardedRef: ref, collection}: TagGroupInnerProps) {
|
|
77
77
|
let tagListRef = useRef<HTMLDivElement>(null);
|
|
78
|
-
let [labelRef, label] = useSlot(
|
|
78
|
+
let [labelRef, label] = useSlot(
|
|
79
|
+
!props['aria-label'] && !props['aria-labelledby']
|
|
80
|
+
);
|
|
79
81
|
let state = useListState({
|
|
80
82
|
...props,
|
|
81
83
|
children: undefined,
|
package/src/TextField.tsx
CHANGED
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
|
|
13
13
|
import {AriaTextFieldProps, useTextField} from 'react-aria';
|
|
14
14
|
import {ContextValue, DOMProps, Provider, RACValidation, removeDataAttributes, RenderProps, SlotProps, useContextProps, useRenderProps, useSlot, useSlottedContext} from './utils';
|
|
15
|
+
import {createHideableComponent} from '@react-aria/collections';
|
|
15
16
|
import {FieldErrorContext} from './FieldError';
|
|
16
17
|
import {filterDOMProps, mergeProps} from '@react-aria/utils';
|
|
17
18
|
import {FormContext} from './Form';
|
|
18
|
-
import {forwardRefType} from '@react-types/shared';
|
|
19
19
|
import {InputContext} from './Input';
|
|
20
20
|
import {LabelContext} from './Label';
|
|
21
|
-
import React, {createContext, ForwardedRef,
|
|
21
|
+
import React, {createContext, ForwardedRef, useCallback, useRef, useState} from 'react';
|
|
22
22
|
import {TextAreaContext} from './TextArea';
|
|
23
23
|
import {TextContext} from './Text';
|
|
24
24
|
|
|
@@ -55,13 +55,15 @@ export const TextFieldContext = createContext<ContextValue<TextFieldProps, HTMLD
|
|
|
55
55
|
/**
|
|
56
56
|
* A text field allows a user to enter a plain text value with a keyboard.
|
|
57
57
|
*/
|
|
58
|
-
export const TextField = /*#__PURE__*/ (
|
|
58
|
+
export const TextField = /*#__PURE__*/ createHideableComponent(function TextField(props: TextFieldProps, ref: ForwardedRef<HTMLDivElement>) {
|
|
59
59
|
[props, ref] = useContextProps(props, ref, TextFieldContext);
|
|
60
60
|
let {validationBehavior: formValidationBehavior} = useSlottedContext(FormContext) || {};
|
|
61
61
|
let validationBehavior = props.validationBehavior ?? formValidationBehavior ?? 'native';
|
|
62
62
|
let inputRef = useRef(null);
|
|
63
63
|
let [inputContextProps, mergedInputRef] = useContextProps({}, inputRef, InputContext);
|
|
64
|
-
let [labelRef, label] = useSlot(
|
|
64
|
+
let [labelRef, label] = useSlot(
|
|
65
|
+
!props['aria-label'] && !props['aria-labelledby']
|
|
66
|
+
);
|
|
65
67
|
let [inputElementType, setInputElementType] = useState('input');
|
|
66
68
|
let {labelProps, inputProps, descriptionProps, errorMessageProps, ...validation} = useTextField<any>({
|
|
67
69
|
...removeDataAttributes(props),
|
package/src/Toast.tsx
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {AriaToastProps, AriaToastRegionProps, mergeProps, useFocusRing, useToast, useToastRegion} from 'react-aria';
|
|
14
|
+
import {ButtonContext} from './Button';
|
|
15
|
+
import {ContextValue, DEFAULT_SLOT, Provider, RenderProps, StyleRenderProps, useContextProps, useRenderProps} from './utils';
|
|
16
|
+
import {createPortal} from 'react-dom';
|
|
17
|
+
import {forwardRefType} from '@react-types/shared';
|
|
18
|
+
import {QueuedToast, ToastQueue, ToastState, useToastQueue} from 'react-stately';
|
|
19
|
+
import React, {createContext, ForwardedRef, forwardRef, HTMLAttributes, JSX, ReactElement, useContext} from 'react';
|
|
20
|
+
import {TextContext} from './Text';
|
|
21
|
+
import {useObjectRef} from '@react-aria/utils';
|
|
22
|
+
|
|
23
|
+
const ToastStateContext = createContext<ToastState<any> | null>(null);
|
|
24
|
+
|
|
25
|
+
export interface ToastRegionRenderProps<T> {
|
|
26
|
+
/** A list of all currently visible toasts. */
|
|
27
|
+
visibleToasts: QueuedToast<T>[],
|
|
28
|
+
/**
|
|
29
|
+
* Whether the toast region is currently focused.
|
|
30
|
+
* @selector [data-focused]
|
|
31
|
+
*/
|
|
32
|
+
isFocused: boolean,
|
|
33
|
+
/**
|
|
34
|
+
* Whether the toast region is keyboard focused.
|
|
35
|
+
* @selector [data-focus-visible]
|
|
36
|
+
*/
|
|
37
|
+
isFocusVisible: boolean
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface ToastRegionProps<T> extends AriaToastRegionProps, StyleRenderProps<ToastRegionRenderProps<T>> {
|
|
41
|
+
/** The queue of toasts to display. */
|
|
42
|
+
queue: ToastQueue<T>,
|
|
43
|
+
/** A function to render each toast. */
|
|
44
|
+
children: (renderProps: {toast: QueuedToast<T>}) => ReactElement
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* A ToastRegion displays one or more toast notifications.
|
|
49
|
+
*/
|
|
50
|
+
export const ToastRegion = /*#__PURE__*/ (forwardRef as forwardRefType)(function ToastRegion<T>(props: ToastRegionProps<T>, ref: ForwardedRef<HTMLDivElement>): JSX.Element | null {
|
|
51
|
+
let state = useToastQueue(props.queue);
|
|
52
|
+
let objectRef = useObjectRef(ref);
|
|
53
|
+
let {regionProps} = useToastRegion(props, state, objectRef);
|
|
54
|
+
|
|
55
|
+
let {focusProps, isFocused, isFocusVisible} = useFocusRing();
|
|
56
|
+
let renderProps = useRenderProps({
|
|
57
|
+
...props,
|
|
58
|
+
children: undefined,
|
|
59
|
+
defaultClassName: 'react-aria-ToastRegion',
|
|
60
|
+
values: {
|
|
61
|
+
visibleToasts: state.visibleToasts,
|
|
62
|
+
isFocused,
|
|
63
|
+
isFocusVisible
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
let region = (
|
|
68
|
+
<ToastStateContext.Provider value={state}>
|
|
69
|
+
<div
|
|
70
|
+
{...renderProps}
|
|
71
|
+
{...mergeProps(regionProps, focusProps)}
|
|
72
|
+
ref={objectRef}
|
|
73
|
+
data-focused={isFocused || undefined}
|
|
74
|
+
data-focus-visible={isFocusVisible || undefined}>
|
|
75
|
+
{typeof props.children === 'function' ? <ToastList {...props} style={{display: 'contents'}} /> : props.children}
|
|
76
|
+
</div>
|
|
77
|
+
</ToastStateContext.Provider>
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
return state.visibleToasts.length > 0 && typeof document !== 'undefined'
|
|
81
|
+
? createPortal(region, document.body)
|
|
82
|
+
: null;
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// TODO: possibly export this so additional children can be added to the region, outside the list.
|
|
86
|
+
const ToastList = /*#__PURE__*/ (forwardRef as forwardRefType)(function ToastList<T>(props: ToastRegionProps<T>, ref: ForwardedRef<HTMLOListElement>) {
|
|
87
|
+
let state = useContext(ToastStateContext)!;
|
|
88
|
+
return (
|
|
89
|
+
// @ts-ignore
|
|
90
|
+
<ol ref={ref} style={props.style} className={props.className}>
|
|
91
|
+
{state.visibleToasts.map((toast) => (
|
|
92
|
+
<li key={toast.key} style={{display: 'contents'}}>
|
|
93
|
+
{props.children({toast})}
|
|
94
|
+
</li>
|
|
95
|
+
))}
|
|
96
|
+
</ol>
|
|
97
|
+
);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
export interface ToastRenderProps<T> {
|
|
101
|
+
/**
|
|
102
|
+
* The toast object to display.
|
|
103
|
+
*/
|
|
104
|
+
toast: QueuedToast<T>,
|
|
105
|
+
/**
|
|
106
|
+
* Whether the toast is currently focused.
|
|
107
|
+
* @selector [data-focused]
|
|
108
|
+
*/
|
|
109
|
+
isFocused: boolean,
|
|
110
|
+
/**
|
|
111
|
+
* Whether the toast is keyboard focused.
|
|
112
|
+
* @selector [data-focus-visible]
|
|
113
|
+
*/
|
|
114
|
+
isFocusVisible: boolean
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface ToastProps<T> extends AriaToastProps<T>, RenderProps<ToastRenderProps<T>> {}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* A Toast displays a brief, temporary notification of actions, errors, or other events in an application.
|
|
121
|
+
*/
|
|
122
|
+
export const Toast = /*#__PURE__*/ (forwardRef as forwardRefType)(function Toast<T>(props: ToastProps<T>, ref: ForwardedRef<HTMLDivElement>) {
|
|
123
|
+
let state = useContext(ToastStateContext)!;
|
|
124
|
+
let objectRef = useObjectRef(ref);
|
|
125
|
+
let {toastProps, contentProps, titleProps, descriptionProps, closeButtonProps} = useToast(
|
|
126
|
+
props,
|
|
127
|
+
state,
|
|
128
|
+
objectRef
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
let {focusProps, isFocused, isFocusVisible} = useFocusRing();
|
|
132
|
+
let renderProps = useRenderProps({
|
|
133
|
+
...props,
|
|
134
|
+
defaultClassName: 'react-aria-Toast',
|
|
135
|
+
values: {
|
|
136
|
+
toast: props.toast,
|
|
137
|
+
isFocused,
|
|
138
|
+
isFocusVisible
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
return (
|
|
143
|
+
<div
|
|
144
|
+
{...renderProps}
|
|
145
|
+
{...mergeProps(toastProps, focusProps)}
|
|
146
|
+
ref={objectRef}
|
|
147
|
+
data-focused={isFocused || undefined}
|
|
148
|
+
data-focus-visible={isFocusVisible || undefined}>
|
|
149
|
+
<Provider
|
|
150
|
+
values={[
|
|
151
|
+
[ToastContentContext, contentProps],
|
|
152
|
+
[TextContext, {
|
|
153
|
+
slots: {
|
|
154
|
+
[DEFAULT_SLOT]: {},
|
|
155
|
+
title: titleProps,
|
|
156
|
+
description: descriptionProps
|
|
157
|
+
}
|
|
158
|
+
}],
|
|
159
|
+
[ButtonContext, {
|
|
160
|
+
slots: {
|
|
161
|
+
[DEFAULT_SLOT]: {},
|
|
162
|
+
close: closeButtonProps
|
|
163
|
+
}
|
|
164
|
+
}]
|
|
165
|
+
]}>
|
|
166
|
+
{renderProps.children}
|
|
167
|
+
</Provider>
|
|
168
|
+
</div>
|
|
169
|
+
);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
export const ToastContentContext = createContext<ContextValue<HTMLAttributes<HTMLElement>, HTMLDivElement>>({});
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* ToastContent wraps the main content of a toast notification.
|
|
176
|
+
*/
|
|
177
|
+
export const ToastContent = /*#__PURE__*/ forwardRef(function ToastContent(props: HTMLAttributes<HTMLElement>, ref: ForwardedRef<HTMLDivElement>) {
|
|
178
|
+
[props, ref] = useContextProps(props, ref, ToastContentContext);
|
|
179
|
+
return (
|
|
180
|
+
<div className="react-aria-ToastContent" {...props} ref={ref}>
|
|
181
|
+
{props.children}
|
|
182
|
+
</div>
|
|
183
|
+
);
|
|
184
|
+
});
|
package/src/Tree.tsx
CHANGED
|
@@ -10,17 +10,16 @@
|
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {
|
|
13
|
+
import {AriaTreeItemOptions, AriaTreeProps, FocusScope, mergeProps, useFocusRing, useGridListSelectionCheckbox, useHover, useTree, useTreeItem} from 'react-aria';
|
|
14
14
|
import {ButtonContext} from './Button';
|
|
15
15
|
import {CheckboxContext} from './RSPContexts';
|
|
16
16
|
import {Collection, CollectionBuilder, CollectionNode, createBranchComponent, createLeafComponent, useCachedChildren} from '@react-aria/collections';
|
|
17
17
|
import {CollectionProps, CollectionRendererContext, DefaultCollectionRenderer, ItemRenderProps, usePersistedKeys} from './Collection';
|
|
18
18
|
import {ContextValue, DEFAULT_SLOT, Provider, RenderProps, ScrollableProps, SlotProps, StyleRenderProps, useContextProps, useRenderProps} from './utils';
|
|
19
|
-
import {DisabledBehavior, Expandable, forwardRefType, HoverEvents, Key, LinkDOMProps, RefObject} from '@react-types/shared';
|
|
19
|
+
import {DisabledBehavior, Expandable, forwardRefType, HoverEvents, Key, LinkDOMProps, MultipleSelection, RefObject} from '@react-types/shared';
|
|
20
20
|
import {filterDOMProps, useObjectRef} from '@react-aria/utils';
|
|
21
|
-
import {FocusScope, mergeProps, useFocusRing, useGridListSelectionCheckbox, useHover} from 'react-aria';
|
|
22
21
|
import {Collection as ICollection, Node, SelectionBehavior, TreeState, useTreeState} from 'react-stately';
|
|
23
|
-
import React, {createContext, ForwardedRef, forwardRef,
|
|
22
|
+
import React, {createContext, ForwardedRef, forwardRef, ReactNode, useContext, useEffect, useMemo, useRef} from 'react';
|
|
24
23
|
import {useControlledState} from '@react-stately/utils';
|
|
25
24
|
|
|
26
25
|
class TreeCollection<T> implements ICollection<Node<T>> {
|
|
@@ -120,29 +119,29 @@ export interface TreeRenderProps {
|
|
|
120
119
|
|
|
121
120
|
export interface TreeEmptyStateRenderProps extends Omit<TreeRenderProps, 'isEmpty'> {}
|
|
122
121
|
|
|
123
|
-
export interface TreeProps<T> extends Omit<
|
|
122
|
+
export interface TreeProps<T> extends Omit<AriaTreeProps<T>, 'children'>, MultipleSelection, CollectionProps<T>, StyleRenderProps<TreeRenderProps>, SlotProps, ScrollableProps<HTMLDivElement>, Expandable {
|
|
124
123
|
/** How multiple selection should behave in the tree. */
|
|
125
124
|
selectionBehavior?: SelectionBehavior,
|
|
126
125
|
/** Provides content to display when there are no items in the list. */
|
|
127
126
|
renderEmptyState?: (props: TreeEmptyStateRenderProps) => ReactNode,
|
|
128
127
|
/**
|
|
129
128
|
* Whether `disabledKeys` applies to all interactions, or only selection.
|
|
130
|
-
* @default '
|
|
129
|
+
* @default 'all'
|
|
131
130
|
*/
|
|
132
131
|
disabledBehavior?: DisabledBehavior
|
|
133
132
|
}
|
|
134
133
|
|
|
135
134
|
|
|
136
|
-
export const
|
|
137
|
-
export const
|
|
135
|
+
export const TreeContext = createContext<ContextValue<TreeProps<any>, HTMLDivElement>>(null);
|
|
136
|
+
export const TreeStateContext = createContext<TreeState<any> | null>(null);
|
|
138
137
|
|
|
139
138
|
/**
|
|
140
139
|
* A tree provides users with a way to navigate nested hierarchical information, with support for keyboard navigation
|
|
141
140
|
* and selection.
|
|
142
141
|
*/
|
|
143
|
-
export const
|
|
142
|
+
export const Tree = /*#__PURE__*/ (forwardRef as forwardRefType)(function Tree<T extends object>(props: TreeProps<T>, ref: ForwardedRef<HTMLDivElement>) {
|
|
144
143
|
// Render the portal first so that we have the collection by the time we render the DOM in SSR.
|
|
145
|
-
[props, ref] = useContextProps(props, ref,
|
|
144
|
+
[props, ref] = useContextProps(props, ref, TreeContext);
|
|
146
145
|
|
|
147
146
|
return (
|
|
148
147
|
<CollectionBuilder content={<Collection {...props} />}>
|
|
@@ -163,7 +162,7 @@ function TreeInner<T extends object>({props, collection, treeRef: ref}: TreeInne
|
|
|
163
162
|
expandedKeys: propExpandedKeys,
|
|
164
163
|
defaultExpandedKeys: propDefaultExpandedKeys,
|
|
165
164
|
onExpandedChange,
|
|
166
|
-
disabledBehavior = '
|
|
165
|
+
disabledBehavior = 'all'
|
|
167
166
|
} = props;
|
|
168
167
|
let {CollectionRoot, isVirtualized, layoutDelegate} = useContext(CollectionRendererContext);
|
|
169
168
|
|
|
@@ -189,7 +188,7 @@ function TreeInner<T extends object>({props, collection, treeRef: ref}: TreeInne
|
|
|
189
188
|
disabledBehavior
|
|
190
189
|
});
|
|
191
190
|
|
|
192
|
-
let {gridProps} =
|
|
191
|
+
let {gridProps} = useTree({
|
|
193
192
|
...props,
|
|
194
193
|
isVirtualized,
|
|
195
194
|
layoutDelegate
|
|
@@ -211,7 +210,6 @@ function TreeInner<T extends object>({props, collection, treeRef: ref}: TreeInne
|
|
|
211
210
|
});
|
|
212
211
|
|
|
213
212
|
let emptyState: ReactNode = null;
|
|
214
|
-
let emptyStatePropOverrides: HTMLAttributes<HTMLElement> | null = null;
|
|
215
213
|
if (state.collection.size === 0 && props.renderEmptyState) {
|
|
216
214
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
217
215
|
let {isEmpty, ...values} = renderValues;
|
|
@@ -236,7 +234,7 @@ function TreeInner<T extends object>({props, collection, treeRef: ref}: TreeInne
|
|
|
236
234
|
<div
|
|
237
235
|
{...filterDOMProps(props)}
|
|
238
236
|
{...renderProps}
|
|
239
|
-
{...mergeProps(gridProps, focusProps
|
|
237
|
+
{...mergeProps(gridProps, focusProps)}
|
|
240
238
|
ref={ref}
|
|
241
239
|
slot={props.slot || undefined}
|
|
242
240
|
onScroll={props.onScroll}
|
|
@@ -245,7 +243,7 @@ function TreeInner<T extends object>({props, collection, treeRef: ref}: TreeInne
|
|
|
245
243
|
data-focus-visible={isFocusVisible || undefined}>
|
|
246
244
|
<Provider
|
|
247
245
|
values={[
|
|
248
|
-
[
|
|
246
|
+
[TreeStateContext, state]
|
|
249
247
|
]}>
|
|
250
248
|
<CollectionRoot
|
|
251
249
|
collection={state.collection}
|
|
@@ -260,30 +258,39 @@ function TreeInner<T extends object>({props, collection, treeRef: ref}: TreeInne
|
|
|
260
258
|
|
|
261
259
|
// TODO: readd the rest of the render props when tree supports them
|
|
262
260
|
export interface TreeItemRenderProps extends Omit<ItemRenderProps, 'allowsDragging' | 'isDragging' | 'isDropTarget'> {
|
|
263
|
-
/**
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
/** Whether the tree item's children have keyboard focus. */
|
|
268
|
-
isFocusVisibleWithin: boolean
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
export interface TreeItemContentRenderProps extends ItemRenderProps {
|
|
272
|
-
// Whether the tree item is expanded.
|
|
261
|
+
/**
|
|
262
|
+
* Whether the tree item is expanded.
|
|
263
|
+
* @selector [data-expanded]
|
|
264
|
+
*/
|
|
273
265
|
isExpanded: boolean,
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
266
|
+
/**
|
|
267
|
+
* Whether the tree item has child tree items.
|
|
268
|
+
* @selector [data-has-child-items]
|
|
269
|
+
*/
|
|
270
|
+
hasChildItems: boolean,
|
|
271
|
+
/**
|
|
272
|
+
* What level the tree item has within the tree.
|
|
273
|
+
* @selector [data-level="number"]
|
|
274
|
+
*/
|
|
277
275
|
level: number,
|
|
278
|
-
|
|
279
|
-
|
|
276
|
+
/**
|
|
277
|
+
* Whether the tree item's children have keyboard focus.
|
|
278
|
+
* @selector [data-focus-visible-within]
|
|
279
|
+
*/
|
|
280
|
+
isFocusVisibleWithin: boolean,
|
|
281
|
+
/** The state of the tree. */
|
|
282
|
+
state: TreeState<unknown>,
|
|
283
|
+
/** The unique id of the tree row. */
|
|
284
|
+
id: Key
|
|
280
285
|
}
|
|
281
286
|
|
|
287
|
+
export interface TreeItemContentRenderProps extends TreeItemRenderProps {}
|
|
288
|
+
|
|
282
289
|
// The TreeItemContent is the one that accepts RenderProps because we would get much more complicated logic in TreeItem otherwise since we'd
|
|
283
290
|
// need to do a bunch of check to figure out what is the Content and what are the actual collection elements (aka child rows) of the TreeItem
|
|
284
291
|
export interface TreeItemContentProps extends Pick<RenderProps<TreeItemContentRenderProps>, 'children'> {}
|
|
285
292
|
|
|
286
|
-
export const
|
|
293
|
+
export const TreeItemContent = /*#__PURE__*/ createLeafComponent('content', function TreeItemContent(props: TreeItemContentProps) {
|
|
287
294
|
let values = useContext(TreeItemContentContext)!;
|
|
288
295
|
let renderProps = useRenderProps({
|
|
289
296
|
children: props.children,
|
|
@@ -298,7 +305,7 @@ export const UNSTABLE_TreeItemContent = /*#__PURE__*/ createLeafComponent('conte
|
|
|
298
305
|
|
|
299
306
|
export const TreeItemContentContext = createContext<TreeItemContentRenderProps | null>(null);
|
|
300
307
|
|
|
301
|
-
export interface TreeItemProps<T = object> extends StyleRenderProps<TreeItemRenderProps>, LinkDOMProps, HoverEvents {
|
|
308
|
+
export interface TreeItemProps<T = object> extends StyleRenderProps<TreeItemRenderProps>, LinkDOMProps, HoverEvents, Pick<AriaTreeItemOptions, 'hasChildItems'> {
|
|
302
309
|
/** The unique id of the tree row. */
|
|
303
310
|
id?: Key,
|
|
304
311
|
/** The object value that this tree item represents. When using dynamic collections, this is set automatically. */
|
|
@@ -308,20 +315,27 @@ export interface TreeItemProps<T = object> extends StyleRenderProps<TreeItemRend
|
|
|
308
315
|
/** An accessibility label for this tree item. */
|
|
309
316
|
'aria-label'?: string,
|
|
310
317
|
/** The content of the tree item along with any nested children. Supports static nested tree items or use of a Collection to dynamically render nested tree items. */
|
|
311
|
-
children: ReactNode
|
|
318
|
+
children: ReactNode,
|
|
319
|
+
/** Whether the item is disabled. */
|
|
320
|
+
isDisabled?: boolean,
|
|
321
|
+
/**
|
|
322
|
+
* Handler that is called when a user performs an action on this tree item. The exact user event depends on
|
|
323
|
+
* the collection's `selectionBehavior` prop and the interaction modality.
|
|
324
|
+
*/
|
|
325
|
+
onAction?: () => void
|
|
312
326
|
}
|
|
313
327
|
|
|
314
328
|
/**
|
|
315
329
|
* A TreeItem represents an individual item in a Tree.
|
|
316
330
|
*/
|
|
317
|
-
export const
|
|
318
|
-
let state = useContext(
|
|
331
|
+
export const TreeItem = /*#__PURE__*/ createBranchComponent('item', <T extends object>(props: TreeItemProps<T>, ref: ForwardedRef<HTMLDivElement>, item: Node<T>) => {
|
|
332
|
+
let state = useContext(TreeStateContext)!;
|
|
319
333
|
ref = useObjectRef<HTMLDivElement>(ref);
|
|
320
334
|
// TODO: remove this when we support description in tree row
|
|
321
335
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
322
|
-
let {rowProps, gridCellProps, expandButtonProps, descriptionProps, ...states} =
|
|
336
|
+
let {rowProps, gridCellProps, expandButtonProps, descriptionProps, ...states} = useTreeItem({node: item}, state, ref);
|
|
323
337
|
let isExpanded = rowProps['aria-expanded'] === true;
|
|
324
|
-
let
|
|
338
|
+
let hasChildItems = props.hasChildItems || [...state.collection.getChildren!(item.key)]?.length > 1;;
|
|
325
339
|
let level = rowProps['aria-level'] || 1;
|
|
326
340
|
|
|
327
341
|
let {hoverProps, isHovered} = useHover({
|
|
@@ -341,17 +355,21 @@ export const UNSTABLE_TreeItem = /*#__PURE__*/ createBranchComponent('item', <T
|
|
|
341
355
|
state
|
|
342
356
|
);
|
|
343
357
|
|
|
358
|
+
let selectionMode = state.selectionManager.selectionMode;
|
|
359
|
+
let selectionBehavior = state.selectionManager.selectionBehavior;
|
|
344
360
|
let renderPropValues = React.useMemo<TreeItemContentRenderProps>(() => ({
|
|
345
361
|
...states,
|
|
346
362
|
isHovered,
|
|
347
363
|
isFocusVisible,
|
|
348
364
|
isExpanded,
|
|
349
|
-
|
|
365
|
+
hasChildItems,
|
|
350
366
|
level,
|
|
351
|
-
selectionMode
|
|
352
|
-
selectionBehavior
|
|
353
|
-
isFocusVisibleWithin
|
|
354
|
-
|
|
367
|
+
selectionMode,
|
|
368
|
+
selectionBehavior,
|
|
369
|
+
isFocusVisibleWithin,
|
|
370
|
+
state,
|
|
371
|
+
id: item.key
|
|
372
|
+
}), [states, isHovered, isFocusVisible, selectionMode, selectionBehavior, isExpanded, hasChildItems, level, isFocusVisibleWithin, state, item.key]);
|
|
355
373
|
|
|
356
374
|
let renderProps = useRenderProps({
|
|
357
375
|
...props,
|
|
@@ -373,7 +391,7 @@ export const UNSTABLE_TreeItem = /*#__PURE__*/ createBranchComponent('item', <T
|
|
|
373
391
|
|
|
374
392
|
let expandButtonRef = useRef<HTMLButtonElement>(null);
|
|
375
393
|
useEffect(() => {
|
|
376
|
-
if (
|
|
394
|
+
if (hasChildItems && !expandButtonRef.current) {
|
|
377
395
|
console.warn('Expandable tree items must contain a expand button so screen reader users can expand/collapse the item.');
|
|
378
396
|
}
|
|
379
397
|
// eslint-disable-next-line
|
|
@@ -404,8 +422,8 @@ export const UNSTABLE_TreeItem = /*#__PURE__*/ createBranchComponent('item', <T
|
|
|
404
422
|
{...renderProps}
|
|
405
423
|
ref={ref}
|
|
406
424
|
// TODO: missing selectionBehavior, hasAction and allowsSelection data attribute equivalents (available in renderProps). Do we want those?
|
|
407
|
-
data-expanded={(
|
|
408
|
-
data-has-child-
|
|
425
|
+
data-expanded={(hasChildItems && isExpanded) || undefined}
|
|
426
|
+
data-has-child-items={hasChildItems || undefined}
|
|
409
427
|
data-level={level}
|
|
410
428
|
data-selected={states.isSelected || undefined}
|
|
411
429
|
data-disabled={states.isDisabled || undefined}
|
|
@@ -445,7 +463,7 @@ export const UNSTABLE_TreeItem = /*#__PURE__*/ createBranchComponent('item', <T
|
|
|
445
463
|
);
|
|
446
464
|
});
|
|
447
465
|
|
|
448
|
-
export interface
|
|
466
|
+
export interface UNSTABLE_TreeLoadingIndicatorRenderProps {
|
|
449
467
|
/**
|
|
450
468
|
* What level the tree item has within the tree.
|
|
451
469
|
* @selector [data-level]
|
|
@@ -453,13 +471,13 @@ export interface TreeLoadingIndicatorRenderProps {
|
|
|
453
471
|
level: number
|
|
454
472
|
}
|
|
455
473
|
|
|
456
|
-
export interface TreeLoaderProps extends RenderProps<
|
|
474
|
+
export interface TreeLoaderProps extends RenderProps<UNSTABLE_TreeLoadingIndicatorRenderProps>, StyleRenderProps<UNSTABLE_TreeLoadingIndicatorRenderProps> {}
|
|
457
475
|
|
|
458
476
|
export const UNSTABLE_TreeLoadingIndicator = createLeafComponent('loader', function TreeLoader<T extends object>(props: TreeLoaderProps, ref: ForwardedRef<HTMLDivElement>, item: Node<T>) {
|
|
459
|
-
let state = useContext(
|
|
477
|
+
let state = useContext(TreeStateContext);
|
|
460
478
|
// This loader row is is non-interactable, but we want the same aria props calculated as a typical row
|
|
461
479
|
// @ts-ignore
|
|
462
|
-
let {rowProps} =
|
|
480
|
+
let {rowProps} = useTreeItem({node: item}, state, ref);
|
|
463
481
|
let level = rowProps['aria-level'] || 1;
|
|
464
482
|
|
|
465
483
|
let ariaProps = {
|
package/src/Virtualizer.tsx
CHANGED
|
@@ -24,20 +24,35 @@ export interface LayoutOptionsDelegate<O> {
|
|
|
24
24
|
|
|
25
25
|
interface ILayout<O> extends Layout<Node<unknown>, O>, Partial<DropTargetDelegate>, LayoutOptionsDelegate<O> {}
|
|
26
26
|
|
|
27
|
+
interface LayoutClass<O> {
|
|
28
|
+
new(): ILayout<O>
|
|
29
|
+
}
|
|
30
|
+
|
|
27
31
|
export interface VirtualizerProps<O> {
|
|
28
32
|
/** The child collection to virtualize (e.g. ListBox, GridList, or Table). */
|
|
29
33
|
children: ReactNode,
|
|
30
34
|
/** The layout object that determines the position and size of the visible elements. */
|
|
31
|
-
layout: ILayout<O>,
|
|
35
|
+
layout: LayoutClass<O> | ILayout<O>,
|
|
32
36
|
/** Options for the layout. */
|
|
33
37
|
layoutOptions?: O
|
|
34
38
|
}
|
|
35
39
|
|
|
40
|
+
interface LayoutContextValue {
|
|
41
|
+
layout: ILayout<any>,
|
|
42
|
+
layoutOptions?: any
|
|
43
|
+
}
|
|
44
|
+
|
|
36
45
|
const VirtualizerContext = createContext<VirtualizerState<any, any> | null>(null);
|
|
37
|
-
const LayoutContext = createContext<
|
|
46
|
+
const LayoutContext = createContext<LayoutContextValue | null>(null);
|
|
38
47
|
|
|
48
|
+
/**
|
|
49
|
+
* A Virtualizer renders a scrollable collection of data using customizable layouts.
|
|
50
|
+
* It supports very large collections by only rendering visible items to the DOM, reusing
|
|
51
|
+
* them as the user scrolls.
|
|
52
|
+
*/
|
|
39
53
|
export function Virtualizer<O>(props: VirtualizerProps<O>) {
|
|
40
|
-
let {children, layout, layoutOptions} = props;
|
|
54
|
+
let {children, layout: layoutProp, layoutOptions} = props;
|
|
55
|
+
let layout = useMemo(() => typeof layoutProp === 'function' ? new layoutProp() : layoutProp, [layoutProp]);
|
|
41
56
|
let renderer: CollectionRenderer = useMemo(() => ({
|
|
42
57
|
isVirtualized: true,
|
|
43
58
|
layoutDelegate: layout,
|