mirror of
https://github.com/zoriya/flood.git
synced 2026-06-01 18:47:44 +00:00
TableHeading, Textbox: replace setRef with forwardRef
This commit is contained in:
@@ -26,7 +26,7 @@ interface FilesystemBrowserTextboxStates {
|
||||
|
||||
class FilesystemBrowserTextbox extends React.Component<FilesystemBrowserTextboxProps, FilesystemBrowserTextboxStates> {
|
||||
formRowRef = React.createRef<HTMLDivElement>();
|
||||
textboxRef: HTMLInputElement | null = null;
|
||||
textboxRef = React.createRef<HTMLInputElement>();
|
||||
|
||||
constructor(props: FilesystemBrowserTextboxProps) {
|
||||
super(props);
|
||||
@@ -77,11 +77,11 @@ class FilesystemBrowserTextbox extends React.Component<FilesystemBrowserTextboxP
|
||||
/* eslint-disable react/sort-comp */
|
||||
handleDestinationInputChange = debounce(
|
||||
() => {
|
||||
if (this.textboxRef == null) {
|
||||
if (this.textboxRef.current == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const destination = this.textboxRef.value;
|
||||
const destination = this.textboxRef.current.value;
|
||||
|
||||
if (this.props.onChange) {
|
||||
this.props.onChange(destination);
|
||||
@@ -105,8 +105,8 @@ class FilesystemBrowserTextbox extends React.Component<FilesystemBrowserTextboxP
|
||||
};
|
||||
|
||||
handleItemSelection = (destination: string, isDirectory = true) => {
|
||||
if (this.textboxRef != null) {
|
||||
this.textboxRef.value = destination;
|
||||
if (this.textboxRef.current != null) {
|
||||
this.textboxRef.current.value = destination;
|
||||
}
|
||||
this.setState({destination, isDirectoryListOpen: isDirectory});
|
||||
};
|
||||
@@ -178,9 +178,7 @@ class FilesystemBrowserTextbox extends React.Component<FilesystemBrowserTextboxP
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'torrents.add.destination.placeholder',
|
||||
})}
|
||||
setRef={(ref) => {
|
||||
this.textboxRef = ref;
|
||||
}}>
|
||||
ref={this.textboxRef}>
|
||||
<FormElementAddon onClick={this.handleDirectoryListButtonClick}>
|
||||
<Search />
|
||||
</FormElementAddon>
|
||||
|
||||
@@ -23,7 +23,7 @@ interface TagSelectStates {
|
||||
export default class TagSelect extends React.Component<TagSelectProps, TagSelectStates> {
|
||||
formRowRef = React.createRef<HTMLDivElement>();
|
||||
menuRef = React.createRef<HTMLDivElement>();
|
||||
textboxRef: HTMLInputElement | null = null;
|
||||
textboxRef = React.createRef<HTMLInputElement>();
|
||||
|
||||
tagMenuItems = Object.keys(TorrentFilterStore.taxonomy.tagCounts).reduce((accumulator: React.ReactNodeArray, tag) => {
|
||||
if (tag === '') {
|
||||
@@ -115,8 +115,8 @@ export default class TagSelect extends React.Component<TagSelectProps, TagSelect
|
||||
}
|
||||
|
||||
this.setState({selectedTags}, () => {
|
||||
if (this.textboxRef != null) {
|
||||
this.textboxRef.value = selectedTags.join();
|
||||
if (this.textboxRef.current != null) {
|
||||
this.textboxRef.current.value = selectedTags.join();
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -161,9 +161,7 @@ export default class TagSelect extends React.Component<TagSelectProps, TagSelect
|
||||
addonPlacement="after"
|
||||
defaultValue={defaultValue}
|
||||
placeholder={placeholder}
|
||||
setRef={(ref) => {
|
||||
this.textboxRef = ref;
|
||||
}}>
|
||||
ref={this.textboxRef}>
|
||||
<FormElementAddon onClick={this.toggleOpenState} className="select__indicator">
|
||||
<Chevron />
|
||||
</FormElementAddon>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import classnames from 'classnames';
|
||||
import {FormattedMessage, injectIntl, WrappedComponentProps} from 'react-intl';
|
||||
import {forwardRef, MutableRefObject, ReactNodeArray, useRef, useState} from 'react';
|
||||
import {FormattedMessage, useIntl} from 'react-intl';
|
||||
import {observer} from 'mobx-react';
|
||||
import * as React from 'react';
|
||||
import {useEnsuredForwardedRef} from 'react-use';
|
||||
|
||||
import TorrentListColumns, {TorrentListColumn} from '../../constants/TorrentListColumns';
|
||||
import SettingStore from '../../stores/SettingStore';
|
||||
@@ -12,153 +13,132 @@ const pointerDownStyles = `
|
||||
* { cursor: col-resize !important; }
|
||||
`;
|
||||
|
||||
interface TableHeadingProps extends WrappedComponentProps {
|
||||
interface TableHeadingProps {
|
||||
onCellClick: (column: TorrentListColumn) => void;
|
||||
onWidthsChange: (column: TorrentListColumn, width: number) => void;
|
||||
setRef?: React.RefCallback<HTMLDivElement>;
|
||||
}
|
||||
|
||||
@observer
|
||||
class TableHeading extends React.Component<TableHeadingProps> {
|
||||
focusedCell: TorrentListColumn | null = null;
|
||||
focusedCellWidth: number | null = null;
|
||||
isPointerDown = false;
|
||||
lastPointerX: number | null = null;
|
||||
tableHeading: HTMLDivElement | null = null;
|
||||
resizeLine: HTMLDivElement | null = null;
|
||||
const TableHeading = observer(
|
||||
forwardRef<HTMLDivElement, TableHeadingProps>(({onCellClick, onWidthsChange}: TableHeadingProps, ref) => {
|
||||
const [isPointerDown, setIsPointerDown] = useState<boolean>(false);
|
||||
|
||||
getHeadingElements() {
|
||||
const {intl, onCellClick} = this.props;
|
||||
const focusedCell = useRef<TorrentListColumn>();
|
||||
const focusedCellWidth = useRef<number>();
|
||||
const lastPointerX = useRef<number>();
|
||||
const tableHeading = useEnsuredForwardedRef<HTMLDivElement>(ref as MutableRefObject<HTMLDivElement>);
|
||||
const resizeLine = useRef<HTMLDivElement>(null);
|
||||
|
||||
return SettingStore.floodSettings.torrentListColumns.reduce((accumulator: React.ReactNodeArray, {id, visible}) => {
|
||||
if (!visible) {
|
||||
return accumulator;
|
||||
const intl = useIntl();
|
||||
|
||||
const handlePointerMove = (event: PointerEvent) => {
|
||||
let widthDelta = 0;
|
||||
if (lastPointerX.current != null) {
|
||||
widthDelta = event.clientX - lastPointerX.current;
|
||||
}
|
||||
|
||||
const labelID = TorrentListColumns[id]?.id;
|
||||
if (labelID == null) {
|
||||
return accumulator;
|
||||
let nextCellWidth = 20;
|
||||
if (focusedCellWidth.current != null) {
|
||||
nextCellWidth = focusedCellWidth.current + widthDelta;
|
||||
}
|
||||
|
||||
let handle = null;
|
||||
const width = SettingStore.floodSettings.torrentListColumnWidths[id] || 100;
|
||||
if (nextCellWidth > 20) {
|
||||
focusedCellWidth.current = nextCellWidth;
|
||||
lastPointerX.current = event.clientX;
|
||||
if (resizeLine.current != null && tableHeading.current != null) {
|
||||
resizeLine.current.style.transform = `translate(${Math.max(0, event.clientX)}px, ${
|
||||
tableHeading.current.getBoundingClientRect().top
|
||||
}px)`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (!this.isPointerDown) {
|
||||
handle = (
|
||||
<span
|
||||
className="table__heading__handle"
|
||||
onPointerDown={(event) => {
|
||||
this.handlePointerDown(event, id, width);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
const handlePointerUp = () => {
|
||||
UIStore.removeGlobalStyle(pointerDownStyles);
|
||||
window.removeEventListener('pointerup', handlePointerUp);
|
||||
window.removeEventListener('pointermove', handlePointerMove);
|
||||
|
||||
setIsPointerDown(false);
|
||||
lastPointerX.current = undefined;
|
||||
|
||||
if (resizeLine.current != null) {
|
||||
resizeLine.current.style.opacity = '0';
|
||||
}
|
||||
|
||||
const isSortActive = id === SettingStore.floodSettings.sortTorrents.property;
|
||||
const classes = classnames('table__cell table__heading', {
|
||||
'table__heading--is-sorted': isSortActive,
|
||||
[`table__heading--direction--${SettingStore.floodSettings.sortTorrents.direction}`]: isSortActive,
|
||||
});
|
||||
|
||||
accumulator.push(
|
||||
<div className={classes} key={id} onClick={() => onCellClick(id)} style={{width: `${width}px`}}>
|
||||
<span
|
||||
className="table__heading__label"
|
||||
title={intl.formatMessage({
|
||||
id: labelID,
|
||||
})}>
|
||||
<FormattedMessage id={labelID} />
|
||||
</span>
|
||||
{handle}
|
||||
</div>,
|
||||
);
|
||||
|
||||
return accumulator;
|
||||
}, []);
|
||||
}
|
||||
|
||||
handlePointerMove = (event: PointerEvent) => {
|
||||
let widthDelta = 0;
|
||||
if (this.lastPointerX != null) {
|
||||
widthDelta = event.clientX - this.lastPointerX;
|
||||
}
|
||||
|
||||
let nextCellWidth = 20;
|
||||
if (this.focusedCellWidth != null) {
|
||||
nextCellWidth = this.focusedCellWidth + widthDelta;
|
||||
}
|
||||
|
||||
if (nextCellWidth > 20) {
|
||||
this.focusedCellWidth = nextCellWidth;
|
||||
this.lastPointerX = event.clientX;
|
||||
if (this.resizeLine != null && this.tableHeading != null) {
|
||||
this.resizeLine.style.transform = `translate(${Math.max(0, event.clientX)}px, ${
|
||||
this.tableHeading.getBoundingClientRect().top
|
||||
}px)`;
|
||||
if (focusedCell.current != null && focusedCellWidth.current != null) {
|
||||
onWidthsChange(focusedCell.current, focusedCellWidth.current);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
handlePointerUp = () => {
|
||||
UIStore.removeGlobalStyle(pointerDownStyles);
|
||||
global.document.removeEventListener('pointerup', this.handlePointerUp);
|
||||
global.document.removeEventListener('pointermove', (e) => this.handlePointerMove(e));
|
||||
|
||||
this.isPointerDown = false;
|
||||
this.lastPointerX = null;
|
||||
|
||||
if (this.resizeLine != null) {
|
||||
this.resizeLine.style.opacity = '0';
|
||||
}
|
||||
|
||||
if (this.focusedCell != null && this.focusedCellWidth != null) {
|
||||
this.props.onWidthsChange(this.focusedCell, this.focusedCellWidth);
|
||||
}
|
||||
|
||||
this.focusedCell = null;
|
||||
this.focusedCellWidth = null;
|
||||
};
|
||||
|
||||
handlePointerDown = (event: React.PointerEvent, slug: TorrentListColumn, width: number) => {
|
||||
if (!this.isPointerDown && this.resizeLine != null && this.tableHeading != null) {
|
||||
global.document.addEventListener('pointerup', this.handlePointerUp);
|
||||
global.document.addEventListener('pointermove', this.handlePointerMove);
|
||||
UIStore.addGlobalStyle(pointerDownStyles);
|
||||
|
||||
this.focusedCell = slug;
|
||||
this.focusedCellWidth = width;
|
||||
this.isPointerDown = true;
|
||||
this.lastPointerX = event.clientX;
|
||||
this.resizeLine.style.transform = `translate(${Math.max(0, event.clientX)}px, ${
|
||||
this.tableHeading.getBoundingClientRect().top
|
||||
}px)`;
|
||||
this.resizeLine.style.opacity = '1';
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {setRef} = this.props;
|
||||
focusedCell.current = undefined;
|
||||
focusedCellWidth.current = undefined;
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className="table__row table__row--heading"
|
||||
ref={(ref) => {
|
||||
this.tableHeading = ref;
|
||||
if (setRef != null) {
|
||||
setRef(ref);
|
||||
<div className="table__row table__row--heading" ref={tableHeading}>
|
||||
{SettingStore.floodSettings.torrentListColumns.reduce((accumulator: ReactNodeArray, {id, visible}) => {
|
||||
if (!visible) {
|
||||
return accumulator;
|
||||
}
|
||||
}}>
|
||||
{this.getHeadingElements()}
|
||||
|
||||
const labelID = TorrentListColumns[id]?.id;
|
||||
if (labelID == null) {
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
let handle = null;
|
||||
const width = SettingStore.floodSettings.torrentListColumnWidths[id] || 100;
|
||||
|
||||
if (!isPointerDown) {
|
||||
handle = (
|
||||
<span
|
||||
className="table__heading__handle"
|
||||
onPointerDown={(event) => {
|
||||
if (!isPointerDown && resizeLine.current != null && tableHeading.current != null) {
|
||||
setIsPointerDown(true);
|
||||
|
||||
focusedCell.current = id;
|
||||
focusedCellWidth.current = width;
|
||||
lastPointerX.current = event.clientX;
|
||||
|
||||
window.addEventListener('pointerup', handlePointerUp);
|
||||
window.addEventListener('pointermove', handlePointerMove);
|
||||
UIStore.addGlobalStyle(pointerDownStyles);
|
||||
|
||||
resizeLine.current.style.transform = `translate(${Math.max(0, event.clientX)}px, ${
|
||||
tableHeading.current.getBoundingClientRect().top
|
||||
}px)`;
|
||||
resizeLine.current.style.opacity = '1';
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const isSortActive = id === SettingStore.floodSettings.sortTorrents.property;
|
||||
const classes = classnames('table__cell table__heading', {
|
||||
'table__heading--is-sorted': isSortActive,
|
||||
[`table__heading--direction--${SettingStore.floodSettings.sortTorrents.direction}`]: isSortActive,
|
||||
});
|
||||
|
||||
accumulator.push(
|
||||
<div className={classes} key={id} onClick={() => onCellClick(id)} style={{width: `${width}px`}}>
|
||||
<span
|
||||
className="table__heading__label"
|
||||
title={intl.formatMessage({
|
||||
id: labelID,
|
||||
})}>
|
||||
<FormattedMessage id={labelID} />
|
||||
</span>
|
||||
{handle}
|
||||
</div>,
|
||||
);
|
||||
|
||||
return accumulator;
|
||||
}, [])}
|
||||
<div className="table__cell table__heading table__heading--fill" />
|
||||
<div
|
||||
className="table__heading__resize-line"
|
||||
ref={(ref) => {
|
||||
this.resizeLine = ref;
|
||||
}}
|
||||
/>
|
||||
<div className="table__heading__resize-line" ref={resizeLine} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
export default injectIntl(TableHeading);
|
||||
export default TableHeading;
|
||||
|
||||
@@ -93,7 +93,7 @@ const getEmptyTorrentListNotification = (): ReactNode => {
|
||||
|
||||
@observer
|
||||
class TorrentList extends Component<WrappedComponentProps> {
|
||||
listHeaderRef: HTMLDivElement | null = null;
|
||||
listHeaderRef = createRef<HTMLDivElement>();
|
||||
listViewportRef = createRef<FixedSizeList>();
|
||||
|
||||
torrentListViewportSize = observable.object<{width: number; height: number}>({
|
||||
@@ -123,8 +123,8 @@ class TorrentList extends Component<WrappedComponentProps> {
|
||||
};
|
||||
|
||||
handleViewportScroll = (scrollLeft: number) => {
|
||||
if (this.listHeaderRef != null) {
|
||||
this.listHeaderRef.scrollLeft = scrollLeft;
|
||||
if (this.listHeaderRef.current != null) {
|
||||
this.listHeaderRef.current.scrollLeft = scrollLeft;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -168,9 +168,7 @@ class TorrentList extends Component<WrappedComponentProps> {
|
||||
SettingActions.saveSetting('sortTorrents', sortBy);
|
||||
}}
|
||||
onWidthsChange={this.handleColumnWidthChange}
|
||||
setRef={(ref) => {
|
||||
this.listHeaderRef = ref;
|
||||
}}
|
||||
ref={this.listHeaderRef}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import CSSTransition from 'react-transition-group/CSSTransition';
|
||||
import classnames from 'classnames';
|
||||
import {CSSProperties, forwardRef, MouseEvent, ReactNode} from 'react';
|
||||
import {CSSProperties, forwardRef, MouseEvent, ReactNode, RefObject} from 'react';
|
||||
|
||||
import Overlay from './Overlay';
|
||||
import transitionTimeouts from '../constants/transitionTimeouts';
|
||||
@@ -18,7 +18,7 @@ interface ContextMenuProps {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
triggerRef?: Element | null;
|
||||
triggerRef?: RefObject<Element>;
|
||||
matchTriggerWidth?: boolean;
|
||||
padding?: boolean;
|
||||
scrolling?: boolean;
|
||||
@@ -47,8 +47,8 @@ const ContextMenu = forwardRef<HTMLDivElement, ContextMenuProps>(
|
||||
const dropdownStyle: CSSProperties = {};
|
||||
let shouldRenderAbove = false;
|
||||
|
||||
if (triggerRef) {
|
||||
const buttonBoundingRect = triggerRef.getBoundingClientRect();
|
||||
if (triggerRef?.current) {
|
||||
const buttonBoundingRect = triggerRef.current.getBoundingClientRect();
|
||||
const windowHeight = window.innerHeight;
|
||||
const spaceAbove = buttonBoundingRect.top;
|
||||
const spaceBelow = windowHeight - buttonBoundingRect.bottom;
|
||||
|
||||
@@ -41,9 +41,9 @@ interface SelectStates {
|
||||
export default class Select extends Component<SelectProps, SelectStates> {
|
||||
menuRef = createRef<HTMLDivElement>();
|
||||
|
||||
inputRef: HTMLInputElement | null = null;
|
||||
inputRef = createRef<HTMLInputElement>();
|
||||
|
||||
triggerRef: HTMLButtonElement | null = null;
|
||||
triggerRef = createRef<HTMLButtonElement>();
|
||||
|
||||
static defaultProps = {
|
||||
persistentPlaceholder: false,
|
||||
@@ -167,9 +167,7 @@ export default class Select extends Component<SelectProps, SelectStates> {
|
||||
return (
|
||||
<Button
|
||||
additionalClassNames="select__button"
|
||||
buttonRef={(ref) => {
|
||||
this.triggerRef = ref;
|
||||
}}
|
||||
buttonRef={this.triggerRef}
|
||||
addonPlacement="after"
|
||||
onClick={this.handleTriggerClick}
|
||||
priority={priority}
|
||||
@@ -194,8 +192,8 @@ export default class Select extends Component<SelectProps, SelectStates> {
|
||||
this.props.onSelect(id);
|
||||
}
|
||||
|
||||
if (this.inputRef) {
|
||||
dispatchChangeEvent(this.inputRef);
|
||||
if (this.inputRef.current) {
|
||||
dispatchChangeEvent(this.inputRef.current);
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -258,9 +256,7 @@ export default class Select extends Component<SelectProps, SelectStates> {
|
||||
name={`${id}`}
|
||||
onChange={noop}
|
||||
tabIndex={-1}
|
||||
ref={(ref) => {
|
||||
this.inputRef = ref;
|
||||
}}
|
||||
ref={this.inputRef}
|
||||
type="text"
|
||||
value={selectedID}
|
||||
/>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import classnames from 'classnames';
|
||||
import * as React from 'react';
|
||||
import {Children, cloneElement, forwardRef, ReactElement} from 'react';
|
||||
|
||||
import FormElementAddon from './FormElementAddon';
|
||||
import FormRowItem from './FormRowItem';
|
||||
@@ -8,40 +8,23 @@ import type {FormRowItemProps} from './FormRowItem';
|
||||
|
||||
type TextboxProps = Pick<
|
||||
React.InputHTMLAttributes<HTMLInputElement>,
|
||||
'defaultValue' | 'placeholder' | 'onChange' | 'onClick' | 'autoComplete'
|
||||
'children' | 'defaultValue' | 'placeholder' | 'onChange' | 'onClick' | 'autoComplete'
|
||||
> & {
|
||||
id: string;
|
||||
label?: React.ReactNode;
|
||||
type?: 'text' | 'password';
|
||||
width?: FormRowItemProps['width'];
|
||||
setRef?: React.Ref<HTMLInputElement>;
|
||||
addonPlacement?: 'before' | 'after';
|
||||
labelOffset?: boolean;
|
||||
wrapperClassName?: string;
|
||||
};
|
||||
|
||||
export default class Textbox extends React.Component<TextboxProps> {
|
||||
static defaultProps = {
|
||||
type: 'text',
|
||||
};
|
||||
|
||||
getLabel(): React.ReactNode {
|
||||
const {id, label} = this.props;
|
||||
|
||||
if (label) {
|
||||
return (
|
||||
<label className="form__element__label" htmlFor={id}>
|
||||
{label}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
const Textbox = forwardRef<HTMLInputElement, TextboxProps>(
|
||||
(
|
||||
{
|
||||
children,
|
||||
id,
|
||||
label,
|
||||
addonPlacement,
|
||||
labelOffset,
|
||||
wrapperClassName,
|
||||
@@ -50,17 +33,17 @@ export default class Textbox extends React.Component<TextboxProps> {
|
||||
placeholder,
|
||||
autoComplete,
|
||||
type,
|
||||
setRef,
|
||||
onChange,
|
||||
onClick,
|
||||
} = this.props;
|
||||
|
||||
}: TextboxProps,
|
||||
ref,
|
||||
) => {
|
||||
let addonCount = 0;
|
||||
const childElements = React.Children.map(children, (child) => {
|
||||
const childAsElement = child as React.ReactElement;
|
||||
const childElements = Children.map(children, (child) => {
|
||||
const childAsElement = child as ReactElement;
|
||||
if (childAsElement && childAsElement.type === FormElementAddon) {
|
||||
addonCount += 1;
|
||||
return React.cloneElement(childAsElement, {
|
||||
return cloneElement(childAsElement, {
|
||||
addonIndex: addonCount,
|
||||
addonPlacement,
|
||||
});
|
||||
@@ -78,7 +61,11 @@ export default class Textbox extends React.Component<TextboxProps> {
|
||||
|
||||
return (
|
||||
<FormRowItem width={width}>
|
||||
{this.getLabel()}
|
||||
{label ?? (
|
||||
<label className="form__element__label" htmlFor={id}>
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
<div className={wrapperClasses}>
|
||||
<input
|
||||
className={inputClasses}
|
||||
@@ -87,7 +74,7 @@ export default class Textbox extends React.Component<TextboxProps> {
|
||||
name={id}
|
||||
onChange={onChange}
|
||||
onClick={onClick}
|
||||
ref={setRef}
|
||||
ref={ref}
|
||||
tabIndex={0}
|
||||
type={type}
|
||||
autoComplete={autoComplete}
|
||||
@@ -96,5 +83,16 @@ export default class Textbox extends React.Component<TextboxProps> {
|
||||
</div>
|
||||
</FormRowItem>
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
Textbox.defaultProps = {
|
||||
label: undefined,
|
||||
type: 'text',
|
||||
width: undefined,
|
||||
addonPlacement: undefined,
|
||||
labelOffset: undefined,
|
||||
wrapperClassName: undefined,
|
||||
};
|
||||
|
||||
export default Textbox;
|
||||
|
||||
Reference in New Issue
Block a user