const SuggestionsDropdown = styled.div` max-height: 200px; overflow-y: auto; border-radius: 4px; background-color: #0e0e10; position: absolute; top: 100%; width: 100%; z-index: 10; `; const SuggestionItem = styled.div` padding: 8px 16px; color: #fff; cursor: pointer; &:hover { background-color: #1f1f21; } `; const Text = styled.div` display: flex; column-gap: 0.5rem; align-items: center; color: #fff; font-family: Helvetica Neue; font-size: 24px; font-style: normal; font-weight: 500; line-height: 120% margin-bottom: 1rem; `; const Input = styled.input` color: #fff; width: 100%; height: 40px; padding: 8px 60px 8px 16px; margin-top: 1rem; margin-bottom: 1rem; border-radius: 4px; background-color: #0e0e10; border: none; `; const FunctionButton = styled.button` background-color: ${({ disabled }) => (disabled ? `${colors.disabled};` : `${colors.base};`)}; :hover { background-color: ${({ disabled }) => (disabled ? `${colors.disabled};` : `${colors.hover};`)}; } color: #fff; border-radius: 4px; padding-top: 0.5rem; padding-bottom: 0.5rem; border: none; width: 100%; `; const CloseButton = styled.div` color: #fff; :hover { color: #5765f2; } position: absolute; right: 1rem; cursor: pointer; `; const { title, toggle, placeholder, onAccountSelected, buttonText, componentOwnerId, fetchAccounts, validator, colors } = props; const BaseModal = (props) => ( <Widget src={`${componentOwnerId}/widget/Calimero.Common.Popups.BaseModal`} props={{ ...props, componentOwnerId, }} /> ); const [isOpen, setIsOpen] = useState(false); const [isProcessing, setIsProcessing] = useState(false); const [inputValue, setInputValue] = useState(""); const [validInput, setValidInput] = useState(false); const [suggestions, setSuggestions] = useState([]); const inputRef = useRef(""); useEffect(() => { inputRef.current = inputValue; }, [inputValue]); const runProcess = () => { setIsProcessing(true); functionLoader(inputValue).then((_) => { setIsProcessing(false); setIsOpen(false); }); }; const onOpenChange = (isOpen) => { if (isProcessing && !isOpen) { return; } setIsOpen(isOpen); }; const debouncedFetchUsers = (value) => { setTimeout(() => fetchAccounts(value).then((users) => { const accounts = users.map((user) => user.id); setSuggestions(accounts); }), 200); }; const handleInputChange = (e) => { const value = e.target.value; setInputValue(value); if (validator) { setValidInput(validator(value)); } debouncedFetchUsers(value); }; const handleClosePopup = () => { if (isProcessing) return; setIsOpen(false); }; const handleSuggestionClick = (suggestion) => { onAccountSelected(suggestion); setIsOpen(false); } const popupContent = ( <> <CloseButton onClick={handleClosePopup}> <i className="bi bi-x-lg"></i> </CloseButton> <Text>{title}</Text> <Input onChange={handleInputChange} value={inputValue} placeholder={placeholder} /> {suggestions.length > 0 && ( <SuggestionsDropdown> {suggestions.map((suggestion, index) => ( <SuggestionItem key={index} onClick={() => handleSuggestionClick(suggestion)}> {suggestion} </SuggestionItem> ))} </SuggestionsDropdown> )} <FunctionButton onClick={runProcess} disabled={validator && !validInput}> {isProcessing ? ( <Widget src={`${componentOwnerId}/widget/Calimero.Curb.Loader.Loader`} props={{ size: 16 }} /> ) : ( buttonText )} </FunctionButton> </> ); return ( <BaseModal toggle={toggle} content={popupContent} open={isOpen} onOpenChange={onOpenChange} /> );