{"_id":"@axocoatl/lattice","name":"@axocoatl/lattice","dist-tags":{"latest":"1.1.0"},"versions":{"1.1.0":{"name":"@axocoatl/lattice","version":"1.1.0","description":"Vanilla Web Components graph canvas — drag nodes, draw edges, live execution state, undo/redo, copy/paste, minimap, auto-layout, virtualization. No build step, no framework. The visual DAG editor for self-coordinating agent systems.","type":"module","main":"./src/index.js","module":"./src/index.js","exports":{".":{"import":"./src/index.js","default":"./src/index.js"},"./viewport":"./src/viewport.js","./selection":"./src/selection.js","./geometry":"./src/geometry.js","./history":"./src/history.js","./layout":"./src/layout.js","./elements/lattice":"./src/lattice.js","./elements/node":"./src/node.js","./elements/handle":"./src/handle.js","./elements/edge":"./src/edge.js","./elements/minimap":"./src/minimap.js","./elements/controls":"./src/controls.js"},"scripts":{"test":"node --test test/unit.mjs && node test/integration.mjs","test:unit":"node --test test/unit.mjs","test:integration":"node test/integration.mjs"},"devDependencies":{"playwright":"^1.49.0"},"keywords":["web-components","custom-elements","graph","flow","dag","canvas","agent","axocoatl","lattice","no-build","vanilla"],"homepage":"https://github.com/axocoatl/axocoatl/tree/main/packages/lattice","repository":{"type":"git","url":"git+https://github.com/axocoatl/axocoatl.git","directory":"packages/lattice"},"bugs":{"url":"https://github.com/axocoatl/axocoatl/issues"},"license":"Apache-2.0","author":{"name":"Axocoatl Contributors"},"publishConfig":{"access":"public"},"sideEffects":["./src/index.js","./src/lattice.js"],"engines":{"node":">=18"},"_id":"@axocoatl/lattice@1.1.0","_nodeVersion":"22.21.1","_npmVersion":"10.9.4","dist":{"integrity":"sha512-yTmr2XQGpOmiEtIQEsYPowNdaX/29djF+5Zm8azdqj2qXWlVjtFe7VJJkqLWlO3VrQpiH8Ic6W/ZM7ZxM3YYHA==","shasum":"38c6684452fb75143d67a781f8331654c97e1c31","tarball":"https://registry.npmjs.org/@axocoatl/lattice/-/lattice-1.1.0.tgz","fileCount":18,"unpackedSize":173599,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDwiJp3azRZZW/Hg0G+wrJRRKlHbDiVPCmQYTan4DRmEgIgDzju7lnZ2UoZpq3zWt5SIofv8WJkR/c9N4XXZ6rAqnE="}]},"_npmUser":{"name":"cubanerick","email":"erick5eche@gmail.com"},"directories":{},"maintainers":[{"name":"cubanerick","email":"erick5eche@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/lattice_1.1.0_1780405815328_0.8836097496519402"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-02T13:10:15.143Z","1.1.0":"2026-06-02T13:10:15.479Z","modified":"2026-06-02T13:10:15.690Z"},"maintainers":[{"name":"cubanerick","email":"erick5eche@gmail.com"}],"description":"Vanilla Web Components graph canvas — drag nodes, draw edges, live execution state, undo/redo, copy/paste, minimap, auto-layout, virtualization. No build step, no framework. The visual DAG editor for self-coordinating agent systems.","homepage":"https://github.com/axocoatl/axocoatl/tree/main/packages/lattice","keywords":["web-components","custom-elements","graph","flow","dag","canvas","agent","axocoatl","lattice","no-build","vanilla"],"repository":{"type":"git","url":"git+https://github.com/axocoatl/axocoatl.git","directory":"packages/lattice"},"author":{"name":"Axocoatl Contributors"},"bugs":{"url":"https://github.com/axocoatl/axocoatl/issues"},"license":"Apache-2.0","readme":"# @axocoatl/lattice\n\n> Vanilla Web Components graph canvas. Drag-to-wire nodes, infinite zoom-pan-snap, no build step, no framework.\n\nA reactive graph editor in plain Web Components and SVG. Framework-agnostic — drop into React, Vue, Svelte, or plain HTML. The visual layer of [Axocoatl](https://github.com/axocoatl/axocoatl), broken out as its own package because vanilla graph canvases shouldn't require pulling in a 200KB framework dependency.\n\n```html\n<script type=\"module\" src=\"https://cdn.jsdelivr.net/npm/@axocoatl/lattice\"></script>\n\n<ax-lattice background=\"dots\" snap=\"20\" fit-view-on-init>\n  <!-- nodes & edges go here (phase B+) -->\n</ax-lattice>\n```\n\n## Why\n\nMost graph editors on the web (React Flow, etc.) ship as React libraries. They're excellent, but they bake your framework choice in and weigh 100–200KB minified gzipped before you write a single component.\n\n`@axocoatl/lattice` is the answer if you want:\n\n- **No build step.** The published source is the dist. Import directly from a CDN or npm.\n- **No framework lock-in.** Custom Elements + Shadow DOM. Works the same inside React, Vue, Svelte, Solid, htmx, or plain HTML.\n- **Small.** Phase A is < 10 KB of source. No framework runtime to pay for.\n- **Themeable via CSS Custom Properties.** Style with `--ax-bg`, `--ax-fg`, `--ax-accent`, no shadow-piercing required for the documented hooks.\n\n## Install\n\n```bash\nnpm install @axocoatl/lattice\n```\n\nOr import directly from a CDN — no install needed:\n\n```html\n<script type=\"module\" src=\"https://cdn.jsdelivr.net/npm/@axocoatl/lattice\"></script>\n```\n\n## Phase C — Handles, edges & drag-to-connect (current)\n\n```html\n<ax-lattice snap=\"20\" background=\"dots\" fit-view-on-init>\n  <ax-node id=\"a\" data-x=\"0\" data-y=\"0\">\n    research\n    <ax-handle type=\"source\" handle-id=\"out\" position=\"right\"></ax-handle>\n  </ax-node>\n  <ax-node id=\"b\" data-x=\"280\" data-y=\"0\">\n    summarize\n    <ax-handle type=\"target\" handle-id=\"in\" position=\"left\"></ax-handle>\n  </ax-node>\n\n  <ax-edge from=\"a:out\" to=\"b:in\" label=\"findings\"></ax-edge>\n</ax-lattice>\n\n<script type=\"module\">\n  import '@axocoatl/lattice';\n  const lat = document.querySelector('ax-lattice');\n\n  // A user drag from a source handle to a target handle fires this.\n  // It's cancellable — preventDefault and create the edge yourself if you\n  // want to validate or de-dupe first.\n  lat.addEventListener('edge-connect', e => {\n    console.log('connect', e.detail.from, '→', e.detail.to);\n  });\n\n  lat.addEventListener('selection-change', e => console.log('nodes', e.detail.ids));\n  lat.addEventListener('node-moveend', e => console.log(e.target.id, e.detail));\n\n  // Programmatic\n  lat.addEdge({ from: 'a:out', to: 'b:in' });\n  lat.deleteSelectedEdges();\n</script>\n```\n\nDrag from a `source` handle to a `target` handle to draw an edge. Click an\nedge curve to select it; Delete removes it. Everything from Phase A/B (pan,\nzoom, node drag, multi/box-select, group-drag) still applies.\n\n## Phase D — Minimap, controls, undo/redo, copy/paste\n\n```html\n<div style=\"position:relative\">\n  <ax-lattice id=\"lat\" snap=\"20\" background=\"dots\" fit-view-on-init>\n    <!-- nodes & edges -->\n  </ax-lattice>\n  <ax-controls for=\"lat\" style=\"position:absolute;top:14px;left:14px\"></ax-controls>\n  <ax-minimap  for=\"lat\" style=\"position:absolute;bottom:14px;right:14px\"></ax-minimap>\n</div>\n```\n\n- **Undo / redo** — `Cmd/Ctrl+Z`, `Cmd/Ctrl+Shift+Z`. Or `lat.undo()` / `lat.redo()`.\n  Tracks moves, deletes, edge creation, and paste.\n- **Copy / paste** — `Cmd/Ctrl+C` / `Cmd/Ctrl+V`. Or `lat.copy()` / `lat.paste()`.\n  Copies the node selection plus enclosed edges; paste offsets and re-ids.\n- **`<ax-minimap>`** — scaled overview; click or drag it to navigate.\n- **`<ax-controls>`** — zoom / fit / undo / redo toolbar; undo/redo reflect state.\n\nBoth overlays link to a lattice by `for=\"latticeId\"` or by assigning `.target`.\n\n### Attributes\n| Name | Type | Default | Description |\n|---|---|---|---|\n| `zoom` | number | `1` | Current zoom level |\n| `min-zoom` | number | `0.2` | Minimum allowed zoom |\n| `max-zoom` | number | `3` | Maximum allowed zoom |\n| `pan-x` | number | `0` | Horizontal pan offset |\n| `pan-y` | number | `0` | Vertical pan offset |\n| `snap` | number | `0` | Grid snap size; `0` disables snapping |\n| `background` | `dots` \\| `grid` \\| `none` | `dots` | Background pattern |\n| `fit-view-on-init` | boolean | `false` | Auto fit-view after first render |\n\n### Methods\n| Method | Description |\n|---|---|\n| `setViewport({ x, y, k })` | Set pan + zoom imperatively |\n| `getViewport()` | Returns `{ x, y, k }` |\n| `fitView({ padding? })` | Frame all content |\n| `zoomIn()` / `zoomOut()` | Step zoom |\n| `screenToLattice({ x, y })` | Pointer → lattice coordinate |\n| `latticeToScreen({ x, y })` | Lattice → screen coordinate |\n| `snap(value)` | Snap a lattice coordinate (no-op when snap=0) |\n| `nodes` (getter) | Snapshot Set of registered `<ax-node>`s |\n| `selection` (getter) | Snapshot Set of currently selected nodes |\n| `selectedIds()` | Array of selected node ids in registry order |\n| `selectAll()` / `deselectAll()` | Selection ops |\n| `deleteSelected()` | Fires `nodes-delete-request` (cancellable); on accept, removes them from DOM |\n\n### Events\n| Name | `detail` | Fires when |\n|---|---|---|\n| `viewport-change` | `{ x, y, k }` | Pan or zoom changes (rAF-coalesced) |\n| `selection-change` | `{ ids: string[], count }` | Selection set changes |\n| `nodes-delete-request` | `{ ids: string[] }` | Before deletion — preventDefault to keep the nodes |\n| `nodes-deleted` | `{ ids: string[] }` | After deletion |\n| `node-select` | `{ additive: boolean }` (from a node, bubbles) | A node was clicked / shift-clicked |\n| `node-movestart`, `node-moving`, `node-moveend` | `{ x, y, dx?, dy? }` | Node drag lifecycle |\n\n### `<ax-node>` API\n| Method / property | Description |\n|---|---|\n| `x`, `y`, `position` | Lattice-space position (read & write) |\n| `selected` (attr & prop) | Current selection state |\n| `moveTo({ x, y, snap? })` | Programmatic move (no events) |\n| `getBox()` | `{ x, y, width, height }` in lattice space |\n\n### `<ax-node>` CSS Custom Properties\n| Var | Default | Effect |\n|---|---|---|\n| `--ax-node-bg` | `#181d27` | Background |\n| `--ax-node-fg` | `#e8ecf3` | Foreground |\n| `--ax-node-border` | `#2e3645` | Border |\n| `--ax-node-border-hover` | `#4a536a` | Border on hover |\n| `--ax-node-border-sel` | `var(--ax-accent)` | Border when selected |\n| `--ax-node-shadow` | small drop shadow | Box shadow |\n| `--ax-node-shadow-sel` | accent ring + shadow | Box shadow when selected |\n| `--ax-node-radius` | `9px` | Border radius |\n| `--ax-node-padding` | `11px 14px` | Inner padding |\n| `--ax-marquee-fill` (on lattice) | `rgba(124,92,255,.12)` | Box-select overlay fill |\n\n### CSS Custom Properties\n| Var | Default | Effect |\n|---|---|---|\n| `--ax-bg` | `#0a0c11` | Canvas background |\n| `--ax-fg` | `#e8ecf3` | Text / foreground |\n| `--ax-grid` | `#232a37` | Grid line/dot color |\n| `--ax-grid-size` | `20px` | Grid spacing |\n| `--ax-accent` | `#7c5cff` | Selection / highlight color |\n\n## Roadmap\n\n| Phase | Version | Status | Surface |\n|---|---|---|---|\n| **0** | — | ✓ shipped | Scaffold, demo, README |\n| **A** | 0.1 | ✓ shipped | `<ax-lattice>` pan/zoom/snap/background |\n| **B** | 0.2 | ✓ shipped | `<ax-node>` + click/shift/box select + drag + group drag + delete + keyboard model |\n| **C** | 0.3 | ✓ shipped | `<ax-handle>` + `<ax-edge>` + drag-to-connect + edge select/delete + bezier routing |\n| **D** | 0.4 | ✓ shipped | `<ax-minimap>`, `<ax-controls>`, undo/redo, copy/paste |\n| **E** | 1.0 | ✓ shipped | Virtualization, layered auto-layout |\n| **F** | 1.0 | ✓ shipped | API freeze, ARIA, `docs/API.md`, unit + integration test suites |\n\n**v1.1.0** — stable API + native execution state (`<ax-node status>`,\n`<ax-edge active>`). See [`docs/API.md`](docs/API.md) for the full reference.\n\n## License\n\n[Apache-2.0](LICENSE) — © Axocoatl Contributors.\n","readmeFilename":"README.md","_rev":"1-8406638fdb3a3c3247035772e69dd07a"}