mirror of
https://github.com/ant-design/ant-design.git
synced 2024-12-19 11:58:41 +08:00
742ce37887
* 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>
151 lines
4.6 KiB
TypeScript
151 lines
4.6 KiB
TypeScript
import * as React from 'react';
|
|
|
|
import type { ItemType } from './useItems';
|
|
import type { ResizableInfo } from './useResizable';
|
|
import { getPtg } from './useSizes';
|
|
|
|
export default function useResize(
|
|
items: ItemType[],
|
|
resizableInfos: ResizableInfo[],
|
|
percentSizes: number[],
|
|
containerSize: number,
|
|
updateSizes: (sizes: number[]) => void,
|
|
) {
|
|
const limitSizes = items.map((item) => [item.min, item.max]);
|
|
|
|
const ptg2px = (ptg: number) => ptg * containerSize;
|
|
|
|
// ======================== Resize ========================
|
|
function getLimitSize(str: string | number | undefined, defaultLimit: number) {
|
|
if (typeof str === 'string') {
|
|
return ptg2px(getPtg(str));
|
|
}
|
|
return str ?? defaultLimit;
|
|
}
|
|
|
|
// Real px sizes
|
|
const [cacheSizes, setCacheSizes] = React.useState<number[]>([]);
|
|
|
|
/**
|
|
* When start drag, check the direct is `start` or `end`.
|
|
* This will handle when 2 splitter bar are in the same position.
|
|
*/
|
|
const [movingIndex, setMovingIndex] = React.useState<{
|
|
index: number;
|
|
confirmed: boolean;
|
|
} | null>(null);
|
|
|
|
const getPxSizes = () => percentSizes.map(ptg2px);
|
|
|
|
const onOffsetStart = (index: number) => {
|
|
setCacheSizes(getPxSizes());
|
|
setMovingIndex({
|
|
index,
|
|
confirmed: false,
|
|
});
|
|
};
|
|
|
|
const onOffsetUpdate = (index: number, offset: number) => {
|
|
// First time trigger move index update is not sync in the state
|
|
let confirmedIndex: number | null = null;
|
|
|
|
// We need to know what the real index is.
|
|
if ((!movingIndex || !movingIndex.confirmed) && offset !== 0) {
|
|
// Search for the real index
|
|
if (offset > 0) {
|
|
confirmedIndex = index;
|
|
setMovingIndex({
|
|
index,
|
|
confirmed: true,
|
|
});
|
|
} else {
|
|
for (let i = index; i >= 0; i -= 1) {
|
|
if (cacheSizes[i] > 0 && resizableInfos[i].resizable) {
|
|
confirmedIndex = i;
|
|
setMovingIndex({
|
|
index: i,
|
|
confirmed: true,
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const mergedIndex = confirmedIndex ?? movingIndex?.index ?? index;
|
|
|
|
const numSizes = [...cacheSizes];
|
|
const nextIndex = mergedIndex + 1;
|
|
|
|
// Get boundary
|
|
const startMinSize = getLimitSize(limitSizes[mergedIndex][0], 0);
|
|
const endMinSize = getLimitSize(limitSizes[nextIndex][0], 0);
|
|
const startMaxSize = getLimitSize(limitSizes[mergedIndex][1], containerSize);
|
|
const endMaxSize = getLimitSize(limitSizes[nextIndex][1], containerSize);
|
|
|
|
let mergedOffset = offset;
|
|
|
|
// Align with the boundary
|
|
if (numSizes[mergedIndex] + mergedOffset < startMinSize) {
|
|
mergedOffset = startMinSize - numSizes[mergedIndex];
|
|
}
|
|
if (numSizes[nextIndex] - mergedOffset < endMinSize) {
|
|
mergedOffset = numSizes[nextIndex] - endMinSize;
|
|
}
|
|
if (numSizes[mergedIndex] + mergedOffset > startMaxSize) {
|
|
mergedOffset = startMaxSize - numSizes[mergedIndex];
|
|
}
|
|
if (numSizes[nextIndex] - mergedOffset > endMaxSize) {
|
|
mergedOffset = numSizes[nextIndex] - endMaxSize;
|
|
}
|
|
|
|
// Do offset
|
|
numSizes[mergedIndex] += mergedOffset;
|
|
numSizes[nextIndex] -= mergedOffset;
|
|
|
|
updateSizes(numSizes);
|
|
|
|
return numSizes;
|
|
};
|
|
|
|
const onOffsetEnd = () => {
|
|
setMovingIndex(null);
|
|
};
|
|
|
|
// ======================= Collapse =======================
|
|
const onCollapse = (index: number, type: 'start' | 'end') => {
|
|
const currentSizes = getPxSizes();
|
|
|
|
const currentIndex = type === 'start' ? index : index + 1;
|
|
const targetIndex = type === 'start' ? index + 1 : index;
|
|
|
|
const currentSize = currentSizes[currentIndex];
|
|
const targetSize = currentSizes[targetIndex];
|
|
|
|
if (currentSize !== 0 && targetSize !== 0) {
|
|
// Collapse directly
|
|
currentSizes[currentIndex] = 0;
|
|
currentSizes[targetIndex] += currentSize;
|
|
} else {
|
|
const totalSize = currentSize + targetSize;
|
|
|
|
const currentSizeMin = getLimitSize(limitSizes[currentIndex][0], 0);
|
|
const currentSizeMax = getLimitSize(limitSizes[currentIndex][1], containerSize);
|
|
const targetSizeMin = getLimitSize(limitSizes[targetIndex][0], 0);
|
|
const targetSizeMax = getLimitSize(limitSizes[targetIndex][1], containerSize);
|
|
|
|
const limitStart = Math.max(currentSizeMin, totalSize - targetSizeMax);
|
|
const limitEnd = Math.min(currentSizeMax, totalSize - targetSizeMin);
|
|
const halfOffset = (limitEnd - limitStart) / 2;
|
|
|
|
currentSizes[currentIndex] -= halfOffset;
|
|
currentSizes[targetIndex] += halfOffset;
|
|
}
|
|
|
|
updateSizes(currentSizes);
|
|
|
|
return currentSizes;
|
|
};
|
|
|
|
return [onOffsetStart, onOffsetUpdate, onOffsetEnd, onCollapse, movingIndex?.index] as const;
|
|
}
|