# JavaScript quick start

Mount a sized, interactive diagram in plain JavaScript with either [`render`](https://bench-grafloria-6l.atloria.app/p/bench-grafloria-6l-dqcsEdUbfS/developer/grafloria-element-core#render) or the `<grafloria-flow>` custom element.

Grafloria has one headless model underneath its framework bindings; the element and `render()` give you two ways to mount that same diagram in a browser.

## Prerequisites

- A browser project that runs JavaScript modules and can resolve npm packages (the steps below use Vite).
- `@grafloria/element` 0.4.83, with peer dependencies `@grafloria/engine` `^0.3.16` and `@grafloria/renderer` `^0.4.15`.

## Install

```bash
npm install @grafloria/element @grafloria/engine @grafloria/renderer
npm install --save-dev vite
```

Add a `dev` script that runs Vite, or start the local server with `npx vite` from your project directory.

## 1. Mount with `render()`

Use `render()` when you want the live [`DiagramInstance`](https://bench-grafloria-6l.atloria.app/p/bench-grafloria-6l-dqcsEdUbfS/developer/grafloria-renderer-instance-diagraminstance#diagraminstance) returned to your JavaScript code. It takes the diagram data first and then a sized target element.

Create `index.html` with a real height for the canvas:

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Grafloria flow</title>
    <style>
      html, body { margin: 0; height: 100%; }
      #canvas { width: 100%; height: 80vh; }
    </style>
  </head>
  <body>
    <div id="canvas"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>
```

In `src/main.js`, pass a spec containing two nodes and an edge:

```js
import { render } from '@grafloria/element';

const canvas = document.getElementById('canvas');
if (!(canvas instanceof HTMLElement)) {
  throw new Error('Canvas element not found');
}
canvas.style.height = '80vh';
const diagram = render({
  nodes: [
    { id: 'ingest', position: { x: 60, y: 80 }, size: { width: 180, height: 80 }, data: { label: 'Ingest' } },
    { id: 'publish', position: { x: 380, y: 80 }, size: { width: 180, height: 80 }, data: { label: 'Publish' } },
  ],
  edges: [{ id: 'ingest-to-publish', source: 'ingest', target: 'publish' }],
}, canvas);
```

![Look at the canvas immediately after `render()` mounts the diagram.](https://atloriaassets.blob.core.windows.net/assets/a438221c-c1af-407c-b9e6-a56c986db846/7f794eb07613b0168e61389e4b23a2f0.png)

The canvas shows **Ingest** connected to **Publish**. You can drag nodes, connect them, pan, and zoom; `diagram` is the returned instance for further operations. The spec is diagram data, not Mermaid text.

## 2. Or mount the custom element

Choose `<grafloria-flow>` when HTML attributes are the natural place to provide the diagram. Import the package from your JavaScript module to register the element, then put JSON arrays in its `nodes` and `edges` attributes.

Use this `index.html` instead of the `render()` version above. The element fills its own box, so give the element a resolved height:

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Grafloria flow</title>
    <style>
      html, body { margin: 0; height: 100%; }
      grafloria-flow { display: block; width: 100%; height: 80vh; }
    </style>
  </head>
  <body>
    <grafloria-flow
      nodes='[{"id":"extract","position":{"x":60,"y":80},"label":"Extract"},{"id":"load","position":{"x":300,"y":80},"label":"Load"}]'
      edges='[{"id":"extract-to-load","source":"extract","target":"load"}]'>
    </grafloria-flow>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>
```

Use the exported [`GrafloriaFlowElement`](https://bench-grafloria-6l.atloria.app/p/bench-grafloria-6l-dqcsEdUbfS/developer/grafloria-element-core#grafloriaflowelement) class to narrow the queried element to the custom-element API. Importing the package registers the default tag.

```js
import { GrafloriaFlowElement } from '@grafloria/element';

const element = document.querySelector('grafloria-flow');
const flow = element instanceof GrafloriaFlowElement
  ? element
  : new GrafloriaFlowElement();
if (!(element instanceof GrafloriaFlowElement)) {
  flow.style.width = '100%';
  flow.style.height = '80vh';
  flow.nodes = [
    { id: 'extract', position: { x: 60, y: 80 }, label: 'Extract' },
    { id: 'load', position: { x: 300, y: 80 }, label: 'Load' },
  ];
  flow.edges = [{ id: 'extract-to-load', source: 'extract', target: 'load' }];
  document.body.append(flow);
}
flow.fitView();
```

![Look at the element's canvas immediately after it mounts the diagram.](https://atloriaassets.blob.core.windows.net/assets/a438221c-c1af-407c-b9e6-a56c986db846/42b3472cdef8fbf1c92b4def8af7528a.png)

The element shows **Extract** connected to **Load**, and `flow.fitView()` frames the diagram in the element. Its `nodes` and `edges` values are JSON strings in HTML; for rich JavaScript objects, set the element's `nodes` and `edges` properties instead. The element exposes its instance through `diagram` when you need the instance API.

## What you have

Both entry points mount an interactive diagram with a visible edge in a container with a real height. `render()` returns the instance directly; the custom element gives you HTML attributes and DOM events, and disposes its diagram when disconnected.

## Where next

- The [`<grafloria-flow>` reference](https://bench-grafloria-6l.atloria.app/p/bench-grafloria-6l-dqcsEdUbfS/developer/grafloria-element-core#grafloriaflowelement) documents the element class and its API.
- [How Grafloria works](https://bench-grafloria-6l.atloria.app/p/bench-grafloria-6l-dqcsEdUbfS/developer/how-grafloria-works) for the model, document, and command concepts behind the bindings.
- [Open the JavaScript starter in StackBlitz](https://stackblitz.com/github/grafloria/grafloria/tree/main/starters/javascript?file=src/main.js) to run the `render()` sample, or browse the [live demo gallery](https://grafloria.com/demos/).
