diff --git a/bun.lockb b/bun.lockb
index ea578d9..c6639ba 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/src/App.tsx b/src/App.tsx
index 1ee5347..20f1dd5 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,4 +1,4 @@
-import { Canvas } from "@react-three/fiber";
+import { Canvas, useThree } from "@react-three/fiber";
import { OrbitControls } from "@react-three/drei";
import styles from "./styles.module.scss";
@@ -6,39 +6,105 @@ import "katex/dist/katex.min.css";
import Point from "./components/Point";
import Path from "./components/Path";
import { SettingsBox } from "./SettingsContext";
+import { useCallback, useState } from "react";
+import { atom, useAtom, useSetAtom } from "jotai";
// https://threejs.org/manual/#en/align-html-elements-to-3d
+type coord = [number, number, number];
+const coords: coord[] = [
+ [0, 0, 0],
+ [0, 0, 1],
+ [0, 1, 0],
+ [0, 1, 1],
+ [1, 0, 0],
+ [1, 0, 1],
+ [1, 1, 0],
+ [1, 1, 1],
+];
+
+const ppCoord = (c: coord): string => c.map((n) => n.toString()).join("");
+
+const offset = (a: coord): coord => [a[0] - 0.5, a[1] - 0.5, a[2] - 0.5];
+
+const offsetCoords: [string, coord][] = coords.map((a) => [
+ ppCoord(a),
+ offset(a),
+]);
+
+function getInitialValue() {
+ try {
+ const h = location.hash;
+ if (h.length === 0) return defaultValues;
+ return JSON.parse(atob(h.replace("#", "")));
+ } catch (e) {
+ console.log("error", e);
+ return defaultValues;
+ }
+}
+
+export const stateAtom = atom<{ [_: string]: string }>(getInitialValue());
+
+export const updateStateAtom = atom(null, (get, set, newValue) => {
+ set(stateAtom, newValue);
+ location.hash = btoa(JSON.stringify(newValue));
+});
+
+function AdjustCamera() {
+ useThree(({ camera }) => {
+ camera.position.z = 2;
+ });
+ return <>>;
+}
+
+const paths: [string, [coord, coord]][] = offsetCoords
+ .flatMap((a) => offsetCoords.map((b) => [a, b]))
+ .filter(
+ ([[_a, [a1, a2, a3]], [_b, [b1, b2, b3]]]) =>
+ [a1 === b1 ? 1 : 0, a2 === b2 ? 1 : 0, a3 === b3 ? 1 : 0].reduce(
+ (x, y) => x + y
+ ) === 2 &&
+ a1 <= b1 &&
+ a2 <= b2 &&
+ a3 <= b3
+ )
+ .map(([[aname, acoord], [bname, bcoord]]) => [
+ aname + bname,
+ [acoord, bcoord],
+ ]);
+
+const defaultValues: [string, string] = Object.fromEntries([
+ ...offsetCoords.map(([a]) => [a, ""]),
+ ...paths.map(([a]) => [a, ""]),
+]);
+
+function parseCoord(s: string): coord {
+ return offset(s.split("").map((n) => parseInt(n)));
+}
+
+function parsePath(s: string): [coord, coord] {
+ return [parseCoord(s.substring(0, 3)), parseCoord(s.substring(3, 6))];
+}
+
function App() {
- let coords: [number, number, number][] = [
- [0, 0, 0],
- [0, 0, 1],
- [0, 1, 0],
- [0, 1, 1],
- [1, 0, 0],
- [1, 0, 1],
- [1, 1, 0],
- [1, 1, 1],
- ];
+ const [state] = useAtom(stateAtom);
+ const updateStateFunc = useSetAtom(updateStateAtom);
- coords = coords.map((a) => [a[0] - 0.5, a[1] - 0.5, a[2] - 0.5]);
+ console.log("state", state);
- const paths = coords
- .flatMap((a) => coords.map((b) => [a, b]))
- .filter(
- ([[a1, a2, a3], [b1, b2, b3]]) =>
- [a1 === b1 ? 1 : 0, a2 === b2 ? 1 : 0, a3 === b3 ? 1 : 0].reduce(
- (x, y) => x + y,
- ) === 2 &&
- a1 <= b1 &&
- a2 <= b2 &&
- a3 <= b3,
- );
+ const updateState = useCallback(
+ (z: string, value: string) => {
+ const newState = { ...state, [z]: value };
+ updateStateFunc(newState);
+ },
+ [state]
+ );
return (
diff --git a/src/SettingsContext.tsx b/src/SettingsContext.tsx
index 630f8db..4fe0b82 100644
--- a/src/SettingsContext.tsx
+++ b/src/SettingsContext.tsx
@@ -1,13 +1,25 @@
-import { atom, useAtom } from "jotai";
+import { atom, useAtom, useAtomValue, useSetAtom } from "jotai";
import styles from "./styles.module.scss";
+import { stateAtom, updateStateAtom } from "./App";
+import { useCallback } from "react";
export const showEmptyAtom = atom(true);
export function SettingsBox() {
+ const state = useAtomValue(stateAtom);
+ const updateState = useSetAtom(updateStateAtom);
const [showEmpty, setShowEmpty] = useAtom(showEmptyAtom);
+ const doClear = useCallback(() => {
+ updateState(
+ Object.fromEntries(Object.entries(state).map(([a, _]) => [a, ""]))
+ );
+ }, [state]);
+
return (
+
+
void;
+}
-export default function EditBox() {
- const [value, setValue] = useState("");
+export default function EditBox({ onUpdate, value }: EditBoxProps) {
+ const [innerValue, setInnerValue] = useState("");
const [isEditing, setIsEditing] = useState(false);
const showEmpty = useAtomValue(showEmptyAtom);
+ useEffect(() => {
+ setInnerValue(value);
+ }, [value]);
+
const handleDblClick = useCallback(() => {
if (!isEditing) setIsEditing(true);
}, [isEditing]);
const done = useCallback(
(evt: FormEvent) => {
+ onUpdate?.(innerValue);
evt.preventDefault();
if (isEditing) setIsEditing(false);
},
- [isEditing],
+ [value, isEditing, innerValue]
);
return (
@@ -32,8 +40,8 @@ export default function EditBox() {
// biome-ignore lint/a11y/noAutofocus:
autoFocus={true}
onBlur={done}
- value={value}
- onChange={(evt) => setValue(evt.target.value)}
+ value={innerValue}
+ onChange={(evt) => setInnerValue(evt.target.value)}
placeholder="Type latex code..."
/>
diff --git a/src/components/Path.tsx b/src/components/Path.tsx
index 1ccbb2a..41439dc 100644
--- a/src/components/Path.tsx
+++ b/src/components/Path.tsx
@@ -8,9 +8,11 @@ extend({ MeshLineGeometry, MeshLineMaterial });
export interface PointProps {
start: [number, number, number];
end: [number, number, number];
+ value: string;
+ onEdit?: (newValue: string) => void;
}
-export default function Path({ start, end }: PointProps) {
+export default function Path({ start, end, onEdit, value }: PointProps) {
const midpoint: [number, number, number] = [
(start[0] + end[0]) / 2.0,
(start[1] + end[1]) / 2.0,
@@ -23,7 +25,7 @@ export default function Path({ start, end }: PointProps) {
-
+
>
);
diff --git a/src/components/Point.tsx b/src/components/Point.tsx
index bb9115d..3f0b334 100644
--- a/src/components/Point.tsx
+++ b/src/components/Point.tsx
@@ -3,16 +3,18 @@ import EditBox from "./EditBox";
export interface PointProps {
coord: [number, number, number];
+ value: string;
+ onEdit?: (newValue: string) => void;
}
-export default function Point({ coord }: PointProps) {
+export default function Point({ coord, onEdit, value }: PointProps) {
return (
-
+
);