
META-INF.resources.page_editor.app.components.MasterLayout.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com.liferay.layout.content.page.editor.web
Show all versions of com.liferay.layout.content.page.editor.web
Liferay Layout Content Page Editor Web
The newest version!
/**
* SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com
* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
*/
import classNames from 'classnames';
import {openToast} from 'frontend-js-components-web';
import PropTypes from 'prop-types';
import React, {useCallback, useEffect, useMemo, useRef} from 'react';
import {useDrop} from 'react-dnd';
import {
LayoutDataPropTypes,
getLayoutDataItemPropTypes,
} from '../../prop_types/index';
import {LAYOUT_DATA_ITEM_TYPES} from '../config/constants/layoutDataItemTypes';
import {useSelectItem} from '../contexts/ControlsContext';
import {useSelector, useSelectorRef} from '../contexts/StoreContext';
import Layout from './Layout';
import FragmentContent from './fragment_content/FragmentContent';
import {FormStep} from './layout_data_items/FormStep';
import {FormStepContainer} from './layout_data_items/FormStepContainer';
import hasDropZoneChild from './layout_data_items/hasDropZoneChild';
import {
Collection,
Column,
Container,
Form,
Row,
} from './layout_data_items/index';
const LAYOUT_DATA_ITEMS = {
[LAYOUT_DATA_ITEM_TYPES.collection]: Collection,
[LAYOUT_DATA_ITEM_TYPES.collectionItem]: CollectionItem,
[LAYOUT_DATA_ITEM_TYPES.column]: MasterColumn,
[LAYOUT_DATA_ITEM_TYPES.container]: Container,
[LAYOUT_DATA_ITEM_TYPES.form]: Form,
[LAYOUT_DATA_ITEM_TYPES.formStep]: FormStep,
[LAYOUT_DATA_ITEM_TYPES.formStepContainer]: FormStepContainer,
[LAYOUT_DATA_ITEM_TYPES.dropZone]: DropZoneContainer,
[LAYOUT_DATA_ITEM_TYPES.fragment]: Fragment,
[LAYOUT_DATA_ITEM_TYPES.fragmentDropZone]: Root,
[LAYOUT_DATA_ITEM_TYPES.root]: Root,
[LAYOUT_DATA_ITEM_TYPES.row]: Row,
};
const MasterPage = React.memo(() => {
const fragmentEntryLinks = useSelector((state) => state.fragmentEntryLinks);
const masterLayoutData = useSelector(
(state) => state.masterLayout?.masterLayoutData
);
const mainItem = masterLayoutData.items[masterLayoutData.rootItems.main];
const [, targetRef] = useDrop({
accept: Object.values(LAYOUT_DATA_ITEM_TYPES),
drop: (_, monitor) => {
const {x, y} = monitor.getClientOffset();
const element = document.elementFromPoint(x, y);
if (element.closest('.page-editor')) {
return;
}
openToast({
message: Liferay.Language.get(
'fragments-and-widgets-cannot-be-placed-inside-this-area'
),
type: 'danger',
});
},
});
return (
);
});
MasterPage.displayName = 'MasterPage';
export default MasterPage;
function MasterLayoutDataItem({fragmentEntryLinks, item, layoutData}) {
const Component = LAYOUT_DATA_ITEMS[item.type];
if (!Component) {
return null;
}
return (
{item.children.map((childId) => {
return (
);
})}
);
}
MasterLayoutDataItem.propTypes = {
fragmentEntryLinks: PropTypes.object.isRequired,
item: getLayoutDataItemPropTypes().isRequired,
layoutData: LayoutDataPropTypes.isRequired,
};
function DropZoneContainer() {
const mainItemId = useSelector((state) => state.layoutData.rootItems.main);
return ;
}
function Root({children}) {
return {children};
}
function CollectionItem({children}) {
return {children};
}
function Fragment({item, layoutData}) {
const ref = useRef(null);
const selectItem = useSelectItem();
const hasDropzoneChild = useMemo(
() => hasDropZoneChild(item, layoutData),
[item, layoutData]
);
useEffect(() => {
const element = ref.current;
if (!element) {
return;
}
const handler = (event) => {
const element = event.target;
if (element.closest('[href]')) {
event.preventDefault();
}
if (!event.target.closest('.page-editor')) {
selectItem(null);
}
};
element.addEventListener('click', handler);
if (!hasDropzoneChild) {
element.setAttribute('inert', '');
}
element.setAttribute('aria-hidden', 'true');
return () => {
element.removeEventListener('click', handler);
if (!hasDropzoneChild) {
element.removeAttribute('inert');
}
element.removeAttribute('aria-hidden');
};
});
const fragmentEntryLinksRef = useSelectorRef(
(state) => state.fragmentEntryLinks
);
const masterLayoutDataRef = useSelectorRef(
(state) => state.masterLayout?.masterLayoutData
);
const getPortals = useCallback(
(element) =>
Array.from(element.querySelectorAll('lfr-drop-zone')).map(
(dropZoneElement) => {
const mainItemId =
dropZoneElement.getAttribute('uuid') || '';
const Component = () =>
mainItemId ? (
) : null;
Component.displayName = `DropZone(${mainItemId})`;
return {
Component,
element: dropZoneElement,
};
}
),
[fragmentEntryLinksRef, masterLayoutDataRef]
);
return (
);
}
Fragment.propTypes = {
fragmentEntryLinks: PropTypes.object.isRequired,
item: getLayoutDataItemPropTypes({
config: PropTypes.shape({
fragmentEntryLinkId: PropTypes.string.isRequired,
}),
}).isRequired,
};
function MasterColumn({children, className, ...otherProps}) {
return (
{children}
);
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy