mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-06-17 16:45:31 +02:00
Reuse text field component
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import { XCircleIcon } from '@heroicons/react/24/solid';
|
||||
import * as React from 'react';
|
||||
|
||||
export interface ITextFieldProps {
|
||||
name: string;
|
||||
value?: string;
|
||||
placeholder?: string;
|
||||
icon?: JSX.Element;
|
||||
disabled?: boolean;
|
||||
autoFocus?: boolean;
|
||||
multiline?: boolean;
|
||||
rows?: number;
|
||||
onChange?: (value: string) => void;
|
||||
onReset?: () => void;
|
||||
}
|
||||
|
||||
export const TextField: React.FunctionComponent<ITextFieldProps> = ({
|
||||
name,
|
||||
value,
|
||||
placeholder,
|
||||
icon,
|
||||
autoFocus,
|
||||
multiline,
|
||||
rows,
|
||||
disabled,
|
||||
onChange,
|
||||
onReset
|
||||
}: React.PropsWithChildren<ITextFieldProps>) => {
|
||||
return (
|
||||
<div className="relative flex justify-center">
|
||||
{
|
||||
icon && (
|
||||
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
{icon}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
multiline ? (
|
||||
<textarea
|
||||
rows={rows || 3}
|
||||
name={name}
|
||||
className={`block w-full py-2 ${icon ? "pl-10" : "pl-2"} pr-2 sm:text-sm appearance-none disabled:opacity-50 rounded bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] placeholder-[var(--vscode-input-placeholderForeground)] border-[var(--frontmatter-border)] focus:border-[var(--vscode-focusBorder)] focus:outline-0`}
|
||||
style={{
|
||||
boxShadow: "none"
|
||||
}}
|
||||
placeholder={placeholder || ""}
|
||||
value={value}
|
||||
autoFocus={!!autoFocus}
|
||||
onChange={(e) => onChange && onChange(e.target.value)}
|
||||
disabled={!!disabled}
|
||||
/>
|
||||
) : (
|
||||
<input
|
||||
type="text"
|
||||
name={name}
|
||||
className={`block w-full py-2 ${icon ? "pl-10" : "pl-2"} pr-2 sm:text-sm appearance-none disabled:opacity-50 rounded bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] placeholder-[var(--vscode-input-placeholderForeground)] border-[var(--frontmatter-border)] focus:border-[var(--vscode-focusBorder)] focus:outline-0`}
|
||||
style={{
|
||||
boxShadow: "none"
|
||||
}}
|
||||
placeholder={placeholder || ""}
|
||||
value={value}
|
||||
autoFocus={!!autoFocus}
|
||||
onChange={(e) => onChange && onChange(e.target.value)}
|
||||
disabled={!!disabled}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
{(value && onReset) && (
|
||||
<button onClick={onReset} className="absolute inset-y-0 right-0 pr-3 flex items-center text-[var(--vscode-input-foreground)] hover:text-[var(--vscode-textLink-activeForeground)]">
|
||||
<XCircleIcon className={`h-5 w-5`} aria-hidden="true" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,8 +1,8 @@
|
||||
import { MagnifyingGlassIcon, XCircleIcon } from '@heroicons/react/24/solid';
|
||||
import * as React from 'react';
|
||||
import useThemeColors from '../../hooks/useThemeColors';
|
||||
import * as l10n from '@vscode/l10n';
|
||||
import { LocalizationKey } from '../../../localization';
|
||||
import { TextField } from '../Common/TextField';
|
||||
|
||||
export interface IFilterInputProps {
|
||||
placeholder: string;
|
||||
@@ -21,7 +21,6 @@ export const FilterInput: React.FunctionComponent<IFilterInputProps> = ({
|
||||
onReset,
|
||||
onChange
|
||||
}: React.PropsWithChildren<IFilterInputProps>) => {
|
||||
const { getColors } = useThemeColors();
|
||||
|
||||
return (
|
||||
<div className="flex space-x-4 flex-1">
|
||||
@@ -29,32 +28,19 @@ export const FilterInput: React.FunctionComponent<IFilterInputProps> = ({
|
||||
<label htmlFor="search" className="sr-only">
|
||||
{l10n.t(LocalizationKey.commonSearch)}
|
||||
</label>
|
||||
<div className="relative flex justify-center">
|
||||
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<MagnifyingGlassIcon className={`h-5 w-5 ${getColors(`text-gray-400`, 'text-[var(--vscode-input-foreground)]')}`} aria-hidden="true" />
|
||||
</div>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
name="search"
|
||||
className={`block w-full py-2 pl-10 pr-3 sm:text-sm appearance-none disabled:opacity-50 rounded ${getColors(
|
||||
'bg-white dark:bg-vulcan-300 border border-gray-300 dark:border-vulcan-100 text-vulcan-500 dark:text-whisper-500 placeholder-gray-400 dark:placeholder-whisper-800 focus:outline-none',
|
||||
'bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] border-[var(--vscode-input-border)] placeholder-[var(--vscode-input-placeholderForeground)] focus:outline-[var(--vscode-focusBorder)] focus:outline-1 focus:outline-offset-0 focus:shadow-none focus:border-transparent'
|
||||
)
|
||||
}`}
|
||||
placeholder={placeholder || l10n.t(LocalizationKey.commonSearch)}
|
||||
value={value}
|
||||
autoFocus={autoFocus}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => onChange(event.target.value)}
|
||||
disabled={!isReady}
|
||||
/>
|
||||
|
||||
{value && onReset && (
|
||||
<button onClick={onReset} className="absolute inset-y-0 right-0 pr-3 flex items-center">
|
||||
<XCircleIcon className={`h-5 w-5 ${getColors(`text-gray-400`, 'text-[var(--vscode-input-foreground)]')}`} aria-hidden="true" />
|
||||
</button>
|
||||
<TextField
|
||||
name='search'
|
||||
icon={(
|
||||
<MagnifyingGlassIcon className={`h-4 w-4 text-[var(--vscode-input-foreground)]`} aria-hidden="true" />
|
||||
)}
|
||||
</div>
|
||||
value={value}
|
||||
autoFocus={autoFocus}
|
||||
placeholder={placeholder || l10n.t(LocalizationKey.commonSearch)}
|
||||
disabled={!isReady}
|
||||
onChange={onChange}
|
||||
onReset={onReset}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -2,11 +2,11 @@ import { MagnifyingGlassIcon, XCircleIcon } from '@heroicons/react/24/solid';
|
||||
import * as React from 'react';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
import { useDebounce } from '../../../hooks/useDebounce';
|
||||
import useThemeColors from '../../hooks/useThemeColors';
|
||||
import { SearchAtom, SearchReadyAtom } from '../../state';
|
||||
import { RefreshDashboardData } from './RefreshDashboardData';
|
||||
import * as l10n from '@vscode/l10n';
|
||||
import { LocalizationKey } from '../../../localization';
|
||||
import { TextField } from '../Common/TextField';
|
||||
|
||||
export interface ISearchboxProps {
|
||||
placeholder?: string;
|
||||
@@ -19,10 +19,9 @@ export const Searchbox: React.FunctionComponent<ISearchboxProps> = ({
|
||||
const [debounceSearchValue, setDebounceValue] = useRecoilState(SearchAtom);
|
||||
const searchReady = useRecoilValue(SearchReadyAtom);
|
||||
const debounceSearch = useDebounce<string>(value, 500);
|
||||
const { getColors } = useThemeColors();
|
||||
|
||||
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setValue(event.target.value);
|
||||
const handleChange = (newValue: string) => {
|
||||
setValue(newValue);
|
||||
};
|
||||
|
||||
const reset = React.useCallback(() => {
|
||||
@@ -46,31 +45,18 @@ export const Searchbox: React.FunctionComponent<ISearchboxProps> = ({
|
||||
<label htmlFor="search" className="sr-only">
|
||||
{l10n.t(LocalizationKey.commonSearch)}
|
||||
</label>
|
||||
<div className="relative flex justify-center">
|
||||
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<MagnifyingGlassIcon className={`h-5 w-5 ${getColors(`text-gray-400`, 'text-[var(--vscode-input-foreground)]')}`} aria-hidden="true" />
|
||||
</div>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
name="search"
|
||||
className={`block w-full py-2 pl-10 pr-3 sm:text-sm appearance-none disabled:opacity-50 rounded ${getColors(
|
||||
'bg-white dark:bg-vulcan-300 border border-gray-300 dark:border-vulcan-100 text-vulcan-500 dark:text-whisper-500 placeholder-gray-400 dark:placeholder-whisper-800 focus:outline-none',
|
||||
'bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] border-[var(--vscode-input-border, --vscode-editorWidget-border)] placeholder-[var(--vscode-input-placeholderForeground)] focus:outline-[var(--vscode-focusBorder)] focus:outline-1 focus:outline-offset-0 focus:shadow-none focus:border-transparent'
|
||||
)
|
||||
}`}
|
||||
placeholder={placeholder || l10n.t(LocalizationKey.commonSearch)}
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
disabled={!searchReady}
|
||||
/>
|
||||
|
||||
{value && (
|
||||
<button onClick={reset} className="absolute inset-y-0 right-0 pr-3 flex items-center">
|
||||
<XCircleIcon className={`h-5 w-5 ${getColors(`text-gray-400`, 'text-[var(--vscode-input-foreground)]')}`} aria-hidden="true" />
|
||||
</button>
|
||||
<TextField
|
||||
name='search'
|
||||
icon={(
|
||||
<MagnifyingGlassIcon className={`h-4 w-4 text-[var(--vscode-input-foreground)]`} aria-hidden="true" />
|
||||
)}
|
||||
</div>
|
||||
value={value}
|
||||
placeholder={placeholder || l10n.t(LocalizationKey.commonSearch)}
|
||||
disabled={!searchReady}
|
||||
onChange={handleChange}
|
||||
onReset={reset}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<RefreshDashboardData />
|
||||
|
||||
@@ -1,37 +1,28 @@
|
||||
import * as React from 'react';
|
||||
import useThemeColors from '../../hooks/useThemeColors';
|
||||
import { TextField } from '../Common/TextField';
|
||||
|
||||
export interface IDetailsInputProps {
|
||||
name: string;
|
||||
value: string;
|
||||
onChange: (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
|
||||
onChange: (value: string) => void;
|
||||
isTextArea?: boolean;
|
||||
}
|
||||
|
||||
export const DetailsInput: React.FunctionComponent<IDetailsInputProps> = ({ value, isTextArea, onChange }: React.PropsWithChildren<IDetailsInputProps>) => {
|
||||
const { getColors } = useThemeColors();
|
||||
|
||||
export const DetailsInput: React.FunctionComponent<IDetailsInputProps> = ({ name, value, isTextArea, onChange }: React.PropsWithChildren<IDetailsInputProps>) => {
|
||||
if (isTextArea) {
|
||||
return (
|
||||
<textarea
|
||||
rows={3}
|
||||
className={`py-1 px-2 sm:text-sm border w-full ${getColors(
|
||||
'bg-white dark:bg-vulcan-300 border-gray-300 dark:border-vulcan-100 text-vulcan-500 dark:text-whisper-500 placeholder-gray-400 dark:placeholder-whisper-800 focus:outline-none',
|
||||
'bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] border-[var(--vscode-input-border)] placeholder-[var(--vscode-input-placeholderForeground)] focus:outline-[var(--vscode-focusBorder)] focus:outline-1 focus:outline-offset-0 focus:shadow-none focus:border-transparent'
|
||||
)
|
||||
}`}
|
||||
<TextField
|
||||
name={name}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
multiline
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<input
|
||||
className={`py-1 px-2 sm:text-sm border w-full ${getColors(
|
||||
'bg-white dark:bg-vulcan-300 border-gray-300 dark:border-vulcan-100 text-vulcan-500 dark:text-whisper-500 placeholder-gray-400 dark:placeholder-whisper-800 focus:outline-none',
|
||||
'bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] border-[var(--vscode-input-border)] placeholder-[var(--vscode-input-placeholderForeground)] focus:outline-[var(--vscode-focusBorder)] focus:outline-1 focus:outline-offset-0 focus:shadow-none focus:border-transparent'
|
||||
)
|
||||
}`}
|
||||
<TextField
|
||||
name={name}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
/>
|
||||
|
||||
@@ -206,7 +206,7 @@ export const DetailsSlideOver: React.FunctionComponent<IDetailsSlideOverProps> =
|
||||
{l10n.t(LocalizationKey.dashboardMediaMetadataPanelFieldFileName)}
|
||||
</label>
|
||||
<div className="relative mt-1">
|
||||
<DetailsInput value={name || ""} onChange={(e) => setFilename(`${e.target.value}.${extension}`)} />
|
||||
<DetailsInput name={`filename`} value={name || ""} onChange={(e) => setFilename(`${e}.${extension}`)} />
|
||||
|
||||
<div className="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none">
|
||||
<span className={`sm:text-sm placeholder-[var(--vscode-input-placeholderForeground)]`}>.{extension}</span>
|
||||
@@ -219,7 +219,7 @@ export const DetailsSlideOver: React.FunctionComponent<IDetailsSlideOverProps> =
|
||||
{l10n.t(LocalizationKey.dashboardMediaCommonTitle)}
|
||||
</label>
|
||||
<div className="mt-1">
|
||||
<DetailsInput value={title || ""} onChange={(e) => setTitle(e.target.value)} />
|
||||
<DetailsInput name={`title`} value={title || ""} onChange={(e) => setTitle(e)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -229,7 +229,7 @@ export const DetailsSlideOver: React.FunctionComponent<IDetailsSlideOverProps> =
|
||||
{l10n.t(LocalizationKey.dashboardMediaCommonCaption)}
|
||||
</label>
|
||||
<div className="mt-1">
|
||||
<DetailsInput value={caption || ""} onChange={(e) => setCaption(e.target.value)} isTextArea />
|
||||
<DetailsInput name={`caption`} value={caption || ""} onChange={(e) => setCaption(e)} isTextArea />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -239,7 +239,7 @@ export const DetailsSlideOver: React.FunctionComponent<IDetailsSlideOverProps> =
|
||||
{l10n.t(LocalizationKey.dashboardMediaCommonAlt)}
|
||||
</label>
|
||||
<div className="mt-1">
|
||||
<DetailsInput value={alt || ""} onChange={(e) => setAlt(e.target.value)} isTextArea />
|
||||
<DetailsInput name={`alt`} value={alt || ""} onChange={(e) => setAlt(e)} isTextArea />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -52,7 +52,7 @@ export const NewForm: React.FunctionComponent<INewFormProps> = ({
|
||||
name='title'
|
||||
value={title}
|
||||
placeholder={l10n.t(LocalizationKey.dashboardSnippetsViewNewFormSnippetInputTitlePlaceholder)}
|
||||
onChange={(e) => onTitleUpdate(e.currentTarget.value)}
|
||||
onChange={(e) => onTitleUpdate(e)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -66,7 +66,7 @@ export const NewForm: React.FunctionComponent<INewFormProps> = ({
|
||||
name='description'
|
||||
value={description}
|
||||
placeholder={l10n.t(LocalizationKey.dashboardSnippetsViewNewFormSnippetInputDescriptionPlaceholder)}
|
||||
onChange={(e) => onDescriptionUpdate(e.currentTarget.value)}
|
||||
onChange={(e) => onDescriptionUpdate(e)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -84,7 +84,7 @@ export const NewForm: React.FunctionComponent<INewFormProps> = ({
|
||||
name='snippet'
|
||||
value={body}
|
||||
placeholder={l10n.t(LocalizationKey.dashboardSnippetsViewNewFormSnippetInputSnippetPlaceholder)}
|
||||
onChange={(e) => onBodyUpdate(e.currentTarget.value)}
|
||||
onChange={(e) => onBodyUpdate(e)}
|
||||
isTextArea
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,48 +1,33 @@
|
||||
import * as React from 'react';
|
||||
import useThemeColors from '../../hooks/useThemeColors';
|
||||
import { TextField } from '../Common/TextField';
|
||||
|
||||
export interface ISnippetInputProps {
|
||||
name: string;
|
||||
value?: string;
|
||||
placeholder?: string;
|
||||
onChange?: (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
|
||||
onChange?: (value: string) => void;
|
||||
isTextArea?: boolean;
|
||||
}
|
||||
|
||||
export const SnippetInput: React.FunctionComponent<ISnippetInputProps> = ({ name, value, placeholder, isTextArea, onChange }: React.PropsWithChildren<ISnippetInputProps>) => {
|
||||
const { getColors } = useThemeColors();
|
||||
|
||||
if (isTextArea) {
|
||||
return (
|
||||
<textarea
|
||||
<TextField
|
||||
name={name}
|
||||
value={value || ''}
|
||||
placeholder={placeholder}
|
||||
rows={5}
|
||||
className={`block w-full sm:text-sm ${
|
||||
getColors(
|
||||
'focus:outline-none border-gray-300 text-vulcan-500',
|
||||
'border-transparent bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] placeholder-[var(--vscode-input-placeholderForeground)] focus:outline-[var(--vscode-focusBorder)] focus:outline-1 focus:outline-offset-0 focus:shadow-none focus:border-transparent'
|
||||
)
|
||||
}`}
|
||||
onChange={onChange}
|
||||
multiline
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<input
|
||||
type="text"
|
||||
<TextField
|
||||
name={name}
|
||||
value={value || ''}
|
||||
placeholder={placeholder}
|
||||
className={`block w-full sm:text-sm ${
|
||||
getColors(
|
||||
'focus:outline-none border-gray-300 text-vulcan-500',
|
||||
'border-transparent bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] placeholder-[var(--vscode-input-placeholderForeground)] focus:outline-[var(--vscode-focusBorder)] focus:outline-1 focus:outline-offset-0 focus:shadow-none focus:border-transparent'
|
||||
)
|
||||
}`}
|
||||
onChange={onChange}
|
||||
/>
|
||||
onChange={onChange} />
|
||||
);
|
||||
};
|
||||
@@ -3,6 +3,7 @@ import { ChevronDownIcon } from '@heroicons/react/24/outline';
|
||||
import { Choice, SnippetField, SnippetInfoField } from '../../../models';
|
||||
import useThemeColors from '../../hooks/useThemeColors';
|
||||
import { useEffect } from 'react';
|
||||
import { TextField } from '../Common/TextField';
|
||||
|
||||
export interface ISnippetInputFieldProps {
|
||||
field: SnippetField;
|
||||
@@ -32,11 +33,10 @@ export const SnippetInputField: React.FunctionComponent<ISnippetInputFieldProps>
|
||||
<select
|
||||
name={field.name}
|
||||
value={field.value || ''}
|
||||
className={`block w-full sm:text-sm ${getColors(
|
||||
'focus:outline-none border-gray-300 text-vulcan-500',
|
||||
'border-transparent bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] placeholder-[var(--vscode-input-placeholderForeground)] focus:outline-[var(--vscode-focusBorder)] focus:outline-1 focus:outline-offset-0 focus:shadow-none focus:border-transparent'
|
||||
)
|
||||
}`}
|
||||
className={`block w-full sm:text-sm pr-2 appearance-none disabled:opacity-50 rounded bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] placeholder-[var(--vscode-input-placeholderForeground)] border-[var(--frontmatter-border)] focus:border-[var(--vscode-focusBorder)] focus:outline-0`}
|
||||
style={{
|
||||
boxShadow: "none"
|
||||
}}
|
||||
onChange={(e) => onValueChange(field, e.target.value)}
|
||||
>
|
||||
{(field.choices || [])?.map((option: string | Choice, index: number) =>
|
||||
@@ -59,31 +59,21 @@ export const SnippetInputField: React.FunctionComponent<ISnippetInputFieldProps>
|
||||
|
||||
if (field.type === 'string' && !field.single) {
|
||||
return (
|
||||
<textarea
|
||||
<TextField
|
||||
name={field.name}
|
||||
value={field.value || ''}
|
||||
className={`block w-full sm:text-sm h-auto ${getColors(
|
||||
'focus:outline-none border-gray-300 text-vulcan-500',
|
||||
'border-transparent bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] placeholder-[var(--vscode-input-placeholderForeground)] focus:outline-[var(--vscode-focusBorder)] focus:outline-1 focus:outline-offset-0 focus:shadow-none focus:border-transparent'
|
||||
)
|
||||
}`}
|
||||
onChange={(e) => onValueChange(field, e.currentTarget.value)}
|
||||
onChange={(e) => onValueChange(field, e)}
|
||||
rows={4}
|
||||
multiline
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<input
|
||||
type="text"
|
||||
<TextField
|
||||
name={field.name}
|
||||
value={field.value || ''}
|
||||
className={`block w-full sm:text-sm ${getColors(
|
||||
'focus:outline-none border-gray-300 text-vulcan-500',
|
||||
'border-transparent bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] placeholder-[var(--vscode-input-placeholderForeground)] focus:outline-[var(--vscode-focusBorder)] focus:outline-1 focus:outline-offset-0 focus:shadow-none focus:border-transparent'
|
||||
)
|
||||
}`}
|
||||
onChange={(e) => onValueChange(field, e.currentTarget.value)}
|
||||
onChange={(e) => onValueChange(field, e)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { FunnelIcon, XCircleIcon } from '@heroicons/react/24/outline';
|
||||
import * as React from 'react';
|
||||
import { TextField } from '../Common/TextField';
|
||||
|
||||
export interface IFilterInputProps {
|
||||
label?: string;
|
||||
@@ -29,27 +30,17 @@ export const FilterInput: React.FunctionComponent<IFilterInputProps> = ({
|
||||
)
|
||||
}
|
||||
|
||||
<div className="relative flex justify-center">
|
||||
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<TextField
|
||||
name='filter'
|
||||
icon={(
|
||||
<FunnelIcon className={`h-4 w-4 text-[var(--vscode-input-foreground)]`} aria-hidden="true" />
|
||||
</div>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
name="filter"
|
||||
className={`block w-full py-2 pl-10 pr-3 sm:text-sm appearance-none disabled:opacity-50 rounded bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] border-[var(--vscode-input-border)] placeholder-[var(--vscode-input-placeholderForeground)] focus:outline-[var(--vscode-focusBorder)] focus:outline-1 focus:outline-offset-0 focus:shadow-none focus:border-transparent`}
|
||||
placeholder={placeholder || ""}
|
||||
value={value}
|
||||
onChange={(e) => onChange && onChange(e.target.value)}
|
||||
disabled={disabled}
|
||||
/>
|
||||
|
||||
{value && (
|
||||
<button onClick={onReset} className="absolute inset-y-0 right-0 pr-3 flex items-center">
|
||||
<XCircleIcon className={`h-5 w-5 text-[var(--vscode-input-foreground)]`} aria-hidden="true" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
value={value}
|
||||
placeholder={placeholder || ""}
|
||||
disabled={disabled}
|
||||
onChange={onChange}
|
||||
onReset={onReset}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user