添加 ResultBox 组件
This commit is contained in:
parent
7bbc723b42
commit
c4dd46bafc
|
@ -1,3 +1,6 @@
|
|||
import React from 'react';
|
||||
import ResultBox from '../../../src/components/ResultBox';
|
||||
|
||||
export default {
|
||||
type: 'page',
|
||||
title: '表单页面',
|
||||
|
@ -17,6 +20,38 @@ export default {
|
|||
label: 'Email',
|
||||
type: 'email',
|
||||
name: 'email'
|
||||
},
|
||||
|
||||
{
|
||||
name: 'checkboxes',
|
||||
type: 'checkboxes',
|
||||
joinValues: false,
|
||||
options: [
|
||||
{
|
||||
label: '张学友',
|
||||
value: 'a'
|
||||
},
|
||||
{
|
||||
label: '刘德华',
|
||||
value: 'b'
|
||||
},
|
||||
{
|
||||
label: '黎明',
|
||||
value: 'c'
|
||||
},
|
||||
{
|
||||
label: '郭富城',
|
||||
value: 'd'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
label: 'Result',
|
||||
name: 'checkboxes',
|
||||
component: ({value, onChange}) => {
|
||||
return <ResultBox value={value} onChange={onChange} allowInput />;
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -279,3 +279,106 @@
|
|||
border-color: $active-border;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin input-clear {
|
||||
padding: px2rem(3px);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
svg {
|
||||
fill: $Form-input-iconColor;
|
||||
top: 0;
|
||||
width: px2rem(10px);
|
||||
height: px2rem(10px);
|
||||
}
|
||||
|
||||
&:hover svg {
|
||||
fill: darken($color: $Form-input-iconColor, $amount: 20%);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin input-input {
|
||||
display: flex;
|
||||
background-color: $Form-input-bg;
|
||||
border: $Form-input-borderWidth solid $Form-input-borderColor;
|
||||
border-radius: $Form-input-borderRadius;
|
||||
// height: $Form-input-height;
|
||||
line-height: $Form-input-lineHeight;
|
||||
padding: $Form-input-paddingY $Form-input-paddingX;
|
||||
font-size: $Form-input-fontSize;
|
||||
flex-wrap: wrap;
|
||||
|
||||
input {
|
||||
flex-basis: px2rem(80px);
|
||||
flex-grow: 1;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: $Form-input-color;
|
||||
width: 100%;
|
||||
height: $Form-input-lineHeight * $Form-input-fontSize;
|
||||
|
||||
&::placeholder {
|
||||
color: $Form-input-placeholderColor;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin input-text {
|
||||
position: relative;
|
||||
min-width: $Form-control-widthBase;
|
||||
|
||||
&.is-inline {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&-input {
|
||||
@include input-input();
|
||||
}
|
||||
|
||||
&.is-error > &-input {
|
||||
border-color: $Form-input-onError-borderColor;
|
||||
background-color: $Form-input-onError-bg;
|
||||
}
|
||||
|
||||
&.is-focused > &-input {
|
||||
border-color: $Form-input-onFocused-borderColor;
|
||||
box-shadow: $Form-input-boxShadow;
|
||||
|
||||
@if $Form-input-onFocused-bg !=$Form-input-bg {
|
||||
background-color: $Form-input-onFocused-bg;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-error.is-focused > &-input {
|
||||
border-color: $Form-input-onError-borderColor;
|
||||
}
|
||||
|
||||
&.is-disabled > &-input {
|
||||
color: $text--muted-color;
|
||||
background: $Form-input-onDisabled-bg;
|
||||
border-color: $Form-input-onDisabled-borderColor;
|
||||
}
|
||||
|
||||
&-spinner {
|
||||
line-height: $Form-input-lineHeight * $Form-input-fontSize;
|
||||
}
|
||||
|
||||
&-clear {
|
||||
@include input-clear();
|
||||
}
|
||||
|
||||
// 需要能撑开
|
||||
@include media-breakpoint-up(sm) {
|
||||
&.#{$ns}Form-control--sizeXs > &-input,
|
||||
&.#{$ns}Form-control--sizeSm > &-input,
|
||||
&.#{$ns}Form-control--sizeMd > &-input,
|
||||
&.#{$ns}Form-control--sizeLg > &-input {
|
||||
min-width: 100%;
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -589,6 +589,14 @@ $Remark-borderColor: $borderColor !default;
|
|||
$Remark-onHover-borderColor: $borderColor !default;
|
||||
$Remark-marginLeft: $gap-sm !default;
|
||||
|
||||
$ResultBox-value-bg: #f5f5f5 !default;
|
||||
$ResultBox-value--onHover-bg: #ebebeb !default;
|
||||
$ResultBox-value-color: #000 !default;
|
||||
$ResultBox-value--onDisabled-color: #cccccc !default;
|
||||
$ResultBox-icon-color: #999 !default;
|
||||
$ResultBox-icon--onHover-color: #666666 !default;
|
||||
$ResultBox-icon--onDisabled-color: #ebebeb !default;
|
||||
|
||||
// Form
|
||||
$Form-fontSize: $fontSizeBase !default;
|
||||
$Form-description-color: lighten($text-color, 10%) !default;
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
.#{$ns}ResultBox {
|
||||
@include input-input();
|
||||
flex-wrap: wrap;
|
||||
padding: 0 3px;
|
||||
min-height: $Form-input-height;
|
||||
align-items: center;
|
||||
|
||||
&.is-error {
|
||||
border-color: $Form-input-onError-borderColor;
|
||||
background-color: $Form-input-onError-bg;
|
||||
}
|
||||
|
||||
&.is-focused {
|
||||
border-color: $Form-input-onFocused-borderColor;
|
||||
box-shadow: $Form-input-boxShadow;
|
||||
|
||||
@if $Form-input-onFocused-bg !=$Form-input-bg {
|
||||
background-color: $Form-input-onFocused-bg;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-error.is-focused {
|
||||
border-color: $Form-input-onError-borderColor;
|
||||
}
|
||||
|
||||
&.is-disabled {
|
||||
color: $text--muted-color;
|
||||
background: $Form-input-onDisabled-bg;
|
||||
border-color: $Form-input-onDisabled-borderColor;
|
||||
}
|
||||
|
||||
&-clear {
|
||||
@include input-clear();
|
||||
}
|
||||
|
||||
> svg {
|
||||
display: inline-block;
|
||||
width: 14px;
|
||||
color: $icon-color;
|
||||
}
|
||||
|
||||
> a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&-mid {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
&-value {
|
||||
background: $ResultBox-value-bg;
|
||||
color: $ResultBox-value-color;
|
||||
font-size: $Form-input-fontSize;
|
||||
padding: 0 5px;
|
||||
min-height: 24px;
|
||||
flex-wrap: nowrap;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin: 2px 3px;
|
||||
user-select: none;
|
||||
|
||||
> a {
|
||||
cursor: pointer;
|
||||
margin-left: 5px;
|
||||
color: $ResultBox-icon-color;
|
||||
&:hover {
|
||||
color: $ResultBox-icon--onHover-color;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: $ResultBox-value--onHover-bg;
|
||||
}
|
||||
|
||||
&.is-disabled {
|
||||
pointer-events: none;
|
||||
color: $ResultBox-value--onDisabled-color;
|
||||
|
||||
> a {
|
||||
color: $ResultBox-icon--onDisabled-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-placeholder {
|
||||
color: $Form-input-placeholderColor;
|
||||
user-select: none;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
> input {
|
||||
padding-left: 8px;
|
||||
min-height: 24px;
|
||||
}
|
||||
}
|
|
@ -1,106 +1,3 @@
|
|||
@mixin input-clear {
|
||||
padding: px2rem(3px);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
svg {
|
||||
fill: $Form-input-iconColor;
|
||||
top: 0;
|
||||
width: px2rem(10px);
|
||||
height: px2rem(10px);
|
||||
}
|
||||
|
||||
&:hover svg {
|
||||
fill: darken($color: $Form-input-iconColor, $amount: 20%);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin input-input {
|
||||
display: flex;
|
||||
background-color: $Form-input-bg;
|
||||
border: $Form-input-borderWidth solid $Form-input-borderColor;
|
||||
border-radius: $Form-input-borderRadius;
|
||||
// height: $Form-input-height;
|
||||
line-height: $Form-input-lineHeight;
|
||||
padding: $Form-input-paddingY $Form-input-paddingX;
|
||||
font-size: $Form-input-fontSize;
|
||||
flex-wrap: wrap;
|
||||
|
||||
input {
|
||||
flex-basis: px2rem(80px);
|
||||
flex-grow: 1;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: $Form-input-color;
|
||||
width: 100%;
|
||||
height: $Form-input-lineHeight * $Form-input-fontSize;
|
||||
|
||||
&::placeholder {
|
||||
color: $Form-input-placeholderColor;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin input-text {
|
||||
position: relative;
|
||||
min-width: $Form-control-widthBase;
|
||||
|
||||
&.is-inline {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&-input {
|
||||
@include input-input();
|
||||
}
|
||||
|
||||
&.is-error > &-input {
|
||||
border-color: $Form-input-onError-borderColor;
|
||||
background-color: $Form-input-onError-bg;
|
||||
}
|
||||
|
||||
&.is-focused > &-input {
|
||||
border-color: $Form-input-onFocused-borderColor;
|
||||
box-shadow: $Form-input-boxShadow;
|
||||
|
||||
@if $Form-input-onFocused-bg !=$Form-input-bg {
|
||||
background-color: $Form-input-onFocused-bg;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-error.is-focused > &-input {
|
||||
border-color: $Form-input-onError-borderColor;
|
||||
}
|
||||
|
||||
&.is-disabled > &-input {
|
||||
color: $text--muted-color;
|
||||
background: $Form-input-onDisabled-bg;
|
||||
border-color: $Form-input-onDisabled-borderColor;
|
||||
}
|
||||
|
||||
&-spinner {
|
||||
line-height: $Form-input-lineHeight * $Form-input-fontSize;
|
||||
}
|
||||
|
||||
&-clear {
|
||||
@include input-clear();
|
||||
}
|
||||
|
||||
// 需要能撑开
|
||||
@include media-breakpoint-up(sm) {
|
||||
&.#{$ns}Form-control--sizeXs > &-input,
|
||||
&.#{$ns}Form-control--sizeSm > &-input,
|
||||
&.#{$ns}Form-control--sizeMd > &-input,
|
||||
&.#{$ns}Form-control--sizeLg > &-input {
|
||||
min-width: 100%;
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.#{$ns}TextControl {
|
||||
@include input-text();
|
||||
|
||||
|
|
|
@ -539,6 +539,8 @@ $Combo--horizontal-dragger-top: px2rem(5px);
|
|||
@import '../components/carousel';
|
||||
@import '../components/image-gallery';
|
||||
@import '../components/images';
|
||||
@import '../components/input-box';
|
||||
@import '../components/result-box';
|
||||
|
||||
@import '../components/form/fieldset';
|
||||
@import '../components/form/group';
|
||||
|
@ -558,7 +560,7 @@ $Combo--horizontal-dragger-top: px2rem(5px);
|
|||
@import '../components/form/date';
|
||||
@import '../components/form/date-range';
|
||||
@import '../components/form/image';
|
||||
@import '../components/form/input-box';
|
||||
|
||||
@import '../components/form/file';
|
||||
@import '../components/form/editor';
|
||||
@import '../components/form/rich-text';
|
||||
|
|
|
@ -202,6 +202,8 @@ pre {
|
|||
@import '../components/carousel';
|
||||
@import '../components/image-gallery';
|
||||
@import '../components/images';
|
||||
@import '../components/input-box';
|
||||
@import '../components/result-box';
|
||||
|
||||
@import '../components/form/fieldset';
|
||||
@import '../components/form/group';
|
||||
|
@ -221,7 +223,7 @@ pre {
|
|||
@import '../components/form/date';
|
||||
@import '../components/form/date-range';
|
||||
@import '../components/form/image';
|
||||
@import '../components/form/input-box';
|
||||
|
||||
@import '../components/form/file';
|
||||
@import '../components/form/editor';
|
||||
@import '../components/form/rich-text';
|
||||
|
|
|
@ -67,6 +67,8 @@ $Form-input-borderColor: #cfdadd;
|
|||
@import '../components/carousel';
|
||||
@import '../components/image-gallery';
|
||||
@import '../components/images';
|
||||
@import '../components/input-box';
|
||||
@import '../components/result-box';
|
||||
|
||||
@import '../components/form/fieldset';
|
||||
@import '../components/form/group';
|
||||
|
@ -86,7 +88,7 @@ $Form-input-borderColor: #cfdadd;
|
|||
@import '../components/form/date';
|
||||
@import '../components/form/date-range';
|
||||
@import '../components/form/image';
|
||||
@import '../components/form/input-box';
|
||||
|
||||
@import '../components/form/file';
|
||||
@import '../components/form/editor';
|
||||
@import '../components/form/rich-text';
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
import {ThemeProps, themeable} from '../theme';
|
||||
import React from 'react';
|
||||
import {InputBoxProps} from './InputBox';
|
||||
import uncontrollable from 'uncontrollable';
|
||||
import {Icon} from './icons';
|
||||
import Input from './Input';
|
||||
import {autobind} from '../utils/helper';
|
||||
|
||||
export interface ResultBoxProps
|
||||
extends ThemeProps,
|
||||
Omit<InputBoxProps, 'value' | 'onChange'> {
|
||||
value?: Array<any>;
|
||||
itemRender: (value: any) => JSX.Element;
|
||||
onChange?: (value: Array<any>) => void;
|
||||
|
||||
allowInput?: boolean;
|
||||
inputValue?: string;
|
||||
onInputChange?: (value: string) => void;
|
||||
}
|
||||
|
||||
export class ResultBox extends React.Component<ResultBoxProps> {
|
||||
static defaultProps: Pick<
|
||||
ResultBoxProps,
|
||||
'clearable' | 'placeholder' | 'itemRender'
|
||||
> = {
|
||||
clearable: false,
|
||||
placeholder: '暂无结果',
|
||||
itemRender: (option: any) => <span>{String(option.label)}</span>
|
||||
};
|
||||
|
||||
state = {
|
||||
isFocused: false
|
||||
};
|
||||
|
||||
@autobind
|
||||
clearValue() {
|
||||
const onChange = this.props.onChange;
|
||||
onChange && onChange([]);
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleInputChange(e: React.ChangeEvent<HTMLInputElement>) {
|
||||
const onInputChange = this.props.onInputChange;
|
||||
onInputChange && onInputChange(e.currentTarget.value);
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleFocus(e: any) {
|
||||
const onFocus = this.props.onFocus;
|
||||
onFocus && onFocus(e);
|
||||
this.setState({
|
||||
isFocused: true
|
||||
});
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleBlur(e: any) {
|
||||
const onBlur = this.props.onBlur;
|
||||
onBlur && onBlur(e);
|
||||
this.setState({
|
||||
isFocused: false
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
className,
|
||||
classnames: cx,
|
||||
classPrefix,
|
||||
clearable,
|
||||
disabled,
|
||||
hasError,
|
||||
value,
|
||||
placeholder,
|
||||
result,
|
||||
children,
|
||||
itemRender,
|
||||
onInputChange,
|
||||
inputValue,
|
||||
allowInput,
|
||||
...rest
|
||||
} = this.props;
|
||||
const isFocused = this.state.isFocused;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cx(
|
||||
'ResultBox',
|
||||
className,
|
||||
isFocused ? 'is-focused' : '',
|
||||
disabled ? 'is-disabled' : '',
|
||||
hasError ? 'is-error' : ''
|
||||
)}
|
||||
>
|
||||
{Array.isArray(value) && value.length ? (
|
||||
value.map((item, index) => (
|
||||
<div className={cx('ResultBox-value')} key={index}>
|
||||
<span className={cx('ResultBox-valueLabel')}>
|
||||
{itemRender(item)}
|
||||
</span>
|
||||
<a>
|
||||
<Icon icon="close" />
|
||||
</a>
|
||||
</div>
|
||||
))
|
||||
) : allowInput ? null : (
|
||||
<span className={cx('ResultBox-placeholder')}>
|
||||
{placeholder || '无'}
|
||||
</span>
|
||||
)}
|
||||
|
||||
{allowInput ? (
|
||||
<Input
|
||||
{...rest}
|
||||
value={inputValue || ''}
|
||||
onChange={this.handleInputChange}
|
||||
placeholder={
|
||||
Array.isArray(value) && value.length
|
||||
? '手动输入内容'
|
||||
: placeholder
|
||||
}
|
||||
onFocus={this.handleFocus}
|
||||
onBlur={this.handleBlur}
|
||||
/>
|
||||
) : (
|
||||
<span className={cx('ResultBox-mid')} />
|
||||
)}
|
||||
|
||||
{clearable && !disabled && Array.isArray(value) && value.length ? (
|
||||
<a onClick={this.clearValue} className={cx('ResultBox-clear')}>
|
||||
<Icon icon="close" className="icon" />
|
||||
</a>
|
||||
) : null}
|
||||
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(
|
||||
uncontrollable(ResultBox, {
|
||||
value: 'onChange',
|
||||
inputValue: 'onInputChange'
|
||||
})
|
||||
);
|
Loading…
Reference in New Issue