2025-02-19 17:31:33 -08:00
|
|
|
// Copyright 2025 Signal Messenger, LLC
|
|
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
import React, { useCallback } from 'react';
|
2025-03-26 12:35:32 -07:00
|
|
|
import { VisuallyHidden } from 'react-aria';
|
|
|
|
import type { LocalizerType } from '../../../types/I18N';
|
2025-02-19 17:31:33 -08:00
|
|
|
|
|
|
|
export type FunSearchProps = Readonly<{
|
2025-03-26 12:35:32 -07:00
|
|
|
i18n: LocalizerType;
|
2025-02-19 17:31:33 -08:00
|
|
|
'aria-label': string;
|
|
|
|
placeholder: string;
|
|
|
|
searchInput: string;
|
|
|
|
onSearchInputChange: (newSearchInput: string) => void;
|
|
|
|
}>;
|
|
|
|
|
|
|
|
export function FunSearch(props: FunSearchProps): JSX.Element {
|
2025-03-26 12:35:32 -07:00
|
|
|
const { i18n, onSearchInputChange } = props;
|
|
|
|
|
2025-02-19 17:31:33 -08:00
|
|
|
const handleChange = useCallback(
|
|
|
|
event => {
|
|
|
|
onSearchInputChange(event.target.value);
|
|
|
|
},
|
|
|
|
[onSearchInputChange]
|
|
|
|
);
|
|
|
|
|
2025-03-26 12:35:32 -07:00
|
|
|
const handleClear = useCallback(() => {
|
|
|
|
onSearchInputChange('');
|
|
|
|
}, [onSearchInputChange]);
|
|
|
|
|
2025-02-19 17:31:33 -08:00
|
|
|
return (
|
|
|
|
<div className="FunSearch__Container">
|
|
|
|
<div className="FunSearch__Icon" />
|
|
|
|
<input
|
|
|
|
className="FunSearch__Input"
|
|
|
|
aria-label={props['aria-label']}
|
|
|
|
type="text"
|
|
|
|
value={props.searchInput}
|
|
|
|
onChange={handleChange}
|
|
|
|
placeholder={props.placeholder}
|
|
|
|
/>
|
2025-03-26 12:35:32 -07:00
|
|
|
{props.searchInput !== '' && (
|
|
|
|
<button
|
|
|
|
type="button"
|
|
|
|
className="FunSearch__Clear"
|
|
|
|
onClick={handleClear}
|
|
|
|
>
|
|
|
|
<span className="FunSearch__ClearButton">
|
|
|
|
<VisuallyHidden>
|
|
|
|
{i18n('icu:FunSearch__ClearButtonLabel')}
|
|
|
|
</VisuallyHidden>
|
|
|
|
</span>
|
|
|
|
</button>
|
|
|
|
)}
|
2025-02-19 17:31:33 -08:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|