@ui5/webcomponents-react
Version:
React Wrapper for UI5 Web Components and additional components
94 lines (93 loc) • 3.23 kB
JavaScript
'use client';
import { Device, useIsomorphicLayoutEffect, useSyncRef, useStylesheet } from '@ui5/webcomponents-react-base';
import { clsx } from 'clsx';
import { forwardRef, useContext, useEffect, useState } from 'react';
import { SplitterLayoutContext } from '../../internal/SplitterLayoutContext.js';
import { classNames, styleData } from './SplitterElement.module.css.js';
import { jsx as _jsx } from "react/jsx-runtime";
/**
* The `SplitterElement` holds the component of the content area. Allowed size values are of the type css property width or
* height according to the orientation of the `SplitterLayout`. If `size` isn't passed to the element, the width or
* height of the content area will be calculated automatically according to the size of the given `SplitterLayout`.
* The `minSize` defines the minimum width or height of the area and is set to 0 when no minimum size is given, so the
* content can be completely collapsed.
*/
const SplitterElement = /*#__PURE__*/forwardRef((props, ref) => {
const {
children,
style,
className,
minSize = 0,
size = 'auto',
resizable: _0,
...rest
} = props;
const [componentRef, splitterElementRef] = useSyncRef(ref);
const {
vertical,
reset
} = useContext(SplitterLayoutContext);
const safariStyles = Device.isSafari() ? {
width: 'min-content',
flex: '1 1 auto'
} : {};
const defaultFlexStyles = size !== 'auto' ? {
flex: `0 1 ${size}`
} : {
flex: '1 0 min-content',
...safariStyles
};
const [flexStyles, setFlexStyles] = useState(defaultFlexStyles);
const [flexBasisApplied, setFlexBasisApplied] = useState(false);
useStylesheet(styleData, SplitterElement.displayName);
useEffect(() => {
const elementObserver = new ResizeObserver(([element]) => {
if (element.target.getBoundingClientRect().width !== 0 && !flexBasisApplied) {
const resetSafariStyles = Device.isSafari() ? {
width: 'unset'
} : {};
setFlexStyles({
flex: `0 0 ${element.target.getBoundingClientRect()[vertical ? 'height' : 'width']}px`,
...resetSafariStyles
});
setFlexBasisApplied(true);
}
});
if (size === 'auto' && splitterElementRef.current) {
elementObserver.observe(splitterElementRef.current);
} else {
setFlexStyles({
flex: `0 1 ${size}`
});
}
return () => {
elementObserver.disconnect();
};
}, [size, flexBasisApplied, vertical]);
useIsomorphicLayoutEffect(() => {
if (reset) {
setFlexStyles(undefined);
setFlexBasisApplied(false);
}
}, [reset, size]);
useIsomorphicLayoutEffect(() => {
if (flexStyles === undefined) {
setFlexStyles(defaultFlexStyles);
}
}, [flexStyles]);
return /*#__PURE__*/_jsx("div", {
ref: componentRef,
className: clsx(classNames.splitterElement, className),
style: {
minHeight: vertical && minSize ? `${minSize}px` : undefined,
minWidth: !vertical && minSize ? `${minSize}px` : undefined,
...flexStyles,
...style
},
...rest,
"data-min-size": minSize,
children: children
});
});
SplitterElement.displayName = 'SplitterElement';
export { SplitterElement };