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> </> ); }