Skip to content

Commit e2eddca

Browse files
authored
Merge pull request #7 from BeAPI/ver/1.0.2
Release 1.0.2
2 parents 6a5e766 + 036d966 commit e2eddca

9 files changed

Lines changed: 143 additions & 41 deletions

File tree

.plugin-data

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"version": "1.0.1",
2+
"version": "1.0.2",
33
"slug": "blockparty-modal"
44
}

README.md

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Blockparty Modal is a WordPress plugin that lets you add accessible modal dialog
1616
- **Modal dialog**: Uses the native `<dialog>` element for semantics and accessibility
1717
- **Configurable content**: Title (with heading level), rich text content, and optional close button
1818
- **Close behaviour**: Choose how the modal closes — click outside, close button only, or prevent closing by backdrop
19-
- **Trigger linking**: Link any block (e.g. core/button) to open a specific modal via `linkedModalId`
19+
- **Trigger linking**: Link a block to open a specific modal via `linkedModalId`; by default only the Button block is allowed as a trigger (filterable)
2020
- **Stable modal ID**: Each modal can have a unique ID for trigger association
2121
- **Layout & styling**: Supports wide and full-width alignment, dimensions, colors, and spacing
2222
- **Internationalized**: Multilingual support with translation files (French included)
@@ -70,11 +70,27 @@ npm run build
7070
- **Close behaviour** — "Any" (click outside or close button), "Close button only", or "None"
7171
- **Close button** — show or hide the close button
7272
- **Prevent scroll** — lock body scroll when the modal is open
73-
4. To open the modal from a button:
74-
- Add a **Button** block (or another block that supports the modal trigger)
75-
- In the block settings, set **Linked Modal ID** to the same value as the modal’s **Modal ID**
73+
4. To open the modal from a trigger block:
74+
- Add a **Button** block (by default, only the Button block can be a modal trigger)
75+
- In the block sidebar, open **Attached modal** and select the modal to open
7676
- On the frontend, clicking that button will open the corresponding modal
7777

78+
### Blocks allowed as modal triggers
79+
80+
By default, only the **core/button** block can be linked to a modal. To allow other blocks (e.g. paragraph, image, or custom blocks), use the filter `blockparty_modal_trigger_allowed_blocks` in your theme or plugin:
81+
82+
```php
83+
add_filter( 'blockparty_modal_trigger_allowed_blocks', function ( $blocks ) {
84+
$blocks[] = 'core/paragraph';
85+
$blocks[] = 'my-plugin/cta';
86+
return $blocks;
87+
} );
88+
```
89+
90+
- **Filter name:** `blockparty_modal_trigger_allowed_blocks`
91+
- **Parameters:** `array` — List of block names (e.g. `'core/button'`).
92+
- **Default:** `array( 'core/button' )`
93+
7894
## 🛠️ Development
7995

8096
### Project Structure
@@ -231,7 +247,19 @@ This plugin is distributed under the GPL-2.0-or-later license. See the [LICENSE]
231247

232248
## 📝 Changelog
233249

234-
See [readme.txt](readme.txt) for version history.
250+
See [readme.txt](readme.txt) for the full version history. Recent highlights:
251+
252+
- **1.0.2**
253+
- Filter `blockparty_modal_trigger_allowed_blocks` to control which blocks can be modal triggers; dialog margin and InnerBlocks fixes.
254+
- Crawl Modal blocks from patterns
255+
- Set min required PHP version to 8.0
256+
- Style issues
257+
258+
- **1.0.1**
259+
- Filter `blockparty_modal_trigger_allowed_blocks` to control which blocks can be modal triggers; dialog margin and InnerBlocks fixes.
260+
261+
- **1.0.0**
262+
- Initial release (Modal block, trigger linking, close behaviour, i18n).
235263

236264
---
237265

blockparty-modal.php

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
/**
33
* Plugin Name: Blockparty Modal
44
* Description: Modal block for WordPress editor.
5-
* Version: 1.0.1
5+
* Version: 1.0.2
66
* Requires at least: 6.8
7-
* Requires PHP: 7.4
7+
* Requires PHP: 8.0
88
* Author: Be API Technical Team
99
* License: GPL-2.0-or-later
1010
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
@@ -19,10 +19,17 @@
1919
exit; // Exit if accessed directly.
2020
}
2121

22-
define( 'BLOCKPARTY_MODAL_VERSION', '1.0.1' );
22+
define( 'BLOCKPARTY_MODAL_VERSION', '1.0.2' );
2323
define( 'BLOCKPARTY_MODAL_URL', plugin_dir_url( __FILE__ ) );
2424
define( 'BLOCKPARTY_MODAL_DIR', plugin_dir_path( __FILE__ ) );
2525

26+
27+
// Require vendor
28+
if ( file_exists( BLOCKPARTY_MODAL_DIR . '/vendor/autoload.php' ) ) {
29+
/** @psalm-suppress UnresolvableInclude */
30+
require BLOCKPARTY_MODAL_DIR . '/vendor/autoload.php';
31+
}
32+
2633
/**
2734
* Registers the block(s) metadata from the `blocks-manifest.php` and registers the block type(s)
2835
* based on the registered block metadata. Behind the scenes, it registers also all assets so they can be enqueued
@@ -36,18 +43,51 @@ function init(): void {
3643
wp_register_block_types_from_metadata_collection( __DIR__ . '/build', __DIR__ . '/build/blocks-manifest.php' );
3744
wp_set_script_translations( 'blockparty-modal-editor-script', 'blockparty-modal', BLOCKPARTY_MODAL_DIR . '/languages' );
3845
}
46+
3947
add_action( 'init', __NAMESPACE__ . '\\init', 10, 0 );
4048

49+
/**
50+
* Passes the list of blocks allowed as modal triggers to the block editor settings
51+
* so the "Attached modal" panel is only shown for those blocks.
52+
*
53+
* @param array<array-key, mixed> $settings Block editor settings.
54+
* @param \WP_Block_Editor_Context $_context Block editor context (unused).
55+
* @return array<array-key, mixed> Modified settings.
56+
*/
57+
function block_editor_settings_modal_trigger_blocks( array $settings, \WP_Block_Editor_Context $_context ): array { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed -- Required by block_editor_settings_all filter signature.
58+
/** @psalm-suppress MixedAssignment */
59+
$raw = apply_filters(
60+
'blockparty_modal_trigger_allowed_blocks',
61+
get_default_modal_trigger_allowed_blocks()
62+
);
63+
$settings['blockpartyModalTriggerAllowedBlocks'] = array_values(
64+
array_filter( is_array( $raw ) ? $raw : [], 'is_string' )
65+
);
66+
return $settings;
67+
}
68+
69+
add_filter( 'block_editor_settings_all', __NAMESPACE__ . '\\block_editor_settings_modal_trigger_blocks', 10, 2 );
70+
71+
/**
72+
* Default list of block names allowed to be used as modal triggers (linkedModalId).
73+
*
74+
* @return string[] Block names (e.g. 'core/button').
75+
*/
76+
function get_default_modal_trigger_allowed_blocks(): array {
77+
return [ 'core/button' ];
78+
}
79+
4180
/**
4281
* Wraps block output with a trigger wrapper when linkedModalId is set,
4382
* so the view script can open the modal on click.
83+
* Only blocks in the allowed list (filterable) get this behavior; by default only core/button.
4484
* For core/button, the inner link or button is turned into the trigger (no wrapper).
4585
*
46-
* @param string $block_content The block content.
47-
* @param array $block The full block, including attributes.
86+
* @param string $block_content The block content.
87+
* @param array<array-key, mixed> $block The full block, including attributes.
4888
* @return string Filtered block content.
4989
*/
50-
function render_block_add_modal_trigger( $block_content, $block ) {
90+
function render_block_add_modal_trigger( $block_content, array $block ) {
5191
$linked_modal_id = isset( $block['attrs']['linkedModalId'] )
5292
? $block['attrs']['linkedModalId']
5393
: '';
@@ -56,9 +96,24 @@ function render_block_add_modal_trigger( $block_content, $block ) {
5696
return $block_content;
5797
}
5898

99+
$block_name = (string) ( $block['blockName'] ?? '' );
100+
/** @psalm-suppress MixedAssignment */
101+
$raw_blocks = apply_filters(
102+
'blockparty_modal_trigger_allowed_blocks',
103+
get_default_modal_trigger_allowed_blocks()
104+
);
105+
$allowed_blocks = array_filter(
106+
is_array( $raw_blocks ) ? $raw_blocks : array(),
107+
'is_string'
108+
);
109+
110+
if ( '' === $block_name || ! in_array( $block_name, $allowed_blocks, true ) ) {
111+
return $block_content;
112+
}
113+
59114
$dialog_id = 'modal-' . $linked_modal_id;
60115

61-
if ( isset( $block['blockName'] ) && 'core/button' === $block['blockName'] ) {
116+
if ( 'core/button' === $block_name ) {
62117
$modified = modify_button_block_for_modal_trigger( $block_content, $linked_modal_id, $dialog_id );
63118
if ( null !== $modified ) {
64119
return $modified;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "blockparty-modal",
3-
"version": "1.0.1",
3+
"version": "1.0.2",
44
"description": "Add a modal block to the WordPress editor.",
55
"author": "Be API",
66
"license": "GPL-2.0-or-later",

readme.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ directory take precedence. For example, `/assets/screenshot-1.png` would win ove
4545

4646
== Changelog ==
4747

48+
= 1.0.2 =
49+
* Filter `blockparty_modal_trigger_allowed_blocks` to control which blocks can be modal triggers; dialog margin and InnerBlocks fixes.
50+
* Crawl Modal blocks from patterns
51+
* Set min required PHP version to 8.0
52+
* Style issues
53+
4854
= 1.0.1 =
4955
* Fix margin style for dialog element; set to auto by default instead of 0.
5056
* Remove dupplicated InnerBlocks.Content

src/blockparty-modal/block.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"$schema": "https://schemas.wp.org/trunk/block.json",
33
"apiVersion": 3,
44
"name": "blockparty/modal",
5-
"version": "1.0.1",
5+
"version": "1.0.2",
66
"title": "Modal",
77
"category": "widgets",
88
"description": "Insert a modal dialog that opens on trigger. Configure content and behaviour in the editor; the modal is displayed on the frontend when activated.",

src/blockparty-modal/index.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import metadata from './block.json';
2323
import {
2424
MODAL_BLOCK_NAME,
2525
LINKED_MODAL_ATTR,
26-
getModalOptionsFromBlocks,
26+
getModalOptionsFromEditor,
2727
addLinkedModalAttribute,
2828
} from './utils';
2929

@@ -52,7 +52,7 @@ blockTypes.forEach( ( blockType ) => {
5252
}
5353
} );
5454

55-
// Add "Open modal on click" panel with Combobox to all blocks except the modal itself.
55+
// Add "Attached modal" panel with Combobox only to blocks allowed as modal triggers (see filter blockparty_modal_trigger_allowed_blocks).
5656
addFilter(
5757
'editor.BlockEdit',
5858
'blockparty-modal/with-modal-trigger-control',
@@ -63,9 +63,18 @@ addFilter(
6363
return <BlockEdit { ...props } />;
6464
}
6565

66+
const allowedBlocks = useSelect( ( select ) => {
67+
const settings = select( 'core/block-editor' ).getSettings();
68+
const list = settings?.blockpartyModalTriggerAllowedBlocks;
69+
return Array.isArray( list ) ? list : [ 'core/button' ];
70+
}, [] );
71+
72+
if ( ! allowedBlocks.includes( name ) ) {
73+
return <BlockEdit { ...props } />;
74+
}
75+
6676
const modalOptions = useSelect( ( select ) => {
67-
const blocks = select( 'core/block-editor' ).getBlocks();
68-
return getModalOptionsFromBlocks( blocks );
77+
return getModalOptionsFromEditor( select );
6978
}, [] );
7079

7180
const options = [

src/blockparty-modal/style.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@
2727

2828
&:not(.block-editor-block-list__block) {
2929
margin: var(--wp-block-blockparty-modal-margin);
30+
31+
&:first-child,
32+
&:last-child {
33+
margin-block: var(--wp-block-blockparty-modal-margin);
34+
}
3035
}
3136

3237
&::backdrop {

src/blockparty-modal/utils.js

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,33 @@ export function generateStableModalId() {
2626
}
2727

2828
/**
29-
* Recursively collect blockparty/modal blocks with modalId and title.
29+
* Collect modal options from the block editor store using getClientIdsWithDescendants
30+
* and getBlock, so modals inside reusable blocks (core/block) and patterns are included.
3031
*
31-
* @param {Object[]} blocks - Block list.
32+
* @param {Function} select - The wp.data select function (e.g. from useSelect).
3233
* @return {Object[]} Options for ComboboxControl.
3334
*/
34-
export function getModalOptionsFromBlocks( blocks ) {
35+
export function getModalOptionsFromEditor( select ) {
36+
const blockEditor = select( 'core/block-editor' );
37+
const clientIds = blockEditor.getClientIdsWithDescendants();
38+
if ( ! Array.isArray( clientIds ) ) {
39+
return [];
40+
}
3541
const options = [];
36-
function traverse( blockList ) {
37-
if ( ! blockList || ! blockList.length ) {
38-
return;
39-
}
40-
for ( const block of blockList ) {
41-
if ( block.name === MODAL_BLOCK_NAME ) {
42-
const modalId = block.attributes?.modalId || block.clientId;
43-
const title =
44-
block.attributes?.title?.trim() ||
45-
__( 'Modal', 'blockparty-modal' );
46-
options.push( {
47-
value: modalId,
48-
label: title || `#${ modalId.slice( 0, 8 ) }`,
49-
} );
50-
}
51-
if ( block.innerBlocks?.length ) {
52-
traverse( block.innerBlocks );
53-
}
42+
for ( const clientId of clientIds ) {
43+
const block = blockEditor.getBlock( clientId );
44+
if ( ! block || block.name !== MODAL_BLOCK_NAME ) {
45+
continue;
5446
}
47+
const modalId = block.attributes?.modalId || block.clientId;
48+
const title =
49+
block.attributes?.title?.trim() ||
50+
__( 'Modal', 'blockparty-modal' );
51+
options.push( {
52+
value: modalId,
53+
label: title || `#${ String( modalId ).slice( 0, 8 ) }`,
54+
} );
5555
}
56-
traverse( blocks );
5756
return options;
5857
}
5958

0 commit comments

Comments
 (0)