优化 checkboxes

This commit is contained in:
2betop 2020-05-12 14:17:43 +08:00
parent 4ed9216d83
commit 94363cd1c5
5 changed files with 84 additions and 74 deletions

View File

@ -2,6 +2,7 @@
margin: 0 $gap-sm 0 0;
font-weight: $fontWeightNormal;
user-select: none;
pointer-events: none;
input {
opacity: 0;
@ -20,8 +21,10 @@
display: inline-block;
vertical-align: middle;
position: relative;
pointer-events: all;
+ span {
pointer-events: all;
margin-left: $Checkbox-gap;
cursor: pointer;
@ -230,6 +233,7 @@
color: $text--muted-color;
margin-left: $Checkbox-gap;
margin-top: $gap-xs;
pointer-events: all;
}
}
@ -274,6 +278,22 @@
}
.#{$ns}Checkboxes {
> .#{$ns}Checkbox {
display: block;
height: $Form-input-height;
line-height: $Form-input-lineHeight;
font-size: $Form-input-fontSize;
padding: (
$Form-input-height - $Form-input-lineHeight * $Form-input-fontSize
)/2 $gap-sm
($Form-input-height - $Form-input-lineHeight * $Form-input-fontSize)/2
($gap-sm + $Checkbox-size);
}
&--inline > .#{$ns}Checkbox {
display: inline-block;
}
&-addBtn {
display: block;
cursor: pointer;

View File

@ -27,8 +27,6 @@
&-items {
flex-grow: 1;
height: 0;
overflow: auto;
}
&-item {

View File

@ -8,117 +8,111 @@ import React from 'react';
import uncontrollable from 'uncontrollable';
import Checkbox from './Checkbox';
import chunk from 'lodash/chunk';
import {ClassNamesFn, themeable} from '../theme';
import {Option, OptionProps, value2array} from './Select';
import {ClassNamesFn, themeable, ThemeProps} from '../theme';
import {Option, value2array, Options} from './Select';
import find from 'lodash/find';
// import isPlainObject from 'lodash/isPlainObject';
interface CheckboxesProps extends OptionProps {
id?: string;
key?: string;
interface CheckboxesProps extends ThemeProps {
options: Options;
className?: string;
type: string;
placeholder?: string;
disabled?: boolean;
value?: string;
onChange?: Function;
value?: Array<any>;
onChange?: (value: Array<Option>) => void;
inline?: boolean;
checked?: boolean;
labelClassName?: string;
classPrefix: string;
classnames: ClassNamesFn;
option2value?: (option: Option) => any;
itemClassName?: string;
itemRender: (option: Option) => JSX.Element;
disabled?: boolean;
}
export class Checkboxes extends React.PureComponent<CheckboxesProps, any> {
export class Checkboxes extends React.Component<CheckboxesProps, any> {
static defaultProps = {
joinValues: true,
extractValue: false,
inline: false,
delimiter: ',',
columnsCount: 1 // 一行显示一个
placeholder: '暂无选项',
itemRender: (option: Option) => <span>{option.label}</span>
};
toggleOption(option: Option) {
const {
value,
onChange,
delimiter,
valueField,
options,
simpleValue
} = this.props;
let valueArray = value2array(value, {
multiple: true,
valueField,
delimiter,
options
});
let idx = valueArray.indexOf(option);
if (!~idx) {
option =
value2array(option[valueField || 'value'], {
multiple: true,
valueField,
delimiter,
options
})[0] || option;
idx = valueArray.indexOf(option);
static value2array(
value: any,
options: Options,
option2value: (option: Option) => any = (option: Option) => option
): Options {
if (value === void 0) {
return [];
}
if (!Array.isArray(value)) {
value = [value];
}
return value
.map((value: any) => {
const option = find(options, option => option2value(option) === value);
return option;
})
.filter((item: any) => item);
}
toggleOption(option: Option) {
const {value, onChange, option2value, options} = this.props;
let valueArray = Checkboxes.value2array(value, options, option2value);
let idx = valueArray.indexOf(option);
if (~idx) {
valueArray.splice(idx, 1);
} else {
valueArray.push(option);
}
let newValue: string | Array<Option> = simpleValue
? valueArray.map(item => item[valueField || 'value'])
let newValue: string | Array<Option> = option2value
? valueArray.map(item => option2value(item))
: valueArray;
onChange && onChange(newValue);
onChange?.(newValue);
}
render() {
const {
value,
valueField,
delimiter,
options,
className,
placeholder,
disabled,
inline,
labelClassName
labelClassName,
disabled,
classnames: cx,
option2value,
itemClassName,
itemRender
} = this.props;
let valueArray = value2array(value, {
multiple: true,
valueField,
delimiter,
options
});
let valueArray = Checkboxes.value2array(value, options, option2value);
let body: Array<React.ReactNode> = [];
if (options) {
if (Array.isArray(options) && options.length) {
body = options.map((option, key) => (
<Checkbox
className={cx(itemClassName, option.className)}
key={key}
onChange={() => this.toggleOption(option)}
checked={!!~valueArray.indexOf(option)}
disabled={disabled || option.disabled}
inline={inline}
labelClassName={labelClassName}
description={option.description}
>
{option.label}
{itemRender(option)}
</Checkbox>
));
}
return (
<div className={className}>
{body && body.length ? body : placeholder}
<div className={cx('Checkboxes', className, inline ? 'Checkboxes--inline' : '')}>
{body && body.length ? body : (
<div>{placeholder}</div>
)}
</div>
);
}

View File

@ -47,16 +47,14 @@ export interface OptionProps {
delimiter?: string;
clearable?: boolean;
placeholder?: string;
autoFill?: {[propName: string]: any};
disabled?: boolean;
creatable?: boolean;
onAdd?: (
idx?: number | Array<number>,
value?: any,
skipForm?: boolean
) => void;
addControls?: Array<any>;
editable?: boolean;
editControls?: Array<any>;
onEdit?: (value: Option, origin?: Option, skipForm?: boolean) => void;
removable?: boolean;
onDelete?: (value: Option) => void;

View File

@ -17,14 +17,14 @@ export interface SelectionsProps extends ThemeProps {
disabled?: boolean;
title?: string;
placeholder: string;
optionRender: (option: Option) => JSX.Element;
itemRender: (option: Option) => JSX.Element;
itemClassName?: string;
}
export class Selections extends React.Component<SelectionsProps> {
static defaultProps: Pick<SelectionsProps, 'placeholder' | 'optionRender'> = {
static defaultProps: Pick<SelectionsProps, 'placeholder' | 'itemRender'> = {
placeholder: '请先选择数据',
optionRender: (option: Option) => <span>{option.label}</span>
itemRender: (option: Option) => <span>{option.label}</span>
};
id = guid();
@ -115,7 +115,7 @@ export class Selections extends React.Component<SelectionsProps> {
className,
value,
placeholder,
optionRender,
itemRender,
disabled,
title,
itemClassName,
@ -130,11 +130,11 @@ export class Selections extends React.Component<SelectionsProps> {
<div className={cx('Selections-items')}>
{value.map((option, index) => (
<div className={cx('Selections-item', itemClassName, option?.className)} key={index}>
{sortable && !disabled ? (
{sortable && !disabled && value.length > 1 ? (
<Icon className={cx('Selections-dragbar')} icon="combo-dragger"/>
) : null}
<label>{optionRender(option)}</label>
<label>{itemRender(option)}</label>
{!disabled ? (
<a