@secretstache/wordpress-gutenberg 0.4.13 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- package/build/index.js +3 -3
- package/build/index.js.map +1 -1
- package/build/styles.css +53 -44
- package/package.json +1 -1
- package/src/components/SpacingControl.js +0 -1
- package/src/hooks/useAllowedBlocks.js +1 -1
- package/src/styles/styles.scss +5 -1
- package/src/utils/helpers.js +21 -0
- package/src/utils/index.js +1 -1
- package/src/utils/rootBlock/{setRootBlockAppender.js → appender.js} +26 -18
- package/src/utils/rootBlock/index.js +5 -3
- package/src/utils/rootBlock/rootBlockVisibilityFilter.js +35 -0
- package/src/utils/rootBlock/setRootBlockFilter.js +29 -0
- package/src/utils/rootBlock/setRootBlockForPostTypes.js +73 -0
- package/src/utils/rootBlock/unsetRootBlockFilter.js +26 -0
- package/src/utils/rootContainer/README.md +72 -0
- package/src/utils/rootContainer/index.js +42 -0
- package/src/utils/rootBlock/README.md +0 -156
- package/src/utils/rootBlock/hideRootBlockForOtherBlocks.js +0 -33
- package/src/utils/rootBlock/setRootBlock.js +0 -115
- package/src/utils/waitForContainer/README.md +0 -40
- package/src/utils/waitForContainer/index.js +0 -26
package/build/styles.css
CHANGED
@@ -20,50 +20,6 @@
|
|
20
20
|
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container {
|
21
21
|
margin-bottom: 0;
|
22
22
|
padding-bottom: 0; }
|
23
|
-
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container .bc-image-wrapper {
|
24
|
-
position: relative;
|
25
|
-
height: auto;
|
26
|
-
align-self: start; }
|
27
|
-
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container .bc-image-wrapper__actions {
|
28
|
-
display: none;
|
29
|
-
position: absolute;
|
30
|
-
top: 0;
|
31
|
-
left: 0;
|
32
|
-
right: 0;
|
33
|
-
bottom: 0;
|
34
|
-
flex-wrap: nowrap;
|
35
|
-
justify-content: center;
|
36
|
-
align-items: center;
|
37
|
-
gap: 20px;
|
38
|
-
padding: 5px 15px;
|
39
|
-
z-index: 20; }
|
40
|
-
@media screen and (max-width: 768px) {
|
41
|
-
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container .bc-image-wrapper__actions {
|
42
|
-
gap: 15px; } }
|
43
|
-
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container .bc-image-wrapper__btn {
|
44
|
-
font-size: 14px !important;
|
45
|
-
backdrop-filter: blur(16px) saturate(180%);
|
46
|
-
background: rgba(255, 255, 255, 0.75);
|
47
|
-
flex-grow: 1;
|
48
|
-
justify-content: center;
|
49
|
-
max-width: 130px; }
|
50
|
-
@media screen and (max-width: 768px) {
|
51
|
-
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container .bc-image-wrapper__btn {
|
52
|
-
padding: 5px; } }
|
53
|
-
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container .bc-image-wrapper__overlay {
|
54
|
-
display: none;
|
55
|
-
position: absolute;
|
56
|
-
top: 0;
|
57
|
-
left: 0;
|
58
|
-
right: 0;
|
59
|
-
bottom: 0;
|
60
|
-
z-index: 10;
|
61
|
-
background: rgba(255, 255, 255, 0.3);
|
62
|
-
backdrop-filter: blur(3px); }
|
63
|
-
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container .bc-image-wrapper:hover .bc-image-wrapper__actions {
|
64
|
-
display: flex; }
|
65
|
-
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container .bc-image-wrapper:hover .bc-image-wrapper__overlay {
|
66
|
-
display: block; }
|
67
23
|
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container .root-block-appender {
|
68
24
|
position: absolute;
|
69
25
|
bottom: 30px;
|
@@ -271,6 +227,59 @@
|
|
271
227
|
.editor-sidebar .bc-spacing-range-control .components-base-control__help {
|
272
228
|
margin-left: -11px; }
|
273
229
|
|
230
|
+
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container .bc-image-wrapper,
|
231
|
+
.editor-sidebar .bc-image-wrapper {
|
232
|
+
position: relative;
|
233
|
+
height: auto;
|
234
|
+
align-self: start; }
|
235
|
+
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container .bc-image-wrapper__actions,
|
236
|
+
.editor-sidebar .bc-image-wrapper__actions {
|
237
|
+
display: none;
|
238
|
+
position: absolute;
|
239
|
+
top: 0;
|
240
|
+
left: 0;
|
241
|
+
right: 0;
|
242
|
+
bottom: 0;
|
243
|
+
flex-wrap: nowrap;
|
244
|
+
justify-content: center;
|
245
|
+
align-items: center;
|
246
|
+
gap: 20px;
|
247
|
+
padding: 5px 15px;
|
248
|
+
z-index: 20; }
|
249
|
+
@media screen and (max-width: 768px) {
|
250
|
+
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container .bc-image-wrapper__actions,
|
251
|
+
.editor-sidebar .bc-image-wrapper__actions {
|
252
|
+
gap: 15px; } }
|
253
|
+
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container .bc-image-wrapper__btn,
|
254
|
+
.editor-sidebar .bc-image-wrapper__btn {
|
255
|
+
font-size: 14px !important;
|
256
|
+
backdrop-filter: blur(16px) saturate(180%);
|
257
|
+
background: rgba(255, 255, 255, 0.75);
|
258
|
+
flex-grow: 1;
|
259
|
+
justify-content: center;
|
260
|
+
max-width: 130px; }
|
261
|
+
@media screen and (max-width: 768px) {
|
262
|
+
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container .bc-image-wrapper__btn,
|
263
|
+
.editor-sidebar .bc-image-wrapper__btn {
|
264
|
+
padding: 5px; } }
|
265
|
+
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container .bc-image-wrapper__overlay,
|
266
|
+
.editor-sidebar .bc-image-wrapper__overlay {
|
267
|
+
display: none;
|
268
|
+
position: absolute;
|
269
|
+
top: 0;
|
270
|
+
left: 0;
|
271
|
+
right: 0;
|
272
|
+
bottom: 0;
|
273
|
+
z-index: 10;
|
274
|
+
background: rgba(255, 255, 255, 0.3);
|
275
|
+
backdrop-filter: blur(3px); }
|
276
|
+
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container .bc-image-wrapper:hover .bc-image-wrapper__actions,
|
277
|
+
.editor-sidebar .bc-image-wrapper:hover .bc-image-wrapper__actions {
|
278
|
+
display: flex; }
|
279
|
+
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container .bc-image-wrapper:hover .bc-image-wrapper__overlay,
|
280
|
+
.editor-sidebar .bc-image-wrapper:hover .bc-image-wrapper__overlay {
|
281
|
+
display: block; }
|
282
|
+
|
274
283
|
.block-editor-block-types-list > [role=presentation] {
|
275
284
|
justify-content: center; }
|
276
285
|
|
package/package.json
CHANGED
@@ -27,7 +27,6 @@ const Control = ({ label, max, min, value, onChange, disabled, tooltip, ...other
|
|
27
27
|
max={max}
|
28
28
|
marks={generateMarks(min, max)}
|
29
29
|
resetFallbackValue={-1}
|
30
|
-
help="Use -1 for default settings."
|
31
30
|
renderTooltipContent={(value) => {
|
32
31
|
if (value === -1) return 'Default';
|
33
32
|
|
package/src/styles/styles.scss
CHANGED
@@ -33,7 +33,6 @@
|
|
33
33
|
}
|
34
34
|
|
35
35
|
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container {
|
36
|
-
@import "image-wrapper";
|
37
36
|
@import "root-block-appender";
|
38
37
|
@import "empty-block-appender";
|
39
38
|
@import "new-child-btn";
|
@@ -74,6 +73,11 @@
|
|
74
73
|
@import "responsive-spacing";
|
75
74
|
}
|
76
75
|
|
76
|
+
.editor-styles-wrapper .block-editor-block-list__layout.is-root-container,
|
77
|
+
.editor-sidebar {
|
78
|
+
@import "image-wrapper";
|
79
|
+
}
|
80
|
+
|
77
81
|
.block-editor-block-types-list > [role=presentation] {
|
78
82
|
justify-content: center;
|
79
83
|
}
|
package/src/utils/helpers.js
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import { filters } from '@wordpress/hooks';
|
1
2
|
import apiFetch from '@wordpress/api-fetch';
|
2
3
|
import slugify from 'slugify';
|
3
4
|
import classNames from 'classnames';
|
@@ -144,3 +145,23 @@ export const getSpacingClasses = (
|
|
144
145
|
[`${mobilePrefix}pb-${spacing?.mobile?.padding?.bottom}`]: spacing?.mobile?.padding?.bottom !== -1,
|
145
146
|
});
|
146
147
|
};
|
148
|
+
|
149
|
+
/**
|
150
|
+
* @param namespace
|
151
|
+
* @returns {*[]}
|
152
|
+
*/
|
153
|
+
const getFiltersByNamespace = (namespace) => {
|
154
|
+
const list = [];
|
155
|
+
|
156
|
+
Object.entries(filters).forEach(([filterName, filterData]) => {
|
157
|
+
const handlers = filterData.handlers || [];
|
158
|
+
|
159
|
+
handlers.forEach((handler) => {
|
160
|
+
if (handler.namespace.startsWith(namespace)) {
|
161
|
+
list.push({ filterName, namespace: handler.namespace });
|
162
|
+
}
|
163
|
+
});
|
164
|
+
});
|
165
|
+
|
166
|
+
return list;
|
167
|
+
};
|
package/src/utils/index.js
CHANGED
@@ -1,25 +1,17 @@
|
|
1
1
|
import { createBlock } from '@wordpress/blocks';
|
2
2
|
import { dispatch } from '@wordpress/data';
|
3
3
|
|
4
|
-
import {
|
4
|
+
import { getRootContainer } from '../rootContainer/index.js';
|
5
5
|
|
6
|
-
const
|
7
|
-
const ROOT_BLOCK_APPENDER_SELECTOR = '.is-root-container .root-block-appender';
|
6
|
+
const ROOT_BLOCK_APPENDER_SELECTOR = '.root-block-appender';
|
8
7
|
|
9
8
|
/**
|
10
9
|
* Initializes the custom button for the root appender.
|
10
|
+
* @param {Element} rootContainer - The root container of the editor.
|
11
11
|
* @param {string} blockName - The name of the block to be created when the appender is clicked.
|
12
12
|
* @param {string} tooltipText - The tooltip text displayed on the appender.
|
13
13
|
*/
|
14
|
-
const initialize = (blockName, tooltipText) => {
|
15
|
-
const rootContainer = document.querySelector(ROOT_CONTAINER_SELECTOR);
|
16
|
-
|
17
|
-
if (!rootContainer) {
|
18
|
-
console.error('Root container not found');
|
19
|
-
|
20
|
-
return;
|
21
|
-
}
|
22
|
-
|
14
|
+
const initialize = (rootContainer, blockName, tooltipText) => {
|
23
15
|
const button = document.createElement('button');
|
24
16
|
|
25
17
|
button.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false"><path d="M11 12.5V17.5H12.5V12.5H17.5V11H12.5V6H11V11H6V12.5H11Z"></path></svg>';
|
@@ -32,6 +24,8 @@ const initialize = (blockName, tooltipText) => {
|
|
32
24
|
});
|
33
25
|
|
34
26
|
rootContainer.prepend(button);
|
27
|
+
|
28
|
+
return !!rootContainer.querySelector(ROOT_BLOCK_APPENDER_SELECTOR);
|
35
29
|
};
|
36
30
|
|
37
31
|
/**
|
@@ -42,13 +36,27 @@ const initialize = (blockName, tooltipText) => {
|
|
42
36
|
* @param {string} [tooltipText='Add Row'] - The tooltip text displayed on the appender.
|
43
37
|
*/
|
44
38
|
export const setRootBlockAppender = (blockName, tooltipText = 'Add Row') => {
|
45
|
-
|
39
|
+
const rootContainer = getRootContainer();
|
40
|
+
|
41
|
+
if (rootContainer) {
|
42
|
+
initialize(rootContainer, blockName, tooltipText);
|
43
|
+
} else {
|
44
|
+
console.error('Root container is not found.')
|
45
|
+
}
|
46
46
|
};
|
47
47
|
|
48
48
|
export const unsetRootBlockAppender = () => {
|
49
|
-
const
|
50
|
-
|
51
|
-
if (
|
52
|
-
appender.
|
49
|
+
const rootContainer = getRootContainer();
|
50
|
+
|
51
|
+
if (rootContainer) {
|
52
|
+
const appender = rootContainer.querySelector(ROOT_BLOCK_APPENDER_SELECTOR);
|
53
|
+
|
54
|
+
if (appender) {
|
55
|
+
appender.remove();
|
56
|
+
} else {
|
57
|
+
console.error('Root block appender is not found.');
|
58
|
+
}
|
59
|
+
} else {
|
60
|
+
console.error('Root container is not found.')
|
53
61
|
}
|
54
|
-
}
|
62
|
+
};
|
@@ -1,4 +1,6 @@
|
|
1
|
-
export * from './
|
2
|
-
export * from './
|
1
|
+
export * from './setRootBlockForPostTypes.js'
|
2
|
+
export * from './setRootBlockFilter.js'
|
3
|
+
export * from './unsetRootBlockFilter.js';
|
4
|
+
export * from './rootBlockVisibilityFilter.js';
|
5
|
+
export * from './appender.js';
|
3
6
|
export * from './hideRootBlockForInlineInserter.js';
|
4
|
-
export * from './hideRootBlockForOtherBlocks.js';
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import { addFilter, removeFilter } from '@wordpress/hooks';
|
2
|
+
import { getBlockTypes } from '@wordpress/blocks';
|
3
|
+
|
4
|
+
export const rootBlockVisibilityFilter = {
|
5
|
+
add({ rootBlockName }) {
|
6
|
+
addFilter(
|
7
|
+
'blocks.registerBlockType',
|
8
|
+
'ssm/root-block-visibility',
|
9
|
+
(blockSettings, blockName) => {
|
10
|
+
const isRootBlock = blockName === rootBlockName;
|
11
|
+
const hasOwnAllowedBlocks = !!blockSettings?.allowedBlocks;
|
12
|
+
const hasParent = !!blockSettings?.parent;
|
13
|
+
|
14
|
+
if (isRootBlock || hasParent || hasOwnAllowedBlocks) {
|
15
|
+
return blockSettings;
|
16
|
+
}
|
17
|
+
|
18
|
+
// get all blockTypes
|
19
|
+
blockSettings.allowedBlocks = getBlockTypes()
|
20
|
+
?.filter((allowedBlock) => {
|
21
|
+
const isRootBlock = allowedBlock.name === rootBlockName;
|
22
|
+
const hasParent = !!allowedBlock?.parent;
|
23
|
+
|
24
|
+
return !isRootBlock && !hasParent;
|
25
|
+
})
|
26
|
+
?.map(allowedBlock => allowedBlock.name);
|
27
|
+
|
28
|
+
return blockSettings;
|
29
|
+
},
|
30
|
+
);
|
31
|
+
},
|
32
|
+
remove() {
|
33
|
+
removeFilter('blocks.registerBlockType', 'ssm/root-block-visibility');
|
34
|
+
},
|
35
|
+
};
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import { addFilter, removeFilter } from '@wordpress/hooks';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Adds a filter to set the specified block as the root block by modifying block settings during registration.
|
5
|
+
* Blocks other than the root block will have their 'ancestor' property set to the root block name,
|
6
|
+
* making them only insertable within the root block.
|
7
|
+
*/
|
8
|
+
export const setRootBlockFilter = {
|
9
|
+
add(rootBlockName) {
|
10
|
+
addFilter(
|
11
|
+
'blocks.registerBlockType',
|
12
|
+
'ssm/set-root-block',
|
13
|
+
(settings, name) => {
|
14
|
+
const isRootBlock = name === rootBlockName;
|
15
|
+
const isBaseBlock = name === 'core/block';
|
16
|
+
const hasAncestor = !!settings?.ancestor;
|
17
|
+
|
18
|
+
if (!isRootBlock && !isBaseBlock && !hasAncestor) {
|
19
|
+
settings.ancestor = [rootBlockName];
|
20
|
+
}
|
21
|
+
|
22
|
+
return settings;
|
23
|
+
},
|
24
|
+
);
|
25
|
+
},
|
26
|
+
remove() {
|
27
|
+
removeFilter('blocks.registerBlockType', 'ssm/set-root-block');
|
28
|
+
},
|
29
|
+
};
|
@@ -0,0 +1,73 @@
|
|
1
|
+
import { dispatch, select, subscribe } from '@wordpress/data';
|
2
|
+
import { setRootBlockFilter } from './setRootBlockFilter.js';
|
3
|
+
import { unsetRootBlockFilter } from './unsetRootBlockFilter.js';
|
4
|
+
import { rootBlockVisibilityFilter } from './rootBlockVisibilityFilter.js';
|
5
|
+
import { waitForRootContainer } from '../rootContainer/index.js';
|
6
|
+
import { setRootBlockAppender, unsetRootBlockAppender } from './appender.js';
|
7
|
+
|
8
|
+
/**
|
9
|
+
* Configures a root block for specific post types
|
10
|
+
*
|
11
|
+
* @param {string} rootBlockName - The name of the root block to set.
|
12
|
+
* @param {Array<string>} [postTypes=['page', 'post']] - The post types for which the root block should be enabled.
|
13
|
+
* @param {Function} [callback] - Optional callback to execute when the root block state changes.
|
14
|
+
* @param {Array<Object>} [filters=[rootBlockVisibilityFilter]] - Filters to apply or remove when enabling/disabling the root block.
|
15
|
+
* @param {boolean} [initAppender=true] - Whether to initialize the root block appender.
|
16
|
+
* @param {string} [appenderTooltipText='Add Row'] - Tooltip text for the root block appender.
|
17
|
+
*/
|
18
|
+
export const setRootBlockForPostTypes = (
|
19
|
+
rootBlockName,
|
20
|
+
postTypes = ['page', 'post'],
|
21
|
+
callback,
|
22
|
+
filters = [ rootBlockVisibilityFilter ],
|
23
|
+
initAppender = true,
|
24
|
+
appenderTooltipText = 'Add Row',
|
25
|
+
) => {
|
26
|
+
let isRootBlockEnabled = false;
|
27
|
+
|
28
|
+
waitForRootContainer().then(() => {
|
29
|
+
console.log('Root Container found.');
|
30
|
+
|
31
|
+
subscribe(() => {
|
32
|
+
const currentPostType = select('core/editor').getCurrentPostType();
|
33
|
+
|
34
|
+
if (postTypes.includes(currentPostType) && !isRootBlockEnabled) {
|
35
|
+
isRootBlockEnabled = true;
|
36
|
+
|
37
|
+
setRootBlockFilter.add(rootBlockName);
|
38
|
+
unsetRootBlockFilter.remove();
|
39
|
+
|
40
|
+
if (filters?.length > 0) {
|
41
|
+
filters.forEach((filter) => filter.add({ rootBlockName, isRootBlockEnabled, currentPostType }));
|
42
|
+
dispatch('core/blocks').reapplyBlockTypeFilters();
|
43
|
+
}
|
44
|
+
|
45
|
+
if (callback) {
|
46
|
+
callback({ isRootBlockEnabled, currentPostType });
|
47
|
+
}
|
48
|
+
|
49
|
+
if (initAppender) {
|
50
|
+
setRootBlockAppender(rootBlockName, appenderTooltipText);
|
51
|
+
}
|
52
|
+
} else if (!postTypes.includes(currentPostType) && isRootBlockEnabled) {
|
53
|
+
isRootBlockEnabled = false;
|
54
|
+
|
55
|
+
setRootBlockFilter.remove()
|
56
|
+
unsetRootBlockFilter.add(rootBlockName);
|
57
|
+
|
58
|
+
if (filters?.length > 0) {
|
59
|
+
filters.forEach((filter) => filter.remove({ rootBlockName, isRootBlockEnabled, currentPostType }));
|
60
|
+
dispatch('core/blocks').reapplyBlockTypeFilters();
|
61
|
+
}
|
62
|
+
|
63
|
+
if (callback) {
|
64
|
+
callback({ isRootBlockEnabled, currentPostType });
|
65
|
+
}
|
66
|
+
|
67
|
+
if (initAppender) {
|
68
|
+
unsetRootBlockAppender();
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}, 'core/block-editor');
|
72
|
+
})
|
73
|
+
};
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import { addFilter, removeFilter } from '@wordpress/hooks';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Adds a filter to unset the root block restrictions by removing the 'ancestor' property from block settings
|
5
|
+
* if it includes the specified root block name.
|
6
|
+
*/
|
7
|
+
export const unsetRootBlockFilter = {
|
8
|
+
add(rootBlockName) {
|
9
|
+
addFilter(
|
10
|
+
'blocks.registerBlockType',
|
11
|
+
'ssm/unset-root-block',
|
12
|
+
(settings) => {
|
13
|
+
const hasRootAncestor = settings.ancestor && settings.ancestor.includes(rootBlockName);
|
14
|
+
|
15
|
+
if (hasRootAncestor) {
|
16
|
+
settings.ancestor = null;
|
17
|
+
}
|
18
|
+
|
19
|
+
return settings;
|
20
|
+
},
|
21
|
+
);
|
22
|
+
},
|
23
|
+
remove() {
|
24
|
+
removeFilter('blocks.registerBlockType', 'ssm/unset-root-block');
|
25
|
+
},
|
26
|
+
};
|
@@ -0,0 +1,72 @@
|
|
1
|
+
## Overview
|
2
|
+
|
3
|
+
The `waitForRootContainer` function is a utility that periodically checks for the presence of the Gutenberg editor's root container, identified by the class `.is-root-container`. Once the container is found, it resolves a promise, allowing for additional initialization logic.
|
4
|
+
|
5
|
+
## Function Signature
|
6
|
+
|
7
|
+
```javascript
|
8
|
+
/**
|
9
|
+
* Periodically checks for the presence of the Gutenberg editor's root container and resolves when found.
|
10
|
+
*
|
11
|
+
* @param {number} [maxAttempts=10] - The maximum number of attempts to check for the root container.
|
12
|
+
* @param {number} [interval=500] - The interval time (in milliseconds) between attempts.
|
13
|
+
* @returns {Promise<Element>} - Resolves with the root container element if found, or rejects if not found after max attempts.
|
14
|
+
*/
|
15
|
+
export const waitForRootContainer = (maxAttempts = 10, interval = 500);
|
16
|
+
```
|
17
|
+
|
18
|
+
### Parameters
|
19
|
+
- **maxAttempts** (`number`, optional): The maximum number of attempts to check for the root container. Default is `10`.
|
20
|
+
- **interval** (`number`, optional): The interval time (in milliseconds) between each attempt. Default is `500`.
|
21
|
+
|
22
|
+
### Returns
|
23
|
+
- **Promise<Element>**: Resolves with the root container element when found. Rejects with an error if the container is not found after the maximum attempts.
|
24
|
+
|
25
|
+
---
|
26
|
+
|
27
|
+
## Usage Example
|
28
|
+
To use the `waitForRootContainer` function, import it into your script and handle the promise:
|
29
|
+
|
30
|
+
```javascript
|
31
|
+
import { waitForRootContainer } from '@secretstache/wordpress-gutenberg';
|
32
|
+
|
33
|
+
waitForRootContainer(10, 500)
|
34
|
+
.then((rootContainer) => {
|
35
|
+
console.log('Gutenberg root container found:', rootContainer);
|
36
|
+
// Your initialization logic here
|
37
|
+
})
|
38
|
+
.catch((error) => {
|
39
|
+
console.error('Failed to find Gutenberg root container:', error);
|
40
|
+
});
|
41
|
+
```
|
42
|
+
|
43
|
+
### Example Output
|
44
|
+
In this example:
|
45
|
+
- The function checks for the Gutenberg root container (identified by `.is-root-container`) up to 10 times, waiting 500ms between each check.
|
46
|
+
- If the container is found, it resolves with the container element.
|
47
|
+
- If the container is not found after 10 attempts, it rejects with an error.
|
48
|
+
|
49
|
+
---
|
50
|
+
|
51
|
+
## getRootContainer
|
52
|
+
|
53
|
+
The `getRootContainer` function retrieves the Gutenberg editor's root container element from the DOM.
|
54
|
+
|
55
|
+
### Usage Example
|
56
|
+
|
57
|
+
```javascript
|
58
|
+
import { getRootContainer } from '@secretstache/wordpress-gutenberg';
|
59
|
+
|
60
|
+
const rootContainer = getRootContainer();
|
61
|
+
if (rootContainer) {
|
62
|
+
console.log('Gutenberg root container found:', rootContainer);
|
63
|
+
} else {
|
64
|
+
console.log('Gutenberg root container not found');
|
65
|
+
}
|
66
|
+
```
|
67
|
+
|
68
|
+
---
|
69
|
+
|
70
|
+
### Notes
|
71
|
+
- The `getRootContainer` function searches both the main DOM and an iframe (if applicable) for the Gutenberg root container with the class `.is-root-container`.
|
72
|
+
- `waitForRootContainer` is built on top of `getRootContainer` and provides retry logic for situations where the root container is not immediately available.
|
@@ -0,0 +1,42 @@
|
|
1
|
+
const ROOT_CONTAINER_SELECTOR = '.is-root-container';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Retrieves the Gutenberg editor's root container element from the DOM or an iframe.
|
5
|
+
*
|
6
|
+
* @returns {Element|null} - Returns the root container element if found, or null if not found.
|
7
|
+
*/
|
8
|
+
export const getRootContainer = () => {
|
9
|
+
const rootContainer = document.querySelector(ROOT_CONTAINER_SELECTOR);
|
10
|
+
|
11
|
+
if (rootContainer) {
|
12
|
+
return rootContainer;
|
13
|
+
}
|
14
|
+
|
15
|
+
const iframe = document.querySelector('.block-editor iframe');
|
16
|
+
const iframeDocument = iframe?.contentDocument || iframe?.contentWindow?.document;
|
17
|
+
|
18
|
+
return iframeDocument?.querySelector(ROOT_CONTAINER_SELECTOR) || null;
|
19
|
+
};
|
20
|
+
|
21
|
+
export const waitForRootContainer = (maxAttempts = 10, interval = 500) => {
|
22
|
+
return new Promise((resolve, reject) => {
|
23
|
+
let attempts = 0;
|
24
|
+
|
25
|
+
const checkRootContainer = () => {
|
26
|
+
const rootContainer = getRootContainer();
|
27
|
+
|
28
|
+
if (rootContainer) {
|
29
|
+
return resolve(rootContainer);
|
30
|
+
} else {
|
31
|
+
if (attempts <= maxAttempts) {
|
32
|
+
attempts++;
|
33
|
+
setTimeout(checkRootContainer, interval);
|
34
|
+
} else {
|
35
|
+
reject(new Error('Root container not found after max attempts.'));
|
36
|
+
}
|
37
|
+
}
|
38
|
+
};
|
39
|
+
|
40
|
+
checkRootContainer();
|
41
|
+
});
|
42
|
+
};
|