design-comuni-plone-theme
Version:
Volto Theme for Italia design guidelines
247 lines (227 loc) • 7.93 kB
JSX
/**
* Edit icons block.
* @module components/ItaliaTheme/Blocks/Accordion/Edit
*/
import React from 'react';
import { defineMessages } from 'react-intl';
import { Container, Row, Col } from 'design-react-kit';
import { SidebarPortal } from '@plone/volto/components';
import { flattenToAppURL } from '@plone/volto/helpers';
import { UniversalLink } from '@plone/volto/components';
import { handleKeyDownOwnFocusManagement } from 'design-comuni-plone-theme/helpers/blocks';
import {
withDNDContext,
SubblocksEdit,
SubblocksWrapper,
} from 'volto-subblocks';
import { TextEditorWidget } from 'design-comuni-plone-theme/components/ItaliaTheme';
import EditBlock from './Block/EditBlock';
import Sidebar from './Sidebar';
const messages = defineMessages({
addItem: {
id: 'Add accordion item',
defaultMessage: 'Aggiungi elemento',
},
title: {
id: 'Title',
defaultMessage: 'Titolo...',
},
description: {
id: 'Description',
defaultMessage: 'Descrizione...',
},
});
/**
* Edit Accordion block class.
* @class Edit
* @extends Component
*/
class Edit extends SubblocksEdit {
constructor(props) {
super(props);
this.state.selectedField = 'title';
this.nodeF = React.createRef();
}
UNSAFE_componentWillReceiveProps(newProps) {
if (newProps.selected) {
if (!this.props.selected) {
if (!this.state.selectedField && this.state.subIndexSelected < 0) {
//a11y - test subIndexSelected<0 per gestire il focus con navigazione da tastiera al contrario (dal blocco successivo a questo blocco)
this.setState({ selectedField: 'title' });
}
}
} else {
this.setState({ selectedField: null });
}
}
handleEnter = (e) => {
if (
this.props.selected &&
this.state.subIndexSelected < 0 &&
!this.state.selectedField
) {
handleKeyDownOwnFocusManagement(e, this.props);
}
};
handleClick = (e) => {
const hasParent = (element, className) => {
if (!element.parentNode) {
return false;
}
if (element.classList.contains(className)) {
return true;
}
return hasParent(element.parentNode, className);
};
const clickOutsideSubblocks =
!e.target.classList.contains('volto-subblocks-wrapper') &&
!hasParent(e.target, 'volto-subblocks-wrapper');
if (clickOutsideSubblocks) {
this.setState({ subIndexSelected: -1 });
}
};
componentDidMount() {
if (this.props.selected && this.node) {
this.node.focus();
}
if (this.props.selected && this.nodeF.current) {
this.nodeF.current.focus();
}
if (this.state.subblocks.length === 0) {
this.addSubblock();
}
if (this.nodeF && this.nodeF.current) {
this.nodeF.current.addEventListener('keydown', this.handleEnter, false);
this.nodeF.current.addEventListener('click', this.handleClick, false);
}
}
/**
* Render method.
* @method render
* @returns {string} Markup for the component.
*/
render() {
if (__SERVER__) {
return <div />;
}
return (
<div className="public-ui" tabIndex="-1" ref={this.nodeF}>
<div
className={`full-width section bg-${
this.props.data.bg_color ?? 'primary'
} py-5`}
role="form"
aria-label={this.props.blocksConfig[this.props.type].title}
>
<Container className="px-md-4">
<div className="block-header">
<div className="title">
<TextEditorWidget
{...this.props}
key="title"
showToolbar={false}
data={this.props.data}
fieldName="title"
selected={this.state.selectedField === 'title'}
placeholder={this.props.intl.formatMessage(messages.title)}
setSelected={(f) => {
this.setState({ selectedField: f, subIndexSelected: -1 });
if (!this.props.selected) {
//a11y - per il focus del blocco da tastiera
this.props.onSelectBlock(this.props.block);
}
}}
focusNextField={() => {
this.setState({ selectedField: 'description' });
}}
/>
</div>
<div className="description">
<TextEditorWidget
{...this.props}
key="description"
data={this.props.data}
fieldName="description"
selected={this.state.selectedField === 'description'}
placeholder={this.props.intl.formatMessage(
messages.description,
)}
setSelected={(f) => {
this.setState({ selectedField: f, subIndexSelected: -1 });
}}
focusPrevField={() => {
this.setState({ selectedField: 'title' });
}}
focusNextField={() => {
this.setState({ selectedField: null, subIndexSelected: 0 });
}}
/>
</div>
</div>
<SubblocksWrapper node={this.node}>
<Row
className={
this.state.subblocks.length > 3
? 'justify-content-start'
: 'justify-content-center'
}
>
{this.state.subblocks.map((subblock, subindex) => (
<Col lg="4" key={subblock.id} className="pb-3">
<EditBlock
{...this.props}
data={subblock}
index={subindex}
blockIndex={this.props.index}
selected={this.isSubblockSelected(subindex)}
{...this.subblockProps}
onChangeFocus={this.onSubblockChangeFocus}
isLast={subindex === this.state.subblocks.length - 1}
isFirst={subindex === 0}
onFocusPreviousBlock={() => {
this.setState({
selectedField: 'description',
subIndexSelected: -1,
});
}}
/>
</Col>
))}
{this.props.selected && (
<Col lg={12} className="text-center pb-3">
{this.renderAddBlockButton(
this.props.intl.formatMessage(messages.addItem),
)}
</Col>
)}
</Row>
</SubblocksWrapper>
{this.props.data.href && this.props.data.linkMoreTitle && (
<div className="link-button text-center my-4">
<UniversalLink
href={flattenToAppURL(this.props.data.href)}
className="btn btn-tertiary"
>
{this.props.data.linkMoreTitle}
</UniversalLink>
</div>
)}
<SidebarPortal selected={this.props.selected || false}>
<Sidebar
{...this.props}
data={this.props.data}
block={this.props.block}
onChangeBlock={this.props.onChangeBlock}
onChangeSubBlock={this.onChangeSubblocks}
selected={this.state.subIndexSelected}
setSelected={this.onSubblockChangeFocus}
openObjectBrowser={this.props.openObjectBrowser}
/>
</SidebarPortal>
</Container>
</div>
</div>
);
}
}
export default React.memo(withDNDContext(Edit));