Skip to content

Commit

Permalink
refactor: rename EventButton and add Glossary section to README
Browse files Browse the repository at this point in the history
  • Loading branch information
mikerourke committed Dec 2, 2024
1 parent c28e424 commit 87fedc2
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 45 deletions.
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Keytar

Handle keyboard and mouse events in the browser.
Handle keyboard and mouse events using bitflags.
Check out the [documentation](https://laserware.github.io/keytar/) for the API.

## Overview
Expand Down Expand Up @@ -50,3 +50,13 @@ function handleKeyDown(event: KeyboardEvent): void {
});
}
```

## Glossary

The following terms are used throughout the codebase to describe operations that can be performed with either the keyboard or mouse.

- A `Key` is any non-modifier keyboard key (e.g. the letter `a` or the `Delete` key).
- A `Modifier` is the modifier key that can be used in combination with a `Key` (e.g. `Shift` or `Alt`).
- A `MouseButton` represents the clicked button that corresponds to the [MouseEvent.buttons](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons) property.
- A `Token` can be a `Key`, `Modifier`, or `MouseButton` (i.e. a union type).
- A `Chord` is a `Token` or `number` that represents a combination of `Token` values combined using the [bitwise OR (`|`) operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_OR).
4 changes: 2 additions & 2 deletions src/__tests__/getChordDisplay.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getChordDisplay } from "../getChordDisplay.ts";
import { EventButton, Key, Modifier, MouseButton } from "../types.ts";
import { Key, Modifier, MouseButton, MouseEventButton } from "../types.ts";

vi.mock("@laserware/arcade", async (importActual) => {
const mod = await importActual();
Expand Down Expand Up @@ -34,7 +34,7 @@ describe("the getChordDisplay function", () => {

it("returns the chord display for a mouse event", () => {
const event = new MouseEvent("mousedown", {
buttons: EventButton.Left,
buttons: MouseEventButton.Left,
altKey: true,
ctrlKey: true,
metaKey: true,
Expand Down
16 changes: 8 additions & 8 deletions src/__tests__/isChordPressed.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { isPlatform } from "@laserware/arcade";

import { getChordDisplay } from "../getChordDisplay.ts";
import { isChordPressed } from "../isChordPressed.ts";
import { EventButton, Key, Modifier, MouseButton } from "../types.ts";
import { Key, Modifier, MouseButton, MouseEventButton } from "../types.ts";

vi.mock("@laserware/arcade");

Expand Down Expand Up @@ -199,7 +199,7 @@ describe("the isChordPressed function", () => {
vi.mocked(isPlatform).mockImplementationOnce((platform: string) => platform === "mac");

// prettier-ignore
const event = new MouseEvent("mousedown", { altKey: true, ctrlKey: false, metaKey: false, shiftKey: false, buttons: EventButton.Left });
const event = new MouseEvent("mousedown", { altKey: true, ctrlKey: false, metaKey: false, shiftKey: false, buttons: MouseEventButton.Left });

const result = isChordPressed(event, Modifier.Alt | MouseButton.Left);

Expand Down Expand Up @@ -245,32 +245,32 @@ describe("the isChordPressed function", () => {
// prettier-ignore
it.concurrent.each([
{
event: new MouseEvent("keydown", { buttons: EventButton.Left, altKey: false, ctrlKey: false, metaKey: false, shiftKey: false }),
event: new MouseEvent("keydown", { buttons: MouseEventButton.Left, altKey: false, ctrlKey: false, metaKey: false, shiftKey: false }),
chord: MouseButton.Left,
display: getChordDisplay(MouseButton.Left),
},
{
event: new MouseEvent("keydown", { buttons: EventButton.Right, altKey: true, ctrlKey: false, metaKey: false, shiftKey: false }),
event: new MouseEvent("keydown", { buttons: MouseEventButton.Right, altKey: true, ctrlKey: false, metaKey: false, shiftKey: false }),
chord: Modifier.Alt | MouseButton.Right,
display: getChordDisplay(Modifier.Alt | MouseButton.Right),
},
{
event: new MouseEvent("keydown", { buttons: EventButton.Auxiliary, altKey: true, ctrlKey: false, metaKey: false, shiftKey: true }),
event: new MouseEvent("keydown", { buttons: MouseEventButton.Auxiliary, altKey: true, ctrlKey: false, metaKey: false, shiftKey: true }),
chord: Modifier.Alt | Modifier.Shift | MouseButton.Auxiliary,
display: getChordDisplay(Modifier.Alt | Modifier.Shift | MouseButton.Auxiliary),
},
{
event: new MouseEvent("keydown", { buttons: EventButton.BrowserBack, altKey: true, ctrlKey: true, metaKey: false, shiftKey: true }),
event: new MouseEvent("keydown", { buttons: MouseEventButton.BrowserBack, altKey: true, ctrlKey: true, metaKey: false, shiftKey: true }),
chord: Modifier.Alt | Modifier.Ctrl | Modifier.Shift | MouseButton.BrowserBack,
display: getChordDisplay(Modifier.Alt | Modifier.Ctrl | Modifier.Shift | MouseButton.BrowserBack),
},
{
event: new MouseEvent("keydown", { buttons: EventButton.BrowserForward, altKey: true, ctrlKey: true, metaKey: true, shiftKey: true }),
event: new MouseEvent("keydown", { buttons: MouseEventButton.BrowserForward, altKey: true, ctrlKey: true, metaKey: true, shiftKey: true }),
chord: Modifier.Alt | Modifier.Cmd | Modifier.Ctrl | Modifier.Shift | MouseButton.BrowserForward,
display: getChordDisplay(Modifier.Alt | Modifier.Cmd | Modifier.Ctrl | Modifier.Shift | MouseButton.BrowserForward),
},
{
event: new MouseEvent("keydown", { buttons: EventButton.None, altKey: true, ctrlKey: false, metaKey: false, shiftKey: true }),
event: new MouseEvent("keydown", { buttons: MouseEventButton.None, altKey: true, ctrlKey: false, metaKey: false, shiftKey: true }),
chord: Modifier.Alt | Modifier.Shift | MouseButton.None,
display: getChordDisplay(Modifier.Alt | Modifier.Shift | MouseButton.None),
},
Expand Down
8 changes: 4 additions & 4 deletions src/getChordDisplay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import {
eventKeyByKeyEnumTable,
keyEnumByEventKeyTable,
modifierByModifierStatusTable,
mouseButtonByEventButtonTable,
mouseButtonByMouseEventButtonTable,
tokensDisplayTable,
} from "./tables.ts";
import {
EventButton,
Key,
Modifier,
MouseButton,
MouseEventButton,
type Chord,
type ChordedEvent,
type Token,
Expand Down Expand Up @@ -151,9 +151,9 @@ function eventToTokens(event: ChordedEvent): TokenSet {
}

if ("buttons" in event) {
const eventButton = event.buttons as EventButton;
const eventButton = event.buttons as MouseEventButton;

const mouseButton = mouseButtonByEventButtonTable.get(eventButton);
const mouseButton = mouseButtonByMouseEventButtonTable.get(eventButton);
if (mouseButton !== undefined) {
tokens.add(mouseButton);
}
Expand Down
14 changes: 7 additions & 7 deletions src/isChordPressed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { isPlatform } from "@laserware/arcade";
import { getKeyForLookup, hasTokenInChord, stripToken } from "./common.ts";
import { eventKeyByKeyEnumTable } from "./tables.ts";
import {
EventButton,
Modifier,
MouseButton,
MouseEventButton,
type Chord,
type ChordedEvent,
} from "./types.ts";
Expand All @@ -29,25 +29,25 @@ export function isChordPressed(
let lookup = chord;

if ("buttons" in event) {
const button = event.buttons as EventButton;
const button = event.buttons as MouseEventButton;

if (button === EventButton.BrowserForward) {
if (button === MouseEventButton.BrowserForward) {
lookup = stripToken(lookup, MouseButton.BrowserForward);
}

if (button === EventButton.BrowserBack) {
if (button === MouseEventButton.BrowserBack) {
lookup = stripToken(lookup, MouseButton.BrowserBack);
}

if (button === EventButton.Auxiliary) {
if (button === MouseEventButton.Auxiliary) {
lookup = stripToken(lookup, MouseButton.Auxiliary);
}

if (button === EventButton.Right) {
if (button === MouseEventButton.Right) {
lookup = stripToken(lookup, MouseButton.Right);
}

if (button === EventButton.Left) {
if (button === MouseEventButton.Left) {
lookup = stripToken(lookup, MouseButton.Left);
}

Expand Down
2 changes: 1 addition & 1 deletion src/printableChars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function isPrintableCharPressed(event: ChordedEvent): boolean {
* @returns `true` if the specified `key` is a printable character.
*/
export function isPrintableChar(key: string): boolean {
if (/[a-z0-9]/gi.test(key) && key.length === 1) {
if (key.match(/\S/) && key.length === 1) {
return true;
}

Expand Down
21 changes: 12 additions & 9 deletions src/tables.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { isPlatform } from "@laserware/arcade";

import {
EventButton,
Key,
Modifier,
MouseButton,
MouseEventButton,
type Chord,
type KeyModifierState,
} from "./types.ts";
Expand All @@ -29,17 +29,20 @@ export const modifierByModifierStatusTable = new Map<
* Table for looking up the {@linkcode MouseButton} that corresponds to the
* [`event.buttons` property](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons)
* on a [MouseEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent)
* (represented by {@linkcode EventButton}).
* (represented by {@linkcode MouseEventButton}).
*
* @internal
*/
export const mouseButtonByEventButtonTable = new Map<EventButton, MouseButton>([
[EventButton.None, MouseButton.None],
[EventButton.Left, MouseButton.Left],
[EventButton.Right, MouseButton.Right],
[EventButton.Auxiliary, MouseButton.Auxiliary],
[EventButton.BrowserBack, MouseButton.BrowserBack],
[EventButton.BrowserForward, MouseButton.BrowserForward],
export const mouseButtonByMouseEventButtonTable = new Map<
MouseEventButton,
MouseButton
>([
[MouseEventButton.None, MouseButton.None],
[MouseEventButton.Left, MouseButton.Left],
[MouseEventButton.Right, MouseButton.Right],
[MouseEventButton.Auxiliary, MouseButton.Auxiliary],
[MouseEventButton.BrowserBack, MouseButton.BrowserBack],
[MouseEventButton.BrowserForward, MouseButton.BrowserForward],
]);

/**
Expand Down
26 changes: 13 additions & 13 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,25 @@ export enum Key {
Quote = 80,
}

/**
* Keyboard modifier keys (e.g. Shift, Alt, etc.).
*/
export enum Modifier {
/* 256 */ Alt = 1 << 8,
/* 512 */ Cmd = 1 << 9,
/* 1024 */ Ctrl = 1 << 10,
/* 1536 */ CmdOrCtrl = Cmd | Ctrl,
/* 2048 */ Shift = 1 << 11,
}

/**
* These are taken directly from the actual value from the event. We're using
* the bit-shifted representation to stay consistent with {@linkcode Modifier}.
*
* See the [buttons](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons)
* documentation on MDN for additional details.
*/
export enum EventButton {
export enum MouseEventButton {
/* 0 */ None = 0,
/* 1 */ Left = 1 << 0,
/* 2 */ Right = 1 << 1,
Expand All @@ -135,25 +146,14 @@ export enum EventButton {
/* 16 */ BrowserForward = 1 << 4,
}

/**
* Keyboard modifier keys (e.g. Shift, Alt, etc.).
*/
export enum Modifier {
/* 256 */ Alt = 1 << 8,
/* 512 */ Cmd = 1 << 9,
/* 1024 */ Ctrl = 1 << 10,
/* 1536 */ CmdOrCtrl = Cmd | Ctrl,
/* 2048 */ Shift = 1 << 11,
}

/**
* Represents mouse buttons that could be pressed. These do not match the mouse
* buttons from the [MouseEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent) (which are much lower).
* This is so we can check for a combination of keyboard modifiers and mouse
* buttons (e.g. `Shift` + Left Click).
*/
export enum MouseButton {
/* 4096 */ None = 0,
None = 0,
// We start here so we can include keyboard modifiers:
/* 8192 */ Left = 1 << 13,
/* 16384 */ Right = 1 << 14,
Expand Down

0 comments on commit 87fedc2

Please sign in to comment.