react-aria-components 1.12.2 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Autocomplete.main.js +3 -3
- package/dist/Autocomplete.main.js.map +1 -1
- package/dist/Autocomplete.mjs +3 -3
- package/dist/Autocomplete.module.js +3 -3
- package/dist/Autocomplete.module.js.map +1 -1
- package/dist/Button.main.js +5 -11
- package/dist/Button.main.js.map +1 -1
- package/dist/Button.mjs +5 -11
- package/dist/Button.module.js +5 -11
- package/dist/Button.module.js.map +1 -1
- package/dist/DateField.main.js +12 -8
- package/dist/DateField.main.js.map +1 -1
- package/dist/DateField.mjs +12 -8
- package/dist/DateField.module.js +12 -8
- package/dist/DateField.module.js.map +1 -1
- package/dist/DatePicker.main.js +6 -2
- package/dist/DatePicker.main.js.map +1 -1
- package/dist/DatePicker.mjs +6 -2
- package/dist/DatePicker.module.js +6 -2
- package/dist/DatePicker.module.js.map +1 -1
- package/dist/GridList.main.js +24 -21
- package/dist/GridList.main.js.map +1 -1
- package/dist/GridList.mjs +25 -23
- package/dist/GridList.module.js +25 -23
- package/dist/GridList.module.js.map +1 -1
- package/dist/Group.main.js +3 -2
- package/dist/Group.main.js.map +1 -1
- package/dist/Group.mjs +3 -2
- package/dist/Group.module.js +3 -2
- package/dist/Group.module.js.map +1 -1
- package/dist/Input.main.js.map +1 -1
- package/dist/Input.module.js.map +1 -1
- package/dist/ListBox.main.js +14 -4
- package/dist/ListBox.main.js.map +1 -1
- package/dist/ListBox.mjs +14 -4
- package/dist/ListBox.module.js +14 -4
- package/dist/ListBox.module.js.map +1 -1
- package/dist/Menu.main.js +16 -6
- package/dist/Menu.main.js.map +1 -1
- package/dist/Menu.mjs +16 -6
- package/dist/Menu.module.js +16 -6
- package/dist/Menu.module.js.map +1 -1
- package/dist/Modal.main.js +9 -1
- package/dist/Modal.main.js.map +1 -1
- package/dist/Modal.mjs +10 -2
- package/dist/Modal.module.js +10 -2
- package/dist/Modal.module.js.map +1 -1
- package/dist/NumberField.main.js +2 -1
- package/dist/NumberField.main.js.map +1 -1
- package/dist/NumberField.mjs +2 -1
- package/dist/NumberField.module.js +2 -1
- package/dist/NumberField.module.js.map +1 -1
- package/dist/ProgressBar.main.js.map +1 -1
- package/dist/ProgressBar.module.js.map +1 -1
- package/dist/RSPContexts.main.js +4 -0
- package/dist/RSPContexts.main.js.map +1 -1
- package/dist/RSPContexts.mjs +3 -1
- package/dist/RSPContexts.module.js +3 -1
- package/dist/RSPContexts.module.js.map +1 -1
- package/dist/RadioGroup.main.js +10 -2
- package/dist/RadioGroup.main.js.map +1 -1
- package/dist/RadioGroup.mjs +10 -2
- package/dist/RadioGroup.module.js +10 -2
- package/dist/RadioGroup.module.js.map +1 -1
- package/dist/SearchField.main.js +2 -2
- package/dist/SearchField.main.js.map +1 -1
- package/dist/SearchField.mjs +2 -2
- package/dist/SearchField.module.js +2 -2
- package/dist/SearchField.module.js.map +1 -1
- package/dist/Select.main.js +62 -22
- package/dist/Select.main.js.map +1 -1
- package/dist/Select.mjs +65 -25
- package/dist/Select.module.js +65 -25
- package/dist/Select.module.js.map +1 -1
- package/dist/SelectionIndicator.main.js +45 -0
- package/dist/SelectionIndicator.main.js.map +1 -0
- package/dist/SelectionIndicator.mjs +35 -0
- package/dist/SelectionIndicator.module.js +35 -0
- package/dist/SelectionIndicator.module.js.map +1 -0
- package/dist/SharedElementTransition.main.js +139 -0
- package/dist/SharedElementTransition.main.js.map +1 -0
- package/dist/SharedElementTransition.mjs +129 -0
- package/dist/SharedElementTransition.module.js +129 -0
- package/dist/SharedElementTransition.module.js.map +1 -0
- package/dist/Table.main.js +16 -11
- package/dist/Table.main.js.map +1 -1
- package/dist/Table.mjs +17 -12
- package/dist/Table.module.js +17 -12
- package/dist/Table.module.js.map +1 -1
- package/dist/Tabs.main.js +11 -3
- package/dist/Tabs.main.js.map +1 -1
- package/dist/Tabs.mjs +11 -3
- package/dist/Tabs.module.js +11 -3
- package/dist/Tabs.module.js.map +1 -1
- package/dist/TagGroup.main.js +28 -16
- package/dist/TagGroup.main.js.map +1 -1
- package/dist/TagGroup.mjs +28 -16
- package/dist/TagGroup.module.js +28 -16
- package/dist/TagGroup.module.js.map +1 -1
- package/dist/TextField.main.js +2 -2
- package/dist/TextField.main.js.map +1 -1
- package/dist/TextField.mjs +2 -2
- package/dist/TextField.module.js +2 -2
- package/dist/TextField.module.js.map +1 -1
- package/dist/ToggleButton.main.js +7 -1
- package/dist/ToggleButton.main.js.map +1 -1
- package/dist/ToggleButton.mjs +7 -1
- package/dist/ToggleButton.module.js +7 -1
- package/dist/ToggleButton.module.js.map +1 -1
- package/dist/ToggleButtonGroup.main.js +3 -1
- package/dist/ToggleButtonGroup.main.js.map +1 -1
- package/dist/ToggleButtonGroup.mjs +3 -1
- package/dist/ToggleButtonGroup.module.js +3 -1
- package/dist/ToggleButtonGroup.module.js.map +1 -1
- package/dist/Tree.main.js +16 -4
- package/dist/Tree.main.js.map +1 -1
- package/dist/Tree.mjs +16 -4
- package/dist/Tree.module.js +16 -4
- package/dist/Tree.module.js.map +1 -1
- package/dist/import.mjs +10 -4
- package/dist/main.js +18 -3
- package/dist/main.js.map +1 -1
- package/dist/module.js +10 -4
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +99 -24
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.main.js.map +1 -1
- package/dist/utils.module.js.map +1 -1
- package/package.json +23 -23
- package/src/Autocomplete.tsx +1 -1
- package/src/Button.tsx +9 -11
- package/src/DateField.tsx +21 -12
- package/src/DatePicker.tsx +11 -2
- package/src/GridList.tsx +32 -33
- package/src/Group.tsx +5 -2
- package/src/Input.tsx +7 -1
- package/src/ListBox.tsx +12 -7
- package/src/Menu.tsx +11 -6
- package/src/Modal.tsx +11 -2
- package/src/NumberField.tsx +1 -1
- package/src/ProgressBar.tsx +1 -1
- package/src/RSPContexts.ts +19 -0
- package/src/RadioGroup.tsx +8 -2
- package/src/SearchField.tsx +1 -1
- package/src/Select.tsx +75 -34
- package/src/SelectionIndicator.tsx +40 -0
- package/src/SharedElementTransition.tsx +185 -0
- package/src/Table.tsx +17 -16
- package/src/Tabs.tsx +8 -2
- package/src/TagGroup.tsx +31 -24
- package/src/TextField.tsx +1 -1
- package/src/ToggleButton.tsx +6 -1
- package/src/ToggleButtonGroup.tsx +4 -1
- package/src/Tree.tsx +16 -9
- package/src/index.ts +10 -3
- package/src/utils.tsx +1 -1
- package/dist/context.main.js +0 -25
- package/dist/context.main.js.map +0 -1
- package/dist/context.mjs +0 -19
- package/dist/context.module.js +0 -19
- package/dist/context.module.js.map +0 -1
- package/src/context.tsx +0 -34
package/src/Select.tsx
CHANGED
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {AriaSelectProps, HiddenSelect, useFocusRing, useLocalizedStringFormatter, useSelect} from 'react-aria';
|
|
13
|
+
import {AriaSelectProps, HiddenSelect, useFocusRing, useListFormatter, useLocalizedStringFormatter, useSelect} from 'react-aria';
|
|
14
14
|
import {ButtonContext} from './Button';
|
|
15
15
|
import {Collection, Node, SelectState, useSelectState} from 'react-stately';
|
|
16
|
-
import {CollectionBuilder} from '@react-aria/collections';
|
|
16
|
+
import {CollectionBuilder, createHideableComponent} from '@react-aria/collections';
|
|
17
17
|
import {ContextValue, Provider, RACValidation, removeDataAttributes, RenderProps, SlotProps, useContextProps, useRenderProps, useSlot, useSlottedContext} from './utils';
|
|
18
18
|
import {FieldErrorContext} from './FieldError';
|
|
19
19
|
import {filterDOMProps, mergeProps, useResizeObserver} from '@react-aria/utils';
|
|
@@ -26,9 +26,11 @@ import {LabelContext} from './Label';
|
|
|
26
26
|
import {ListBoxContext, ListStateContext} from './ListBox';
|
|
27
27
|
import {OverlayTriggerStateContext} from './Dialog';
|
|
28
28
|
import {PopoverContext} from './Popover';
|
|
29
|
-
import React, {createContext, ForwardedRef, forwardRef, HTMLAttributes, ReactNode, useCallback, useContext, useMemo, useRef, useState} from 'react';
|
|
29
|
+
import React, {createContext, ForwardedRef, forwardRef, Fragment, HTMLAttributes, ReactNode, useCallback, useContext, useMemo, useRef, useState} from 'react';
|
|
30
30
|
import {TextContext} from './Text';
|
|
31
31
|
|
|
32
|
+
type SelectionMode = 'single' | 'multiple';
|
|
33
|
+
|
|
32
34
|
export interface SelectRenderProps {
|
|
33
35
|
/**
|
|
34
36
|
* Whether the select is focused, either via a mouse or keyboard.
|
|
@@ -62,7 +64,7 @@ export interface SelectRenderProps {
|
|
|
62
64
|
isRequired: boolean
|
|
63
65
|
}
|
|
64
66
|
|
|
65
|
-
export interface SelectProps<T extends object = {}> extends Omit<AriaSelectProps<T>, 'children' | 'label' | 'description' | 'errorMessage' | 'validationState' | 'validationBehavior' | 'items'>, RACValidation, RenderProps<SelectRenderProps>, SlotProps, GlobalDOMAttributes<HTMLDivElement> {
|
|
67
|
+
export interface SelectProps<T extends object = {}, M extends SelectionMode = 'single'> extends Omit<AriaSelectProps<T, M>, 'children' | 'label' | 'description' | 'errorMessage' | 'validationState' | 'validationBehavior' | 'items'>, RACValidation, RenderProps<SelectRenderProps>, SlotProps, GlobalDOMAttributes<HTMLDivElement> {
|
|
66
68
|
/**
|
|
67
69
|
* Temporary text that occupies the select when it is empty.
|
|
68
70
|
* @default 'Select an item' (localized)
|
|
@@ -70,13 +72,13 @@ export interface SelectProps<T extends object = {}> extends Omit<AriaSelectProps
|
|
|
70
72
|
placeholder?: string
|
|
71
73
|
}
|
|
72
74
|
|
|
73
|
-
export const SelectContext = createContext<ContextValue<SelectProps<any>, HTMLDivElement>>(null);
|
|
74
|
-
export const SelectStateContext = createContext<SelectState<unknown> | null>(null);
|
|
75
|
+
export const SelectContext = createContext<ContextValue<SelectProps<any, SelectionMode>, HTMLDivElement>>(null);
|
|
76
|
+
export const SelectStateContext = createContext<SelectState<unknown, SelectionMode> | null>(null);
|
|
75
77
|
|
|
76
78
|
/**
|
|
77
79
|
* A select displays a collapsible list of options and allows a user to select one of them.
|
|
78
80
|
*/
|
|
79
|
-
export const Select = /*#__PURE__*/ (forwardRef as forwardRefType)(function Select<T extends object = {}>(props: SelectProps<T>, ref: ForwardedRef<HTMLDivElement>) {
|
|
81
|
+
export const Select = /*#__PURE__*/ (forwardRef as forwardRefType)(function Select<T extends object = {}, M extends SelectionMode = 'single'>(props: SelectProps<T, M>, ref: ForwardedRef<HTMLDivElement>) {
|
|
80
82
|
[props, ref] = useContextProps(props, ref, SelectContext);
|
|
81
83
|
let {children, isDisabled = false, isInvalid = false, isRequired = false} = props;
|
|
82
84
|
let content = useMemo(() => (
|
|
@@ -104,7 +106,7 @@ export const Select = /*#__PURE__*/ (forwardRef as forwardRefType)(function Sele
|
|
|
104
106
|
const CLEAR_CONTEXTS = [LabelContext, ButtonContext, TextContext];
|
|
105
107
|
|
|
106
108
|
interface SelectInnerProps<T extends object> {
|
|
107
|
-
props: SelectProps<T>,
|
|
109
|
+
props: SelectProps<T, SelectionMode>,
|
|
108
110
|
selectRef: ForwardedRef<HTMLDivElement>,
|
|
109
111
|
collection: Collection<Node<T>>
|
|
110
112
|
}
|
|
@@ -228,10 +230,17 @@ export interface SelectValueRenderProps<T> {
|
|
|
228
230
|
* @selector [data-placeholder]
|
|
229
231
|
*/
|
|
230
232
|
isPlaceholder: boolean,
|
|
231
|
-
/**
|
|
233
|
+
/**
|
|
234
|
+
* The object value of the first selected item.
|
|
235
|
+
* @deprecated
|
|
236
|
+
*/
|
|
232
237
|
selectedItem: T | null,
|
|
233
|
-
/** The
|
|
234
|
-
|
|
238
|
+
/** The object values of the currently selected items. */
|
|
239
|
+
selectedItems: (T | null)[],
|
|
240
|
+
/** The textValue of the currently selected items. */
|
|
241
|
+
selectedText: string,
|
|
242
|
+
/** The state of the select. */
|
|
243
|
+
state: SelectState<T, 'single' | 'multiple'>
|
|
235
244
|
}
|
|
236
245
|
|
|
237
246
|
export interface SelectValueProps<T extends object> extends Omit<HTMLAttributes<HTMLElement>, keyof RenderProps<unknown>>, RenderProps<SelectValueRenderProps<T>> {}
|
|
@@ -242,46 +251,78 @@ export const SelectValueContext = createContext<ContextValue<SelectValueProps<an
|
|
|
242
251
|
* SelectValue renders the current value of a Select, or a placeholder if no value is selected.
|
|
243
252
|
* It is usually placed within the button element.
|
|
244
253
|
*/
|
|
245
|
-
export const SelectValue = /*#__PURE__*/ (
|
|
254
|
+
export const SelectValue = /*#__PURE__*/ createHideableComponent(function SelectValue<T extends object>(props: SelectValueProps<T>, ref: ForwardedRef<HTMLSpanElement>) {
|
|
246
255
|
[props, ref] = useContextProps(props, ref, SelectValueContext);
|
|
247
|
-
let state = useContext(SelectStateContext)
|
|
256
|
+
let state = useContext(SelectStateContext)! as SelectState<T, 'single' | 'multiple'>;
|
|
248
257
|
let {placeholder} = useSlottedContext(SelectContext)!;
|
|
249
|
-
let
|
|
250
|
-
|
|
251
|
-
: null;
|
|
252
|
-
let rendered = selectedItem?.props.children;
|
|
253
|
-
if (typeof rendered === 'function') {
|
|
258
|
+
let rendered = state.selectedItems.map((item) => {
|
|
259
|
+
let rendered = item.props?.children;
|
|
254
260
|
// If the selected item has a function as a child, we need to call it to render to React.JSX.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
261
|
+
if (typeof rendered === 'function') {
|
|
262
|
+
let fn = rendered as (s: ItemRenderProps) => ReactNode;
|
|
263
|
+
rendered = fn({
|
|
264
|
+
isHovered: false,
|
|
265
|
+
isPressed: false,
|
|
266
|
+
isSelected: false,
|
|
267
|
+
isFocused: false,
|
|
268
|
+
isFocusVisible: false,
|
|
269
|
+
isDisabled: false,
|
|
270
|
+
selectionMode: 'single',
|
|
271
|
+
selectionBehavior: 'toggle'
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return rendered;
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
let formatter = useListFormatter();
|
|
279
|
+
let textValue = useMemo(() => state.selectedItems.map(item => item?.textValue), [state.selectedItems]);
|
|
280
|
+
let selectionMode = state.selectionManager.selectionMode;
|
|
281
|
+
let selectedText = useMemo(() => (
|
|
282
|
+
selectionMode === 'single'
|
|
283
|
+
? textValue[0] ?? ''
|
|
284
|
+
: formatter.format(textValue)
|
|
285
|
+
), [selectionMode, formatter, textValue]);
|
|
286
|
+
|
|
287
|
+
let defaultChildren = useMemo(() => {
|
|
288
|
+
if (selectionMode === 'single') {
|
|
289
|
+
return rendered[0];
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
let parts = formatter.formatToParts(textValue);
|
|
293
|
+
if (parts.length === 0) {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
let index = 0;
|
|
298
|
+
return parts.map(part => {
|
|
299
|
+
if (part.type === 'element') {
|
|
300
|
+
return <Fragment key={index}>{rendered[index++]}</Fragment>;
|
|
301
|
+
} else {
|
|
302
|
+
return part.value;
|
|
303
|
+
}
|
|
265
304
|
});
|
|
266
|
-
}
|
|
305
|
+
}, [selectionMode, formatter, textValue, rendered]);
|
|
267
306
|
|
|
268
307
|
let stringFormatter = useLocalizedStringFormatter(intlMessages, 'react-aria-components');
|
|
269
308
|
|
|
270
309
|
let renderProps = useRenderProps({
|
|
271
310
|
...props,
|
|
272
|
-
defaultChildren:
|
|
311
|
+
defaultChildren: defaultChildren ?? placeholder ?? stringFormatter.format('selectPlaceholder'),
|
|
273
312
|
defaultClassName: 'react-aria-SelectValue',
|
|
274
313
|
values: {
|
|
275
|
-
selectedItem: state.
|
|
276
|
-
|
|
277
|
-
|
|
314
|
+
selectedItem: state.selectedItems[0]?.value as T ?? null,
|
|
315
|
+
selectedItems: useMemo(() => state.selectedItems.map(item => item.value as T ?? null), [state.selectedItems]),
|
|
316
|
+
selectedText,
|
|
317
|
+
isPlaceholder: state.selectedItems.length === 0,
|
|
318
|
+
state
|
|
278
319
|
}
|
|
279
320
|
});
|
|
280
321
|
|
|
281
322
|
let DOMProps = filterDOMProps(props, {global: true});
|
|
282
323
|
|
|
283
324
|
return (
|
|
284
|
-
<span ref={ref} {...DOMProps} {...renderProps} data-placeholder={
|
|
325
|
+
<span ref={ref} {...DOMProps} {...renderProps} data-placeholder={state.selectedItems.length === 0 || undefined}>
|
|
285
326
|
{/* clear description and error message slots */}
|
|
286
327
|
<TextContext.Provider value={undefined}>
|
|
287
328
|
{renderProps.children}
|
|
@@ -0,0 +1,40 @@
|
|
|
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 {ContextValue, useContextProps} from './utils';
|
|
14
|
+
import React, {createContext, ForwardedRef, forwardRef} from 'react';
|
|
15
|
+
import {SharedElement, SharedElementPropsBase} from './SharedElementTransition';
|
|
16
|
+
|
|
17
|
+
export interface SelectionIndicatorProps extends SharedElementPropsBase {
|
|
18
|
+
isSelected?: boolean
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const SelectionIndicatorContext = createContext<ContextValue<SelectionIndicatorProps, HTMLDivElement>>({
|
|
22
|
+
isSelected: false
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* An animated indicator of selection state within a group of items.
|
|
28
|
+
*/
|
|
29
|
+
export const SelectionIndicator = forwardRef(function SelectionIndicator(props: SelectionIndicatorProps, ref: ForwardedRef<HTMLDivElement>) {
|
|
30
|
+
[props, ref] = useContextProps(props, ref, SelectionIndicatorContext);
|
|
31
|
+
let {isSelected, ...otherProps} = props;
|
|
32
|
+
return (
|
|
33
|
+
<SharedElement
|
|
34
|
+
{...otherProps}
|
|
35
|
+
ref={ref}
|
|
36
|
+
className={props.className || 'react-aria-SelectionIndicator'}
|
|
37
|
+
name="SelectionIndicator"
|
|
38
|
+
isVisible={isSelected} />
|
|
39
|
+
);
|
|
40
|
+
});
|
|
@@ -0,0 +1,185 @@
|
|
|
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 {flushSync} from 'react-dom';
|
|
14
|
+
import React, {createContext, ForwardedRef, forwardRef, HTMLAttributes, ReactNode, RefObject, useContext, useRef, useState} from 'react';
|
|
15
|
+
import {RenderProps, useRenderProps} from './utils';
|
|
16
|
+
import {useLayoutEffect} from '@react-aria/utils';
|
|
17
|
+
import {useObjectRef} from 'react-aria';
|
|
18
|
+
|
|
19
|
+
interface Snapshot {
|
|
20
|
+
rect: DOMRect,
|
|
21
|
+
style: [string, string][]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const SharedElementContext = createContext<RefObject<{[name: string]: Snapshot}> | null>(null);
|
|
25
|
+
|
|
26
|
+
export interface SharedElementTransitionProps {
|
|
27
|
+
children: ReactNode
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A scope for SharedElements, which animate between parents.
|
|
32
|
+
*/
|
|
33
|
+
export function SharedElementTransition(props: SharedElementTransitionProps) {
|
|
34
|
+
let ref = useRef({});
|
|
35
|
+
return (
|
|
36
|
+
<SharedElementContext.Provider value={ref}>
|
|
37
|
+
{props.children}
|
|
38
|
+
</SharedElementContext.Provider>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface SharedElementRenderProps {
|
|
43
|
+
/**
|
|
44
|
+
* Whether the element is currently entering.
|
|
45
|
+
* @selector [data-entering]
|
|
46
|
+
*/
|
|
47
|
+
isEntering: boolean,
|
|
48
|
+
/**
|
|
49
|
+
* Whether the element is currently exiting.
|
|
50
|
+
* @selector [data-exiting]
|
|
51
|
+
*/
|
|
52
|
+
isExiting: boolean
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface SharedElementPropsBase extends Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'className' | 'style'>, RenderProps<SharedElementRenderProps> {}
|
|
56
|
+
|
|
57
|
+
export interface SharedElementProps extends SharedElementPropsBase {
|
|
58
|
+
name: string,
|
|
59
|
+
isVisible?: boolean
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* An element that animates between its old and new position when moving between parents.
|
|
64
|
+
*/
|
|
65
|
+
export const SharedElement = forwardRef(function SharedElement(props: SharedElementProps, ref: ForwardedRef<HTMLDivElement>) {
|
|
66
|
+
let {name, isVisible = true, children, className, style, ...divProps} = props;
|
|
67
|
+
let [state, setState] = useState(isVisible ? 'visible' : 'hidden');
|
|
68
|
+
let scopeRef = useContext(SharedElementContext);
|
|
69
|
+
if (!scopeRef) {
|
|
70
|
+
throw new Error('<SharedElement> must be rendered inside a <SharedElementTransition>');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (isVisible && state === 'hidden') {
|
|
74
|
+
setState('visible');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
ref = useObjectRef(ref);
|
|
78
|
+
useLayoutEffect(() => {
|
|
79
|
+
let element = ref.current;
|
|
80
|
+
let scope = scopeRef.current;
|
|
81
|
+
let prevSnapshot = scope[name];
|
|
82
|
+
let frame: number | null = null;
|
|
83
|
+
|
|
84
|
+
if (element && isVisible && prevSnapshot) {
|
|
85
|
+
// Element is transitioning from a previous instance.
|
|
86
|
+
setState('visible');
|
|
87
|
+
let animations = element.getAnimations();
|
|
88
|
+
|
|
89
|
+
// Set properties to animate from.
|
|
90
|
+
let values = prevSnapshot.style.map(([property, prevValue]) => {
|
|
91
|
+
let value = element.style[property];
|
|
92
|
+
if (property === 'translate') {
|
|
93
|
+
let prevRect = prevSnapshot.rect;
|
|
94
|
+
let currentItem = element.getBoundingClientRect();
|
|
95
|
+
let deltaX = prevRect.left - currentItem?.left;
|
|
96
|
+
let deltaY = prevRect.top - currentItem?.top;
|
|
97
|
+
element.style.translate = `${deltaX}px ${deltaY}px`;
|
|
98
|
+
} else {
|
|
99
|
+
element.style[property] = prevValue;
|
|
100
|
+
}
|
|
101
|
+
return [property, value];
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Cancel any new animations triggered by these properties.
|
|
105
|
+
for (let a of element.getAnimations()) {
|
|
106
|
+
if (!animations.includes(a)) {
|
|
107
|
+
a.cancel();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Remove overrides after one frame to animate to the current values.
|
|
112
|
+
frame = requestAnimationFrame(() => {
|
|
113
|
+
frame = null;
|
|
114
|
+
for (let [property, value] of values) {
|
|
115
|
+
element.style[property] = value;
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
delete scope[name];
|
|
120
|
+
} else if (element && isVisible && !prevSnapshot) {
|
|
121
|
+
// No previous instance exists, apply the entering state.
|
|
122
|
+
queueMicrotask(() => flushSync(() => setState('entering')));
|
|
123
|
+
frame = requestAnimationFrame(() => {
|
|
124
|
+
frame = null;
|
|
125
|
+
setState('visible');
|
|
126
|
+
});
|
|
127
|
+
} else if (element && !isVisible) {
|
|
128
|
+
// Wait until layout effects finish, and check if a snapshot still exists.
|
|
129
|
+
// If so, no new SharedElement consumed it, so enter the exiting state.
|
|
130
|
+
queueMicrotask(() => {
|
|
131
|
+
if (scope[name]) {
|
|
132
|
+
delete scope[name];
|
|
133
|
+
flushSync(() => setState('exiting'));
|
|
134
|
+
Promise.all(element.getAnimations().map(a => a.finished))
|
|
135
|
+
.then(() => setState('hidden'))
|
|
136
|
+
.catch(() => {});
|
|
137
|
+
} else {
|
|
138
|
+
// Snapshot was consumed by another instance, unmount.
|
|
139
|
+
setState('hidden');
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return () => {
|
|
145
|
+
if (frame != null) {
|
|
146
|
+
cancelAnimationFrame(frame);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (element && element.isConnected && !element.hasAttribute('data-exiting')) {
|
|
150
|
+
// On unmount, store a snapshot of the rectangle and computed style for transitioning properties.
|
|
151
|
+
let style = window.getComputedStyle(element);
|
|
152
|
+
if (style.transitionProperty !== 'none') {
|
|
153
|
+
let transitionProperty = style.transitionProperty.split(/\s*,\s*/);
|
|
154
|
+
scope[name] = {
|
|
155
|
+
rect: element.getBoundingClientRect(),
|
|
156
|
+
style: transitionProperty.map(p => [p, style[p]])
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
}, [ref, scopeRef, name, isVisible]);
|
|
162
|
+
|
|
163
|
+
let renderProps = useRenderProps({
|
|
164
|
+
children,
|
|
165
|
+
className,
|
|
166
|
+
style,
|
|
167
|
+
values: {
|
|
168
|
+
isEntering: state === 'entering',
|
|
169
|
+
isExiting: state === 'exiting'
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
if (state === 'hidden') {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return (
|
|
178
|
+
<div
|
|
179
|
+
{...divProps}
|
|
180
|
+
{...renderProps}
|
|
181
|
+
ref={ref}
|
|
182
|
+
data-entering={state === 'entering' || undefined}
|
|
183
|
+
data-exiting={state === 'exiting' || undefined} />
|
|
184
|
+
);
|
|
185
|
+
});
|
package/src/Table.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import {AriaLabelingProps, GlobalDOMAttributes, HoverEvents, Key, LinkDOMProps,
|
|
|
2
2
|
import {BaseCollection, Collection, CollectionBuilder, CollectionNode, createBranchComponent, createLeafComponent, FilterableNode, LoaderNode, useCachedChildren} from '@react-aria/collections';
|
|
3
3
|
import {buildHeaderRows, TableColumnResizeState} from '@react-stately/table';
|
|
4
4
|
import {ButtonContext} from './Button';
|
|
5
|
-
import {CheckboxContext} from './RSPContexts';
|
|
5
|
+
import {CheckboxContext, FieldInputContext, SelectableCollectionContext, SelectableCollectionContextValue} from './RSPContexts';
|
|
6
6
|
import {CollectionProps, CollectionRendererContext, DefaultCollectionRenderer, ItemRenderProps} from './Collection';
|
|
7
7
|
import {ColumnSize, ColumnStaticSize, TableCollection as ITableCollection, TableProps as SharedTableProps} from '@react-types/table';
|
|
8
8
|
import {ContextValue, DEFAULT_SLOT, DOMProps, Provider, RenderProps, SlotProps, StyleProps, StyleRenderProps, useContextProps, useRenderProps} from './utils';
|
|
@@ -10,13 +10,14 @@ import {DisabledBehavior, DraggableCollectionState, DroppableCollectionState, Mu
|
|
|
10
10
|
import {DragAndDropContext, DropIndicatorContext, DropIndicatorProps, useDndPersistedKeys, useRenderDropIndicator} from './DragAndDrop';
|
|
11
11
|
import {DragAndDropHooks} from './useDragAndDrop';
|
|
12
12
|
import {DraggableItemResult, DragPreviewRenderer, DropIndicatorAria, DroppableCollectionResult, FocusScope, ListKeyboardDelegate, mergeProps, useFocusRing, useHover, useLocale, useLocalizedStringFormatter, useTable, useTableCell, useTableColumnHeader, useTableColumnResize, useTableHeaderRow, useTableRow, useTableRowGroup, useTableSelectAllCheckbox, useTableSelectionCheckbox, useVisuallyHidden} from 'react-aria';
|
|
13
|
-
import {FieldInputContext, SelectableCollectionContext} from './context';
|
|
14
13
|
import {filterDOMProps, inertValue, isScrollable, LoadMoreSentinelProps, mergeRefs, useLayoutEffect, useLoadMoreSentinel, useObjectRef, useResizeObserver} from '@react-aria/utils';
|
|
15
14
|
import {GridNode} from '@react-types/grid';
|
|
16
15
|
// @ts-ignore
|
|
17
16
|
import intlMessages from '../intl/*.json';
|
|
18
17
|
import React, {createContext, ForwardedRef, forwardRef, JSX, ReactElement, ReactNode, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
|
|
19
18
|
import ReactDOM from 'react-dom';
|
|
19
|
+
import {SelectionIndicatorContext} from './SelectionIndicator';
|
|
20
|
+
import {SharedElementTransition} from './SharedElementTransition';
|
|
20
21
|
|
|
21
22
|
class TableCollection<T> extends BaseCollection<T> implements ITableCollection<T> {
|
|
22
23
|
headerRows: GridNode<T>[] = [];
|
|
@@ -355,23 +356,21 @@ export const Table = forwardRef(function Table(props: TableProps, ref: Forwarded
|
|
|
355
356
|
});
|
|
356
357
|
|
|
357
358
|
interface TableInnerProps {
|
|
358
|
-
props: TableProps
|
|
359
|
-
forwardedRef: ForwardedRef<
|
|
359
|
+
props: TableProps & SelectableCollectionContextValue<unknown>,
|
|
360
|
+
forwardedRef: ForwardedRef<HTMLElement>,
|
|
360
361
|
selectionState: MultipleSelectionState,
|
|
361
362
|
collection: ITableCollection<Node<object>>
|
|
362
363
|
}
|
|
363
364
|
|
|
364
365
|
|
|
365
366
|
function TableInner({props, forwardedRef: ref, selectionState, collection}: TableInnerProps) {
|
|
366
|
-
|
|
367
|
-
[contextProps] = useContextProps({}, null, SelectableCollectionContext);
|
|
368
|
-
let {filter, ...collectionProps} = contextProps;
|
|
367
|
+
[props, ref] = useContextProps(props, ref, SelectableCollectionContext);
|
|
369
368
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
370
|
-
let {shouldUseVirtualFocus, disallowTypeAhead, ...DOMCollectionProps} =
|
|
369
|
+
let {shouldUseVirtualFocus, disallowTypeAhead, filter, ...DOMCollectionProps} = props;
|
|
371
370
|
let tableContainerContext = useContext(ResizableTableContainerContext);
|
|
372
371
|
ref = useObjectRef(useMemo(() => mergeRefs(ref, tableContainerContext?.tableRef), [ref, tableContainerContext?.tableRef]));
|
|
373
372
|
let tableState = useTableState({
|
|
374
|
-
...
|
|
373
|
+
...DOMCollectionProps,
|
|
375
374
|
collection,
|
|
376
375
|
children: undefined,
|
|
377
376
|
UNSAFE_selectionState: selectionState
|
|
@@ -381,7 +380,6 @@ function TableInner({props, forwardedRef: ref, selectionState, collection}: Tabl
|
|
|
381
380
|
let {isVirtualized, layoutDelegate, dropTargetDelegate: ctxDropTargetDelegate, CollectionRoot} = useContext(CollectionRendererContext);
|
|
382
381
|
let {dragAndDropHooks} = props;
|
|
383
382
|
let {gridProps} = useTable({
|
|
384
|
-
...props,
|
|
385
383
|
...DOMCollectionProps,
|
|
386
384
|
layoutDelegate,
|
|
387
385
|
isVirtualized
|
|
@@ -493,17 +491,19 @@ function TableInner({props, forwardedRef: ref, selectionState, collection}: Tabl
|
|
|
493
491
|
<ElementType
|
|
494
492
|
{...mergeProps(DOMProps, renderProps, gridProps, focusProps, droppableCollection?.collectionProps)}
|
|
495
493
|
style={style}
|
|
496
|
-
ref={ref}
|
|
494
|
+
ref={ref as RefObject<HTMLTableElement>}
|
|
497
495
|
slot={props.slot || undefined}
|
|
498
496
|
onScroll={props.onScroll}
|
|
499
497
|
data-allows-dragging={isListDraggable || undefined}
|
|
500
498
|
data-drop-target={isRootDropTarget || undefined}
|
|
501
499
|
data-focused={isFocused || undefined}
|
|
502
500
|
data-focus-visible={isFocusVisible || undefined}>
|
|
503
|
-
<
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
501
|
+
<SharedElementTransition>
|
|
502
|
+
<CollectionRoot
|
|
503
|
+
collection={filteredState.collection}
|
|
504
|
+
scrollRef={tableContainerContext?.scrollRef ?? ref}
|
|
505
|
+
persistedKeys={useDndPersistedKeys(selectionManager, dragAndDropHooks, dropState)} />
|
|
506
|
+
</SharedElementTransition>
|
|
507
507
|
</ElementType>
|
|
508
508
|
</FocusScope>
|
|
509
509
|
{dragPreview}
|
|
@@ -1182,7 +1182,8 @@ export const Row = /*#__PURE__*/ createBranchComponent(
|
|
|
1182
1182
|
}
|
|
1183
1183
|
}
|
|
1184
1184
|
}
|
|
1185
|
-
}]
|
|
1185
|
+
}],
|
|
1186
|
+
[SelectionIndicatorContext, {isSelected: states.isSelected}]
|
|
1186
1187
|
]}>
|
|
1187
1188
|
<CollectionBranch collection={state.collection} parent={item} />
|
|
1188
1189
|
</Provider>
|
package/src/Tabs.tsx
CHANGED
|
@@ -18,6 +18,8 @@ import {ContextValue, Provider, RenderProps, SlotProps, StyleRenderProps, useCon
|
|
|
18
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
|
+
import {SelectionIndicatorContext} from './SelectionIndicator';
|
|
22
|
+
import {SharedElementTransition} from './SharedElementTransition';
|
|
21
23
|
|
|
22
24
|
export interface TabsProps extends Omit<AriaTabListProps<any>, 'items' | 'children'>, RenderProps<TabsRenderProps>, SlotProps, GlobalDOMAttributes<HTMLDivElement> {}
|
|
23
25
|
|
|
@@ -230,7 +232,9 @@ function TabListInner<T extends object>({props, forwardedRef: ref}: TabListInner
|
|
|
230
232
|
{...mergeProps(DOMProps, renderProps, tabListProps)}
|
|
231
233
|
ref={objectRef}
|
|
232
234
|
data-orientation={orientation || undefined}>
|
|
233
|
-
<
|
|
235
|
+
<SharedElementTransition>
|
|
236
|
+
<CollectionRoot collection={state.collection} persistedKeys={usePersistedKeys(state.selectionManager.focusedKey)} />
|
|
237
|
+
</SharedElementTransition>
|
|
234
238
|
</div>
|
|
235
239
|
);
|
|
236
240
|
}
|
|
@@ -284,7 +288,9 @@ export const Tab = /*#__PURE__*/ createLeafComponent(TabItemNode, (props: TabPro
|
|
|
284
288
|
data-focus-visible={isFocusVisible || undefined}
|
|
285
289
|
data-pressed={isPressed || undefined}
|
|
286
290
|
data-hovered={isHovered || undefined}>
|
|
287
|
-
{
|
|
291
|
+
<SelectionIndicatorContext.Provider value={{isSelected}}>
|
|
292
|
+
{renderProps.children}
|
|
293
|
+
</SelectionIndicatorContext.Provider>
|
|
288
294
|
</ElementType>
|
|
289
295
|
);
|
|
290
296
|
});
|
package/src/TagGroup.tsx
CHANGED
|
@@ -16,12 +16,14 @@ import {Collection, CollectionBuilder, createLeafComponent, ItemNode} from '@rea
|
|
|
16
16
|
import {CollectionProps, CollectionRendererContext, DefaultCollectionRenderer, ItemRenderProps, usePersistedKeys} from './Collection';
|
|
17
17
|
import {ContextValue, DOMProps, Provider, RenderProps, SlotProps, StyleRenderProps, useContextProps, useRenderProps, useSlot} from './utils';
|
|
18
18
|
import {filterDOMProps, mergeProps, useObjectRef} from '@react-aria/utils';
|
|
19
|
-
import {forwardRefType, GlobalDOMAttributes, HoverEvents, Key, LinkDOMProps, PressEvents} from '@react-types/shared';
|
|
19
|
+
import {forwardRefType, GlobalDOMAttributes, HoverEvents, Key, LinkDOMProps, PressEvents, RefObject} from '@react-types/shared';
|
|
20
20
|
import {LabelContext} from './Label';
|
|
21
21
|
import {ListState, Node, UNSTABLE_useFilteredListState, useListState} from 'react-stately';
|
|
22
22
|
import {ListStateContext} from './ListBox';
|
|
23
23
|
import React, {createContext, ForwardedRef, forwardRef, JSX, ReactNode, useContext, useEffect, useRef} from 'react';
|
|
24
|
-
import {SelectableCollectionContext} from './
|
|
24
|
+
import {SelectableCollectionContext, SelectableCollectionContextValue} from './RSPContexts';
|
|
25
|
+
import {SelectionIndicatorContext} from './SelectionIndicator';
|
|
26
|
+
import {SharedElementTransition} from './SharedElementTransition';
|
|
25
27
|
import {TextContext} from './Text';
|
|
26
28
|
|
|
27
29
|
export interface TagGroupProps extends Omit<AriaTagGroupProps<unknown>, 'children' | 'items' | 'label' | 'description' | 'errorMessage' | 'keyboardDelegate'>, DOMProps, SlotProps, GlobalDOMAttributes<HTMLDivElement> {}
|
|
@@ -62,54 +64,56 @@ export const TagListContext = createContext<ContextValue<TagListProps<any>, HTML
|
|
|
62
64
|
export const TagGroup = /*#__PURE__*/ (forwardRef as forwardRefType)(function TagGroup(props: TagGroupProps, ref: ForwardedRef<HTMLDivElement>) {
|
|
63
65
|
[props, ref] = useContextProps(props, ref, TagGroupContext);
|
|
64
66
|
return (
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
<ListStateContext.Provider value={null}>
|
|
68
|
+
<CollectionBuilder content={props.children}>
|
|
69
|
+
{collection => <TagGroupInner props={props} forwardedRef={ref} collection={collection} />}
|
|
70
|
+
</CollectionBuilder>
|
|
71
|
+
</ListStateContext.Provider>
|
|
68
72
|
);
|
|
69
73
|
});
|
|
70
74
|
|
|
71
|
-
interface TagGroupInnerProps {
|
|
72
|
-
props: TagGroupProps
|
|
75
|
+
interface TagGroupInnerProps<T> {
|
|
76
|
+
props: TagGroupProps & SelectableCollectionContextValue<T>,
|
|
73
77
|
forwardedRef: ForwardedRef<HTMLDivElement>,
|
|
74
78
|
collection
|
|
75
79
|
}
|
|
76
80
|
|
|
77
|
-
function TagGroupInner({props, forwardedRef: ref, collection}: TagGroupInnerProps) {
|
|
78
|
-
let
|
|
79
|
-
|
|
80
|
-
let {
|
|
81
|
+
function TagGroupInner<T extends object>({props, forwardedRef: ref, collection}: TagGroupInnerProps<T>) {
|
|
82
|
+
let tagListRef = useRef<HTMLElement>(null);
|
|
83
|
+
// Extract the user provided id so it doesn't clash with the collection id provided by Autocomplete
|
|
84
|
+
let {id, ...otherProps} = props;
|
|
85
|
+
[otherProps, tagListRef] = useContextProps(otherProps, tagListRef, SelectableCollectionContext);
|
|
81
86
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
82
|
-
let {
|
|
83
|
-
let tagListRef = useRef<HTMLDivElement>(null);
|
|
87
|
+
let {filter, shouldUseVirtualFocus, ...DOMCollectionProps} = otherProps;
|
|
84
88
|
let [labelRef, label] = useSlot(
|
|
85
89
|
!props['aria-label'] && !props['aria-labelledby']
|
|
86
90
|
);
|
|
87
91
|
let tagGroupState = useListState({
|
|
88
|
-
...
|
|
92
|
+
...DOMCollectionProps,
|
|
89
93
|
children: undefined,
|
|
90
94
|
collection
|
|
91
95
|
});
|
|
92
96
|
|
|
93
|
-
let filteredState = UNSTABLE_useFilteredListState(tagGroupState
|
|
97
|
+
let filteredState = UNSTABLE_useFilteredListState(tagGroupState as ListState<T>, filter);
|
|
94
98
|
|
|
95
99
|
// Prevent DOM props from going to two places.
|
|
96
|
-
let domProps = filterDOMProps(
|
|
97
|
-
let domPropOverrides = Object.fromEntries(Object.entries(domProps).map(([k]) => [k, undefined]));
|
|
100
|
+
let domProps = filterDOMProps(otherProps, {global: true});
|
|
101
|
+
let domPropOverrides = Object.fromEntries(Object.entries(domProps).map(([k, val]) => [k, k === 'id' ? val : undefined]));
|
|
98
102
|
let {
|
|
99
103
|
gridProps,
|
|
100
104
|
labelProps,
|
|
101
105
|
descriptionProps,
|
|
102
106
|
errorMessageProps
|
|
103
107
|
} = useTagGroup({
|
|
104
|
-
...props,
|
|
105
|
-
...domPropOverrides,
|
|
106
108
|
...DOMCollectionProps,
|
|
109
|
+
...domPropOverrides,
|
|
107
110
|
label
|
|
108
111
|
}, filteredState, tagListRef);
|
|
109
112
|
|
|
110
113
|
return (
|
|
111
114
|
<div
|
|
112
115
|
{...domProps}
|
|
116
|
+
id={id}
|
|
113
117
|
ref={ref}
|
|
114
118
|
slot={props.slot || undefined}
|
|
115
119
|
className={props.className ?? 'react-aria-TagGroup'}
|
|
@@ -117,7 +121,7 @@ function TagGroupInner({props, forwardedRef: ref, collection}: TagGroupInnerProp
|
|
|
117
121
|
<Provider
|
|
118
122
|
values={[
|
|
119
123
|
[LabelContext, {...labelProps, elementType: 'span', ref: labelRef}],
|
|
120
|
-
[TagListContext, {...gridProps, ref: tagListRef}],
|
|
124
|
+
[TagListContext, {...gridProps, ref: tagListRef as RefObject<HTMLDivElement>}],
|
|
121
125
|
[ListStateContext, filteredState],
|
|
122
126
|
[TextContext, {
|
|
123
127
|
slots: {
|
|
@@ -176,9 +180,11 @@ function TagListInner<T extends object>({props, forwardedRef}: TagListInnerProps
|
|
|
176
180
|
data-empty={state.collection.size === 0 || undefined}
|
|
177
181
|
data-focused={isFocused || undefined}
|
|
178
182
|
data-focus-visible={isFocusVisible || undefined}>
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
183
|
+
<SharedElementTransition>
|
|
184
|
+
{state.collection.size === 0 && props.renderEmptyState
|
|
185
|
+
? props.renderEmptyState(renderValues)
|
|
186
|
+
: <CollectionRoot collection={state.collection} persistedKeys={persistedKeys} />}
|
|
187
|
+
</SharedElementTransition>
|
|
182
188
|
</div>
|
|
183
189
|
);
|
|
184
190
|
}
|
|
@@ -263,7 +269,8 @@ export const Tag = /*#__PURE__*/ createLeafComponent(ItemNode, (props: TagProps,
|
|
|
263
269
|
remove: removeButtonProps
|
|
264
270
|
}
|
|
265
271
|
}],
|
|
266
|
-
[CollectionRendererContext, DefaultCollectionRenderer]
|
|
272
|
+
[CollectionRendererContext, DefaultCollectionRenderer],
|
|
273
|
+
[SelectionIndicatorContext, {isSelected: states.isSelected}]
|
|
267
274
|
]}>
|
|
268
275
|
{renderProps.children}
|
|
269
276
|
</Provider>
|