diff --git a/.changeset/olive-rice-sell.md b/.changeset/olive-rice-sell.md new file mode 100644 index 00000000000..42f36e9a8f3 --- /dev/null +++ b/.changeset/olive-rice-sell.md @@ -0,0 +1,5 @@ +--- +'@graphiql/react': patch +--- + +Prefer KeyboardEvent#key over KeyboardEvent#keyCode diff --git a/.eslintrc.js b/.eslintrc.js index c0a781d7f4c..80f0baf3fc4 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -198,6 +198,11 @@ module.exports = { message: "`useMemo` with an empty dependency array can't provide a stable reference, use `useRef` instead.", }, + { + // ❌ event.keyCode + selector: 'MemberExpression > .property[type=Identifier][name=keyCode]', + message: 'Use `.key` instead of `.keyCode`', + }, ], 'no-ternary': 0, 'no-underscore-dangle': 0, @@ -282,6 +287,8 @@ module.exports = { 'unicorn/prefer-node-protocol': 'error', 'import/no-unresolved': ['error', { ignore: ['^node:'] }], 'unicorn/prefer-string-replace-all': 'error', + // doesn't catch a lot of cases; we use ESLint builtin `no-restricted-syntax` to forbid `.keyCode` + 'unicorn/prefer-keyboard-event-key': 'off', 'unicorn/prefer-switch': 'error', // TODO: Fix all errors for the following rules included in recommended config diff --git a/packages/graphiql-react/src/editor/header-editor.ts b/packages/graphiql-react/src/editor/header-editor.ts index 83a05e3dfc9..19e8727c316 100644 --- a/packages/graphiql-react/src/editor/header-editor.ts +++ b/packages/graphiql-react/src/editor/header-editor.ts @@ -96,13 +96,10 @@ export function useHeaderEditor( }); newEditor.on('keyup', (editorInstance, event) => { - const code = event.keyCode; - if ( - (code >= 65 && code <= 90) || // letters - (!event.shiftKey && code >= 48 && code <= 57) || // numbers - (event.shiftKey && code === 189) || // underscore - (event.shiftKey && code === 222) // " - ) { + const { keyCode, key, shiftKey } = event; + const isLetter = keyCode >= 65 && keyCode <= 90; + const isNumber = keyCode >= 48 && keyCode <= 57; + if (isLetter || (!shiftKey && isNumber) || key === '_' || key === '"') { editorInstance.execCommand('autocomplete'); } }); diff --git a/packages/graphiql-react/src/editor/variable-editor.ts b/packages/graphiql-react/src/editor/variable-editor.ts index 96e50d9ee6d..d3c54ac995b 100644 --- a/packages/graphiql-react/src/editor/variable-editor.ts +++ b/packages/graphiql-react/src/editor/variable-editor.ts @@ -116,13 +116,10 @@ export function useVariableEditor( }); newEditor.on('keyup', (editorInstance, event) => { - const code = event.keyCode; - if ( - (code >= 65 && code <= 90) || // letters - (!event.shiftKey && code >= 48 && code <= 57) || // numbers - (event.shiftKey && code === 189) || // underscore - (event.shiftKey && code === 222) // " - ) { + const { keyCode, key, shiftKey } = event; + const isLetter = keyCode >= 65 && keyCode <= 90; + const isNumber = keyCode >= 48 && keyCode <= 57; + if (isLetter || (!shiftKey && isNumber) || key === '_' || key === '"') { editorInstance.execCommand('autocomplete'); } }); diff --git a/packages/graphiql-react/src/explorer/components/search.tsx b/packages/graphiql-react/src/explorer/components/search.tsx index c4258d86b30..886899d7b89 100644 --- a/packages/graphiql-react/src/explorer/components/search.tsx +++ b/packages/graphiql-react/src/explorer/components/search.tsx @@ -50,10 +50,11 @@ export function Search() { useEffect(() => { function handleKeyDown(event: KeyboardEvent) { - if (event.metaKey && event.keyCode === 75 && inputRef.current) { - inputRef.current.focus(); + if (event.metaKey && event.key === 'k') { + inputRef.current?.focus(); } } + window.addEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown); }, []); diff --git a/packages/graphiql-react/src/history/components.tsx b/packages/graphiql-react/src/history/components.tsx index b5ad56b52a8..3ca42552d85 100644 --- a/packages/graphiql-react/src/history/components.tsx +++ b/packages/graphiql-react/src/history/components.tsx @@ -75,11 +75,9 @@ export function HistoryItem(props: QueryHistoryItemProps) { defaultValue={props.item.label} ref={inputRef} onKeyDown={e => { - if (e.keyCode === 27) { - // Escape + if (e.key === 'Esc') { setIsEditable(false); - } else if (e.keyCode === 13) { - // Enter + } else if (e.key === 'Enter') { setIsEditable(false); editLabel({ ...props.item, label: e.currentTarget.value }); } diff --git a/packages/graphiql-react/src/schema.tsx b/packages/graphiql-react/src/schema.tsx index 8fa7fc04176..6284fc95ddc 100644 --- a/packages/graphiql-react/src/schema.tsx +++ b/packages/graphiql-react/src/schema.tsx @@ -194,6 +194,7 @@ export function SchemaContextProvider(props: SchemaContextProviderProps) { const counter = ++counterRef.current; const maybeIntrospectionData = props.schema; + async function fetchIntrospectionData() { if (maybeIntrospectionData) { // No need to introspect if we already have the data @@ -317,10 +318,11 @@ export function SchemaContextProvider(props: SchemaContextProviderProps) { */ useEffect(() => { function triggerIntrospection(event: KeyboardEvent) { - if (event.keyCode === 82 && event.shiftKey && event.ctrlKey) { + if (event.ctrlKey && event.key === 'R') { introspect(); } } + window.addEventListener('keydown', triggerIntrospection); return () => window.removeEventListener('keydown', triggerIntrospection); });