@carbon/ibm-products
Version:
Carbon for IBM Products
85 lines (83 loc) • 3.11 kB
JavaScript
/**
* Copyright IBM Corp. 2020, 2026
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
import { usePreviousValue } from "../../../global/js/hooks/usePreviousValue.js";
import { includesResourceKey } from "../utils/handleMultipleKeys.js";
import { useEffect, useState } from "react";
//#region src/components/DataSpreadsheet/hooks/useMultipleKeyTracking.js
/**
* Copyright IBM Corp. 2022, 2022
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
const hasFocus = () => typeof document !== "undefined" && document.hasFocus();
const useMultipleKeyTracking = ({ ref, containerHasFocus, isEditing }) => {
const [usingMac, setUsingMac] = useState("");
const [windowFocused, setWindowFocused] = useState(hasFocus);
const [keysPressedList, setKeysPressedList] = useState([]);
const previousState = usePreviousValue({
isEditing,
windowFocused,
containerHasFocus
});
useEffect(() => {
if (window.navigator.userAgent.includes("Macintosh")) setUsingMac(true);
else setUsingMac(false);
setWindowFocused(hasFocus());
const onWindowFocus = () => setWindowFocused(true);
const onWindowBlur = () => setWindowFocused(false);
window.addEventListener("focus", onWindowFocus);
window.addEventListener("blur", onWindowBlur);
return () => {
window.removeEventListener("focus", onWindowFocus);
window.removeEventListener("blur", onWindowBlur);
};
}, []);
useEffect(() => {
if (ref && containerHasFocus && !isEditing) ref.current.onkeydown = ref.current.onkeyup = (event) => {
if (event.type === "keydown") {
if (keysPressedList.includes(event.code)) return;
if (includesResourceKey(keysPressedList, usingMac) && keysPressedList.length > 1) {
const filteredClonedKeys = [...keysPressedList].filter((item) => item === "MetaLeft" || item === "MetaRight");
filteredClonedKeys.push(event.code);
return setKeysPressedList([...new Set(filteredClonedKeys)]);
}
const tempKeys = [...keysPressedList];
tempKeys.push(event.code);
setKeysPressedList([...new Set(tempKeys)]);
}
if (event.type === "keyup") {
const filteredClone = [...keysPressedList].filter((item) => item !== event.code);
if (event.code === "MetaLeft" || event.code === "MetaRight") return setKeysPressedList([]);
setKeysPressedList([...new Set(filteredClone)]);
}
};
if (previousState?.windowFocused && !windowFocused) setKeysPressedList([]);
if (ref && !containerHasFocus || isEditing) {
ref.current.onkeydown = void 0;
ref.current.onkeyup = void 0;
if (!previousState?.isEditing && isEditing || previousState?.containerHasFocus && !containerHasFocus) setKeysPressedList([]);
}
}, [
keysPressedList,
containerHasFocus,
ref,
isEditing,
previousState?.isEditing,
previousState?.containerHasFocus,
windowFocused,
previousState?.windowFocused,
usingMac
]);
return {
keysPressedList,
windowFocused,
usingMac
};
};
//#endregion
export { useMultipleKeyTracking };