@wordpress/commands 0.9.0 → 0.11.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/CHANGELOG.md +4 -0
- package/build/components/command-menu.js +67 -46
- package/build/components/command-menu.js.map +1 -1
- package/build/hooks/use-command-context.js +3 -7
- package/build/hooks/use-command-context.js.map +1 -1
- package/build/hooks/use-command-loader.js +0 -4
- package/build/hooks/use-command-loader.js.map +1 -1
- package/build/hooks/use-command.js +0 -4
- package/build/hooks/use-command.js.map +1 -1
- package/build/index.js +0 -6
- package/build/index.js.map +1 -1
- package/build/lock-unlock.js +1 -2
- package/build/lock-unlock.js.map +1 -1
- package/build/private-apis.js +1 -4
- package/build/private-apis.js.map +1 -1
- package/build/store/actions.js +5 -11
- package/build/store/actions.js.map +1 -1
- package/build/store/index.js +2 -11
- package/build/store/index.js.map +1 -1
- package/build/store/private-actions.js +0 -1
- package/build/store/private-actions.js.map +1 -1
- package/build/store/reducer.js +7 -18
- package/build/store/reducer.js.map +1 -1
- package/build/store/selectors.js +33 -4
- package/build/store/selectors.js.map +1 -1
- package/build-module/components/command-menu.js +70 -42
- package/build-module/components/command-menu.js.map +1 -1
- package/build-module/hooks/use-command-context.js +5 -4
- package/build-module/hooks/use-command-context.js.map +1 -1
- package/build-module/hooks/use-command-loader.js +2 -2
- package/build-module/hooks/use-command-loader.js.map +1 -1
- package/build-module/hooks/use-command.js +2 -2
- package/build-module/hooks/use-command.js.map +1 -1
- package/build-module/index.js.map +1 -1
- package/build-module/lock-unlock.js.map +1 -1
- package/build-module/private-apis.js.map +1 -1
- package/build-module/store/actions.js +5 -5
- package/build-module/store/actions.js.map +1 -1
- package/build-module/store/index.js +2 -2
- package/build-module/store/index.js.map +1 -1
- package/build-module/store/private-actions.js.map +1 -1
- package/build-module/store/reducer.js +8 -17
- package/build-module/store/reducer.js.map +1 -1
- package/build-module/store/selectors.js +34 -0
- package/build-module/store/selectors.js.map +1 -1
- package/build-style/style-rtl.css +36 -18
- package/build-style/style.css +36 -18
- package/package.json +12 -10
- package/src/components/command-menu.js +78 -22
- package/src/components/style.scss +38 -19
- package/src/store/selectors.js +30 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/commands",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Handles the commands menu.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -27,21 +27,23 @@
|
|
|
27
27
|
"react-native": "src/index",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@babel/runtime": "^7.16.0",
|
|
30
|
-
"@wordpress/components": "^25.
|
|
31
|
-
"@wordpress/data": "^9.
|
|
32
|
-
"@wordpress/element": "^5.
|
|
33
|
-
"@wordpress/i18n": "^4.
|
|
34
|
-
"@wordpress/icons": "^9.
|
|
35
|
-
"@wordpress/keyboard-shortcuts": "^4.
|
|
36
|
-
"@wordpress/private-apis": "^0.
|
|
30
|
+
"@wordpress/components": "^25.6.0",
|
|
31
|
+
"@wordpress/data": "^9.10.0",
|
|
32
|
+
"@wordpress/element": "^5.17.0",
|
|
33
|
+
"@wordpress/i18n": "^4.40.0",
|
|
34
|
+
"@wordpress/icons": "^9.31.0",
|
|
35
|
+
"@wordpress/keyboard-shortcuts": "^4.17.0",
|
|
36
|
+
"@wordpress/private-apis": "^0.22.0",
|
|
37
|
+
"classnames": "^2.3.1",
|
|
37
38
|
"cmdk": "^0.2.0",
|
|
38
39
|
"rememo": "^4.0.2"
|
|
39
40
|
},
|
|
40
41
|
"peerDependencies": {
|
|
41
|
-
"react": "^18.0.0"
|
|
42
|
+
"react": "^18.0.0",
|
|
43
|
+
"react-dom": "^18.0.0"
|
|
42
44
|
},
|
|
43
45
|
"publishConfig": {
|
|
44
46
|
"access": "public"
|
|
45
47
|
},
|
|
46
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "78a288d55b83a713b2f7d98d5a855c0771a2afc6"
|
|
47
49
|
}
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { Command } from 'cmdk';
|
|
4
|
+
import { Command, useCommandState } from 'cmdk';
|
|
5
|
+
import classnames from 'classnames';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* WordPress dependencies
|
|
8
9
|
*/
|
|
9
10
|
import { useSelect, useDispatch } from '@wordpress/data';
|
|
10
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
useState,
|
|
13
|
+
useEffect,
|
|
14
|
+
useRef,
|
|
15
|
+
useCallback,
|
|
16
|
+
useMemo,
|
|
17
|
+
} from '@wordpress/element';
|
|
11
18
|
import { __ } from '@wordpress/i18n';
|
|
12
19
|
import {
|
|
13
20
|
Modal,
|
|
@@ -18,7 +25,7 @@ import {
|
|
|
18
25
|
store as keyboardShortcutsStore,
|
|
19
26
|
useShortcut,
|
|
20
27
|
} from '@wordpress/keyboard-shortcuts';
|
|
21
|
-
import { Icon } from '@wordpress/icons';
|
|
28
|
+
import { Icon, search as inputIcon } from '@wordpress/icons';
|
|
22
29
|
|
|
23
30
|
/**
|
|
24
31
|
* Internal dependencies
|
|
@@ -43,12 +50,18 @@ function CommandMenuLoader( { name, search, hook, setLoader, close } ) {
|
|
|
43
50
|
key={ command.name }
|
|
44
51
|
value={ command.searchLabel ?? command.label }
|
|
45
52
|
onSelect={ () => command.callback( { close } ) }
|
|
53
|
+
id={ command.name }
|
|
46
54
|
>
|
|
47
55
|
<HStack
|
|
48
56
|
alignment="left"
|
|
49
|
-
className=
|
|
57
|
+
className={ classnames(
|
|
58
|
+
'commands-command-menu__item',
|
|
59
|
+
{
|
|
60
|
+
'has-icon': command.icon,
|
|
61
|
+
}
|
|
62
|
+
) }
|
|
50
63
|
>
|
|
51
|
-
<Icon icon={ command.icon } />
|
|
64
|
+
{ command.icon && <Icon icon={ command.icon } /> }
|
|
52
65
|
<span>
|
|
53
66
|
<TextHighlight
|
|
54
67
|
text={ command.label }
|
|
@@ -112,12 +125,15 @@ export function CommandMenuGroup( { isContextual, search, setLoader, close } ) {
|
|
|
112
125
|
key={ command.name }
|
|
113
126
|
value={ command.searchLabel ?? command.label }
|
|
114
127
|
onSelect={ () => command.callback( { close } ) }
|
|
128
|
+
id={ command.name }
|
|
115
129
|
>
|
|
116
130
|
<HStack
|
|
117
131
|
alignment="left"
|
|
118
|
-
className=
|
|
132
|
+
className={ classnames( 'commands-command-menu__item', {
|
|
133
|
+
'has-icon': command.icon,
|
|
134
|
+
} ) }
|
|
119
135
|
>
|
|
120
|
-
<Icon icon={ command.icon } />
|
|
136
|
+
{ command.icon && <Icon icon={ command.icon } /> }
|
|
121
137
|
<span>
|
|
122
138
|
<TextHighlight
|
|
123
139
|
text={ command.label }
|
|
@@ -140,6 +156,33 @@ export function CommandMenuGroup( { isContextual, search, setLoader, close } ) {
|
|
|
140
156
|
);
|
|
141
157
|
}
|
|
142
158
|
|
|
159
|
+
function CommandInput( { isOpen, search, setSearch } ) {
|
|
160
|
+
const commandMenuInput = useRef();
|
|
161
|
+
const _value = useCommandState( ( state ) => state.value );
|
|
162
|
+
const selectedItemId = useMemo( () => {
|
|
163
|
+
const item = document.querySelector(
|
|
164
|
+
`[cmdk-item=""][data-value="${ _value }"]`
|
|
165
|
+
);
|
|
166
|
+
return item?.getAttribute( 'id' );
|
|
167
|
+
}, [ _value ] );
|
|
168
|
+
useEffect( () => {
|
|
169
|
+
// Focus the command palette input when mounting the modal.
|
|
170
|
+
if ( isOpen ) {
|
|
171
|
+
commandMenuInput.current.focus();
|
|
172
|
+
}
|
|
173
|
+
}, [ isOpen ] );
|
|
174
|
+
return (
|
|
175
|
+
<Command.Input
|
|
176
|
+
ref={ commandMenuInput }
|
|
177
|
+
value={ search }
|
|
178
|
+
onValueChange={ setSearch }
|
|
179
|
+
placeholder={ __( 'Search for commands' ) }
|
|
180
|
+
aria-activedescendant={ selectedItemId }
|
|
181
|
+
icon={ search }
|
|
182
|
+
/>
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
143
186
|
export function CommandMenu() {
|
|
144
187
|
const { registerShortcut } = useDispatch( keyboardShortcutsStore );
|
|
145
188
|
const [ search, setSearch ] = useState( '' );
|
|
@@ -149,13 +192,12 @@ export function CommandMenu() {
|
|
|
149
192
|
);
|
|
150
193
|
const { open, close } = useDispatch( commandsStore );
|
|
151
194
|
const [ loaders, setLoaders ] = useState( {} );
|
|
152
|
-
const commandMenuInput = useRef();
|
|
153
195
|
|
|
154
196
|
useEffect( () => {
|
|
155
197
|
registerShortcut( {
|
|
156
198
|
name: 'core/commands',
|
|
157
199
|
category: 'global',
|
|
158
|
-
description: __( 'Open the command palette' ),
|
|
200
|
+
description: __( 'Open the command palette.' ),
|
|
159
201
|
keyCombination: {
|
|
160
202
|
modifier: 'primary',
|
|
161
203
|
character: 'k',
|
|
@@ -165,7 +207,11 @@ export function CommandMenu() {
|
|
|
165
207
|
|
|
166
208
|
useShortcut(
|
|
167
209
|
'core/commands',
|
|
210
|
+
/** @type {import('react').KeyboardEventHandler} */
|
|
168
211
|
( event ) => {
|
|
212
|
+
// Bails to avoid obscuring the effect of the preceding handler(s).
|
|
213
|
+
if ( event.defaultPrevented ) return;
|
|
214
|
+
|
|
169
215
|
event.preventDefault();
|
|
170
216
|
if ( isOpen ) {
|
|
171
217
|
close();
|
|
@@ -191,16 +237,23 @@ export function CommandMenu() {
|
|
|
191
237
|
close();
|
|
192
238
|
};
|
|
193
239
|
|
|
194
|
-
useEffect( () => {
|
|
195
|
-
// Focus the command palette input when mounting the modal.
|
|
196
|
-
if ( isOpen ) {
|
|
197
|
-
commandMenuInput.current.focus();
|
|
198
|
-
}
|
|
199
|
-
}, [ isOpen ] );
|
|
200
|
-
|
|
201
240
|
if ( ! isOpen ) {
|
|
202
241
|
return false;
|
|
203
242
|
}
|
|
243
|
+
|
|
244
|
+
const onKeyDown = ( event ) => {
|
|
245
|
+
if (
|
|
246
|
+
// Ignore keydowns from IMEs
|
|
247
|
+
event.nativeEvent.isComposing ||
|
|
248
|
+
// Workaround for Mac Safari where the final Enter/Backspace of an IME composition
|
|
249
|
+
// is `isComposing=false`, even though it's technically still part of the composition.
|
|
250
|
+
// These can only be detected by keyCode.
|
|
251
|
+
event.keyCode === 229
|
|
252
|
+
) {
|
|
253
|
+
event.preventDefault();
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
|
|
204
257
|
const isLoading = Object.values( loaders ).some( Boolean );
|
|
205
258
|
|
|
206
259
|
return (
|
|
@@ -211,13 +264,16 @@ export function CommandMenu() {
|
|
|
211
264
|
__experimentalHideHeader
|
|
212
265
|
>
|
|
213
266
|
<div className="commands-command-menu__container">
|
|
214
|
-
<Command
|
|
267
|
+
<Command
|
|
268
|
+
label={ __( 'Command palette' ) }
|
|
269
|
+
onKeyDown={ onKeyDown }
|
|
270
|
+
>
|
|
215
271
|
<div className="commands-command-menu__header">
|
|
216
|
-
<
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
272
|
+
<Icon icon={ inputIcon } />
|
|
273
|
+
<CommandInput
|
|
274
|
+
search={ search }
|
|
275
|
+
setSearch={ setSearch }
|
|
276
|
+
isOpen={ isOpen }
|
|
221
277
|
/>
|
|
222
278
|
</div>
|
|
223
279
|
<Command.List>
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
// dirty hack to clean up modal
|
|
2
2
|
.commands-command-menu {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
border-radius: $grid-unit-05;
|
|
4
|
+
width: calc(100% - #{$grid-unit-40});
|
|
5
|
+
margin: auto;
|
|
6
|
+
max-width: 420px;
|
|
5
7
|
position: relative;
|
|
6
|
-
top: 15
|
|
8
|
+
top: calc(15% + #{$header-height});
|
|
9
|
+
|
|
10
|
+
@include break-small() {
|
|
11
|
+
top: 15%;
|
|
12
|
+
}
|
|
7
13
|
|
|
8
14
|
.components-modal__content {
|
|
9
15
|
margin: 0;
|
|
@@ -19,6 +25,7 @@
|
|
|
19
25
|
.commands-command-menu__header {
|
|
20
26
|
display: flex;
|
|
21
27
|
align-items: center;
|
|
28
|
+
padding-left: $grid-unit-20;
|
|
22
29
|
|
|
23
30
|
.components-button {
|
|
24
31
|
height: $grid-unit-70;
|
|
@@ -42,33 +49,32 @@
|
|
|
42
49
|
[cmdk-input] {
|
|
43
50
|
border: none;
|
|
44
51
|
width: 100%;
|
|
45
|
-
padding: $grid-unit-20;
|
|
52
|
+
padding: $grid-unit-20 $grid-unit-20 $grid-unit-20 $grid-unit-10;
|
|
46
53
|
outline: none;
|
|
47
54
|
color: $gray-900;
|
|
48
55
|
margin: 0;
|
|
49
|
-
font-size:
|
|
56
|
+
font-size: 16px;
|
|
50
57
|
line-height: 28px;
|
|
51
|
-
border-bottom: 1px solid $gray-200;
|
|
52
58
|
border-radius: 0;
|
|
53
59
|
|
|
54
60
|
&::placeholder {
|
|
55
|
-
color: $gray-
|
|
61
|
+
color: $gray-700;
|
|
56
62
|
}
|
|
57
63
|
|
|
58
64
|
&:focus {
|
|
59
65
|
box-shadow: none;
|
|
60
66
|
outline: none;
|
|
61
|
-
border-bottom: 1px solid $gray-200;
|
|
62
67
|
}
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
[cmdk-item] {
|
|
66
|
-
border-radius: $
|
|
71
|
+
border-radius: $radius-block-ui;
|
|
67
72
|
cursor: pointer;
|
|
68
73
|
display: flex;
|
|
69
74
|
align-items: center;
|
|
70
|
-
padding: $grid-unit;
|
|
71
75
|
color: $gray-900;
|
|
76
|
+
font-size: $default-font-size;
|
|
77
|
+
min-height: $button-size-next-default-40px;
|
|
72
78
|
|
|
73
79
|
&[aria-selected="true"],
|
|
74
80
|
&:active {
|
|
@@ -86,16 +92,25 @@
|
|
|
86
92
|
}
|
|
87
93
|
|
|
88
94
|
svg {
|
|
89
|
-
fill: $gray-
|
|
95
|
+
fill: $gray-900;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
> div {
|
|
99
|
+
padding: $grid-unit;
|
|
100
|
+
padding-left: $grid-unit-50; // Account for commands without icons.
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
> .has-icon {
|
|
104
|
+
padding-left: $grid-unit;
|
|
90
105
|
}
|
|
91
106
|
}
|
|
92
107
|
|
|
93
108
|
[cmdk-root] > [cmdk-list] {
|
|
94
|
-
max-height:
|
|
109
|
+
max-height: 368px; // Specific to not have commands overflow oddly.
|
|
95
110
|
overflow: auto;
|
|
96
111
|
|
|
97
|
-
&
|
|
98
|
-
padding: $grid-unit;
|
|
112
|
+
& [cmdk-list-sizer] > [cmdk-group] > [cmdk-group-items]:not(:empty) {
|
|
113
|
+
padding: 0 $grid-unit $grid-unit;
|
|
99
114
|
}
|
|
100
115
|
}
|
|
101
116
|
|
|
@@ -103,9 +118,9 @@
|
|
|
103
118
|
display: flex;
|
|
104
119
|
align-items: center;
|
|
105
120
|
justify-content: center;
|
|
106
|
-
height: $grid-unit-80;
|
|
107
121
|
white-space: pre-wrap;
|
|
108
|
-
color: $gray-
|
|
122
|
+
color: $gray-900;
|
|
123
|
+
padding: $grid-unit-10 0 $grid-unit-40;
|
|
109
124
|
}
|
|
110
125
|
|
|
111
126
|
[cmdk-loading] {
|
|
@@ -115,10 +130,14 @@
|
|
|
115
130
|
[cmdk-list-sizer] {
|
|
116
131
|
position: relative;
|
|
117
132
|
}
|
|
133
|
+
}
|
|
118
134
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
135
|
+
.commands-command-menu__item span {
|
|
136
|
+
// Ensure commands do not run off the edge (great for post titles).
|
|
137
|
+
display: inline-block;
|
|
138
|
+
overflow: hidden;
|
|
139
|
+
text-overflow: ellipsis;
|
|
140
|
+
white-space: nowrap;
|
|
122
141
|
}
|
|
123
142
|
|
|
124
143
|
.commands-command-menu__item mark {
|
package/src/store/selectors.js
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import createSelector from 'rememo';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Returns the registered static commands.
|
|
8
|
+
*
|
|
9
|
+
* @param {Object} state State tree.
|
|
10
|
+
* @param {boolean} contextual Whether to return only contextual commands.
|
|
11
|
+
*
|
|
12
|
+
* @return {import('./actions').WPCommandConfig[]} The list of registered commands.
|
|
13
|
+
*/
|
|
6
14
|
export const getCommands = createSelector(
|
|
7
15
|
( state, contextual = false ) =>
|
|
8
16
|
Object.values( state.commands ).filter( ( command ) => {
|
|
@@ -13,6 +21,14 @@ export const getCommands = createSelector(
|
|
|
13
21
|
( state ) => [ state.commands, state.context ]
|
|
14
22
|
);
|
|
15
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Returns the registered command loaders.
|
|
26
|
+
*
|
|
27
|
+
* @param {Object} state State tree.
|
|
28
|
+
* @param {boolean} contextual Whether to return only contextual command loaders.
|
|
29
|
+
*
|
|
30
|
+
* @return {import('./actions').WPCommandLoaderConfig[]} The list of registered command loaders.
|
|
31
|
+
*/
|
|
16
32
|
export const getCommandLoaders = createSelector(
|
|
17
33
|
( state, contextual = false ) =>
|
|
18
34
|
Object.values( state.commandLoaders ).filter( ( loader ) => {
|
|
@@ -23,10 +39,24 @@ export const getCommandLoaders = createSelector(
|
|
|
23
39
|
( state ) => [ state.commandLoaders, state.context ]
|
|
24
40
|
);
|
|
25
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Returns whether the command palette is open.
|
|
44
|
+
*
|
|
45
|
+
* @param {Object} state State tree.
|
|
46
|
+
*
|
|
47
|
+
* @return {boolean} Returns whether the command palette is open.
|
|
48
|
+
*/
|
|
26
49
|
export function isOpen( state ) {
|
|
27
50
|
return state.isOpen;
|
|
28
51
|
}
|
|
29
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Returns whether the active context.
|
|
55
|
+
*
|
|
56
|
+
* @param {Object} state State tree.
|
|
57
|
+
*
|
|
58
|
+
* @return {string} Context.
|
|
59
|
+
*/
|
|
30
60
|
export function getContext( state ) {
|
|
31
61
|
return state.context;
|
|
32
62
|
}
|