### Install and Start Demo
Source: https://github.com/clientio/joint/blob/master/packages/joint-core/demo/custom-shapes/README.md
Navigate to the demo directory and run these commands to install its dependencies and start the demo server.
```bash
yarn install
yarn start
```
--------------------------------
### Install and Run Project
Source: https://github.com/clientio/joint/blob/master/examples/genogram-ts/README.md
Install project dependencies and start the development server. Open the provided URL in your browser to view the application.
```bash
yarn install
yarn dev
```
--------------------------------
### Install Dependencies and Start Server
Source: https://github.com/clientio/joint/blob/master/examples/angular-element-view-ts/README.md
Install project dependencies using yarn and start the development server. Navigate to http://localhost:4200/ to view the application.
```bash
# Install dependencies
yarn install
# Start development server
yarn start
```
--------------------------------
### Navigate to Examples Directory
Source: https://github.com/clientio/joint/blob/master/packages/joint-core/README.md
Change directory to the 'examples' folder to explore example applications.
```bash
cd examples
```
--------------------------------
### Run JointJS Development Server
Source: https://github.com/clientio/joint/blob/master/examples/absolute-port-layout-dynamic-port-sizes-js/README.md
Start the development server for the JointJS example. Access the application via the printed URL, typically http://localhost:5173.
```bash
yarn dev
```
--------------------------------
### Start the JointJS List Demo
Source: https://github.com/clientio/joint/blob/master/examples/bezier-js/README.md
Navigate to the demo directory and run this command to start the application.
```bash
yarn start
```
--------------------------------
### List Available Examples
Source: https://github.com/clientio/joint/blob/master/packages/joint-cli/README.md
Use the `joint list` command to see all available example projects from the joint-demos GitHub repository.
```bash
npx @joint/cli list
```
```bash
joint list
```
--------------------------------
### Download JointJS Examples
Source: https://github.com/clientio/joint/blob/master/packages/joint-cli/README.md
Download a specific example project, such as 'kitchen-sink/js', into your current directory or a specified destination. Use `--force` to overwrite existing files.
```bash
npx @joint/cli download kitchen-sink/js
```
```bash
joint download kitchen-sink/js
```
```bash
joint download kitchen-sink/js my-app
```
```bash
joint download kitchen-sink/js .
```
```bash
joint download kitchen-sink/js --force
```
```bash
joint download kitchen-sink/js . --force
```
--------------------------------
### Install Dependencies
Source: https://github.com/clientio/joint/blob/master/examples/joint-react/README.md
Install project dependencies using Yarn or npm.
```bash
yarn install
# or if you're using npm
npm install
```
--------------------------------
### Install and Build JointJS
Source: https://github.com/clientio/joint/blob/master/examples/tree-shake/README.md
Install dependencies and build the JointJS library. This is a prerequisite for running the demo.
```bash
yarn install
yarn run dist
```
--------------------------------
### Quick Start: Create a Simple Diagram with Two Connected Nodes
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/README.md
A complete example demonstrating how to set up a basic diagram with two connected nodes using @joint/react. It includes defining elements, links, and a custom element renderer.
```tsx
import React, { useCallback } from 'react';
import { GraphProvider, Paper, createElements, createLinks } from '@joint/react';
// Define your diagram elements (nodes)
const initialElements = createElements([
{
id: '1',
label: 'Start',
x: 100, // Position from left
y: 50, // Position from top
width: 120,
height: 60
},
{
id: '2',
label: 'End',
x: 100,
y: 200,
width: 120,
height: 60
},
]);
// Define connections between elements
const initialLinks = createLinks([
{
id: 'link1',
source: '1', // ID of source element
target: '2' // ID of target element
}
]);
// Main component that renders the diagram
function DiagramExample() {
// Define how each element should look
const renderElement = useCallback((element) => (
{element.label}
), []);
return (
);
}
// Wrap your app with GraphProvider
export default function App() {
return (
);
}
```
--------------------------------
### Clone Repository
Source: https://github.com/clientio/joint/blob/master/examples/joint-react/README.md
Clone the joint-react repository to get started. Navigate into the cloned directory.
```bash
git clone
cd joint-react
```
--------------------------------
### Download Examples from a Fork
Source: https://github.com/clientio/joint/blob/master/packages/joint-cli/README.md
Specify a custom GitHub owner and branch using `--owner` and `--branch` options to download examples from a forked repository.
```bash
joint list --owner myGitHubUser
```
```bash
joint download kitchen-sink/js --owner myGitHubUser --branch dev
```
--------------------------------
### Install and Build JointJS
Source: https://github.com/clientio/joint/blob/master/examples/bezier-js/README.md
Run these commands in the root folder to install dependencies and build JointJS.
```bash
yarn install
yarn run build
```
--------------------------------
### Install @joint/react with npm, yarn, or bun
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/README.md
Install the library using your preferred package manager. Ensure you have Node.js 14+ and React 16.8+.
```sh
# Using npm
npm install @joint/react
# Using yarn
yarn add @joint/react
# Using bun
bun add @joint/react
```
--------------------------------
### Install JointJS MSAGL Layout
Source: https://github.com/clientio/joint/blob/master/packages/joint-layout-msagl/README.md
Install the JointJS MSAGL layout module using npm.
```bash
npm install @joint/layout-msagl
```
--------------------------------
### Run Linting Checks
Source: https://github.com/clientio/joint/blob/master/packages/joint-core/README.md
Execute linting checks on the src and types directories to identify code style errors. No setup is required beyond having the project dependencies installed.
```bash
yarn run lint
```
--------------------------------
### Clone and Install JointJS
Source: https://github.com/clientio/joint/blob/master/CONTRIBUTING.md
Clone the JointJS repository and install dependencies using Yarn.
```bash
git clone https://github.com/clientIO/joint.git
cd joint
yarn install
```
--------------------------------
### Run Development Server
Source: https://github.com/clientio/joint/blob/master/examples/joint-react/README.md
Start the Vite development server to run the project locally. The app will be available at http://localhost:3000.
```bash
yarn dev
# or if you're using npm
npm run dev
```
--------------------------------
### Install Dependencies with Yarn
Source: https://github.com/clientio/joint/blob/master/CLAUDE.md
Use this command to install all project dependencies within the Yarn workspace monorepo.
```bash
yarn install
```
--------------------------------
### Run the JointJS Libavoid Web Worker Demo
Source: https://github.com/clientio/joint/blob/master/examples/libavoid/README.md
Use this command to start the standalone routing demo with web workers enabled.
```bash
yarn run start-web-worker
```
--------------------------------
### Install @joint/cli Globally
Source: https://github.com/clientio/joint/blob/master/packages/joint-cli/README.md
Install the @joint/cli package globally using npm to make the `joint` command available in your terminal.
```bash
npm install -g @joint/cli
```
--------------------------------
### Automatic Layout Example
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/examples/with-auto-layout/docs.mdx
Demonstrates how to use automatic layout. The layout is applied once all React elements are rendered and their sizes are calculated. Requires the 'Code' component.
```tsx
import { FC } from 'react';
import { Joint } from '@clientio/joint';
import { Box, Button, Text } from '@chakra-ui/react';
interface Props {
children?: React.ReactNode;
}
export const Default: FC = ({ children }) => {
return (
Hello World
{children}
);
};
```
--------------------------------
### HTML Overlay Example Code
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/tutorials/step-by-step/docs.mdx
This code snippet illustrates using the `useHTMLOverlay` prop for rendering HTML content in nodes with @joint/react.
```tsx
import { GraphProvider, Paper, createElements, createLinks, InferElement } from '@joint/react';
const elements = createElements([
{ id: 'node1', label: 'Node 1', x: 100, y: 50, width: 100, height: 40 },
{ id: 'node2', label: 'Node 2', x: 300, y: 50, width: 100, height: 40 },
]);
type ElementType = InferElement;
const links = createLinks([
{ id: 'link1', source: 'node1', target: 'node2' },
]);
function RenderHTMLNode({ label, width, height }) {
return (
{label}
);
}
function App() {
return (
);
}
export default App;
```
--------------------------------
### Display Resizable Node Code
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/examples/with-resizable-node/docs.mdx
Renders the source code for the resizable node example using a Markdown block.
```tsx
{`\
\
${Code}
\
`}
```
--------------------------------
### HTML Node Example Code
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/tutorials/step-by-step/docs.mdx
This code snippet demonstrates rendering HTML content within nodes using @joint/react.
```tsx
import { GraphProvider, Paper, createElements, createLinks, InferElement, MeasuredNode } from '@joint/react';
const elements = createElements([
{ id: 'node1', label: 'Node 1', x: 100, y: 50, width: 100, height: 40 },
{ id: 'node2', label: 'Node 2', x: 300, y: 50, width: 100, height: 40 },
]);
type ElementType = InferElement;
const links = createLinks([
{ id: 'link1', source: 'node1', target: 'node2' },
]);
function RenderHTMLNode({ label, width, height }) {
return (
{label}
);
}
function App() {
return (
);
}
export default App;
```
--------------------------------
### Built-in Shapes Example
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/examples/with-auto-layout/docs.mdx
Demonstrates using built-in shapes within the Joint component. Requires the 'CodeWithBuildInShapes' component.
```tsx
import { FC } from 'react';
import { Joint } from '@clientio/joint';
import { Box, Button, Text } from '@chakra-ui/react';
interface Props {
children?: React.ReactNode;
}
export const WithBuildInShapes: FC = ({ children }) => {
return (
Hello World
{children}
);
};
```
--------------------------------
### Clone JointJS Repository
Source: https://github.com/clientio/joint/blob/master/packages/joint-core/README.md
Clone the JointJS Git repository to set up the project locally. Ensure you have Git installed.
```bash
git clone https://github.com/clientIO/joint.git
```
--------------------------------
### Proximity Link Example Code
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/examples/with-proximity-link/docs.mdx
This code implements proximity-based linking for nodes. It dynamically adds or removes links based on the distance between nodes. Ensure necessary imports are present.
```tsx
import { FC, useState, useEffect, useRef } from 'react';
import { useNode, useEditor, useSelection, useZoom } from '@craftjs/core';
import styled from 'styled-components';
const Link = styled.line<{ color: string }>`
stroke: ${(props) => props.color};
stroke-width: 2;
`;
interface Node {
id: string;
x: number;
y: number;
}
interface ProximityLinkExampleProps {
nodes: Node[];
maxDistance?: number;
linkcolor?: string;
}
export const ProximityLinkExample: FC = ({
nodes,
maxDistance = 100,
linkcolor = '#007bff',
}) => {
const { enabled } = useEditor();
const { zoom } = useZoom();
const [links, setLinks] = useState<{ id: string; x1: number; y1: number; x2: number; y2: number }[]>([]);
useEffect(() => {
const newLinks: { id: string; x1: number; y1: number; x2: number; y2: number }[] = [];
for (let i = 0; i < nodes.length; i++) {
for (let j = i + 1; j < nodes.length; j++) {
const node1 = nodes[i];
const node2 = nodes[j];
const distance = Math.sqrt(Math.pow(node1.x - node2.x, 2) + Math.pow(node1.y - node2.y, 2));
if (distance <= maxDistance) {
newLinks.push({
id: `${node1.id}-${node2.id}`,
x1: node1.x,
y1: node1.y,
x2: node2.x,
y2: node2.y,
});
}
}
}
setLinks(newLinks);
}, [nodes, maxDistance]);
return (
);
};
```
--------------------------------
### Link Tools Implementation in TSX
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/examples/with-link-tools/docs.mdx
This code snippet demonstrates the setup and usage of link tools in a JointJS diagram. It includes necessary imports from '@storybook/blocks' and local story files. Ensure all required modules are correctly imported.
```tsx
import { Meta, Story, Canvas, Controls, Markdown } from '@storybook/blocks';
import * as Stories from './story';
import Code from './code?raw';
# Link Tools Example
This example shows how to use link tools in your project. Link tools are interactive features that let you edit and manipulate links in a diagram. They make it easy to customize and work with links visually. For more information, check out the [Link Tools documentation](https://resources.jointjs.com/tutorial/link-tools).
You can also use the `jsx` utility provided by JointJS to convert JSX into JointJS markup. This makes it simpler to define custom elements and tools.
### Demo
Here is a live demo of the link tools in action:
### Code
Below is the code used in this example. You can copy and modify it to fit your needs:
{`\
\
\
${Code}
\
\
\
`}
```
--------------------------------
### Main Angular Component Setup
Source: https://github.com/clientio/joint/blob/master/examples/angular-element-view-ts/README.md
The main Angular component sets up the JointJS graph, paper, and adds the custom AngularElement. It passes necessary Angular services like ComponentFactoryResolver, ApplicationRef, and Injector to the custom view.
```typescript
import { Component, AfterViewInit, ViewChild, ElementRef, ChangeDetectorRef } from '@angular/core';
import { dia, ui, shapes } from '@jointjs/core';
import { AngularElement } from './models/angular-element';
import { AngularElementView } from './views/angular-element-view';
import { ComponentFactoryResolver, ApplicationRef, Injector } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
private graph: dia.Graph;
private paper: dia.Paper;
@ViewChild('paperContainer', { static: true })
private paperContainer!: ElementRef;
constructor(
private componentFactoryResolver: ComponentFactoryResolver,
private applicationRef: ApplicationRef,
private injector: Injector,
private changeDetectorRef: ChangeDetectorRef
) {
this.graph = new dia.Graph();
}
ngAfterViewInit(): void {
this.paper = new dia.Paper({
el: this.paperContainer.nativeElement,
model: this.graph,
width: 800,
height: 600,
gridSize: 10,
defaultConnector: { // Default connector
router: { name: 'normal' },
connector: { name: 'rounded' }
},
defaultLink: {
toolMarkup: '',
vertexMarkup: ''
},
// Custom view for AngularElement
view: 'AngularElementView'
});
// Pass Angular services to the custom view
(this.paper as any).options.componentFactoryResolver = this.componentFactoryResolver;
(this.paper as any).options.applicationRef = this.applicationRef;
(this.paper as any).options.injector = this.injector;
// Register the custom view
dia.elementViewRegistry.register('AngularElementView', AngularElementView);
this.addAngularElement();
}
addAngularElement(): void {
const angularElement = new AngularElement({
position: { x: 100, y: 100 },
size: { width: 100, height: 50 },
attrs: {
component: {
name: 'Initial Name'
}
}
});
this.graph.addCell(angularElement);
}
}
```
--------------------------------
### Open Demo in Browser
Source: https://github.com/clientio/joint/blob/master/examples/tree-shake/README.md
Open the index.html file in your browser to view the demo. Ensure the build process is complete.
```bash
open index.html
```
--------------------------------
### Build Project for Production
Source: https://github.com/clientio/joint/blob/master/examples/joint-react/README.md
Build the project for production deployment.
```bash
yarn build
# or if you're using npm
npm run build
```
--------------------------------
### Build and Analyze Demo Dependencies
Source: https://github.com/clientio/joint/blob/master/examples/tree-shake/README.md
Build the demo and analyze its dependencies using vite-bundle-analyzer. Navigate to the demo directory before running.
```bash
yarn run build
```
--------------------------------
### Preview Production Build
Source: https://github.com/clientio/joint/blob/master/examples/joint-react/README.md
Preview the production build locally to test the deployed version.
```bash
yarn preview
# or if you're using npm
npm run preview
```
--------------------------------
### SVG Node Example Code
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/tutorials/step-by-step/docs.mdx
This code snippet is an example of an SVG node used within the @joint/react library.
```tsx
import { GraphProvider, Paper, createElements, createLinks, InferElement } from '@joint/react';
const elements = createElements([
{ id: 'node1', label: 'Node 1', x: 100, y: 50, width: 100, height: 40, attrs: { body: { fill: '#915436' } } },
{ id: 'node2', label: 'Node 2', x: 300, y: 50, width: 100, height: 40, attrs: { body: { fill: '#43754A' } } },
]);
type ElementType = InferElement;
const links = createLinks([
{ id: 'link1', source: { id: 'node1', port: 'right' }, target: { id: 'node2', port: 'left' } },
]);
function App() {
return (
);
}
export default App;
```
--------------------------------
### Set Up Graph Context with GraphProvider
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/tutorials/step-by-step/docs.mdx
Wrap your diagram components with `GraphProvider` to provide the graph context. It accepts initial elements and links.
```tsx
import { GraphProvider } from '@joint/react';
import { elements, links } from './data'; // Assuming elements and links are defined elsewhere
{/* Your diagram components */}
```
--------------------------------
### Build Bundles
Source: https://github.com/clientio/joint/blob/master/CLAUDE.md
Commands to build project bundles.
```bash
yarn build
```
```bash
yarn build-bundles
```
--------------------------------
### Project Structure Overview
Source: https://github.com/clientio/joint/blob/master/examples/genogram-ts/README.md
Overview of the project's directory structure, highlighting key files for entry point, shapes, layout algorithms, utilities, data handling, theming, and datasets.
```tree
src/
main.ts Entry point — paper setup, dataset loading, rendering
shapes.ts Element and link shape definitions (MalePerson, FemalePerson, etc.)
highlighters.ts Custom dia.HighlighterView classes (deceased cross, adopted brackets)
layout/
index.ts Genogram layout algorithm (dagre + couple containers)
minimize-crossings.ts 5-phase crossing minimization for dagre's customOrder
utils.ts Element creation, lineage highlighting, family tree graph
data.ts Data types and parsing (PersonNode, parent-child/mate links)
theme.ts Centralized sizes, colors, z-index defaults, link style overrides
styles.css Paper and hover styling
families/ Dataset JSON files
thompson.json Thompson family (fictional, multi-generational)
british-royals.json British Royal Family (George V to present)
relationship-chart.json Labeled relationship roles (Father, Cousin, etc.)
benchmark.json Large dataset (~1000 persons, 7 generations)
scripts/
test-layout.cts Node.js layout test (no browser needed)
```
--------------------------------
### Run All Tests
Source: https://github.com/clientio/joint/blob/master/packages/joint-layout-directed-graph/README.md
Execute all tests for the project using this command.
```bash
yarn run test
```
--------------------------------
### Run Single QUnit Test File
Source: https://github.com/clientio/joint/blob/master/CLAUDE.md
Navigate to the joint-core package and run a specific QUnit test file using Grunt.
```bash
cd packages/joint-core
grunttest:server --file=test/jointjs/paper.js # Single test file
```
--------------------------------
### Create Initial Links
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/introduction.mdx
Use the createLinks utility to generate an array of initial link data for connecting nodes in your diagram. This is useful for setting up the graph's initial state.
```ts
import { createLinks } from '@joint/react';
const initialLinks = createLinks([
{ source: '1', target: '2', id: '1-2' },
]);
```
--------------------------------
### Navigate to JointJS Core Demo
Source: https://github.com/clientio/joint/blob/master/packages/joint-core/README.md
Navigate to the demo directory for the JointJS Core package to run demo applications.
```bash
cd packages/joint-core/demo
```
--------------------------------
### Build JointJS for Production
Source: https://github.com/clientio/joint/blob/master/examples/absolute-port-layout-dynamic-port-sizes-js/README.md
Create a production-ready build of the JointJS application. The output will be placed in the dist/ directory.
```bash
yarn build
```
--------------------------------
### Genogram Data Format Example
Source: https://github.com/clientio/joint/blob/master/examples/genogram-ts/README.md
JSON structure for representing a person in the genogram dataset. Includes fields for ID, name, sex, parentage, dates, and adoption status.
```json
{
"id": 1,
"name": "Jane Doe",
"sex": "F",
"mother": 2,
"father": 3,
"dob": "1990-01-15",
"dod": "2020-06-01",
"adopted": true,
"multiple": 1,
"identical": 4
}
```
--------------------------------
### Render HTML Content in Nodes using foreignObject
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/tutorials/step-by-step/docs.mdx
Example of rendering HTML content within SVG nodes by wrapping the HTML content in a `foreignObject` and using `MeasuredNode` for auto-sizing.
```tsx
import { MeasuredNode } from '@joint/react';
function RenderHTMLNode({ label, width, height }) {
return (
{label}
);
}
```
--------------------------------
### Handle Element Click Events in @joint/react
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/README.md
Example of how to attach an event handler to elements in the diagram. The `onElementPointerClick` prop allows you to define a callback function that executes when an element is clicked.
```tsx
function DiagramExample() {
const handleElementClick = useCallback((element) => {
console.log('Element clicked:', element);
}, []);
return (
);
}
```
--------------------------------
### Generate Distribution Files
Source: https://github.com/clientio/joint/blob/master/packages/joint-layout-directed-graph/README.md
Use this command to generate distribution files from the source code.
```bash
yarn run dist
```
--------------------------------
### Node Update with Color Picker using useUpdateElement
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/examples/with-node-update/docs.mdx
Integrate the useUpdateElement hook with a color picker component to dynamically update node colors. This example requires a color picker implementation.
```tsx
import React, { useState } from 'react';
import { useUpdateElement } from '@clientio/react';
import ColorPicker from './ColorPicker'; // Assuming ColorPicker component exists
interface MyComponentProps {
id: string;
initialData: Record;
}
const MyComponent: React.FC = ({ id, initialData }) => {
const updateElement = useUpdateElement();
const [color, setColor] = useState(initialData.color || '#000000');
const handleColorChange = (newColor: string) => {
setColor(newColor);
updateElement(id, { ...initialData, color: newColor });
};
return (
);
};
export default MyComponent;
```
--------------------------------
### Preview JointJS Production Build
Source: https://github.com/clientio/joint/blob/master/examples/absolute-port-layout-dynamic-port-sizes-js/README.md
Locally preview the production build of the JointJS application.
```bash
yarn preview
```
--------------------------------
### Deduplicate Layout Edges
Source: https://github.com/clientio/joint/blob/master/examples/genogram-ts/TUTORIAL.md
Identifies and flags duplicate layout edges to prevent the layout engine from getting confused. Only the first occurrence participates in layout; duplicates are added back later.
```typescript
const edgeKey = `${srcLayout}->${tgtLayout}`
const isDuplicate = layoutEdgeSet.has(edgeKey)
layoutEdgeSet.add(edgeKey)
if (isDuplicate) {
(link as any)._layoutDuplicate = true;
}
```
--------------------------------
### Build JointJS Distribution Files
Source: https://github.com/clientio/joint/blob/master/CONTRIBUTING.md
Build the distribution files for the JointJS project.
```bash
yarn dist
```
--------------------------------
### Render Resizable Node Demo
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/examples/with-resizable-node/docs.mdx
Displays a live demo of the resizable node component using Storybook's Canvas.
```tsx
```
--------------------------------
### Adjust Name Label Anchors for Orthogonal Links
Source: https://github.com/clientio/joint/blob/master/examples/genogram-ts/TUTORIAL.md
When using orthogonal link styles, name labels are adjusted to be anchored at the end for the left element and the start for the right element, ensuring they align correctly with the inset positioning.
```typescript
if (linkStyle === 'orthogonal') {
leftEl.attr('name', { textAnchor: 'end', x: `calc(w / 2 - ${sizes.nameMargin})` });
rightEl.attr('name', { textAnchor: 'start', x: `calc(w / 2 + ${sizes.nameMargin})` });
}
```
--------------------------------
### Navigate to JointJS Directory
Source: https://github.com/clientio/joint/blob/master/packages/joint-core/README.md
Change the current directory to the cloned JointJS repository.
```bash
cd joint
```
--------------------------------
### Define Custom Element with JSX Markup
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/utils/joint-jsx/jsx-to-markup.docs.mdx
Define a custom JointJS element using JSX syntax for its markup. This example shows how to integrate the `jsx` function to convert a JSX structure into the `MarkupJSON` format expected by JointJS elements.
```tsx
import { Meta , Canvas} from '@storybook/blocks';
import * as Stories from './jsx-to-markup.stories.tsx';
# `jsx-to-markup`
The `jsx-to-markup` utility allows you to define [JointJS](https://resources.jointjs.com/docs/jointjs/v4.0/joint.html) element markup using JSX syntax, making it easier to create and maintain complex SVG or HTML structures for custom JointJS elements.
## What does it do?
- Converts JSX elements (including fragments, custom components, and standard HTML/SVG tags) into JointJS's `MarkupJSON` format.
- Supports attribute extraction, including special handling for `joint-*` attributes.
- Allows you to use React-like composition for defining markup, but **does not** support dynamic React features (like hooks or state).
## Why use it?
- **Readability:** Write markup in familiar JSX/TSX syntax instead of verbose JSON.
- **Maintainability:** Compose and reuse markup using functional components.
- **Integration:** Seamlessly integrates with JointJS's custom element definitions.
## Example
```tsx
import { dia } from '@joint/core';
import { jsx } from '@joint/react';
const CustomRect = dia.Element.define(
'custom.Rect',
{
attrs: { body: { fill: '#007bff' }, label: { text: 'JSX Markup' } },
size: { width: 120, height: 50 },
},
{
// Here we using the jsx function to define the markup
markup: jsx(
),
}
);
```
## How does it work?
- The `jsx` function takes a JSX element and recursively converts it into the `MarkupJSON` format expected by JointJS.
- You can use fragments (`<>...>`) and custom functional components for markup composition.
- Attributes prefixed with `joint-` are extracted and attached as top-level properties in the markup object.
## Limitations
- Only static markup is supported. Dynamic React features (hooks, state, context) are **not** supported.
- Only functional components are supported for composition.
- All children must be valid JSX elements, strings, numbers, booleans, or null.
## See also
- [JointJS Markup documentation](https://resources.jointjs.com/docs/jointjs/v4.0/joint.html#dia.Element.markup)
- [JointJS React integration](https://resources.jointjs.com/docs/jointjs/v4.0/joint.html#ui.Paper)
---
```
--------------------------------
### Render Custom SVG Element as Node in JointJS
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/examples/with-svg-node/docs.mdx
This code defines the structure for rendering a custom SVG element as a node in JointJS. It imports necessary components from '@storybook/blocks' and local utilities, and then uses a Markdown block to display the source code of the example.
```tsx
import { Meta, Story, Canvas, Controls, Markdown } from '@storybook/blocks';
import * as Stories from './story';
import Code from './code?raw';
import {getAPIPropsLink} from '../../utils/get-api-documentation-link'
# Example: Using an SVG Element as a Node
This example demonstrates how to use an SVG element as a node in JointJS. By default, JointJS renders nodes using SVG. Here, we show how you can set {getAPIPropsLink('Paper', 'renderElement')} to render any custom SVG element.
### Demo
Below is a live demo of the example:
### Code
Here is the source code for this example:
{`\`\`\`tsx
${Code}
\`\`\`
`}
```
--------------------------------
### Run Specific Test File in JointJS Core
Source: https://github.com/clientio/joint/blob/master/CONTRIBUTING.md
Navigate to the joint-core package and run a specific client-side test file using npm.
```bash
cd packages/joint-core
npm run test-client -- --file=test/jointjs/graph.js
```
--------------------------------
### Run Layout Test Script
Source: https://github.com/clientio/joint/blob/master/examples/genogram-ts/README.md
Execute the Node.js layout test script to verify the layout pipeline without requiring a browser. Optionally specify a dataset to test.
```bash
yarn test-layout
yarn test-layout --data=thompson.json
```
--------------------------------
### Create and Add Devs Model Shape
Source: https://github.com/clientio/joint/blob/master/packages/joint-core/demo/devs/README.md
Instantiates a `devs.Model` shape with predefined ports and adds it to the graph. Demonstrates dynamic port manipulation and link creation.
```javascript
const shape = new joint.shapes.devs.Model({
position: {
x: 100,
y: 100
},
inPorts: ['in1', 'in2'],
outPorts: ['out1', 'out2']
});
shape.addTo(graph);
// adding/removing ports dynamically
shape.addInPort('in3');
shape.removeOutPort('out1').addOutPort('out3');
const link = new joint.shapes.devs.Link({
source: {
id: shape.id,
port: 'out3'
},
target: {
x: 200,
y: 300
}
});
link.addTo(graph);
// moving the input ports from `left` to `top`
shape.changeInGroup({ position: 'top' });
// moving the output ports 'right' to 'bottom'
shape.changeOutGroup({ position: 'bottom' });
```
--------------------------------
### Create Elements with Inferred and Custom Types
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/tutorials/step-by-step/docs.mdx
Demonstrates creating elements with inferred types and defining custom element types for type safety. Use `createElements` for node creation.
```tsx
import { InferElement } from '@joint/react';
import { createElements, GraphElement } from '@joint/react';
// Inferred type
const elements = createElements([
{ id: '1', label: 'Node 1', x: 100, y: 0, width: 100, height: 25 },
{ id: '2', label: 'Node 2', x: 100, y: 200, width: 100, height: 25 },
]);
// Here we can use the inferred type
type ElementType = InferElement;
// With custom type
interface MyNode extends GraphElement {
label: string;
color: string;
}
const customElements = createElements([
{ id: 'a', label: 'A', color: 'red', x: 0, y: 0, width: 80, height: 40 },
]);
```
--------------------------------
### Create Links Between Elements
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/tutorials/step-by-step/docs.mdx
Shows how to create simple links between elements using their IDs and advanced links using specific ports.
```tsx
import { createLinks } from '@joint/react';
// Simple link by id
const links = createLinks([{ id: 'l1', source: '1', target: '2' }]);
// Link with port (advanced)
const linksWithPorts = createLinks([
{ id: 'l2', source: { id: '1', port: 'out' }, target: { id: '2', port: 'in' } }
]);
```
--------------------------------
### Options Interface for Layout
Source: https://github.com/clientio/joint/blob/master/packages/joint-layout-msagl/README.md
Defines the configuration options available for customizing the layout process.
```typescript
// Callback type definitions
type GetSizeCallback = (element: dia.Element) => dia.Size;
type GetLabelSizeCallback = (cell: dia.Cell) => dia.Size | undefined;
type SetPositionCallback = (element: dia.Element, position: dia.Point) => void;
type SetVerticesCallback = (link: dia.Link, vertices: dia.Point[]) => void;
type SetLabelsCallback = (link: dia.Link, labelBBox: dia.BBox, points: dia.Point[]) => void;
type SetAnchorCallback = (link: dia.Link, linkEndPoint: dia.Point, bbox: dia.BBox, endType: 'source' | 'target') => void;
type SetClusterSizeCallback = (element: dia.Element, size: dia.Size) => void;
interface Options {
// Layout direction
layerDirection?: LayerDirectionEnum; // Default: LayerDirectionEnum.TB
// Spacing
layerSeparation?: number; // Default: 40
nodeSeparation?: number; // Default: 20
// Edge routing
edgeRoutingMode?: EdgeRoutingMode; // Default: EdgeRoutingMode.Rectilinear
polylinePadding?: number; // Default: 1
// Rectilinear self-loop offset
// Vertical pixel offset applied to the two inner vertices of a self-edge
// when edgeRoutingMode is Rectilinear. Default: 10
rectilinearSelfEdgeOffset?: number;
// Grid and origin
gridSize?: number; // Default: 0
x?: number; // Default: 0
y?: number; // Default: 0
clusterPadding?: dia.Sides; // Default: 10
// Element sizing callbacks
getSize?: GetSizeCallback; // Default: element.size()
getLabelSize?: GetLabelSizeCallback; // Default: element.get('labelSize')
// Callbacks for customizing how the layout is applied
setPosition?: SetPositionCallback; // Default: element.position(x, y)
setVertices?: boolean | SetVerticesCallback; // Default: true
setLabels?: boolean | SetLabelsCallback; // Default: true
setAnchor?: boolean | SetAnchorCallback; // Default: true
setClusterSize?: SetClusterSizeCallback; // Default: element.size(size)
}
```
--------------------------------
### Create Initial Elements
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/introduction.mdx
Use the createElements utility to generate an array of initial node data for your diagram. This is typically used when initializing the graph.
```ts
import { createElements } from '@joint/react';
const initialElements = createElements([
{ id: '1', type: 'rect', x: 10, y: 10, width: 100, height: 100 },
]);
```
--------------------------------
### Basic JointJS Graph Layout
Source: https://github.com/clientio/joint/blob/master/packages/joint-layout-msagl/README.md
Create a JointJS graph, add elements, and then apply MSAGL layout with default options.
```typescript
import { dia, shapes } from '@joint/core';
import { layout, EdgeRoutingMode } from '@joint/layout-msagl';
// Create your JointJS graph
const graph = new dia.Graph({}, { cellNamespace: shapes });
const paper = new dia.Paper({
model: graph,
cellViewNamespace: shapes,
el: document.getElementById('paper'),
});
const rect1 = new shapes.standard.Rectangle({
id: 'a',
size: { width: 80, height: 40 },
attrs: { label: { text: 'A' } }
});
const rect2 = new shapes.standard.Rectangle({
id: 'b',
size: { width: 80, height: 40 },
attrs: { label: { text: 'B' } }
});
const link = new shapes.standard.Link({ source: { id: 'a' }, target: { id: 'b' } });
graph.addCells([rect1, rect2, link]);
// Or with custom options
layout(graph, {
layerSeparation: 60,
nodeSeparation: 30,
edgeRoutingMode: EdgeRoutingMode.Rectilinear
});
```
--------------------------------
### Basic Hierarchical Layout with MSAGL
Source: https://github.com/clientio/joint/blob/master/packages/joint-layout-msagl/README.md
Applies a hierarchical layout to a graph with elements and links. Ensure the graph and paper are initialized before applying the layout.
```typescript
import { dia, shapes } from '@joint/core';
import { layout, LayerDirectionEnum, EdgeRoutingMode } from '@joint/layout-msagl';
const graph = new dia.Graph({}, { cellNamespace: shapes });
const paper = new dia.Paper({
model: graph,
cellViewNamespace: shapes,
el: document.getElementById('paper'),
});
// Create elements
const elements = ['A', 'B', 'C', 'D'].map(id =>
new shapes.standard.Rectangle({
id,
size: { width: 80, height: 40 },
attrs: { label: { text: id } }
})
);
// Create links to form a hierarchy: A -> B, A -> C, B -> D, C -> D
const links = [
new shapes.standard.Link({ source: { id: 'A' }, target: { id: 'B' } }),
new shapes.standard.Link({ source: { id: 'A' }, target: { id: 'C' } }),
new shapes.standard.Link({ source: { id: 'B' }, target: { id: 'D' } }),
new shapes.standard.Link({ source: { id: 'C' }, target: { id: 'D' } })
];
graph.addCells([...elements, ...links]);
// Apply layout
const bbox = layout(graph, {
layerDirection: LayerDirectionEnum.TB,
layerSeparation: 50,
nodeSeparation: 30,
edgeRoutingMode: EdgeRoutingMode.Rectilinear
});
```
--------------------------------
### Use Custom Highlighter
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/examples/with-highlighter/docs.mdx
Renders a custom highlighter. This allows for more advanced and specific visual effects.
```tsx
import { Highlighter } from '@joint/react';
return ;
```
--------------------------------
### Initialize DirectedGraph Layout with Custom Ordering
Source: https://github.com/clientio/joint/blob/master/examples/genogram-ts/TUTORIAL.md
Configures DirectedGraph layout with custom ordering to control crossing minimization. Ensure `minimize-crossings.ts` is available and imported.
```typescript
import { minimizeCrossings } from './minimize-crossings';
DirectedGraph.layout(graph, {
rankDir: 'TB',
nodeSep: sizes.symbolGap,
rankSep: sizes.levelGap,
customOrder: (glGraph, jointGraph, defaultOrder) => minimizeCrossings(
glGraph, jointGraph, defaultOrder,
{ parentChildLinks, layoutId, personById, identicalGroupOf, nodeMultipleGroup }
),
});
```
--------------------------------
### Send Element to Front
Source: https://github.com/clientio/joint/blob/master/packages/joint-core/demo/embedding/front-and-back.html
Use `toFront()` to bring an element to the forefront of the Z-index stack.
```javascript
red.toFront()
```
--------------------------------
### Customize Link Behavior with Routers and Connectors
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/tutorials/step-by-step/docs.mdx
Configure default link routing and connection styles using props like `defaultRouter` and `defaultConnector` on the `Paper` component.
```tsx
```
--------------------------------
### Use Opacity Highlighter
Source: https://github.com/clientio/joint/blob/master/packages/joint-react/src/stories/examples/with-highlighter/docs.mdx
Renders an opacity highlighter. This can be used to fade elements in or out.
```tsx
import { Highlighter } from '@joint/react';
return ;
```