-
Notifications
You must be signed in to change notification settings - Fork 4.3k
/
Copy pathblock.js
137 lines (125 loc) · 4.35 KB
/
block.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/**
* External dependencies
*/
import { once } from 'lodash';
/**
* WordPress dependencies
*/
import { select } from '@wordpress/data';
import { createBlock } from '@wordpress/blocks';
/**
* Internal dependencies
*/
import BlockIcon from '../components/block-icon';
/** @typedef {import('@wordpress/block-editor').WPEditorInserterItem} WPEditorInserterItem */
/** @typedef {import('@wordpress/components').WPCompleter} WPCompleter */
/**
* Returns the client ID of the parent where a newly inserted block would be
* placed.
*
* @return {string} Client ID of the parent where a newly inserted block would
* be placed.
*/
function defaultGetBlockInsertionParentClientId() {
return select( 'core/block-editor' ).getBlockInsertionPoint().rootClientId;
}
/**
* Returns the inserter items for the specified parent block.
*
* @param {string} rootClientId Client ID of the block for which to retrieve
* inserter items.
*
* @return {Array<WPEditorInserterItem>} The inserter items for the specified
* parent.
*/
function defaultGetInserterItems( rootClientId ) {
return select( 'core/block-editor' ).getInserterItems( rootClientId );
}
/**
* Returns the name of the currently selected block.
*
* @return {string?} The name of the currently selected block or `null` if no
* block is selected.
*/
function defaultGetSelectedBlockName() {
const { getSelectedBlockClientId, getBlockName } = select(
'core/block-editor'
);
const selectedBlockClientId = getSelectedBlockClientId();
return selectedBlockClientId ? getBlockName( selectedBlockClientId ) : null;
}
/**
* Triggers a fetch of reusable blocks, once.
*
* TODO: Reusable blocks fetching should be reimplemented as a core-data entity
* resolver, not relying on `core/editor` (see #7119). The implementation here
* is imperfect in that the options result will not await the completion of the
* fetch request and thus will not include any reusable blocks. This has always
* been true, but relied upon the fact the user would be delayed in typing an
* autocompleter search query. Once implemented using resolvers, the status of
* this request could be subscribed to as part of a promised return value using
* the result of `hasFinishedResolution`. There is currently reliable way to
* determine that a reusable blocks fetch request has completed.
*
* @return {Promise} Promise resolving once reusable blocks fetched.
*/
const fetchReusableBlocks = once( () => {
const { __experimentalFetchReusableBlocks } = select(
'core/block-editor'
).getSettings();
if ( __experimentalFetchReusableBlocks ) {
__experimentalFetchReusableBlocks();
}
} );
/**
* Creates a blocks repeater for replacing the current block with a selected block type.
*
* @return {WPCompleter} A blocks completer.
*/
export function createBlockCompleter( {
// Allow store-based selectors to be overridden for unit test.
getBlockInsertionParentClientId = defaultGetBlockInsertionParentClientId,
getInserterItems = defaultGetInserterItems,
getSelectedBlockName = defaultGetSelectedBlockName,
} = {} ) {
return {
name: 'blocks',
className: 'block-editor-autocompleters__block',
triggerPrefix: '/',
options() {
fetchReusableBlocks();
const selectedBlockName = getSelectedBlockName();
return getInserterItems( getBlockInsertionParentClientId() ).filter(
// Avoid offering to replace the current block with a block of the same type.
( inserterItem ) => selectedBlockName !== inserterItem.name
);
},
getOptionKeywords( inserterItem ) {
const { title, keywords = [], category } = inserterItem;
return [ category, ...keywords, title ];
},
getOptionLabel( inserterItem ) {
const { icon, title } = inserterItem;
return [ <BlockIcon key="icon" icon={ icon } showColors />, title ];
},
allowContext( before, after ) {
return ! ( /\S/.test( before ) || /\S/.test( after ) );
},
getOptionCompletion( inserterItem ) {
const { name, initialAttributes } = inserterItem;
return {
action: 'replace',
value: createBlock( name, initialAttributes ),
};
},
isOptionDisabled( inserterItem ) {
return inserterItem.isDisabled;
},
};
}
/**
* Creates a blocks repeater for replacing the current block with a selected block type.
*
* @return {WPCompleter} A blocks completer.
*/
export default createBlockCompleter();