Skip to content

Commit 6bd1850

Browse files
authored
CLEANUP: Reimplement notebook keyboard shortcuts more simply. (#757)
1 parent 0446f11 commit 6bd1850

File tree

8 files changed

+53
-44
lines changed

8 files changed

+53
-44
lines changed

packages/frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"@solid-primitives/active-element": "^2.1.1",
4040
"@solid-primitives/context": "^0.3.1",
4141
"@solid-primitives/destructure": "^0.2.1",
42-
"@solid-primitives/keyboard": "^1.3.1",
42+
"@solid-primitives/event-listener": "^2.4.3",
4343
"@solid-primitives/timer": "^1.4.1",
4444
"@solidjs/router": "^0.15.3",
4545
"@viz-js/viz": "^3.15.0",

packages/frontend/pnpm-lock.yaml

Lines changed: 4 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/frontend/src/components/completions.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import type { KbdKey } from "@solid-primitives/keyboard";
21
import { For, type JSX, Show, createMemo, createSignal, onMount } from "solid-js";
32

3+
import type { KbdKey } from "../util/keyboard";
4+
45
import "./completions.css";
56

67
/** A possible completion. */
@@ -96,7 +97,7 @@ export function Completions(props: {
9697
<div class="completion-name">{c.name}</div>
9798
<Show when={c.shortcut}>
9899
<div class="completion-shortcut">
99-
<KbdShortcut shortcut={c.shortcut as KbdKey[]} />
100+
<KbdShortcut shortcut={c.shortcut ?? []} />
100101
</div>
101102
</Show>
102103
</div>

packages/frontend/src/diagram/diagram_editor.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
type CellConstructor,
1212
type FormalCellEditorProps,
1313
NotebookEditor,
14-
cellShortcutModifier,
1514
newFormalCell,
1615
} from "../notebook";
1716
import { DocumentBreadcrumbs, DocumentLoadingScreen, Toolbar } from "../page";
@@ -179,7 +178,7 @@ function diagramCellConstructor(meta: InstanceTypeMeta): CellConstructor<Diagram
179178
return {
180179
name,
181180
description,
182-
shortcut: shortcut && [cellShortcutModifier, ...shortcut],
181+
shortcut,
183182
construct() {
184183
return meta.tag === "ObType"
185184
? newFormalCell(newDiagramObjectDecl(meta.obType))

packages/frontend/src/model/model_editor.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
type FormalCellEditorProps,
1313
NotebookEditor,
1414
NotebookUtils,
15-
cellShortcutModifier,
1615
newFormalCell,
1716
} from "../notebook";
1817
import { DocumentBreadcrumbs, DocumentLoadingScreen, Toolbar } from "../page";
@@ -195,7 +194,7 @@ function modelCellConstructor(meta: ModelTypeMeta): CellConstructor<ModelJudgmen
195194
return {
196195
name,
197196
description,
198-
shortcut: shortcut && [cellShortcutModifier, ...shortcut],
197+
shortcut,
199198
construct() {
200199
return meta.tag === "ObType"
201200
? newFormalCell(newObjectDecl(meta.obType))

packages/frontend/src/notebook/notebook_editor.tsx

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { getReorderDestinationIndex } from "@atlaskit/pragmatic-drag-and-drop-hitbox/util/get-reorder-destination-index";
22
import { monitorForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
33
import type { DocHandle, Prop } from "@automerge/automerge-repo";
4-
import { type KbdKey, createShortcut } from "@solid-primitives/keyboard";
4+
import { makeEventListener } from "@solid-primitives/event-listener";
55
import ListPlus from "lucide-solid/icons/list-plus";
66
import {
77
type Component,
@@ -17,6 +17,7 @@ import invariant from "tiny-invariant";
1717

1818
import type { Cell, Notebook } from "catlog-wasm";
1919
import { type Completion, IconButton } from "../components";
20+
import { type KbdKey, type ModifierKey, keyEventHasModifier } from "../util/keyboard";
2021
import {
2122
type CellActions,
2223
type FormalCellEditorProps,
@@ -137,7 +138,7 @@ export function NotebookEditor<T>(props: {
137138
{
138139
name: "Text",
139140
description: "Start writing text",
140-
shortcut: [cellShortcutModifier, "T"],
141+
shortcut: ["T"],
141142
construct: () => newRichTextCell(),
142143
},
143144
...(props.cellConstructors ?? []),
@@ -149,21 +150,27 @@ export function NotebookEditor<T>(props: {
149150
return {
150151
name,
151152
description,
152-
shortcut,
153+
shortcut: shortcut && [cellShortcutModifier, ...shortcut],
153154
onComplete: () => replaceCellWith(i, cc.construct()),
154155
};
155156
});
156157

157-
createEffect(() => {
158+
makeEventListener(window, "keydown", (evt) => {
158159
if (props.noShortcuts) {
159160
return;
160161
}
161-
for (const command of insertCommands()) {
162-
if (command.shortcut) {
163-
createShortcut(command.shortcut, () => command.onComplete?.());
162+
if (keyEventHasModifier(evt, cellShortcutModifier)) {
163+
for (const command of insertCommands()) {
164+
if (command.shortcut && evt.key.toUpperCase() === command.shortcut[0]) {
165+
command.onComplete?.();
166+
return evt.preventDefault();
167+
}
164168
}
165169
}
166-
createShortcut(["Shift", "Enter"], () => addAfterActiveCell(newStemCell()));
170+
if (evt.shiftKey && evt.key === "Enter") {
171+
addAfterActiveCell(newStemCell());
172+
return evt.preventDefault();
173+
}
167174
});
168175

169176
// Set up drag and drop for notebook cells. Each cell reports to the
@@ -369,4 +376,4 @@ The choice is platform-specific: On Mac, the Alt/Option key remaps keys, so we
369376
use Control, whereas on other platforms Control tends to be already bound in
370377
other shortcuts, so we Alt.
371378
*/
372-
export const cellShortcutModifier: KbdKey = navigator.userAgent.includes("Mac") ? "Control" : "Alt";
379+
const cellShortcutModifier: ModifierKey = navigator.userAgent.includes("Mac") ? "Control" : "Alt";

packages/frontend/src/theory/theory.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import type { KbdKey } from "@solid-primitives/keyboard";
2-
31
import type { DblModel, DblTheory, MorType, ObOp, ObType } from "catlog-wasm";
42
import { MorTypeIndex, ObTypeIndex } from "catlog-wasm";
53
import type { DiagramAnalysisComponent, ModelAnalysisComponent } from "../analysis";
64
import { uniqueIndexArray } from "../util/indexing";
5+
import type { KbdKey } from "../util/keyboard";
76
import type { ArrowStyle } from "../visualization";
87

98
/** A double theory configured for the frontend.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/** Utilities for keyboard events and shortcuts.
2+
3+
The types `ModifierKey` and `KbdKey` are borrowed from
4+
`@solid-primitives/keyboard`, a package that we're no longer using.
5+
6+
@module
7+
*/
8+
9+
export type ModifierKey = "Alt" | "Control" | "Meta" | "Shift";
10+
export type KbdKey = ModifierKey | (string & {});
11+
12+
/** Returns whether the modifier key is active in the keyboard event. */
13+
export function keyEventHasModifier(evt: KeyboardEvent, key: ModifierKey): boolean {
14+
switch (key) {
15+
case "Alt":
16+
return evt.altKey;
17+
case "Control":
18+
return evt.ctrlKey;
19+
case "Meta":
20+
return evt.metaKey;
21+
case "Shift":
22+
return evt.shiftKey;
23+
default:
24+
throw new Error(`Key is not a modifier: ${key}`);
25+
}
26+
}

0 commit comments

Comments
 (0)