Svelte example app with TypeScript

JointJS+ is a standard JavaScript library that you can use in any JavaScript framework. In this tutorial, we will show how you can use JointJS+ in your Svelte apps. The tutorial will go over the typical process of creating a Svelte app, setting up the build process, and integrating JointJS+ components into your Svelte app. The resulting very simple demo app will display the JointJS+ PaperScroller component, and render a rectangle element to that paper area. Similarly, you can add any other JointJS+ UI components, and build up a fully-featured diagramming application. Let's go!

The source code for the following tutorial can be found here. Looking for a different version of your favourite framework? Be sure to checkout the different branches of the repository to see if you find what you need.

Prerequisites

Create a Svelte project using Vite

In order to setup our Svelte project, we will follow the recommended setup using Vite as suggested in the Getting Started section of the Svelte documentation.

npm init vite

After running npm init vite, you will receive several prompts:

Now that the setup is complete, you can run the following:

cd joint-plus-tutorial-svelte
npm install
npm run dev

The app should now be running at http://localhost:5173/.

Add JointJS+ to the Svelte project

Firstly, we need to add JointJS+ to our dependencies. For this tutorial, we will place our installable joint-plus.tgz package in the root directory of our Svelte app. After that is completed, we can now update our existing dependencies in our package.json file with the following:

"dependencies": {
    ...
    "@joint/plus": "file:joint-plus.tgz", // path to file
    ...
},

Then, run npm install.

Next, open the tsconfig.json file in the root project directory, and set "skipLibCheck" to true in the "compilerOptions" as there is no need for the TS compiler to check the JointJS+ library:

"compilerOptions": {
    ...
    "skipLibCheck": true,
    ...
},

Build your app

Before we start, let's clean up our project a little bit.

App.svelte and main.ts should now look like the following:

<script lang="ts">
    import '../node_modules/@joint/plus/joint-plus.css';
</script>

<main class="app">
</main>

<style>
</style>
import './app.css';
import App from './App.svelte';

const app = new App({
    target: document.body
});

export default app;

Lastly, we will add some new global styles to our app. In src/app.css, you can place the following CSS rules:

body {
    margin: 0;
    padding: 0;
    height: 100vh;
    width: 100vw;
}

.app {
    width: 100%;
    height: 100%;
}

.joint-paper {
    border: 1px solid #A0A0A0;
}

That's the basic setup completed, and we are now ready to start creating our Svelte JointJS+ application. We will create our logic inside our App.svelte component, in order to do so, we need to create a reference to a rendered element. In our app, our reference will be the main element. Svelte components support bind:this, allowing you to interact with components programmatically.

Note, the value of main will be undefined until our App.svelte component has mounted, so it is necessary to place our logic inside the Svelte onMount lifecycle function, so we can import that too.

We will also import the JointJS+ namespaces required in order to create our simple application.

Our App.svelte file, should now look like the following:

<script lang="ts">
    import { onMount } from 'svelte';
    import { dia, ui, shapes } from '@joint/plus/joint-plus.js';
    import '../node_modules/@joint/plus/joint-plus.css';

    let ref;

    onMount(() => {});
</script>

<main bind:this={ref} class="app"></main>

<style>
</style>

Now, it's time to create our JointJS+ components. Inside the onMount lifecycle function, you can add the Graph, Paper, and PaperScroller.

const graph = new dia.Graph({}, { cellNamespace: shapes });

const paper = new dia.Paper({
    model: graph,
    background: {
        color: '#F8F9FA',
    },
    frozen: true,
    async: true,
    sorting: dia.Paper.sorting.APPROX,
    cellViewNamespace: shapes
});

const scroller = new ui.PaperScroller({
    paper,
    autoResizePaper: true,
    cursor: 'grab'
});

Resources:

Next, let's render our PaperScroller component. We need to append the PaperScroller HTML element to our ref which we created earlier. Then, inside onMount, add the following:

ref.appendChild(scroller.el);
scroller.render().center();

On the last line, we are calling the "render" method on our PaperScroller. Additionally, we also call the "center" method to position the Paper inside the PaperScroller.

The last steps are to create a simple rectangle shape, add it to our graph, and unfreeze the Paper. Add this block of code to the onMount lifecycle function:

const rect = new shapes.standard.Rectangle({
    position: { x: 100, y: 100 },
    size: { width: 100, height: 50 },
    attrs: {
        label: {
            text: 'Hello World'
        }
    }
});

graph.addCell(rect);

paper.unfreeze();

And that's all it takes to create this simple JointJS+ Svelte application. The final code in App.svelte should look like the following:

<script lang="ts">
    import { onMount } from 'svelte';
    import { dia, ui, shapes } from '@joint/plus';
    import '../node_modules/@joint/plus/joint-plus.css';

    let ref;

    onMount(() => {
        const graph = new dia.Graph({}, { cellNamespace: shapes });

        const paper = new dia.Paper({
            model: graph,
            background: {
                color: '#F8F9FA',
            },
            frozen: true,
            async: true,
            sorting: dia.Paper.sorting.APPROX,
            cellViewNamespace: shapes,
        });

        const scroller = new ui.PaperScroller({
            paper,
            autoResizePaper: true,
            cursor: 'grab',
        });

        ref.appendChild(scroller.el);
        scroller.render().center();

        const rect = new shapes.standard.Rectangle({
            position: { x: 100, y: 100 },
            size: { width: 100, height: 50 },
            attrs: {
                label: {
                    text: 'Hello World',
                },
            },
        });

        graph.addCell(rect);

        paper.unfreeze();
    });
</script>

<main bind:this={ref} class="app"></main>

<style>
</style>

To serve your JointJS+ Svelte application, use npm run dev. The demo application should look like the picture below.

exampleApp