UNPKG

@ui5/webcomponents-react

Version:

React Wrapper for UI5 Web Components and additional components

94 lines (93 loc) 3.23 kB
'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 };