UNPKG

@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
'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