index.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import React, { CSSProperties } from 'react';
  2. import cls from 'classnames';
  3. import PropTypes from 'prop-types';
  4. import { cssClasses, strings } from '@douyinfe/semi-foundation/collapse/constants';
  5. import CollapseFoundation, {
  6. ArgsType,
  7. CollapseAdapter,
  8. CollapseProps,
  9. CollapseState
  10. } from '@douyinfe/semi-foundation/collapse/foundation';
  11. import BaseComponent from '../_base/baseComponent';
  12. import CollapsePanel from './item';
  13. import '@douyinfe/semi-foundation/collapse/collapse.scss';
  14. import { noop } from '@douyinfe/semi-foundation/utils/function';
  15. import { isEqual } from 'lodash';
  16. import CollapseContext from './collapse-context';
  17. export { CollapsePanelProps } from './item';
  18. export interface CollapseReactProps extends CollapseProps{
  19. expandIcon?: React.ReactNode;
  20. collapseIcon?: React.ReactNode;
  21. children?: React.ReactNode | undefined;
  22. style?: CSSProperties;
  23. onChange?: (activeKey: CollapseProps['activeKey'], e: React.MouseEvent) => void;
  24. }
  25. export { CollapseState };
  26. class Collapse extends BaseComponent<CollapseReactProps, CollapseState> {
  27. static Panel = CollapsePanel;
  28. static propTypes = {
  29. activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
  30. defaultActiveKey: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
  31. accordion: PropTypes.bool,
  32. onChange: PropTypes.func,
  33. expandIcon: PropTypes.node,
  34. collapseIcon: PropTypes.node,
  35. style: PropTypes.object,
  36. className: PropTypes.string,
  37. keepDOM: PropTypes.bool,
  38. motion: PropTypes.oneOfType([PropTypes.bool, PropTypes.func, PropTypes.object]),
  39. expandIconPosition: PropTypes.oneOf(strings.iconPosition)
  40. };
  41. static defaultProps = {
  42. defaultActiveKey: '',
  43. onChange: noop,
  44. expandIconPosition: 'right'
  45. };
  46. constructor(props: CollapseReactProps) {
  47. super(props);
  48. this.foundation = new CollapseFoundation(this.adapter);
  49. const initKeys = this.foundation.initActiveKey();
  50. this.state = {
  51. activeSet: new Set(initKeys)
  52. };
  53. this.onChange = this.onChange.bind(this);
  54. }
  55. get adapter(): CollapseAdapter {
  56. return {
  57. ...super.adapter,
  58. handleChange: (activeKey: CollapseProps['activeKey'], e: React.MouseEvent) => this.props.onChange(activeKey, e),
  59. addActiveKey: (activeSet: CollapseState['activeSet']) => this.setState({ activeSet }),
  60. };
  61. }
  62. static getDerivedStateFromProps(props: CollapseReactProps, state: CollapseState) {
  63. if (props.activeKey) {
  64. const keys = Array.isArray(props.activeKey) ? props.activeKey : [props.activeKey];
  65. const newSet = new Set(keys);
  66. if (!isEqual(newSet, state.activeSet)) {
  67. return {
  68. ...state,
  69. activeSet: newSet,
  70. };
  71. }
  72. return state;
  73. }
  74. return state;
  75. }
  76. componentWillUnmount() {
  77. this.foundation.destroy();
  78. }
  79. onChange = (activeKey: string, e: React.MouseEvent) => {
  80. this.foundation.handleChange(activeKey, e);
  81. };
  82. render() {
  83. // eslint-disable-next-line max-len
  84. const { defaultActiveKey, accordion, style, motion, className, keepDOM, expandIconPosition, expandIcon, collapseIcon, children, ...rest } = this.props;
  85. const clsPrefix = cls(cssClasses.PREFIX, className);
  86. const { activeSet } = this.state;
  87. return (
  88. <div className={clsPrefix} style={style}>
  89. <CollapseContext.Provider
  90. value={{
  91. activeSet,
  92. expandIcon,
  93. collapseIcon,
  94. keepDOM,
  95. expandIconPosition,
  96. onClick: this.onChange,
  97. motion
  98. }}
  99. >
  100. {children}
  101. </CollapseContext.Provider>
  102. </div>
  103. );
  104. }
  105. }
  106. export default Collapse;