@secretstache/wordpress-gutenberg 0.6.13 → 0.6.15
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 +1003 -1004
- package/build/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/PatternsModal.jsx +124 -0
- package/src/hooks/useTabs.jsx +9 -10
- package/src/utils/rootBlock/setRootBlockFilter.js +1 -1
package/package.json
CHANGED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { useDispatch, useSelect } from '@wordpress/data';
|
|
2
|
+
import { useState } from '@wordpress/element';
|
|
3
|
+
import { rawHandler } from '@wordpress/blocks';
|
|
4
|
+
import { Button, Modal, TextControl } from '@wordpress/components';
|
|
5
|
+
import { __experimentalBlockPatternsList as BlockPatternsList } from '@wordpress/block-editor';
|
|
6
|
+
|
|
7
|
+
export const PatternsModal = ({ isOpen, onRequestClose, rootClientId }) => {
|
|
8
|
+
const patterns = useSelect(
|
|
9
|
+
(select) => select('core/block-editor').__experimentalGetAllowedPatterns?.(rootClientId) || [],
|
|
10
|
+
[rootClientId]
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
const { insertBlocks, replaceBlock } = useDispatch('core/block-editor');
|
|
14
|
+
const { selectedClientId } = useSelect((select) => ({
|
|
15
|
+
selectedClientId: select('core/block-editor').getSelectedBlockClientId(),
|
|
16
|
+
}), []);
|
|
17
|
+
|
|
18
|
+
const [ searchValue, setSearchValue ] = useState('');
|
|
19
|
+
const [ selectedCategory, setSelectedCategory ] = useState('all');
|
|
20
|
+
|
|
21
|
+
const normalizedPatterns = (patterns || []).map((pattern, index) => ({
|
|
22
|
+
...pattern,
|
|
23
|
+
name: typeof pattern?.name === 'string' ? pattern.name : `pattern-${index}`,
|
|
24
|
+
title: typeof pattern?.title === 'string'
|
|
25
|
+
? pattern.title
|
|
26
|
+
: pattern?.title?.rendered || `Pattern ${index + 1}`,
|
|
27
|
+
blocks: Array.isArray(pattern?.blocks)
|
|
28
|
+
? pattern.blocks
|
|
29
|
+
: typeof pattern?.content === 'string'
|
|
30
|
+
? rawHandler({ HTML: pattern.content })
|
|
31
|
+
: [],
|
|
32
|
+
}));
|
|
33
|
+
|
|
34
|
+
const categories = [
|
|
35
|
+
{ name: 'all', label: 'All Patterns' },
|
|
36
|
+
...Array.from(new Set(normalizedPatterns.flatMap((p) => p.categories || []))).map((name) => ({
|
|
37
|
+
name,
|
|
38
|
+
label: name,
|
|
39
|
+
})),
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
const filteredPatterns = normalizedPatterns.filter((pattern) => {
|
|
43
|
+
const matchesSearch = !searchValue || (pattern.title || '').toLowerCase().includes(searchValue.toLowerCase());
|
|
44
|
+
const inCategory = selectedCategory === 'all' || (pattern.categories || []).includes(selectedCategory);
|
|
45
|
+
|
|
46
|
+
return matchesSearch && inCategory;
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const onClickPattern = (pattern) => {
|
|
50
|
+
const blocks = Array.isArray(pattern.blocks)
|
|
51
|
+
? pattern.blocks
|
|
52
|
+
: typeof pattern.content === 'string'
|
|
53
|
+
? rawHandler({ HTML: pattern.content })
|
|
54
|
+
: [];
|
|
55
|
+
|
|
56
|
+
const allRootAreSections = blocks.length > 0 && blocks.every((b) => b.name === 'ssm/section-wrapper');
|
|
57
|
+
const targetClientId = selectedClientId || rootClientId;
|
|
58
|
+
|
|
59
|
+
if (allRootAreSections) {
|
|
60
|
+
replaceBlock(targetClientId, blocks);
|
|
61
|
+
} else {
|
|
62
|
+
insertBlocks(blocks, 0, targetClientId);
|
|
63
|
+
}
|
|
64
|
+
onRequestClose();
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
if (!isOpen) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<Modal
|
|
73
|
+
title="Patterns"
|
|
74
|
+
onRequestClose={onRequestClose}
|
|
75
|
+
isFullScreen
|
|
76
|
+
>
|
|
77
|
+
<div className="block-editor-block-patterns-explorer">
|
|
78
|
+
<div className="block-editor-block-patterns-explorer__sidebar">
|
|
79
|
+
<div className="block-editor-block-patterns-explorer__search">
|
|
80
|
+
<TextControl
|
|
81
|
+
__nextHasNoMarginBottom
|
|
82
|
+
value={searchValue}
|
|
83
|
+
onChange={setSearchValue}
|
|
84
|
+
label="Search"
|
|
85
|
+
placeholder="Search"
|
|
86
|
+
autoFocus
|
|
87
|
+
/>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
{!searchValue && (
|
|
91
|
+
<div className="block-editor-block-patterns-explorer__sidebar__categories-list">
|
|
92
|
+
{categories.map(({ name, label }) => (
|
|
93
|
+
<Button
|
|
94
|
+
__next40pxDefaultSize
|
|
95
|
+
key={name}
|
|
96
|
+
label={label}
|
|
97
|
+
className="block-editor-block-patterns-explorer__sidebar__categories-list__item"
|
|
98
|
+
isPressed={selectedCategory === name}
|
|
99
|
+
onClick={() => setSelectedCategory(name)}
|
|
100
|
+
>
|
|
101
|
+
{label}
|
|
102
|
+
</Button>
|
|
103
|
+
))}
|
|
104
|
+
</div>
|
|
105
|
+
)}
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
<div className="block-editor-block-patterns-explorer__list">
|
|
109
|
+
{searchValue && (
|
|
110
|
+
<div className="block-editor-block-patterns-explorer__search-results-count">
|
|
111
|
+
{filteredPatterns.length} {filteredPatterns.length === 1 ? 'pattern found' : 'patterns found'}
|
|
112
|
+
</div>
|
|
113
|
+
)}
|
|
114
|
+
|
|
115
|
+
<BlockPatternsList
|
|
116
|
+
blockPatterns={filteredPatterns}
|
|
117
|
+
onClickPattern={onClickPattern}
|
|
118
|
+
isDraggable={false}
|
|
119
|
+
/>
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
</Modal>
|
|
123
|
+
);
|
|
124
|
+
};
|
package/src/hooks/useTabs.jsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useSelect, useDispatch, select } from '@wordpress/data';
|
|
2
2
|
import { store as blockEditorStore } from '@wordpress/block-editor';
|
|
3
|
-
import { useLayoutEffect, useState } from '@wordpress/element';
|
|
3
|
+
import { useCallback, useLayoutEffect, useMemo, useState } from '@wordpress/element';
|
|
4
4
|
import { Button } from '@wordpress/components';
|
|
5
5
|
import { createBlock } from '@wordpress/blocks';
|
|
6
6
|
|
|
@@ -26,7 +26,6 @@ export const useTabs = (tabsClientId, tabItemName) => {
|
|
|
26
26
|
getSelectedBlock,
|
|
27
27
|
getSelectedBlockClientId,
|
|
28
28
|
getBlockOrder,
|
|
29
|
-
getBlockRootClientId,
|
|
30
29
|
} = select(blockEditorStore);
|
|
31
30
|
|
|
32
31
|
return {
|
|
@@ -86,27 +85,27 @@ export const useTabs = (tabsClientId, tabItemName) => {
|
|
|
86
85
|
}
|
|
87
86
|
}, [ selectedBlock, tabItemName, tabsClientId ]);
|
|
88
87
|
|
|
89
|
-
const createTab = (blockName, attributes = {}, position = tabsCount) => {
|
|
88
|
+
const createTab = useCallback((blockName, attributes = {}, position = tabsCount) => {
|
|
90
89
|
const newTab = createBlock(blockName, attributes);
|
|
91
90
|
insertBlock(newTab, position, tabsClientId);
|
|
92
91
|
|
|
93
92
|
return newTab;
|
|
94
|
-
};
|
|
93
|
+
}, [ tabsCount, tabsClientId, insertBlock ]);
|
|
95
94
|
|
|
96
|
-
const onTabAppenderClick = () => {
|
|
95
|
+
const onTabAppenderClick = useCallback(() => {
|
|
97
96
|
const newItem = createTab(tabItemName);
|
|
98
97
|
setActiveItemId(newItem.clientId);
|
|
99
|
-
};
|
|
98
|
+
}, [ tabItemName, createTab, setActiveItemId ]);
|
|
100
99
|
|
|
101
|
-
const TabAppender = ({ label = 'Add new tab', ...other }) => (
|
|
100
|
+
const TabAppender = useMemo(() => ({ label = 'Add new tab', ...other }) => (
|
|
102
101
|
<Button
|
|
103
|
-
className="bc-add-new-child-btn"
|
|
104
|
-
icon={plusIcon}
|
|
105
102
|
label={label}
|
|
103
|
+
icon={plusIcon}
|
|
104
|
+
className="bc-add-new-child-btn"
|
|
106
105
|
onClick={onTabAppenderClick}
|
|
107
106
|
{...other}
|
|
108
107
|
/>
|
|
109
|
-
);
|
|
108
|
+
), [ onTabAppenderClick ]);
|
|
110
109
|
|
|
111
110
|
return {
|
|
112
111
|
tabs,
|
|
@@ -6,7 +6,7 @@ import { addFilter, removeFilter } from '@wordpress/hooks';
|
|
|
6
6
|
* making them only insertable within the root block.
|
|
7
7
|
*/
|
|
8
8
|
export const setRootBlockFilter = {
|
|
9
|
-
add(rootBlockName) {
|
|
9
|
+
add({ rootBlockName }) {
|
|
10
10
|
addFilter(
|
|
11
11
|
'blocks.registerBlockType',
|
|
12
12
|
'ssm/set-root-block',
|