checkboxGroup.tsx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /* eslint-disable max-len */
  2. import React from 'react';
  3. import PropTypes from 'prop-types';
  4. import classnames from 'classnames';
  5. import { checkboxGroupClasses as css, strings } from '@douyinfe/semi-foundation/checkbox/constants';
  6. import CheckboxGroupFoudation, { CheckboxGroupAdapter } from '@douyinfe/semi-foundation/checkbox/checkboxGroupFoundation';
  7. import BaseComponent from '../_base/baseComponent';
  8. import { Context } from './context';
  9. import { isEqual } from 'lodash';
  10. import Checkbox, { CheckboxEvent } from './checkbox';
  11. export type CheckboxDirection = 'horizontal' | 'vertical';
  12. export type CheckboxType = 'default' | 'card' | 'pureCard';
  13. export type CheckboxGroupProps = {
  14. defaultValue?: any[];
  15. disabled?: boolean;
  16. name?: string;
  17. options?: any[];
  18. value?: any[];
  19. onChange?: (value: any[]) => void;
  20. children?: React.ReactNode;
  21. prefixCls?: string;
  22. direction?: CheckboxDirection;
  23. style?: React.CSSProperties;
  24. className?: string;
  25. type?: CheckboxType;
  26. id?: string;
  27. };
  28. export type CheckboxGroupState = {
  29. value?: any[];
  30. };
  31. class CheckboxGroup extends BaseComponent<CheckboxGroupProps, CheckboxGroupState> {
  32. static propTypes = {
  33. defaultValue: PropTypes.array,
  34. disabled: PropTypes.bool,
  35. name: PropTypes.string,
  36. options: PropTypes.array,
  37. value: PropTypes.array,
  38. onChange: PropTypes.func,
  39. children: PropTypes.node,
  40. prefixCls: PropTypes.string,
  41. direction: PropTypes.oneOf<CheckboxGroupProps['direction']>(strings.DIRECTION_SET),
  42. className: PropTypes.string,
  43. type: PropTypes.oneOf([strings.TYPE_DEFAULT, strings.TYPE_CARD, strings.TYPE_PURECARD]),
  44. style: PropTypes.object,
  45. };
  46. static defaultProps: Partial<CheckboxGroupProps> = {
  47. disabled: false,
  48. // eslint-disable-next-line @typescript-eslint/no-empty-function
  49. onChange: () => {},
  50. type: strings.TYPE_DEFAULT,
  51. defaultValue: [] as any,
  52. direction: strings.DEFAULT_DIRECTION,
  53. };
  54. get adapter(): CheckboxGroupAdapter {
  55. return {
  56. ...super.adapter,
  57. updateGroupValue: value => {
  58. this.setState({ value });
  59. },
  60. notifyChange: evt => {
  61. this.props.onChange && this.props.onChange(evt);
  62. },
  63. };
  64. }
  65. constructor(props: CheckboxGroupProps) {
  66. super(props);
  67. this.state = {
  68. value: props.value || props.defaultValue,
  69. };
  70. this.foundation = new CheckboxGroupFoudation(this.adapter);
  71. this.onChange = this.onChange.bind(this);
  72. }
  73. componentDidMount() {
  74. this.foundation.init();
  75. }
  76. componentDidUpdate(prevProps: CheckboxGroupProps) {
  77. if (!isEqual(prevProps.value, this.props.value)) {
  78. this.foundation.handlePropValueChange(this.props.value);
  79. }
  80. }
  81. componentWillUnmount() {
  82. this.foundation.destroy();
  83. }
  84. onChange(evt: CheckboxEvent) {
  85. this.foundation.handleChange(evt);
  86. }
  87. render() {
  88. const { children, options, prefixCls, direction, className, id, style, type } = this.props;
  89. const isPureCardType = type === strings.TYPE_PURECARD;
  90. const isCardType = type === strings.TYPE_CARD || isPureCardType;
  91. const prefix = prefixCls || css.PREFIX;
  92. const prefixClsDisplay = classnames({
  93. [prefix as string]: true,
  94. [`${prefix }-wrapper`]: true,
  95. [`${prefix }-${ direction}`]: direction,
  96. [`${prefix}-${direction}-cardType`]: direction && isCardType,
  97. }, className);
  98. const realValue = this.state.value.slice();
  99. let inner;
  100. if (options) {
  101. inner = (options || []).map((option, index) => {
  102. if (typeof option === 'string') {
  103. return (
  104. <Checkbox
  105. key={index}
  106. disabled={this.props.disabled}
  107. value={option}
  108. prefixCls={prefixCls}
  109. >
  110. {option}
  111. </Checkbox>
  112. );
  113. } else {
  114. return (
  115. <Checkbox
  116. key={index}
  117. disabled={option.disabled || this.props.disabled}
  118. value={option.value}
  119. prefixCls={prefixCls}
  120. extra={option.extra}
  121. className={option.className}
  122. style={option.style}
  123. onChange={option.onChange}
  124. >
  125. {option.label}
  126. </Checkbox>
  127. );
  128. }
  129. });
  130. } else if (children) {
  131. inner = (React.Children.toArray(children) as React.ReactElement[]).map((itm, index) => React.cloneElement(itm, { key: index }));
  132. }
  133. return (
  134. <div className={prefixClsDisplay} style={style} id={id}>
  135. <Context.Provider
  136. value={{
  137. checkboxGroup: {
  138. onChange: this.onChange,
  139. value: realValue,
  140. disabled: this.props.disabled,
  141. name: this.foundation.getFormatName(),
  142. isCardType,
  143. isPureCardType,
  144. },
  145. }}
  146. >
  147. {inner}
  148. </Context.Provider>
  149. </div>
  150. );
  151. }
  152. }
  153. export default CheckboxGroup;