### 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 ( {links.map((link) => ( ))} ); }; ``` -------------------------------- ### 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 ; ```