@secretstache/wordpress-gutenberg 0.4.13 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
};
|