Skip to content

Commit d1a9516

Browse files
committed
R v1.0.4: code split
1 parent 7f7dfdd commit d1a9516

File tree

9 files changed

+284
-162
lines changed

9 files changed

+284
-162
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-api-search",
3-
"version": "1.0.3",
3+
"version": "1.0.4",
44
"description": "SearchBarComponent is a customizable and responsive search bar component for React applications. It provides a flexible, debounced search experience, ideal for integrating search functionality into your app. The component supports dynamic fetching of search results from a remote source, rendering custom items, and handling loading states, empty results, and error handling.",
55
"main": "dist/index.js",
66
"module": "dist/index.mjs",

src/Dropdown.module.css

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
.resultsList {
2+
position: absolute;
3+
top: 100%;
4+
left: 0;
5+
right: 0;
6+
display: none;
7+
flex-direction: column;
8+
overflow-y: auto;
9+
overflow-x: hidden;
10+
margin: 0;
11+
padding: 0;
12+
list-style: none;
13+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
14+
z-index: 1000;
15+
opacity: 0;
16+
pointer-events: none;
17+
transform: translateY(-10px);
18+
}
19+
20+
.resultsList.visible {
21+
display: flex;
22+
animation: slideBounce 0.4s ease forwards;
23+
pointer-events: auto;
24+
}
25+
/* Scrollbar Customization */
26+
.resultsList {
27+
scrollbar-width: thin;
28+
}
29+
30+
.resultsList::-webkit-scrollbar {
31+
width: 6px;
32+
}
33+
34+
.resultsList::-webkit-scrollbar-thumb {
35+
background-color: transparent;
36+
border-radius: 4px;
37+
}
38+
39+
/* Animation for dropdown appearance */
40+
@keyframes slideBounce {
41+
0% {
42+
opacity: 0;
43+
transform: translateY(-10px);
44+
}
45+
60% {
46+
transform: translateY(5px);
47+
}
48+
100% {
49+
opacity: 1;
50+
transform: translateY(0);
51+
}
52+
}
53+
54+
.resultItem {
55+
cursor: pointer;
56+
transition: background-color 0.2s ease;
57+
}
58+
59+
.centerElement {
60+
display: flex;
61+
flex-direction: column;
62+
align-items: center;
63+
justify-content: center;
64+
}

src/Dropdown.tsx

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import styles from './Dropdown.module.css';
2+
3+
interface DropdownProps<T> {
4+
results: T[];
5+
loading: boolean;
6+
error: boolean;
7+
loadingElement: React.ReactNode;
8+
emptyElement: React.ReactNode;
9+
errorElement: React.ReactNode;
10+
renderItem: (item: T) => React.ReactNode;
11+
onSelect?: (item: T) => void;
12+
dropdownStyles: {
13+
borderColor: string;
14+
backgroundColor: string;
15+
maxHeight: string;
16+
borderRadius: string;
17+
scrollBarColor: string;
18+
};
19+
}
20+
21+
const Dropdown = <T,>({
22+
results,
23+
loading,
24+
error,
25+
loadingElement,
26+
emptyElement,
27+
errorElement,
28+
renderItem,
29+
onSelect,
30+
dropdownStyles,
31+
}: DropdownProps<T>) => {
32+
const {
33+
borderColor,
34+
backgroundColor,
35+
maxHeight,
36+
borderRadius,
37+
scrollBarColor,
38+
} = dropdownStyles;
39+
40+
return (
41+
<ul
42+
className={styles.resultsList}
43+
style={{
44+
border: `1px solid ${borderColor}`,
45+
backgroundColor,
46+
maxHeight,
47+
borderRadius,
48+
scrollbarColor: `${scrollBarColor} transparent`,
49+
}}
50+
>
51+
{loading && <li className={styles.centerElement}>{loadingElement}</li>}
52+
{error && <li className={styles.centerElement}>{errorElement}</li>}
53+
{!loading && !error && results.length === 0 && (
54+
<li className={styles.centerElement}>{emptyElement}</li>
55+
)}
56+
{!loading &&
57+
!error &&
58+
results.map((item, index) => (
59+
<li
60+
key={index}
61+
className={styles.resultItem}
62+
onClick={() => onSelect && onSelect(item)}
63+
>
64+
{renderItem(item)}
65+
</li>
66+
))}
67+
</ul>
68+
);
69+
};
70+
71+
export default Dropdown;

src/InputField.module.css

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
.inputWrapper {
2+
display: flex;
3+
align-items: center;
4+
padding: 0 10px;
5+
overflow: hidden;
6+
}
7+
8+
.inputWrapper:focus-within {
9+
box-shadow: 0 0 6px rgba(0, 0, 0, 0.2);
10+
}
11+
12+
.searchIcon,
13+
.closeIcon {
14+
height: 50%;
15+
width: auto;
16+
}
17+
18+
.closeIcon {
19+
cursor: pointer;
20+
transition: all 0.2s ease-in-out;
21+
}
22+
23+
.closeIcon:hover {
24+
transform: rotate(90deg);
25+
}
26+
27+
.input {
28+
flex: 1;
29+
padding: 10px 15px;
30+
border: none;
31+
outline: none;
32+
background: transparent;
33+
}

src/InputField.tsx

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { ChangeEvent } from 'react';
2+
import { MdSearch, MdClose } from 'react-icons/md';
3+
import styles from './InputField.module.css';
4+
5+
interface InputFieldProps {
6+
query: string;
7+
placeholder: string;
8+
hideSearchIcon: boolean;
9+
inputStyles: {
10+
height: string;
11+
borderColor: string;
12+
backgroundColor: string;
13+
borderRadius: string;
14+
fontColor: string;
15+
fontSize: string;
16+
searchIconColor: string;
17+
closeIconColor: string;
18+
};
19+
onInputChange: (e: ChangeEvent<HTMLInputElement>) => void;
20+
onClearInput: () => void;
21+
onFocus: () => void;
22+
}
23+
24+
const InputField: React.FC<InputFieldProps> = ({
25+
query,
26+
placeholder,
27+
hideSearchIcon,
28+
inputStyles,
29+
onInputChange,
30+
onClearInput,
31+
onFocus,
32+
}) => {
33+
const {
34+
height,
35+
borderColor,
36+
backgroundColor,
37+
borderRadius,
38+
fontColor,
39+
fontSize,
40+
searchIconColor,
41+
closeIconColor,
42+
} = inputStyles;
43+
44+
return (
45+
<div
46+
className={styles.inputWrapper}
47+
style={{
48+
height,
49+
border: `1px solid ${borderColor}`,
50+
backgroundColor,
51+
borderRadius,
52+
}}
53+
>
54+
{!hideSearchIcon && (
55+
<MdSearch
56+
style={{ color: searchIconColor }}
57+
className={styles.searchIcon}
58+
/>
59+
)}
60+
<input
61+
type='text'
62+
value={query}
63+
placeholder={placeholder}
64+
className={styles.input}
65+
style={{ color: fontColor, fontSize }}
66+
onChange={onInputChange}
67+
onFocus={onFocus}
68+
/>
69+
{query && (
70+
<MdClose
71+
style={{ color: closeIconColor }}
72+
className={styles.closeIcon}
73+
onClick={onClearInput}
74+
/>
75+
)}
76+
</div>
77+
);
78+
};
79+
80+
export default InputField;

src/SearchBar.module.css

Lines changed: 0 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -2,103 +2,3 @@
22
position: relative;
33
width: 100%;
44
}
5-
6-
.inputWrapper {
7-
display: flex;
8-
align-items: center;
9-
padding: 0 10px;
10-
overflow: hidden;
11-
}
12-
13-
.inputWrapper:focus-within {
14-
box-shadow: 0 0 6px rgba(0, 0, 0, 0.2);
15-
}
16-
17-
.searchIcon,
18-
.closeIcon {
19-
height: 50%;
20-
width: auto;
21-
}
22-
23-
.closeIcon {
24-
cursor: pointer;
25-
transition: all 0.2s ease-in-out;
26-
}
27-
28-
.closeIcon:hover {
29-
transform: rotate(90deg);
30-
}
31-
32-
.input {
33-
flex: 1;
34-
padding: 10px 15px;
35-
border: none;
36-
outline: none;
37-
background: transparent;
38-
}
39-
40-
/* Scrollbar Customization */
41-
.resultsList {
42-
scrollbar-width: thin;
43-
}
44-
45-
.resultsList::-webkit-scrollbar {
46-
width: 6px;
47-
}
48-
49-
.resultsList::-webkit-scrollbar-thumb {
50-
background-color: transparent;
51-
border-radius: 4px;
52-
}
53-
54-
/* Animation for dropdown appearance */
55-
@keyframes slideBounce {
56-
0% {
57-
opacity: 0;
58-
transform: translateY(-10px);
59-
}
60-
60% {
61-
transform: translateY(5px);
62-
}
63-
100% {
64-
opacity: 1;
65-
transform: translateY(0);
66-
}
67-
}
68-
69-
.resultsList {
70-
position: absolute;
71-
top: 100%;
72-
left: 0;
73-
right: 0;
74-
display: none;
75-
flex-direction: column;
76-
overflow-y: auto;
77-
overflow-x: hidden;
78-
margin: 0;
79-
padding: 0;
80-
list-style: none;
81-
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
82-
z-index: 1000;
83-
opacity: 0;
84-
pointer-events: none;
85-
transform: translateY(-10px);
86-
}
87-
88-
.resultsList.visible {
89-
display: flex;
90-
animation: slideBounce 0.4s ease forwards;
91-
pointer-events: auto;
92-
}
93-
94-
.resultItem {
95-
cursor: pointer;
96-
transition: background-color 0.2s ease;
97-
}
98-
99-
.centerElement {
100-
display: flex;
101-
flex-direction: column;
102-
align-items: center;
103-
justify-content: center;
104-
}

0 commit comments

Comments
 (0)