@gfazioli/mantine-split-pane
Version:
A React component that manages split panes allows users to divide and resize content areas within a layout efficiently.
177 lines (174 loc) • 5.07 kB
JavaScript
'use client';
import React, { useImperativeHandle, useEffect } from 'react';
import { createVarsResolver, factory, useProps, useStyles, Box } from '@mantine/core';
import { useSplitContext } from '../Split.context.mjs';
import classes from './SplitPane.module.css.mjs';
const varsResolver = createVarsResolver((_, { grow }) => {
return {
root: {
"--split-pane-grow": grow ? 1 : "initial"
}
};
});
const defaultProps = {
grow: false
};
const SplitPane = factory((_props, ref) => {
const props = useProps("Pane", defaultProps, _props);
const ctx = useSplitContext();
const {
children,
grow,
initialWidth,
initialHeight,
minWidth,
minHeight,
maxWidth,
maxHeight,
onResizeStart,
onResizing,
onResizeEnd,
onResetInitialSize,
className,
style,
classNames,
styles,
unstyled,
vars,
mod,
...others
} = props;
const localRef = React.useRef(null);
useImperativeHandle(ref, () => ({
...localRef.current,
splitPane: localRef.current,
resetInitialSize,
getMinWidth: () => getSizeInPixel(minWidth),
getMinHeight: () => getSizeInPixel(minHeight),
getMaxWidth: () => getSizeInPixel(maxWidth),
getMaxHeight: () => getSizeInPixel(maxHeight),
getInitialWidth: () => initialWidth,
getInitialHeight: () => initialHeight,
onResizeStart: () => onResizeStart && onResizeStart(),
onResizing: (size) => onResizing && onResizing(size),
onResizeEnd: (size) => onResizeEnd && onResizeEnd(size)
}));
const initialWithRef = React.useRef(null);
const initialHeightRef = React.useRef(null);
useEffect(() => {
initialWithRef.current = getInitialVerticalSize();
initialHeightRef.current = getInitialHorizontalSize();
localRef.current.style.width = withPx(getInitialVerticalSize());
localRef.current.style.height = withPx(getInitialHorizontalSize());
}, [localRef.current]);
useEffect(() => {
localRef.current.style.width = withPx(getInitialVerticalSize());
localRef.current.style.height = withPx(getInitialHorizontalSize());
}, [ctx.orientation]);
const getSizeInPixel = (size) => {
if (size) {
if (typeof size === "number") {
return size;
}
if (typeof size === "string" && size.toString().includes("px")) {
const value = parseFloat(size.toString());
return value;
}
if (typeof size === "string" && size.toString().includes("%")) {
const value = parseFloat(size.toString());
const parent = ctx.orientation === "vertical" ? "width" : "height";
const parentSize = localRef.current.parentElement.getBoundingClientRect()[parent];
return parentSize * value / 100;
}
}
};
function withPx(value) {
if (typeof value === "number") {
return `${value}px`;
}
if (typeof value === "string") {
if (value.includes("px")) {
return value;
}
}
return value;
}
function getInitialVerticalSize() {
if (ctx.orientation === "vertical") {
const currentWidth = localRef.current.getBoundingClientRect().width;
if (!initialWidth && !minWidth) {
return currentWidth;
}
if (initialWidth && !minWidth) {
return getSizeInPixel(initialWidth);
}
if (!initialWidth && minWidth) {
return getSizeInPixel(minWidth);
}
if (initialWidth && minWidth) {
return Math.max(getSizeInPixel(initialWidth), getSizeInPixel(minWidth));
}
}
return "auto";
}
function getInitialHorizontalSize() {
if (ctx.orientation === "horizontal") {
const currentHeight = localRef.current.getBoundingClientRect().height;
if (!initialHeight && !minHeight) {
return currentHeight;
}
if (initialHeight && !minHeight) {
return getSizeInPixel(initialHeight);
}
if (!initialHeight && minHeight) {
return getSizeInPixel(minHeight);
}
if (initialHeight && minHeight) {
return Math.max(getSizeInPixel(initialHeight), getSizeInPixel(minHeight));
}
}
return "auto";
}
const getStyles = useStyles({
name: "SplitPane",
classes,
props,
className,
style,
classNames,
styles,
unstyled,
vars,
varsResolver
});
const resetInitialSize = (e) => {
e.preventDefault();
e.stopPropagation();
if (!localRef.current) {
return;
}
if (ctx.orientation === "vertical") {
localRef.current.style.width = withPx(initialWithRef.current);
}
if (ctx.orientation === "horizontal") {
localRef.current.style.height = withPx(initialHeightRef.current);
}
if (onResetInitialSize) {
onResetInitialSize(e);
}
};
return /* @__PURE__ */ React.createElement(
Box,
{
ref: localRef,
mod: { orientation: ctx.orientation },
...others,
...getStyles("root")
},
children
);
});
SplitPane.classes = classes;
SplitPane.displayName = "SplitPane";
export { SplitPane };
//# sourceMappingURL=SplitPane.mjs.map