autoHeight.tsx 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import React from 'react';
  2. export type IReactComponent<P = any> =
  3. | React.StatelessComponent<P>
  4. | React.ComponentClass<P>
  5. | React.ClassicComponentClass<P>;
  6. function computeHeight(node: HTMLDivElement) {
  7. node.style.height = '100%';
  8. const totalHeight = parseInt(getComputedStyle(node).height + '', 10);
  9. const padding =
  10. parseInt(getComputedStyle(node).paddingTop + '', 10) +
  11. parseInt(getComputedStyle(node).paddingBottom + '', 10);
  12. return totalHeight - padding;
  13. }
  14. function getAutoHeight(n: HTMLDivElement) {
  15. if (!n) {
  16. return 0;
  17. }
  18. const node = n;
  19. let height = computeHeight(node);
  20. const parentNode = node.parentNode as HTMLDivElement;
  21. if (parentNode) {
  22. height = computeHeight(parentNode);
  23. }
  24. return height;
  25. }
  26. interface IAutoHeightProps {
  27. height?: number;
  28. }
  29. function autoHeight() {
  30. return function<P extends IAutoHeightProps>(
  31. WrappedComponent: React.ComponentClass<P> | React.SFC<P>,
  32. ): React.ComponentClass<P> {
  33. class AutoHeightComponent extends React.Component<P & IAutoHeightProps> {
  34. state = {
  35. computedHeight: 0,
  36. };
  37. root!: HTMLDivElement;
  38. componentDidMount() {
  39. const { height } = this.props;
  40. if (!height) {
  41. let h = getAutoHeight(this.root);
  42. // eslint-disable-next-line
  43. this.setState({ computedHeight: h });
  44. if (h < 1) {
  45. h = getAutoHeight(this.root);
  46. this.setState({ computedHeight: h });
  47. }
  48. }
  49. }
  50. handleRoot = (node: HTMLDivElement) => {
  51. this.root = node;
  52. };
  53. render() {
  54. const { height } = this.props;
  55. const { computedHeight } = this.state;
  56. const h = height || computedHeight;
  57. return (
  58. <div ref={this.handleRoot}>
  59. {h > 0 && <WrappedComponent {...this.props} height={h} />}
  60. </div>
  61. );
  62. }
  63. }
  64. return AutoHeightComponent;
  65. };
  66. }
  67. export default autoHeight;