From fe914837dfb85ff7b172a51b4757e0c279aa43d5 Mon Sep 17 00:00:00 2001 From: Karl Ghosn Date: Tue, 7 Jan 2025 18:15:00 +0200 Subject: [PATCH 1/2] added example --- README.md | 76 +++++++++++++++++++++++++++++++---------------- example/index.tsx | 62 ++++++++++++++++++++++++++++++++++++++ package-lock.json | 25 ++++++++++++++++ package.json | 1 + src/SearchBar.tsx | 2 -- 5 files changed, 139 insertions(+), 27 deletions(-) create mode 100644 example/index.tsx diff --git a/README.md b/README.md index 1ab0f70..80b9064 100644 --- a/README.md +++ b/README.md @@ -26,39 +26,65 @@ yarn add react-api-search ## Usage ```tsx -import React, { useState } from 'react'; import SearchBar from 'react-api-search'; -const MyComponent = () => { - const [selectedItem, setSelectedItem] = useState(null); - - const fetchSearchResults = async (query: string) => { - const response = await fetch('https://api.example.com/search?q=${query}'); - const data = await response.json(); - return data.results; // return an array of results - }; - - const renderSearchResult = (item: any) =>
{item.name}
; +type Post = { + id: number; + title: string; + body: string; +}; - const handleItemSelect = (item: any) => { - setSelectedItem(item); - }; +const fetchPosts = async (query: string): Promise => { + const response = await fetch( + `https://jsonplaceholder.typicode.com/posts?q=${encodeURIComponent(query)}` + ); + if (!response.ok) throw new Error('Failed to fetch posts'); + const data = await response.json(); + return data; +}; +function App() { return ( -
- - {selectedItem &&
You selected: {selectedItem.name}
} +
+

Posts Search

+
+ + placeholder='Search for posts...' + fetchData={fetchPosts} + loadingElement={ +
Please wait, fetching data...
+ } + emptyElement={ +
No posts match your search. Try something else!
+ } + errorElement={ +
Oops, something went wrong. Please try again later.
+ } + renderItem={(post) => ( +
{ + e.currentTarget.style.backgroundColor = '#f0f0f0'; // hover background + }} + onMouseLeave={(e) => { + e.currentTarget.style.backgroundColor = 'transparent'; // reset background + }} + > +

{post.title}

+

+ {post.body} +

+
+ )} + onSelect={(post) => alert(`Selected post: ${post.title}`)} + debounceDelay={500} + /> +
); -}; +} -export default MyComponent; +export default App; ``` ## Props diff --git a/example/index.tsx b/example/index.tsx new file mode 100644 index 0000000..e12ed3a --- /dev/null +++ b/example/index.tsx @@ -0,0 +1,62 @@ +import React from 'react'; +import { createRoot } from 'react-dom/client'; +import SearchBar from '../src/SearchBar'; + +const container = document.getElementById('root'); +const root = createRoot(container!); + +type Post = { + id: number; + title: string; + body: string; +}; + +const fetchPosts = async (query: string): Promise => { + const response = await fetch( + `https://jsonplaceholder.typicode.com/posts?q=${encodeURIComponent(query)}` + ); + if (!response.ok) throw new Error('Failed to fetch posts'); + const data = await response.json(); + return data; +}; + +root.render( + +
+

Posts Search

+
+ + placeholder='Search for posts...' + fetchData={fetchPosts} + loadingElement={ +
Please wait, fetching data...
+ } + emptyElement={ +
No posts match your search. Try something else!
+ } + errorElement={ +
Oops, something went wrong. Please try again later.
+ } + renderItem={(post) => ( +
{ + e.currentTarget.style.backgroundColor = '#f0f0f0'; // hover background + }} + onMouseLeave={(e) => { + e.currentTarget.style.backgroundColor = 'transparent'; // reset background + }} + > +

{post.title}

+

+ {post.body} +

+
+ )} + onSelect={(post) => alert(`Selected post: ${post.title}`)} + debounceDelay={500} + /> +
+
+
+); diff --git a/package-lock.json b/package-lock.json index 86d1bd3..62601de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "@rollup/plugin-typescript": "^11.1.6", "@types/react": "^18.3.3", "react": "^18.3.1", + "react-dom": "^18.3.1", "rollup": "^4.18.1", "rollup-plugin-dts": "^6.1.1", "rollup-plugin-peer-deps-external": "^2.2.4", @@ -2237,6 +2238,20 @@ "node": ">=0.10.0" } }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, "node_modules/react-icons": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.4.0.tgz", @@ -2422,6 +2437,16 @@ "dev": true, "license": "ISC" }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", diff --git a/package.json b/package.json index da21268..5e2b04d 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@rollup/plugin-typescript": "^11.1.6", "@types/react": "^18.3.3", "react": "^18.3.1", + "react-dom": "^18.3.1", "rollup": "^4.18.1", "rollup-plugin-dts": "^6.1.1", "rollup-plugin-peer-deps-external": "^2.2.4", diff --git a/src/SearchBar.tsx b/src/SearchBar.tsx index 07cf817..b772264 100644 --- a/src/SearchBar.tsx +++ b/src/SearchBar.tsx @@ -1,8 +1,6 @@ import { useState, useEffect, ChangeEvent, useRef } from 'react'; import styles from './SearchBar.module.css'; import { SearchBarProps } from './types'; -import { MdSearch } from 'react-icons/md'; -import { MdClose } from 'react-icons/md'; import Dropdown from './Dropdown'; import InputField from './InputField'; From e911d57f3b2c73e979792eb89125a83df2100ff0 Mon Sep 17 00:00:00 2001 From: Karl Ghosn Date: Tue, 7 Jan 2025 18:15:36 +0200 Subject: [PATCH 2/2] fix readme --- README.md | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/README.md b/README.md index 80b9064..8acbb7d 100644 --- a/README.md +++ b/README.md @@ -120,24 +120,6 @@ export default App; | dropDownBorderRadius | string | Border radius of the dropdown. | '8px' | | scrollBarColor | string | Color of the scrollbar inside the dropdown. | #ccc | -## Example - -### Basic Example - -```tsx - { - const response = await fetch('https://api.example.com/search?q=${query}'); - return response.json(); - }} - renderItem={(item) =>
{item.name}
} - onSelect={(item) => console.log('Selected:', item)} - placeholder='Search for items...' - loadingElement={
Loading...
} - emptyElement={
No results found
} -/> -``` - ## License This project is licensed under the MIT License. See the [LICENSE](https://github.com/ghosnkarl/react-api-search/blob/main/LICENSE) file for more information.