ant-design/components/splitter/hooks/useSizes.ts
Wanpan 742ce37887
feat:🔥New Component: Splitter (#50038)
* feat: SplitPanel init

* feat: SplitPanel update

* feat: SplitPanel update

* feat: splitPanel update useResize

* feat: SplitPanel update

* feat: splitPanel update useResize

* feat: SplitPanel update

* feat: splitPanel demo

* feat: splitPanel update

* feat: splitPanel support complicated combination

* feat: SplitPanel rename to Splitter

* feat: Splitter support onRize

* feat: support collapsible

* feat: support token and collapsible

* feat: update docs

* feat: size defaultSize support string

* feat: min max support string

* feat: update

* feat: support DOM structure

* feat: Optimize UI

* feat: Optimize Code

* fix: Add a default size during initialization to prevent failure to obtain container size

* feat: optimized code

* feat: optimized code

* feat: Optimize Code

* Update components/splitter/demo/layout.tsx

Co-authored-by: lijianan <574980606@qq.com>
Signed-off-by: Wanpan <wanpan96@163.com>

* Update components/splitter/demo/multiple.tsx

Co-authored-by: lijianan <574980606@qq.com>
Signed-off-by: Wanpan <wanpan96@163.com>

* docs: update

* feat: Modify the style and optimize the interface

* feat: use PropsWithChildren

* feat: support rtl

* feat: collapsible supports object types

* fix: when collapsible is boolean not work

* feat: Splitter add test

* feat: update

* test: update snapshots

* docs: update

* test: update snapshots

* test: update

* test: update

* test: update

* test: update

* fix: Removed invalid min and max restrictions when collapsible exists

* test: update

* test: update

* test: update

* test: test coverage

* Revert "test: test coverage"

This reverts commit d247193722.

* test: test coverage

* feat: rename

* feat: optimized code

* ci: lint

* feat: optimized code

* feat: add useag tips

* feat: optimized code

* feat: Modify splitbar layout

* feat: optimized code

* feat: numerical precision

* feat: optimized code

* feat: Optimized trigger region

* feat: Support configuration animation

* fix: Fix Collapsible exception when using multiple panels

* fix: Fixed the issue of drag area overlapping when multiple panels are folded

* feat: optimized code

* feat: annotation

* feAt: optimized code

* fix: bgcolor

* fix: Modify the initial value calculation method

* test: update

* feat: add cover image

* chore: adjust logic

* chore: use items size

* chore: rtl

* chore: limit

* chore: controlled

* docs: update demo

* docs: adjust style

* chore: add split style

* chore: hor collapisble style

* chore: collapse icon

* chore: update warning

* chore: clean up

* chore: collapse logic

* chore: adjust demo

* chore: clean up

* test: adjust logic

* docs: update demo

* docs: rm useless demo

* docs: demo

* test: add demo test

* test: test of them

* test: 100% coverage

* chore: fix lint

* docs: update demo

* refactor: unique resize config

* docs: add demo

* fix: support virtual resiable

* chore: add cursor mask

* test: update snapshot

* test: add test case

* test: update snapshot

* chore: use px base

* chore: rm useless code

---------

Signed-off-by: Wanpan <wanpan96@163.com>
Co-authored-by: lijianan <574980606@qq.com>
Co-authored-by: 二货机器人 <smith3816@gmail.com>
Co-authored-by: ice <49827327+coding-ice@users.noreply.github.com>
2024-09-09 19:23:25 +08:00

114 lines
3.1 KiB
TypeScript

import React from 'react';
import type { PanelProps } from '../interface';
export function getPtg(str: string) {
return Number(str.slice(0, -1)) / 100;
}
function isPtg(itemSize: string | number | undefined): itemSize is string {
return typeof itemSize === 'string' && itemSize.endsWith('%');
}
/**
* Save the size state.
* Align the size into flex percentage base.
*/
export default function useSizes(items: PanelProps[], containerSize: number) {
const propSizes = items.map((item) => item.size);
const itemsCount = items.length;
const ptg2px = (ptg: number) => ptg * containerSize;
// We do not need care the size state match the `items` length in `useState`.
// It will calculate later.
const [innerSizes, setInnerSizes] = React.useState<(string | number | undefined)[]>(() =>
items.map((item) => item.defaultSize),
);
const sizes = React.useMemo(() => {
const mergedSizes = [];
for (let i = 0; i < itemsCount; i += 1) {
mergedSizes[i] = propSizes[i] ?? innerSizes[i];
}
return mergedSizes;
}, [itemsCount, innerSizes, propSizes]);
// Post handle the size. Will do:
// 1. Convert all the px into percentage if not empty.
// 2. Get rest percentage for exist percentage.
// 3. Fill the rest percentage into empty item.
const postPercentSizes = React.useMemo(() => {
let ptgList: (number | undefined)[] = [];
let emptyCount = 0;
// Fill default percentage
for (let i = 0; i < itemsCount; i += 1) {
const itemSize = sizes[i];
if (isPtg(itemSize)) {
ptgList[i] = getPtg(itemSize);
} else if (itemSize || itemSize === 0) {
const num = Number(itemSize);
if (!Number.isNaN(num)) {
ptgList[i] = num / containerSize;
}
} else {
emptyCount += 1;
ptgList[i] = undefined;
}
}
const totalPtg = ptgList.reduce((acc: number, ptg) => acc + (ptg || 0), 0);
if (totalPtg > 1 || !emptyCount) {
// If total percentage is larger than 1, we will scale it down.
const scale = 1 / totalPtg;
ptgList = ptgList.map((ptg) => (ptg === undefined ? 0 : ptg * scale));
} else {
// If total percentage is smaller than 1, we will fill the rest.
const avgRest = (1 - totalPtg) / emptyCount;
ptgList = ptgList.map((ptg) => (ptg === undefined ? avgRest : ptg));
}
return ptgList as number[];
}, [sizes, containerSize]);
const postPxSizes = React.useMemo(
() => postPercentSizes.map(ptg2px),
[postPercentSizes, containerSize],
);
const postPercentMinSizes = React.useMemo(
() =>
items.map((item) => {
if (isPtg(item.min)) {
return getPtg(item.min);
}
return (item.min || 0) / containerSize;
}),
[items, containerSize],
);
const postPercentMaxSizes = React.useMemo(
() =>
items.map((item) => {
if (isPtg(item.max)) {
return getPtg(item.max);
}
return (item.max || containerSize) / containerSize;
}),
[items, containerSize],
);
return [
postPxSizes,
postPercentSizes,
postPercentMinSizes,
postPercentMaxSizes,
setInnerSizes,
] as const;
}