Skip to content
Snippets Groups Projects
Select Git revision
  • c47c124a7a49c3fc99e1803e9c957b1bbec6e164
  • main default protected
  • just_for_review
  • 1.0.0
4 results

FlexibleTable.jsx

Blame
  • FlexibleTable.jsx 13.14 KiB
    import {__} from '@wordpress/i18n';
    import {
    	RichText,
    	InspectorControls,
    	useBlockProps,
    } from '@wordpress/block-editor';
    import {
    	PanelBody,
    	ToggleControl,
    } from '@wordpress/components';
    import {DragDropContext, Draggable, Droppable} from "react-beautiful-dnd";
    import ColorSelector from "../ColorSelector/ColorSelector";
    import NumberWithUnit from "../NumberWithUnit/NumberWithUnit";
    import AlignButtons from "../AlignButtons/AlignButtons";
    import FontStyles from "../FontStyles/FontStyles";
    import QuatroInput from "../QuatroInput/QuatroInput";
    import BlockPlaceholders from "../BlockPlaceholders/BlockPlaceholders";
    
    export default function FlexibleTable({attributes, setAttributes, placeholders, footer, additionalOptions }) {
    	const {
    		headers,
    		rows,
    		states,
    
    		headerBackground,
    		headerTextColor,
    		headerTextAlign,
    		headerFontWeight,
    		headerFontStyle,
    		headerTextDecoration,
    		headerFontSize,
    
    		headerBorderRowWidthTop,
    		headerBorderRowWidthLeft,
    		headerBorderRowWidthRight,
    		headerBorderRowWidthBottom,
    		headerBorderRowColor,
    		headerBorderCellWidthTop,
    		headerBorderCellWidthLeft,
    		headerBorderCellWidthRight,
    		headerBorderCellWidthBottom,
    		headerBorderCellColor,
    
    		bodyBackground,
    		multipleBodyBackground,
    		bodyBackgroundOdd,
    		bodyTextColorOdd,
    		bodyTextColor,
    		bodyTextAlign,
    		bodyFontWeight,
    		bodyFontStyle,
    		bodyTextDecoration,
    		bodyFontSize,
    
    		bodyBorderRowWidthTop,
    		bodyBorderRowWidthLeft,
    		bodyBorderRowWidthRight,
    		bodyBorderRowWidthBottom,
    		bodyBorderRowColor,
    		bodyBorderCellWidthTop,
    		bodyBorderCellWidthLeft,
    		bodyBorderCellWidthRight,
    		bodyBorderCellWidthBottom,
    		bodyBorderCellColor,
    
    	} = attributes;
    
    	const blockProps = useBlockProps();
    
    	const handleMultipleAttributesChange = (newValues) => {
    		setAttributes({...attributes, ...newValues});
    	}
    
    	const updateHeader = (index, value) => {
    		const newHeaders = [...headers];
    		newHeaders[index] = value;
    		setAttributes({headers: newHeaders});
    	};
    
    	const updateCell = (index, value) => {
    		const newRows = [...rows];
    		newRows[index] = value;
    		setAttributes({rows: newRows});
    	};
    
    	const toggleColumn = (index, value) => {
    		const newStates = [...states];
    		newStates[index] = value;
    		setAttributes({states: newStates});
    	};
    
    	const handleDragEnd = (result) => {
    		if (!result.destination) {
    			return;
    		}
    
    		const {source, destination} = result;
    		const newHeaders = [...headers];
    		const newStates = [...states];
    		const newRows = [...rows];
    
    		const [movedHeader] = newHeaders.splice(source.index, 1);
    		newHeaders.splice(destination.index, 0, movedHeader);
    
    		const [movedState] = newStates.splice(source.index, 1);
    		newStates.splice(destination.index, 0, movedState);
    
    		const [movedRow] = newRows.splice(source.index, 1);
    		newRows.splice(destination.index, 0, movedRow);
    
    		setAttributes({
    			headers: newHeaders,
    			states: newStates,
    			rows: newRows
    		});
    	};
    
    	return (
    		<>
    			<InspectorControls>
    				<PanelBody title={__("Table columns", "flexible-invoices-core")}>
    					<DragDropContext onDragEnd={handleDragEnd}>
    						<Droppable droppableId="table-columns">
    							{(provided) => (
    								<ul
    									{...provided.droppableProps}
    									ref={provided.innerRef}
    									style={{padding: 0, listStyle: "none"}}
    								>
    									{headers.map((header, index) => (
    										<Draggable key={header} draggableId={header} index={index}>
    											{(provided) => (
    												<li
    													ref={provided.innerRef}
    													{...provided.draggableProps}
    													{...provided.dragHandleProps}
    													className="fi-settings-toggle"
    													style={{
    														...provided.draggableProps.style,
    													}}
    												>
    													<div className="fi-settings-toggle-header">
    														<span className="dashicons dashicons-ellipsis"></span>
    														<span>{header}</span>
    													</div>
    													<ToggleControl
    														checked={states[index]}
    														onChange={(newValue) => toggleColumn(index, newValue)}
    													/>
    												</li>
    											)}
    										</Draggable>
    									))}
    									{provided.placeholder}
    								</ul>
    							)}
    						</Droppable>
    					</DragDropContext>
    				</PanelBody>
    				<PanelBody title={__('Header appearance', 'flexible-invoices-core')}>
    					<ColorSelector
    						label={__('Text Color', 'flexible-invoices-core')}
    						value={headerTextColor}
    						enableAlpha={false}
    						onChange={(value) => setAttributes({headerTextColor: value})}
    					/>
    					<ColorSelector
    						label={__('Background Color', 'flexible-invoices-core')}
    						value={headerBackground}
    						onChange={(value) => setAttributes({headerBackground: value})}
    					/>
    					<NumberWithUnit
    						label={__('Font Size', 'flexible-invoices-core')}
    						value={headerFontSize}
    						onChange={(value) => setAttributes({headerFontSize: value})}
    					/>
    					<AlignButtons
    						label={__('Text Align', 'flexible-invoices-core')}
    						onChange={(value) => setAttributes({headerTextAlign: value})}
    					/>
    					<FontStyles
    						label={__('Font style', 'flexible-invoices-core')}
    						onChange={(newFontStyles) => setAttributes({
    							...attributes,
    							headerFontStyle: newFontStyles.fontStyle,
    							headerFontWeight: newFontStyles.fontWeight,
    							headerTextDecoration: newFontStyles.textDecoration
    						})}
    						values={
    							{
    								fontStyle: headerFontStyle,
    								fontWeight: headerFontWeight,
    								textDecoration: headerTextDecoration
    							}
    						}
    					/>
    					<ColorSelector
    						label={__('Border row color', 'flexible-invoices-core')}
    						value={headerBorderRowColor}
    						enableAlpha={false}
    						returnFormat={'hex'}
    						onChange={(value) => setAttributes({headerBorderRowColor: value})}
    					/>
    					<QuatroInput
    						label={__("Border row width", 'flexible-invoices-core')}
    						values={
    							{
    								headerBorderRowWidthTop: headerBorderRowWidthTop,
    								headerBorderRowWidthLeft: headerBorderRowWidthLeft,
    								headerBorderRowWidthRight: headerBorderRowWidthRight,
    								headerBorderRowWidthBottom: headerBorderRowWidthBottom,
    							}
    						}
    						onChange={handleMultipleAttributesChange}
    					/>
    					<ColorSelector
    						label={__('Border cell color', 'flexible-invoices-core')}
    						value={headerBorderCellColor}
    						enableAlpha={false}
    						returnFormat={'hex'}
    						onChange={(value) => setAttributes({headerBorderCellColor: value})}
    					/>
    					<QuatroInput
    						label={__("Border cell width", 'flexible-invoices-core')}
    						values={
    							{
    								headerBorderCellWidthTop: headerBorderCellWidthTop,
    								headerBorderCellWidthLeft: headerBorderCellWidthLeft,
    								headerBorderCellWidthRight: headerBorderCellWidthRight,
    								headerBorderCellWidthBottom: headerBorderCellWidthBottom,
    							}
    						}
    						onChange={handleMultipleAttributesChange}
    					/>
    
    				</PanelBody>
    				<PanelBody title={__('Body appearance', 'flexible-invoices-core')}>
    					<ColorSelector
    						label={__('Text color', 'flexible-invoices-core')}
    						value={bodyTextColor}
    						enableAlpha={false}
    						onChange={(value) => setAttributes({bodyTextColor: value})}
    					/>
    					<ColorSelector
    						label={__('Background color', 'flexible-invoices-core')}
    						value={bodyBackground}
    						enableAlpha={false}
    						onChange={(value) => setAttributes({bodyBackground: value})}
    					/>
    
    					<ToggleControl
    						label={__('Duo color table', 'flexible-invoices-core')}
    						checked={multipleBodyBackground}
    						onChange={(newValue) => setAttributes({multipleBodyBackground: newValue})}
    					/>
    
    					{multipleBodyBackground ?
    						<>
    							<ColorSelector
    						label={__('Background color (odd rows)', 'flexible-invoices-core')}
    						value={bodyBackgroundOdd}
    						onChange={(value) => setAttributes({bodyBackgroundOdd: value})}
    					/>
    						<ColorSelector
    							label={__('Text color (odd rows)', 'flexible-invoices-core')}
    							value={bodyTextColorOdd}
    							enableAlpha={false}
    							onChange={(value) => setAttributes({bodyTextColorOdd: value})}
    						/>
    						</>
    						: ''
    
    					}
    
    					<NumberWithUnit
    						label={__('Font size', 'flexible-invoices-core')}
    						value={bodyFontSize}
    						onChange={(value) => setAttributes({bodyFontSize: value})}
    					/>
    					<AlignButtons
    						label={__('Text align', 'flexible-invoices-core')}
    						onChange={(value) => setAttributes({bodyTextAlign: value})}
    					/>
    					<FontStyles
    						label={__('Font style', 'flexible-invoices-core')}
    						onChange={(newFontStyles) => setAttributes({
    							...attributes,
    							bodyFontStyle: newFontStyles.fontStyle,
    							bodyFontWeight: newFontStyles.fontWeight,
    							bodyTextDecoration: newFontStyles.textDecoration
    						})}
    						values={
    							{
    								fontStyle: bodyFontStyle,
    								fontWeight: bodyFontWeight,
    								textDecoration: bodyTextDecoration
    							}
    						}
    					/>
    					<ColorSelector
    						label={__('Border row color', 'flexible-invoices-core')}
    						value={bodyBorderRowColor}
    						enableAlpha={false}
    						onChange={(value) => setAttributes({bodyBorderRowColor: value})}
    					/>
    					<QuatroInput
    						label={__("Border row width", 'flexible-invoices-core')}
    						values={
    							{
    								bodyBorderRowWidthTop: bodyBorderRowWidthTop,
    								bodyBorderRowWidthLeft: bodyBorderRowWidthLeft,
    								bodyBorderRowWidthRight: bodyBorderRowWidthRight,
    								bodyBorderRowWidthBottom: bodyBorderRowWidthBottom,
    							}
    						}
    						onChange={handleMultipleAttributesChange}
    					/>
    					<ColorSelector
    						label={__('Border cell color', 'flexible-invoices-core')}
    						value={bodyBorderCellColor}
    						enableAlpha={false}
    						onChange={(value) => setAttributes({bodyBorderCellColor: value})}
    					/>
    					<QuatroInput
    						label={__("Border cell width", 'flexible-invoices-core')}
    						values={
    							{
    								bodyBorderCellWidthTop: bodyBorderCellWidthTop,
    								bodyBorderCellWidthLeft: bodyBorderCellWidthLeft,
    								bodyBorderCellWidthRight: bodyBorderCellWidthRight,
    								bodyBorderCellWidthBottom: bodyBorderCellWidthBottom,
    							}
    						}
    						onChange={handleMultipleAttributesChange}
    					/>
    				</PanelBody>
    				{additionalOptions}
    				{placeholders && <BlockPlaceholders
    					placeholders={placeholders}
    				/>}
    			</InspectorControls>
    			<div {...blockProps}>
    				<table className="fitb-item-table has-background" style={{
    					borderCollapse: 'collapse'
    				}}>
    					<thead className={"fitb-item-table-header"} style={{
    						borderStyle: "solid",
    						borderColor: headerBorderRowColor,
    						borderTopWidth: headerBorderRowWidthTop,
    						borderLeftWidth: headerBorderRowWidthLeft,
    						borderRightWidth: headerBorderRowWidthRight,
    						borderBottomWidth: headerBorderRowWidthBottom,
    					}}>
    					<tr className={"fitb-item-table-header-row"} style={{
    						background: headerBackground,
    					}}>
    						{headers.map((header, index) => (
    							states[index] ?
    								<th className={"fitb-item-table-header-cell"} key={index}
    									style={{
    										borderStyle: "solid",
    										borderColor: headerBorderCellColor,
    										borderTopWidth: headerBorderCellWidthTop,
    										borderLeftWidth: headerBorderCellWidthLeft,
    										borderRightWidth: headerBorderCellWidthRight,
    										borderBottomWidth: headerBorderCellWidthBottom,
    									}}>
    									<RichText
    										tagName="div"
    										key={index}
    										value={header}
    										style={{
    											color: headerTextColor,
    											textAlign: headerTextAlign,
    											fontStyle: headerFontStyle,
    											textDecoration: headerTextDecoration,
    											fontSize: headerFontSize,
    											fontWeight: headerFontWeight,
    										}}
    										onChange={(value) => updateHeader(index, value)}
    									/>
    								</th> : ''
    						))}
    					</tr>
    					</thead>
    					<tbody className={"fitb-item-table-body"}>
    
    					{Array.from({length: 2}).map((_, index) => (
    						<tr className={"fitb-item-table-row"} style={{
    							background: (multipleBodyBackground && index === 1) ? bodyBackgroundOdd : bodyBackground,
    							borderStyle: "solid",
    							borderColor: bodyBorderRowColor,
    							borderTopWidth: bodyBorderRowWidthTop,
    							borderLeftWidth: bodyBorderRowWidthLeft,
    							borderRightWidth: bodyBorderRowWidthRight,
    							borderBottomWidth: bodyBorderRowWidthBottom,
    						}}>
    							{rows.map((row, index) => (
    								states[index] ?
    									<td className={"fitb-item-table-cell"} key={index}
    										style={{
    											borderStyle: "solid",
    											borderColor: bodyBorderCellColor,
    											borderTopWidth: bodyBorderCellWidthTop,
    											borderLeftWidth: bodyBorderCellWidthLeft,
    											borderRightWidth: bodyBorderCellWidthRight,
    											borderBottomWidth: bodyBorderCellWidthBottom,
    										}}>
    										<RichText
    											tagName="div"
    											key={index}
    											value={row}
    											style={{
    												color: (multipleBodyBackground && index === 1) ? bodyTextColorOdd : bodyTextColor,
    												textAlign: bodyTextAlign,
    												fontStyle: bodyFontStyle,
    												fontSize: bodyFontSize,
    												textDecoration: bodyTextDecoration,
    												fontWeight: bodyFontWeight,
    											}}
    											onChange={(value) =>
    												updateCell(index, value)
    											}
    										/>
    									</td> : ''
    							))}
    						</tr>
    					))}
    					</tbody>
    					{footer &&
    						<tfoot>
    						{footer}
    						</tfoot>
    					}
    				</table>
    			</div>
    		</>
    	);
    }