Add async filtering support to the select-control component (#35839)
* Add async filtering support to the select-control component * Apply comment suggestions * Apply more comment suggestions
This commit is contained in:
parent
0a039a1f13
commit
788b3ef59b
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: add
|
||||
|
||||
Add async filtering support to the `__experimentalSelectControl` component
|
|
@ -111,6 +111,7 @@
|
|||
"@testing-library/dom": "^8.11.3",
|
||||
"@testing-library/jest-dom": "^5.16.2",
|
||||
"@testing-library/react": "^12.1.3",
|
||||
"@testing-library/react-hooks": "^8.0.1",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"@types/jest": "^27.4.1",
|
||||
"@types/lodash": "^4.14.184",
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Spinner } from '@wordpress/components';
|
||||
import { useDebounce } from '@wordpress/compose';
|
||||
import { useCallback, useState, createElement } from '@wordpress/element';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { SelectControlProps } from '../select-control';
|
||||
import { SuffixIcon } from '../suffix-icon';
|
||||
|
||||
export const DEFAULT_DEBOUNCE_TIME = 250;
|
||||
|
||||
export default function useAsyncFilter< T >( {
|
||||
filter,
|
||||
onFilterStart,
|
||||
onFilterEnd,
|
||||
onFilterError,
|
||||
debounceTime,
|
||||
}: UseAsyncFilterInput< T > ): UseAsyncFilterOutput< T > {
|
||||
const [ isFetching, setIsFetching ] = useState( false );
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
function handleInputChangeCallback( value?: string ) {
|
||||
if ( typeof filter === 'function' ) {
|
||||
if ( typeof onFilterStart === 'function' )
|
||||
onFilterStart( value );
|
||||
|
||||
setIsFetching( true );
|
||||
|
||||
filter( value )
|
||||
.then( ( filteredItems ) => {
|
||||
if ( typeof onFilterEnd === 'function' )
|
||||
onFilterEnd( filteredItems, value );
|
||||
} )
|
||||
.catch( ( error: Error ) => {
|
||||
if ( typeof onFilterError === 'function' )
|
||||
onFilterError( error, value );
|
||||
} )
|
||||
.finally( () => {
|
||||
setIsFetching( false );
|
||||
} );
|
||||
}
|
||||
},
|
||||
[ filter, onFilterStart, onFilterEnd, onFilterError ]
|
||||
);
|
||||
|
||||
return {
|
||||
isFetching,
|
||||
suffix:
|
||||
isFetching === true ? (
|
||||
<SuffixIcon icon={ <Spinner /> } />
|
||||
) : undefined,
|
||||
getFilteredItems: ( items ) => items,
|
||||
onInputChange: useDebounce(
|
||||
handleInputChange,
|
||||
typeof debounceTime === 'number'
|
||||
? debounceTime
|
||||
: DEFAULT_DEBOUNCE_TIME
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
export type UseAsyncFilterInput< T > = {
|
||||
filter( value?: string ): Promise< T[] >;
|
||||
onFilterStart?( value?: string ): void;
|
||||
onFilterEnd?( filteredItems: T[], value?: string ): void;
|
||||
onFilterError?( error: Error, value?: string ): void;
|
||||
debounceTime?: number;
|
||||
};
|
||||
|
||||
export type UseAsyncFilterOutput< T > = Pick<
|
||||
SelectControlProps< T >,
|
||||
'suffix' | 'onInputChange' | 'getFilteredItems'
|
||||
> & {
|
||||
isFetching: boolean;
|
||||
};
|
|
@ -1 +1,2 @@
|
|||
export * from './select-control';
|
||||
export { default as useAsyncFilter } from './hooks/use-async-filter';
|
||||
|
|
|
@ -36,7 +36,7 @@ import {
|
|||
defaultGetFilteredItems,
|
||||
} from './utils';
|
||||
|
||||
type SelectControlProps< ItemType > = {
|
||||
export type SelectControlProps< ItemType > = {
|
||||
children?: ChildrenType< ItemType >;
|
||||
items: ItemType[];
|
||||
label: string | JSX.Element;
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
SlotFillProvider,
|
||||
Spinner,
|
||||
} from '@wordpress/components';
|
||||
import React from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import { createElement, useState } from '@wordpress/element';
|
||||
import { tag } from '@wordpress/icons';
|
||||
|
||||
|
@ -17,11 +17,15 @@ import { tag } from '@wordpress/icons';
|
|||
*/
|
||||
import { SelectedType, DefaultItemType, getItemLabelType } from '../types';
|
||||
import { MenuItem } from '../menu-item';
|
||||
import { SelectControl, selectControlStateChangeTypes } from '../';
|
||||
import {
|
||||
SelectControl,
|
||||
selectControlStateChangeTypes,
|
||||
useAsyncFilter,
|
||||
} from '../';
|
||||
import { Menu, MenuSlot } from '../menu';
|
||||
import { SuffixIcon } from '../suffix-icon';
|
||||
|
||||
const sampleItems = [
|
||||
const sampleItems: DefaultItemType[] = [
|
||||
{ value: 'apple', label: 'Apple' },
|
||||
{ value: 'pear', label: 'Pear' },
|
||||
{ value: 'orange', label: 'Orange' },
|
||||
|
@ -133,35 +137,121 @@ export const FuzzyMatching: React.FC = () => {
|
|||
|
||||
export const Async: React.FC = () => {
|
||||
const [ selectedItem, setSelectedItem ] =
|
||||
useState< SelectedType< DefaultItemType > >( null );
|
||||
useState< DefaultItemType | null >( null );
|
||||
const [ fetchedItems, setFetchedItems ] = useState< DefaultItemType[] >(
|
||||
[]
|
||||
);
|
||||
const [ isFetching, setIsFetching ] = useState( false );
|
||||
|
||||
const fetchItems = ( value: string | undefined ) => {
|
||||
setIsFetching( true );
|
||||
setFetchedItems( [] );
|
||||
setTimeout( () => {
|
||||
const results = sampleItems.sort( () => 0.5 - Math.random() );
|
||||
setFetchedItems( results );
|
||||
setIsFetching( false );
|
||||
}, 1500 );
|
||||
};
|
||||
const filter = useCallback(
|
||||
( value = '' ) =>
|
||||
new Promise< DefaultItemType[] >( ( resolve ) => {
|
||||
setTimeout( () => {
|
||||
const filteredItems = [ ...sampleItems ]
|
||||
.sort( ( a, b ) => a.label.localeCompare( b.label ) )
|
||||
.filter( ( { label } ) =>
|
||||
label.toLowerCase().includes( value.toLowerCase() )
|
||||
);
|
||||
resolve( filteredItems );
|
||||
}, 1500 );
|
||||
} ),
|
||||
[ selectedItem ]
|
||||
);
|
||||
|
||||
const { isFetching, ...selectProps } = useAsyncFilter< DefaultItemType >( {
|
||||
filter,
|
||||
onFilterStart() {
|
||||
setFetchedItems( [] );
|
||||
},
|
||||
onFilterEnd( filteredItems ) {
|
||||
setFetchedItems( filteredItems );
|
||||
},
|
||||
} );
|
||||
|
||||
return (
|
||||
<>
|
||||
<SelectControl
|
||||
<SelectControl< DefaultItemType >
|
||||
{ ...selectProps }
|
||||
label="Async"
|
||||
getFilteredItems={ ( allItems ) => {
|
||||
return allItems;
|
||||
} }
|
||||
items={ fetchedItems }
|
||||
onInputChange={ fetchItems }
|
||||
selected={ selectedItem }
|
||||
onSelect={ ( item ) => setSelectedItem( item ) }
|
||||
onRemove={ () => setSelectedItem( null ) }
|
||||
placeholder="Start typing..."
|
||||
onSelect={ setSelectedItem }
|
||||
onRemove={ () => setSelectedItem( null ) }
|
||||
>
|
||||
{ ( {
|
||||
items,
|
||||
isOpen,
|
||||
highlightedIndex,
|
||||
getItemProps,
|
||||
getMenuProps,
|
||||
} ) => {
|
||||
return (
|
||||
<Menu isOpen={ isOpen } getMenuProps={ getMenuProps }>
|
||||
{ isFetching ? (
|
||||
<Spinner />
|
||||
) : (
|
||||
items.map( ( item, index: number ) => (
|
||||
<MenuItem
|
||||
key={ `${ item.value }${ index }` }
|
||||
index={ index }
|
||||
isActive={ highlightedIndex === index }
|
||||
item={ item }
|
||||
getItemProps={ getItemProps }
|
||||
>
|
||||
{ item.label }
|
||||
</MenuItem>
|
||||
) )
|
||||
) }
|
||||
</Menu>
|
||||
);
|
||||
} }
|
||||
</SelectControl>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const AsyncWithoutListeningFilterEvents: React.FC = () => {
|
||||
const [ selectedItem, setSelectedItem ] =
|
||||
useState< DefaultItemType | null >( null );
|
||||
const [ fetchedItems, setFetchedItems ] = useState< DefaultItemType[] >(
|
||||
[]
|
||||
);
|
||||
|
||||
const filter = useCallback(
|
||||
async ( value = '' ) => {
|
||||
setFetchedItems( [] );
|
||||
return new Promise< DefaultItemType[] >( ( resolve ) => {
|
||||
setTimeout( () => {
|
||||
const filteredItems = [ ...sampleItems ]
|
||||
.sort( ( a, b ) => a.label.localeCompare( b.label ) )
|
||||
.filter( ( { label } ) =>
|
||||
label.toLowerCase().includes( value.toLowerCase() )
|
||||
);
|
||||
|
||||
resolve( filteredItems );
|
||||
}, 1500 );
|
||||
} ).then( ( filteredItems ) => {
|
||||
setFetchedItems( filteredItems );
|
||||
return filteredItems;
|
||||
} );
|
||||
},
|
||||
[ selectedItem ]
|
||||
);
|
||||
|
||||
const { isFetching, ...selectProps } = useAsyncFilter< DefaultItemType >( {
|
||||
filter,
|
||||
} );
|
||||
|
||||
return (
|
||||
<>
|
||||
<SelectControl< DefaultItemType >
|
||||
{ ...selectProps }
|
||||
label="Async"
|
||||
items={ fetchedItems }
|
||||
selected={ selectedItem }
|
||||
placeholder="Start typing..."
|
||||
onSelect={ setSelectedItem }
|
||||
onRemove={ () => setSelectedItem( null ) }
|
||||
>
|
||||
{ ( {
|
||||
items,
|
||||
|
|
|
@ -3,4 +3,8 @@
|
|||
align-items: center;
|
||||
height: 100%;
|
||||
padding-right: $gap-smaller;
|
||||
|
||||
.components-spinner {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { act, renderHook } from '@testing-library/react-hooks';
|
||||
import { useDebounce } from '@wordpress/compose';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { useAsyncFilter } from '../';
|
||||
|
||||
jest.mock( '@wordpress/compose', () => ( {
|
||||
...jest.requireActual( '@wordpress/compose' ),
|
||||
useDebounce: jest.fn( ( cb: CallableFunction ) => cb ),
|
||||
} ) );
|
||||
|
||||
describe( 'useAsyncFilter', () => {
|
||||
const filter = jest.fn();
|
||||
const onFilterStart = jest.fn();
|
||||
const onFilterEnd = jest.fn();
|
||||
const onFilterError = jest.fn();
|
||||
|
||||
afterEach( () => {
|
||||
jest.clearAllMocks();
|
||||
} );
|
||||
|
||||
it( 'should filter the items successfully', async () => {
|
||||
const filteredItems: string[] = [];
|
||||
|
||||
filter.mockResolvedValue( filteredItems );
|
||||
|
||||
const { result } = renderHook( () =>
|
||||
useAsyncFilter( {
|
||||
filter,
|
||||
} )
|
||||
);
|
||||
|
||||
const inputValue = 'Apple';
|
||||
|
||||
await act( async () => {
|
||||
if ( result.current.onInputChange )
|
||||
result.current.onInputChange( inputValue, {} );
|
||||
} );
|
||||
|
||||
expect( useDebounce ).toHaveBeenCalledWith(
|
||||
expect.any( Function ),
|
||||
250
|
||||
);
|
||||
expect( filter ).toHaveBeenCalledWith( inputValue );
|
||||
} );
|
||||
|
||||
it( 'should trigger onFilterStart at the begining of the filtering', async () => {
|
||||
const filteredItems: string[] = [];
|
||||
|
||||
onFilterStart.mockImplementation( ( value = '' ) => {
|
||||
expect( filter ).not.toHaveBeenCalledWith( value );
|
||||
} );
|
||||
|
||||
filter.mockImplementation( ( value = '' ) => {
|
||||
expect( onFilterStart ).toHaveBeenCalledWith( value );
|
||||
return Promise.resolve( filteredItems );
|
||||
} );
|
||||
|
||||
const { result } = renderHook( () =>
|
||||
useAsyncFilter( {
|
||||
filter,
|
||||
onFilterStart,
|
||||
} )
|
||||
);
|
||||
|
||||
const inputValue = 'Apple';
|
||||
|
||||
await act( async () => {
|
||||
if ( result.current.onInputChange )
|
||||
result.current.onInputChange( inputValue, {} );
|
||||
} );
|
||||
|
||||
expect( filter ).toHaveBeenCalledWith( inputValue );
|
||||
} );
|
||||
|
||||
it( 'should trigger onFilterEnd when filtering is fullfiled', async () => {
|
||||
const filteredItems: string[] = [];
|
||||
|
||||
filter.mockResolvedValue( filteredItems );
|
||||
|
||||
const { result } = renderHook( () =>
|
||||
useAsyncFilter( {
|
||||
filter,
|
||||
onFilterEnd,
|
||||
onFilterError,
|
||||
} )
|
||||
);
|
||||
|
||||
const inputValue = 'Apple';
|
||||
|
||||
await act( async () => {
|
||||
if ( result.current.onInputChange )
|
||||
result.current.onInputChange( inputValue, {} );
|
||||
} );
|
||||
|
||||
expect( onFilterEnd ).toHaveBeenCalledWith( filteredItems, inputValue );
|
||||
expect( onFilterError ).not.toHaveBeenCalled();
|
||||
} );
|
||||
|
||||
it( 'should trigger onFilterError when filtering is rejected', async () => {
|
||||
const error = new Error();
|
||||
|
||||
filter.mockRejectedValue( error );
|
||||
|
||||
const { result } = renderHook( () =>
|
||||
useAsyncFilter( {
|
||||
filter,
|
||||
onFilterEnd,
|
||||
onFilterError,
|
||||
} )
|
||||
);
|
||||
|
||||
const inputValue = 'Apple';
|
||||
|
||||
await act( async () => {
|
||||
if ( result.current.onInputChange )
|
||||
result.current.onInputChange( inputValue, {} );
|
||||
} );
|
||||
|
||||
expect( onFilterEnd ).not.toHaveBeenCalled();
|
||||
expect( onFilterError ).toHaveBeenCalledWith( error, inputValue );
|
||||
} );
|
||||
} );
|
|
@ -45,6 +45,7 @@ export { default as SelectControl } from './select-control';
|
|||
export {
|
||||
SelectControl as __experimentalSelectControl,
|
||||
selectControlStateChangeTypes,
|
||||
useAsyncFilter,
|
||||
} from './experimental-select-control';
|
||||
export {
|
||||
MenuItem as __experimentalSelectControlMenuItem,
|
||||
|
|
126
pnpm-lock.yaml
126
pnpm-lock.yaml
|
@ -200,6 +200,7 @@ importers:
|
|||
'@testing-library/dom': ^8.11.3
|
||||
'@testing-library/jest-dom': ^5.16.2
|
||||
'@testing-library/react': ^12.1.3
|
||||
'@testing-library/react-hooks': ^8.0.1
|
||||
'@testing-library/user-event': ^13.5.0
|
||||
'@types/jest': ^27.4.1
|
||||
'@types/lodash': ^4.14.184
|
||||
|
@ -355,6 +356,7 @@ importers:
|
|||
'@testing-library/dom': 8.11.3
|
||||
'@testing-library/jest-dom': 5.16.2
|
||||
'@testing-library/react': 12.1.4_sfoxds7t5ydpegc3knd667wn6m
|
||||
'@testing-library/react-hooks': 8.0.1_hiunvzosbwliizyirxfy6hjyim
|
||||
'@testing-library/user-event': 13.5.0_gzufz4q333be4gqfrvipwvqt6a
|
||||
'@types/jest': 27.4.1
|
||||
'@types/lodash': 4.14.184
|
||||
|
@ -2932,6 +2934,42 @@ packages:
|
|||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@babel/helper-define-polyfill-provider/0.3.0_@babel+core@7.16.12:
|
||||
resolution: {integrity: sha512-7hfT8lUljl/tM3h+izTX/pO3W3frz2ok6Pk+gzys8iJqDfZrZy2pXjRTZAvG2YmfHun1X4q8/UZRLatMfqc5Tg==}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.4.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.16.12
|
||||
'@babel/helper-compilation-targets': 7.19.3_@babel+core@7.16.12
|
||||
'@babel/helper-module-imports': 7.18.6
|
||||
'@babel/helper-plugin-utils': 7.19.0
|
||||
'@babel/traverse': 7.19.3
|
||||
debug: 4.3.4
|
||||
lodash.debounce: 4.0.8
|
||||
resolve: 1.22.1
|
||||
semver: 6.3.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@babel/helper-define-polyfill-provider/0.3.0_@babel+core@7.17.8:
|
||||
resolution: {integrity: sha512-7hfT8lUljl/tM3h+izTX/pO3W3frz2ok6Pk+gzys8iJqDfZrZy2pXjRTZAvG2YmfHun1X4q8/UZRLatMfqc5Tg==}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.4.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.17.8
|
||||
'@babel/helper-compilation-targets': 7.19.3_@babel+core@7.17.8
|
||||
'@babel/helper-module-imports': 7.18.6
|
||||
'@babel/helper-plugin-utils': 7.19.0
|
||||
'@babel/traverse': 7.19.3
|
||||
debug: 4.3.4
|
||||
lodash.debounce: 4.0.8
|
||||
resolve: 1.22.1
|
||||
semver: 6.3.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@babel/helper-define-polyfill-provider/0.3.1_@babel+core@7.12.9:
|
||||
resolution: {integrity: sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==}
|
||||
peerDependencies:
|
||||
|
@ -3576,8 +3614,8 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.12.9
|
||||
'@babel/helper-create-class-features-plugin': 7.17.6_@babel+core@7.12.9
|
||||
'@babel/helper-plugin-utils': 7.18.9
|
||||
'@babel/helper-create-class-features-plugin': 7.19.0_@babel+core@7.12.9
|
||||
'@babel/helper-plugin-utils': 7.19.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
@ -3589,8 +3627,8 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.16.12
|
||||
'@babel/helper-create-class-features-plugin': 7.17.6_@babel+core@7.16.12
|
||||
'@babel/helper-plugin-utils': 7.18.9
|
||||
'@babel/helper-create-class-features-plugin': 7.19.0_@babel+core@7.16.12
|
||||
'@babel/helper-plugin-utils': 7.19.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
@ -6540,9 +6578,9 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.16.12
|
||||
'@babel/helper-module-imports': 7.16.0
|
||||
'@babel/helper-plugin-utils': 7.14.5
|
||||
babel-plugin-polyfill-corejs2: 0.3.0_@babel+core@7.16.12
|
||||
'@babel/helper-module-imports': 7.18.6
|
||||
'@babel/helper-plugin-utils': 7.19.0
|
||||
babel-plugin-polyfill-corejs2: 0.3.3_@babel+core@7.16.12
|
||||
babel-plugin-polyfill-corejs3: 0.4.0_@babel+core@7.16.12
|
||||
babel-plugin-polyfill-regenerator: 0.3.0_@babel+core@7.16.12
|
||||
semver: 6.3.0
|
||||
|
@ -6557,9 +6595,9 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.17.8
|
||||
'@babel/helper-module-imports': 7.16.0
|
||||
'@babel/helper-plugin-utils': 7.14.5
|
||||
babel-plugin-polyfill-corejs2: 0.3.0_@babel+core@7.17.8
|
||||
'@babel/helper-module-imports': 7.18.6
|
||||
'@babel/helper-plugin-utils': 7.19.0
|
||||
babel-plugin-polyfill-corejs2: 0.3.3_@babel+core@7.17.8
|
||||
babel-plugin-polyfill-corejs3: 0.4.0_@babel+core@7.17.8
|
||||
babel-plugin-polyfill-regenerator: 0.3.0_@babel+core@7.17.8
|
||||
semver: 6.3.0
|
||||
|
@ -6650,8 +6688,8 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.12.9
|
||||
'@babel/helper-plugin-utils': 7.18.9
|
||||
'@babel/helper-skip-transparent-expression-wrappers': 7.16.0
|
||||
'@babel/helper-plugin-utils': 7.19.0
|
||||
'@babel/helper-skip-transparent-expression-wrappers': 7.18.9
|
||||
dev: true
|
||||
|
||||
/@babel/plugin-transform-spread/7.16.7_@babel+core@7.16.12:
|
||||
|
@ -6661,8 +6699,8 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.16.12
|
||||
'@babel/helper-plugin-utils': 7.18.9
|
||||
'@babel/helper-skip-transparent-expression-wrappers': 7.16.0
|
||||
'@babel/helper-plugin-utils': 7.19.0
|
||||
'@babel/helper-skip-transparent-expression-wrappers': 7.18.9
|
||||
dev: false
|
||||
|
||||
/@babel/plugin-transform-spread/7.16.7_@babel+core@7.17.8:
|
||||
|
@ -6840,7 +6878,7 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.16.12
|
||||
'@babel/helper-create-class-features-plugin': 7.17.6_@babel+core@7.16.12
|
||||
'@babel/helper-create-class-features-plugin': 7.19.0_@babel+core@7.16.12
|
||||
'@babel/helper-plugin-utils': 7.19.0
|
||||
'@babel/plugin-syntax-typescript': 7.16.7_@babel+core@7.16.12
|
||||
transitivePeerDependencies:
|
||||
|
@ -7471,8 +7509,8 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.16.12
|
||||
'@babel/helper-plugin-utils': 7.18.9
|
||||
'@babel/helper-validator-option': 7.16.7
|
||||
'@babel/helper-plugin-utils': 7.19.0
|
||||
'@babel/helper-validator-option': 7.18.6
|
||||
'@babel/plugin-transform-typescript': 7.16.8_@babel+core@7.16.12
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
@ -13300,6 +13338,29 @@ packages:
|
|||
react-error-boundary: 3.1.4_react@17.0.2
|
||||
dev: true
|
||||
|
||||
/@testing-library/react-hooks/8.0.1_hiunvzosbwliizyirxfy6hjyim:
|
||||
resolution: {integrity: sha512-Aqhl2IVmLt8IovEVarNDFuJDVWVvhnr9/GCU6UUnrYXwgDFF9h2L2o2P9KBni1AST5sT6riAyoukFLyjQUgD/g==}
|
||||
engines: {node: '>=12'}
|
||||
peerDependencies:
|
||||
'@types/react': ^16.9.0 || ^17.0.0
|
||||
react: ^16.9.0 || ^17.0.0
|
||||
react-dom: ^16.9.0 || ^17.0.0
|
||||
react-test-renderer: ^16.9.0 || ^17.0.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
react-dom:
|
||||
optional: true
|
||||
react-test-renderer:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.19.0
|
||||
'@types/react': 17.0.50
|
||||
react: 17.0.2
|
||||
react-dom: 17.0.2_react@17.0.2
|
||||
react-error-boundary: 3.1.4_react@17.0.2
|
||||
dev: true
|
||||
|
||||
/@testing-library/react/12.1.4_sfoxds7t5ydpegc3knd667wn6m:
|
||||
resolution: {integrity: sha512-jiPKOm7vyUw311Hn/HlNQ9P8/lHNtArAx0PisXyFixDDvfl8DbD6EUdbshK5eqauvBSvzZd19itqQ9j3nferJA==}
|
||||
engines: {node: '>=12'}
|
||||
|
@ -19127,6 +19188,19 @@ packages:
|
|||
- supports-color
|
||||
dev: true
|
||||
|
||||
/babel-plugin-polyfill-corejs2/0.3.3_@babel+core@7.16.12:
|
||||
resolution: {integrity: sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==}
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/compat-data': 7.19.3
|
||||
'@babel/core': 7.16.12
|
||||
'@babel/helper-define-polyfill-provider': 0.3.3_@babel+core@7.16.12
|
||||
semver: 6.3.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/babel-plugin-polyfill-corejs2/0.3.3_@babel+core@7.17.8:
|
||||
resolution: {integrity: sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==}
|
||||
peerDependencies:
|
||||
|
@ -19169,7 +19243,7 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.16.12
|
||||
'@babel/helper-define-polyfill-provider': 0.3.3_@babel+core@7.16.12
|
||||
'@babel/helper-define-polyfill-provider': 0.3.0_@babel+core@7.16.12
|
||||
core-js-compat: 3.25.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
@ -19181,7 +19255,7 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.17.8
|
||||
'@babel/helper-define-polyfill-provider': 0.3.3_@babel+core@7.17.8
|
||||
'@babel/helper-define-polyfill-provider': 0.3.0_@babel+core@7.17.8
|
||||
core-js-compat: 3.25.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
@ -24004,7 +24078,7 @@ packages:
|
|||
file-entry-cache: 6.0.1
|
||||
functional-red-black-tree: 1.0.1
|
||||
glob-parent: 5.1.2
|
||||
globals: 13.17.0
|
||||
globals: 13.18.0
|
||||
ignore: 4.0.6
|
||||
import-fresh: 3.3.0
|
||||
imurmurhash: 0.1.4
|
||||
|
@ -25327,7 +25401,7 @@ packages:
|
|||
vue-template-compiler:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.16.7
|
||||
'@babel/code-frame': 7.18.6
|
||||
'@types/json-schema': 7.0.9
|
||||
chalk: 4.1.2
|
||||
chokidar: 3.5.3
|
||||
|
@ -25338,7 +25412,7 @@ packages:
|
|||
memfs: 3.3.0
|
||||
minimatch: 3.1.2
|
||||
schema-utils: 2.7.0
|
||||
semver: 7.3.5
|
||||
semver: 7.3.8
|
||||
tapable: 1.1.3
|
||||
typescript: 4.8.4
|
||||
webpack: 5.70.0
|
||||
|
@ -25358,7 +25432,7 @@ packages:
|
|||
vue-template-compiler:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.16.7
|
||||
'@babel/code-frame': 7.18.6
|
||||
'@types/json-schema': 7.0.9
|
||||
chalk: 4.1.2
|
||||
chokidar: 3.5.3
|
||||
|
@ -25370,7 +25444,7 @@ packages:
|
|||
memfs: 3.3.0
|
||||
minimatch: 3.1.2
|
||||
schema-utils: 2.7.0
|
||||
semver: 7.3.5
|
||||
semver: 7.3.8
|
||||
tapable: 1.1.3
|
||||
typescript: 4.8.4
|
||||
webpack: 4.46.0_webpack-cli@3.3.12
|
||||
|
@ -25422,7 +25496,7 @@ packages:
|
|||
vue-template-compiler:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.16.7
|
||||
'@babel/code-frame': 7.18.6
|
||||
'@types/json-schema': 7.0.9
|
||||
chalk: 4.1.2
|
||||
chokidar: 3.5.3
|
||||
|
@ -25433,7 +25507,7 @@ packages:
|
|||
memfs: 3.3.0
|
||||
minimatch: 3.1.2
|
||||
schema-utils: 2.7.0
|
||||
semver: 7.3.5
|
||||
semver: 7.3.8
|
||||
tapable: 1.1.3
|
||||
typescript: 4.8.4
|
||||
webpack: 4.46.0
|
||||
|
|
Loading…
Reference in New Issue