From b4d7b00dd1add8e1cffb7771539fa6c419b64846 Mon Sep 17 00:00:00 2001
From: Sam Nystrom <sam@samnystrom.dev>
Date: Wed, 13 Mar 2024 22:37:58 +0000
Subject: refactor: extract nodes/sockets to components

---
 src/node.tsx | 208 -----------------------------------------------------------
 1 file changed, 208 deletions(-)
 delete mode 100644 src/node.tsx

(limited to 'src/node.tsx')

diff --git a/src/node.tsx b/src/node.tsx
deleted file mode 100644
index cb72734..0000000
--- a/src/node.tsx
+++ /dev/null
@@ -1,208 +0,0 @@
-import { createContext, FunctionComponent, ComponentChildren } from 'preact';
-import { useContext } from 'preact/hooks';
-import { batch, Signal } from '@preact/signals';
-import { InputSocket } from './dataflow.ts';
-import { cls } from './util.ts';
-import './node.css';
-
-export type SocketHandler = (nodeId: number, socket: string, event: MouseEvent) => void;
-export interface SocketHandlers {
-	onOutMouseDown?: SocketHandler;
-	onOutMouseUp?: SocketHandler;
-	onInMouseDown?: SocketHandler;
-	onInMouseUp?: SocketHandler;
-}
-
-export const SocketHandlers = createContext<SocketHandlers>({});
-export const NodeId = createContext<number>(0);
-
-export interface NodeComponentProps<I extends {}> {
-	id: number;
-	x: Signal<number>;
-	y: Signal<number>;
-	inputs: { [Property in keyof I]: InputSocket<I[Property]> };
-}
-export type NodeComponent<I extends {}> = FunctionComponent<NodeComponentProps<I>>;
-
-export interface NodeInfo<I extends {}, O extends {}> {
-	component: NodeComponent<I>;
-	func: (inputs: I) => O;
-	inputs: I;
-}
-
-interface SocketProps {
-	name: string;
-	onMouseDown?: SocketHandler;
-	onMouseUp?: SocketHandler;
-}
-
-const Socket = ({ name, onMouseDown, onMouseUp }: SocketProps) => {
-	const nodeId = useContext(NodeId);
-	const wrap = (func?: SocketHandler) => (event: MouseEvent) => func && func(nodeId, name, event);
-	return (
-		<svg
-			width="10"
-			height="10"
-			viewBox="0 0 16 16"
-			onMouseDown={wrap(onMouseDown)}
-			onMouseUp={wrap(onMouseUp)}
-		>
-			<circle cx="8" cy="8" r="7" stroke="black" stroke-width="1" />
-		</svg>
-	);
-};
-
-const InSocket = ({ name }: { name: string }) => {
-	const handlers = useContext(SocketHandlers);
-	return (
-		<Socket name={name} onMouseDown={handlers.onInMouseDown} onMouseUp={handlers.onInMouseUp} />
-	);
-};
-
-const OutSocket = ({ name }: { name: string }) => {
-	const handlers = useContext(SocketHandlers);
-	return (
-		<Socket name={name} onMouseDown={handlers.onOutMouseDown} onMouseUp={handlers.onOutMouseUp} />
-	);
-};
-
-export interface InputProps<T> {
-	name: string;
-	label: string;
-	value: InputSocket<T>;
-}
-
-export const InputAny = ({ name, label }: Omit<InputProps<any>, 'value'>) => {
-	return (
-		<li class="in">
-			<InSocket name={name} />
-			{label}
-		</li>
-	);
-};
-
-export const InputArray = ({ name, label }: Omit<InputProps<any>, 'value'>) => {
-	return (
-		<li class="in number">
-			<InSocket name={name} />
-			{label}
-		</li>
-	);
-};
-
-const InputNum = (parseFunc: (string) => number) => ({ name, label, value }: InputProps<number>) => {
-	const onInput = (event: InputEvent) => {
-		value.value = parseFunc((event.target as HTMLInputElement).value);
-	}
-	return (
-		<li class={'in number' + (value.link.value ? ' linked' : '')}>
-			<InSocket name={name} />
-			<span>{label}</span>
-			<input type="number" value={value.manual.value} onInput={onInput} />
-		</li>
-	);
-};
-
-export const InputNumber = InputNum(parseFloat);
-export const InputInteger = InputNum(parseInt);
-
-export const InputVector = ({ name, label, value }: InputProps<[number, number, number]>) => {
-	const onInput = (i: 0 | 1 | 2) => (event: InputEvent) => {
-		const newValue: [number, number, number] = [...value.value];
-		newValue[i] = parseFloat((event.target as HTMLInputElement).value);
-		value.value = newValue;
-	};
-	return (
-		<li class={'in vector' + (value.link.value ? ' linked' : '')}>
-			<div>
-				<InSocket name={name} />
-				{label}
-			</div>
-			<input type="number" value={value.value[0]} onInput={onInput(0)} />
-			<input type="number" value={value.value[1]} onInput={onInput(1)} />
-			<input type="number" value={value.value[2]} onInput={onInput(2)} />
-		</li>
-	);
-};
-
-export interface InputSelectProps extends InputProps<string> {
-	options: string[] | Record<string, string[]>;
-}
-
-export const InputSelect = ({ name, label, value, options }: InputSelectProps) => {
-	const onChange = (event: InputEvent) => {
-		value.value = (event.target as HTMLSelectElement).value;
-	}
-	return (
-		<li class={'in select' + (value.link.value ? ' linked' : '')}>
-			<InSocket name={name} />
-			<select aria-label={label} onChange={onChange}>
-				{Array.isArray(options)
-					? options.map(opt => <option value={opt}>{opt}</option>)
-					: Object.entries(options).map(([label, group]) => (
-						<optgroup label={label}>
-							{group.map(opt => <option value={opt}>{opt}</option>)}
-						</optgroup>
-					))
-				}
-			</select>
-		</li>
-	);
-};
-
-export interface OutputProps {
-	name: string;
-	label: string;
-}
-
-const Output = ({ name, label, type }: OutputProps & { type: string }) => {
-	return (
-		<li class={'out ' + type}>
-			{label}
-			<OutSocket name={name} />
-		</li>
-	);
-};
-
-export const OutputNumber = (props: OutputProps) => <Output {...props} type="number" />;
-export const OutputVector = (props: OutputProps) => <Output {...props} type="vector" />;
-
-export interface NodeShellProps {
-	id: number;
-	name: string;
-	x: Signal<number>;
-	y: Signal<number>;
-	children: ComponentChildren;
-}
-
-export const NodeShell = ({ id, name, x, y, children }: NodeShellProps) => {
-	const onMouseDown = (event: MouseEvent) => {
-		event.stopPropagation();
-
-		const onMouseMove = (event: MouseEvent) => batch(() => {
-			x.value += event.movementX;
-			y.value += event.movementY;
-		});
-
-		const onMouseUp = () => {
-			window.removeEventListener('mousemove', onMouseMove);
-			window.removeEventListener('mouseup', onMouseUp);
-		};
-
-		window.addEventListener('mousemove', onMouseMove);
-		window.addEventListener('mouseup', onMouseUp);
-	};
-
-	return (
-		<foreignObject x={x} y={y} width="0" height="0" class="__NodeShell">
-			<details open tabindex={0} class="node" onMouseDown={onMouseDown}>
-				<summary><span onClick={e => e.stopPropagation()}>{name}</span></summary>
-				<ul>
-					<NodeId.Provider value={id}>
-						{children}
-					</NodeId.Provider>
-				</ul>
-			</details>
-		</foreignObject>
-	);
-};
\ No newline at end of file
-- 
cgit v1.2.3

