feat: budget crud actions

This commit is contained in:
Max Koon
2025-12-06 23:02:28 -05:00
parent 76f2a43bd0
commit 27f6e627d4
20 changed files with 445 additions and 113 deletions

View File

@@ -16,9 +16,11 @@ export function ShortcutDebug() {
bottom: 0,
right: 0,
backgroundColor: "black",
padding: 10,
}}
>
<Text style={{ color: "red", fontFamily: "mono" }}>
<Text style={{ color: "red", fontFamily: "mono" }}>Registered:</Text>
<Text style={{ color: "red", fontFamily: "mono", textAlign: "right" }}>
{entries
.values()
.map(([key, _]) => key)

View File

@@ -1,10 +1,23 @@
import type { ReactNode } from "react";
import { keysStore } from "./store";
import type { KeyName } from "./types";
const KEY_MAP: { [k: string]: KeyName } = {
Escape: "escape",
ArrowUp: "up",
ArrowDown: "down",
ArrowLeft: "left",
ArrowRight: "right",
};
if (typeof window !== "undefined") {
window.addEventListener("keydown", (e) => {
const fn = keysStore.getHandler(e.key);
fn?.();
const key = Object.hasOwn(KEY_MAP, e.key) ? KEY_MAP[e.key]! : e.key;
const fn = keysStore.getHandler(key);
// console.log(e.key);
if (!fn) return;
e.preventDefault();
fn();
});
}

View File

@@ -1,14 +1,18 @@
import { useEffect, useRef } from "react";
import { keysStore } from "./store";
import type { Key } from "./types";
import { enforceKeyOptions } from "./util";
export const useShortcut = (key: string, handler: () => void) => {
export const useShortcut = (key: Key, handler: () => void) => {
const keyOptions = enforceKeyOptions(key);
const keyName = keyOptions.name;
const ref = useRef(handler);
ref.current = handler;
useEffect(() => {
keysStore.register(key, ref);
keysStore.register(keyName, ref);
return () => {
keysStore.deregister(key);
keysStore.deregister(keyName);
};
}, []);
};

View File

@@ -1,3 +1,4 @@
export * from "./Debug";
export * from "./Provider";
export * from "./store";
export * from "./hooks";
export * from "./types";

View File

@@ -0,0 +1,52 @@
export type KeyName =
| "0"
| "1"
| "2"
| "3"
| "4"
| "5"
| "6"
| "7"
| "8"
| "9"
| "a"
| "b"
| "c"
| "d"
| "e"
| "f"
| "g"
| "h"
| "i"
| "j"
| "k"
| "l"
| "m"
| "n"
| "o"
| "p"
| "q"
| "r"
| "s"
| "t"
| "u"
| "v"
| "w"
| "x"
| "y"
| "z"
| ":"
| "up"
| "down"
| "left"
| "right"
| "return"
| "escape";
export type Key = KeyName | KeyOptions;
export interface KeyOptions {
name: KeyName;
ctrl?: boolean;
shift?: boolean;
}

View File

@@ -0,0 +1,9 @@
import type { Key, KeyOptions } from "./types";
export function enforceKeyOptions(key: Key): KeyOptions {
return typeof key == "string"
? {
name: key,
}
: key;
}