@wordpress/interface
Version:
Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.
277 lines (272 loc) • 10.1 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _clsx = _interopRequireDefault(require("clsx"));
var _components = require("@wordpress/components");
var _data = require("@wordpress/data");
var _i18n = require("@wordpress/i18n");
var _icons = require("@wordpress/icons");
var _element = require("@wordpress/element");
var _viewport = require("@wordpress/viewport");
var _preferences = require("@wordpress/preferences");
var _compose = require("@wordpress/compose");
var _plugins = require("@wordpress/plugins");
var _complementaryAreaHeader = _interopRequireDefault(require("../complementary-area-header"));
var _complementaryAreaMoreMenuItem = _interopRequireDefault(require("../complementary-area-more-menu-item"));
var _complementaryAreaToggle = _interopRequireDefault(require("../complementary-area-toggle"));
var _pinnedItems = _interopRequireDefault(require("../pinned-items"));
var _store = require("../../store");
var _jsxRuntime = require("react/jsx-runtime");
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
const ANIMATION_DURATION = 0.3;
function ComplementaryAreaSlot({
scope,
...props
}) {
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Slot, {
name: `ComplementaryArea/${scope}`,
...props
});
}
const SIDEBAR_WIDTH = 280;
const variants = {
open: {
width: SIDEBAR_WIDTH
},
closed: {
width: 0
},
mobileOpen: {
width: '100vw'
}
};
function ComplementaryAreaFill({
activeArea,
isActive,
scope,
children,
className,
id
}) {
const disableMotion = (0, _compose.useReducedMotion)();
const isMobileViewport = (0, _compose.useViewportMatch)('medium', '<');
// This is used to delay the exit animation to the next tick.
// The reason this is done is to allow us to apply the right transition properties
// When we switch from an open sidebar to another open sidebar.
// we don't want to animate in this case.
const previousActiveArea = (0, _compose.usePrevious)(activeArea);
const previousIsActive = (0, _compose.usePrevious)(isActive);
const [, setState] = (0, _element.useState)({});
(0, _element.useEffect)(() => {
setState({});
}, [isActive]);
const transition = {
type: 'tween',
duration: disableMotion || isMobileViewport || !!previousActiveArea && !!activeArea && activeArea !== previousActiveArea ? 0 : ANIMATION_DURATION,
ease: [0.6, 0, 0.4, 1]
};
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Fill, {
name: `ComplementaryArea/${scope}`,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__unstableAnimatePresence, {
initial: false,
children: (previousIsActive || isActive) && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__unstableMotion.div, {
variants: variants,
initial: "closed",
animate: isMobileViewport ? 'mobileOpen' : 'open',
exit: "closed",
transition: transition,
className: "interface-complementary-area__fill",
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
id: id,
className: className,
style: {
width: isMobileViewport ? '100vw' : SIDEBAR_WIDTH
},
children: children
})
})
})
});
}
function useAdjustComplementaryListener(scope, identifier, activeArea, isActive, isSmall) {
const previousIsSmallRef = (0, _element.useRef)(false);
const shouldOpenWhenNotSmallRef = (0, _element.useRef)(false);
const {
enableComplementaryArea,
disableComplementaryArea
} = (0, _data.useDispatch)(_store.store);
(0, _element.useEffect)(() => {
// If the complementary area is active and the editor is switching from
// a big to a small window size.
if (isActive && isSmall && !previousIsSmallRef.current) {
disableComplementaryArea(scope);
// Flag the complementary area to be reopened when the window size
// goes from small to big.
shouldOpenWhenNotSmallRef.current = true;
} else if (
// If there is a flag indicating the complementary area should be
// enabled when we go from small to big window size and we are going
// from a small to big window size.
shouldOpenWhenNotSmallRef.current && !isSmall && previousIsSmallRef.current) {
// Remove the flag indicating the complementary area should be
// enabled.
shouldOpenWhenNotSmallRef.current = false;
enableComplementaryArea(scope, identifier);
} else if (
// If the flag is indicating the current complementary should be
// reopened but another complementary area becomes active, remove
// the flag.
shouldOpenWhenNotSmallRef.current && activeArea && activeArea !== identifier) {
shouldOpenWhenNotSmallRef.current = false;
}
if (isSmall !== previousIsSmallRef.current) {
previousIsSmallRef.current = isSmall;
}
}, [isActive, isSmall, scope, identifier, activeArea, disableComplementaryArea, enableComplementaryArea]);
}
function ComplementaryArea({
children,
className,
closeLabel = (0, _i18n.__)('Close plugin'),
identifier: identifierProp,
header,
headerClassName,
icon: iconProp,
isPinnable = true,
panelClassName,
scope,
name,
title,
toggleShortcut,
isActiveByDefault
}) {
const context = (0, _plugins.usePluginContext)();
const icon = iconProp || context.icon;
const identifier = identifierProp || `${context.name}/${name}`;
// This state is used to delay the rendering of the Fill
// until the initial effect runs.
// This prevents the animation from running on mount if
// the complementary area is active by default.
const [isReady, setIsReady] = (0, _element.useState)(false);
const {
isLoading,
isActive,
isPinned,
activeArea,
isSmall,
isLarge,
showIconLabels
} = (0, _data.useSelect)(select => {
const {
getActiveComplementaryArea,
isComplementaryAreaLoading,
isItemPinned
} = select(_store.store);
const {
get
} = select(_preferences.store);
const _activeArea = getActiveComplementaryArea(scope);
return {
isLoading: isComplementaryAreaLoading(scope),
isActive: _activeArea === identifier,
isPinned: isItemPinned(scope, identifier),
activeArea: _activeArea,
isSmall: select(_viewport.store).isViewportMatch('< medium'),
isLarge: select(_viewport.store).isViewportMatch('large'),
showIconLabels: get('core', 'showIconLabels')
};
}, [identifier, scope]);
const isMobileViewport = (0, _compose.useViewportMatch)('medium', '<');
useAdjustComplementaryListener(scope, identifier, activeArea, isActive, isSmall);
const {
enableComplementaryArea,
disableComplementaryArea,
pinItem,
unpinItem
} = (0, _data.useDispatch)(_store.store);
(0, _element.useEffect)(() => {
// Set initial visibility: For large screens, enable if it's active by
// default. For small screens, always initially disable.
if (isActiveByDefault && activeArea === undefined && !isSmall) {
enableComplementaryArea(scope, identifier);
} else if (activeArea === undefined && isSmall) {
disableComplementaryArea(scope, identifier);
}
setIsReady(true);
}, [activeArea, isActiveByDefault, scope, identifier, isSmall, enableComplementaryArea, disableComplementaryArea]);
if (!isReady) {
return;
}
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
children: [isPinnable && /*#__PURE__*/(0, _jsxRuntime.jsx)(_pinnedItems.default, {
scope: scope,
children: isPinned && /*#__PURE__*/(0, _jsxRuntime.jsx)(_complementaryAreaToggle.default, {
scope: scope,
identifier: identifier,
isPressed: isActive && (!showIconLabels || isLarge),
"aria-expanded": isActive,
"aria-disabled": isLoading,
label: title,
icon: showIconLabels ? _icons.check : icon,
showTooltip: !showIconLabels,
variant: showIconLabels ? 'tertiary' : undefined,
size: "compact",
shortcut: toggleShortcut
})
}), name && isPinnable && /*#__PURE__*/(0, _jsxRuntime.jsx)(_complementaryAreaMoreMenuItem.default, {
target: name,
scope: scope,
icon: icon,
children: title
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(ComplementaryAreaFill, {
activeArea: activeArea,
isActive: isActive,
className: (0, _clsx.default)('interface-complementary-area', className),
scope: scope,
id: identifier.replace('/', ':'),
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_complementaryAreaHeader.default, {
className: headerClassName,
closeLabel: closeLabel,
onClose: () => disableComplementaryArea(scope),
toggleButtonProps: {
label: closeLabel,
size: 'compact',
shortcut: toggleShortcut,
scope,
identifier
},
children: header || /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("h2", {
className: "interface-complementary-area-header__title",
children: title
}), isPinnable && !isMobileViewport && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button, {
className: "interface-complementary-area__pin-unpin-item",
icon: isPinned ? _icons.starFilled : _icons.starEmpty,
label: isPinned ? (0, _i18n.__)('Unpin from toolbar') : (0, _i18n.__)('Pin to toolbar'),
onClick: () => (isPinned ? unpinItem : pinItem)(scope, identifier),
isPressed: isPinned,
"aria-expanded": isPinned,
size: "compact"
})]
})
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Panel, {
className: panelClassName,
children: children
})]
})]
});
}
ComplementaryArea.Slot = ComplementaryAreaSlot;
var _default = exports.default = ComplementaryArea;
//# sourceMappingURL=index.js.map