From ac83dd4a08bdbab6df270d6dae8d9e2d6d619342 Mon Sep 17 00:00:00 2001 From: Sam Nystrom Date: Wed, 6 Mar 2024 20:52:45 +0000 Subject: init --- src/node.tsx | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 src/node.tsx (limited to 'src/node.tsx') diff --git a/src/node.tsx b/src/node.tsx new file mode 100644 index 0000000..211398e --- /dev/null +++ b/src/node.tsx @@ -0,0 +1,208 @@ +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 styles from './node.module.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({}); +export const NodeId = createContext(0); + +export interface NodeComponentProps { + id: number; + x: Signal; + y: Signal; + inputs: { [Property in keyof I]: InputSocket }; +} +export type NodeComponent = FunctionComponent>; + +export interface NodeInfo { + component: NodeComponent; + 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 ( + + + + ); +}; + +const InSocket = ({ name }: { name: string }) => { + const handlers = useContext(SocketHandlers); + return ( + + ); +}; + +const OutSocket = ({ name }: { name: string }) => { + const handlers = useContext(SocketHandlers); + return ( + + ); +}; + +export interface InputProps { + name: string; + label: string; + value: InputSocket; +} + +export const InputAny = ({ name, label }: Omit, 'value'>) => { + return ( +
  • + + {label} +
  • + ); +}; + +export const InputArray = ({ name, label }: Omit, 'value'>) => { + return ( +
  • + + {label} +
  • + ); +}; + +const InputNum = (parseFunc: (string) => number) => ({ name, label, value }: InputProps) => { + const onInput = (event: InputEvent) => { + value.value = parseFunc((event.target as HTMLInputElement).value); + } + return ( +
  • + + {label} + +
  • + ); +}; + +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 ( +
  • +
    + + {label} +
    + + + +
  • + ); +}; + +export interface InputSelectProps extends InputProps { + options: string[] | Record; +} + +export const InputSelect = ({ name, label, value, options }: InputSelectProps) => { + const onChange = (event: InputEvent) => { + value.value = (event.target as HTMLSelectElement).value; + } + return ( +
  • + + +
  • + ); +}; + +export interface OutputProps { + name: string; + label: string; +} + +const Output = ({ name, label, type }: OutputProps & { type: string }) => { + return ( +
  • + {label} + +
  • + ); +}; + +export const OutputNumber = (props: OutputProps) => ; +export const OutputVector = (props: OutputProps) => ; + +export interface NodeShellProps { + id: number; + name: string; + x: Signal; + y: Signal; + 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 ( + +
    + e.stopPropagation()}>{name} +
      + + {children} + +
    +
    +
    + ); +}; \ No newline at end of file -- cgit v1.2.3