
META-INF.resources.page_editor.app.components.Sidebar.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 ClayButton, {ClayButtonWithIcon} from '@clayui/button';
import {ReactPortal, useStateSafe} from '@liferay/frontend-js-react-web';
import {Resizer} from '@liferay/layout-js-components-web';
import classNames from 'classnames';
import {useId, useSessionState} from 'frontend-js-components-web';
import {sub} from 'frontend-js-web';
import React, {useRef} from 'react';
import BrowserSidebar from '../../plugins/browser/components/BrowserSidebar';
import CommentsSidebar from '../../plugins/comments/components/CommentsSidebar';
import FragmentsSidebar from '../../plugins/fragments_and_widgets/components/FragmentsSidebar';
import MappingSidebar from '../../plugins/mapping/components/MappingSidebar';
import ContentsSidebar from '../../plugins/page_content/components/ContentsSidebar';
import PageDesignOptionsSidebar from '../../plugins/page_design_options/components/PageDesignOptionsSidebar';
import RulesSidebar from '../../plugins/page_rules/components/RulesSidebar';
import {VIEWPORT_SIZES} from '../config/constants/viewportSizes';
import {config} from '../config/index';
import {useSelectItem} from '../contexts/ControlsContext';
import {useSetOpenShortcutModal} from '../contexts/ShortcutContext';
import {useDispatch, useSelector} from '../contexts/StoreContext';
import selectAvailablePanels from '../selectors/selectAvailablePanels';
import selectItemConfigurationOpen from '../selectors/selectItemConfigurationOpen';
import selectSidebarIsOpened from '../selectors/selectSidebarIsOpened';
import switchSidebarPanel from '../thunks/switchSidebarPanel';
import {useDropClear} from '../utils/drag_and_drop/useDragAndDrop';
import isSmallResolution from '../utils/isSmallResolution';
const {useEffect} = React;
export const MAX_SIDEBAR_WIDTH = 500;
export const MIN_SIDEBAR_WIDTH = 280;
export const SIDEBAR_WIDTH_RESIZE_STEP = 20;
function getActiveSidebarPanel({
sidebarPanelId,
sidebarPanels,
sidebarPanelsMap,
}) {
if (sidebarPanelsMap[sidebarPanelId]) {
return {sidebarPanel: sidebarPanelsMap[sidebarPanelId], sidebarPanelId};
}
const panel = sidebarPanels[0];
return {sidebarPanel: panel, sidebarPanelId: panel.sidebarPanelId};
}
const getOpenShortcutModalTooltipMarkup = () =>
`
${Liferay.Language.get('open-keyboard-shortcuts')}
⇧
+
?
`
.replaceAll('\n', '')
.replaceAll('\t', '');
export default function Sidebar() {
const dropClearRef = useDropClear();
const [hasError, setHasError] = useStateSafe(false);
const dispatch = useDispatch();
const selectItem = useSelectItem();
const setOpenShortcutModal = useSetOpenShortcutModal();
const shortcutButtonTitleId = useId();
const sidebarContentId = useId();
const sidebarId = useId();
const sidebar = useSelector((state) => state.sidebar);
const selectedViewportSize = useSelector(
(state) => state.selectedViewportSize
);
const [sidebarWidth, setSidebarWidth] = useSessionState(
`${config.portletNamespace}_sidebar-width`,
MIN_SIDEBAR_WIDTH
);
const sidebarContentRef = useRef();
const tabListRef = useRef();
const sidebarPanels = useSelector(
selectAvailablePanels(config.sidebarPanels)
);
const sidebarHidden = sidebar.hidden;
const sidebarOpen = selectSidebarIsOpened({sidebar});
const itemConfigurationOpen = selectItemConfigurationOpen({sidebar});
const {sidebarPanel, sidebarPanelId} = getActiveSidebarPanel({
sidebarPanelId: sidebar.panelId,
sidebarPanels,
sidebarPanelsMap: config.sidebarPanelsMap,
});
useEffect(() => {
const wrapper = document.getElementById('wrapper');
if (!wrapper) {
return;
}
wrapper.classList.add('page-editor__wrapper');
wrapper.classList.toggle(
'page-editor__wrapper--padded-start',
sidebarOpen
);
wrapper.classList.toggle(
'page-editor__wrapper--sidebar--hidden',
sidebarHidden
);
wrapper.classList.toggle(
'page-editor__wrapper--padded-end',
itemConfigurationOpen
);
return () => {
wrapper.classList.remove('page-editor__wrapper');
wrapper.classList.remove('page-editor__wrapper--padded-start');
wrapper.classList.remove('page-editor__wrapper--padded-end');
};
}, [sidebarHidden, sidebarOpen, itemConfigurationOpen]);
useEffect(() => {
const wrapper = document.getElementById('wrapper');
if (!wrapper || selectedViewportSize === VIEWPORT_SIZES.desktop) {
return;
}
wrapper.classList.add('overflow-hidden');
return () => {
if (wrapper) {
wrapper.classList.remove('overflow-hidden');
}
};
}, [selectedViewportSize]);
const deselectItem = (event) => {
if (event.target === event.currentTarget) {
selectItem(null);
}
};
const handleClick = (panel) => {
const open =
panel.sidebarPanelId === sidebarPanelId ? !sidebarOpen : true;
const smallResolution = isSmallResolution();
dispatch(
switchSidebarPanel({
itemConfigurationOpen: smallResolution
? false
: sidebar.itemConfigurationOpen,
sidebarOpen: open,
sidebarPanelId: panel.sidebarPanelId,
})
);
if (open) {
sidebarContentRef.current.style.visibility = 'visible';
sidebarContentRef.current?.focus({preventScroll: true});
}
};
const handleTabKeyDown = (event) => {
if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
const tabs = Array.from(
tabListRef.current.querySelectorAll('button')
);
const positionActiveTab = tabs.indexOf(document.activeElement);
const activeTab =
tabs[
event.key === 'ArrowUp'
? positionActiveTab - 1
: positionActiveTab + 1
];
if (activeTab) {
activeTab.focus();
}
}
};
const shortcutButtonTitle = getOpenShortcutModalTooltipMarkup();
return (
{sidebarPanels.map((panel) => {
const active =
sidebarOpen &&
panel.sidebarPanelId === sidebarPanelId;
const {icon, label} = panel;
return (
handleClick(panel)}
role="tab"
size="sm"
symbol={icon}
tabIndex={
panel.sidebarPanelId !== sidebarPanelId
? '-1'
: null
}
title={label}
/>
);
})}
setOpenShortcutModal(true)}
size="sm"
symbol="question-circle-full"
/>
{shortcutButtonTitle}
);
}
const PANEL_COMPONENTS = {
browser: BrowserSidebar,
comments: CommentsSidebar,
fragments_and_widgets: FragmentsSidebar,
mapping: MappingSidebar,
page_content: ContentsSidebar,
page_design_options: PageDesignOptionsSidebar,
page_rules: RulesSidebar,
};
const SidebarPanel = React.memo(({sidebarPanelId}) => {
const Component = PANEL_COMPONENTS[sidebarPanelId];
if (Component !== null) {
return ;
}
return null;
});
class ErrorBoundary extends React.Component {
static getDerivedStateFromError(_error) {
return {hasError: true};
}
constructor(props) {
super(props);
this.state = {hasError: false};
}
componentDidCatch(error) {
if (this.props.handleError) {
this.props.handleError(error);
}
}
render() {
if (this.state.hasError) {
return null;
}
else {
return this.props.children;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy