UNPKG

@wordpress/components

Version:
115 lines (104 loc) 3.34 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import { createElement } from "@wordpress/element"; /** * External dependencies */ import classnames from 'classnames'; /** * WordPress dependencies */ import { useReducedMotion, useMergeRefs } from '@wordpress/compose'; import { forwardRef, useRef } from '@wordpress/element'; import { chevronUp, chevronDown } from '@wordpress/icons'; /** * Internal dependencies */ import Button from '../button'; import Icon from '../icon'; import { useControlledState, useUpdateEffect } from '../utils'; const noop = () => {}; export function UnforwardedPanelBody(props, ref) { const { buttonProps = {}, children, className, icon, initialOpen, onToggle = noop, opened, title, scrollAfterOpen = true } = props; const [isOpened, setIsOpened] = useControlledState(opened, { initial: initialOpen === undefined ? true : initialOpen, fallback: false }); const nodeRef = useRef(null); // Defaults to 'smooth' scrolling // https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView const scrollBehavior = useReducedMotion() ? 'auto' : 'smooth'; const handleOnToggle = event => { event.preventDefault(); const next = !isOpened; setIsOpened(next); onToggle(next); }; // Ref is used so that the effect does not re-run upon scrollAfterOpen changing value. const scrollAfterOpenRef = useRef(); scrollAfterOpenRef.current = scrollAfterOpen; // Runs after initial render. useUpdateEffect(() => { var _nodeRef$current; if (isOpened && scrollAfterOpenRef.current && (_nodeRef$current = nodeRef.current) !== null && _nodeRef$current !== void 0 && _nodeRef$current.scrollIntoView) { /* * Scrolls the content into view when visible. * This improves the UX when there are multiple stacking <PanelBody /> * components in a scrollable container. */ nodeRef.current.scrollIntoView({ inline: 'nearest', block: 'nearest', behavior: scrollBehavior }); } }, [isOpened, scrollBehavior]); const classes = classnames('components-panel__body', className, { 'is-opened': isOpened }); return createElement("div", { className: classes, ref: useMergeRefs([nodeRef, ref]) }, createElement(PanelBodyTitle, _extends({ icon: icon, isOpened: Boolean(isOpened), onClick: handleOnToggle, title: title }, buttonProps)), typeof children === 'function' ? children({ opened: Boolean(isOpened) }) : isOpened && children); } const PanelBodyTitle = forwardRef((_ref, ref) => { let { isOpened, icon, title, ...props } = _ref; if (!title) return null; return createElement("h2", { className: "components-panel__body-title" }, createElement(Button, _extends({ className: "components-panel__body-toggle", "aria-expanded": isOpened, ref: ref }, props), createElement("span", { "aria-hidden": "true" }, createElement(Icon, { className: "components-panel__arrow", icon: isOpened ? chevronUp : chevronDown })), title, icon && createElement(Icon, { icon: icon, className: "components-panel__icon", size: 20 }))); }); export const PanelBody = forwardRef(UnforwardedPanelBody); export default PanelBody; //# sourceMappingURL=body.js.map