@wordpress/editor
Version:
Enhanced block editor for WordPress posts.
189 lines (184 loc) • 7.69 kB
JavaScript
/**
* External dependencies
*/
import clsx from 'clsx';
/**
* WordPress dependencies
*/
import { Button, Flex, FlexItem } from '@wordpress/components';
import { __, _n, sprintf } from '@wordpress/i18n';
import { useCallback, useRef, createInterpolateElement } from '@wordpress/element';
import { __experimentalUseDialog as useDialog, useInstanceId } from '@wordpress/compose';
import { useDispatch } from '@wordpress/data';
/**
* Internal dependencies
*/
import EntityTypeList from './entity-type-list';
import { useIsDirty } from './hooks/use-is-dirty';
import { store as editorStore } from '../../store';
import { unlock } from '../../lock-unlock';
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
function identity(values) {
return values;
}
/**
* Renders the component for managing saved states of entities.
*
* @param {Object} props The component props.
* @param {Function} props.close The function to close the dialog.
* @param {boolean} props.renderDialog Whether to render the component with modal dialog behavior.
* @param {string} props.variant Changes the layout of the component. When an `inline` value is provided, the action buttons are rendered at the end of the component instead of at the start.
*
* @return {React.ReactNode} The rendered component.
*/
export default function EntitiesSavedStates({
close,
renderDialog,
variant
}) {
const isDirtyProps = useIsDirty();
return /*#__PURE__*/_jsx(EntitiesSavedStatesExtensible, {
close: close,
renderDialog: renderDialog,
variant: variant,
...isDirtyProps
});
}
/**
* Renders a panel for saving entities with dirty records.
*
* @param {Object} props The component props.
* @param {string} props.additionalPrompt Additional prompt to display.
* @param {Function} props.close Function to close the panel.
* @param {Function} props.onSave Function to call when saving entities.
* @param {boolean} props.saveEnabled Flag indicating if save is enabled.
* @param {string} props.saveLabel Label for the save button.
* @param {boolean} props.renderDialog Whether to render the component with modal dialog behavior.
* @param {Array} props.dirtyEntityRecords Array of dirty entity records.
* @param {boolean} props.isDirty Flag indicating if there are dirty entities.
* @param {Function} props.setUnselectedEntities Function to set unselected entities.
* @param {Array} props.unselectedEntities Array of unselected entities.
* @param {string} props.variant Changes the layout of the component. When an `inline` value is provided, the action buttons are rendered at the end of the component instead of at the start.
*
* @return {React.ReactNode} The rendered component.
*/
export function EntitiesSavedStatesExtensible({
additionalPrompt = undefined,
close,
onSave = identity,
saveEnabled: saveEnabledProp = undefined,
saveLabel = __('Save'),
renderDialog,
dirtyEntityRecords,
isDirty,
setUnselectedEntities,
unselectedEntities,
variant = 'default'
}) {
const saveButtonRef = useRef();
const {
saveDirtyEntities
} = unlock(useDispatch(editorStore));
// To group entities by type.
const partitionedSavables = dirtyEntityRecords.reduce((acc, record) => {
const {
name
} = record;
if (!acc[name]) {
acc[name] = [];
}
acc[name].push(record);
return acc;
}, {});
// Sort entity groups.
const {
site: siteSavables,
wp_template: templateSavables,
wp_template_part: templatePartSavables,
...contentSavables
} = partitionedSavables;
const sortedPartitionedSavables = [siteSavables, templateSavables, templatePartSavables, ...Object.values(contentSavables)].filter(Array.isArray);
const saveEnabled = saveEnabledProp !== null && saveEnabledProp !== void 0 ? saveEnabledProp : isDirty;
// Explicitly define this with no argument passed. Using `close` on
// its own will use the event object in place of the expected saved entities.
const dismissPanel = useCallback(() => close(), [close]);
const [saveDialogRef, saveDialogProps] = useDialog({
onClose: () => dismissPanel()
});
const dialogLabelId = useInstanceId(EntitiesSavedStatesExtensible, 'entities-saved-states__panel-label');
const dialogDescriptionId = useInstanceId(EntitiesSavedStatesExtensible, 'entities-saved-states__panel-description');
const selectItemsToSaveDescription = !!dirtyEntityRecords.length ? __('Select the items you want to save.') : undefined;
const isInline = variant === 'inline';
const actionButtons = /*#__PURE__*/_jsxs(_Fragment, {
children: [/*#__PURE__*/_jsx(FlexItem, {
isBlock: isInline ? false : true,
as: Button,
variant: isInline ? 'tertiary' : 'secondary',
size: isInline ? undefined : 'compact',
onClick: dismissPanel,
children: __('Cancel')
}), /*#__PURE__*/_jsx(FlexItem, {
isBlock: isInline ? false : true,
as: Button,
ref: saveButtonRef,
variant: "primary",
size: isInline ? undefined : 'compact',
disabled: !saveEnabled,
accessibleWhenDisabled: true,
onClick: () => saveDirtyEntities({
onSave,
dirtyEntityRecords,
entitiesToSkip: unselectedEntities,
close
}),
className: "editor-entities-saved-states__save-button",
children: saveLabel
})]
});
return /*#__PURE__*/_jsxs("div", {
ref: renderDialog ? saveDialogRef : undefined,
...(renderDialog && saveDialogProps),
className: clsx('entities-saved-states__panel', {
'is-inline': isInline
}),
role: renderDialog ? 'dialog' : undefined,
"aria-labelledby": renderDialog ? dialogLabelId : undefined,
"aria-describedby": renderDialog ? dialogDescriptionId : undefined,
children: [!isInline && /*#__PURE__*/_jsx(Flex, {
className: "entities-saved-states__panel-header",
gap: 2,
children: actionButtons
}), /*#__PURE__*/_jsxs("div", {
className: "entities-saved-states__text-prompt",
children: [/*#__PURE__*/_jsx("div", {
className: "entities-saved-states__text-prompt--header-wrapper",
children: /*#__PURE__*/_jsx("strong", {
id: renderDialog ? dialogLabelId : undefined,
className: "entities-saved-states__text-prompt--header",
children: __('Are you ready to save?')
})
}), /*#__PURE__*/_jsxs("div", {
id: renderDialog ? dialogDescriptionId : undefined,
children: [additionalPrompt, /*#__PURE__*/_jsx("p", {
className: "entities-saved-states__text-prompt--changes-count",
children: isDirty ? createInterpolateElement(sprintf(/* translators: %d: number of site changes waiting to be saved. */
_n('There is <strong>%d site change</strong> waiting to be saved.', 'There are <strong>%d site changes</strong> waiting to be saved.', dirtyEntityRecords.length), dirtyEntityRecords.length), {
strong: /*#__PURE__*/_jsx("strong", {})
}) : selectItemsToSaveDescription
})]
})]
}), sortedPartitionedSavables.map(list => {
return /*#__PURE__*/_jsx(EntityTypeList, {
list: list,
unselectedEntities: unselectedEntities,
setUnselectedEntities: setUnselectedEntities
}, list[0].name);
}), isInline && /*#__PURE__*/_jsx(Flex, {
direction: "row",
justify: "flex-end",
className: "entities-saved-states__panel-footer",
children: actionButtons
})]
});
}
//# sourceMappingURL=index.js.map