Skip to content

Latest commit

 

History

History

README.md

@d3-polytree/element

The <d3-polytree-editor> custom element — a framework-free, shadow-DOM wrapper around the @d3-polytree/editor. It hosts the editor with no engine fork, reflects the serialized .pfdn document as a value property / attribute, participates in <form>s via ElementInternals (feature-gated), and emits a change CustomEvent on every committed edit. All styling is inlined into the shadow root, so it renders identically wherever you drop it.

▶ Live demo in Storybook.

Install

pnpm add @d3-polytree/element d3-selection d3-zoom d3-transition d3-scale d3-axis d3-drag

Ships ESM + CJS + .d.ts and a self-contained UMD bundle (dist/element.umd.js). Importing the package registers the tag as a side effect, and all styling is inlined into the shadow root (no CSS import). The six D3 v7 slices are peer dependencies (inherited from the wrapped @d3-polytree/editor → core) for the ESM/CJS build; the UMD bundle inlines them, so a plain <script> drop-in needs nothing extra.

Usage

As a plain HTML element

<script type="module">
  import '@d3-polytree/element'; // registers <d3-polytree-editor>
</script>

<d3-polytree-editor style="display:block; width:100%; height:600px;"></d3-polytree-editor>

Seed it with a document via the value attribute, and read edits back off the change event:

<d3-polytree-editor id="ed" value="<pfdn:diagram …>…</pfdn:diagram>"></d3-polytree-editor>
<script type="module">
  import '@d3-polytree/element';
  const el = document.getElementById('ed');
  el.addEventListener('change', (e) => console.log('new .pfdn:', e.detail));
</script>

Inside a <form>

The element is form-associated (static formAssociated = true) via ElementInternals, so its current .pfdn document is submitted with the form under the element's name — no hidden input, no glue code:

<form>
  <d3-polytree-editor name="diagram"></d3-polytree-editor>
  <button type="submit">Save</button>
</form>

Where ElementInternals is unavailable (older engines, jsdom), form association degrades gracefully and the rest of the element keeps working.

Explicit registration

Auto-registration happens on import. To register under your own control (e.g. after feature-checks), call the named export:

import { defineD3PolytreeEditor } from '@d3-polytree/element';
defineD3PolytreeEditor(); // idempotent — guards HMR / repeated evaluation

API

Member Type Description
value property / attribute The current diagram as a .pfdn XML string; setting it reloads the editor (echo-guarded so the element never reloads on its own emitted change).
exportSVG() method The current SVG with the shadow-scoped CSS inlined, pinned to the light theme so exports stay theme-invariant.
change CustomEvent<string> Fired on every committed edit; detail is the new .pfdn. Bubbles and crosses the shadow boundary (composed).
D3PolytreeEditorElement class The element class, if you need to subclass or reference it.
defineD3PolytreeEditor() function Idempotent tag registration.

The element gives itself tabindex="0" (so keyboard undo/redo reaches the editor) and delegates focus into the shadow root. The editor subscription survives importDiagram reboots, so external value changes never drop the change wiring.

When to use it

Reach for this adapter when you want the editor in any framework (or none) through a standard DOM element and form semantics. For an idiomatic React binding with imperative ref handles, use @d3-polytree/react instead.

Links

License

MIT © David Castillo