diff --git a/index.js b/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..27d9ba3d3219996f8680dd6b64ba98b5aae5967a
--- /dev/null
+++ b/index.js
@@ -0,0 +1,8 @@
+export { default as AlignButtons } from "./src/AlignButtons/AlignButtons";
+export { default as BlockPlaceholders } from "./src/BlockPlaceholders/BlockPlaceholders";
+export { default as ColorSelector } from "./src/ColorSelector/ColorSelector";
+export { default as DuoInput } from "./src/DuoInput/DuoInput";
+export { default as FlexibleTable } from "./src/FlexibleTable/FlexibleTable";
+export { default as FontStyles } from "./src/FontStyles/FontStyles";
+export { default as NumberWithUnit } from "./src/NumberWithUnit/NumberWithUnit";
+export { default as QuatroInput } from "./src/QuatroInput/QuatroInput";
diff --git a/package-lock.json b/package-lock.json
index 13a50e2790f0e77a088257fbdd093ba6d74dd021..e42dea269b1e40102b94874da543f98b4d8ec01e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,7 +11,8 @@
 				"@wordpress/block-editor": "^14.13.0",
 				"@wordpress/components": "^29.4.0",
 				"@wordpress/i18n": "^5.18.0",
-				"react": "^18.3.1"
+				"react": "^18.3.1",
+				"react-beautiful-dnd": "^13.1.1"
 			}
 		},
 		"node_modules/@ariakit/core": {
@@ -892,6 +893,16 @@
 			"integrity": "sha512-9VZUA5omXBfn+hDxFjUDu1FOJTBM3LmvqfDey+Z6Aa8B8/JmF5SMj6FBrjfgJ/Q3YXOZd3qyTDfJyMZSs/wCUA==",
 			"license": "MIT"
 		},
+		"node_modules/@types/hoist-non-react-statics": {
+			"version": "3.3.6",
+			"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz",
+			"integrity": "sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==",
+			"license": "MIT",
+			"dependencies": {
+				"@types/react": "*",
+				"hoist-non-react-statics": "^3.3.0"
+			}
+		},
 		"node_modules/@types/mousetrap": {
 			"version": "1.6.15",
 			"resolved": "https://registry.npmjs.org/@types/mousetrap/-/mousetrap-1.6.15.tgz",
@@ -929,6 +940,27 @@
 				"@types/react": "^18.0.0"
 			}
 		},
+		"node_modules/@types/react-redux": {
+			"version": "7.1.34",
+			"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.34.tgz",
+			"integrity": "sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ==",
+			"license": "MIT",
+			"dependencies": {
+				"@types/hoist-non-react-statics": "^3.3.0",
+				"@types/react": "*",
+				"hoist-non-react-statics": "^3.3.0",
+				"redux": "^4.0.0"
+			}
+		},
+		"node_modules/@types/react-redux/node_modules/redux": {
+			"version": "4.2.1",
+			"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
+			"integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
+			"license": "MIT",
+			"dependencies": {
+				"@babel/runtime": "^7.9.2"
+			}
+		},
 		"node_modules/@use-gesture/core": {
 			"version": "10.3.1",
 			"resolved": "https://registry.npmjs.org/@use-gesture/core/-/core-10.3.1.tgz",
@@ -1946,6 +1978,15 @@
 				"node": ">=10"
 			}
 		},
+		"node_modules/css-box-model": {
+			"version": "1.2.1",
+			"resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz",
+			"integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==",
+			"license": "MIT",
+			"dependencies": {
+				"tiny-invariant": "^1.0.6"
+			}
+		},
 		"node_modules/csstype": {
 			"version": "3.1.3",
 			"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
@@ -2382,6 +2423,12 @@
 			"integrity": "sha512-yywVJy8ctVlN5lNPxsep5urnZ6TTclwPEyigM9M3Bi8vseJBOfqNrGWN/r8NzuIt3PovM323W04blJfGQfQSVg==",
 			"license": "MIT"
 		},
+		"node_modules/memoize-one": {
+			"version": "5.2.1",
+			"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
+			"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==",
+			"license": "MIT"
+		},
 		"node_modules/moment": {
 			"version": "2.30.1",
 			"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
@@ -2677,6 +2724,12 @@
 				"react-is": "^16.13.1"
 			}
 		},
+		"node_modules/raf-schd": {
+			"version": "4.0.3",
+			"resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz",
+			"integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==",
+			"license": "MIT"
+		},
 		"node_modules/re-resizable": {
 			"version": "6.11.0",
 			"resolved": "https://registry.npmjs.org/re-resizable/-/re-resizable-6.11.0.tgz",
@@ -2714,6 +2767,35 @@
 				"react-dom": "^0.14.0 || ^15.0.0 || ^16.0.0"
 			}
 		},
+		"node_modules/react-beautiful-dnd": {
+			"version": "13.1.1",
+			"resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz",
+			"integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==",
+			"deprecated": "react-beautiful-dnd is now deprecated. Context and options: https://github.com/atlassian/react-beautiful-dnd/issues/2672",
+			"license": "Apache-2.0",
+			"dependencies": {
+				"@babel/runtime": "^7.9.2",
+				"css-box-model": "^1.2.0",
+				"memoize-one": "^5.1.1",
+				"raf-schd": "^4.0.2",
+				"react-redux": "^7.2.0",
+				"redux": "^4.0.4",
+				"use-memo-one": "^1.1.1"
+			},
+			"peerDependencies": {
+				"react": "^16.8.5 || ^17.0.0 || ^18.0.0",
+				"react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0"
+			}
+		},
+		"node_modules/react-beautiful-dnd/node_modules/redux": {
+			"version": "4.2.1",
+			"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
+			"integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
+			"license": "MIT",
+			"dependencies": {
+				"@babel/runtime": "^7.9.2"
+			}
+		},
 		"node_modules/react-colorful": {
 			"version": "5.6.1",
 			"resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz",
@@ -2757,6 +2839,37 @@
 			"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
 			"license": "MIT"
 		},
+		"node_modules/react-redux": {
+			"version": "7.2.9",
+			"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz",
+			"integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==",
+			"license": "MIT",
+			"dependencies": {
+				"@babel/runtime": "^7.15.4",
+				"@types/react-redux": "^7.1.20",
+				"hoist-non-react-statics": "^3.3.2",
+				"loose-envify": "^1.4.0",
+				"prop-types": "^15.7.2",
+				"react-is": "^17.0.2"
+			},
+			"peerDependencies": {
+				"react": "^16.8.3 || ^17 || ^18"
+			},
+			"peerDependenciesMeta": {
+				"react-dom": {
+					"optional": true
+				},
+				"react-native": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/react-redux/node_modules/react-is": {
+			"version": "17.0.2",
+			"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
+			"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
+			"license": "MIT"
+		},
 		"node_modules/react-remove-scroll": {
 			"version": "2.6.3",
 			"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz",
@@ -3075,6 +3188,12 @@
 			"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
 			"license": "MIT"
 		},
+		"node_modules/tiny-invariant": {
+			"version": "1.3.3",
+			"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
+			"integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==",
+			"license": "MIT"
+		},
 		"node_modules/tslib": {
 			"version": "2.8.1",
 			"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
diff --git a/package.json b/package.json
index bb0dd5efebb77d292dc34690294010f00b91bf1b..677b5e5d7d362445c210dc426db142e9a56c5c5f 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
 		"@wordpress/block-editor": "^14.13.0",
 		"@wordpress/components": "^29.4.0",
 		"@wordpress/i18n": "^5.18.0",
-		"react": "^18.3.1"
+		"react": "^18.3.1",
+		"react-beautiful-dnd": "^13.1.1"
 	}
 }
diff --git a/src/AlignButtons/AlignButtons.jsx b/src/AlignButtons/AlignButtons.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..03bebeaeda1e2d79660d4b69195b6259439a3b95
--- /dev/null
+++ b/src/AlignButtons/AlignButtons.jsx
@@ -0,0 +1,35 @@
+import {Button} from "@wordpress/components";
+export default function AlignButtons ({label, onChange}) {
+
+
+	const handleChange =  (newAlignment) => {
+		if (onChange) {
+			onChange(newAlignment);
+		}
+	}
+
+	return (
+		<div className='fi-field-wrapper'>
+			<div className='fi-field-label-wrapper'>
+				<span className='fi-field-label'>{label}</span>
+			</div>
+			<div className='fi-field-buttons-wrapper fi-alignbuttons-wrapper'>
+				<Button
+					icon="editor-alignleft"
+					className="has-dashicons"
+					onClick={() => handleChange('left')}
+				/>
+				<Button
+					icon="editor-aligncenter"
+					className="has-dashicons"
+					onClick={() => handleChange('center')}
+				/>
+				<Button
+					icon="editor-alignright"
+					className="has-dashicons"
+					onClick={() => handleChange('right')}
+				/>
+			</div>
+		</div>
+	);
+}
diff --git a/src/BlockPlaceholders/BlockPlaceholders.jsx b/src/BlockPlaceholders/BlockPlaceholders.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..9728205e63f473d9b795268980daeb21dc7fff38
--- /dev/null
+++ b/src/BlockPlaceholders/BlockPlaceholders.jsx
@@ -0,0 +1,16 @@
+import {__} from "@wordpress/i18n";
+import {PanelBody} from "@wordpress/components";
+import Placeholder from "./Placeholder";
+
+export default function BlockPlaceholders({placeholders, children}) {
+	return (
+		<PanelBody title={__('Placeholders', 'flexible-invoices-core')}>
+			{children && <p className='fi-placeholders-list-description'>{children}</p>}
+			{
+				placeholders.map((placeholder) => {
+					return <Placeholder label={placeholder.label}>{placeholder.description}</Placeholder>
+				})
+			}
+		</PanelBody>
+	);
+}
diff --git a/src/BlockPlaceholders/Placeholder.jsx b/src/BlockPlaceholders/Placeholder.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..0062dd5ac426e69b7436ea4627c81408d3b3f835
--- /dev/null
+++ b/src/BlockPlaceholders/Placeholder.jsx
@@ -0,0 +1,9 @@
+export default function Placeholder({label, children}) {
+	return (
+		<div>
+			<input type='text' disabled value={label}/>
+			<p className='fi-placeholders-list-description'>{children}</p>
+			<hr/>
+		</div>
+	);
+}
diff --git a/src/ColorSelector/ColorSelector.jsx b/src/ColorSelector/ColorSelector.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..18452f03e603ca83420eee64e54dc788868f8822
--- /dev/null
+++ b/src/ColorSelector/ColorSelector.jsx
@@ -0,0 +1,58 @@
+import {ColorPicker} from "@wordpress/components";
+import {useState} from "react";
+
+export default function ColorSelector({label, onChange, value, enableAlpha = true, returnFormat = 'rgb'}) {
+
+	const [isPopupActive, setIsPopupActive] = useState(false);
+
+	const handleColorChange = function (newColor) {
+		let color = newColor;
+		if (returnFormat === 'hex') {
+			color = newColor.hex;
+		} else if (returnFormat === 'hsv') {
+			color = newColor.hsv;
+		} else if (returnFormat === 'hsl') {
+			color = newColor.hsl;
+		} else if (returnFormat === 'rgb') {
+			if (enableAlpha === true) {
+				color = `rgba(${newColor.rgb.r}, ${newColor.rgb.g}, ${newColor.rgb.b}, ${newColor.rgb.a})`;
+			} else {
+				color = `rgb(${newColor.rgb.r}, ${newColor.rgb.g}, ${newColor.rgb.b})`;
+			}
+		}
+
+
+		onChange(color);
+	}
+
+	return (
+		<div className='fi-field-wrapper'>
+			<div className='fi-field-label-wrapper'>
+				<span className='fi-field-label'>{label}</span>
+			</div>
+			<div className='fi-field-buttons-wrapper fi-colorpicker-wrapper fi-input-with-columns' style={{
+				width: '216px', //Width of the ColorPicker element
+				border: '1px solid #8c8f94',
+				borderRadius: '0px',
+			}}>
+				<div className='fi-color-preview' style={{
+					background: value,
+					height: '32px',
+					width: '100%'
+				}}
+					 onClick={() => {
+						 setIsPopupActive((isPopupActive) => !isPopupActive)
+					 }}
+				></div>
+			</div>
+			{isPopupActive &&
+				<div className='fi-field-buttons-wrapper fi-colorpicker-wrapper'>
+					<ColorPicker
+						enableAlpha={enableAlpha}
+						color={value}
+						onChangeComplete={handleColorChange}
+					/>
+				</div>}
+		</div>
+	);
+}
diff --git a/src/DuoInput/DuoInput.jsx b/src/DuoInput/DuoInput.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..81b6e0eb7ba66aa39e7632633516a2d6b85c34a3
--- /dev/null
+++ b/src/DuoInput/DuoInput.jsx
@@ -0,0 +1,38 @@
+import NumberWithUnit from "../NumberWithUnit/NumberWithUnit";
+
+export default function DuoInput({label, onChange, values, layout = 'column'}) {
+
+	const keys = Object.keys(values);
+	const valuesArray = Object.values(values);
+	const handleChange = (side, value) => {
+		const changedSide = keys[side];
+		const newValues = {...values, [changedSide]: value};
+
+		if (onChange) {
+			onChange(newValues);
+		}
+	};
+	return (
+		<div className='fi-field-wrapper'>
+			<div className='fi-field-label-wrapper'>
+				<span className='fi-field-label'>{label}</span>
+			</div>
+			<div className='fi-field-buttons-wrapper fi-duo-fields-wrapper'>
+				<div className='fi-duo-fields' style={{ display: 'flex', flexDirection: layout}}>
+					<NumberWithUnit
+						className='fi-duo-field fi-duo-field-input'
+						value={valuesArray[0]}
+						onChange={(e) => {
+							handleChange(0, e)
+						}}
+					/>
+					<NumberWithUnit
+						className='fi-duo-field fi-duo-field-input'
+						value={valuesArray[1]}
+						onChange={(e) => handleChange(1, e)}
+					/>
+				</div>
+			</div>
+		</div>
+	);
+}
diff --git a/src/FlexibleTable/FlexibleTable.jsx b/src/FlexibleTable/FlexibleTable.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..c9ad42965bb17fdcb58c4b3d3cff1089229f837f
--- /dev/null
+++ b/src/FlexibleTable/FlexibleTable.jsx
@@ -0,0 +1,415 @@
+import {__} from '@wordpress/i18n';
+import {InspectorControls, useBlockProps,} from '@wordpress/block-editor';
+import {PanelBody, ToggleControl} from '@wordpress/components';
+import {DragDropContext, Draggable, Droppable} from "react-beautiful-dnd";
+import {DuoInput, NumberWithUnit, ColorSelector, FontStyles, AlignButtons, BlockPlaceholders} from "../../index";
+import TableBody from "./TableBody";
+import TableHead from "./TableHead";
+
+export default function FlexibleTable({
+										  attributes,
+										  setAttributes,
+										  placeholders,
+										  additionalOptions,
+										  tableHeader,
+										  tableBody,
+										  tableFooter,
+									  }) {
+	const {
+		headers,
+		rows,
+		states,
+
+		headerBackground,
+		headerTextColor,
+		headerTextAlign,
+		headerFontWeight,
+		headerFontStyle,
+		headerTextDecoration,
+		headerFontSize,
+
+		tableBorderColor,
+		tableBorderWidth,
+
+		bodyBorderColumnColor,
+		bodyBorderColumnWidthLeft,
+		bodyBorderColumnWidthRight,
+		bodyBorderRowColor,
+		bodyBorderRowWidthTop,
+		bodyBorderRowWidthBottom,
+
+		headerBorderColumnColor,
+		headerBorderColumnWidthLeft,
+		headerBorderColumnWidthRight,
+		headerBorderRowColor,
+		headerBorderRowWidthTop,
+		headerBorderRowWidthBottom,
+
+		bodyBackground,
+		multipleBodyBackground,
+		bodyBackgroundEven,
+		bodyTextColorEven,
+		bodyTextColor,
+		bodyTextAlign,
+		bodyFontWeight,
+		bodyFontStyle,
+		bodyTextDecoration,
+		bodyFontSize,
+	} = 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={__('Table border color', 'flexible-invoices-core')}
+						value={tableBorderColor}
+						enableAlpha={false}
+						returnFormat={'hex'}
+						onChange={(value) => setAttributes({tableBorderColor: value})}
+					/>
+
+					<NumberWithUnit
+						label={__('Table border width', 'flexible-invoices-core')}
+						value={tableBorderWidth}
+						onChange={(value) => setAttributes({tableBorderWidth: value})}
+					/>
+
+					<ColorSelector
+						label={__('Border row color', 'flexible-invoices-core')}
+						value={headerBorderRowColor}
+						enableAlpha={false}
+						returnFormat={'hex'}
+						onChange={(value) => setAttributes({headerBorderRowColor: value})}
+					/>
+
+					<DuoInput
+						label={__("Border row width", 'flexible-invoices-core')}
+						values={
+							{
+								headerBorderRowWidthTop,
+								headerBorderRowWidthBottom,
+							}
+						}
+						onChange={handleMultipleAttributesChange}
+					/>
+					<ColorSelector
+						label={__('Border cell color', 'flexible-invoices-core')}
+						value={headerBorderColumnColor}
+						enableAlpha={false}
+						returnFormat={'hex'}
+						onChange={(value) => setAttributes({headerBorderColumnColor: value})}
+					/>
+					<DuoInput
+						label={__("Border cell width", 'flexible-invoices-core')}
+						values={
+							{
+								headerBorderColumnWidthLeft,
+								headerBorderColumnWidthRight,
+							}
+						}
+						layout={'row'}
+						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 (even rows)', 'flexible-invoices-core')}
+								value={bodyBackgroundEven}
+								onChange={(value) => setAttributes({bodyBackgroundEven: value})}
+							/>
+							<ColorSelector
+								label={__('Text color (even rows)', 'flexible-invoices-core')}
+								value={bodyTextColorEven}
+								enableAlpha={false}
+								onChange={(value) => setAttributes({bodyTextColorEven: 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}
+						returnFormat={'hex'}
+						onChange={(value) => setAttributes({bodyBorderRowColor: value})}
+					/>
+					<DuoInput
+						label={__("Border row width", 'flexible-invoices-core')}
+						values={
+							{
+								bodyBorderRowWidthTop,
+								bodyBorderRowWidthBottom,
+							}
+						}
+						onChange={handleMultipleAttributesChange}
+					/>
+					<ColorSelector
+						label={__('Border cell color', 'flexible-invoices-core')}
+						value={bodyBorderColumnColor}
+						enableAlpha={false}
+						returnFormat={'hex'}
+						onChange={(value) => setAttributes({bodyBorderColumnColor: value})}
+					/>
+					<DuoInput
+						label={__("Border cell width", 'flexible-invoices-core')}
+						values={
+							{
+								bodyBorderColumnWidthRight,
+								bodyBorderColumnWidthLeft,
+							}
+						}
+						layout={'row'}
+						onChange={handleMultipleAttributesChange}
+					/>
+				</PanelBody>
+				{additionalOptions}
+				{placeholders && <BlockPlaceholders
+					placeholders={placeholders}
+				/>}
+			</InspectorControls>
+			<div {...blockProps}>
+				<table className="fitb-item-table has-background" style={{
+					borderStyle: "solid",
+					borderColor: tableBorderColor,
+					borderWidth: tableBorderWidth,
+					borderCollapse: 'collapse'
+				}}>
+					{tableHeader ? tableHeader :
+						<TableHead
+							headers={headers}
+							updateHeader={updateHeader}
+							tableStyles={{
+								headerBackground,
+								headerTextColor,
+								headerTextAlign,
+								headerFontStyle,
+								headerTextDecoration,
+								headerFontSize,
+								headerFontWeight,
+
+								headerBorderColumnColor,
+								headerBorderColumnWidthLeft,
+								headerBorderColumnWidthRight,
+								headerBorderRowColor,
+								headerBorderRowWidthTop,
+								headerBorderRowWidthBottom
+							}}
+							states={states}
+						/>
+					}
+					{
+						tableBody ? tableBody :
+							<TableBody
+								rows={rows}
+								states={states}
+								updateCell={updateCell}
+								tableStyles={
+									{
+										bodyBackground,
+										bodyBackgroundEven,
+										bodyTextColor,
+										bodyTextColorEven,
+										bodyTextDecoration,
+										bodyTextAlign,
+										bodyFontStyle,
+										bodyFontSize,
+										bodyFontWeight,
+
+										bodyBorderColumnColor,
+										bodyBorderColumnWidthLeft,
+										bodyBorderColumnWidthRight,
+										bodyBorderRowColor,
+										bodyBorderRowWidthTop,
+										bodyBorderRowWidthBottom,
+
+										multipleBodyBackground
+									}
+								}
+							/>
+					}
+					{tableFooter &&
+						<tfoot>
+						{tableFooter}
+						</tfoot>
+					}
+				</table>
+			</div>
+		</>
+	);
+}
diff --git a/src/FlexibleTable/TableBody.jsx b/src/FlexibleTable/TableBody.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..24f0a66405472f3f84b9c5eba62dc813e584f172
--- /dev/null
+++ b/src/FlexibleTable/TableBody.jsx
@@ -0,0 +1,69 @@
+import {RichText} from "@wordpress/block-editor";
+
+
+export default function TableBody({tableStyles, updateCell, rows, states}) {
+
+	const {
+		bodyBackground,
+		bodyBackgroundEven,
+		bodyTextColor,
+		bodyTextColorEven,
+		bodyTextDecoration,
+		bodyTextAlign,
+		bodyFontStyle,
+		bodyFontSize,
+		bodyFontWeight,
+
+		bodyBorderColumnColor,
+		bodyBorderColumnWidthLeft,
+		bodyBorderColumnWidthRight,
+		bodyBorderRowColor,
+		bodyBorderRowWidthTop,
+		bodyBorderRowWidthBottom,
+
+		multipleBodyBackground
+	} = tableStyles;
+
+	return (
+		<tbody className={"fitb-item-table-body"}>
+
+		{Array.from({length: 2}).map((_, trIndex) => (
+			<tr className={"fitb-item-table-row"} style={{
+				background: (multipleBodyBackground && trIndex === 1) ? bodyBackgroundEven : bodyBackground,
+				borderStyle: "solid",
+				borderColor: bodyBorderRowColor,
+				borderTopWidth: bodyBorderRowWidthTop,
+				borderBottomWidth: bodyBorderRowWidthBottom,
+			}}>
+				{rows.map((row, index) => (
+					states[index] ?
+						<td className={"fitb-item-table-cell"} key={index}
+							style={{
+								borderStyle: "solid",
+								borderColor: bodyBorderColumnColor,
+								borderLeftWidth: bodyBorderColumnWidthLeft,
+								borderRightWidth: bodyBorderColumnWidthRight,
+							}}>
+							<RichText
+								tagName="div"
+								key={index}
+								value={row}
+								style={{
+									color: (multipleBodyBackground && trIndex === 1) ? bodyTextColorEven : bodyTextColor,
+									textAlign: bodyTextAlign,
+									fontStyle: bodyFontStyle,
+									fontSize: bodyFontSize,
+									textDecoration: bodyTextDecoration,
+									fontWeight: bodyFontWeight,
+								}}
+								onChange={(value) =>
+									updateCell(index, value)
+								}
+							/>
+						</td> : ''
+				))}
+			</tr>
+		))}
+		</tbody>
+	);
+}
diff --git a/src/FlexibleTable/TableHead.jsx b/src/FlexibleTable/TableHead.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..1b07ee2bb81a1295270960230c3d981bac835e39
--- /dev/null
+++ b/src/FlexibleTable/TableHead.jsx
@@ -0,0 +1,58 @@
+import {RichText} from "@wordpress/block-editor";
+
+export default function TableHead( {headers, updateHeader, tableStyles, states} ) {
+	const {
+		headerBackground,
+		headerTextColor,
+		headerTextAlign,
+		headerFontStyle,
+		headerTextDecoration,
+		headerFontSize,
+		headerFontWeight,
+
+		headerBorderColumnColor,
+		headerBorderColumnWidthLeft,
+		headerBorderColumnWidthRight,
+		headerBorderRowColor,
+		headerBorderRowWidthTop,
+		headerBorderRowWidthBottom,
+	} = tableStyles;
+
+	return (
+		<thead className={"fitb-item-table-header"} style={{
+			borderStyle: "solid",
+			borderColor: headerBorderRowColor,
+			borderTopWidth: headerBorderRowWidthTop,
+			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: headerBorderColumnColor,
+							borderLeftWidth: headerBorderColumnWidthLeft,
+							borderRightWidth: headerBorderColumnWidthRight,
+						}}>
+						<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>);
+}
diff --git a/src/FontStyles/FontStyles.jsx b/src/FontStyles/FontStyles.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..897f720d7115d71bcc5b6230c60b00538304593b
--- /dev/null
+++ b/src/FontStyles/FontStyles.jsx
@@ -0,0 +1,97 @@
+import {Button} from "@wordpress/components";
+import {useState} from "react";
+
+export default function  FontStyles({label, onChange, values} ) {
+
+	const [isItalic, setIsItalic] = useState(values.fontStyle === 'italic');
+	const [isBold, setIsBold] = useState(values.fontWeight === 'bold');
+	const [isUnderline, setIsUnderline] = useState(values.textDecoration.includes('underline'));
+	const [isLineThrough, setIsLineThrough] = useState(values.textDecoration.includes('line-through'));
+
+	const fontStyle = isItalic ? 'italic' : 'normal';
+	const fontWeight = isBold ? 'bold' : 'normal';
+	const textDecoration = isUnderline ? 'underline' : isLineThrough ? 'line-through' : 'none';
+
+	const handleChange = function (updatedValues) {
+		const newStyles = {
+			fontStyle: updatedValues.fontStyle || fontStyle,
+			fontWeight: updatedValues.fontWeight || fontWeight,
+			textDecoration: (updatedValues.textDecoration === '' ? 'none' : updatedValues.textDecoration)  || textDecoration
+		};
+		setIsItalic( newStyles.fontStyle === 'italic');
+		setIsBold( newStyles.fontWeight === 'bold');
+		setIsUnderline( newStyles.textDecoration.includes('underline'));
+		setIsLineThrough( newStyles.textDecoration.includes('line-through'));
+
+		if (onChange) {
+			onChange(newStyles);
+		}
+	};
+
+
+	const handleButtonPress = function (styleToChange) {
+		switch (styleToChange) {
+			case 'bold':
+				setIsBold(prev => {
+					const newValue = !prev;
+					handleChange({fontWeight: newValue ? 'bold' : 'normal'});
+					return newValue;
+				});
+				break;
+			case 'italic':
+				setIsItalic(prev => {
+					const newValue = !prev;
+					handleChange({fontStyle: newValue ? 'italic' : 'normal'});
+					return newValue;
+				});
+				break;
+			case 'underline':
+				setIsUnderline(prev => {
+					const newValue = !prev;
+					handleChange({textDecoration: (newValue ? 'underline ' : '') + (isLineThrough ? 'line-through' : '')});
+					return newValue;
+				});
+				break;
+			case 'line-through':
+				setIsLineThrough(prev => {
+					const newValue = !prev;
+					handleChange({textDecoration: (newValue ? 'line-through ' : '') + (isUnderline ? 'underline' : '')});
+					return newValue;
+				});
+				break;
+			default:
+				break;
+		}
+	};
+
+
+	return (
+		<div className='fi-field-wrapper'>
+			<div className='fi-field-label-wrapper'>
+				<span className='fi-field-label'>{label}</span>
+			</div>
+			<div className='fi-field-buttons-wrapper fi-fontstylingbuttons-wrapper'>
+				<Button
+					icon="editor-italic"
+					className={"has-dashicons" + (isItalic ? ' fi-btn-active' : '')}
+					onClick={() => handleButtonPress('italic')}
+				/>
+				<Button
+					icon="editor-bold"
+					className={"has-dashicons" + (isBold ? ' fi-btn-active' : '')}
+					onClick={() => handleButtonPress('bold')}
+				/>
+				<Button
+					icon="editor-strikethrough"
+					className={"has-dashicons" + (isLineThrough ? ' fi-btn-active' : '')}
+					onClick={() => handleButtonPress('line-through')}
+				/>
+				<Button
+					icon="editor-underline"
+					className={"has-dashicons" + (isUnderline ? ' fi-btn-active' : '')}
+					onClick={() => handleButtonPress('underline')}
+				/>
+			</div>
+		</div>
+	);
+}
diff --git a/src/NumberWithUnit/NumberWithUnit.jsx b/src/NumberWithUnit/NumberWithUnit.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..b4853afdd19f431804f6c3d4f863756b50d292a4
--- /dev/null
+++ b/src/NumberWithUnit/NumberWithUnit.jsx
@@ -0,0 +1,69 @@
+import {SelectControl, TextControl} from "@wordpress/components";
+import {useState} from "react";
+
+export default function NumberWithUnit({label, onChange, value, className}) {
+
+	const splitValues = function (fontSize) {
+
+		if( !fontSize ) {
+			return {size: "0", unit: "px"};
+		}
+
+		const match = fontSize.match(/^(\d+)([a-z%]+)$/i);
+
+		if (!match) {
+			return {size: "16", unit: "px"};
+		}
+		return {
+			size: match[1],
+			unit: match[2]
+		};
+	}
+
+	const [unit, setUnit] = useState(splitValues(value).unit);
+	const [size, setSize] = useState(splitValues(value).size);
+
+
+
+	const handleChange = (newSize, newUnit) => {
+		if (onChange) {
+			onChange(newSize + newUnit);
+		}
+	};
+
+
+	return (
+		<div className='fi-field-wrapper'>
+			<div className='fi-field-label-wrapper'>
+				<span className='fi-field-label'>{label}</span>
+			</div>
+			<div className={'fi-field-buttons-wrapper fi-input-with-columns fi-numberwithfields-wrapper' + ' ' + className}>
+				<TextControl
+					style={{flex: 3}}
+					type={'number'}
+					placeholder={'16'}
+					value={size}
+					onChange={(value) => {
+						setSize(value);
+						handleChange(value, unit);
+					}}
+				/>
+				<SelectControl
+					options={[
+						{label: 'px', value: 'px'},
+						{label: '%', value: '%'},
+						{label: 'em', value: 'em'},
+						{label: 'pt', value: 'pt'},
+					]}
+					style={{minWidth:'56px'}}
+					value={unit}
+					onChange={(value) => {
+						setUnit(value);
+						handleChange(size, value);
+					}}
+
+				/>
+			</div>
+		</div>
+	);
+}
diff --git a/src/QuatroInput/QuatroInput.jsx b/src/QuatroInput/QuatroInput.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..15e2795acd6b66bcb41b48a8bef817f6b842cb0e
--- /dev/null
+++ b/src/QuatroInput/QuatroInput.jsx
@@ -0,0 +1,82 @@
+import NumberWithUnit from "../NumberWithUnit/NumberWithUnit";
+
+export default function QuatroInput({label, onChange, values, layout = 'cross'}) {
+
+	const keys = Object.keys(values);
+	const valuesArray = Object.values(values);
+	const handleChange = (side, value) => {
+		const changedSide = keys[side];
+		const newValues = {...values, [changedSide]: value};
+
+		if (onChange) {
+			onChange(newValues);
+		}
+	};
+	return (
+		<div className='fi-field-wrapper'>
+			<div className='fi-field-label-wrapper'>
+				<span className='fi-field-label'>{label}</span>
+			</div>
+			{layout === 'cross' &&
+				<div className='fi-field-buttons-wrapper fi-quatro-fields-wrapper'>
+					<div className='fi-quatro-fields'>
+						<NumberWithUnit
+							className='fi-quatro-field fi-quatro-field-input'
+							value={valuesArray[0]}
+							onChange={(e) => {
+								handleChange(0, e)
+							}}
+						/>
+					</div>
+					<div className='fi-quatro-fields fields-mid'>
+						<NumberWithUnit
+							className='fi-quatro-field fi-quatro-field-input'
+							value={valuesArray[1]}
+							onChange={(e) => handleChange(1, e)}
+						/>
+						<NumberWithUnit
+							className='fi-quatro-field fi-quatro-field-input'
+							value={valuesArray[2]}
+							onChange={(e) => handleChange(2, e)}
+						/>
+					</div>
+					<div className='fi-quatro-fields'>
+						<NumberWithUnit
+							className='fi-quatro-field fi-quatro-field-input'
+							value={valuesArray[3]}
+							onChange={(e) => handleChange(3, e)}
+						/>
+					</div>
+				</div>}
+			{layout === 'box' &&
+				<div className='fi-field-buttons-wrapper fi-quatro-fields-wrapper'>
+					<div className='fi-quatro-fields'>
+						<NumberWithUnit
+							className='fi-quatro-field fi-quatro-field-input'
+							value={valuesArray[0]}
+							onChange={(e) => {
+								handleChange(0, e)
+							}}
+						/>
+						<NumberWithUnit
+							className='fi-quatro-field fi-quatro-field-input'
+							value={valuesArray[1]}
+							onChange={(e) => handleChange(1, e)}
+						/>
+					</div>
+					<div className='fi-quatro-fields fields-mid'>
+						<NumberWithUnit
+							className='fi-quatro-field fi-quatro-field-input'
+							value={valuesArray[2]}
+							onChange={(e) => handleChange(2, e)}
+						/>
+						<NumberWithUnit
+							className='fi-quatro-field fi-quatro-field-input'
+							value={valuesArray[3]}
+							onChange={(e) => handleChange(3, e)}
+						/>
+					</div>
+				</div>}
+		</div>
+	);
+}