resizeItem.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import React, { createRef } from 'react';
  2. import classNames from 'classnames';
  3. import PropTypes from 'prop-types';
  4. import { ResizeItemFoundation, ResizeItemAdapter } from '@douyinfe/semi-foundation/resizable/foundation';
  5. import { cssClasses } from '@douyinfe/semi-foundation/resizable/constants';
  6. import BaseComponent from '../../_base/baseComponent';
  7. import { ResizeCallback, ResizeStartCallback } from '@douyinfe/semi-foundation/resizable/types';
  8. import { ResizeContext, ResizeContextProps } from './resizeContext';
  9. import { noop } from 'lodash';
  10. const prefixCls = cssClasses.PREFIX;
  11. export interface ResizeItemProps {
  12. style?: React.CSSProperties;
  13. className?: string;
  14. min?: string;
  15. max?: string;
  16. children?: React.ReactNode;
  17. onResizeStart?: ResizeStartCallback;
  18. onChange?: ResizeCallback;
  19. onResizeEnd?: ResizeCallback;
  20. defaultSize?: string | number
  21. }
  22. export interface ResizeItemState {
  23. }
  24. class ResizeItem extends BaseComponent<ResizeItemProps, ResizeItemState> {
  25. static propTypes = {
  26. style: PropTypes.object,
  27. className: PropTypes.string,
  28. min: PropTypes.string,
  29. max: PropTypes.string,
  30. children: PropTypes.object,
  31. onResizeStart: PropTypes.func,
  32. onChange: PropTypes.func,
  33. onResizeEnd: PropTypes.func,
  34. defaultSize: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  35. };
  36. static defaultProps: Partial<ResizeItemProps> = {
  37. onResizeStart: noop,
  38. onChange: noop,
  39. onResizeEnd: noop,
  40. };
  41. constructor(props: ResizeItemProps) {
  42. super(props);
  43. this.itemRef = createRef<HTMLDivElement | null>();
  44. this.foundation = new ResizeItemFoundation(this.adapter);
  45. this.state = {
  46. isResizing: false,
  47. };
  48. this.itemIndex = -1;
  49. }
  50. componentDidMount() {
  51. this.foundation.init();
  52. const { min, max, onResizeStart, onChange, onResizeEnd, defaultSize } = this.props;
  53. if (this.itemIndex === -1) {
  54. // 开发过程在StrictMode下context方法会执行两次,需要判断一下是否已经注册过
  55. this.itemIndex = this.context.registerItem(this.itemRef, min, max, defaultSize, onResizeStart, onChange, onResizeEnd);
  56. }
  57. this.direction = this.context.direction; // 留一个direction的引用,方便在componentDidUpdate中判断方向是否有变化
  58. }
  59. componentDidUpdate(_prevProps: ResizeItemProps) {
  60. // 支持动态方向,修改item的style
  61. if (this.context.direction !== this.direction) {
  62. this.direction = this.context.direction;
  63. if (this.direction === 'horizontal') {
  64. const newWidth = this.itemRef.current?.style.height;
  65. this.itemRef.current.style.width = newWidth;
  66. this.itemRef.current.style.removeProperty('height');
  67. } else {
  68. const newHeight = this.itemRef.current?.style.width;
  69. this.itemRef.current.style.height = newHeight;
  70. this.itemRef.current.style.removeProperty('width');
  71. }
  72. }
  73. }
  74. componentWillUnmount() {
  75. this.foundation.destroy();
  76. }
  77. get adapter(): ResizeItemAdapter<ResizeItemProps, ResizeItemState> {
  78. return {
  79. ...super.adapter,
  80. };
  81. }
  82. static contextType = ResizeContext;
  83. context: ResizeContextProps;
  84. direction: 'horizontal' | 'vertical';
  85. itemRef: React.RefObject<HTMLDivElement | null>;
  86. itemIndex: number;
  87. render() {
  88. const style: React.CSSProperties = {
  89. ...this.props.style,
  90. };
  91. return (
  92. <div
  93. style={style}
  94. className={classNames(this.props.className, prefixCls + '-item')}
  95. ref={this.itemRef}
  96. >
  97. {this.props.children}
  98. </div>
  99. );
  100. }
  101. }
  102. export default ResizeItem;