useSizes.js 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import React from 'react';
  2. import { autoPtgSizes } from './sizeUtil';
  3. export function getPtg(str) {
  4. return Number(str.slice(0, -1)) / 100;
  5. }
  6. function isPtg(itemSize) {
  7. return typeof itemSize === 'string' && itemSize.endsWith('%');
  8. }
  9. /**
  10. * Save the size state.
  11. * Align the size into flex percentage base.
  12. */
  13. export default function useSizes(items, containerSize) {
  14. const propSizes = items.map(item => item.size);
  15. const itemsCount = items.length;
  16. const mergedContainerSize = containerSize || 0;
  17. const ptg2px = ptg => ptg * mergedContainerSize;
  18. // We do not need care the size state match the `items` length in `useState`.
  19. // It will calculate later.
  20. const [innerSizes, setInnerSizes] = React.useState(() => items.map(item => item.defaultSize));
  21. const sizes = React.useMemo(() => {
  22. var _a;
  23. const mergedSizes = [];
  24. for (let i = 0; i < itemsCount; i += 1) {
  25. mergedSizes[i] = (_a = propSizes[i]) !== null && _a !== void 0 ? _a : innerSizes[i];
  26. }
  27. return mergedSizes;
  28. }, [itemsCount, innerSizes, propSizes]);
  29. const postPercentMinSizes = React.useMemo(() => items.map(item => {
  30. if (isPtg(item.min)) {
  31. return getPtg(item.min);
  32. }
  33. return (item.min || 0) / mergedContainerSize;
  34. }), [items, mergedContainerSize]);
  35. const postPercentMaxSizes = React.useMemo(() => items.map(item => {
  36. if (isPtg(item.max)) {
  37. return getPtg(item.max);
  38. }
  39. return (item.max || mergedContainerSize) / mergedContainerSize;
  40. }), [items, mergedContainerSize]);
  41. // Post handle the size. Will do:
  42. // 1. Convert all the px into percentage if not empty.
  43. // 2. Get rest percentage for exist percentage.
  44. // 3. Fill the rest percentage into empty item.
  45. const postPercentSizes = React.useMemo(() => {
  46. const ptgList = [];
  47. // Fill default percentage
  48. for (let i = 0; i < itemsCount; i += 1) {
  49. const itemSize = sizes[i];
  50. if (isPtg(itemSize)) {
  51. ptgList[i] = getPtg(itemSize);
  52. } else if (itemSize || itemSize === 0) {
  53. const num = Number(itemSize);
  54. if (!Number.isNaN(num)) {
  55. ptgList[i] = num / mergedContainerSize;
  56. }
  57. } else {
  58. ptgList[i] = undefined;
  59. }
  60. }
  61. // Use autoPtgSizes to handle the undefined sizes
  62. return autoPtgSizes(ptgList, postPercentMinSizes, postPercentMaxSizes);
  63. }, [sizes, mergedContainerSize, postPercentMinSizes, postPercentMaxSizes]);
  64. const postPxSizes = React.useMemo(() => postPercentSizes.map(ptg2px), [postPercentSizes, mergedContainerSize]);
  65. // If ssr, we will use the size from developer config first.
  66. const panelSizes = React.useMemo(() => containerSize ? postPxSizes : sizes, [postPxSizes, containerSize]);
  67. return [panelSizes, postPxSizes, postPercentSizes, postPercentMinSizes, postPercentMaxSizes, setInnerSizes];
  68. }