import { Dataspace, Turn, Dataflow } from '@syndicate-lang/core'; import { boot as bootHtml, template, Anchor } from '@syndicate-lang/html'; message type Key(key: string); message type Mouse(what: string, x: number, y: number); assertion type Status(status: string); Dataspace.boot(ds => { bootHtml(ds); at ds { spawn named 'input-driver' { const container = document.getElementById('container')!; const facet = Turn.activeFacet; facet.preventInertCheck(); const sendMouseEvent = (what: string) => (e: PointerEvent) => facet.turn(() => { const { left, top } = container.getBoundingClientRect(); send message Mouse(what, e.clientX - left, e.clientY - top); }); container.addEventListener('pointerdown', sendMouseEvent('down')); container.addEventListener('pointermove', sendMouseEvent('move')); container.addEventListener('pointerup', sendMouseEvent('up')); container.addEventListener('keydown', (e) => facet.turn(() => { send message Key(e.key); })); } const WIDTH = 50; const HEIGHT = 50; function dragBehaviour(x: Dataflow.Field, y: Dataflow.Field) { const inBounds = (dx: number, dy: number) => dx >= 0 && dy >= 0 && dx < WIDTH && dy < HEIGHT; function awaitClick(status: string) { assert Status(status); on message Mouse('down', $dX: number, $dY: number) => { if (inBounds(dX - x.value, dY - y.value)) { stop { react { assert Status('Intermediate'); const [oX, oY] = [x.value, y.value]; stop on message Mouse('up', _, _) => react { awaitClick('Clicked!'); } stop on message Key('Escape') => react { awaitClick('Cancelled!'); } stop on message Mouse('move', $nX: number, $nY: number) => react { assert Status('Dragging'); stop on message Mouse('up', _, _) => react { awaitClick('Dragged!'); } stop on message Key('Escape') => react { [x.value, y.value] = [oX, oY]; awaitClick('Cancelled!'); } [x.value, y.value] = [oX + nX - dX, oY + nY - dY]; on message Mouse('move', $nX: number, $nY: number) => { [x.value, y.value] = [oX + nX - dX, oY + nY - dY]; } } } } } } } react { awaitClick('Waiting'); } } spawn named 'model' { const ui = new Anchor(); field x: number = 24; field y: number = 24; assert ui.html('#container', template`
`); dragBehaviour(x, y); } spawn named 'status' { const ui = new Anchor(); during Status($s: string) => assert ui.html('#status', template`${s}`); } } });