From 160dcfc1481f883cae92ec8c44bccd27bba63795 Mon Sep 17 00:00:00 2001 From: Severin Landolt <41927988+severinlandolt@users.noreply.github.com> Date: Fri, 9 Feb 2024 18:10:27 +0100 Subject: [PATCH] feat: Added searchValue and onSearchValueChange props on SearchSelect (#944) (#958) * Adds searchValue and onSearchValueChange props --------- Co-authored-by: Perry Raskin --- .gitignore | 3 +- .../SearchSelect/SearchSelect.tsx | 16 ++++-- .../input-elements/SearchSelect.stories.tsx | 8 +++ .../helpers/SimpleSearchSelect.tsx | 55 +++++++++++++++++++ 4 files changed, 77 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 705f39518..fc740099e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ dist .DS_Store storybook-static package-lock.json -.vscode \ No newline at end of file +.vscode +yarn.lock \ No newline at end of file diff --git a/src/components/input-elements/SearchSelect/SearchSelect.tsx b/src/components/input-elements/SearchSelect/SearchSelect.tsx index b22ac4dc1..5d33cb27f 100644 --- a/src/components/input-elements/SearchSelect/SearchSelect.tsx +++ b/src/components/input-elements/SearchSelect/SearchSelect.tsx @@ -1,5 +1,5 @@ "use client"; -import React, { isValidElement, useMemo, useRef, useState } from "react"; +import React, { isValidElement, useMemo, useRef } from "react"; import { useInternalState } from "hooks"; import { Combobox, Transition } from "@headlessui/react"; import { ArrowDownHeadIcon, XCircleIcon } from "assets"; @@ -16,6 +16,8 @@ const makeSearchSelectClassName = makeClassName("SearchSelect"); export interface SearchSelectProps extends React.HTMLAttributes { defaultValue?: string; name?: string; + searchValue?: string; + onSearchValueChange?: (value: string) => void; value?: string; onValueChange?: (value: string) => void; placeholder?: string; @@ -33,6 +35,8 @@ const makeSelectClassName = makeClassName("SearchSelect"); const SearchSelect = React.forwardRef((props, ref) => { const { defaultValue = "", + searchValue, + onSearchValueChange, value, onValueChange, placeholder = "Select...", @@ -50,7 +54,7 @@ const SearchSelect = React.forwardRef((prop } = props; const comboboxButtonRef = useRef(null); - const [searchQuery, setSearchQuery] = useState(""); + const [searchQuery, setSearchQuery] = useInternalState("", searchValue); const [selectedValue, setSelectedValue] = useInternalState(defaultValue, value); const Icon = icon; @@ -62,7 +66,7 @@ const SearchSelect = React.forwardRef((prop }, [children]); const filteredOptions = useMemo( - () => getFilteredOptions(searchQuery, reactElementChildren), + () => getFilteredOptions(searchQuery ?? "", reactElementChildren), [searchQuery, reactElementChildren], ); @@ -70,6 +74,7 @@ const SearchSelect = React.forwardRef((prop setSelectedValue(""); setSearchQuery(""); onValueChange?.(""); + onSearchValueChange?.(""); }; return ( @@ -166,7 +171,10 @@ const SearchSelect = React.forwardRef((prop getSelectButtonColors(hasValue(value), disabled), )} placeholder={placeholder} - onChange={(event) => setSearchQuery(event.target.value)} + onChange={(event) => { + onSearchValueChange?.(event.target.value); + setSearchQuery(event.target.value); + }} displayValue={(value: string) => valueToNameMapping.get(value) ?? ""} />
diff --git a/src/stories/input-elements/SearchSelect.stories.tsx b/src/stories/input-elements/SearchSelect.stories.tsx index 82c76ef93..0794261d9 100644 --- a/src/stories/input-elements/SearchSelect.stories.tsx +++ b/src/stories/input-elements/SearchSelect.stories.tsx @@ -6,6 +6,7 @@ import { SimpleSearchSelectControlled, SimpleSearchSelectWithStaticAndDynamicChildren, SimpleSearchSelectForm, + SimpleSearchSelectServerSideRendering, } from "./helpers/SimpleSearchSelect"; import { CalendarIcon } from "assets"; @@ -84,3 +85,10 @@ export const Form: Story = { required: true, }, }; + +export const ServerSideRendering: Story = { + render: SimpleSearchSelectServerSideRendering, + args: { + required: true, + }, +}; diff --git a/src/stories/input-elements/helpers/SimpleSearchSelect.tsx b/src/stories/input-elements/helpers/SimpleSearchSelect.tsx index 85148c22c..de9f52420 100644 --- a/src/stories/input-elements/helpers/SimpleSearchSelect.tsx +++ b/src/stories/input-elements/helpers/SimpleSearchSelect.tsx @@ -97,3 +97,58 @@ export function SimpleSearchSelectControlled() {
); } + +export function SimpleSearchSelectServerSideRendering() { + const [searchQuery, setSearchQuery] = React.useState(""); + + interface User { + id: number; + name: string; + email: string; + } + const [options, setOptions] = React.useState([]); + + const [value, setValue] = React.useState(); + + const handleSearchQueryChange = (query: string) => { + setSearchQuery(query); + }; + + const handleValueChange = (newValue: string) => { + setValue(newValue); + }; + + const handleReset = () => { + setValue(""); + }; + + React.useEffect(() => { + if (searchQuery) { + fetch("https://jsonplaceholder.typicode.com/users") + .then((response) => response.json()) + .then((data) => { + setOptions(data); + }) + .catch((error) => console.error("Error fetching user data:", error)); + } + }, [searchQuery]); + + return ( +
+ + {options.map((option) => ( + + {`${option.name} (${option.email})`} + + ))} + + +

Selected User ID: {value}

+
+ ); +}