UNPKG

@gfazioli/mantine-split-pane

Version:

A Mantine 9 React component for resizable split pane layouts with 7 resizer variants, context-based prop inheritance, responsive orientation, and dynamic pane generation.

198 lines (195 loc) 5.47 kB
'use client'; import { createVarsResolver, factory, useProps, useStyles, Box } from '@mantine/core'; import { useResizeObserver, useMergedRef } from '@mantine/hooks'; import React, { useState, useMemo, isValidElement, cloneElement } from 'react'; import { SplitDynamic } from './Dynamic/SplitDynamic.mjs'; import { useResponsiveValue } from './hooks/use-responsive-value.mjs'; import { useSplitResizerOrientation } from './hooks/use-split-resizer-orientation.mjs'; import { SplitPane } from './Pane/SplitPane.mjs'; import { defaultProps as defaultProps$1, SplitResizer } from './Resizer/SplitResizer.mjs'; import { SplitContextProvider } from './Split.context.mjs'; import classes from './Split.module.css.mjs'; const defaultProps = { inline: false, autoResizers: false, ...defaultProps$1 }; const varsResolver = createVarsResolver((_, { inline }) => ({ root: { "--split-inline": inline ? "inline-flex" : "flex" } })); const Split = factory((_props) => { const { ref, ...restProps } = _props; const props = useProps("Split", defaultProps, restProps); const { inline, autoResizers, orientation: propOrientation, opacity, size, radius, withKnob, knobAlwaysOn, knobSize, knobOpacity, knobRadius, knobColor, knobHoverColor, spacing, step, shiftStep, snapPoints, snapTolerance, snapFrom, cursorVertical, cursorHorizontal, color, hoverColor, variant, gradient, hoverGradient, classNames, style, styles, unstyled, vars, mod, children, className, ...others } = props; const orientation = useSplitResizerOrientation(propOrientation ?? "vertical"); const resolvedSize = useResponsiveValue(size) ?? defaultProps$1.size; const resolvedSpacing = useResponsiveValue(spacing) ?? defaultProps$1.spacing; const resolvedKnobSize = useResponsiveValue(knobSize) ?? defaultProps$1.knobSize; const [resizeObserverRef, containerRect] = useResizeObserver(); const [containerSize, setContainerSize] = useState({ width: 0, height: 0 }); React.useEffect(() => { if (containerRect.width > 0 || containerRect.height > 0) { setContainerSize({ width: containerRect.width, height: containerRect.height }); } }, [containerRect.width, containerRect.height]); const mergedRef = useMergedRef(ref, resizeObserverRef); const getStyles = useStyles({ name: "Split", props, classes, className, style, classNames, styles, unstyled, vars, varsResolver }); const childrenCount = React.Children.count(children); const childRefs = useMemo( () => Array.from( { length: childrenCount }, () => React.createRef() ), [childrenCount] ); let clonedChildren; if (autoResizers) { const elementsWithResizers = []; let resizerIndex = 0; let paneIndex = 0; const paneRefs = []; React.Children.forEach(children, (child, index) => { if (isValidElement(child) && child.type === SplitPane) { const ref2 = childRefs[index]; paneRefs.push(ref2); elementsWithResizers.push( cloneElement(child, { key: child.key ?? `pane-${paneIndex}`, ref: ref2 }) ); paneIndex++; } }); const finalElements = []; elementsWithResizers.forEach((pane, index) => { finalElements.push(pane); if (index < elementsWithResizers.length - 1) { const beforeRef = paneRefs[index]; const afterRef = paneRefs[index + 1]; finalElements.push( /* @__PURE__ */ React.createElement( SplitResizer, { key: `auto-resizer-${resizerIndex++}`, __beforeRef: beforeRef, __afterRef: afterRef } ) ); } }); clonedChildren = finalElements; } else { clonedChildren = React.Children.map(children, (child, index) => { if (isValidElement(child)) { if (child.type === SplitResizer) { const beforeRef = childRefs[index - 1]; const afterRef = childRefs[index + 1]; return cloneElement(child, { __beforeRef: beforeRef, __afterRef: afterRef }); } else if (child.type === SplitPane) { return cloneElement(child, { ref: childRefs[index] }); } return child; } return child; }) ?? []; } return /* @__PURE__ */ React.createElement( SplitContextProvider, { value: { orientation, size: resolvedSize, opacity, radius, color, hoverColor, knobSize: resolvedKnobSize, knobOpacity, knobRadius, knobColor, knobHoverColor, variant, withKnob, knobAlwaysOn, spacing: resolvedSpacing, step, shiftStep, snapPoints, snapTolerance, snapFrom, cursorVertical, cursorHorizontal, gradient, hoverGradient, containerSize } }, /* @__PURE__ */ React.createElement(Box, { ref: mergedRef, mod: { orientation }, ...getStyles("root"), ...others }, clonedChildren) ); }); Split.classes = classes; Split.displayName = "Split"; Split.Pane = SplitPane; Split.Resizer = SplitResizer; Split.Dynamic = SplitDynamic; export { Split }; //# sourceMappingURL=Split.mjs.map