mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
SearchInput refactoring
Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>
This commit is contained in:
parent
14e88a5bb6
commit
de33f52a30
@ -11,7 +11,7 @@ import { navigation } from "../../navigation";
|
||||
import { ItemListLayout } from "../item-object-list/item-list-layout";
|
||||
import { t, Trans } from "@lingui/macro";
|
||||
import { _i18n } from "../../i18n";
|
||||
import { SearchInput } from "../input";
|
||||
import { SearchInputUrl } from "../input";
|
||||
|
||||
enum sortBy {
|
||||
name = "name",
|
||||
@ -72,7 +72,7 @@ export class HelmCharts extends Component<Props> {
|
||||
(items: HelmChart[]) => items.filter(item => !item.deprecated)
|
||||
]}
|
||||
customizeHeader={() => (
|
||||
<SearchInput placeholder={_i18n._(t`Search Helm Charts`)} />
|
||||
<SearchInputUrl placeholder={_i18n._(t`Search Helm Charts`)} />
|
||||
)}
|
||||
renderTableHeader={[
|
||||
{ className: "icon" },
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
export * from './input'
|
||||
export * from './search-input'
|
||||
export * from './search-input-url'
|
||||
export * from './file-input'
|
||||
|
||||
@ -24,6 +24,7 @@ export type InputProps<T = string> = Omit<InputElementProps, "onChange" | "onSub
|
||||
showValidationLine?: boolean; // show animated validation line for async validators
|
||||
iconLeft?: string | React.ReactNode; // material-icon name in case of string-type
|
||||
iconRight?: string | React.ReactNode;
|
||||
contentRight?: string | React.ReactNode; // Any component of string goes after iconRight
|
||||
validators?: Validator | Validator[];
|
||||
onChange?(value: T, evt: React.ChangeEvent<InputElement>): void;
|
||||
onSubmit?(value: T): void;
|
||||
@ -258,7 +259,7 @@ export class Input extends React.Component<InputProps, State> {
|
||||
render() {
|
||||
const {
|
||||
multiLine, showValidationLine, validators, theme, maxRows, children,
|
||||
maxLength, rows, disabled, autoSelectOnFocus, iconLeft, iconRight,
|
||||
maxLength, rows, disabled, autoSelectOnFocus, iconLeft, iconRight, contentRight,
|
||||
...inputProps
|
||||
} = this.props;
|
||||
const { focused, dirty, valid, validating, errors } = this.state;
|
||||
@ -291,6 +292,7 @@ export class Input extends React.Component<InputProps, State> {
|
||||
{isString(iconLeft) ? <Icon material={iconLeft} /> : iconLeft}
|
||||
{multiLine ? <textarea {...inputProps as any} /> : <input {...inputProps as any} />}
|
||||
{isString(iconRight) ? <Icon material={iconRight} /> : iconRight}
|
||||
{contentRight}
|
||||
</label>
|
||||
<div className="input-info flex gaps">
|
||||
{!valid && dirty && (
|
||||
|
||||
49
src/renderer/components/input/search-input-url.tsx
Normal file
49
src/renderer/components/input/search-input-url.tsx
Normal file
@ -0,0 +1,49 @@
|
||||
import React from "react";
|
||||
import debounce from "lodash/debounce";
|
||||
import { autorun, observable } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { getSearch, setSearch } from "../../navigation";
|
||||
import { InputProps } from "./input";
|
||||
import { SearchInput } from "./search-input";
|
||||
|
||||
interface Props extends InputProps {
|
||||
compact?: boolean; // show only search-icon when not focused
|
||||
}
|
||||
|
||||
@observer
|
||||
export class SearchInputUrl extends React.Component<Props> {
|
||||
@observable inputVal = ""; // fix: use empty string to avoid react warnings
|
||||
|
||||
@disposeOnUnmount
|
||||
updateInput = autorun(() => this.inputVal = getSearch())
|
||||
updateUrl = debounce((val: string) => setSearch(val), 250)
|
||||
|
||||
setValue = (value: string) => {
|
||||
this.inputVal = value;
|
||||
this.updateUrl(value);
|
||||
}
|
||||
|
||||
clear = () => {
|
||||
this.setValue("");
|
||||
this.updateUrl.flush();
|
||||
}
|
||||
|
||||
onChange = (val: string, evt: React.ChangeEvent<any>) => {
|
||||
this.setValue(val);
|
||||
if (this.props.onChange) {
|
||||
this.props.onChange(val, evt);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { inputVal } = this;
|
||||
return (
|
||||
<SearchInput
|
||||
value={inputVal}
|
||||
onChange={this.onChange}
|
||||
onClear={this.clear}
|
||||
{...this.props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,10 @@
|
||||
|
||||
> label {
|
||||
color: inherit;
|
||||
background: none;
|
||||
border: none;
|
||||
border-radius: $radius;
|
||||
box-shadow: 0 0 0 1px $halfGray;
|
||||
padding: 6px 6px 6px 10px;
|
||||
|
||||
.Icon {
|
||||
|
||||
@ -1,24 +1,22 @@
|
||||
import "./search-input.scss";
|
||||
|
||||
import React from "react";
|
||||
import debounce from "lodash/debounce"
|
||||
import { autorun, observable } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { t } from "@lingui/macro";
|
||||
import { Icon } from "../icon";
|
||||
import { observer } from "mobx-react";
|
||||
import { _i18n } from "../../i18n";
|
||||
import { cssNames } from "../../utils";
|
||||
import { Icon } from "../icon";
|
||||
import { Input, InputProps } from "./input";
|
||||
import { getSearch, setSearch } from "../../navigation";
|
||||
import { _i18n } from '../../i18n';
|
||||
|
||||
interface Props extends InputProps {
|
||||
compact?: boolean; // show only search-icon when not focused
|
||||
updateUrl?: boolean;
|
||||
closeIcon?: boolean;
|
||||
onClear?: () => void;
|
||||
}
|
||||
|
||||
const defaultProps: Partial<Props> = {
|
||||
autoFocus: true,
|
||||
updateUrl: true,
|
||||
closeIcon: true,
|
||||
get placeholder() {
|
||||
return _i18n._(t`Search...`)
|
||||
},
|
||||
@ -28,36 +26,14 @@ const defaultProps: Partial<Props> = {
|
||||
export class SearchInput extends React.Component<Props> {
|
||||
static defaultProps = defaultProps as object;
|
||||
|
||||
@observable inputVal = this.props.value || ""; // fix: use empty string to avoid react warnings
|
||||
|
||||
@disposeOnUnmount
|
||||
updateInput = autorun(() => {
|
||||
if (this.props.updateUrl) this.inputVal = getSearch();
|
||||
})
|
||||
updateUrl = debounce((val: string) => setSearch(val), 250)
|
||||
|
||||
setValue = (value: string) => {
|
||||
this.inputVal = value;
|
||||
if (this.props.updateUrl) {
|
||||
this.updateUrl(value);
|
||||
}
|
||||
}
|
||||
|
||||
clear = () => {
|
||||
this.setValue("");
|
||||
if (this.props.updateUrl) {
|
||||
this.updateUrl.flush();
|
||||
}
|
||||
if (this.props.onChange) {
|
||||
this.props.onChange("", null);
|
||||
if (this.props.onClear) {
|
||||
this.props.onClear();
|
||||
}
|
||||
}
|
||||
|
||||
onChange = (val: string, evt: React.ChangeEvent<any>) => {
|
||||
this.setValue(val);
|
||||
if (this.props.onChange) {
|
||||
this.props.onChange(val, evt);
|
||||
}
|
||||
this.props.onChange(val, evt);
|
||||
}
|
||||
|
||||
onKeyDown = (evt: React.KeyboardEvent<any>) => {
|
||||
@ -73,16 +49,14 @@ export class SearchInput extends React.Component<Props> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { inputVal } = this;
|
||||
const { className, compact, updateUrl, ...inputProps } = this.props;
|
||||
const icon = inputVal
|
||||
? <Icon small material="close" onClick={this.clear}/>
|
||||
const { className, compact, closeIcon, onClear, ...inputProps } = this.props;
|
||||
const icon = this.props.value
|
||||
? closeIcon ? <Icon small material="close" onClick={this.clear}/> : null
|
||||
: <Icon small material="search"/>
|
||||
return (
|
||||
<Input
|
||||
{...inputProps}
|
||||
className={cssNames("SearchInput", className, { compact })}
|
||||
value={inputVal}
|
||||
onChange={this.onChange}
|
||||
onKeyDown={this.onKeyDown}
|
||||
iconRight={icon}
|
||||
|
||||
@ -22,15 +22,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.SearchInput {
|
||||
label {
|
||||
background: none;
|
||||
border: none;
|
||||
border-radius: $radius;
|
||||
box-shadow: 0 0 0 1px $halfGray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .items {
|
||||
|
||||
@ -12,7 +12,7 @@ import { AddRemoveButtons, AddRemoveButtonsProps } from "../add-remove-buttons";
|
||||
import { NoItems } from "../no-items";
|
||||
import { Spinner } from "../spinner";
|
||||
import { ItemObject, ItemStore } from "../../item.store";
|
||||
import { SearchInput } from "../input";
|
||||
import { SearchInputUrl } from "../input";
|
||||
import { namespaceStore } from "../+namespaces/namespace.store";
|
||||
import { Filter, FilterType, pageFilters } from "./page-filters.store";
|
||||
import { PageFiltersList } from "./page-filters-list";
|
||||
@ -349,7 +349,7 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
||||
[FilterType.NAMESPACE]: true, // namespace-select used instead
|
||||
}}/>
|
||||
</>,
|
||||
search: <SearchInput/>,
|
||||
search: <SearchInputUrl/>,
|
||||
}
|
||||
let header = this.renderHeaderContent(placeholders);
|
||||
if (customizeHeader) {
|
||||
|
||||
@ -4,7 +4,7 @@ import "./virtual-list.scss";
|
||||
|
||||
import React, { Component } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Align, ListChildComponentProps, VariableSizeList } from "react-window";
|
||||
import { Align, ListChildComponentProps, ListOnScrollProps, VariableSizeList } from "react-window";
|
||||
import { cssNames, noop } from "../../utils";
|
||||
import { TableRowProps } from "../table/table-row";
|
||||
import { ItemObject } from "../../item.store";
|
||||
@ -22,7 +22,7 @@ interface Props<T extends ItemObject = any> {
|
||||
readyOffset?: number;
|
||||
selectedItemId?: string;
|
||||
getRow?: (uid: string | number) => React.ReactElement<any>;
|
||||
onScroll?: () => any;
|
||||
onScroll?: (props: ListOnScrollProps) => any;
|
||||
outerRef?: ((instance: unknown) => void) | React.MutableRefObject<unknown>
|
||||
}
|
||||
|
||||
@ -107,7 +107,7 @@ export class VirtualList extends Component<Props, State> {
|
||||
ref={this.listRef}
|
||||
outerRef={outerRef}
|
||||
children={Row}
|
||||
onScroll={() => onScroll()}
|
||||
onScroll={onScroll}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user