@wordpress/keyboard-shortcuts 5.44.0 → 5.45.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.
Files changed (77) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +5 -9
  3. package/build/components/shortcut-provider.cjs +7 -3
  4. package/build/components/shortcut-provider.cjs.map +3 -3
  5. package/build/context.cjs +2 -1
  6. package/build/context.cjs.map +3 -3
  7. package/build/hooks/use-shortcut-event-match.cjs +16 -9
  8. package/build/hooks/use-shortcut-event-match.cjs.map +3 -3
  9. package/build/hooks/use-shortcut.cjs +4 -3
  10. package/build/hooks/use-shortcut.cjs.map +3 -3
  11. package/build/index.cjs +2 -1
  12. package/build/index.cjs.map +2 -2
  13. package/build/store/actions.cjs +2 -1
  14. package/build/store/actions.cjs.map +3 -3
  15. package/build/store/index.cjs +2 -1
  16. package/build/store/index.cjs.map +3 -3
  17. package/build/store/reducer.cjs +2 -1
  18. package/build/store/reducer.cjs.map +3 -3
  19. package/build/store/selectors.cjs +14 -2
  20. package/build/store/selectors.cjs.map +3 -3
  21. package/build/store/types.cjs +19 -0
  22. package/build/store/types.cjs.map +7 -0
  23. package/build-module/components/shortcut-provider.mjs +6 -3
  24. package/build-module/components/shortcut-provider.mjs.map +3 -3
  25. package/build-module/context.mjs +1 -1
  26. package/build-module/context.mjs.map +3 -3
  27. package/build-module/hooks/use-shortcut-event-match.mjs +15 -9
  28. package/build-module/hooks/use-shortcut-event-match.mjs.map +3 -3
  29. package/build-module/hooks/use-shortcut.mjs +3 -3
  30. package/build-module/hooks/use-shortcut.mjs.map +3 -3
  31. package/build-module/index.mjs +1 -1
  32. package/build-module/index.mjs.map +1 -1
  33. package/build-module/store/actions.mjs +1 -1
  34. package/build-module/store/actions.mjs.map +3 -3
  35. package/build-module/store/index.mjs +1 -1
  36. package/build-module/store/index.mjs.map +3 -3
  37. package/build-module/store/reducer.mjs +1 -1
  38. package/build-module/store/reducer.mjs.map +3 -3
  39. package/build-module/store/selectors.mjs +13 -2
  40. package/build-module/store/selectors.mjs.map +3 -3
  41. package/build-module/store/types.mjs +1 -0
  42. package/build-module/store/types.mjs.map +7 -0
  43. package/build-types/components/shortcut-provider.d.ts +15 -0
  44. package/build-types/components/shortcut-provider.d.ts.map +1 -0
  45. package/build-types/context.d.ts +8 -0
  46. package/build-types/context.d.ts.map +1 -0
  47. package/build-types/hooks/use-shortcut-event-match.d.ts +8 -0
  48. package/build-types/hooks/use-shortcut-event-match.d.ts.map +1 -0
  49. package/build-types/hooks/use-shortcut.d.ts +14 -0
  50. package/build-types/hooks/use-shortcut.d.ts.map +1 -0
  51. package/build-types/hooks/use-shortcut.native.d.ts +3 -0
  52. package/build-types/hooks/use-shortcut.native.d.ts.map +1 -0
  53. package/build-types/index.d.ts +5 -0
  54. package/build-types/index.d.ts.map +1 -0
  55. package/build-types/store/actions.d.ts +114 -0
  56. package/build-types/store/actions.d.ts.map +1 -0
  57. package/build-types/store/index.d.ts +9 -0
  58. package/build-types/store/index.d.ts.map +1 -0
  59. package/build-types/store/reducer.d.ts +16 -0
  60. package/build-types/store/reducer.d.ts.map +1 -0
  61. package/build-types/store/selectors.d.ts +321 -0
  62. package/build-types/store/selectors.d.ts.map +1 -0
  63. package/build-types/store/types.d.ts +9 -0
  64. package/build-types/store/types.d.ts.map +1 -0
  65. package/package.json +8 -6
  66. package/src/components/{shortcut-provider.js → shortcut-provider.tsx} +16 -6
  67. package/src/{context.js → context.ts} +12 -5
  68. package/src/hooks/use-shortcut-event-match.ts +51 -0
  69. package/src/hooks/{use-shortcut.js → use-shortcut.ts} +15 -11
  70. package/src/store/{actions.js → actions.ts} +21 -19
  71. package/src/store/{index.js → index.ts} +0 -2
  72. package/src/store/{reducer.js → reducer.ts} +13 -4
  73. package/src/store/{selectors.js → selectors.ts} +56 -28
  74. package/src/store/types.ts +10 -0
  75. package/src/hooks/use-shortcut-event-match.js +0 -41
  76. /package/src/hooks/{use-shortcut.native.js → use-shortcut.native.ts} +0 -0
  77. /package/src/{index.js → index.ts} +0 -0
@@ -0,0 +1,321 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import type { ShortcutKeyCombination } from './actions';
5
+ interface ShortcutState {
6
+ category: string;
7
+ keyCombination: ShortcutKeyCombination;
8
+ aliases?: ShortcutKeyCombination[];
9
+ description: string;
10
+ }
11
+ type ShortcutsState = Record<string, ShortcutState>;
12
+ /**
13
+ * Shortcut formatting methods.
14
+ */
15
+ declare const FORMATTING_METHODS: {
16
+ /**
17
+ * Display formatting.
18
+ */
19
+ display: import("@wordpress/keycodes").WPModifierHandler<import("@wordpress/keycodes").WPKeyHandler<string>>;
20
+ /**
21
+ * Raw shortcut formatting.
22
+ */
23
+ raw: import("@wordpress/keycodes").WPModifierHandler<import("@wordpress/keycodes").WPKeyHandler<string>>;
24
+ /**
25
+ * ARIA label formatting.
26
+ */
27
+ ariaLabel: import("@wordpress/keycodes").WPModifierHandler<import("@wordpress/keycodes").WPKeyHandler<string>>;
28
+ };
29
+ /**
30
+ * Returns the main key combination for a given shortcut name.
31
+ *
32
+ * @param {Object} state Global state.
33
+ * @param {string} name Shortcut name.
34
+ *
35
+ * @example
36
+ *
37
+ *```js
38
+ * import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts';
39
+ * import { useSelect } from '@wordpress/data';
40
+ * import { createInterpolateElement } from '@wordpress/element';
41
+ * import { sprintf } from '@wordpress/i18n';
42
+ * const ExampleComponent = () => {
43
+ * const {character, modifier} = useSelect(
44
+ * ( select ) =>
45
+ * select( keyboardShortcutsStore ).getShortcutKeyCombination(
46
+ * 'core/editor/next-region'
47
+ * ),
48
+ * []
49
+ * );
50
+ *
51
+ * return (
52
+ * <div>
53
+ * { createInterpolateElement(
54
+ * sprintf(
55
+ * 'Character: <code>%s</code> / Modifier: <code>%s</code>',
56
+ * character,
57
+ * modifier
58
+ * ),
59
+ * {
60
+ * code: <code />,
61
+ * }
62
+ * ) }
63
+ * </div>
64
+ * );
65
+ * };
66
+ *```
67
+ *
68
+ * @return {ShortcutKeyCombination?} Key combination.
69
+ */
70
+ export declare function getShortcutKeyCombination(state: ShortcutsState, name: string): ShortcutKeyCombination | null;
71
+ /**
72
+ * Returns a string representing the main key combination for a given shortcut name.
73
+ *
74
+ * @param {Object} state Global state.
75
+ * @param {string} name Shortcut name.
76
+ * @param {keyof FORMATTING_METHODS} representation Type of representation
77
+ * (display, raw, ariaLabel).
78
+ * @example
79
+ *
80
+ *```js
81
+ * import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts';
82
+ * import { useSelect } from '@wordpress/data';
83
+ * import { sprintf } from '@wordpress/i18n';
84
+ *
85
+ * const ExampleComponent = () => {
86
+ * const {display, raw, ariaLabel} = useSelect(
87
+ * ( select ) =>{
88
+ * return {
89
+ * display: select( keyboardShortcutsStore ).getShortcutRepresentation('core/editor/next-region' ),
90
+ * raw: select( keyboardShortcutsStore ).getShortcutRepresentation('core/editor/next-region','raw' ),
91
+ * ariaLabel: select( keyboardShortcutsStore ).getShortcutRepresentation('core/editor/next-region', 'ariaLabel')
92
+ * }
93
+ * },
94
+ * []
95
+ * );
96
+ *
97
+ * return (
98
+ * <ul>
99
+ * <li>{ sprintf( 'display string: %s', display ) }</li>
100
+ * <li>{ sprintf( 'raw string: %s', raw ) }</li>
101
+ * <li>{ sprintf( 'ariaLabel string: %s', ariaLabel ) }</li>
102
+ * </ul>
103
+ * );
104
+ * };
105
+ *```
106
+ *
107
+ * @return {?string} Shortcut representation.
108
+ */
109
+ export declare function getShortcutRepresentation(state: ShortcutsState, name: string, representation?: keyof typeof FORMATTING_METHODS): string | null;
110
+ /**
111
+ * Returns the shortcut description given its name.
112
+ *
113
+ * @param {Object} state Global state.
114
+ * @param {string} name Shortcut name.
115
+ *
116
+ * @example
117
+ *
118
+ *```js
119
+ * import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts';
120
+ * import { useSelect } from '@wordpress/data';
121
+ * import { __ } from '@wordpress/i18n';
122
+ * const ExampleComponent = () => {
123
+ * const shortcutDescription = useSelect(
124
+ * ( select ) =>
125
+ * select( keyboardShortcutsStore ).getShortcutDescription( 'core/editor/next-region' ),
126
+ * []
127
+ * );
128
+ *
129
+ * return shortcutDescription ? (
130
+ * <div>{ shortcutDescription }</div>
131
+ * ) : (
132
+ * <div>{ __( 'No description.' ) }</div>
133
+ * );
134
+ * };
135
+ *```
136
+ * @return {?string} Shortcut description.
137
+ */
138
+ export declare function getShortcutDescription(state: ShortcutsState, name: string): string | null;
139
+ /**
140
+ * Returns the aliases for a given shortcut name.
141
+ *
142
+ * @param {Object} state Global state.
143
+ * @param {string} name Shortcut name.
144
+ * @example
145
+ *
146
+ *```js
147
+ * import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts';
148
+ * import { useSelect } from '@wordpress/data';
149
+ * import { createInterpolateElement } from '@wordpress/element';
150
+ * import { sprintf } from '@wordpress/i18n';
151
+ * const ExampleComponent = () => {
152
+ * const shortcutAliases = useSelect(
153
+ * ( select ) =>
154
+ * select( keyboardShortcutsStore ).getShortcutAliases(
155
+ * 'core/editor/next-region'
156
+ * ),
157
+ * []
158
+ * );
159
+ *
160
+ * return (
161
+ * shortcutAliases.length > 0 && (
162
+ * <ul>
163
+ * { shortcutAliases.map( ( { character, modifier }, index ) => (
164
+ * <li key={ index }>
165
+ * { createInterpolateElement(
166
+ * sprintf(
167
+ * 'Character: <code>%s</code> / Modifier: <code>%s</code>',
168
+ * character,
169
+ * modifier
170
+ * ),
171
+ * {
172
+ * code: <code />,
173
+ * }
174
+ * ) }
175
+ * </li>
176
+ * ) ) }
177
+ * </ul>
178
+ * )
179
+ * );
180
+ * };
181
+ *```
182
+ *
183
+ * @return {ShortcutKeyCombination[]} Key combinations.
184
+ */
185
+ export declare function getShortcutAliases(state: ShortcutsState, name: string): ShortcutKeyCombination[];
186
+ /**
187
+ * Returns the shortcuts that include aliases for a given shortcut name.
188
+ *
189
+ * @param {Object} state Global state.
190
+ * @param {string} name Shortcut name.
191
+ * @example
192
+ *
193
+ *```js
194
+ * import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts';
195
+ * import { useSelect } from '@wordpress/data';
196
+ * import { createInterpolateElement } from '@wordpress/element';
197
+ * import { sprintf } from '@wordpress/i18n';
198
+ *
199
+ * const ExampleComponent = () => {
200
+ * const allShortcutKeyCombinations = useSelect(
201
+ * ( select ) =>
202
+ * select( keyboardShortcutsStore ).getAllShortcutKeyCombinations(
203
+ * 'core/editor/next-region'
204
+ * ),
205
+ * []
206
+ * );
207
+ *
208
+ * return (
209
+ * allShortcutKeyCombinations.length > 0 && (
210
+ * <ul>
211
+ * { allShortcutKeyCombinations.map(
212
+ * ( { character, modifier }, index ) => (
213
+ * <li key={ index }>
214
+ * { createInterpolateElement(
215
+ * sprintf(
216
+ * 'Character: <code>%s</code> / Modifier: <code>%s</code>',
217
+ * character,
218
+ * modifier
219
+ * ),
220
+ * {
221
+ * code: <code />,
222
+ * }
223
+ * ) }
224
+ * </li>
225
+ * )
226
+ * ) }
227
+ * </ul>
228
+ * )
229
+ * );
230
+ * };
231
+ *```
232
+ *
233
+ * @return {ShortcutKeyCombination[]} Key combinations.
234
+ */
235
+ export declare const getAllShortcutKeyCombinations: ((state: any, name: any) => ShortcutKeyCombination[]) & import("rememo").EnhancedSelector;
236
+ /**
237
+ * Returns the raw representation of all the keyboard combinations of a given shortcut name.
238
+ *
239
+ * @param {Object} state Global state.
240
+ * @param {string} name Shortcut name.
241
+ *
242
+ * @example
243
+ *
244
+ *```js
245
+ * import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts';
246
+ * import { useSelect } from '@wordpress/data';
247
+ * import { createInterpolateElement } from '@wordpress/element';
248
+ * import { sprintf } from '@wordpress/i18n';
249
+ *
250
+ * const ExampleComponent = () => {
251
+ * const allShortcutRawKeyCombinations = useSelect(
252
+ * ( select ) =>
253
+ * select( keyboardShortcutsStore ).getAllShortcutRawKeyCombinations(
254
+ * 'core/editor/next-region'
255
+ * ),
256
+ * []
257
+ * );
258
+ *
259
+ * return (
260
+ * allShortcutRawKeyCombinations.length > 0 && (
261
+ * <ul>
262
+ * { allShortcutRawKeyCombinations.map(
263
+ * ( shortcutRawKeyCombination, index ) => (
264
+ * <li key={ index }>
265
+ * { createInterpolateElement(
266
+ * sprintf(
267
+ * ' <code>%s</code>',
268
+ * shortcutRawKeyCombination
269
+ * ),
270
+ * {
271
+ * code: <code />,
272
+ * }
273
+ * ) }
274
+ * </li>
275
+ * )
276
+ * ) }
277
+ * </ul>
278
+ * )
279
+ * );
280
+ * };
281
+ *```
282
+ *
283
+ * @return {string[]} Shortcuts.
284
+ */
285
+ export declare const getAllShortcutRawKeyCombinations: ((state: any, name: any) => (string | null)[]) & import("rememo").EnhancedSelector;
286
+ /**
287
+ * Returns the shortcut names list for a given category name.
288
+ *
289
+ * @param {Object} state Global state.
290
+ * @param {string} name Category name.
291
+ * @example
292
+ *
293
+ *```js
294
+ * import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts';
295
+ * import { useSelect } from '@wordpress/data';
296
+ *
297
+ * const ExampleComponent = () => {
298
+ * const categoryShortcuts = useSelect(
299
+ * ( select ) =>
300
+ * select( keyboardShortcutsStore ).getCategoryShortcuts(
301
+ * 'block'
302
+ * ),
303
+ * []
304
+ * );
305
+ *
306
+ * return (
307
+ * categoryShortcuts.length > 0 && (
308
+ * <ul>
309
+ * { categoryShortcuts.map( ( categoryShortcut ) => (
310
+ * <li key={ categoryShortcut }>{ categoryShortcut }</li>
311
+ * ) ) }
312
+ * </ul>
313
+ * )
314
+ * );
315
+ * };
316
+ *```
317
+ * @return {string[]} Shortcut names.
318
+ */
319
+ export declare const getCategoryShortcuts: ((state: ShortcutsState, categoryName: string) => string[]) & import("rememo").EnhancedSelector;
320
+ export {};
321
+ //# sourceMappingURL=selectors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selectors.d.ts","sourceRoot":"","sources":["../../src/store/selectors.ts"],"names":[],"mappings":"AAUA;;GAEG;AACH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAExD,UAAU,aAAa;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,sBAAsB,CAAC;IACvC,OAAO,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACnC,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,KAAK,cAAc,GAAG,MAAM,CAAE,MAAM,EAAE,aAAa,CAAE,CAAC;AAQtD;;GAEG;AACH,QAAA,MAAM,kBAAkB;IACvB;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;CAEH,CAAC;AA0BF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,yBAAyB,CACxC,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,MAAM,GACV,sBAAsB,GAAG,IAAI,CAE/B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,yBAAyB,CACxC,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,MAAM,EACZ,cAAc,GAAE,MAAM,OAAO,kBAA8B,GACzD,MAAM,GAAG,IAAI,CAGf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,sBAAsB,CACrC,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,MAAM,GACV,MAAM,GAAG,IAAI,CAEf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,wBAAgB,kBAAkB,CACjC,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,MAAM,GACV,sBAAsB,EAAE,CAI1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,eAAO,MAAM,6BAA6B,2FAWzC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,eAAO,MAAM,gCAAgC,oFAQ5C,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,oBAAoB,WACvB,cAAc,gBAAgB,MAAM,KAAI,MAAM,EAAE,qCAMzD,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { ShortcutKeyCombination } from './actions';
2
+ export interface ShortcutState {
3
+ category: string;
4
+ keyCombination: ShortcutKeyCombination;
5
+ aliases?: ShortcutKeyCombination[];
6
+ description: string;
7
+ }
8
+ export type ShortcutsState = Record<string, ShortcutState>;
9
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/store/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAExD,MAAM,WAAW,aAAa;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,sBAAsB,CAAC;IACvC,OAAO,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACnC,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,CAAE,MAAM,EAAE,aAAa,CAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/keyboard-shortcuts",
3
- "version": "5.44.0",
3
+ "version": "5.45.0",
4
4
  "description": "Handling keyboard shortcuts.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -13,7 +13,7 @@
13
13
  "repository": {
14
14
  "type": "git",
15
15
  "url": "https://github.com/WordPress/gutenberg.git",
16
- "directory": "packages/keycodes"
16
+ "directory": "packages/keyboard-shortcuts"
17
17
  },
18
18
  "bugs": {
19
19
  "url": "https://github.com/WordPress/gutenberg/issues"
@@ -33,6 +33,7 @@
33
33
  "module": "build-module/index.mjs",
34
34
  "exports": {
35
35
  ".": {
36
+ "types": "./build-types/index.d.ts",
36
37
  "import": "./build-module/index.mjs",
37
38
  "require": "./build/index.cjs"
38
39
  },
@@ -40,10 +41,11 @@
40
41
  },
41
42
  "react-native": "src/index",
42
43
  "wpScript": true,
44
+ "types": "build-types/index.d.ts",
43
45
  "dependencies": {
44
- "@wordpress/data": "^10.44.0",
45
- "@wordpress/element": "^6.44.0",
46
- "@wordpress/keycodes": "^4.44.0"
46
+ "@wordpress/data": "^10.45.0",
47
+ "@wordpress/element": "^6.45.0",
48
+ "@wordpress/keycodes": "^4.45.0"
47
49
  },
48
50
  "peerDependencies": {
49
51
  "react": "^18.0.0"
@@ -51,5 +53,5 @@
51
53
  "publishConfig": {
52
54
  "access": "public"
53
55
  },
54
- "gitHead": "b862d8c84121a47bbeff882f6c87e61681ce2e0d"
56
+ "gitHead": "8c229eaed0e88c9827e2da3d73a78f9ddd77714b"
55
57
  }
@@ -10,25 +10,35 @@ import { context } from '../context';
10
10
 
11
11
  const { Provider } = context;
12
12
 
13
+ type ShortcutCallback = ( event: KeyboardEvent ) => void;
14
+
15
+ interface ShortcutProviderProps extends React.HTMLAttributes< HTMLDivElement > {
16
+ onKeyDown?: ( event: React.KeyboardEvent< HTMLDivElement > ) => void;
17
+ }
18
+
13
19
  /**
14
20
  * Handles callbacks added to context by `useShortcut`.
15
21
  * Adding a provider allows to register contextual shortcuts
16
22
  * that are only active when a certain part of the UI is focused.
17
23
  *
18
- * @param {Object} props Props to pass to `div`.
24
+ * @param props Props to pass to `div`.
19
25
  *
20
- * @return {Element} Component.
26
+ * @return Component.
21
27
  */
22
- export function ShortcutProvider( props ) {
23
- const [ keyboardShortcuts ] = useState( () => new Set() );
28
+ export function ShortcutProvider( props: ShortcutProviderProps ) {
29
+ const [ keyboardShortcuts ] = useState(
30
+ () => new Set< ShortcutCallback >()
31
+ );
24
32
 
25
- function onKeyDown( event ) {
33
+ function onKeyDown( event: React.KeyboardEvent< HTMLDivElement > ) {
26
34
  if ( props.onKeyDown ) {
27
35
  props.onKeyDown( event );
28
36
  }
29
37
 
38
+ // Convert React event to native KeyboardEvent for compatibility
39
+ const nativeEvent = event.nativeEvent;
30
40
  for ( const keyboardShortcut of keyboardShortcuts ) {
31
- keyboardShortcut( event );
41
+ keyboardShortcut( nativeEvent );
32
42
  }
33
43
  }
34
44
 
@@ -3,21 +3,28 @@
3
3
  */
4
4
  import { createContext } from '@wordpress/element';
5
5
 
6
- const globalShortcuts = new Set();
7
- const globalListener = ( event ) => {
6
+ type ShortcutCallback = ( event: KeyboardEvent ) => void;
7
+
8
+ interface ShortcutContextType {
9
+ add: ( shortcut: ShortcutCallback ) => void;
10
+ delete: ( shortcut: ShortcutCallback ) => void;
11
+ }
12
+
13
+ const globalShortcuts = new Set< ShortcutCallback >();
14
+ const globalListener = ( event: KeyboardEvent ) => {
8
15
  for ( const keyboardShortcut of globalShortcuts ) {
9
16
  keyboardShortcut( event );
10
17
  }
11
18
  };
12
19
 
13
- export const context = createContext( {
14
- add: ( shortcut ) => {
20
+ export const context = createContext< ShortcutContextType >( {
21
+ add: ( shortcut: ShortcutCallback ) => {
15
22
  if ( globalShortcuts.size === 0 ) {
16
23
  document.addEventListener( 'keydown', globalListener );
17
24
  }
18
25
  globalShortcuts.add( shortcut );
19
26
  },
20
- delete: ( shortcut ) => {
27
+ delete: ( shortcut: ShortcutCallback ) => {
21
28
  globalShortcuts.delete( shortcut );
22
29
  if ( globalShortcuts.size === 0 ) {
23
30
  document.removeEventListener( 'keydown', globalListener );
@@ -0,0 +1,51 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useSelect } from '@wordpress/data';
5
+ import { useCallback } from '@wordpress/element';
6
+ import { isKeyboardEvent } from '@wordpress/keycodes';
7
+
8
+ /**
9
+ * Internal dependencies
10
+ */
11
+ import { store as keyboardShortcutsStore } from '../store';
12
+
13
+ /**
14
+ * Returns a function to check if a keyboard event matches a shortcut name.
15
+ *
16
+ * @return A function to check if a keyboard event matches a
17
+ * predefined shortcut combination.
18
+ */
19
+ export default function useShortcutEventMatch(): (
20
+ name: string,
21
+ event: KeyboardEvent
22
+ ) => boolean {
23
+ const { getAllShortcutKeyCombinations } = useSelect(
24
+ keyboardShortcutsStore
25
+ );
26
+
27
+ /**
28
+ * A function to check if a keyboard event matches a predefined shortcut
29
+ * combination.
30
+ *
31
+ * @param name Shortcut name.
32
+ * @param event Event to check.
33
+ *
34
+ * @return True if the event matches the shortcuts, false if not.
35
+ */
36
+ return useCallback(
37
+ ( name: string, event: KeyboardEvent ) => {
38
+ return getAllShortcutKeyCombinations( name ).some(
39
+ ( combination ) => {
40
+ if ( ! combination ) {
41
+ return false;
42
+ }
43
+ return isKeyboardEvent[
44
+ combination.modifier ?? 'undefined'
45
+ ]( event, combination.character );
46
+ }
47
+ );
48
+ },
49
+ [ getAllShortcutKeyCombinations ]
50
+ );
51
+ }
@@ -9,22 +9,26 @@ import { useContext, useEffect, useRef } from '@wordpress/element';
9
9
  import useShortcutEventMatch from './use-shortcut-event-match';
10
10
  import { context } from '../context';
11
11
 
12
+ interface UseShortcutOptions {
13
+ isDisabled?: boolean;
14
+ }
15
+
12
16
  /**
13
17
  * Attach a keyboard shortcut handler.
14
18
  *
15
- * @param {string} name Shortcut name.
16
- * @param {Function} callback Shortcut callback.
17
- * @param {Object} options Shortcut options.
18
- * @param {boolean} options.isDisabled Whether to disable to shortut.
19
+ * @param name Shortcut name.
20
+ * @param callback Shortcut callback.
21
+ * @param options Shortcut options.
22
+ * @param options.isDisabled Whether to disable the shortcut.
19
23
  */
20
24
  export default function useShortcut(
21
- name,
22
- callback,
23
- { isDisabled = false } = {}
25
+ name: string,
26
+ callback: ( event: KeyboardEvent ) => void,
27
+ { isDisabled = false }: UseShortcutOptions = {}
24
28
  ) {
25
29
  const shortcuts = useContext( context );
26
30
  const isMatch = useShortcutEventMatch();
27
- const callbackRef = useRef();
31
+ const callbackRef = useRef< ( event: KeyboardEvent ) => void >();
28
32
 
29
33
  useEffect( () => {
30
34
  callbackRef.current = callback;
@@ -35,8 +39,8 @@ export default function useShortcut(
35
39
  return;
36
40
  }
37
41
 
38
- function _callback( event ) {
39
- if ( isMatch( name, event ) ) {
42
+ function _callback( event: KeyboardEvent ) {
43
+ if ( isMatch( name, event ) && callbackRef.current ) {
40
44
  callbackRef.current( event );
41
45
  }
42
46
  }
@@ -45,5 +49,5 @@ export default function useShortcut(
45
49
  return () => {
46
50
  shortcuts.delete( _callback );
47
51
  };
48
- }, [ name, isDisabled, shortcuts ] );
52
+ }, [ name, isDisabled, shortcuts, isMatch ] );
49
53
  }
@@ -1,30 +1,32 @@
1
- /** @typedef {import('@wordpress/keycodes').WPKeycodeModifier} WPKeycodeModifier */
1
+ import type { WPKeycodeModifier } from '@wordpress/keycodes';
2
2
 
3
3
  /**
4
4
  * Keyboard key combination.
5
- *
6
- * @typedef {Object} WPShortcutKeyCombination
7
- *
8
- * @property {string} character Character.
9
- * @property {WPKeycodeModifier|undefined} modifier Modifier.
10
5
  */
6
+ export interface ShortcutKeyCombination {
7
+ character: string;
8
+ modifier: WPKeycodeModifier | undefined;
9
+ }
11
10
 
12
11
  /**
13
12
  * Configuration of a registered keyboard shortcut.
14
- *
15
- * @typedef {Object} WPShortcutConfig
16
- *
17
- * @property {string} name Shortcut name.
18
- * @property {string} category Shortcut category.
19
- * @property {string} description Shortcut description.
20
- * @property {WPShortcutKeyCombination} keyCombination Shortcut key combination.
21
- * @property {WPShortcutKeyCombination[]} [aliases] Shortcut aliases.
22
13
  */
14
+ export interface ShortcutConfig {
15
+ name: string;
16
+ category: string;
17
+ description: string;
18
+ keyCombination: ShortcutKeyCombination;
19
+ aliases?: ShortcutKeyCombination[];
20
+ }
21
+
22
+ export type ShortcutAction =
23
+ | ReturnType< typeof registerShortcut >
24
+ | ReturnType< typeof unregisterShortcut >;
23
25
 
24
26
  /**
25
27
  * Returns an action object used to register a new keyboard shortcut.
26
28
  *
27
- * @param {WPShortcutConfig} config Shortcut config.
29
+ * @param {ShortcutConfig} config Shortcut config.
28
30
  *
29
31
  * @example
30
32
  *
@@ -72,9 +74,9 @@ export function registerShortcut( {
72
74
  description,
73
75
  keyCombination,
74
76
  aliases,
75
- } ) {
77
+ }: ShortcutConfig ) {
76
78
  return {
77
- type: 'REGISTER_SHORTCUT',
79
+ type: 'REGISTER_SHORTCUT' as const,
78
80
  name,
79
81
  category,
80
82
  keyCombination,
@@ -120,9 +122,9 @@ export function registerShortcut( {
120
122
  *```
121
123
  * @return {Object} action.
122
124
  */
123
- export function unregisterShortcut( name ) {
125
+ export function unregisterShortcut( name: string ) {
124
126
  return {
125
- type: 'UNREGISTER_SHORTCUT',
127
+ type: 'UNREGISTER_SHORTCUT' as const,
126
128
  name,
127
129
  };
128
130
  }
@@ -16,8 +16,6 @@ const STORE_NAME = 'core/keyboard-shortcuts';
16
16
  * Store definition for the keyboard shortcuts namespace.
17
17
  *
18
18
  * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore
19
- *
20
- * @type {Object}
21
19
  */
22
20
  export const store = createReduxStore( STORE_NAME, {
23
21
  reducer,
@@ -1,12 +1,21 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import type { ShortcutAction } from './actions';
5
+ import type { ShortcutsState } from './types';
6
+
1
7
  /**
2
8
  * Reducer returning the registered shortcuts
3
9
  *
4
- * @param {Object} state Current state.
5
- * @param {Object} action Dispatched action.
10
+ * @param state Current state.
11
+ * @param action Dispatched action.
6
12
  *
7
- * @return {Object} Updated state.
13
+ * @return Updated state.
8
14
  */
9
- function reducer( state = {}, action ) {
15
+ function reducer(
16
+ state: ShortcutsState = {},
17
+ action: ShortcutAction
18
+ ): ShortcutsState {
10
19
  switch ( action.type ) {
11
20
  case 'REGISTER_SHORTCUT':
12
21
  return {