Skip to content

Commit

Permalink
feat: ✨ implement checkbox
Browse files Browse the repository at this point in the history
  • Loading branch information
huang-xiao-jian committed Jun 8, 2020
1 parent dea0afe commit 170dd0a
Show file tree
Hide file tree
Showing 9 changed files with 471 additions and 1 deletion.
71 changes: 71 additions & 0 deletions packages/Checkbox/Checkbox.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
.van-checkbox {
display: flex;
align-items: center;
overflow: hidden;
user-select: none;
}
.van-checkbox__icon-wrap,
.van-checkbox__label {
line-height: 20px;
line-height: var(--checkbox-size, 20px);
}
.van-checkbox__icon-wrap {
flex: none;
}
.van-checkbox__icon {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
width: 1em;
height: 1em;
color: transparent;
text-align: center;
transition-property: color, border-color, background-color;
font-size: 20px;
font-size: var(--checkbox-size, 20px);
border: 1px solid #c8c9cc;
border: 1px solid var(--checkbox-border-color, #c8c9cc);
transition-duration: 0.2s;
transition-duration: var(--checkbox-transition-duration, 0.2s);
}
.van-checkbox__icon--round {
border-radius: 100%;
}
.van-checkbox__icon--checked {
color: #fff;
color: var(--white, #fff);
background-color: #1989fa;
background-color: var(--checkbox-checked-icon-color, #1989fa);
border-color: #1989fa;
border-color: var(--checkbox-checked-icon-color, #1989fa);
}
.van-checkbox__icon--disabled {
background-color: #ebedf0;
background-color: var(--checkbox-disabled-background-color, #ebedf0);
border-color: #c8c9cc;
border-color: var(--checkbox-disabled-icon-color, #c8c9cc);
}
.van-checkbox__icon--disabled.van-checkbox__icon--checked {
color: #c8c9cc;
color: var(--checkbox-disabled-icon-color, #c8c9cc);
}
.van-checkbox__label {
word-wrap: break-word;
margin-left: 10px;
margin-left: var(--checkbox-label-margin, 10px);
color: #323233;
color: var(--checkbox-label-color, #323233);
}
.van-checkbox__label--left {
float: left;
margin: 0 10px 0 0;
margin: 0 var(--checkbox-label-margin, 10px) 0 0;
}
.van-checkbox__label--disabled {
color: #c8c9cc;
color: var(--checkbox-disabled-label-color, #c8c9cc);
}
.van-checkbox__label:empty {
margin: 0;
}
156 changes: 156 additions & 0 deletions packages/Checkbox/Checkbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// packages
import React, {
FunctionComponent,
useContext,
CSSProperties,
ReactElement,
} from 'react';
import clsx from 'clsx';
import { View } from 'remax/wechat';
// internal
import Icon from '../Icon';
import CheckboxGroupContext, {
CheckboxChangeEvent,
} from '../CheckboxGroup/CheckboxGroupContext';
import { Switch, Case } from '../tools/Switch';
import pickStyle from '../tools/pick-style';
import withDefaultProps from '../tools/with-default-props-advance';
import './Checkbox.css';

// 默认值填充属性
interface NeutralCheckboxProps {
shape: 'round' | 'square';
value: boolean;
disabled: boolean;
labelDisabled: boolean;
labelPosition: 'left' | 'right';
checkedColor: string;
iconSize: string;
}

interface ExogenousCheckboxProps {
// 自定义图标
icon?: ReactElement;
// 唯一标示
name: string;
// 容器类名,用以覆盖内部
className?: string;
// 事件回调
onChange?: (event: CheckboxChangeEvent) => void;
}

type CheckboxProps = NeutralCheckboxProps & ExogenousCheckboxProps;

const DefaultCheckboxProps: NeutralCheckboxProps = {
shape: 'round',
value: false,
disabled: false,
labelDisabled: false,
labelPosition: 'right',
checkedColor: '#1989fa',
iconSize: '20px;',
};

const Checkbox: FunctionComponent<CheckboxProps> = (props) => {
const {
labelPosition,
labelDisabled,
checkedColor,
icon,
iconSize,
name,
shape,
className,
children,
value,
onChange,
disabled: _disabled1,
} = props;
// const { isChecked, onChange, disabled: _disabled2 } = useContext(
// CheckboxGroupContext
// );
const context = useContext(CheckboxGroupContext);

// derivation, fuse standalone and CheckboxGroup usage
const disabled = _disabled1 || context?.disabled;
const checked = context ? context?.isChecked(name) : value;
const color = checked && !disabled ? checkedColor : undefined;

// binding
const classnames = {
container: clsx(className, 'van-checkbox'),
label: clsx(
'van-checkbox__label',
`van-checkbox__label--${labelPosition}`,
{
'van-checkbox__label--disabled': disabled,
}
),
iconParent: clsx('van-checkbox__icon', `van-checkbox__icon--${shape}`, {
'van-checkbox__icon--disabled': disabled,
'van-checkbox__icon--checked': checked,
}),
};
const stylesheet: Record<'iconParent' | 'icon', CSSProperties> = {
iconParent: pickStyle({
fontSize: iconSize,
borderColor: color,
backgroundColor: color,
}),
icon: {
lineHeight: '1.25em',
},
};
const visibility = {
customIcon: !!icon,
};

// 事件绑定
const onChangeWrap = context?.onChange || onChange;
const onClick = () => {
if (!disabled) {
if (typeof onChangeWrap === 'function') {
onChangeWrap({
detail: {
name,
status: !checked,
},
});
}
}
};
const onClickLabel = () => {
if (!disabled && !labelDisabled) {
if (typeof onChangeWrap === 'function') {
onChangeWrap({
detail: {
name,
status: !checked,
},
});
}
}
};

return (
<View className={classnames.container}>
<View className="van-checkbox__icon-wrap" onClick={onClick}>
<View className={classnames.iconParent} style={stylesheet.iconParent}>
<Switch>
<Case in={visibility.customIcon}>{icon}</Case>
<Case default>
<Icon name="success" size=".8em" style={stylesheet.icon} />
</Case>
</Switch>
</View>
</View>
<View className={classnames.label} onClick={onClickLabel}>
{children}
</View>
</View>
);
};

export default withDefaultProps<ExogenousCheckboxProps, NeutralCheckboxProps>(
DefaultCheckboxProps
)(Checkbox);
4 changes: 4 additions & 0 deletions packages/Checkbox/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/**
* @description - nothing but export component
*/
export { default } from './Checkbox';
Empty file.
47 changes: 47 additions & 0 deletions packages/CheckboxGroup/CheckboxGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// packages
import React, { FunctionComponent } from 'react';
// internal
import withDefaultProps from '../tools/with-default-props-advance';
import CheckboxGroupContext, {
CheckboxChangeEventDetail,
} from './CheckboxGroupContext';
import './CheckboxGroup.css';

// 默认值填充属性
interface NeutralCheckboxGroupProps {
disabled: boolean;
}

interface ExogenousCheckboxGroupProps {
name?: string;
value: string[];
max?: number;
onChange?: (event: { detail: CheckboxChangeEventDetail }) => void;
}

type RadioGroupProps = NeutralCheckboxGroupProps & ExogenousCheckboxGroupProps;

const DefaultRadioGroupProps: NeutralCheckboxGroupProps = {
disabled: false,
};

const CheckboxGroup: FunctionComponent<RadioGroupProps> = (props) => {
const { disabled, value, onChange, children } = props;
const payload = {
disabled,
value,
onChange,
isChecked: (name: string) => value.includes(name),
};

return (
<CheckboxGroupContext.Provider value={payload}>
{children}
</CheckboxGroupContext.Provider>
);
};

export default withDefaultProps<
ExogenousCheckboxGroupProps,
NeutralCheckboxGroupProps
>(DefaultRadioGroupProps)(CheckboxGroup);
21 changes: 21 additions & 0 deletions packages/CheckboxGroup/CheckboxGroupContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// packages
import { createContext } from 'react';

// interface
export interface CheckboxChangeEventDetail {
name: string;
status: boolean;
}

export interface CheckboxChangeEvent {
detail: CheckboxChangeEventDetail;
}

export interface CheckboxGroupContextAbstract {
disabled: boolean;
isChecked: (name: string) => boolean;
onChange?: (event: { detail: CheckboxChangeEventDetail }) => void;
}

// 默认值需要保持一致,以防万一
export default createContext<CheckboxGroupContextAbstract | null>(null);
4 changes: 4 additions & 0 deletions packages/CheckboxGroup/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/**
* @description - nothing but export component
*/
export { default } from './CheckboxGroup';
3 changes: 2 additions & 1 deletion public/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ page {
position: static !important;
}

.demo-block__radio {
.demo-block__radio,
.demo-block__checkbox {
margin-top: 6px;
}
Loading

0 comments on commit 170dd0a

Please sign in to comment.