From 6985cd4b2299650d66c8f3e5ac952879ede94ed1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com>
Date: Wed, 9 Nov 2022 02:12:53 +0000
Subject: [PATCH] feat: more consistent keyboard implementation

---
 .../web/react/components/button/button.tsx    | 10 +++
 .../keyboard-chip8/keyboard-chip8.css         |  6 +-
 .../keyboard-chip8/keyboard-chip8.tsx         | 61 +++++++++++++++++--
 .../components/keyboard-gb/keyboard-gb.tsx    |  8 ++-
 4 files changed, 73 insertions(+), 12 deletions(-)

diff --git a/examples/web/react/components/button/button.tsx b/examples/web/react/components/button/button.tsx
index 4c1ffda3..f57f5530 100644
--- a/examples/web/react/components/button/button.tsx
+++ b/examples/web/react/components/button/button.tsx
@@ -44,6 +44,14 @@ export const Button: FC<ButtonProps> = ({
         onFile && onFile(file);
         event.target.value = "";
     };
+    const onMouseDown = (event: React.MouseEvent) => {
+        event.stopPropagation();
+        event.preventDefault();
+    };
+    const onMouseUp = (event: React.MouseEvent) => {
+        event.stopPropagation();
+        event.preventDefault();
+    };
     const onKeyPress = (event: React.KeyboardEvent) => {
         if (event.key !== "Enter") return;
         onClick && onClick();
@@ -62,6 +70,8 @@ export const Button: FC<ButtonProps> = ({
         <span
             className={classes()}
             onClick={onClick}
+            onMouseDown={onMouseDown}
+            onMouseUp={onMouseUp}
             onKeyPress={onKeyPress}
             tabIndex={focusable ? 0 : undefined}
         >
diff --git a/examples/web/react/components/keyboard-chip8/keyboard-chip8.css b/examples/web/react/components/keyboard-chip8/keyboard-chip8.css
index 7b49d14e..97507e3b 100644
--- a/examples/web/react/components/keyboard-chip8/keyboard-chip8.css
+++ b/examples/web/react/components/keyboard-chip8/keyboard-chip8.css
@@ -47,10 +47,6 @@
     margin-right: 0px;
 }
 
-.keyboard-chip8 .key:hover {
+.keyboard-chip8 .key.pressed {
     background-color: #50cb93;
 }
-
-.keyboard-chip8 .key:active {
-    background-color: #2a9d8f;
-}
diff --git a/examples/web/react/components/keyboard-chip8/keyboard-chip8.tsx b/examples/web/react/components/keyboard-chip8/keyboard-chip8.tsx
index dd5bafd7..99ddd4f8 100644
--- a/examples/web/react/components/keyboard-chip8/keyboard-chip8.tsx
+++ b/examples/web/react/components/keyboard-chip8/keyboard-chip8.tsx
@@ -1,30 +1,79 @@
-import React, { FC } from "react";
+import React, { FC, useState } from "react";
 
 import "./keyboard-chip8.css";
 
 type KeyboardChip8Props = {
+    focusable?: boolean;
     style?: string[];
     onKeyDown?: (key: string) => void;
+    onKeyUp?: (key: string) => void;
 };
 
 export const KeyboardChip8: FC<KeyboardChip8Props> = ({
+    focusable = true,
     style = [],
-    onKeyDown
+    onKeyDown,
+    onKeyUp
 }) => {
     const classes = () => ["keyboard", "keyboard-chip8", ...style].join(" ");
-    const renderKey = (key: string) => {
+    const renderKey = (key: string, styles: string[] = []) => {
+        const [pressed, setPressed] = useState(false);
         return (
             <span
-                className="key"
+                className={["key", pressed ? "pressed" : "", ...styles].join(
+                    " "
+                )}
                 key={key}
-                tabIndex={0}
+                tabIndex={focusable ? 0 : undefined}
                 onKeyDown={(event) => {
                     if (event.key !== "Enter") return;
+                    setPressed(true);
                     onKeyDown && onKeyDown(key);
                     event.stopPropagation();
                     event.preventDefault();
                 }}
-                onClick={() => onKeyDown && onKeyDown(key)}
+                onKeyUp={(event) => {
+                    if (event.key !== "Enter") return;
+                    setPressed(false);
+                    onKeyUp && onKeyUp(key);
+                    event.stopPropagation();
+                    event.preventDefault();
+                }}
+                onBlur={(event) => {
+                    setPressed(false);
+                    onKeyUp && onKeyUp(key);
+                }}
+                onMouseDown={(event) => {
+                    setPressed(true);
+                    onKeyDown && onKeyDown(key);
+                    event.stopPropagation();
+                    event.preventDefault();
+                }}
+                onMouseUp={(event) => {
+                    setPressed(false);
+                    onKeyUp && onKeyUp(key);
+                    event.stopPropagation();
+                    event.preventDefault();
+                }}
+                onMouseLeave={(event) => {
+                    if (!pressed) return;
+                    setPressed(false);
+                    onKeyUp && onKeyUp(key);
+                    event.stopPropagation();
+                    event.preventDefault();
+                }}
+                onTouchStart={(event) => {
+                    setPressed(true);
+                    onKeyDown && onKeyDown(key);
+                    event.stopPropagation();
+                    event.preventDefault();
+                }}
+                onTouchEnd={(event) => {
+                    setPressed(false);
+                    onKeyUp && onKeyUp(key);
+                    event.stopPropagation();
+                    event.preventDefault();
+                }}
             >
                 {key}
             </span>
diff --git a/examples/web/react/components/keyboard-gb/keyboard-gb.tsx b/examples/web/react/components/keyboard-gb/keyboard-gb.tsx
index f6af2b52..18672a13 100644
--- a/examples/web/react/components/keyboard-gb/keyboard-gb.tsx
+++ b/examples/web/react/components/keyboard-gb/keyboard-gb.tsx
@@ -5,12 +5,14 @@ import "./keyboard-gb.css";
 declare const require: any;
 
 type KeyboardGBProps = {
+    focusable?: boolean;
     style?: string[];
     onKeyDown?: (key: string) => void;
     onKeyUp?: (key: string) => void;
 };
 
 export const KeyboardGB: FC<KeyboardGBProps> = ({
+    focusable = true,
     style = [],
     onKeyDown,
     onKeyUp
@@ -28,7 +30,7 @@ export const KeyboardGB: FC<KeyboardGBProps> = ({
                     " "
                 )}
                 key={keyName ?? key}
-                tabIndex={0}
+                tabIndex={focusable ? 0 : undefined}
                 onKeyDown={(event) => {
                     if (event.key !== "Enter") return;
                     setPressed(true);
@@ -43,6 +45,10 @@ export const KeyboardGB: FC<KeyboardGBProps> = ({
                     event.stopPropagation();
                     event.preventDefault();
                 }}
+                onBlur={(event) => {
+                    setPressed(false);
+                    onKeyUp && onKeyUp(key);
+                }}
                 onMouseDown={(event) => {
                     setPressed(true);
                     onKeyDown && onKeyDown(keyName ?? key);
-- 
GitLab