useHeights.js 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. "use strict";
  2. var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
  3. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
  4. Object.defineProperty(exports, "__esModule", {
  5. value: true
  6. });
  7. exports.default = useHeights;
  8. var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
  9. var _react = _interopRequireWildcard(require("react"));
  10. var React = _react;
  11. var _CacheMap = _interopRequireDefault(require("../utils/CacheMap"));
  12. function parseNumber(value) {
  13. var num = parseFloat(value);
  14. return isNaN(num) ? 0 : num;
  15. }
  16. function useHeights(getKey, onItemAdd, onItemRemove) {
  17. var _React$useState = React.useState(0),
  18. _React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2),
  19. updatedMark = _React$useState2[0],
  20. setUpdatedMark = _React$useState2[1];
  21. var instanceRef = (0, _react.useRef)(new Map());
  22. var heightsRef = (0, _react.useRef)(new _CacheMap.default());
  23. var promiseIdRef = (0, _react.useRef)(0);
  24. function cancelRaf() {
  25. promiseIdRef.current += 1;
  26. }
  27. function collectHeight() {
  28. var sync = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
  29. cancelRaf();
  30. var doCollect = function doCollect() {
  31. var changed = false;
  32. instanceRef.current.forEach(function (element, key) {
  33. if (element && element.offsetParent) {
  34. var offsetHeight = element.offsetHeight;
  35. var _getComputedStyle = getComputedStyle(element),
  36. marginTop = _getComputedStyle.marginTop,
  37. marginBottom = _getComputedStyle.marginBottom;
  38. var marginTopNum = parseNumber(marginTop);
  39. var marginBottomNum = parseNumber(marginBottom);
  40. var totalHeight = offsetHeight + marginTopNum + marginBottomNum;
  41. if (heightsRef.current.get(key) !== totalHeight) {
  42. heightsRef.current.set(key, totalHeight);
  43. changed = true;
  44. }
  45. }
  46. });
  47. // Always trigger update mark to tell parent that should re-calculate heights when resized
  48. if (changed) {
  49. setUpdatedMark(function (c) {
  50. return c + 1;
  51. });
  52. }
  53. };
  54. if (sync) {
  55. doCollect();
  56. } else {
  57. promiseIdRef.current += 1;
  58. var id = promiseIdRef.current;
  59. Promise.resolve().then(function () {
  60. if (id === promiseIdRef.current) {
  61. doCollect();
  62. }
  63. });
  64. }
  65. }
  66. function setInstanceRef(item, instance) {
  67. var key = getKey(item);
  68. var origin = instanceRef.current.get(key);
  69. if (instance) {
  70. instanceRef.current.set(key, instance);
  71. collectHeight();
  72. } else {
  73. instanceRef.current.delete(key);
  74. }
  75. // Instance changed
  76. if (!origin !== !instance) {
  77. if (instance) {
  78. onItemAdd === null || onItemAdd === void 0 || onItemAdd(item);
  79. } else {
  80. onItemRemove === null || onItemRemove === void 0 || onItemRemove(item);
  81. }
  82. }
  83. }
  84. (0, _react.useEffect)(function () {
  85. return cancelRaf;
  86. }, []);
  87. return [setInstanceRef, collectHeight, heightsRef.current, updatedMark];
  88. }