useResize.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
  2. import * as React from 'react';
  3. import { getPtg } from './useSizes';
  4. /**
  5. * Handle user drag resize logic.
  6. */
  7. export default function useResize(items, resizableInfos, percentSizes, containerSize, updateSizes, isRTL) {
  8. const limitSizes = items.map(item => [item.min, item.max]);
  9. const mergedContainerSize = containerSize || 0;
  10. const ptg2px = ptg => ptg * mergedContainerSize;
  11. // ======================== Resize ========================
  12. function getLimitSize(str, defaultLimit) {
  13. if (typeof str === 'string') {
  14. return ptg2px(getPtg(str));
  15. }
  16. return str !== null && str !== void 0 ? str : defaultLimit;
  17. }
  18. // Real px sizes
  19. const [cacheSizes, setCacheSizes] = React.useState([]);
  20. const cacheCollapsedSize = React.useRef([]);
  21. /**
  22. * When start drag, check the direct is `start` or `end`.
  23. * This will handle when 2 splitter bar are in the same position.
  24. */
  25. const [movingIndex, setMovingIndex] = React.useState(null);
  26. const getPxSizes = () => percentSizes.map(ptg2px);
  27. const onOffsetStart = index => {
  28. setCacheSizes(getPxSizes());
  29. setMovingIndex({
  30. index,
  31. confirmed: false
  32. });
  33. };
  34. const onOffsetUpdate = (index, offset) => {
  35. var _a;
  36. // First time trigger move index update is not sync in the state
  37. let confirmedIndex = null;
  38. // We need to know what the real index is.
  39. if ((!movingIndex || !movingIndex.confirmed) && offset !== 0) {
  40. // Search for the real index
  41. if (offset > 0) {
  42. confirmedIndex = index;
  43. setMovingIndex({
  44. index,
  45. confirmed: true
  46. });
  47. } else {
  48. for (let i = index; i >= 0; i -= 1) {
  49. if (cacheSizes[i] > 0 && resizableInfos[i].resizable) {
  50. confirmedIndex = i;
  51. setMovingIndex({
  52. index: i,
  53. confirmed: true
  54. });
  55. break;
  56. }
  57. }
  58. }
  59. }
  60. const mergedIndex = (_a = confirmedIndex !== null && confirmedIndex !== void 0 ? confirmedIndex : movingIndex === null || movingIndex === void 0 ? void 0 : movingIndex.index) !== null && _a !== void 0 ? _a : index;
  61. const numSizes = _toConsumableArray(cacheSizes);
  62. const nextIndex = mergedIndex + 1;
  63. // Get boundary
  64. const startMinSize = getLimitSize(limitSizes[mergedIndex][0], 0);
  65. const endMinSize = getLimitSize(limitSizes[nextIndex][0], 0);
  66. const startMaxSize = getLimitSize(limitSizes[mergedIndex][1], mergedContainerSize);
  67. const endMaxSize = getLimitSize(limitSizes[nextIndex][1], mergedContainerSize);
  68. let mergedOffset = offset;
  69. // Align with the boundary
  70. if (numSizes[mergedIndex] + mergedOffset < startMinSize) {
  71. mergedOffset = startMinSize - numSizes[mergedIndex];
  72. }
  73. if (numSizes[nextIndex] - mergedOffset < endMinSize) {
  74. mergedOffset = numSizes[nextIndex] - endMinSize;
  75. }
  76. if (numSizes[mergedIndex] + mergedOffset > startMaxSize) {
  77. mergedOffset = startMaxSize - numSizes[mergedIndex];
  78. }
  79. if (numSizes[nextIndex] - mergedOffset > endMaxSize) {
  80. mergedOffset = numSizes[nextIndex] - endMaxSize;
  81. }
  82. // Do offset
  83. numSizes[mergedIndex] += mergedOffset;
  84. numSizes[nextIndex] -= mergedOffset;
  85. updateSizes(numSizes);
  86. return numSizes;
  87. };
  88. const onOffsetEnd = () => {
  89. setMovingIndex(null);
  90. };
  91. // ======================= Collapse =======================
  92. const onCollapse = (index, type) => {
  93. const currentSizes = getPxSizes();
  94. const adjustedType = isRTL ? type === 'start' ? 'end' : 'start' : type;
  95. const currentIndex = adjustedType === 'start' ? index : index + 1;
  96. const targetIndex = adjustedType === 'start' ? index + 1 : index;
  97. const currentSize = currentSizes[currentIndex];
  98. const targetSize = currentSizes[targetIndex];
  99. if (currentSize !== 0 && targetSize !== 0) {
  100. // Collapse directly
  101. currentSizes[currentIndex] = 0;
  102. currentSizes[targetIndex] += currentSize;
  103. cacheCollapsedSize.current[index] = currentSize;
  104. } else {
  105. const totalSize = currentSize + targetSize;
  106. const currentSizeMin = getLimitSize(limitSizes[currentIndex][0], 0);
  107. const currentSizeMax = getLimitSize(limitSizes[currentIndex][1], mergedContainerSize);
  108. const targetSizeMin = getLimitSize(limitSizes[targetIndex][0], 0);
  109. const targetSizeMax = getLimitSize(limitSizes[targetIndex][1], mergedContainerSize);
  110. const limitStart = Math.max(currentSizeMin, totalSize - targetSizeMax);
  111. const limitEnd = Math.min(currentSizeMax, totalSize - targetSizeMin);
  112. const halfOffset = targetSizeMin || (limitEnd - limitStart) / 2;
  113. const targetCacheCollapsedSize = cacheCollapsedSize.current[index];
  114. const currentCacheCollapsedSize = totalSize - targetCacheCollapsedSize;
  115. const shouldUseCache = targetCacheCollapsedSize && targetCacheCollapsedSize <= targetSizeMax && targetCacheCollapsedSize >= targetSizeMin && currentCacheCollapsedSize <= currentSizeMax && currentCacheCollapsedSize >= currentSizeMin;
  116. if (shouldUseCache) {
  117. currentSizes[targetIndex] = targetCacheCollapsedSize;
  118. currentSizes[currentIndex] = currentCacheCollapsedSize;
  119. } else {
  120. currentSizes[currentIndex] -= halfOffset;
  121. currentSizes[targetIndex] += halfOffset;
  122. }
  123. }
  124. updateSizes(currentSizes);
  125. return currentSizes;
  126. };
  127. return [onOffsetStart, onOffsetUpdate, onOffsetEnd, onCollapse, movingIndex === null || movingIndex === void 0 ? void 0 : movingIndex.index];
  128. }