diff --git a/blocks/all.php b/blocks/all.php index 98b4093..23facba 100644 --- a/blocks/all.php +++ b/blocks/all.php @@ -49,3 +49,4 @@ function ( array $categories ) { require_once plugin_dir_path( __FILE__ ) . 'post-listing/class-post-listing-block.php'; require_once plugin_dir_path( __FILE__ ) . 'search-and-filter/class-search-and-filter-block.php'; require_once plugin_dir_path( __FILE__ ) . 'tabs/class-tabs-block.php'; +require_once plugin_dir_path( __FILE__ ) . 'table/class-table-block.php'; diff --git a/blocks/table/assets/_table.scss b/blocks/table/assets/_table.scss new file mode 100644 index 0000000..5832acb --- /dev/null +++ b/blocks/table/assets/_table.scss @@ -0,0 +1,154 @@ +@use '/scss/globals'; +@use '/scss/extenders/container'; +@use '/scss/mixins/integrated-buttons'; + +@mixin render { + .table__outer-wrapper, + .wp-block-acf-table { + background-color: white; + color: globals.$color-a; + + & * { + color: inherit; + } + } + + .table__outer-wrapper { + @extend %container__outer-wrapper; + } + + .table__wrapper { + @extend %container__wrapper; + padding-top: calc(globals.$space-vertical * 1.6875); + padding-bottom: calc(globals.$space-vertical * 2.65625); + } + + .table__inner { + @extend %container__inner; + } + + .table__sections { + display: grid; + gap: globals.$space-vertical globals.$space-horizontal; + grid-template-columns: 1fr; + } + + .table__outer-wrapper .table__section--device-visibility-desktop-only { + display: none; + + @media only screen and (min-width: globals.$breakpoint-large) { + display: block; + } + } + + .table__outer-wrapper .table__section--device-visibility-mobile-only { + @media only screen and (min-width: globals.$breakpoint-large) { + display: none; + } + } + + .table__additional-content { + margin-bottom: calc(globals.$space-bottom * -1); + + .wp-block-heading, + p { + max-width: 970px; + + &:not(.has-text-align-right, .has-text-align-left) { + margin-left: auto; + margin-right: auto; + text-align: center; + } + + &.has-text-align-right { + margin-left: auto; + } + } + + @include integrated-buttons.render; + + .wp-block-buttons-is-layout-flex { + justify-content: center; + } + } + + .table__table.block-editor-block-list__layout { + display: table; + + .wp-block-acf-table-table-row { + display: table-row-group; + } + + .table__table-row { + display: table-row; + } + + .wp-block-acf-table-table-row-cell { + display: table-cell; + vertical-align: top; + } + } + + .table__section--table { + overflow: auto; + } + + .table__table-outer-wrapper { + width: max-content; + min-width: 100%; + overflow: hidden; + } + + .table__table-wrapper { + margin: 0 -4px; + + @media only screen and (min-width: globals.$breakpoint-medium) { + margin: 0 -8px; + } + } + + .table__table { + min-width: 100%; + border-collapse: collapse; + } + + .table__table-cell { + padding: 0 4px; + vertical-align: top; + + @media only screen and (min-width: globals.$breakpoint-medium) { + padding: 0 8px; + } + } + + .table__table-row { + .table__table-cell { + &:first-child { + .table__table-cell-content { + justify-content: flex-start; + } + } + } + } + + .table__table-row--has-bottom-space .table__table-cell { + padding-bottom: 5px; + } + + .table__table-cell-content-outer, + .wp-block-acf-table-table-row-cell-cell-content { + width: min-content; + min-width: 100%; + } + + .table__table-cell-content { + display: flex; + } + + .table__table-cell-content-inner { + p { + margin-bottom: 0; + font-size: 1.5rem; + } + } +} diff --git a/blocks/table/assets/match-table-height.js b/blocks/table/assets/match-table-height.js new file mode 100644 index 0000000..8dd1b3b --- /dev/null +++ b/blocks/table/assets/match-table-height.js @@ -0,0 +1,31 @@ +(function() { + 'use strict'; + + const selectors = [ + '.table__table-cell-content' + ]; + + // Function to apply matchHeight to all elements matching selectors + function applyMatchHeight() { + const elements = jQuery(selectors.join(', ')); + + // Remove existing matchHeight to prevent duplication + elements.matchHeight({ remove: true }); + // Apply matchHeight to all matching elements + elements.matchHeight(); + } + + jQuery(document).ready( + () => { + applyMatchHeight(); + + const observer = new MutationObserver( + () => { + applyMatchHeight(); + } + ); + + observer.observe(document.body, {childList: true, subtree: true}); + } + ); +})(); diff --git a/blocks/table/class-table-block.php b/blocks/table/class-table-block.php new file mode 100644 index 0000000..2648948 --- /dev/null +++ b/blocks/table/class-table-block.php @@ -0,0 +1,203 @@ +check_js_dependencies(); + }, + 20 + ); + + return true; + } + + /** + * {@inheritdoc} + */ + protected function fields(): array { + return array( + array( + 'key' => 'field_table_id', + 'label' => 'ID', + 'name' => 'id', + 'type' => 'text', + ), + ); + } + + /** + * {@inheritdoc} + */ + protected function child_blocks(): array { + return array( + new Child_Block( + 'additional-content', + 'Additional Content', + array(), + __DIR__ . '/templates/additional-content.php', + array(), + 'text' + ), + new Child_Block( + 'table', + 'Table', + array( + array( + 'key' => 'field_table_device_visibility', + 'label' => 'Device Visibility', + 'name' => 'device_visibility', + 'type' => 'select', + 'instructions' => 'Please choose which devices the table should be visible on.', + 'choices' => array( + 'all' => 'All', + 'desktop-only' => 'Desktop Only', + 'mobile-only' => 'Mobile Only', + ), + ), + ), + __DIR__ . '/templates/table.php', + array( + new Child_Block( + 'row', + 'Table Row', + array( + array( + 'key' => 'field_table_row_has_bottom_space', + 'label' => 'Bottom Space', + 'name' => 'has_bottom_space', + 'type' => 'true_false', + 'message' => 'Has bottom space?', + 'default_value' => true, + ), + ), + __DIR__ . '/templates/row.php', + array( + new Child_Block( + 'cell', + 'Table Cell', + array( + array( + 'key' => 'field_table_cell_colspan', + 'label' => 'Colspan', + 'name' => 'colspan', + 'type' => 'number', + 'instructions' => 'The number of columns the cell should span. This will not be reflected in the editor.', + 'default_value' => 1, + ), + ), + __DIR__ . '/templates/cell.php', + array( + new Child_Block( + 'cell-content', + 'Table Cell Content', + array(), + __DIR__ . '/templates/cell-content.php', + array(), + 'text', + array( + 'mode' => false, + 'color' => array( + 'text' => true, + 'background' => true, + ), + ), + ), + ), + 'table-col-after' + ), + ), + 'table-row-after' + ), + ), + 'editor-table' + ), + ); + } + + /** + * {@inheritdoc} + */ + protected function template(): string { + return __DIR__ . '/templates/block.php'; + } + + /** + * {@inheritdoc} + */ + protected function supports(): array { + return array( + 'mode' => false, + 'color' => array( + 'text' => true, + 'background' => true, + ), + ); + } + + /** + * {@inheritdoc + */ + protected function scripts(): array { + return array( + new Script( 'match-table-height', plugin_dir_url( __FILE__ ) . 'assets/match-table-height.js', array( 'match-height' ), '1' ), + ); + } + + /** + * Checks if the js dependencies are working correctly. + * + * @throws \Exception If dependencies are not met. + * + * @return void + */ + protected function check_js_dependencies() { + // Check if we have match heights script. + if ( ! wp_script_is( 'match-height', 'registered' ) ) { + throw new \Exception( 'Please ensure that the match heights script has been registered. You can find an example of how to add this to existing projects inside the theme package.' ); + } + } +} diff --git a/blocks/table/templates/additional-content.php b/blocks/table/templates/additional-content.php new file mode 100644 index 0000000..81c84c6 --- /dev/null +++ b/blocks/table/templates/additional-content.php @@ -0,0 +1,21 @@ + + +