mattermost/webapp/channels/src/components/quick_input/quick_input.tsx

196 lines
5.6 KiB
TypeScript
Raw Normal View History

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import classNames from 'classnames';
import type {ReactComponentLike} from 'prop-types';
import React, {useCallback, useEffect, useRef} from 'react';
import type {ReactNode} from 'react';
import {FormattedMessage} from 'react-intl';
import WithTooltip from 'components/with_tooltip';
export type Props = {
/**
* An optional React component that will be used instead of an HTML input when rendering
*/
inputComponent?: ReactComponentLike;
/**
* The string value displayed in this input
*/
value?: string;
/**
* When true, and an onClear callback is defined, show an X on the input field that clears
* the input when clicked.
*/
clearable?: boolean;
/**
* The optional tooltip text to display on the X shown when clearable. Pass a components
* such as FormattedMessage to localize.
*/
clearableTooltipText?: string | ReactNode;
/**
* Callback to clear the input value, and used in tandem with the clearable prop above.
*/
onClear?: () => void;
/**
* ClassName for the clear button container
*/
clearClassName?: string;
/**
* Callback to handle the change event of the input
*/
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
/**
* Callback to handle the key up of the input
*/
onKeyUp?: (event: React.KeyboardEvent) => void;
Initial version of the new search interface (#27301) * Initial version of the new search interface * Fixing CI * style tweaks * tweaks to date picker in search * change search input to button * Addressing a lot of small problems * Addressing current search visualization * Fixing problem on filter autocompletion * Adding some more fixes * Tiny style ajustment * Removing unnecessary slice call * Adding search extensibility * Improving the extensibility * Fixing and refactoring a bit * On clear click, clear the current search * splitting components for simplicity * tweaks to file ext search * Addressing PR review comments and adding color to the extensions search icons * Improving a bit the extension search * Fixing CI * Fixing some bugs * Keep the focus on search input whenever we change the search type * Adding SearchHint tests * Adding search_box_type_selector tests * Adding tests for the SearchBox component * Adding tests for search box suggestions * Adding SearchBoxInput tests * Splitting extension suggestion component and provider * ExtensionSuggestion tests * Removing unneeded property * Adding SearchBoxhints tests * Adding tests for NewSearch component * Adding tests for the extension suggestion provider * Fixing linter errors * Fixing tests * Fixing linter errors * Fixing linter errors * Adding license check for plugins * Addressing PR review comments * Addressing PR review comments * Addressing PR review comments * Fixing tests * Fixing some cypress tests * More work around cypress tests for search * Some accessibility changes * more work on cypress tests * fixing more cypress tests * Fixing linter errors * Fixing tests * Fixing ctrl+f6 switching * Fixing scrolling on small windows wheneve you are searching * Improve editing in the middle of the search text * Addressing some PR review comments * Addressing some PR review comments * Addressing some PR review comments * Addressing some PR review comments * Fixing tests and linter errors * Fixingls tests and linter errors * Fix type checks * Clearer logic to render plugin or builtin suggestion * Addressing PR review changes * Addressing PR review changes * Using selectors for plugin components * Changing uppercase to lowercase on lists of components * Updating tests * Updating snapshots * minor css tweaks * minor css tweak * Adding the search type and the clear button * Fixing problem with the filetype selector * fixing linter errors * Some fixes * More linter fixes * Reverting prettier auto-formating * Fixing CI * Fixing CI * Fixing chrome problem * Fixing CI * Addressing PR review comments --------- Co-authored-by: Matthew Birtch <mattbirtch@gmail.com> Co-authored-by: Christopher Speller <crspeller@gmail.com> Co-authored-by: Mattermost Build <build@mattermost.com>
2024-10-14 06:56:35 -04:00
/**
* Callback to handle the key down of the input
*/
onKeyDown?: (event: React.KeyboardEvent) => void;
/**
* When true, and an onClear callback is defined, show an X on the input field even if
* the input is empty.
*/
clearableWithoutValue?: boolean;
forwardedRef?: ((instance: HTMLInputElement | HTMLTextAreaElement | null) => void) | React.MutableRefObject<HTMLInputElement | HTMLTextAreaElement | null> | null;
maxLength?: number;
className?: string;
placeholder?: string;
autoFocus?: boolean;
type?: string;
id?: string;
onInput?: (e?: React.FormEvent<HTMLInputElement>) => void;
Initial version of the new search interface (#27301) * Initial version of the new search interface * Fixing CI * style tweaks * tweaks to date picker in search * change search input to button * Addressing a lot of small problems * Addressing current search visualization * Fixing problem on filter autocompletion * Adding some more fixes * Tiny style ajustment * Removing unnecessary slice call * Adding search extensibility * Improving the extensibility * Fixing and refactoring a bit * On clear click, clear the current search * splitting components for simplicity * tweaks to file ext search * Addressing PR review comments and adding color to the extensions search icons * Improving a bit the extension search * Fixing CI * Fixing some bugs * Keep the focus on search input whenever we change the search type * Adding SearchHint tests * Adding search_box_type_selector tests * Adding tests for the SearchBox component * Adding tests for search box suggestions * Adding SearchBoxInput tests * Splitting extension suggestion component and provider * ExtensionSuggestion tests * Removing unneeded property * Adding SearchBoxhints tests * Adding tests for NewSearch component * Adding tests for the extension suggestion provider * Fixing linter errors * Fixing tests * Fixing linter errors * Fixing linter errors * Adding license check for plugins * Addressing PR review comments * Addressing PR review comments * Addressing PR review comments * Fixing tests * Fixing some cypress tests * More work around cypress tests for search * Some accessibility changes * more work on cypress tests * fixing more cypress tests * Fixing linter errors * Fixing tests * Fixing ctrl+f6 switching * Fixing scrolling on small windows wheneve you are searching * Improve editing in the middle of the search text * Addressing some PR review comments * Addressing some PR review comments * Addressing some PR review comments * Addressing some PR review comments * Fixing tests and linter errors * Fixingls tests and linter errors * Fix type checks * Clearer logic to render plugin or builtin suggestion * Addressing PR review changes * Addressing PR review changes * Using selectors for plugin components * Changing uppercase to lowercase on lists of components * Updating tests * Updating snapshots * minor css tweaks * minor css tweak * Adding the search type and the clear button * Fixing problem with the filetype selector * fixing linter errors * Some fixes * More linter fixes * Reverting prettier auto-formating * Fixing CI * Fixing CI * Fixing chrome problem * Fixing CI * Addressing PR review comments --------- Co-authored-by: Matthew Birtch <mattbirtch@gmail.com> Co-authored-by: Christopher Speller <crspeller@gmail.com> Co-authored-by: Mattermost Build <build@mattermost.com>
2024-10-14 06:56:35 -04:00
tabIndex?: number;
size?: 'md' | 'lg';
role?: string;
}
const defaultClearableTooltipText = (
<FormattedMessage
id={'input.clear'}
defaultMessage='Clear'
/>);
// A component that can be used to make controlled inputs that function properly in certain
// environments (ie. IE11) where typing quickly would sometimes miss inputs
export const QuickInput = React.memo(({
value = '',
clearable = false,
autoFocus,
forwardedRef,
inputComponent,
clearClassName,
clearableWithoutValue,
clearableTooltipText,
onClear: onClearFromProps,
className,
size = 'md',
...restProps
}: Props) => {
const inputRef = useRef<HTMLInputElement | HTMLTextAreaElement | null>(null);
useEffect(() => {
if (autoFocus) {
requestAnimationFrame(() => {
inputRef.current?.focus();
});
}
/* eslint-disable-next-line react-hooks/exhaustive-deps --
* This 'useEffect' should only run once during mount.
**/
}, []);
useEffect(() => {
if (!inputRef.current || inputRef.current.value === value) {
return;
}
inputRef.current.value = value;
}, [value]);
const setInputRef = useCallback((input: HTMLInputElement) => {
if (forwardedRef) {
if (typeof forwardedRef === 'function') {
forwardedRef(input);
} else {
forwardedRef.current = input;
}
}
inputRef.current = input;
}, [forwardedRef]);
const onClear = useCallback((e: React.MouseEvent<HTMLButtonElement> | React.TouchEvent) => {
e.preventDefault();
e.stopPropagation();
if (onClearFromProps) {
onClearFromProps();
}
inputRef.current?.focus();
}, [onClearFromProps]);
const showClearButton = onClearFromProps && (clearableWithoutValue || (clearable && value));
const inputElement = React.createElement(
inputComponent || 'input',
{
...restProps,
ref: setInputRef,
defaultValue: value, // Only set the defaultValue since the real one will be updated using the 'useEffect' above
className: classNames(className, {
'form-control--lg': size === 'lg',
}),
},
);
return (
<div className='input-wrapper'>
{inputElement}
{showClearButton && (
<WithTooltip title={clearableTooltipText || defaultClearableTooltipText}>
<button
data-testid='input-clear'
className={classNames(clearClassName, 'input-clear visible')}
onClick={onClear}
>
<span
className='input-clear-x'
aria-hidden='true'
>
<i className='icon icon-close-circle'/>
</span>
</button>
</WithTooltip>
)}
</div>
);
});
type ForwardedProps = Omit<React.ComponentPropsWithoutRef<typeof QuickInput>, 'forwardedRef'>;
const forwarded = React.forwardRef<HTMLInputElement | HTMLTextAreaElement, ForwardedProps>((props, ref) => (
<QuickInput
forwardedRef={ref}
{...props}
/>
));
forwarded.displayName = 'QuickInput';
export default forwarded;