feat: add tui app
This commit is contained in:
15
packages/ui/src/index.tsx
Normal file
15
packages/ui/src/index.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Text } from "react-native";
|
||||
import { List } from "./list";
|
||||
import { useQuery } from "@rocicorp/zero/react";
|
||||
import { queries } from '@money/shared';
|
||||
|
||||
export function Settings() {
|
||||
const [items] = useQuery(queries.getItems(null));
|
||||
|
||||
return <List
|
||||
items={items}
|
||||
renderItem={({ item, isSelected }) => <Text style={{ color: isSelected ? 'white' : 'black' }}>{item.name}</Text>}
|
||||
/>
|
||||
}
|
||||
|
||||
|
||||
30
packages/ui/src/list.tsx
Normal file
30
packages/ui/src/list.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import { useState, type ReactNode } from "react";
|
||||
import { View, Text } from "react-native";
|
||||
import { useKeyboard } from "./useKeyboard";
|
||||
|
||||
export type ListProps<T> = {
|
||||
items: T[],
|
||||
renderItem: (props: { item: T, isSelected: boolean }) => ReactNode;
|
||||
};
|
||||
export function List<T>({ items, renderItem }: ListProps<T>) {
|
||||
const [idx, setIdx] = useState(0);
|
||||
|
||||
useKeyboard((key) => {
|
||||
if (key.name == 'j') {
|
||||
setIdx((prevIdx) => prevIdx + 1 < items.length ? prevIdx + 1 : items.length - 1);
|
||||
} else if (key.name == 'k') {
|
||||
setIdx((prevIdx) => prevIdx == 0 ? 0 : prevIdx - 1);
|
||||
} else if (key.name == 'g' && key.shift) {
|
||||
setIdx(items.length - 1);
|
||||
}
|
||||
}, [items]);
|
||||
|
||||
return (
|
||||
<View>
|
||||
{items.map((item, index) => <View style={{ backgroundColor: index == idx ? 'black' : undefined }}>
|
||||
{renderItem({ item, isSelected: index == idx })}
|
||||
</View>)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
5
packages/ui/src/useKeyboard.ts
Normal file
5
packages/ui/src/useKeyboard.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { useKeyboard as useOpentuiKeyboard } from "@opentui/react";
|
||||
|
||||
export function useKeyboard(handler: Parameters<typeof useOpentuiKeyboard>[0], _deps: any[] = []) {
|
||||
return useOpentuiKeyboard(handler);
|
||||
}
|
||||
35
packages/ui/src/useKeyboard.web.ts
Normal file
35
packages/ui/src/useKeyboard.web.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { useEffect } from "react";
|
||||
import type { KeyboardEvent } from "react";
|
||||
import type { KeyEvent } from "@opentui/core";
|
||||
|
||||
|
||||
export function useKeyboard(handler: (key: KeyEvent) => void, deps: any[] = []) {
|
||||
useEffect(() => {
|
||||
const handlerWeb = (event: KeyboardEvent) => {
|
||||
// @ts-ignore
|
||||
handler({
|
||||
name: event.key.toLowerCase(),
|
||||
ctrl: event.ctrlKey,
|
||||
meta: event.metaKey,
|
||||
shift: event.shiftKey,
|
||||
option: event.metaKey,
|
||||
sequence: '',
|
||||
number: false,
|
||||
raw: '',
|
||||
eventType: 'press',
|
||||
source: "raw",
|
||||
code: event.code,
|
||||
super: false,
|
||||
hyper: false,
|
||||
capsLock: false,
|
||||
numLock: false,
|
||||
baseCode: event.keyCode,
|
||||
});
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
window.addEventListener("keydown", handlerWeb);
|
||||
// @ts-ignore
|
||||
return () => window.removeEventListener("keydown", handlerWeb);
|
||||
}, deps);
|
||||
}
|
||||
Reference in New Issue
Block a user