From c81a096df1ff64b3b6f23deb7e771803f534f476 Mon Sep 17 00:00:00 2001 From: Kevin O'Connell Date: Mon, 16 Sep 2024 11:53:34 -0400 Subject: [PATCH 1/4] add a limit prop to the dropdown --- .../organisms/NeynarUserDropdown/index.tsx | 57 ++++++++++++------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/src/components/organisms/NeynarUserDropdown/index.tsx b/src/components/organisms/NeynarUserDropdown/index.tsx index f4dddda..3b7b50c 100644 --- a/src/components/organisms/NeynarUserDropdown/index.tsx +++ b/src/components/organisms/NeynarUserDropdown/index.tsx @@ -13,18 +13,19 @@ interface User { } export interface NeynarUserDropdownProps { - value: string; - onChange: (value: string) => void; - style?: React.CSSProperties; - placeholder?: string; - disabled?: boolean; - viewerFid?: number; - customStyles?: { - dropdown?: React.CSSProperties; - listItem?: React.CSSProperties; - avatar?: React.CSSProperties; - userInfo?: React.CSSProperties; - }; + value: string; + onChange: (value: string) => void; + style?: React.CSSProperties; + placeholder?: string; + disabled?: boolean; + viewerFid?: number; + customStyles?: { + dropdown?: React.CSSProperties; + listItem?: React.CSSProperties; + avatar?: React.CSSProperties; + userInfo?: React.CSSProperties; + }; + limit?: number | null; // Number of users that can be selected, or null for no limit } const Container = styled.div(() => ({ @@ -39,19 +40,21 @@ const Input = styled.input(() => ({ async function fetchUsersByQuery({ q, viewerFid, - client_id + client_id, }: { q: string; viewerFid?: number; client_id: string; }): Promise { try { - let requestUrl = `${NEYNAR_API_URL}/v2/farcaster/user/search?q=${q}&limit=5${viewerFid ? `&viewer_fid=${viewerFid}` : ''}&client_id=${client_id}`; + let requestUrl = `${NEYNAR_API_URL}/v2/farcaster/user/search?q=${q}&limit=5${ + viewerFid ? `&viewer_fid=${viewerFid}` : '' + }&client_id=${client_id}`; const response = await customFetch(requestUrl); const data = await response.json(); return data?.result?.users || []; } catch (error) { - console.log("Error fetching users by query", error); + console.log('Error fetching users by query', error); return null; } } @@ -63,7 +66,8 @@ export const NeynarUserDropdown: React.FC = ({ placeholder = 'Enter FIDs or usernames', disabled = false, viewerFid, -customStyles = {}, + customStyles = {}, + limit = null, // Default limit is null for no limit }) => { const { client_id } = useNeynarContext(); const [currentValue, setCurrentValue] = useState(''); @@ -71,15 +75,17 @@ customStyles = {}, const [users, setUsers] = useState([]); const inputRef = useRef(null); + // Splitting the value and storing in array format useEffect(() => { const values = value?.split(',') || []; - if (!values[values.length -1]) { + if (!values[values.length - 1]) { setCurrentValue(''); return; } setCurrentValue(values[values.length - 1].trim()); }, [value]); + // Fetch users when current value changes useEffect(() => { const shouldFetchUsers = currentValue !== '' && !/^\d+$/.test(currentValue); if (shouldFetchUsers) { @@ -90,7 +96,11 @@ customStyles = {}, }, [currentValue]); const fetchUsers = async (query: string) => { - const fetchedUsers = await fetchUsersByQuery({ q: query, viewerFid, client_id }); + const fetchedUsers = await fetchUsersByQuery({ + q: query, + viewerFid, + client_id, + }); if (fetchedUsers) { setUsers(fetchedUsers); setShowDropdown(true); @@ -104,7 +114,14 @@ customStyles = {}, const handleUserSelect = (user: User) => { let values = value.split(','); - values[values.length - 1] = user.fid.toString(); + + // If limit is defined and reached, replace the last user; otherwise add the user + if (limit !== null && values.length >= limit) { + values[values.length - 1] = user.fid.toString(); // Replace the last user + } else { + values.push(user.fid.toString()); // Add the user if under the limit or if no limit + } + const newValue = values.join(','); onChange(newValue); setCurrentValue(''); @@ -144,4 +161,4 @@ customStyles = {}, ); }; -export default NeynarUserDropdown; \ No newline at end of file +export default NeynarUserDropdown; From 0ec78e01d5822de1a992bba896fedcab4478184a Mon Sep 17 00:00:00 2001 From: Kevin O'Connell Date: Mon, 16 Sep 2024 11:54:43 -0400 Subject: [PATCH 2/4] remove comments --- src/components/organisms/NeynarUserDropdown/index.tsx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/components/organisms/NeynarUserDropdown/index.tsx b/src/components/organisms/NeynarUserDropdown/index.tsx index 3b7b50c..3a17b7f 100644 --- a/src/components/organisms/NeynarUserDropdown/index.tsx +++ b/src/components/organisms/NeynarUserDropdown/index.tsx @@ -67,7 +67,7 @@ export const NeynarUserDropdown: React.FC = ({ disabled = false, viewerFid, customStyles = {}, - limit = null, // Default limit is null for no limit + limit = null, }) => { const { client_id } = useNeynarContext(); const [currentValue, setCurrentValue] = useState(''); @@ -75,7 +75,6 @@ export const NeynarUserDropdown: React.FC = ({ const [users, setUsers] = useState([]); const inputRef = useRef(null); - // Splitting the value and storing in array format useEffect(() => { const values = value?.split(',') || []; if (!values[values.length - 1]) { @@ -85,7 +84,6 @@ export const NeynarUserDropdown: React.FC = ({ setCurrentValue(values[values.length - 1].trim()); }, [value]); - // Fetch users when current value changes useEffect(() => { const shouldFetchUsers = currentValue !== '' && !/^\d+$/.test(currentValue); if (shouldFetchUsers) { @@ -115,11 +113,10 @@ export const NeynarUserDropdown: React.FC = ({ const handleUserSelect = (user: User) => { let values = value.split(','); - // If limit is defined and reached, replace the last user; otherwise add the user if (limit !== null && values.length >= limit) { - values[values.length - 1] = user.fid.toString(); // Replace the last user + values[values.length - 1] = user.fid.toString(); } else { - values.push(user.fid.toString()); // Add the user if under the limit or if no limit + values.push(user.fid.toString()); } const newValue = values.join(','); From c2d9b04f2684bc1771618efa02c2b30f47afd8df Mon Sep 17 00:00:00 2001 From: Dylan Steck Date: Mon, 16 Sep 2024 16:28:37 -0400 Subject: [PATCH 3/4] fix: remove release please and manually increment version in meantime --- .github/workflows/release-please.yaml | 34 --------------------------- package.json | 2 +- 2 files changed, 1 insertion(+), 35 deletions(-) delete mode 100644 .github/workflows/release-please.yaml diff --git a/.github/workflows/release-please.yaml b/.github/workflows/release-please.yaml deleted file mode 100644 index dc17aa4..0000000 --- a/.github/workflows/release-please.yaml +++ /dev/null @@ -1,34 +0,0 @@ -name: Release Please - -on: - push: - branches: - - main - -jobs: - release: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Setup Node.js - uses: actions/setup-node@v3 - with: - node-version: '20' - - - name: Release Please - id: release - uses: google-github-actions/release-please-action@v3 - with: - release-type: node - package-name: "@neynar/react" - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Publish to npm - if: steps.release.outputs.releases_created != 'true' - run: | - npm install - npm publish - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} \ No newline at end of file diff --git a/package.json b/package.json index 51b01a8..9f6de7d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@neynar/react", - "version": "0.9.3", + "version": "0.9.4", "description": "Farcaster frontend component library powered by Neynar", "main": "dist/bundle.cjs.js", "module": "dist/bundle.es.js", From 0751ddbf048b0f5d5155e9362fefb28fb8ea2e1a Mon Sep 17 00:00:00 2001 From: Dylan Steck Date: Mon, 16 Sep 2024 16:34:09 -0400 Subject: [PATCH 4/4] add: docs for `NeynarUserDropdown` in `README.md` --- README.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/README.md b/README.md index 085df0c..cb63241 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,35 @@ import { NeynarProfileCard } from "@neynar/react"; viewerFid={1} /> ``` +### `` +This component is a dropdown to search for Farcaster users. + +Params: +- `value` (string): The currently selected user value. +- `onChange` (function): Callback function called with the new value when the user selection changes. +- `style?` (CSSProperties): Custom styles for the dropdown. Default: undefined. +- `placeholder?` (string): Placeholder text to display in the dropdown. Default: undefined. +- `disabled?` (boolean): Boolean indicating whether the dropdown is disabled. Default: false. +- `viewerFid?` (number): The FID of the viewer. Default: undefined. +- `customStyles?` (object): Custom styles for various elements within the dropdown. Properties include: + - `dropdown?` (CSSProperties): Styles for the dropdown container. + - `listItem?` (CSSProperties): Styles for the individual list items. + - `avatar?` (CSSProperties): Styles for the user's avatar. + - `userInfo?` (CSSProperties): Styles for the user's information text. +- `limit?` (number | null): The number of users that can be selected, or null for no limit. Default: null. + +Usage: +```tsx +import { NeynarUserDropdown } from "@neynar/react"; + + console.log(newValue)} + viewerFid={1} + limit={5} +/> +``` + ### `` This component displays a specific cast (post) on Farcaster.