@fluent-windows/core
Version:
React components that inspired by Microsoft's Fluent Design System.
109 lines (104 loc) • 3.4 kB
JavaScript
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
import * as React from 'react';
import classNames from 'classnames';
import { createUseStyles } from '@fluent-windows/styles';
import { styles } from './Input.styled';
import { InputPropTypes } from './Input.type';
import { toUpperCase } from '../utils';
import FormLabel from '../FormLabel';
import { CloseLine as CloseLineIconIcon } from '@fluent-windows/icons';
import Transition from '../Transition';
import IconButton from '../IconButton';
import TextArea from './components/TextArea';
export const name = 'Input';
const useStyles = createUseStyles(styles, {
name
});
const Input = React.forwardRef((props, ref) => {
const {
className: classNameProp,
style,
value,
onChange,
onFocus,
onBlur,
label,
placeholder,
disabled,
cleared,
password,
error,
// TODO cleared 和 suffix 同时存在时应该 warning
suffix = null,
ghost,
...rest
} = props;
const clearedRef = React.useRef(null);
const [_value, _setValue] = React.useState(value);
const handleChange = React.useCallback(e => {
onChange && onChange(e ? e.target.value : '');
_setValue(e ? e.target.value : '');
}, [onChange]);
const handleClear = React.useCallback(e => {
e.preventDefault();
e.stopPropagation();
handleChange(null); // TODO 应该引入 warning 当前组件为非受控组件时提示
}, [handleChange]);
const _label = React.useMemo(() => label ? toUpperCase(label) : '', [label]);
const [focus, setFocus] = React.useState(false);
const handleFocus = React.useCallback(e => {
typeof onFocus === 'function' && onFocus(e);
setFocus(true);
}, [onFocus]);
const handleBlur = React.useCallback(e => {
typeof onBlur === 'function' && onBlur(e);
setFocus(false);
}, [onBlur]);
const classes = useStyles({ ...props,
focus,
_value
});
const wrapperClassName = classNames(classes.wrapper, {
[classes.disabled]: disabled
});
const className = classNames(classes.root, {
[classes.error]: error,
[classes.ghost]: ghost
}, classNameProp);
return React.createElement(FormLabel, {
className: wrapperClassName,
label: _label,
style: style
}, React.createElement("div", null, React.createElement("input", _extends({
className: className,
ref: ref,
value: value,
onChange: handleChange,
onFocus: handleFocus,
onBlur: handleBlur,
placeholder: placeholder,
disabled: disabled,
type: password ? 'password' : 'text'
}, rest)), suffix && React.createElement("div", {
className: classes.suffix
}, suffix), cleared && React.createElement(Transition, {
visible: !!value,
wrapper: false
}, React.createElement(IconButton, {
className: classes.clearedIcon,
onClick: handleClear,
size: "small",
ref: clearedRef
}, React.createElement(CloseLineIconIcon, null)))));
});
Object.defineProperty(Input, 'TextArea', {
get() {
return TextArea;
}
});
Input.displayName = `F${name}`;
Input.propTypes = InputPropTypes;
Input.defaultProps = {
suffix: null
};
export default Input;