@danielres/svelte-dageditor
v0.0.5
Published
An advanced editable DAG (directed acyclic graph) component for Svelte[Kit].
Downloads
8
Readme
@danielres/svelte-dageditor
An advanced editable DAG (directed acyclic graph) component for Svelte[Kit].
This is basically a treeview of interconnected nodes, with the ability to add, remove, rename, delete, and move nodes around. The major difference with a traditional tree structure, is that nodes can have multiple parents.
This allows to create flexible multi-dimensional datastructures/taxonomies/classification systems beyond the limitations of the more common flat or tree-like structures.
- No extra dependencies
- Written in TypeScript
- Supports Svelte 3 and SvelteKit
- Provides undo/redo
- Uses (svelte native) drag and drop
- Comes with default styles (copy them to your project and customize them as you wish)
- 9Kb (unpacked, all included)
Disclaimer
This is an early alpha version, seems to work well. But it is not yet ready for production use. Major breaking changes are expected.
Installation
npm install @danielres/svelte-dageditor
or
pnpm install @danielres/svelte-dageditor
or
yarn add @danielres/svelte-dageditor
Example usage
<script>
// import editable DAG tree logic (stores, commands, etc.):
import { makeDagStore } from '@danielres/svelte-dageditor'
// import the Tree component:
import { Tree } from '@danielres/svelte-dageditor'
// import default styles:
import '@danielres/svelte-dageditor/dist/styles.css'
import { onMount } from 'svelte'
// Provide nodes and relations (could be fetched from a server / db):
const data = {
nodes: [
{ name: '<root>', id: '<root>' },
{ name: 'tag1', id: 'tag1' },
{ name: 'tag2', id: 'tag2' },
],
relations: [
{ id: 'aaa', parentId: '<root>', childId: 'tag1' },
{ id: 'aaa', parentId: '<root>', childId: 'tag2' },
],
}
// Generate the editable tree stores
// The first argument ("<root>" in this example) should be the
// id of the node that we wish to use as the root:
const dag = makeDagStore('<root>', data.nodes, data.relations)
const { commands } = dag
// Optional: use undo/redo features
// Optional: get the undos/redos counts
// Optional: get the history store containing executed commands
const { undo, redo, undos, redos, history } = commands
onMount(() => {
// All actions that can be done through the UI are also available programmatically.
// Example: execute some commands:
commands.rename({ id: 'tag1', to: 'tag1-renamed' })
commands.rename({ id: 'tag2', to: 'tag2-renamed' })
commands.move({ id: 'tag2', from: '<root>', to: 'tag1' })
})
</script>
<div class="flex justify-between items-center">
<div class="flex items-center gap-2">
<button on:click={undo} disabled={!$undos}>Undo ({$undos})</button>
<button on:click={redo} disabled={!$redos}>Redo ({$redos})</button>
</div>
</div>
<div class="grid grid-cols-2">
<main class="py-4 px-8 grid gap-8 h-fit">
<!-- The DAG rendered as an editable tree -->
<!-- root={true} allows to render the root node differently -->
<Tree {dag} root={true} />
</main>
</div>
<!-- Optional: inspect the internals (commands, history) -->
<div>
<h2>Commands:</h2>
<pre>{JSON.stringify($commands, null, 2)}</pre>
<h2>History:</h2>
<pre>{JSON.stringify($history, null, 2)}</pre>
</div>
<style lang="postcss">
button {
@apply text-sm text-gray-600 bg-gray-200 rounded opacity-75;
@apply px-2 py-1;
@apply transition-opacity;
}
button:disabled {
@apply opacity-25;
}
button:not(:disabled) {
@apply cursor-pointer;
}
button:not(:disabled):hover {
@apply opacity-100;
}
</style>