@wordpress/commands 1.55.0 → 1.56.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 +6 -0
- package/README.md +24 -22
- package/build/hooks/use-command-loader.cjs +10 -2
- package/build/hooks/use-command-loader.cjs.map +2 -2
- package/build-module/hooks/use-command-loader.mjs +11 -3
- package/build-module/hooks/use-command-loader.mjs.map +2 -2
- package/package.json +13 -14
- package/src/hooks/use-command-loader.js +18 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 1.56.0 (2026-09-23)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- `useCommandLoader`: stop unregistering and re-registering the loader when the `hook` option changes identity between renders ([#82819](https://github.com/WordPress/gutenberg/pull/82819)).
|
|
10
|
+
|
|
5
11
|
## 1.55.0 (2026-09-10)
|
|
6
12
|
|
|
7
13
|
### Internal
|
package/README.md
CHANGED
|
@@ -6,13 +6,13 @@ Commands is a generic package that allows registering and modifying commands to
|
|
|
6
6
|
|
|
7
7
|
There are two ways to register commands: static or dynamic. Both methods receive a command object as an argument, which provides:
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
9
|
+
- `name`: A unique machine-readable name for the command
|
|
10
|
+
- `label`: A human-readable label
|
|
11
|
+
- `icon`: An SVG icon
|
|
12
|
+
- `callback`: A callback function that is called when the command is selected
|
|
13
|
+
- `category`: (Optional) The category of the command. See [Command categories](#command-categories) below
|
|
14
|
+
- `context`: (Optional) The context of the command
|
|
15
|
+
- `keywords`: (Optional) An array of keywords for search matching
|
|
16
16
|
|
|
17
17
|
### Static commands
|
|
18
18
|
|
|
@@ -30,9 +30,9 @@ Static and dynamic commands can be contextual. This means that in a given contex
|
|
|
30
30
|
|
|
31
31
|
At the moment, three contexts have been implemented:
|
|
32
32
|
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
33
|
+
- `site-editor`: This is the context that is set when you are navigating in the site editor (sidebar visible).
|
|
34
|
+
- `entity-edit`: This is the context that is set when you are editing a document (template, template part or page).
|
|
35
|
+
- `block-selection-edit`: This is the context that is set when a block is selected.
|
|
36
36
|
|
|
37
37
|
As the usage of the Command Palette expands, more contexts will be added.
|
|
38
38
|
|
|
@@ -42,10 +42,10 @@ Attaching a command or command loader to a given context is as simple as adding
|
|
|
42
42
|
|
|
43
43
|
Each command can be assigned a `category` that describes what kind of action it performs. Categories are used by the Command Palette to visually differentiate commands. The following categories are available:
|
|
44
44
|
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
45
|
+
- `command`: Executes code or toggles a command (e.g., Add block, duplicating a block).
|
|
46
|
+
- `view`: Navigates to an area in the admin or opens a panel (e.g., "Go to: Templates").
|
|
47
|
+
- `edit`: Navigates to edit a document (e.g., editing a template, editing a page).
|
|
48
|
+
- `action`: A generic fallback for commands that don't fit the other categories. This is also the default when an invalid category is provided.
|
|
49
49
|
|
|
50
50
|
If no `category` is specified, the command will have `action` set. If an invalid value is provided, a warning is emitted in development mode and the category defaults to `action`.
|
|
51
51
|
|
|
@@ -55,9 +55,9 @@ A category can also supply a fallback icon, used when the command passes no `ico
|
|
|
55
55
|
|
|
56
56
|
The Command Palette also offers a number of [selectors and actions](https://developer.wordpress.org/block-editor/reference-guides/data/data-core-commands/) to manipulate its state, which include:
|
|
57
57
|
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
58
|
+
- Retrieving the registered commands and command loaders using the following selectors `getCommands` and `getCommandLoader`
|
|
59
|
+
- Checking if the Command Palette is open using the `isOpen` selector.
|
|
60
|
+
- Programmatically open or close the Command Palette using the `open` and `close` actions.
|
|
61
61
|
|
|
62
62
|
See the [Commands Data](https://developer.wordpress.org/block-editor/reference-guides/data/data-core-commands/) documentation for more information.
|
|
63
63
|
|
|
@@ -89,7 +89,7 @@ Store definition for the commands namespace.
|
|
|
89
89
|
|
|
90
90
|
_Related_
|
|
91
91
|
|
|
92
|
-
-
|
|
92
|
+
- <https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore>
|
|
93
93
|
|
|
94
94
|
_Usage_
|
|
95
95
|
|
|
@@ -102,7 +102,7 @@ const { open: openCommandCenter } = useDispatch( commandsStore );
|
|
|
102
102
|
|
|
103
103
|
_Type_
|
|
104
104
|
|
|
105
|
-
-
|
|
105
|
+
- `Object`
|
|
106
106
|
|
|
107
107
|
### useCommand
|
|
108
108
|
|
|
@@ -128,12 +128,14 @@ useCommand( {
|
|
|
128
128
|
|
|
129
129
|
_Parameters_
|
|
130
130
|
|
|
131
|
-
-
|
|
131
|
+
- _command_ `import('../store/actions').WPCommandConfig`: command config.
|
|
132
132
|
|
|
133
133
|
### useCommandLoader
|
|
134
134
|
|
|
135
135
|
Attach a command loader to the command palette. Used for dynamic commands.
|
|
136
136
|
|
|
137
|
+
The palette always calls the most recent `hook`. Changing the `hook` instance doesn't re-render the palette.
|
|
138
|
+
|
|
137
139
|
_Usage_
|
|
138
140
|
|
|
139
141
|
```js
|
|
@@ -202,7 +204,7 @@ useCommandLoader( {
|
|
|
202
204
|
|
|
203
205
|
_Parameters_
|
|
204
206
|
|
|
205
|
-
-
|
|
207
|
+
- _loader_ `import('../store/actions').WPCommandLoaderConfig`: command loader config.
|
|
206
208
|
|
|
207
209
|
### useCommands
|
|
208
210
|
|
|
@@ -240,7 +242,7 @@ useCommands( [
|
|
|
240
242
|
|
|
241
243
|
_Parameters_
|
|
242
244
|
|
|
243
|
-
-
|
|
245
|
+
- _commands_ `import('../store/actions').WPCommandConfig[]`: Array of command configs.
|
|
244
246
|
|
|
245
247
|
<!-- END TOKEN(Autogenerated API docs) -->
|
|
246
248
|
|
|
@@ -27,13 +27,21 @@ var import_data = require("@wordpress/data");
|
|
|
27
27
|
var import_store = require("../store/index.cjs");
|
|
28
28
|
function useCommandLoader(loader) {
|
|
29
29
|
const { registerCommandLoader, unregisterCommandLoader } = (0, import_data.useDispatch)(import_store.store);
|
|
30
|
+
const currentHookRef = (0, import_element.useRef)(loader.hook);
|
|
31
|
+
(0, import_element.useEffect)(() => {
|
|
32
|
+
currentHookRef.current = loader.hook;
|
|
33
|
+
}, [loader.hook]);
|
|
34
|
+
const hook = (0, import_element.useCallback)(
|
|
35
|
+
(...args) => currentHookRef.current(...args),
|
|
36
|
+
[]
|
|
37
|
+
);
|
|
30
38
|
(0, import_element.useEffect)(() => {
|
|
31
39
|
if (loader.disabled) {
|
|
32
40
|
return;
|
|
33
41
|
}
|
|
34
42
|
registerCommandLoader({
|
|
35
43
|
name: loader.name,
|
|
36
|
-
hook
|
|
44
|
+
hook,
|
|
37
45
|
context: loader.context,
|
|
38
46
|
category: loader.category
|
|
39
47
|
});
|
|
@@ -42,7 +50,7 @@ function useCommandLoader(loader) {
|
|
|
42
50
|
};
|
|
43
51
|
}, [
|
|
44
52
|
loader.name,
|
|
45
|
-
|
|
53
|
+
hook,
|
|
46
54
|
loader.context,
|
|
47
55
|
loader.category,
|
|
48
56
|
loader.disabled,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/hooks/use-command-loader.js"],
|
|
4
|
-
"sourcesContent": ["import { useEffect } from '@wordpress/element';\nimport { useDispatch } from '@wordpress/data';\nimport { store as commandsStore } from '../store';\n\n/**\n * Attach a command loader to the command palette. Used for dynamic commands.\n *\n * @param {import('../store/actions').WPCommandLoaderConfig} loader command loader config.\n *\n * @example\n * ```js\n * import { __ } from '@wordpress/i18n';\n * import { addQueryArgs } from '@wordpress/url';\n * import { useCommandLoader } from '@wordpress/commands';\n * import { page } from '@wordpress/icons';\n * import { useSelect } from '@wordpress/data';\n * import { store as coreStore } from '@wordpress/core-data';\n * import { useMemo } from '@wordpress/element';\n *\n * function usePageSearchCommandLoader( { search } ) {\n * // Retrieve the pages for the \"search\" term.\n * const { records, isLoading } = useSelect(\n * ( select ) => {\n * const { getEntityRecords } = select( coreStore );\n * const query = {\n * search: !! search ? search : undefined,\n * per_page: 10,\n * orderby: search ? 'relevance' : 'date',\n * };\n * return {\n * records: getEntityRecords( 'postType', 'page', query ),\n * isLoading: ! select( coreStore ).hasFinishedResolution(\n * 'getEntityRecords',\n * [ 'postType', 'page', query ]\n * ),\n * };\n * },\n * [ search ]\n * );\n *\n * // Create the commands.\n * const commands = useMemo( () => {\n * return ( records ?? [] ).slice( 0, 10 ).map( ( record ) => {\n * return {\n * name: record.title?.rendered + ' ' + record.id,\n * label: record.title?.rendered\n * ? record.title?.rendered\n * : __( '(no title)' ),\n * icon: page,\n * category: 'edit',\n * callback: ( { close } ) => {\n * const args = {\n * \t\t\t\t\t\t\tp: '/page',\n * \t\t\t\t\t\t\tpostId: record.id,\n * };\n * document.location = addQueryArgs( 'site-editor.php', args );\n * close();\n * },\n * };\n * } );\n * }, [ records ] );\n *\n * return {\n * commands,\n * isLoading,\n * };\n * }\n *\n * useCommandLoader( {\n * name: 'myplugin/page-search',\n * hook: usePageSearchCommandLoader,\n * } );\n * ```\n */\nexport default function useCommandLoader( loader ) {\n\tconst { registerCommandLoader, unregisterCommandLoader } =\n\t\tuseDispatch( commandsStore );\n\tuseEffect( () => {\n\t\tif ( loader.disabled ) {\n\t\t\treturn;\n\t\t}\n\t\tregisterCommandLoader( {\n\t\t\tname: loader.name,\n\t\t\thook
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,
|
|
4
|
+
"sourcesContent": ["import { useCallback, useEffect, useRef } from '@wordpress/element';\nimport { useDispatch } from '@wordpress/data';\nimport { store as commandsStore } from '../store';\n\n/**\n * Attach a command loader to the command palette. Used for dynamic commands.\n *\n * The palette always calls the most recent `hook`. Changing the `hook` instance\n * doesn't re-render the palette.\n *\n * @param {import('../store/actions').WPCommandLoaderConfig} loader command loader config.\n *\n * @example\n * ```js\n * import { __ } from '@wordpress/i18n';\n * import { addQueryArgs } from '@wordpress/url';\n * import { useCommandLoader } from '@wordpress/commands';\n * import { page } from '@wordpress/icons';\n * import { useSelect } from '@wordpress/data';\n * import { store as coreStore } from '@wordpress/core-data';\n * import { useMemo } from '@wordpress/element';\n *\n * function usePageSearchCommandLoader( { search } ) {\n * // Retrieve the pages for the \"search\" term.\n * const { records, isLoading } = useSelect(\n * ( select ) => {\n * const { getEntityRecords } = select( coreStore );\n * const query = {\n * search: !! search ? search : undefined,\n * per_page: 10,\n * orderby: search ? 'relevance' : 'date',\n * };\n * return {\n * records: getEntityRecords( 'postType', 'page', query ),\n * isLoading: ! select( coreStore ).hasFinishedResolution(\n * 'getEntityRecords',\n * [ 'postType', 'page', query ]\n * ),\n * };\n * },\n * [ search ]\n * );\n *\n * // Create the commands.\n * const commands = useMemo( () => {\n * return ( records ?? [] ).slice( 0, 10 ).map( ( record ) => {\n * return {\n * name: record.title?.rendered + ' ' + record.id,\n * label: record.title?.rendered\n * ? record.title?.rendered\n * : __( '(no title)' ),\n * icon: page,\n * category: 'edit',\n * callback: ( { close } ) => {\n * const args = {\n * \t\t\t\t\t\t\tp: '/page',\n * \t\t\t\t\t\t\tpostId: record.id,\n * };\n * document.location = addQueryArgs( 'site-editor.php', args );\n * close();\n * },\n * };\n * } );\n * }, [ records ] );\n *\n * return {\n * commands,\n * isLoading,\n * };\n * }\n *\n * useCommandLoader( {\n * name: 'myplugin/page-search',\n * hook: usePageSearchCommandLoader,\n * } );\n * ```\n */\nexport default function useCommandLoader( loader ) {\n\tconst { registerCommandLoader, unregisterCommandLoader } =\n\t\tuseDispatch( commandsStore );\n\tconst currentHookRef = useRef( loader.hook );\n\tuseEffect( () => {\n\t\tcurrentHookRef.current = loader.hook;\n\t}, [ loader.hook ] );\n\n\t// Stable identity, so a hook rebuilt on every render does not re-register\n\t// the loader.\n\tconst hook = useCallback(\n\t\t( ...args ) => currentHookRef.current( ...args ),\n\t\t[]\n\t);\n\n\tuseEffect( () => {\n\t\tif ( loader.disabled ) {\n\t\t\treturn;\n\t\t}\n\t\tregisterCommandLoader( {\n\t\t\tname: loader.name,\n\t\t\thook,\n\t\t\tcontext: loader.context,\n\t\t\tcategory: loader.category,\n\t\t} );\n\t\treturn () => {\n\t\t\tunregisterCommandLoader( loader.name );\n\t\t};\n\t}, [\n\t\tloader.name,\n\t\thook,\n\t\tloader.context,\n\t\tloader.category,\n\t\tloader.disabled,\n\t\tregisterCommandLoader,\n\t\tunregisterCommandLoader,\n\t] );\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAA+C;AAC/C,kBAA4B;AAC5B,mBAAuC;AA2ExB,SAAR,iBAAmC,QAAS;AAClD,QAAM,EAAE,uBAAuB,wBAAwB,QACtD,yBAAa,aAAAA,KAAc;AAC5B,QAAM,qBAAiB,uBAAQ,OAAO,IAAK;AAC3C,gCAAW,MAAM;AAChB,mBAAe,UAAU,OAAO;AAAA,EACjC,GAAG,CAAE,OAAO,IAAK,CAAE;AAInB,QAAM,WAAO;AAAA,IACZ,IAAK,SAAU,eAAe,QAAS,GAAG,IAAK;AAAA,IAC/C,CAAC;AAAA,EACF;AAEA,gCAAW,MAAM;AAChB,QAAK,OAAO,UAAW;AACtB;AAAA,IACD;AACA,0BAAuB;AAAA,MACtB,MAAM,OAAO;AAAA,MACb;AAAA,MACA,SAAS,OAAO;AAAA,MAChB,UAAU,OAAO;AAAA,IAClB,CAAE;AACF,WAAO,MAAM;AACZ,8BAAyB,OAAO,IAAK;AAAA,IACtC;AAAA,EACD,GAAG;AAAA,IACF,OAAO;AAAA,IACP;AAAA,IACA,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP;AAAA,IACA;AAAA,EACD,CAAE;AACH;",
|
|
6
6
|
"names": ["commandsStore"]
|
|
7
7
|
}
|
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
// packages/commands/src/hooks/use-command-loader.js
|
|
2
|
-
import { useEffect } from "@wordpress/element";
|
|
2
|
+
import { useCallback, useEffect, useRef } from "@wordpress/element";
|
|
3
3
|
import { useDispatch } from "@wordpress/data";
|
|
4
4
|
import { store as commandsStore } from "../store/index.mjs";
|
|
5
5
|
function useCommandLoader(loader) {
|
|
6
6
|
const { registerCommandLoader, unregisterCommandLoader } = useDispatch(commandsStore);
|
|
7
|
+
const currentHookRef = useRef(loader.hook);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
currentHookRef.current = loader.hook;
|
|
10
|
+
}, [loader.hook]);
|
|
11
|
+
const hook = useCallback(
|
|
12
|
+
(...args) => currentHookRef.current(...args),
|
|
13
|
+
[]
|
|
14
|
+
);
|
|
7
15
|
useEffect(() => {
|
|
8
16
|
if (loader.disabled) {
|
|
9
17
|
return;
|
|
10
18
|
}
|
|
11
19
|
registerCommandLoader({
|
|
12
20
|
name: loader.name,
|
|
13
|
-
hook
|
|
21
|
+
hook,
|
|
14
22
|
context: loader.context,
|
|
15
23
|
category: loader.category
|
|
16
24
|
});
|
|
@@ -19,7 +27,7 @@ function useCommandLoader(loader) {
|
|
|
19
27
|
};
|
|
20
28
|
}, [
|
|
21
29
|
loader.name,
|
|
22
|
-
|
|
30
|
+
hook,
|
|
23
31
|
loader.context,
|
|
24
32
|
loader.category,
|
|
25
33
|
loader.disabled,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/hooks/use-command-loader.js"],
|
|
4
|
-
"sourcesContent": ["import { useEffect } from '@wordpress/element';\nimport { useDispatch } from '@wordpress/data';\nimport { store as commandsStore } from '../store';\n\n/**\n * Attach a command loader to the command palette. Used for dynamic commands.\n *\n * @param {import('../store/actions').WPCommandLoaderConfig} loader command loader config.\n *\n * @example\n * ```js\n * import { __ } from '@wordpress/i18n';\n * import { addQueryArgs } from '@wordpress/url';\n * import { useCommandLoader } from '@wordpress/commands';\n * import { page } from '@wordpress/icons';\n * import { useSelect } from '@wordpress/data';\n * import { store as coreStore } from '@wordpress/core-data';\n * import { useMemo } from '@wordpress/element';\n *\n * function usePageSearchCommandLoader( { search } ) {\n * // Retrieve the pages for the \"search\" term.\n * const { records, isLoading } = useSelect(\n * ( select ) => {\n * const { getEntityRecords } = select( coreStore );\n * const query = {\n * search: !! search ? search : undefined,\n * per_page: 10,\n * orderby: search ? 'relevance' : 'date',\n * };\n * return {\n * records: getEntityRecords( 'postType', 'page', query ),\n * isLoading: ! select( coreStore ).hasFinishedResolution(\n * 'getEntityRecords',\n * [ 'postType', 'page', query ]\n * ),\n * };\n * },\n * [ search ]\n * );\n *\n * // Create the commands.\n * const commands = useMemo( () => {\n * return ( records ?? [] ).slice( 0, 10 ).map( ( record ) => {\n * return {\n * name: record.title?.rendered + ' ' + record.id,\n * label: record.title?.rendered\n * ? record.title?.rendered\n * : __( '(no title)' ),\n * icon: page,\n * category: 'edit',\n * callback: ( { close } ) => {\n * const args = {\n * \t\t\t\t\t\t\tp: '/page',\n * \t\t\t\t\t\t\tpostId: record.id,\n * };\n * document.location = addQueryArgs( 'site-editor.php', args );\n * close();\n * },\n * };\n * } );\n * }, [ records ] );\n *\n * return {\n * commands,\n * isLoading,\n * };\n * }\n *\n * useCommandLoader( {\n * name: 'myplugin/page-search',\n * hook: usePageSearchCommandLoader,\n * } );\n * ```\n */\nexport default function useCommandLoader( loader ) {\n\tconst { registerCommandLoader, unregisterCommandLoader } =\n\t\tuseDispatch( commandsStore );\n\tuseEffect( () => {\n\t\tif ( loader.disabled ) {\n\t\t\treturn;\n\t\t}\n\t\tregisterCommandLoader( {\n\t\t\tname: loader.name,\n\t\t\thook
|
|
5
|
-
"mappings": ";AAAA,SAAS,
|
|
4
|
+
"sourcesContent": ["import { useCallback, useEffect, useRef } from '@wordpress/element';\nimport { useDispatch } from '@wordpress/data';\nimport { store as commandsStore } from '../store';\n\n/**\n * Attach a command loader to the command palette. Used for dynamic commands.\n *\n * The palette always calls the most recent `hook`. Changing the `hook` instance\n * doesn't re-render the palette.\n *\n * @param {import('../store/actions').WPCommandLoaderConfig} loader command loader config.\n *\n * @example\n * ```js\n * import { __ } from '@wordpress/i18n';\n * import { addQueryArgs } from '@wordpress/url';\n * import { useCommandLoader } from '@wordpress/commands';\n * import { page } from '@wordpress/icons';\n * import { useSelect } from '@wordpress/data';\n * import { store as coreStore } from '@wordpress/core-data';\n * import { useMemo } from '@wordpress/element';\n *\n * function usePageSearchCommandLoader( { search } ) {\n * // Retrieve the pages for the \"search\" term.\n * const { records, isLoading } = useSelect(\n * ( select ) => {\n * const { getEntityRecords } = select( coreStore );\n * const query = {\n * search: !! search ? search : undefined,\n * per_page: 10,\n * orderby: search ? 'relevance' : 'date',\n * };\n * return {\n * records: getEntityRecords( 'postType', 'page', query ),\n * isLoading: ! select( coreStore ).hasFinishedResolution(\n * 'getEntityRecords',\n * [ 'postType', 'page', query ]\n * ),\n * };\n * },\n * [ search ]\n * );\n *\n * // Create the commands.\n * const commands = useMemo( () => {\n * return ( records ?? [] ).slice( 0, 10 ).map( ( record ) => {\n * return {\n * name: record.title?.rendered + ' ' + record.id,\n * label: record.title?.rendered\n * ? record.title?.rendered\n * : __( '(no title)' ),\n * icon: page,\n * category: 'edit',\n * callback: ( { close } ) => {\n * const args = {\n * \t\t\t\t\t\t\tp: '/page',\n * \t\t\t\t\t\t\tpostId: record.id,\n * };\n * document.location = addQueryArgs( 'site-editor.php', args );\n * close();\n * },\n * };\n * } );\n * }, [ records ] );\n *\n * return {\n * commands,\n * isLoading,\n * };\n * }\n *\n * useCommandLoader( {\n * name: 'myplugin/page-search',\n * hook: usePageSearchCommandLoader,\n * } );\n * ```\n */\nexport default function useCommandLoader( loader ) {\n\tconst { registerCommandLoader, unregisterCommandLoader } =\n\t\tuseDispatch( commandsStore );\n\tconst currentHookRef = useRef( loader.hook );\n\tuseEffect( () => {\n\t\tcurrentHookRef.current = loader.hook;\n\t}, [ loader.hook ] );\n\n\t// Stable identity, so a hook rebuilt on every render does not re-register\n\t// the loader.\n\tconst hook = useCallback(\n\t\t( ...args ) => currentHookRef.current( ...args ),\n\t\t[]\n\t);\n\n\tuseEffect( () => {\n\t\tif ( loader.disabled ) {\n\t\t\treturn;\n\t\t}\n\t\tregisterCommandLoader( {\n\t\t\tname: loader.name,\n\t\t\thook,\n\t\t\tcontext: loader.context,\n\t\t\tcategory: loader.category,\n\t\t} );\n\t\treturn () => {\n\t\t\tunregisterCommandLoader( loader.name );\n\t\t};\n\t}, [\n\t\tloader.name,\n\t\thook,\n\t\tloader.context,\n\t\tloader.category,\n\t\tloader.disabled,\n\t\tregisterCommandLoader,\n\t\tunregisterCommandLoader,\n\t] );\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,aAAa,WAAW,cAAc;AAC/C,SAAS,mBAAmB;AAC5B,SAAS,SAAS,qBAAqB;AA2ExB,SAAR,iBAAmC,QAAS;AAClD,QAAM,EAAE,uBAAuB,wBAAwB,IACtD,YAAa,aAAc;AAC5B,QAAM,iBAAiB,OAAQ,OAAO,IAAK;AAC3C,YAAW,MAAM;AAChB,mBAAe,UAAU,OAAO;AAAA,EACjC,GAAG,CAAE,OAAO,IAAK,CAAE;AAInB,QAAM,OAAO;AAAA,IACZ,IAAK,SAAU,eAAe,QAAS,GAAG,IAAK;AAAA,IAC/C,CAAC;AAAA,EACF;AAEA,YAAW,MAAM;AAChB,QAAK,OAAO,UAAW;AACtB;AAAA,IACD;AACA,0BAAuB;AAAA,MACtB,MAAM,OAAO;AAAA,MACb;AAAA,MACA,SAAS,OAAO;AAAA,MAChB,UAAU,OAAO;AAAA,IAClB,CAAE;AACF,WAAO,MAAM;AACZ,8BAAyB,OAAO,IAAK;AAAA,IACtC;AAAA,EACD,GAAG;AAAA,IACF,OAAO;AAAA,IACP;AAAA,IACA,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP;AAAA,IACA;AAAA,EACD,CAAE;AACH;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/commands",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.56.0",
|
|
4
4
|
"description": "Handles the commands menu.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -20,8 +20,7 @@
|
|
|
20
20
|
"url": "https://github.com/WordPress/gutenberg/issues"
|
|
21
21
|
},
|
|
22
22
|
"engines": {
|
|
23
|
-
"node": ">=18.12.0"
|
|
24
|
-
"npm": ">=8.19.2"
|
|
23
|
+
"node": ">=18.12.0"
|
|
25
24
|
},
|
|
26
25
|
"files": [
|
|
27
26
|
"src",
|
|
@@ -43,16 +42,16 @@
|
|
|
43
42
|
},
|
|
44
43
|
"wpScript": true,
|
|
45
44
|
"dependencies": {
|
|
46
|
-
"@wordpress/base-styles": "^13.
|
|
47
|
-
"@wordpress/components": "^
|
|
48
|
-
"@wordpress/data": "^10.
|
|
49
|
-
"@wordpress/element": "^8.
|
|
50
|
-
"@wordpress/i18n": "^6.
|
|
51
|
-
"@wordpress/icons": "^
|
|
52
|
-
"@wordpress/keyboard-shortcuts": "^5.
|
|
53
|
-
"@wordpress/keycodes": "^4.
|
|
54
|
-
"@wordpress/preferences": "^4.
|
|
55
|
-
"@wordpress/private-apis": "^1.
|
|
45
|
+
"@wordpress/base-styles": "^13.2.0",
|
|
46
|
+
"@wordpress/components": "^41.0.0",
|
|
47
|
+
"@wordpress/data": "^10.56.0",
|
|
48
|
+
"@wordpress/element": "^8.8.0",
|
|
49
|
+
"@wordpress/i18n": "^6.29.0",
|
|
50
|
+
"@wordpress/icons": "^17.0.0",
|
|
51
|
+
"@wordpress/keyboard-shortcuts": "^5.56.0",
|
|
52
|
+
"@wordpress/keycodes": "^4.56.0",
|
|
53
|
+
"@wordpress/preferences": "^4.56.0",
|
|
54
|
+
"@wordpress/private-apis": "^1.56.0",
|
|
56
55
|
"clsx": "^2.1.1",
|
|
57
56
|
"cmdk": "^1.0.0"
|
|
58
57
|
},
|
|
@@ -63,5 +62,5 @@
|
|
|
63
62
|
"publishConfig": {
|
|
64
63
|
"access": "public"
|
|
65
64
|
},
|
|
66
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "56d8058eda6e30c4cc8bfc37818fa6ed972f7dc2"
|
|
67
66
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import { useEffect } from '@wordpress/element';
|
|
1
|
+
import { useCallback, useEffect, useRef } from '@wordpress/element';
|
|
2
2
|
import { useDispatch } from '@wordpress/data';
|
|
3
3
|
import { store as commandsStore } from '../store';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Attach a command loader to the command palette. Used for dynamic commands.
|
|
7
7
|
*
|
|
8
|
+
* The palette always calls the most recent `hook`. Changing the `hook` instance
|
|
9
|
+
* doesn't re-render the palette.
|
|
10
|
+
*
|
|
8
11
|
* @param {import('../store/actions').WPCommandLoaderConfig} loader command loader config.
|
|
9
12
|
*
|
|
10
13
|
* @example
|
|
@@ -75,13 +78,25 @@ import { store as commandsStore } from '../store';
|
|
|
75
78
|
export default function useCommandLoader( loader ) {
|
|
76
79
|
const { registerCommandLoader, unregisterCommandLoader } =
|
|
77
80
|
useDispatch( commandsStore );
|
|
81
|
+
const currentHookRef = useRef( loader.hook );
|
|
82
|
+
useEffect( () => {
|
|
83
|
+
currentHookRef.current = loader.hook;
|
|
84
|
+
}, [ loader.hook ] );
|
|
85
|
+
|
|
86
|
+
// Stable identity, so a hook rebuilt on every render does not re-register
|
|
87
|
+
// the loader.
|
|
88
|
+
const hook = useCallback(
|
|
89
|
+
( ...args ) => currentHookRef.current( ...args ),
|
|
90
|
+
[]
|
|
91
|
+
);
|
|
92
|
+
|
|
78
93
|
useEffect( () => {
|
|
79
94
|
if ( loader.disabled ) {
|
|
80
95
|
return;
|
|
81
96
|
}
|
|
82
97
|
registerCommandLoader( {
|
|
83
98
|
name: loader.name,
|
|
84
|
-
hook
|
|
99
|
+
hook,
|
|
85
100
|
context: loader.context,
|
|
86
101
|
category: loader.category,
|
|
87
102
|
} );
|
|
@@ -90,7 +105,7 @@ export default function useCommandLoader( loader ) {
|
|
|
90
105
|
};
|
|
91
106
|
}, [
|
|
92
107
|
loader.name,
|
|
93
|
-
|
|
108
|
+
hook,
|
|
94
109
|
loader.context,
|
|
95
110
|
loader.category,
|
|
96
111
|
loader.disabled,
|