Skip to content

Commit 1d6bd5e

Browse files
1) adding ClearIcon, MagnifierIcon, onClear, theme, corner, inputContainerStyle, onFocus props and remove inconsColor, searchIconStyle and clearIconStyle props
2) fix issue of click event inside the popper 3) provide multi themes 4) adding css style
1 parent c7cf541 commit 1d6bd5e

File tree

8 files changed

+215
-138
lines changed

8 files changed

+215
-138
lines changed

example/stories/simple-manipulation/README.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,22 @@ import React, {useState} from 'react';
33
import ReactCustomSearchList from 'react-custom-search-list';
44
import 'react-custom-search-list/style/react-custom-search-list.css';
55
function App() {
6-
const [searchValue, setSearchValue] = useState('');
6+
const [value, setValue] = useState('');
77
return (
8-
<ReactCustomSearchList fullWidth value={searchValue} setValue={setSearchValue}>
8+
<ReactCustomSearchList
9+
fullWidth={false}
10+
value={value}
11+
corner={false}
12+
theme="panel"
13+
onChange={(e) => setValue(e.target.value)}
14+
onClear={() => setValue('')}>
915
{/**Render your suggestions list here*/}
1016
<ul>
1117
<li>
1218
<button
19+
id="ccc"
1320
onClick={() => {
14-
console.log('onclick');
21+
console.log('button click');
1522
}}>
1623
Option A
1724
</button>

src/defaultOptions.js

Lines changed: 0 additions & 40 deletions
This file was deleted.

src/icons/clear.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import React from 'react';
2+
export default function (props) {
3+
const {value, onClear} = props;
4+
return (
5+
<svg
6+
width="20"
7+
height="20"
8+
focusable="false"
9+
xmlns="http://www.w3.org/2000/svg"
10+
viewBox="0 0 24 24"
11+
fill="gray"
12+
onClick={(e) => {
13+
onClear(e);
14+
}}
15+
style={{
16+
backgroundColor: 'white',
17+
cursor: 'pointer',
18+
opacity: value.length ? 1 : 0,
19+
}}>
20+
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.58 12 5 17.58 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path>
21+
</svg>
22+
);
23+
}

src/icons/close.js

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/icons/search.js renamed to src/icons/magnifier.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ export default function (props) {
88
focusable="false"
99
xmlns="http://www.w3.org/2000/svg"
1010
viewBox="0 0 24 24"
11-
{...props}>
11+
fill="gray"
12+
style={{backgroundColor: 'white'}}>
1213
<path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path>
1314
</svg>
1415
);

src/index.js

Lines changed: 80 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,109 @@
1-
import React, {useRef, useState, useLayoutEffect, useEffect} from 'react';
1+
import React, {useRef, useState, useCallback, useEffect} from 'react';
22
import Popper from './popper';
3-
import SearchIcon from './icons/search.js';
4-
import CloseIcon from './icons/close.js';
5-
import deop from './defaultOptions.js';
3+
import MagnifierIcon from './icons/magnifier.js';
4+
import ClearIcon from './icons/clear.js';
65
/**
76
*
87
* @param {Object} props
8+
* @param {React.ReactNode} [props.children=null] - will be shown in popup
99
* @param {value} props.value - input value
10-
* @param {Function} props.setValue - setState function for input value
11-
* @param {React.ReactNode} [props.children] - will be shown in popup
12-
* @param {Object} [props.rootStyle] - style object of the root element
13-
* @param {Object} [props.inputStyle] - style object of the input element
10+
* @param {Function} props.onChange - onChange function for input
11+
* @param {Object} [props.rootStyle={}] - style object of the root element
12+
* @param {Object} [props.inputContainerStyle={}] - style object of the parent element of text input
13+
* @param {Object} [props.inputStyle={}] - style object of the input element
1414
* @param {String} [props.placeholder="search"]
15-
* @param {String} [props.iconsColor="gray"] - svg icon's color
16-
* @param {Object} [props.searchIconStyle] - style object for magnifying icon
17-
* @param {Object} [props.clearIconStyle] - style object for clear icon
18-
* @param {Object} [props.popperStyle] - style object for popper container
19-
* @param {Function} [props.onKeyDown] - keydown event for input
20-
* @param {Function} [props.onBlur] - blur event for the input
21-
* @param {Boolean} [props.fullWidth=false] - set popper width same as input
22-
* @param {'auto'| 'auto-start'| 'auto-end'| 'top'| 'top-start'| 'top-end'| 'bottom'| 'bottom-start'| 'bottom-end'| 'right'| 'right-start'| 'right-end'| 'left'| 'left-start'| 'left-end'} [props.placement="bottom"] - popper's placement
15+
* @param {Function} [props.onKeyDown=()=>{}] - keydown event for input
16+
* @param {Function} [props.onFocus=()=>{}] - focus event for input
17+
* @param {Function} [props.onBlur=()=>{}] - blur event for the input
18+
* @param {Object} [props.popperStyle={}] - style object for popper container
19+
* @param {Boolean} [props.fullWidth=true] - set popper width same as input
20+
* @param {'auto'| 'auto-start'| 'auto-end'| 'top'| 'top-start'| 'top-end'| 'bottom'| 'bottom-start'| 'bottom-end'| 'right'| 'right-start'| 'right-end'| 'left'| 'left-start'| 'left-end'} [props.placement="bottom-start"] - popper's placement
21+
* @param {React.FC} [props.ClearIconComponent=ClearIcon] - custom Clear icon
22+
* @param {React.FC} [props.MagnifierIconComponent=MagnifierIcon] - custom Magnifier icon
23+
* @param {Function} [props.onClear=()=>{}] - triggerd when the user clicks on the default Clear icon
24+
* @param {"underline"|"outline"|"panel"} [props.theme="outline"] - searchbox theme
25+
* @param {Boolean} [props.corner=true] - if set true then border-radius would be "5px"
2326
*/
2427
function ReactCustomSearchList(props) {
2528
const {
26-
children,
27-
value,
28-
setValue,
29-
rootStyle,
30-
inputStyle,
31-
placeholder,
32-
iconsColor,
33-
searchIconStyle,
34-
clearIconStyle,
35-
onKeyDown,
36-
onBlur,
37-
popperStyle,
38-
fullWidth,
39-
placement,
40-
} = {
41-
...deop,
42-
...props,
43-
};
29+
children = null,
30+
value = '',
31+
onChange,
32+
rootStyle = {},
33+
inputContainerStyle = {},
34+
inputStyle = {},
35+
placeholder = 'search',
36+
onKeyDown = () => {},
37+
onFocus = () => {},
38+
onBlur = () => {},
39+
popperStyle = {},
40+
fullWidth = true,
41+
placement = 'bottom-start',
42+
ClearIconComponent = ClearIcon,
43+
MagnifierIconComponent = MagnifierIcon,
44+
onClear = () => {},
45+
theme = 'outline',
46+
corner = true,
47+
} = props;
4448
const [open, setOpen] = useState(false);
45-
const [isBlur, setIsBlur] = useState(false);
4649
const rootRef = useRef();
47-
const onFocus = (e) => {
50+
const onClickHandler = useCallback(() => {
4851
setOpen(true);
49-
};
50-
const onBlurHandle = (e) => {
51-
e.preventDefault();
52-
console.log('onBlurHandle');
53-
debugger;
54-
setOpen(false);
55-
setIsBlur(true);
56-
onBlur(e);
57-
};
52+
}, []);
53+
const onKeyDownHandler = useCallback(
54+
(e) => {
55+
(e) => {
56+
if (e.key.toLowerCase() === 'enter' && open === false) {
57+
setOpen(true);
58+
}
59+
onKeyDown(e);
60+
};
61+
},
62+
[onKeyDown],
63+
);
5864
useEffect(() => {
59-
if (isBlur) {
60-
console.log('useEffect');
61-
}
62-
}, [isBlur]);
65+
const click = (e) => {
66+
setTimeout(() => {
67+
setOpen(false);
68+
});
69+
};
70+
open
71+
? document.body.addEventListener('click', click, {once: true, useCapture: true})
72+
: document.body.removeEventListener('click', click, {once: true, useCapture: true});
73+
return () => {
74+
if (open) {
75+
console.log('remove listener');
76+
document.body.removeEventListener('click', click, {once: true, useCapture: true});
77+
}
78+
};
79+
}, [open]);
6380
return (
64-
<div className="rc-search-suggestions-root">
81+
<div className={`rc-search-suggestions-root ${theme}${corner ? ' corner' : ''}`} style={rootStyle}>
6582
{open ? (
6683
<Popper
6784
rootRef={rootRef}
68-
style={{...deop.popperStyle, ...popperStyle}}
69-
fullWidth={fullWidth}
85+
style={popperStyle}
86+
fullWidth={theme === 'panel' ? true : fullWidth}
7087
placement={placement}>
7188
{children}
7289
</Popper>
7390
) : null}
74-
<div className="rc-search-suggestions-container" ref={rootRef} style={{...deop.rootStyle, ...rootStyle}}>
75-
<SearchIcon
76-
className="rc-search-suggestions-magnifying"
77-
fill={iconsColor}
78-
style={{...deop.searchIconStyle, ...searchIconStyle}}
79-
/>
91+
<div className={`rc-search-suggestions-container`} ref={rootRef} style={inputContainerStyle}>
92+
{MagnifierIconComponent ? <MagnifierIconComponent /> : null}
8093
<input
81-
onFocus={onFocus}
82-
onBlur={onBlurHandle}
8394
value={value}
84-
onChange={(e) => setValue(e.target.value)}
95+
onChange={onChange}
96+
onFocus={onFocus}
97+
onClick={onClickHandler}
98+
onKeyDown={onKeyDownHandler}
99+
onBlur={onBlur}
85100
placeholder={placeholder}
86-
className="rc-search-suggestions-input"
87-
style={{...deop.inputStyle, ...inputStyle}}
88-
onKeyDown={onKeyDown}
89-
/>
90-
<CloseIcon
91-
className="rc-search-suggestions-close"
92-
fill={iconsColor}
93-
style={{opacity: value.length ? 1 : 0, ...deop.clearIconStyle, ...clearIconStyle}}
94-
onClick={() => {
95-
setValue('');
96-
}}
101+
style={inputStyle}
97102
/>
103+
{ClearIconComponent ? <ClearIconComponent value={value} onClear={onClear} /> : null}
98104

99-
{/* <div
100-
className={
101-
'rc-search-suggestions-divider ' + open
102-
? 'rc-search-suggestions-divider-open'
103-
: 'rc-search-suggestions-divider-close'
104-
}
105-
/> */}
105+
<div className="rc-search-suggestions-divider rc-search-suggestions-divider-bottom" />
106+
<div className="rc-search-suggestions-divider rc-search-suggestions-divider-top" />
106107
</div>
107108
</div>
108109
);

src/popper/popper.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export default function Popper(getDeps, props) {
2222
}, [children]);
2323
return (
2424
<>
25-
<div ref={popperRef} className="rc-search-suggestions-popper" style={style}>
25+
<div ref={popperRef} className="rc-search-suggestions-popper" style={style} tabIndex={0}>
2626
{children}
2727
</div>
2828
</>

0 commit comments

Comments
 (0)