@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@secretstache/wordpress-gutenberg",
3
- "version": "0.6.13",
3
+ "version": "0.6.15",
4
4
  "description": "",
5
5
  "author": "Secret Stache",
6
6
  "license": "GPL-2.0-or-later",
@@ -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
+ };
@@ -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',