mirror of https://github.com/vizality/vizality
add FilterInput component, rename Icon component rawSVG prop to svgOnly
parent
76ab552aaf
commit
3ab226e90e
@ -0,0 +1,82 @@
|
||||
import React, { memo, useEffect, useState } from 'react';
|
||||
import { joinClassNames } from '@vizality/util/dom';
|
||||
import { getModule } from '@vizality/webpack';
|
||||
import { Messages } from '@vizality/i18n';
|
||||
|
||||
import { Icon } from '.';
|
||||
|
||||
/**
|
||||
* @component
|
||||
* @returns {}
|
||||
*/
|
||||
export default memo(({ size, disabled, value, loading, caseSensitive, sortResults, minLength = 4, debounce = 200, filterKeys, fuzzy, inputClassName, className, onChange, ...other }) => {
|
||||
const [ query, setQuery ] = useState(value || '');
|
||||
const { container, inner, disabled: _disabled, small, medium, large, input, clear, iconLayout, iconContainer, icon, visible, pointer } = getModule('container', 'inner', 'small', 'input', 'clear');
|
||||
|
||||
/**
|
||||
* Check if size prop matches one of the available sizes, if it doesn't, set it
|
||||
* to small by default.
|
||||
*/
|
||||
switch (size) {
|
||||
case 'small' || small:
|
||||
size = small; break;
|
||||
case 'small' || medium:
|
||||
size = medium; break;
|
||||
case 'small' || large:
|
||||
size = large; break;
|
||||
default: size = small;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up a debounce timeout to only perform the search query every x
|
||||
* milliseconds. Especially useful for API calls.
|
||||
*/
|
||||
const debounceTimeout = setTimeout(() => onChange(query), debounce);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} evt
|
||||
* @returns
|
||||
*/
|
||||
const handleOnChange = evt => {
|
||||
evt.persist?.();
|
||||
return setQuery(evt?.currentTarget?.value);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof value !== 'undefined') {
|
||||
const evt = {
|
||||
currentTarget: {
|
||||
value
|
||||
}
|
||||
};
|
||||
handleOnChange(evt);
|
||||
}
|
||||
}, [ value ]);
|
||||
|
||||
/**
|
||||
* Clear the debounce timeout on dismount.
|
||||
*/
|
||||
useEffect(() => {
|
||||
return () => clearTimeout(debounceTimeout);
|
||||
}, [ debounceTimeout ]);
|
||||
|
||||
return (
|
||||
<div className={joinClassNames(container, size, className, { [_disabled]: disabled })} {...other}>
|
||||
<div className={inner}>
|
||||
<input
|
||||
className={joinClassNames(input, inputClassName)}
|
||||
onChange={handleOnChange}
|
||||
value={query}
|
||||
placeholder={Messages.SEARCH}
|
||||
/>
|
||||
<div className={joinClassNames(iconLayout, size, { [pointer]: query?.length })} tabindex={query?.length ? '0' : '-1'} role='button'>
|
||||
<div className={iconContainer}>
|
||||
<Icon svgOnly name='Search' className={joinClassNames(icon, { [visible]: !query?.length })} />
|
||||
<Icon svgOnly name='Close' className={joinClassNames(clear, icon, { [visible]: query?.length })} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
Loading…
Reference in new issue