diff --git a/blocks/all.php b/blocks/all.php index 9f3aa9e..98b4093 100644 --- a/blocks/all.php +++ b/blocks/all.php @@ -48,3 +48,4 @@ function ( array $categories ) { require_once plugin_dir_path( __FILE__ ) . 'mobile-menu/class-mobile-menu-block.php'; 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'; diff --git a/blocks/tabs/assets/_tabs.scss b/blocks/tabs/assets/_tabs.scss new file mode 100644 index 0000000..565096d --- /dev/null +++ b/blocks/tabs/assets/_tabs.scss @@ -0,0 +1,47 @@ +@use '/scss/globals'; +@use '/scss/extenders/container'; + +@mixin render { + .tabs__outer-wrapper { + @extend %container__outer-wrapper; + } + + .tabs__wrapper { + @extend %container__wrapper; + } + + .tabs__wrapper--reduce-bottom-space { + @extend %container__wrapper--reduce-bottom-space; + } + + .tabs__inner { + @extend %container__inner; + } + + .tabs__tabs { + display: flex; + } + + .tabs__tab-outer-wrapper, + .wp-block-acf-tabs-tab { + background-color: lightgray; + } + + .tabs__tab { + padding: globals.$space-top globals.$space-right 0 globals.$space-left; + background-color: transparent; + border: none; + cursor: pointer; + } + + .tabs__tab--active { + background-color: gray; + } + + .tabs__pattern { + &[hidden], + &[aria-hidden="true"] { + display: none; + } + } +} \ No newline at end of file diff --git a/blocks/tabs/assets/admin.js b/blocks/tabs/assets/admin.js new file mode 100644 index 0000000..1c69188 --- /dev/null +++ b/blocks/tabs/assets/admin.js @@ -0,0 +1,69 @@ +class Tabs extends AdminBlock { + + setup() { + this.setActiveTab(parseInt(this.getAttribute('active_tab'))); + this.setEventListeners(); + } + + setEventListeners() { + this.blockDiv.on( + 'click', + '.tabs__tab', + (event) => { + const index = this.blockDiv.find('.tabs__tab').index(event.currentTarget); + + this.capturePatterns(); + this.setActiveTab(index); + } + ); + + this.addListener( + (path, originalValue, newValue) => { + // Check if path matches pattern: innerBlocks[n].attributes.data.field_tabs_block_pattern + const regex = /^innerBlocks\[\d+\]\.attributes\.data\.field_tabs_block_pattern$/; + if (!regex.test(path)) { + return; + } + + this.capturePatterns(); + } + ); + } + + setActiveTab(index) { + this.blockDiv.find('.tabs__tab').removeClass('tabs__tab--active'); + this.blockDiv.find('.tabs__tab').eq(index).addClass('tabs__tab--active'); + this.setAttribute('active_tab', index); + } + + capturePatterns() { + this.loadBlock(); + + let patterns = []; + + for (const i in this.block.innerBlocks) { + patterns[i] = ''; + if (typeof this.block.innerBlocks[i].attributes == 'undefined') { + continue; + } + if (typeof this.block.innerBlocks[i].attributes.data == 'undefined') { + continue; + } + if (typeof this.block.innerBlocks[i].attributes.data.field_tabs_block_pattern !== 'undefined') { + patterns[i] = this.block.innerBlocks[i].attributes.data.field_tabs_block_pattern; + } + if (typeof this.block.innerBlocks[i].attributes.data.pattern !== 'undefined') { + patterns[i] = this.block.innerBlocks[i].attributes.data.pattern; + } + } + + this.setAttribute('patterns', patterns.join(',')); + } +} + +new AdminBlockInitializer( + '.wp-block-acf-tabs', + (blockDiv) => { + window.mytest = new Tabs(blockDiv); + } +); diff --git a/blocks/tabs/assets/tabs.js b/blocks/tabs/assets/tabs.js new file mode 100644 index 0000000..5342ad3 --- /dev/null +++ b/blocks/tabs/assets/tabs.js @@ -0,0 +1,57 @@ +class Tabs { + + elements = {}; + + constructor(wrapper) { + this.loadElements(wrapper); + this.setTabActiveState(); + this.addEventListeners(); + } + + loadElements(wrapper) { + this.elements.wrapper = wrapper; + this.elements.tab = wrapper.find('.tabs__tab'); + this.elements.pattern = wrapper.next().find('.tabs__pattern'); + } + + setTabActiveState() { + this.elements.tab.removeClass('tabs__tab--active'); + this.elements.pattern.prop('hidden', true); + this.elements.pattern.attr('aria-hidden', true); + + const index = this.elements.wrapper.data('active-tab'); + const tab = this.elements.tab.eq(index); + const pattern = this.elements.pattern.eq(index); + + tab.addClass('tabs__tab--active'); + pattern.prop('hidden', false); + pattern.attr('aria-hidden', false); + } + + addEventListeners() { + this.elements.tab.on( + 'click', + () => { + const index = this.elements.tab.index(event.currentTarget); + this.setActiveTab(index); + this.setTabActiveState(); + } + ); + } + + setActiveTab(index) { + this.elements.wrapper.data('active-tab', index); + } +} + +jQuery(document).ready( + () => { + const wrappers = jQuery('.tabs__wrapper'); + + wrappers.each( + (index) => { + new Tabs(wrappers.eq(index)); + } + ); + } +); diff --git a/blocks/tabs/class-tabs-block.php b/blocks/tabs/class-tabs-block.php new file mode 100644 index 0000000..9d9812a --- /dev/null +++ b/blocks/tabs/class-tabs-block.php @@ -0,0 +1,142 @@ + array( + 'type' => 'number', + 'default' => 0, + ), + 'patterns' => array( + 'type' => 'string', + 'default' => array(), + ), + ); + } + + /** + * {@inheritdoc} + */ + protected function child_blocks(): array { + return array( + new Child_Block( + 'tab', + 'Tab', + array( + array( + 'key' => 'field_tabs_block_pattern', + 'name' => 'pattern', + 'label' => 'Pattern', + 'type' => 'select', + 'choices' => $this->get_block_pattern_choices(), + ), + ), + __DIR__ . '/templates/tab.php', + array(), + '', + array( + 'mode' => false, + 'color' => array( + 'text' => false, + 'background' => true, + ), + ) + ), + ); + } + + /** + * {@inheritdoc} + */ + protected function template(): string { + return __DIR__ . '/templates/block.php'; + } + + /** + * {@inheritdoc} + */ + protected function use_default_wrapper_template(): bool { + return false; + } + + /** + * {@inheritdoc} + */ + protected function supports(): array { + return array( + 'mode' => false, + 'color' => array( + 'text' => false, + 'background' => true, + ), + ); + } + + /** + * {@inheritdoc} + */ + protected function admin_scripts(): array { + return array( + new Script( + 'tabs-block', + plugin_dir_url( __FILE__ ) . 'assets/admin.js', + array( 'jquery', 'admin-block-initializer', 'admin-block' ), + '1.0.0' + ), + ); + } + + /** + * {@inheritdoc} + */ + protected function scripts(): array { + return array( + new Script( + 'tabs-block', + plugin_dir_url( __FILE__ ) . 'assets/tabs.js', + array( 'jquery' ), + '1.0.0' + ), + ); + } +} diff --git a/blocks/tabs/templates/block.php b/blocks/tabs/templates/block.php new file mode 100644 index 0000000..105d055 --- /dev/null +++ b/blocks/tabs/templates/block.php @@ -0,0 +1,107 @@ +should_hide() ) { + return; +} + +/** + * Retrieve the active tab attribute. + * + * @var int The active tab index. + */ +$active_tab = Helpers::get_block_attribute( 'active_tab', $wp_block ); +$active_tab = $active_tab ?? 0; + +/** + * Retrieve the patterns attribute. + * + * @var array The patterns array. + */ +$patterns = Helpers::get_block_attribute( 'patterns', $wp_block ); +$patterns = $patterns ? explode( ',', $patterns ) : array(); + +/** + * Assign the inner block template to a variable. + * + * @var array The inner block template. + */ +$inner_block_template = array( + array( + $block['name'] . '-tab', + ), + array( + $block['name'] . '-tab', + ), + array( + $block['name'] . '-tab', + ), +); +?> + + + + + +