@visuallyjs/browser-ui-react-mcp 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"docs/apps/adding-interactivity.md":{"title":"Adding Interactivity","body":"# Adding Interactivity\n\nIn the [Building an App](/react/docs/apps/building-an-app.md) page we ran through the steps involved in creating a basic app and having it display some nodes and edges. On this page we're going to talk you through how to go about adding interactivity to the app - such things as the ability to drag new edges, respond to events, and more.\n\n## Dragging edges[](#dragging-edges)\n\nTo add support for dragging edges between vertices, we need to update the JSX we use to draw our nodes with some markup containing specific VisuallyJs attributes. We'll add a little red circle to the corner of each node to use an edge drag source, and we'll make the entire node element a drag target:\n\n```jsx\nconst viewOptions = {\n nodes: {\n default: {\n jsx: (ctx: JsxWrapperProps) => <div data-vjs-target={true} className=\"my-node\">\n <span>{ctx.data.label} {ctx.data.id}</span>\n <div className=\"edge-source\" data-vjs-source={true}/>\n </div>\n }\n },\n groups: {\n default: {\n constrain:true,\n jsx: (ctx: JsxWrapperProps) => <div data-vjs-target={true} className=\"my-group\">\n <strong>{ctx.data.label} {ctx.data.id}</strong>\n <div data-vjs-group-content={true}/>\n <div className=\"edge-source\" data-vjs-source={true}/>\n </div>\n }\n }\n}\n\n```\n\n**********\n\nWe've used some CSS to style the `.edge-source` elements. The key points to note are the **data-vjs-target** attribute on the node's root element, and the **data-vjs-source** attribute on the connect elements - respectively, they inform VisuallyJs that the entire element is an edge target, and that the red circles are edge sources. You can use any markup you like to setup this mechanism, you just need to use those attributes.\n\nEdges created with this setup will be of type `default`, but there are a number of attributes you can use to control what type of edge is created - we refer you to the [Edges](/react/docs/apps/edges/overview.md) documentation.\n\n## Events[](#events)\n\nVisuallyJs has a powerful event binding mechanism that allows you to map handlers to operations on the objects in your model. For example, let's map a `tap` event to our various mappings:\n\n```jsx\nimport { EVENT_TAP, \n NodeEventCallbackPayload, \n GroupEventCallbackPayload,\n EdgeEventCallbackPayload} from \"@visuallyjs/browser-ui\"\n\nconst viewOptions = {\n nodes:{\n default:{\n jsx: (ctx: JsxWrapperProps) => <div data-vjs-target={true} className=\"my-node\">\n <span>{ctx.data.label} {ctx.data.id}</span>\n <div className=\"edge-source\" data-vjs-source={true}/>\n </div>,\n events:{\n [EVENT_TAP]:(p:NodeEventCallbackPayload) => {\n alert(`You clicked on node ${p.obj.id}`)\n } \n }\n }\n },\n groups: {\n default: {\n constrain:true,\n jsx: (ctx: JsxWrapperProps) => <div data-vjs-target={true} className=\"my-group\">\n <strong>{ctx.data.label} {ctx.data.id}</strong>\n <div data-vjs-group-content={true}/>\n <div className=\"edge-source\" data-vjs-source={true}/>\n </div>,\n events:{\n [EVENT_TAP]:(p:GroupEventCallbackPayload) => {\n alert(`You clicked on group ${p.obj.id}`)\n }\n }\n }\n },\n edges:{\n default:{\n overlays:[{\n type:ArrowOverlay.type,\n options:{\n location:1\n }\n }],\n events:{\n [EVENT_TAP]:(p:EdgeEventCallbackPayload) => {\n if(confirm(`You clicked on edge ${p.obj.id}. Do you want to delete it?`)) {\n p.model.removeEdge(p.obj)\n }\n }\n }\n }\n }\n}\n\n```\n\nTry clicking on a node, group or edge - for nodes and groups you'll see a popup displaying their id, but for edges we ask you if you want to delete the edge. This demonstrates a powerful common thread throughout VisuallyJs - programmatically, you operate on your app at the data model level, and VisuallyJs takes care of what that means for the UI.\n\n**********\n\nNotice in the event mappings above the various types for the callback payloads:\n\n* Node event listeners are invoked with an object of type [NodeEventCallbackPayload]()\n* Group event listeners are invoked with an object of type [GroupEventCallbackPayload]()\n* Edge event listeners are invoked with an object of type [EdgeEventCallbackPayload]()\n\ninfo\n\nA `tap` event is an event captured by VisuallyJs, which consists of a `mousedown` event on some element, followed by a `mouseup` event on the same element, where the pointer has not moved between the two events. We recommend you use these events in preference to `click` events throughout your code, unless you have a specific reason to bind to a `click`. Browsers will fire a click event when you drag an element; they do not check that the pointer is in the same location on mouseup as it was on mousedown.\n\n## Next Steps[](#next-steps)\n\n[Layouts](layouts/overview)\n\n[Read about the available layouts in VisuallyJs](layouts/overview)\n\n[Edges](edges/overview)\n\n[Read about everything you can do with edges](edges/overview)","url":"https://visuallyjs.com/react/docs/apps/adding-interactivity","lib":"react","topic":"apps"},"docs/apps/building-an-app.md":{"title":"Building An App","body":"# Building an App\n\nOn this page we'll run through how to build a basic app with VisuallyJs - we'll be creating the app from the [Overview](/react/docs/apps.md) page, from the initial setup of the app with a couple of helper components, to the addition of nodes and groups and edges, and then we'll provide some suggestions for where you may wish to go next.\n\nNote that in this example we're providing you the basics of how to render groups, but not every app needs groups of course.\n\n## Installation[](#installation)\n\nYou'll need to ensure you've imported VisuallyJs:\n\n* npm\n* pnpm\n* yarn\n* bun\n\n```bash\nnpm install @visuallyjs/browser-ui-react\n\n```\n\n```bash\npnpm add @visuallyjs/browser-ui-react\n\n```\n\n```bash\nyarn add @visuallyjs/browser-ui-react\n\n```\n\n```bash\nbun add @visuallyjs/browser-ui-react\n\n```\n\n## Creating the app[](#creating-the-app)\n\n### 1. Import components and CSS[](#1-import-components-and-css)\n\nThe first step is to import `SurfaceComponent`, `ControlsComponent`, `MiniviewComponent` and the VisuallyJs default stylesheet:\n\n```jsx\nimport { SurfaceComponent, ControlsComponent, MiniviewComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\"\n\n```\n\n### 2. Create your component[](#2-create-your-component)\n\n```jsx\nexport default function MyApp() {\n return <div style={{width:\"600px\", height:\"500px\"}}>\n <SurfaceComponent>\n <ControlsComponent/>\n <MiniviewComponent/>\n </SurfaceComponent>\n </div>\n}\n\n```\n\nThis is the result - a blank canvas:\n\n**********\n\n### 3. Add nodes and group[](#3-add-nodes-and-group)\n\nNow we'll add the nodes and the group. Notice how the node `3` declares that it belongs to group `g1`.\n\n```jsx\nexport default function MyApp() {\n \n const data = {\n nodes:[\n { id:\"1\", label:\"Node\", left:50, top:30 },\n { id:\"2\", label:\"Node\", left:50, top:200 },\n { id:\"3\", label:\"Node\", left:50, top:30, group:\"g1\" }\n ],\n groups:[\n { id:\"g1\", left:280, top:30, label:\"Group\" }\n ]\n }\n \n return <div style={{width:\"600px\", height:\"500px\"}}>\n <SurfaceComponent data={data}>\n <ControlsComponent/>\n <MiniviewComponent/>\n </SurfaceComponent>\n </div>\n}\n\n```\n\n**********\n\ninfo\n\nOur nodes/groups have a `left` and `top` property, which defines their position. This is the default setup, in which VisuallyJs uses an [Absolute layout](/react/docs/apps/layouts/absolute.md). But VisuallyJs ships with a number of different layouts you can use to automatically position your elements - you can read about them in the [layouts docs](/react/docs/apps/layouts/overview.md). For node `3`, the left and top values define the node's position with respect to its parent group.\n\n### 4. Customise nodes and group[](#4-customise-nodes-and-group)\n\nSo far we've got a basic surface up and running and we're rendering our nodes and groups using some default JSX. But the real power of VisuallyJs apps comes when you supply the JSX to render nodes/groups yourself. To do that, we're going to declare a `viewOptions` object, into which we're going to set a mapping for nodes of type \"default\". The mapping provides the JSX to use to render the node:\n\n```jsx\nimport {SurfaceComponent, ControlsComponent, MiniviewComponent} from \"@visuallyjs/browser-ui-react\";\n\nexport default function MyApp() {\n\n const data = {...}\n\n const viewOptions = {\n nodes: {\n default: {\n jsx: (ctx: JsxWrapperProps) => <div className=\"my-node\">\n <span>{ctx.data.label} {ctx.data.id}</span>\n </div>\n }\n },\n groups: {\n default: {\n constrain:true,\n jsx: (ctx: JsxWrapperProps) => <div className=\"my-group\">\n <strong>{ctx.data.label} {ctx.data.id}</strong>\n <div data-vjs-group-content={true}/>\n </div>\n }\n }\n }\n\n return <div style={{width: \"600px\", height: \"500px\"}}>\n <SurfaceComponent data={data}>\n <ControlsComponent/>\n <MiniviewComponent/>\n </SurfaceComponent>\n </div>\n}\n\n```\n\n**********\n\nThe key piece to note here is the `ctx` object which is passed in to the JSX you provide - it contains information about the vertex that is being rendered, as well as the UI rendering it, and the underlying model. This object is of type [JsxWrapperProps]().\n\n#### Notes about styling[](#notes-about-styling)\n\nIn our code snippet above we do not show the specific styles used for the nodes/group - they are set by the underlying CSS, and can be anything at all. VisuallyJs will automatically adapt to whatever dimensions the objects in your UI end up having.\n\n#### Notes about the group[](#notes-about-the-group)\n\nThere are a couple of things to take note of regarding the group mapping in the above code snippet:\n\n* We declared `constrain:true` on the group mapping. This instructs VisuallyJs that children of the group cannot be dragged outside of the group. There are a number of related flags controlling child content - see the [groups](/react/docs/apps/nodes-and-groups/groups.md) page for a thorough discussion.\n* Inside our group's markup we declared a `div` that has `data-vjs-group-content=\"true\"` set on it. This is an optional mechanism you can use to tell VisuallyJs what part of your group nodes should act as the container for child nodes/groups. It allows you great flexibility in creating the UI representing groups in your data model.\n\n### 5. Add edges[](#5-add-edges)\n\nTo add edges to our app, we add them in to the `data` object we created above:\n\n```jsx\nconst data = {\n nodes:[ ... ],\n edges:[\n { source:\"1\", target:\"2\" }\n ]\n}\n\n```\n\n**********\n\n### 6. Customise edges[](#6-customise-edges)\n\nOur new edge uses the default settings - it's a straight line, it's anchored on each node on the face that is closest to the other node, and it has no overlays. We can update the `viewOptions` to include an edge definition:\n\n```jsx\nconst viewOptions = {\n nodes:{ ... }, \n edges:{\n default:{\n overlays:[\n { \n type:ArrowOverlay.type,\n options:{\n location:1\n }\n }\n ]\n }\n }\n}\n\n```\n\n**********\n\nHere, we've added an `Arrow` overlay, but there are many configuration options for edges - we'd recommend taking a look through the [edge documentation](/react/docs/apps/edges/overview.md) for a thorough discussion.\n\n## Next Steps[](#next-steps)\n\n[Adding Interactivity](adding-interactivity)\n\n[Add support for dragging edges, responding to events, and more](adding-interactivity)\n\n[Layouts](layouts/overview)\n\n[Read about the available layouts in VisuallyJs](layouts/overview)\n\n[Nodes](nodes)\n\n[Read about everything you can do with nodes](nodes)\n\n[Groups](groups)\n\n[Read about everything you can do with groups](groups)\n\n[Edges](edges/overview)\n\n[Read about everything you can do with edges](edges/overview)","url":"https://visuallyjs.com/react/docs/apps/building-an-app","lib":"react","topic":"apps"},"docs/apps/copy-paste.md":{"title":"Copy Paste","body":"# Copy/paste\n\nVisuallyJs offers an easy to use API for copy/paste - the `Surface` and `Paper` components expose a `clipboard` member, which offers a number of different methods. All paste operations are executed within a transaction and can be rolled-back/re-run as an atomic unit.\n\n## Copying objects[](#copying-objects)\n\nCall the `copy` method to add items to the clipboard. The signature of the `copy` method is:\n\n#### copy[](#copy)\n\nCopy some set of objects into the clipboard.\n\nSignature\n\ncopy(obj:[Base]() | [VisuallyJsSelection]() | Array<[Base]()> | [Path]())\n\nParameters\n\n| | | |\n| --- | ------------------------------------------------------------------ | ---------------------------------------------------- |\n| obj | [Base]() \\| [VisuallyJsSelection]() \\| Array<[Base]()> \\| [Path]() | The object, or objects, to copy in to the clipboard. |\n\nReturn value\n\nvoid\n\nYou can pass a variety of different types in to this method - any node, group or edge, or an array of these, or a [Selection](/react/docs/apps/model/selections.md) or [Path](/react/docs/apps/model/paths.md).\n\nIn this first example, our canvas initially has two nodes. The `addItemsToSelection` function connects these two nodes with a programmatic call to `addEdge`, and it then copies both nodes and the new edge into the clipboard. The `pasteItems` method pastes the contents of the clipboard, to canvas origin `{50, 250}` (paste origin is discussed below).\n\n```jsx\nimport { useRef } from \"react\"\nimport { SurfaceComponent, SurfaceComponentRef, SurfaceProvider } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const surfaceRef = useRef<SurfaceComponentRef>(null)\n \n function addItemsToSelection() {\n const surface = surfaceRef.current.getSurface()\n\n const source = surface.model.getNode(\"source\")\n const target = surface.model.getNode(\"target\")\n const edge = surface.model.addEdge({source, target})\n\n surface.clipboard.copy([source, target, edge]) // copy both nodes and the edge\n }\n\n function pasteItems() {\n const surface = surfaceRef.current.getSurface()\n surface.clipboard.paste({origin:{x:50, y:250}})\n }\n \n return <SurfaceProvider> \n <SurfaceComponent ref={surfaceRef} data={data}/>\n <button onClick={() => addItemsToSelection()}>Copy items</button>\n <button onClick={() => pasteItems()}>Paste items</button>\n </SurfaceProvider>\n}\n\n```\n\nWhen you paste the contents of this clipboard, a copy of `source` will be created, a copy of `target` will be created, and a copy of `edge` - whose source and target are the new vertices - will also be created.\n\nCopy itemsPaste items\n\n<br />\n\nNote that the pasted items are always pasted to the same place in this example - because we use `{origin:{x:50, y:250}}` in our paste command. The section below on paste options discusses the paste origin and what options are available to you.\n\n<br />\n\n***\n\n## Pasting clipboard contents[](#pasting-clipboard-contents)\n\nUse the `paste` method to paste the current contents of the clipboard.\n\n#### paste[](#paste)\n\nPaste the clipboard's most recent entry, optionally removing it from the clipboard afterwards.\n\nSignature\n\npaste(options:[BrowserUIPasteOptions]())\n\nParameters\n\n| | | |\n| ------- | ------------------------- | ---------------------- |\n| options | [BrowserUIPasteOptions]() | Options for the paste. |\n\nReturn value\n\n[ClonedSet]()\n\ninfo\n\n### Paste origin[](#paste-origin)\n\nA set of vertices has an implicit origin, which is computed as the `x` position of the leftmost vertex, and the `y` position of the topmost vertex. When you call paste without providing an `origin`, the new objects are placed on top of the existing object. When you call `paste` and provide an `origin` - as we did in the example above - the location of each vertex to be pasted is translated by the delta between the paste origin and the computed origin of the clipboard:\n\n```text\nsurface.clipboard.paste({origin:{x:50, y:250}})\n\n```\n\n### Event as origin[](#event-as-origin)\n\nIn real world use cases it is the user who generally decides where to paste content. The clipboard allows you to use a `MouseEvent` as the origin instead of specifying it yourself. At any point, the canvas for a given Surface has been panned in one or both axes, and is likely zoomed in or out to some value other than 1:1. When you provide a `MouseEvent` as the origin for a paste, the location of this event is automatically mapped to a location onto the Surface. In this next example, first press `Copy Items` to populate the clipboard. Then you can click anywhere on the canvas to paste the copied content:\n\n**********\n\nCopy items\n\n<br />\n\nThe code for this is as shown here - note our `EVENT_CANVAS_CLICK` listener in the render options. We pass the event from that method into the paste method.\n\n```jsx\nimport { useRef } from \"react\"\nimport { SurfaceComponent, SurfaceComponentRef, SurfaceProvider } from \"@visuallyjs/browser-ui-react\"\nimport { EVENT_CANVAS_CLICK } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const surfaceRef = useRef<SurfaceComponentRef>(null)\n \n function addItemsToSelection() {\n // ...\n }\n \n return <SurfaceProvider> \n <SurfaceComponent ref={surfaceRef} data={data} renderOptions={{\n events: {\n [EVENT_CANVAS_CLICK]: (ui, event) => ui.clipboard.paste({event})\n }\n }}/>\n <button onClick={() => addItemsToSelection()}>Copy items</button>\n </SurfaceProvider>\n}\n\n```\n\n### Vertices not in clipboard[](#vertices-not-in-clipboard)\n\nIn this snippet we create two nodes and an edge, and then we copy one of the nodes and the edge into the clipboard:\n\n```javascript\n\n// ... import and create a clipboard\n\nconst source = model.addNode({id:\"source\"})\nconst target = model.addNode({id:\"target\"})\nconst edge = model.addEdge({source, target})\n\nsurface.clipboard.copy([source, edge]) // copy source node only and the edge\n\n\n```\n\nWhat happens now if we paste this?\n\n```javascript\nclipboard.paste({event:someMouseEvent})\n\n```\n\nBy default, the clipboard will create a copy of `source`, and a copy of `edge`. The cloned source will be the source for the cloned edge, but the target for the cloned edge will be the *original target* vertex. You can see that in this example:\n\n**********\n\nCopy items\n\n<br />\n\nThis behaviour can be modified via the use of the `hermetic` flag.\n\n```javascript\nclipboard.paste({event:someMouseEvent, hermetic:true})\n\n```\n\nIn this call, `hermetic:true` instructs the clipboard to only paste edges for which both the source and target vertices were also in the clipboard. So in this case, only a clone of the `source` vertex will be pasted, and the edge will **not** be pasted. `hermetic` defaults to `false`.\n\n### Edge geometry[](#edge-geometry)\n\nAn edge that has \"geometry\" attached to it is an edge that has either been loaded with a `geometry` section in the JSON, or has been edited by a connector editor, using the mouse, or fingers. When you copy an edge with geometry and subsequently paste it, the rules for the associated geometry are:\n\n* if you copy and paste the edge and both its source and target vertices, the pasted edge has geometry attached, the value for which is the original edge's geometry translated according to the transformation of the origin as discussed above.\n\n* if you copy and paste an edge but not both its source and target vertices, the pasted edge does *not* have geometry attached, and will be painted according to VisuallyJs's default algorithm for the specific connector.\n\n### Nested groups and nodes[](#nested-groups-and-nodes)\n\nIf you copy and paste a group that has child nodes or groups, the child nodes or groups will also be copied, and pasted as children of the pasted group. This mechanism works to an arbitrary level of nesting. If you wish to copy a group without any of its child content, you can specify a \"shallow\" paste, by setting `shallow:true` on the paste call:\n\n```typescript\nclipboard.paste({event, shallow:true}) \n\n```\n\nIn this canvas we have copied the main group into the clipboard on load. When you left-click on the canvas, the group is pasted with all of its descendants at the point you clicked. When you right-click, the group is \"shallow\" pasted - only the group itself, not any of its descendants.\n\n**********\n\n<br />\n\nThis is the code we used:\n\n```jsx\nimport { useRef, useEffect } from \"react\"\nimport { SurfaceComponent, SurfaceComponentRef, SurfaceProvider } from \"@visuallyjs/browser-ui-react\"\nimport {EVENT_CANVAS_CLICK, EVENT_CONTEXTMENU} from \"@visuallyjs/browser-ui\";\n\nconst shallowCopyData = {\n groups:[\n {id:\"g1\", left:50, top:10 },\n {id:\"g2\", left:50, top:10, group:\"g1\" },\n {id:\"g3\", left:50, top:10, group:\"g2\" }\n ],\n nodes:[\n { id:\"1\", left:50, top:10, group:\"g3\" }\n ]\n}\n\nexport default function MyComponent() {\n\n const surfaceRef = useRef<SurfaceComponentRef>(null)\n \n const renderOptions = {\n events: {\n // on left-click, paste a deep clone of the group\n [EVENT_CANVAS_CLICK]: (ui, event) => ui.clipboard.paste({event}),\n // on right-click, paste a shallow clone of the group\n [EVENT_CONTEXTMENU]: (ui, event) => ui.clipboard.paste({event, shallow:true})\n }\n }\n\n // on load we zoom out and center the group so there's some whitespace for you to click in.\n // then we copy group `g1` to the clipboard.\n useEffect(() => {\n const s = surfaceRef.current.getSurface()\n s.setZoom(0.4)\n s.centerContent()\n s.clipboard.copy(s.model.getGroup(\"g1\"))\n }, []);\n \n return <SurfaceProvider> \n <SurfaceComponent ref={surfaceRef} data={shallowCopyData} renderOptions={renderOptions}/>\n </SurfaceProvider>\n}\n\n```\n\n## Pasting the current selection[](#pasting-the-current-selection)\n\nAs discussed in the [Selection docs](/react/docs/apps/model/selections.md), each VisuallyJs model maintains a list of currently selected objects, and various parts of the UI add/remove objects to/from the current selection. You can paste the current selection for some model via the `pasteCurrentSelection` method:\n\n#### pasteCurrentSelection[](#pastecurrentselection)\n\nCopies and pastes the contents of the associated model instance's current selection into the clipboard. This method is equivalent to calling `copyCurrentSelection()` first and then calling `paste(..)`.\n\nSignature\n\npasteCurrentSelection(options:[PasteOptions]())\n\nParameters\n\n| | | |\n| ------- | ---------------- | ---------------------- |\n| options | [PasteOptions]() | Options for the paste. |\n\nReturn value\n\n[ClonedSet]()\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { EVENT_TAP, EVENT_CANVAS_CLICK } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n events: {\n [EVENT_CANVAS_CLICK]: (ui, event) => ui.clipboard.pasteCurrentSelection({event})\n }\n}\n\n const viewOptions = {\n nodes: {\n default: {\n events: {\n [EVENT_TAP]: (p) => p.model.toggleSelection(p.obj)\n }\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions} viewOptions={viewOptions}/>\n}\n\n```\n\nIn this canvas, when you tap a vertex it will be added to the model's current selection. Subsequently clicking on the canvas will paste a copy of the vertices in the current selection at the location you clicked. To clear the selection, use the `Clear selection` button in the controls.\n\n**********\n\n<br />\n\n## Clearing the clipboard[](#clearing-the-clipboard)\n\nThe clipboard offers a `clear` method that will remove all copied content:\n\n```text\nclipboard.clear()\n\n```\n\nYou can also instruct the clipboard to clear the content that was just pasted:\n\n```javascript\nclipboard.paste({origin:{x:50, y:50}, clear:true})\n\n```","url":"https://visuallyjs.com/react/docs/apps/copy-paste","lib":"react","topic":"apps"},"docs/apps/drag-and-drop/palettes.md":{"title":"Palettes","body":"# Palettes\n\nA common use case in the sorts of applications for which VisuallyJs is useful is the requirement to be able to drag and drop new nodes/groups onto the workspace.\n\n## Setup[](#setup)\n\nTo configure your UI to drag and drop HTML elements onto your canvas, you'll use a `PaletteComponent`. Here's how to set one up:\n\n```jsx\n\nimport { PaletteComponent, SurfaceComponent, SurfaceProvider } from '@visuallyjs/browser-ui-react';\n\nexport default function MyApp() {\n \n return <div className=\"row\">\n <SurfaceProvider>\n <div className=\"col-9\">\n <SurfaceComponent/>\n </div>\n <div className=\"col-3\">\n <PaletteComponent selector=\"li\">\n <ul>\n <li data-vjs-type=\"foo\" vjs-is-group=\"true\">FOO</li>\n <li data-vjs-type=\"bar\">BAR</li>\n </ul>\n </PaletteComponent>\n </div>\n </SurfaceProvider>\n </div> \n}\n\n\n```\n\nThe basic contract is that you declare a `PaletteComponent` in your JSX, and you provide - at the minimum - a `selector`, which tells the palette component how to find which children of the component are draggable. You then write out the children however you like - in this case we use a `ul` and an `li` for each draggable type.\n\nThe `PaletteComponent` needs to know which surface it is going to be attached to, and it does this by being context aware - in the code above we have a `SurfaceProvider` wrapping both the surface component and the palette component. When the surface component is instantiated, it populates the surface provider's context, and the palette component is notified of the surface to use.\n\n## Providing data for a dragged element[](#providing-data-for-a-dragged-element)\n\nThe drop manager uses a `dataGenerator` function to get a suitable piece of backing data for some element that is being dragged. If you do not provide a `dataGenerator`, the default generator is used, which gets data values from `data-vjs-***` attributes on the element a user is dragging. For instance with this element:\n\n```html\n<div data-vjs-type=\"process\" data-vjs-label=\"Process\" data-vjs-width=\"120\" data-vjs-height=\"80\">Process</div>\n\n```\n\nVisuallyJs will prepare this payload for the object representing the drag:\n\n```javascript\n{\n \"type\":\"process\",\n \"label\":\"Process\",\n \"width\":\"120\",\n \"height\":\"80\"\n}\n\n```\n\nnote\n\nThe default mechanism used by VisuallyJs for determining the type of some object is to test the `type` member. Providing `type` as we have here allows VisuallyJs to determine which template to use to render the node, how it will behave, etc.\n\nYou can supply a `dataGenerator` function if you want to customise the initial dataset for dragged elements:\n\n```jsx\n\nimport { PaletteComponent, SurfaceComponent, SurfaceProvider } from '@visuallyjs/browser-ui-react';\n\nexport default function MyApp() {\n \n const dataGenerator = (el) => { \n return { \n width:120, \n height:80, \n type:el.getAttribute(\"data-vjs-type\") \n } \n };\n \n return <div className=\"row\">\n <SurfaceProvider>\n <div className=\"col-9\">\n <SurfaceComponent/>\n </div>\n <div className=\"col-3\">\n <PaletteComponent selector=\"li\" dataGenerator={dataGenerator}>\n <ul>\n <li data-vjs-type=\"foo\" vjs-is-group=\"true\">FOO</li>\n <li data-vjs-type=\"bar\">BAR</li>\n </ul>\n </PaletteComponent>\n </div>\n </SurfaceProvider>\n </div> \n}\n\n\n```\n\nIn the code above we also see a `dataGenerator` prop: `dataGenerator` provides a means for the component to generate an initial data payload for some node that is being dragged. You do not need to provide a `dataGenerator` - by default, VisuallyJs will extract any `data-vjs-***` attributes as the initial payload for a node/group.\n\n## Distinguishing between a node and a group[](#distinguishing-between-a-node-and-a-group)\n\nBy default, VisuallyJs will look for a `data-vjs-is-group` attribute on a dragged element. If the value of this attribute is `\"true\"`, VisuallyJs will assume the element represents a group. You can provide your own `groupIdentifier` if you wish.\n\n## Specifying the size for a new element[](#specifying-the-size-for-a-new-element)\n\nBy default, the `SurfacePalette` clones the DOM element on which the user started a drag and then sets the size of the element that is being dragged to match the bounding client rectangle of the element that was cloned.\n\nIn some situations, particularly when you have a grid in your surface, you may wish to mandate the size for any new elements that are being dragged on to the surface, which you can do by providing a `dragSize` object:\n\n```jsx\n<PaletteComponent selector=\"li\" dragSize={{ width:250, h: 100 }}>\n\n</PaletteComponent>\n\n```\n\n## Filtering draggable elements[](#filtering-draggable-elements)\n\nIt is possible, when drag starts, to decide whether or not you want the dragged element to be droppable on the canvas, via the `canvasDropFilter` prop:\n\n```jsx\n\n<PaletteComponent selector=\"li\" \n canvasDropFilter={(data) => data.type === \"someDroppableOnCanvasType\"}>\n\n ...\n \n</PaletteComponent>\n\n```\n\n## Getting notification of a new vertex[](#getting-notification-of-a-new-vertex)\n\nYou can create a `PaletteComponent` with an `onVertexAdded` callback, which will be invoked whenever a new vertex has been dropped onto the canvas:\n\n```jsx\n\n<PaletteComponent selector=\"li\" \n onVertexAdded={(vertex, dropTarget) => { } }>\n\n ...\n\n</PaletteComponent>\n\n```\n\n`vertex` is the new vertex that was added. In the event that the new vertex was dropped on top of some existing node, `dropTarget` will be provided, containing information about the node onto which the new vertex was dropped, as well as its position and size.\n\n## Working with decorators[](#working-with-decorators)\n\nIf you have any Decorators in your UI, you may wish to inform the drop manager about the elements they have created, because without doing this the drop manager will not be able to recognise them as background. To do this, you use the `canvasSelector` prop:\n\n```jsx\n<PaletteComponent selector=\"li\" canvasSelector=\".someElementMyDecoratorCreated\">\n\n</PaletteComponent>\n\n```\n\n`canvasSelector` takes any valid CSS3 selector. This identifies the elements that your decorator has created that the drop manager should treat as background.\n\n## CSS[](#css)\n\n| Class | Description |\n| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| `vjs-drag-active` | Assigned to any element that is a candidate drop target for an edge that is being dragged |\n| `vjs-drag-hover` | Assigned to any element that is the current drop target for an edge that is being dragged |\n| `vjs-palette-current-shape-type` | Assigned to a shape in a ShapePalette that matches the type of the model's currently selected shape. |\n| `vjs-palette-drag-active` | Assigned to possible drop targets when an element is being dragged from the Palette |\n| `vjs-palette-drag-hover` | Assigned to a drop target when an element that is being dragged from the Palette is hovering over it. |\n| `vjs-palette-drag-hover-cannot-drop` | Assigned to a vertex or the canvas when an element that is being dragged from the palette is hovering over it but drop is not allowed. |\n| `vjs-palette-current` | Assigned to an element when it is being dragged from a palette |\n| `vjs-palette-selected-element` | Assigned to the currently selected element in a palette when in tap/draw mode. |\n| `vjs-palette-tap-mode-active` | Assigned to the surface canvas when a user has tapped an element in a palette in tap mode. this class can be used to show the user that a vertex can be dropped via click or drawn on the canvas |\n\nIn order to use these classes for visual cues in the UI, you'll probably want to define slightly different selectors for each target type. Let's suppose when a drag starts we want to outline our canvas and any nodes/groups with a purple line, and we want to draw any possible target edges with a purple line too:\n\n```css\n.vjs-surface.vjs-palette-active, .vjs-node.vjs-palette-active, .vjs-group.vjs-palette-active {\n outline:4px solid purple;\n}\n\nsvg.vjs-palette-active path {\n stroke:purple;\n}\n\n```\n\nNow when something is the current drop target, we'll either outline it green or make its path green:\n\n```css\n.vjs-surface.vjs-palette-hover, .vjs-node.vjs-palette-hover, .vjs-group.vjs-palette-hover {\n outline:4px solid green;\n}\n\nsvg.vjs-palette-hover path {\n stroke:green;\n}\n\n```\n\nThis is just an example of course. You can do anything with the CSS that you like.\n\n***\n\n## Options[](#options)\n\nPaletteComponentProps\n\nProps for the `PaletteComponent`\n\n| Name | Type | Description |\n| ------------------ | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| allowClickToAdd? | boolean | When in draw mode, allow addition of new vertices simply by clicking, instead of requiring a shape be drawn. (When this is true, the drag to draw functionality also still works) |\n| allowDropOnCanvas? | boolean | Whether or not to allow drop on whitespace in the canvas. Defaults to true. |\n| allowDropOnEdge? | boolean | Whether or not to allow drop on edge. Defaults to false. |\n| allowDropOnGroup? | boolean | Whether or not to allow drop on existing vertices. Defaults to true. |\n| allowDropOnNode? | boolean | Defaults to false. Allows items to be dropped onto nodes in the canvas. If this is true and an element is dropped onto a node, the result is the same as if the element has been dropped onto whitespace. Note that when this is false and the user has dragged something over a node, the drag item is still not considered to be over the canvas, and releasing the mouse button at that time will not cause a new node to be added. Use `ignoreDropOnNode` if that's the behaviour you want. |\n| canvasDropFilter? | [CanvasDropFilter<]()[BrowserElement]()> | Optional filter to test if objects may be dropped on the canvas. |\n| className? | string | Optional extra css classes to set on the element |\n| clickToAddOnly? | boolean | This flag relates to \"draw\" mode, and defaults to false. When true, the palette only supports click to draw new vertices, not drag. This flag is forced to true if the associated UI does not have `useModelForSizes` set, since there is no point in allowing a user to drag a vertex to some size if its not going to be honoured. When you set this flag and associated UI does have `useModelForSizes` set, the palette will use default sizes for new nodes/groups. |\n| dataGenerator? | [DataGeneratorFunction<]()[BrowserElement]()> | Function to use to get a dataset for an item that is being dragged or has been tapped. If omitted, Visually JS will use a default data generator that extracts data values from any `data-vjs-***` attribute on the element being dragged. |\n| dragSize? | [Size]() | Optional size to use for elements dragged from the palette, when in \"drag\" mode |\n| groupIdentifier? | [GroupIdentifierFunction<]()[BrowserElement]()> | Function to use to determine whether an item that is being dragged or has been tapped represents a group. |\n| ignoreDropOnNode? | boolean | Defaults to false. When true, the palette treats nodes as if they are part of the canvas - a user can drag new items on top of existing nodes and the new item will be added to the canvas. If you want to force your users to drop on canvas whitespace, don't set this. Note that this flag will force `allowDropOnNode` to `false`. |\n| mode? | PaletteMode | Mode to operate in - 'drag', 'tap' or 'draw'. Defaults to 'drag'. |\n| onVertexAdded? | [OnVertexAddedCallback]() | Optional callback that will be invoked after a new vertex has been dropped and added to the dataset. |\n| selectAfterAdd? | boolean | Defaults to false. When true, a newly added vertex is set as the model's current selection. |\n| selector? | string | CSS 3 selector identifying what child elements of `container` are draggable/tappable. Optional. If omitted, a default of `[data-vjs-type]` will be used. |\n| surface? | [Surface]() | The surface to attach to. Optional: this component can derive a surface from a SurfaceProvider or SurfaceComponent. You'll only need this in certain advanced scenarios. |\n| typeGenerator? | [TypeGeneratorFunction<]()[BrowserElement]()> | Function to use to get the type of an item that is being dragged or has been tapped. |","url":"https://visuallyjs.com/react/docs/apps/drag-and-drop/palettes","lib":"react","topic":"apps"},"docs/apps/edges/anchors.md":{"title":"Anchors","body":"# Anchors\n\nAn anchor models the notion of where on an element an edge should connect. There are three main types:\n\n* **static** - These are fixed to some point on an element and do not move. They can be specified using a string to identify one of the defaults that VisuallyJs ships with, or an object describing the location and orientation of edges connected to it.\n\n* **dynamic** - These are lists of static anchors from which VisuallyJs selects the most appropriate one each time a connection is painted. The algorithm used to determine the most appropriate anchor picks the one that is closest to the center of the other element in the connection. A future version of VisuallyJs might support a pluggable algorithm to make this decision.\n\n* **continuous** - These anchors are not fixed to any specific location; they are assigned to one of the four faces of an element depending on that element's orientation to the other element in the associated connection. These are the default anchors used by VisuallyJs.\n\n## Static Anchors[](#static-anchors)\n\nVisuallyJs has nine default anchor locations you can use to specify where the connectors connect to elements: these are the four corners of an element, the center of the element, and the midpoint of each edge of the element:\n\nTopLeft\n\nTopRight\n\nTop\n\nBottomLeft\n\nBottomRight\n\nBottom\n\nCenter\n\nLeft\n\nRight\n\nEach of these string representations is just a wrapper around the underlying object-based syntax `{x, y, ox, oy}`, where `x` and `y `are coordinates in the interval `[0,1]` specifying the position of the anchor, and `ox` and `oy`, which specify the orientation of the curve incident to the anchor, can have a value of 0, 1 or -1. For example, `{x:0, y:0.5, ox:-1, oy:0}` defines a `Left` anchor with a connector curve that emanates leftward from the anchor. Similarly, `{x:0.5, y:0, ox:0, oy:-1}` defines a `Top` anchor with a connector curve emanating upwards.\n\n```javascript\nanchor:\"Bottom\"\n\n```\n\nis identical to:\n\n```javascript\nanchor:{ x:0.5, y:1, ox:0, oy:1 }\n\n```\n\n### Anchor Offsets[](#anchor-offsets)\n\nIn addition to supplying the location and orientation of an anchor, you can optionally supply two more parameters that define an offset in pixels from the given location. Here's the anchor specified above, but with a 50 pixel offset below the element in the y axis:\n\n```javascript\nanchor:{ x:0.5, y:1, ox:0, oy:1, offsetX:0, offsetY:50 } \n\n```\n\n## Dynamic Anchors[](#dynamic-anchors)\n\nThese are anchors that can be positioned in one of a number of locations, choosing the one that is most appropriate each time something moves or is painted in the UI.\n\nThere is no special syntax for creating a dynamic anchor; you just provide an array of individual static anchor specifications, eg:\n\n```javascript\n\nanchor:[\n {x:0.2, y:0, ox:0, oy:-1 },\n {x:1, y:0.2, ox:1, oy:0 },\n {x:0.8, y:1, ox:0, oy:1 },\n {x:0, y:0.8, ox:-1, oy:0 } \n]\n\n```\n\nNote that you can mix the types of these individual static anchor specifications:\n\n```javascript\nanchor:[\n {x:0.2, y:0, ox:0, oy:-1 },\n {x:1, y:0.2, ox:1, oy:0 },\n \"Top\",\n \"Bottom\"\n]\n\n\n```\n\n### Default[](#default)\n\nVisuallyJs provides a dynamic anchor called `AutoDefault` that chooses from `Top`, `Right`, `Bottom` and `Left`:\n\n```javascript\nanchor:\"AutoDefault\"\n\n```\n\nThese two nodes have an endpoint with an `AutoDefault` anchor - drag them around and see how they choose from `Top`, `Left`, `Bottom` and `Right` depending on their orientation.\n\n**********\n\n### Location selection[](#location-selection)\n\nThe algorithm that decides which location to choose just calculates which location is closest to the center of the other element in the edge. It is possible that future versions of VisuallyJs could support more sophisticated choice algorithms, if the need arose.\n\n## Continuous Anchors[](#continuous-anchors)\n\nAs discussed above, these are anchors whose positions are calculated by VisuallyJs according to the orientation between elements in a connection, and also how many other continuous anchors happen to be sharing the element. You specify that you want to use continuous anchors using the string syntax you would use to specify one of the default static anchors, for example:\n\n```javascript\nanchor:\"Continuous\"\n\n```\n\nNote in this example we specified only \"anchor\", rather than \"anchors\" - VisuallyJs will use the same spec for both anchors. But we could have said this:\n\n```javascript\nanchors:[\"Bottom\", \"Continuous\"]\n\n```\n\n...which would have resulted in the source element having a static anchor at `Bottom`. In practise, though, it seems the continuous anchors work best if both elements in a connection are using them.\n\nTry dragging these nodes around and see how the anchors adapt their positions:\n\n**********\n\n### Face selection[](#face-selection)\n\nBy default, a continuous anchor will choose points from all four faces of the element on which it resides. You can control this behaviour, though, with the `faces` parameter on the anchor spec:\n\n```javascript\nanchor:{ type:\"Continuous\", options:{ faces:[ \"top\", \"left\" ] } }\n\n```\n\nAllowed values are:\n\n* `top`\n* `left`\n* `right`\n* `bottom`\n\nIf you provide an empty array for the `faces` parameter, VisuallyJs will default to using all four faces.","url":"https://visuallyjs.com/react/docs/apps/edges/anchors","lib":"react","topic":"apps"},"docs/apps/edges/click-to-add-edges.md":{"title":"Click To Add Edges","body":"# Click to add edges\n\nThis is an input method for edges whereby your users click a source vertex to select it, and then click a target vertex. With pointer devices the user can see the edge that is being created as the pointer moves to the target, but with touch devices this is not the case, so take that into account if you're considering using this.\n\n## Configuration[](#configuration)\n\nTo setup click to add edges, you specify a flag in your render options:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n inputMethod: \"click\"\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n## HTML configuration[](#html-configuration)\n\nIn your HTML, the setup is the same as for when you wish to enable [edge dragging](/react/docs/apps/edges/dragging-edges.md):\n\n```jsx\n<div data-vjs-target=\"true\">\n <h1>Some Vertex</h1>\n <div data-vjs-source=\"true\" className=\"dragFromHere\"></div>\n</div>\n\n```\n\nAll of the same attributes are supported for click to add edges; the only difference is in the user's interaction.\n\n**********\n\n## Cancelling edge input[](#cancelling-edge-input)\n\nIf you've clicked a source vertex but you wish to abort, you have one of two choices:\n\n* Press the **ESCAPE** key\n* Right-click somewhere in the canvas whitespace\n\ncaution\n\nIf you have set `consumeRightClick:false` in your render options, right click will *not* work to cancel edge input.\n\n## Unattached edges[](#unattached-edges)\n\nThe click to add functionality cannot currently be used to establish an edge whose target is initially unattached.\n\n## Relocating edges[](#relocating-edges)\n\nEdges that were added via click-to-add can only be relocated by dragging.\n\n## CSS Classes[](#css-classes)\n\n| Class | Description |\n| ----------------------------- | -------------------------------------------------------------------------------------------------- |\n| `vjs-edge-click-entry-method` | Added to the document body when in click mode for edges, and the user has clicked/tapped a source. |","url":"https://visuallyjs.com/react/docs/apps/edges/click-to-add-edges","lib":"react","topic":"apps"},"docs/apps/edges/connectors.md":{"title":"Connectors","body":"# Connectors\n\nThis page contains definitions and examples for the various connectors that ship with VisuallyJs.\n\n## Bezier[](#bezier)\n\nProvides a cubic Bezier path (having two control points) between the two anchors.\n\n```javascript\n\n{\n \"connector\": \"Bezier\"\n}\n\n```\n\n**********\n\n### Scale[](#scale)\n\nThe key measurement in the Bezier connector is how far the control points are from the anchors. This is controlled by the `scale` option, which is a measure of the ratio of a control point's distance from its anchor compared to the distance between the two anchors in the edge. By default this is 0.45. Increasing this value will make the connector more curvy - in the canvas below we have set it to 0.85:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Bezier\",\n \"options\": {\n \"scale\": 0.85\n }\n }\n}\n\n```\n\n**********\n\nYou can set this to any number, even numbers greater than 1.\n\n### Stubs[](#stubs)\n\nYou can set a `stub` on the connector:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Bezier\",\n \"options\": {\n \"stub\": 25\n }\n }\n}\n\n```\n\n**********\n\n### Gap[](#gap)\n\nYou can set a `gap` on the connector to leave some space between the anchor point and the connector line:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Bezier\",\n \"options\": {\n \"gap\": 10\n }\n }\n}\n\n```\n\n**********\n\n### Options[](#options)\n\nBezierConnectorOptions\n\nOptions for CubicBezierConnector\n\n| Name | Type | Description |\n| ----------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| cssClass? | string | Optional class to set on the element used to render the connector. |\n| gap? | number | Defines a number of pixels between the end of the connector and its anchor point. Defaults to zero. |\n| hoverClass? | string | Optional class to set on the element used to render the connector when the mouse is hovering over the connector. |\n| loopbackDistance? | number | When the connector's source and target is the same vertex, this is a measure of how far the control point will<br />be placed from the element. Defaults to 62 pixels |\n| scale? | number | Where to put the control point relative to the source/target. The number provided here should be a decimal, whose value defines the proportional distance between the source and target that the control point should be located at. The default value is 0.45. Larger values will make the Bezier curvier. |\n| stub? | number | Stub defines a number of pixels that the connector travels away from its element before the connector's actual path begins. |\n\n***\n\n## Straight[](#straight)\n\nDraws a series of one or more straight line segments between the source and target, with options to smooth to a curve or to round the corners between segments. The default computation creates a single segment, but if you have vertex avoidance switched on, or if you edit the path, then the connector will have multiple segments.\n\n```javascript\n\n{\n \"connector\": \"Straight\"\n}\n\n```\n\n**********\n\n### Stubs[](#stubs-1)\n\nYou can set a `stub` on the connector:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Straight\",\n \"options\": {\n \"stub\": 25\n }\n }\n}\n\n```\n\n**********\n\n### Gap[](#gap-1)\n\nYou can set a `gap` on the connector to leave some space between the anchor point and the connector line:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Straight\",\n \"options\": {\n \"gap\": 10\n }\n }\n}\n\n```\n\n**********\n\n### Geometry[](#geometry)\n\nYou can supply a `geometry` object for the edge that the connector represents for when you want multiple segments:\n\n```javascript\nedges:[\n{ \n \"source\":\"1\", \n \"target\":\"3\",\n \"geometry\":{\n source:{ curX:170, curY:90, ox:1, oy:0, x:1, y:0.5 },\n target:{ curX:510, curY:230, ox:0, oy:1, x:0.5, y:1 },\n segments:[\n { x1: 170, y1: 90, x2:250, y2:90 },\n { x1: 250, y1: 90, x2:400, y2:310 },\n { x1: 400, y1:310, x2:510, y2:230 }\n ]\n }\n }\n]\n\n```\n\n```javascript\n\n{\n \"connector\": \"Straight\"\n}\n\n```\n\n**********\n\n### Smoothing[](#smoothing)\n\nYou can also specify that you want to smooth the connector via the `smooth` option:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Straight\",\n \"options\": {\n \"smooth\": true\n }\n }\n}\n\n```\n\n**********\n\nnote\n\nIf you set `smooth:true` on a `Straight` connector but don't provide a a value for `stub` then you won't see any curve when there's only one segment, as the smoothing is only applied when the connector has more than one segment. If you provide a small value for `stub` you will see quite a pronounced hook, as in the following example where we set `stub` to 10.\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Straight\",\n \"options\": {\n \"stub\": 10,\n \"smooth\": true\n }\n }\n}\n\n```\n\n**********\n\nCompare with the same dataset and a `stub` of 50:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Straight\",\n \"options\": {\n \"stub\": 50,\n \"smooth\": true\n }\n }\n}\n\n```\n\n**********\n\nSmoothing works better when there are multiple segments in the connector, or when it does not just consist of one straight segment and stubs.\n\n### Rounded corners[](#rounded-corners)\n\nAn alternative to smoothing is rounded corners:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Straight\",\n \"options\": {\n \"cornerRadius\": 15\n }\n }\n}\n\n```\n\n**********\n\n### Options[](#options-1)\n\nStraightConnectorOptions\n\nOptions for a straight connector.\n\n| Name | Type | Description |\n| ------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| alwaysRespectStubs? | boolean | Defaults to true, meaning always draw a stub of the desired length, even when the source and target elements are very close together. This only applies when constrain is set to PATH\\_CONSTRAIN\\_ORTHOGONAL. |\n| constrain? | [ConnectorPathConstrainment]() | Optional constraint on the direction path segments can travel in. Options are PATH\\_CONSTRAIN\\_NONE, PATH\\_CONSTRAIN\\_ORTHOGONAL (segments are vertical and/or horizontal lines) and PATH\\_CONSTRAIN\\_DIAGONAL (segments are vertical, horizontal, or 45 degree lines). You can also use PATH\\_CONSTRAIN\\_MANHATTAN as an alias for PATH\\_CONSTRAIN\\_ORTHOGONAL or PATH\\_CONSTRAIN\\_METRO as an alias for PATH\\_CONSTRAIN\\_DIAGONAL. |\n| cornerRadius? | number | Optional radius to apply to corners. If you have set `smooth:true` this will be ignored. |\n| cssClass? | string | Optional class to set on the element used to render the connector. |\n| gap? | number | Defines a number of pixels between the end of the connector and its anchor point. Defaults to zero. |\n| hoverClass? | string | Optional class to set on the element used to render the connector when the mouse is hovering over the connector. |\n| loopbackRadius? | number | For a loopback connection (when constrain is set to orthogonal), the size of the loop. |\n| midpoint? | number | The point to use as the halfway point between the source and target when constrain is set to orthogonal. Defaults to 0.5. |\n| slightlyWonky? | boolean | If true, and a cornerRadius is set, the lines are drawn in such a way that they look slightly hand drawn. |\n| smooth? | boolean | Whether or not to smooth the connector. Defaults to false. It is not recommended to use this in conjunction with `orthogonal` or `diagonal` constrain, as the line tends to take on a bit of a hand-drawn appearance. It's not without charm but it's also not for everyone. |\n| smoothing? | number | The amount of smoothing to apply. The default is 0.15. Values that deviate too much from the default will make your lines look weird. |\n| stub? | number | Stub defines a number of pixels that the connector travels away from its element before the connector's actual path begins. |\n\n***\n\n## Orthogonal[](#orthogonal)\n\nDraws a connection that consists of a series of vertical or horizontal segments - the classic flowchart look. Internally this connector is an alias for a `Straight` connector with `constrain:\"orthogonal\"`.\n\n```javascript\n\n{\n \"connector\": \"Orthogonal\"\n}\n\n```\n\n**********\n\n### Stubs[](#stubs-2)\n\nYou can set a `stub` on the connector.\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Orthogonal\",\n \"options\": {\n \"stub\": 25\n }\n }\n}\n\n```\n\n**********\n\n### Gap[](#gap-2)\n\nYou can set a `gap` on the connector to leave some space between the anchor point and the connector line:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Orthogonal\",\n \"options\": {\n \"gap\": 10\n }\n }\n}\n\n```\n\n**********\n\n### Rounded corners[](#rounded-corners-1)\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Orthogonal\",\n \"options\": {\n \"cornerRadius\": 5\n }\n }\n}\n\n```\n\n**********\n\n### Slightly wonky[](#slightly-wonky)\n\nWe stumbled across this effect in error while developing the orthogonal connector and we thought it had a certain charm, so we put it on a flag - it gives your connectors a slightly hand-drawn feel. You need to set a `cornerRadius` when you set this flag or you won't see any effect. Here we've used a corner radius of 5 pixels. Feel free to experiment, but in our experience numbers much larger than that tend to reduce the charm.\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Orthogonal\",\n \"options\": {\n \"slightlyWonky\": true,\n \"cornerRadius\": 5\n }\n }\n}\n\n```\n\n**********\n\n### Options[](#options-2)\n\nOrthogonalConnectorOptions\n\nOptions for an orthogonal connector.\n\n| Name | Type | Description |\n| ------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------- |\n| alwaysRespectStubs? | boolean | Defaults to true, meaning always draw a stub of the desired length, even when the source and target elements are very close together. |\n| cornerRadius? | number | Optional curvature of the corners in the connector. Defaults to 0. |\n| cssClass? | string | Optional class to set on the element used to render the connector. |\n| gap? | number | Defines a number of pixels between the end of the connector and its anchor point. Defaults to zero. |\n| hoverClass? | string | Optional class to set on the element used to render the connector when the mouse is hovering over the connector. |\n| loopbackRadius? | number | For a loopback connection, the size of the loop. |\n| midpoint? | number | The point to use as the halfway point between the source and target. Defaults to 0.5. |\n| slightlyWonky? | boolean | If true, and a cornerRadius is set, the lines are drawn in such a way that they look slightly hand drawn. |\n| stub? | number | Stub defines a number of pixels that the connector travels away from its element before the connector's actual path begins. |\n\n***\n\n## QuadraticBezier[](#quadraticbezier)\n\nDraws slightly curved lines, similar to the connectors you may have seen in software like GraphViz.\n\n```javascript\n\n{\n \"connector\": \"QuadraticBezier\"\n}\n\n```\n\n**********\n\n### Curviness[](#curviness)\n\nYou can set the `curviness` of the connector to adjust how pronounced the curve is, by changing the position of the control with respect to the midpoint of the two anchors. The default value is 10. There is no limit to what you can set this value to be, although large values do tend to be less pleasing. You can also set this to be a negative number, which will result in the connector curving in the opposite way to the default.\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"QuadraticBezier\",\n \"options\": {\n \"curviness\": 30\n }\n }\n}\n\n```\n\n**********\n\n### Stubs[](#stubs-3)\n\nYou can set a `stub` on the connector:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"QuadraticBezier\",\n \"options\": {\n \"stub\": 25\n }\n }\n}\n\n```\n\n**********\n\n### Gap[](#gap-3)\n\nYou can set a `gap` on the connector to leave some space between the anchor point and the connector line:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"QuadraticBezier\",\n \"options\": {\n \"gap\": 10\n }\n }\n}\n\n```\n\n**********\n\n### Options[](#options-3)\n\nQuadraticBezierConnectorOptions\n\nOptions for a QuadraticBezierConnector\n\n| Name | Type | Description |\n| ----------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| cssClass? | string | Optional class to set on the element used to render the connector. |\n| curviness? | number | A measure of how \"curvy\" the bezier is. In terms of maths what this translates to is how far from the midpoint of the curve the control points is positioned. |\n| gap? | number | Defines a number of pixels between the end of the connector and its anchor point. Defaults to zero. |\n| hoverClass? | string | Optional class to set on the element used to render the connector when the mouse is hovering over the connector. |\n| loopbackDistance? | number | When the connector's source and target is the same vertex, this is a measure of how far the control point will<br />be placed from the element. Defaults to 62 pixels |\n| stub? | number | Stub defines a number of pixels that the connector travels away from its element before the connector's actual path begins. |","url":"https://visuallyjs.com/react/docs/apps/edges/connectors","lib":"react","topic":"apps"},"docs/apps/edges/dragging-edges.md":{"title":"Dragging Edges","body":"# Dragging edges\n\nYou can setup your app for edge dragging by specifying some part of each vertex's DOM element to act as a connection source and/or target, via a set of `data-vjs-` attributes. VisuallyJs offers very fine-grained control over this setup, and assigns a [variety of CSS classes](#css-classes) during the edge drag lifecycle, to assist you in providing the best experience for your users.\n\n## Configuring Connectivity[](#configuring-connectivity)\n\n### Source and target attributes[](#source-and-target-attributes)\n\nYou can specify parts of your UI that should act as connection sources and/or targets using a set of `data-vjs-` attributes inside your vertex components/template:\n\n```html\n<div data-vjs-source=\"true\" data-vjs-target=\"true\"></div>\n\n```\n\nThis is the most basic setup: a div element that is declared to be both a source and target of connections established by dragging with the mouse. Note, though, that the surface widget will automatically exclude any elements with a `data-vjs-source` attribute from being able to instigate dragging, since once an element can act as a connection source it is not possible to also support element dragging: the user's intent would be ambiguous.\n\nIn this canvas, you can drag edges from each node to each other node - but note the nodes themselves are not draggable, because the entire node is declared as a connection source:\n\n**********\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const viewOptions = {\n nodes: {\n default: {\n jsx: (ctx) => <div data-vjs-source='true' data-vjs-target='true'/>\n }\n }\n}\n return <SurfaceComponent viewOptions={viewOptions}/>\n}\n\n```\n\nSo, a more plausible real world scenario would be some element in which only part of it could act as a connection source:\n\n```jsx\n<div data-vjs-target=\"true\">\n <h1>Some Vertex</h1>\n <div data-vjs-source=\"true\" className=\"dragFromHere\"></div>\n</div>\n\n```\n\nIn this canvas the red circles are our `data-vjs-source` elements - you can drag edges from them, and you can drag each node around. But you cannot drag the nodes around by their red circles:\n\n**********\n\nNote that we still put the `data-vjs-target` attribute on the root element since there is no ambiguity - when the element is behaving as a connection target it is not going to be the element that is currently being dragged.\n\n### Mapping to port types[](#mapping-to-port-types)\n\nIn the example above there is no specific piece of information provided to VisuallyJs to indicate that it should use anything other than the defaults for edges that are dragged. If you want finer-grained control over edge appearance you can use the `data-vjs-port-type` attribute on elements in your templates.\n\nConsider an app in which our vertices are represented with data objects like this:\n\n```javascript\n{ \n id:\"1\", \n left:50, \n top:50, \n scope:\"cadetblue\"\n}\n\n```\n\nIn this example, we declare a few different `port` types in our view options, each of which contains declarations for the appearance of connectors attached to that type. For example, a connection from a `cadetblue` port will use a `QuadraticBezier` connector, whereas `darkseagreen` and `lightcoral` use `Orthogonal`, and the `lightcoral` type also has an arrow overlay declared.\n\nIn the template we specify a port type to use for each element source via the `data-vjs-port-type` attribute: the value, in this example, is extracted from the `scope` in each node's data.\n\nTry dragging an edge from each of these nodes and you'll see the port type mapping action:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { StateMachineConnector, OrthogonalConnector, ArrowOverlay } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const viewOptions = {\n nodes: {\n $[DEFAULT]: (ctx) => <div data-vjs-port-type={ctx.data.scope}\n data-vjs-source={true}\n data-vjs-target={true}>{ctx.data.id}</div>\n },\n ports: {\n cadetblue: {\n connector: CONNECTOR_TYPE_QUADRATIC_BEZIER\n },\n darkseagreen: {\n connector: OrthogonalConnector.type\n },\n lightcoral: {\n connector: OrthogonalConnector.type,\n connectorOverlays: [\n {\n type: ArrowOverlay.type,\n options: {\n location: 1,\n width: 10,\n length: 6\n }\n }\n ]\n }\n }\n}\n return <SurfaceComponent viewOptions={viewOptions}/>\n}\n\n```\n\n**********\n\n### Mapping ports to elements[](#mapping-ports-to-elements)\n\nPorts on a vertex have an ID, which must be unique across the ports on that vertex, and which can be addressed. We use ports in the data model of several of our applications - for instance, in the Schema Builder starter app, we have a `table` node type, which has a set of columns. Each column in a table is mapped to a specific port id. This allows us to define edges between columns on two tables, for instance we may have an edge from `book.book_author_id` to `author.author_id`; here `book` and `author` are table IDs, and `book_author_id` and `author_id` are port IDs.\n\nVisuallyJs offers two attributes to assist in mapping ports from your model into your UI.\n\n#### Physical ports[](#physical-ports)\n\nYou can map port IDs to DOM elements - what we refer to as **physical** ports - via the `data-vjs-port` attribute.\n\nHere, we have two nodes that each contain a list of columns, and each column has an `id`, for instance:\n\n```javascript\n{ \n id:\"1\", \n left:50, \n top:50, \n columns:[\n {id:\"one\", scope:\"cadetblue\"}, \n {id:\"two\", scope:\"darkseagreen\"}, \n {id:\"three\", scope:\"cadetblue\" }\n ] \n}\n\n```\n\nWe render each node this this template:\n\n```jsx\n<div style={{display:\"flex\",flexDirection:\"column\"}}>\n {\n ctx.obj.data.columns.map(c => <div data-vjs-scope={c.scope}\n style={{backgroundColor:c.scope}} \n data-vjs-source={true} \n data-vjs-target={true} \n data-vjs-port={c.id}>{c.id}</div>)\n }\n</div>\n\n```\n\nEach of our column elements declares `data-vjs-source` and `data-vjs-target` to be true, meaning the element is both a source and target for edges dragged with the mouse. But the key piece is the `data-vjs-port` attribute: it indicates to VisuallyJs that that element is the *physical* representation of the given port on that vertex. Any edges connected to the port with that ID on the vertex will be connected to that DOM element.\n\nIn the dataset for the canvas below we have two edges:\n\n```javascript\n[\n { \"source\":\"1.three\", \"target\":\"2.two\" },\n { \"source\":\"1.two\", \"target\":\"2.five\" }\n]\n\n```\n\nThese edges are from a port on some vertex to a port on some other vertex, and it is the `data-vjs-port` attribute in our template that helps VisuallyJs figure out which DOM elements to connect.\n\n**********\n\nWe call this a **physical** port mapping: for some port ID, there is a specific DOM element mapped to it.\n\n#### Logical ports[](#logical-ports)\n\nWhat we call **logical** ports are slightly different - with this setup, there is no specific DOM element mapped to a given port, and edges connected to a logical port are shown in the UI as being connected to the port's vertex.\n\ncaution\n\nIf you wish to use logical ports, you need to tell VisuallyJs in the render options. VisuallyJs assumes, by default, that you're not using logical ports.\n\nHere, we have two nodes that each contain a list of columns, and each column has an `id`, for instance:\n\n```javascript\n{ \n id:\"1\", \n left:50, \n top:50, \n columns:[\n {id:\"one\", scope:\"cadetblue\"}, \n {id:\"two\", scope:\"darkseagreen\"}, \n {id:\"three\", scope:\"cadetblue\" }\n ] \n}\n\n```\n\nWe render each node this way:\n\n```jsx\n\n<div style={{display:\"flex\",flexDirection:\"column\"}}>\n {\n ctx.obj.data.columns.map(c => <div data-vjs-scope={c.scope}\n style={{backgroundColor:c.scope}} \n data-vjs-source={true} \n data-vjs-target={true} \n data-vjs-port-id={c.id}>{c.id}</div>)\n }\n</div>\n\n```\n\nIn this example the key piece is the `data-vjs-port-id` attribute: it indicates to VisuallyJs that that element is the *logical* representation of the given port on that vertex, meaning that any edges dragged from that element will be assigned a source port ID corresponding to the `data-vjs-port-id` attribute's value, but the actual DOM element used for the edge will be the vertex's DOM element.\n\nIn the dataset for the canvas below we have two edges:\n\n```javascript\n[\n { \"source\":\"1.three\", \"target\":\"2.two\" },\n { \"source\":\"1.two\", \"target\":\"2.five\" }\n]\n\n```\n\nThese edges are from a port on some vertex to a port on some other vertex, and it is the `data-vjs-port-id` attribute in our template that helps VisuallyJs figure out which DOM elements to connect.\n\n**********\n\nWe call this a **logical** port mapping: for some port ID, there is no specific DOM element mapped to it; VisuallyJs uses the DOM element for the port's vertex.\n\n***\n\n### Available attributes[](#available-attributes)\n\nThis is the list of supported connectivity attributes:\n\n| Attribute | Description |\n| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| `data-vjs-allow-loopback` | Indicates the it should be possible to drag loopback connections from this element to itself. |\n| `data-vjs-edge-type` | Optional attribute used to tell VisuallyJs what `type` to use from some element that has `data-vjs-source=\"true\"` set. |\n| `data-vjs-magnet` | Indicates the element acts as a magnet, when edge snapping is turned on. |\n| `data-vjs-port` | This attribute indicates that the given element is the specific DOM element to which connections for the given port should be attached. It is distinct from `data-vjs-port-id` in that this attribute is a \"physical\" presence of a port. Connections to/from the associated port are attached to this DOM element, and not to the element representing the vertex to which the port belongs. |\n| `data-vjs-port-id` | This attribute indicates the ID of the logical port that the element represents. A logical port is one which exists in the data model, but connections to/from the port in the UI are shown as being attached to the vertex to which the port belongs. Don't confuse this with the `data-vjs-port` attribute. When you drag a connection to/from some DOM element with this attribute set, you are instructing VisuallyJs to associate the source/target of the new edge with a port with the specified ID, but that the edge should be connected visually to the DOM element representing the vertex. |\n| `data-vjs-port-type` | Optional attribute used to tell VisuallyJs the type of the port represented by the given element. Maps to a port type defined in your view. |\n| `data-vjs-source` | Indicates the given DOM element acts as a source for edges dragged with the mouse/touch events. Any element with this attribute set will automatically be excluded from instigating a drag of the vertex on which the element resides |\n| `data-vjs-target` | Indicates the given DOM element acts as a target for edges dragged with the mouse/touch events. Elements with this attribute set are not excluded from instigating a drag of the vertex on which the element resides. |\n| `data-vjs-target-port` | Indicates the ID of the physical port represented by this element when the element is acting as the target of some edge. See discussion at `data-vjs-port` to read about how this differs from `data-vjs-target-port-id` |\n\n***\n\n## Visual cues[](#visual-cues)\n\n### While dragging[](#while-dragging)\n\nThere are two main CSS classes you can use to provide visual cues to your users about the state of an edge drag:\n\n* `vjs-drag-active` When an edge is being dragged, this class is assigned to all elements onto which the edge could be dropped\n\n* `vjs-drag-hover` When an edge is being dragged and the mouse is hovering over a possible target, this class is assigned to that element\n\nIn the canvas below we have these style rules:\n\n```css\n.vjs-node {\n outline:1px solid;\n}\n \n.vjs-drag-active {\n outline:2px solid forestgreen;\n}\n\n.vjs-drag-hover {\n outline:4px solid orangered;\n}\n\n```\n\nTry dragging an edge - you'll see the `.vjs-drag-active` class applied to each of the nodes initially. When you drag the edge over one of the nodes you'll see the `.vjs-drag-hover` class applied:\n\n**********\n\n### Connected elements[](#connected-elements)\n\nWhen some element has one or more edges attached to it, VisuallyJs adds the CSS class `vjs-connected` to the element in the DOM. In the canvas below we have this style rule declared:\n\n```css\n.vjs-connected {\n background-color: #0a58ca;\n color:white;\n}\n\n```\n\nNodes 1 and 2 are connected in our initial dataset and are, accordingly, painted with a blue background, via the CSS rule. If you drag a new edge (from one of the red circles) to node 3 you'll see it update to have a blue background, as the `vjs-connected` class will be assigned when the edge is established.\n\n**********\n\n***\n\n## Snapping to drag targets[](#snapping-to-drag-targets)\n\nYou can instruct VisuallyJs to snap to drag targets when dragging edges. The simplest setup is:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edgeSnap: {\n enabled: true\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nWhich you can see in operation here - try dragging an edge from one of the red circles. As it gets within proximity of one of the other nodes, the edge is snapped:\n\n**********\n\nThe canvas above configures each element as a target, and the default behaviour is to snap to any target.\n\n### Limiting snap targets[](#limiting-snap-targets)\n\nIf you wish to only snap to certain elements, you can use the `requireMagnets` option:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edgeSnap: {\n enabled: true,\n requireMagnets: true\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nHere, we have instructed VisuallyJs to only snap to elements that have declared themselves to be \"magnets\" - which you configure via the `data-vjs-magnet` attribute in your HTML:\n\n```html\n<div data-vjs-target=\"true\" data-vjs-magnet=\"true\">\n ...\n</div>\n\n```\n\nIn this canvas the node with the red outline is declared as a magnet, because it has `data-vjs-magnet=\"true\"` declared. Try dragging an edge from one of the other nodes. It won't snap to any node except the one with the red border:\n\n**********\n\n### Child elements as target[](#child-elements-as-target)\n\nSnapping works when something other than the entire element is the target. In this next example we use this markup for our nodes:\n\n```html\n<div>\n <div data-vjs-target=\"true\" class=\"dragToHere\"/>\n <div data-vjs-source=\"true\" class=\"dragFromHere\"/>\n</div>\n\n```\n\nOur drag targets are the red circles in the top left corner - and it is to these that edges will snap. But the snapping is activated in proximity to the vertex:\n\n**********\n\nUsing nested elements as targets with snapping turned on also, of course, works with `requireMagnets:true` set.\n\n### Adjusting sensitivity[](#adjusting-sensitivity)\n\nBy default the snapping mechanism will kick in at a distance of 50 pixels from the target. You can change this:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edgeSnap: {\n enabled: true,\n threshold: 20\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n***\n\n## Constraining connectivity[](#constraining-connectivity)\n\nThere are a couple of different approaches to control connectivity.\n\n### Edge scope[](#edge-scope)\n\nA high level approach to controlling connectivity is offered by the `data-vjs-scope` attribute. Edges dragged from some source element with a `data-vjs-scope` attribute can only be attached to target elements that have a matching `data-vjs-scope`. We use this approach in our Schema builder starter app.\n\nHere, we have two nodes that each contain a list of columns, and each column has a `scope` in its backing data - this is the data object for the node on the left:\n\n```javascript\n{ \n id:\"1\", \n left:50, \n top:50, \n columns:[\n {id:\"one\", scope:\"cadetblue\"}, \n {id:\"two\", scope:\"darkseagreen\"}, \n {id:\"three\", scope:\"cadetblue\" }\n ] \n}\n\n```\n\nWe're using HTML colours for our `scope` so that we can style the elements easily, but scope is just an arbitrary string. We render each node this this template:\n\n```jsx\n<div style={{display:\"flex\",flexDirection:\"column\"}}>\n {\n obj.data.columns.map(c => <div data-vjs-scope={c.scope} \n style={{backgroundColor:c.scope}} \n data-vjs-source={true} \n data-vjs-target={true} \n data-vjs-port={c.id}>{c.id}</div>)\n }\n</div>\n\n```\n\nEach of our column elements declares `data-vjs-source` and `data-vjs-target` to be true, meaning the element is both a source and target for edges dragged with the mouse. But the key piece is the `data-vjs-scope` attribute: try dragging an edge from a green to blue or vice verse below - you can't, due to a scope mismatch. But you can drag between elements having the same colour.\n\n**********\n\n***\n\n### Interceptors[](#interceptors)\n\nIf edge scope is too high level for your needs, you can use `interceptors`, which provide a fine-grained means of controlling connectivity, at the model level.\n\ninfo\n\nThe interceptors discussed here are passed as arguments to the underlying model - they operate at the model level, ie. both on programmatic calls to connect vertices and when the user is connecting vertices via the mouse/touch events.\n\nConnectivity can be controlled at runtime by **interceptors** - callbacks that can be used to cancel some proposed activity, and that are bound on an instance of the VisuallyJs model by supplying a specific function in the model constructor options.\n\n#### beforeConnect[](#beforeconnect)\n\nA function to run before an edge with the given data can be established between the given source and target. Returning false from this method aborts the connection. Note that this method fires regardless of the source of the new edge, meaning it will be called when loading data programmatically.\n\n##### Method signature[](#method-signature)\n\n`beforeConnect(source: Vertex, target: Vertex): any`\n\n##### Parameters[](#parameters)\n\n* *source* The source vertex for the new edge\n* *target* The target vertex for the new edge\n\n##### Return value[](#return-value)\n\n* `false` - aborts the connection\n* all other values are ignored and will allow the edge to be established\n\n##### Example[](#example)\n\nHere, we reject connections from any vertex to itself.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n beforeConnect: (source: Vertex, target: Vertex) => {\n return (source !== target)\n }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n#### beforeMoveConnection[](#beforemoveconnection)\n\nA function to run before an edge of the given type is relocated from its current source or target to a new source or target. Returning false from this method will abort the move.\n\n##### Method signature[](#method-signature-1)\n\n`beforeMoveConnection(source: Vertex, target: Vertex, edge: Edge): any`\n\n##### Parameters[](#parameters-1)\n\n* *source* Candidate source. May be the edge's current source, or may be a new source.\n* *target* Candidate target. May be the edge's current target, or may be a new target.\n* *edge* The edge that is being moved.\n\nThe parameters `source` and `target` reflect the source and target of the edge if the move were to be accepted. So if, for example, your user drags a connection by its target and drops it elsewhere, `target` will be the drop target, not the edge's current target, but `source` will be the edge's current source. You can access the current source/target via the `source` and `target` properties of `edge`.\n\n##### Return value[](#return-value-1)\n\n* `false` - aborts the move\n* all other values are ignored and will allow the move to occur\n\n##### Example[](#example-1)\n\nHere, we reject moving any edge that has `fixed:true` in it backing data:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n beforeMoveConnection: (source: Vertex, target: Vertex, edge:Edge) => {\n return (edge.data.fixed !== true)\n }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n#### beforeStartConnect[](#beforestartconnect)\n\nA function to run before an edge of the given type is dragged from the given source (ie. before the mouse starts moving). This interceptor is slightly different to the others in that it's not just a yes/no question: as with the other interceptors, returning false from this method will reject the action, that is in this case it will not allow a connection drag to begin. But you can also return an object from this method, and when you do that, the connection start is allowed, and the object you returned becomes the payload for the new edge.\n\n##### Method signature[](#method-signature-2)\n\n`beforeStartConnect(source: Vertex, type: string): any`\n\n##### Parameters[](#parameters-2)\n\n* *source* The vertex that is the source for the new edge\n* *type* The computed type for this new edge.\n\n##### Return value[](#return-value-2)\n\n* `false` - aborts the connection\n* `Object` - An object returned from this method will be used as the initial payload for the new edge\n* all other values are ignored and will allow the connection start to continue\n\n##### Example - reject a connection start[](#example---reject-a-connection-start)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n beforeStartConnect: (source: Vertex, type:string) => {\n return type !== 'not-connectable'\n }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n##### Example - provide an initial payload[](#example---provide-an-initial-payload)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n beforeStartConnect: (source: Vertex, type:string) => {\n return {\n type,\n message:`initial payload for vertex ${source.id}`\n }\n }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n#### beforeDetach[](#beforedetach)\n\nA function to run before the given edge is detached from the given source vertex. If this method returns false, the detach will be aborted.\n\n##### Method signature[](#method-signature-3)\n\n`beforeDetach(source: Vertex, target: Vertex, edge: Edge, isDiscard?: boolean): any`\n\n##### Parameters[](#parameters-3)\n\n* *source* The source vertex for the edge that is to be detached.\n* *target* The candidate target for the edge - may be null, if the edge is being discarded\n* *edge* The edge that is being detached.\n* *isDiscard* True if the edge is not now connected to a target.\n\n##### Return value[](#return-value-3)\n\n* `false` Returning false will abort the edge detach\n* all other values are ignored and will allow the detach to occur\n\n##### Example[](#example-2)\n\nHere, we reject the detach if the target is null, ie. the user is trying to discard the edge, not relocate it.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n beforeDetach: (source: Vertex, target: Vertex, edge: Edge, isDiscard?: boolean) => {\n return target != null\n }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n#### beforeStartDetach[](#beforestartdetach)\n\n##### Method signature[](#method-signature-4)\n\n`beforeStartDetach(source: Vertex, edge: Edge): any`\n\nA function to run before the given edge is detached from the given source vertex. If this method returns false, the detach will be aborted. The difference between this and `beforeDetach` is that this method is fired as soon as a user tries to detach an edge from an anchor in the UI, whereas `beforeDetach` allows a user to detach the edge in the UI.\n\n##### Parameters[](#parameters-4)\n\n* *source* The source vertex for the edge that the user has started to detach\n* *edge* The edge that the user has started to detach\n\n##### Return value[](#return-value-4)\n\n* `false` Returning false will abort the edge detach\n* all other values are ignored and will allow the user to begin the detach\n\n##### Example[](#example-3)\n\nHere, we reject the detach if the source vertex has `doNotDetachEdges:true` in its backing data.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n beforeDetach: (source: Vertex, edge: Edge) => {\n return source.data.doNotDetachEdges !== true\n }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n##### Multiple interceptors[](#multiple-interceptors)\n\nYou can provide multiple interceptors - in this example we provide a `beforeStartConnect` and `beforeDetach` interceptor to the model. The `beforeStartConnect` interceptor prevents the user from dragging connections from any vertex whose ID is not an even number. The `beforeDetach` interceptor reattaches detached connections whose source ID is not an event number\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n beforeStartConnect: (source, type) => {\n // only allow connections from nodes whose \n // ID is an even number\n return parseInt(source.id, 10) % 2 === 0\n },\n beforeDetach: (source, target, edge, isDiscard) => {\n // only allow connections to be detached whose \n // source ID is an even number\n return parseInt(edge.source.id, 10) % 2 === 0\n }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n**********\n\n## Active filtering[](#active-filtering)\n\nYou can use a `beforeConnect` interceptor to implement a scheme where unavailable targets are disabled when the user starts to drag a new connection.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n beforeConnect: (source:Vertex, target:Vertex) => {\n return source.data.scope === target.data.scope\n }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n**********\n\nDisabled vertices are assigned the DOM attribute `data-vjs-enabled=\"false\"`, which you can target via css. For example, in this page, we have this rule:\n\n```css\n[data-vjs-enabled='false'] {\n filter: grayscale(0.4);\n opacity: 0.5;\n}\n\n```\n\n***\n\n## CSS Classes[](#css-classes)\n\nThere are a number of CSS classes assigned to various parts of the UI during an edge drag. These can be used to easily add visual cues for your users, and also to manage z-index for the best user experience.\n\n| Class | Description |\n| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `vjs-connector-source-drag` | The class assigned to the SVG element with which a user can drag to reposition the source of some edge. |\n| `vjs-connector-target-drag` | The class assigned to the SVG element with which a user can drag to reposition the target of some edge. |\n| `vjs-connector-transient-drag` | Assigned to the temporary DOM element used when relocating an existing edge via the mouse/touch events. |\n| `vjs-edge-relocating` | Assigned by the Surface to the DOM element representing an edge that is being dragged to relocate its source or target. This class is only added when the edge input handler is in drag mode. It is assigned to the connector element once the mouse starts to move, and removed on mouseup. |\n| `vjs-edge-will-relocate` | Assigned by the Surface to the DOM element representing an edge that is about to be relocated. When the edge input mode is dragging, this class is assigned on mousedown on one of the drag handles, before the mouse moves, and removed when the mouse begins to move (or on mouseup if the user does not move the mouse). When the edge input mode is tap, this class is assigned when the user has tapped on one of the relocate handles, and is removed either when the user clicks on whitespace, cancelling the relocation, or clicks on an active target and effects the relocation. |\n| `vjs-surface-edge-dragging` | Assigned by the Surface to its root element when an edge is being dragged. This is not assigned to the edge element itself. |\n\n***\n\n## Advanced Markup Configuration[](#advanced-markup-configuration)\n\nAbove, we listed the most commonly used attributes to configure connectivity, but there are several more that can be used in more advanced configurations, specifically when you want to use a different physical or logical port mapping depending on whether the connection is to an edge or target.\n\n| Attribute | Description |\n| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| `data-vjs-source-port` | Indicates the ID of the physical port that the element represents when it is acting as an edge source. In some situations you might want to use the same element as a source and target, but have the data model use different ports ids. See discussion for `data-vjs-port` to read about how this differs from `data-vjs-source-port-id` |\n| `data-vjs-source-port-id` | Indicates the ID of the logical port that the element represents when it is acting as an edge source. In some situations you might want to use the same element as a source and target, but have the data model use different logical ports. |\n| `data-vjs-source-port-type` | Indicates the type of the port represented by this element when the element is acting as the source of some edge. Maps to a port type defined in your view. In some situations you might want to use the same element as a source and target, but have the data model use different ports types. |\n| `data-vjs-target-port-id` | Indicates the ID of the logical port that the element represents when it is acting as an edge target. |\n| `data-vjs-target-port-type` | Indicates the type of the port represented by this element when the element is acting as the target of some edge. Maps to a port type defined in your view. |","url":"https://visuallyjs.com/react/docs/apps/edges/dragging-edges","lib":"react","topic":"apps"},"docs/apps/edges/edge-labels.md":{"title":"Edge Labels","body":"# Edge Labels\n\nThere are several properties on an edge mapping that you can use to configure labels for your edges.\n\n## Static labels[](#static-labels)\n\nHere, we hardcode a label for every edge by setting it as a string:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const viewOptions = {\n edges: {\n default: {\n label: \"Edge\"\n }\n }\n}\n return <SurfaceComponent viewOptions={viewOptions}/>\n}\n\n```\n\n**********\n\n<!-- -->\n\n## Dynamic labels[](#dynamic-labels)\n\nYou can extract the value of each edge's `label` from the edge's backing data:\n\n<!-- -->\n\n## Custom CSS class[](#custom-css-class)\n\nYou can provide your own class/classes to set on the element VisuallyJs uses for the edge label:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const viewOptions = {\n edges: {\n default: {\n label: \"{{label}}\",\n labelClass: \"myLabel\"\n }\n }\n}\n return <SurfaceComponent viewOptions={viewOptions}/>\n}\n\n```\n\n<!-- -->\n\nProvide a space-separated list if you wish to provide more than one class.\n\n## Label location[](#label-location)\n\nBy default, an edge label will be assigned a location of `0.5` - meaning it will be halfway along the edge path. You can change this by providing a `labelLocation` in your edge data:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const viewOptions = {\n edges: {\n default: {\n label: \"{{label}}\",\n labelClass: \"myLabel\",\n labelLocation: 0.25\n }\n }\n}\n return <SurfaceComponent viewOptions={viewOptions}/>\n}\n\n```\n\nYou can also control this via a `labelLocation` value in your edge's backing data. For example, this edge:\n\n```javascript\n{\n source:\"someNode\",\n target:\"someOtherNode\",\n data:{\n labelLocation:0.25\n }\n}\n\n```\n\nwould instruct VisuallyJs to put the label at 0.25, and you would not need to set `labelLocation` in the edge mapping in your view.","url":"https://visuallyjs.com/react/docs/apps/edges/edge-labels","lib":"react","topic":"apps"},"docs/apps/edges/markers.md":{"title":"Markers","body":"# Overlays & Markers\n\nMarkers are overlays that are being used in the specific context of marking the source or target of some edge. `Label` and `Custom` overlays are not supported for markers, but all of the simple shape overlays are.\n\nIn this example we show a `Dot` marker as the source and a `PlainArrow` as the target.\n\n```javascript\nedges:{\n sourceMarker:\"Dot\",\n targetMarker:\"PlainArrow\"\n}\n\n```\n\n**********\n\ninfo\n\n## Location[](#location)\n\nAlthough markers are just overlays, you do not supply a location when specifying a marker - or rather, you do, but implicitly, by the fact that you have identified a marker as a `sourceMarker` (location:0) or a `targetMarker` (location:1). VisuallyJs will automatically set this location and also set `direction:-1` for a target marker.\n\n## Differences to overlays[](#differences-to-overlays)\n\nMarkers are specified with the same syntax as overlays, so what is the difference? There are two:\n\n### Syntax[](#syntax)\n\nThe `sourceMarker` / `targetMarker` syntax is a useful shortcut to having to declare a set of `overlays` and configuring the properties required to set an overlay at the source/target of an edge. It is the difference, for instance, of typing this:\n\n```javascript\nmarkers:{\n sourceMarker:\"Dot\",\n targetMarker:\"PlainArrow\"\n}\n\n```\n\nversus typing this:\n\n```javascript\noverlays:[\n { type:\"Dot\", options:{location:0}},\n { type:\"PlainArrow\", options:{location:1}}\n]\n\n```\n\n### Edge overlap[](#edge-overlap)\n\nWhen an overlay is used as a marker, the path of the edge is adjusted so that it stops at the edge of the marker. An exaggerated example is given below - in this canvas, the edges have a stroke width of 8 pixels, and you can see in the top edge how the edge path intersects the overlays whereas in the bottom edge it does not.\n\n**********","url":"https://visuallyjs.com/react/docs/apps/edges/markers","lib":"react","topic":"apps"},"docs/apps/edges/overlays.md":{"title":"Overlays","body":"# Overlays\n\nOverlays are adornments to connections. There are two types - simple overlays, which are such things as arrows at the end of a line, or a label, etc, and component overlays, in which you can provide a component to use for the overlay.\n\n<!-- -->\n\nIn this canvas we have an edge with 6 [simple overlays](#simple-overlays) - a [Rectangle](#rectangle), a [PlainArrow](#plainarrow), a [Label](#label), a [Diamond](#diamond), a [Dot](#dot), and an [Arrow](#arrow):\n\n**********\n\ninfo\n\n## Location[](#location)\n\nA key concept with overlays is that of their **location**. It refers to some point along the path inscribed by the edge, and it can be specified in one of three ways:\n\n* as a decimal in the range \\[0..1], which indicates some proportional amount of travel along the path inscribed by the edge. The default value of 0.5 is in this form, and it means the default location of an overlay on an edge is a point halfway along the path.\n* as an integer greater than 1, which indicates some absolute number of pixels to travel along the edge from the start point\n* as an integer less than zero, which indicates some absolute number of pixels to travel backwards along the edge from the end point.\n\nThe default location for an overlay is halfway along the path traveled by the connector - `location` is `0.5`. If you specify `location:1`, then the overlay will be at the end of the path; `location:0` puts the overlay at the start.\n\n## Simple Overlays[](#simple-overlays)\n\nVisuallyJs ships with several types of simple overlays:\n\n* **Arrow** - a configurable arrow that is painted at some point along the connector. You can control the length and width of the Arrow, the 'foldback' point - a point the tail points fold back into, and the direction (allowed values are 1 and -1; 1 is the default and means point in the direction of the connection)\n* **Label** - a configurable label that is painted at some point along the connector, either as an SVG element or an HTML element\n* **PlainArrow** - an Arrow shaped as a triangle, with no foldback.\n* **Diamond** - A diamond shaped overlay.\n* **Dot** A circle overlay, with configurable radius\n* **Rectangle** A rectangle overlay, with configurable width and height\n* **Custom** - allows you to create the overlay yourself - your overlay may be any DOM element you like.\n\n`PlainArrow` and `Diamond` are actually just configured instances of the generic `Arrow` overlay (see examples).\n\n### Arrow[](#arrow)\n\nAn arrow with a configurable `foldback` point.\n\nArrowOverlayOptions\n\nOptions for an Arrow overlay.\n\n| Name | Type | Description |\n| ----------- | ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |\n| attributes? | Record\\<string,string> | Optional custom attributes to write to the overlay's element. |\n| cssClass? | string | Optional CSS class(es) to add to the overlay's element. |\n| direction? | number | 1 to point forwards (the default), -1 to point backwards. Only taken into consideration in some overlay types. |\n| events? | Record<[OverlayEvents](),(value:any, event:any) => any> | Optional event handlers to attach to the overlay. |\n| foldback? | number | How far, as a decimal, along the line from head to baseline to fold back into. Defaults to 0.623. |\n| hollow? | boolean | Defaults to false. When true, the arrow is stroked but not filled. |\n| id? | string | Optional ID for the overlay. Can be used to retrieve the overlay from a connection. |\n| length? | number | Length from the head to the baseline. Defaults to 20. |\n| location? | number | Defaults to 0.5. See docs. |\n| paintStyle? | [PaintStyle]() | Optional paint style to use. |\n| visibility? | [OverlayVisibility]() | Whether the overlay is always visible, or only on hover. Defaults to OVERLAY\\_VISIBILITY\\_ALWAYS. |\n| width? | number | Width of the arrow's baseline. Defaults to 20. |\n\n#### Arrow direction[](#arrow-direction)\n\nA point to note is that `location:0` for arrow overlays will not reverse the direction in which the arrow is pointing. To have the arrow point backwards along the path you have to provide a value for `direction`:\n\n```javascript\noverlays:[ \n {\n type:\"Arrow\",\n options:{\n width:10,\n length:15,\n location:0,\n direction:-1\n }\n } \n]\n\n```\n\nThe `direction:-1` here instructs VisuallyJs to draw the arrow painting backwards. There are only two valid values for `direction` - `1` and `-1`. If you provide any other value - or no value - then VisuallyJs will use a value of 1, meaning the arrow points forwards.\n\n### PlainArrow[](#plainarrow)\n\nThis overlay is an extension of `Arrow` with the `foldback` parameter's value fixed to `1`. This results in an arrow with a flat back.\n\n### Diamond[](#diamond)\n\nThis overlay is an extension of `Arrow` with the `foldback` parameter's value fixed to `2`. This results in an arrow shaped like a diamond.\n\n### Dot[](#dot)\n\nThis is a circle, with configurable radius.\n\nDotOverlayOptions\n\nOptions for a Dot overlay\n\n| Name | Type | Description |\n| ----------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| align? | \"center\" \\| \"flush\" | When the overlay is at position 1 or 0 (or is being used a source/target marker), this determines how the dot intersects the vertex. A value of 'flush', which is the default, means a point on the circumference of the dot touches the vertex boundary. A value of 'center' means the dot's center is on the vertex boundary. |\n| attributes? | Record\\<string,string> | Optional custom attributes to write to the overlay's element. |\n| cssClass? | string | Optional CSS class(es) to add to the overlay's element. |\n| direction? | number | 1 to point forwards (the default), -1 to point backwards. Only taken into consideration in some overlay types. |\n| events? | Record<[OverlayEvents](),(value:any, event:any) => any> | Optional event handlers to attach to the overlay. |\n| hollow? | boolean | Defaults to false. When true, the arrow is stroked but not filled. |\n| id? | string | Optional ID for the overlay. Can be used to retrieve the overlay from a connection. |\n| location? | number | Defaults to 0.5. See docs. |\n| paintStyle? | [PaintStyle]() | Optional paint style to use. |\n| radius? | number | Radius of the dot. Defaults to 5. |\n| visibility? | [OverlayVisibility]() | Whether the overlay is always visible, or only on hover. Defaults to OVERLAY\\_VISIBILITY\\_ALWAYS. |\n\n### Rectangle[](#rectangle)\n\nThis is a rectangle, with configurable width and height.\n\nRectangleOverlayOptions\n\nOptions for a Rectangle overlay\n\n| Name | Type | Description |\n| ----------- | ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| align? | \"center\" \\| \"flush\" | When the overlay is at position 1 or 0 (or is being used a source/target marker), this determines how the rectangle intersects the vertex. A value of 'flush', which is the default, means a point on the boundary of the rectangle touches the vertex boundary. A value of 'center' means the rectangle's center is on the vertex boundary. |\n| attributes? | Record\\<string,string> | Optional custom attributes to write to the overlay's element. |\n| cssClass? | string | Optional CSS class(es) to add to the overlay's element. |\n| direction? | number | 1 to point forwards (the default), -1 to point backwards. Only taken into consideration in some overlay types. |\n| events? | Record<[OverlayEvents](),(value:any, event:any) => any> | Optional event handlers to attach to the overlay. |\n| height? | number | Height of the rectangle. Defaults to 10. |\n| hollow? | boolean | Defaults to false. When true, the arrow is stroked but not filled. |\n| id? | string | Optional ID for the overlay. Can be used to retrieve the overlay from a connection. |\n| location? | number | Defaults to 0.5. See docs. |\n| paintStyle? | [PaintStyle]() | Optional paint style to use. |\n| rotate? | boolean | Whether or not to rotate the rectangle so that it is always perpendicular to the connector path. Defaults to false. |\n| visibility? | [OverlayVisibility]() | Whether the overlay is always visible, or only on hover. Defaults to OVERLAY\\_VISIBILITY\\_ALWAYS. |\n| width? | number | Width of the rectangle. Defaults to 10. |\n\n### Label[](#label)\n\nLabelOverlayOptions\n\nOptions for a label overlay\n\n| Name | Type | Description |\n| ----------------------- | ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |\n| attributes? | Record\\<string,string> | Optional custom attributes to write to the overlay's element. |\n| cssClass? | string | Optional CSS class(es) to add to the overlay's element. |\n| direction? | number | 1 to point forwards (the default), -1 to point backwards. Only taken into consideration in some overlay types. |\n| events? | Record<[OverlayEvents](),(value:any, event:any) => any> | Optional event handlers to attach to the overlay. |\n| font? | [FontSpec]() | Optional spec for the font to use on this label. |\n| id? | string | Optional ID for the overlay. Can be used to retrieve the overlay from a connection. |\n| label | string \\| Function | String, or a function returning a string, for the label. |\n| labelLocationAttribute? | string | Optional name of the attribute that identifies this overlay's location on the path. Defaults to `location`. |\n| location? | number | Defaults to 0.5. See docs. |\n| useHTMLElement? | boolean | Whether or not to use an HTML element. Defaults to false (uses an SVG element) |\n| visibility? | [OverlayVisibility]() | Whether the overlay is always visible, or only on hover. Defaults to OVERLAY\\_VISIBILITY\\_ALWAYS. |\n\nThe `label` for a label overlay can be a string or a function, but in practice with VisuallyJs you'll generally be defining labels as strings, as the values presented to the renderer are extracted from the JSON backing data for each edge.\n\n#### SVG vs HTML elements[](#svg-vs-html-elements)\n\nBy default, regardless of whether or not the container is an SVG element, a label overlay will be rendered as an SVG element. This is the most memory efficient and also allows a label to be printed by an SVG exporter. You can instruct VisuallyJs to use an HTML element via the `useHTMLElement` option for the label.\n\n### Custom[](#custom)\n\nThe custom overlay allows you to create your own overlays, which VisuallyJs will position for you. You need to implement one method - `create(component)` - which is passed the component on which the overlay is located as an argument, and which returns either a DOM element or a valid selector from the underlying library:\n\n```javascript\n\n overlays:[\n {\n type:\"Custom\"\n options:{\n create:(component) => {\n const d = document.createElement(\"select\")\n d.innerHTML = \"<option value='foo'>foo</option><option value='bar'>bar</option>\"\n return d\n },\n location:0.7,\n id:\"customOverlay\"\n }\n }\n ]\n\n```\n\nHere we have created a select box with a couple of values, assigned to it the id of 'customOverlay' and placed it at location 0.7. Note that the 'id' we assigned is distinct from the element's id. You can use the id you provided to later retrieve this overlay using the `getOverlay(id)` method on a connection.\n\nnote\n\nA custom overlay is a plain HTML element - you may wish to consider using a component overlay instead.\n\n## Showing/hiding on hover[](#showinghiding-on-hover)\n\nIt is possible to mark some overlay as being only visible when the mouse is hovering over the edge to which it belongs:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { OVERLAY_VISIBILITY_HOVER } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n paintOutline: true,\n outlineWidth: 30\n }\n}\n\n const viewOptions = {\n edges: {\n default: {\n overlays: [\n {\n type: \"Label\",\n options: {\n label: \"Hello!\",\n visibility: OVERLAY_VISIBILITY_HOVER\n }\n }\n ]\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions} viewOptions={viewOptions}/>\n}\n\n```\n\n<!-- -->\n\nTry hovering the mouse over the edge path in this example:\n\n<!-- -->\n\n**********\n\ninfo\n\nIn this example we made it easy to hover over the edge by instructing VisuallyJs to paint a 30 pixel transparent connector outline, via the `outlineWidth:30` config.\n\n## React component overlays[](#react-component-overlays)\n\nVisuallyJs supports using React components as overlays.\n\n### Simple example[](#simple-example)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const viewOptions = {\n edges: {\n default: {\n overlays: [\n {\n jsx: (ctx) => <div onClick={() => alert('You clicked ' + ctx.data.label)}>\n I am {ctx.data.label}. Click me.\n </div>\n }\n ]\n }\n }\n}\n return <SurfaceComponent viewOptions={viewOptions}/>\n}\n\n```\n\n**********\n\n### Less Simple Example[](#less-simple-example)\n\nThe previous example demonstrates how the component overlay can display, reactively, the data object for the edge it represents. But we wanted to point out that the overlay has access not only to its edge, but also to the source and target vertices of the edge - again, reactively. So in this canvas below we show two nodes with an overlay on the edge that connects them. The overlay displays the background color of each node, and you can click the nodes to cycle their background color. When you do so, you'll see the overlay update itself too:\n\n**********\n\n#### Discussion[](#discussion)\n\nHow did we do this?\n\n##### Node data[](#node-data)\n\nFirst of all, we declared our nodes like this:\n\n```javascript\n{\n id:\"1\", \n left:50, \n top:50, \n bg:\"blue\" \n}\n\n```\n\n##### Helper functions[](#helper-functions)\n\nWe then wrote a quick helper function to get a random color, and another function which can invoke an update on the model:\n\n```javascript\nconst randomColor = () => `#${Array.from({length:3}, () => Math.floor(Math.random()*255).toString(16)).join(\"\")}`\n\nconst cycle = (ctx, node) => ctx.model.updateNode(node, {bg:randomColor()})\n\n```\n\nThe `cycle` method uses the `updateNode` method on the model to perform the update. `ctx` is passed in from either the node component or the overlay component, and is of type [JsxWrapperProps]().\n\n##### Node component[](#node-component)\n\nOur node component looks like this:\n\n```jsx\nconst NodeComponent = function({ctx}) {\n return <div style={{backgroundColor:ctx.data.bg}}\n onClick={() => cycle(ctx, ctx.obj)}>\n </div>\n}\n\n```\n\nIn this component, `ctx.obj` is the node being drawn. This component extracts `bg` from the node data and uses it for the background color, and binds a click listener, which calls `cycle`, which will result in the node's background colour being updated.\n\n##### Overlay component[](#overlay-component)\n\nOur overlay component looks like this:\n\n```jsx\nconst OverlayComponent = function({ctx}) {\n return <div className=\"advanced-demo-overlay\">\n \n <div style={{backgroundColor:ctx.obj.source.data.bg}} \n onClick={() => cycle(ctx, ctx.obj.source)}/>\n \n <div style={{backgroundColor:ctx.obj.target.data.bg}} \n onClick={() => cycle(ctx, ctx.obj.target)}/>\n \n </div>\n}\n\n```\n\nIn this component, `ctx.obj` is the edge the overlay represents. It has a `source` and `target` member which are the source and target nodes of the edge. This component extracts `bg` from the data of the source and target nodes and uses them for the background color of the two divs, and binds a click listener to each of those, which calls `cycle`, either with the source node or the target node.\n\n##### App component[](#app-component)\n\nOur app looks like this:\n\n```jsx\n<SurfaceComponent viewOptions={{\n nodes:{\n default:{\n jsx:(ctx) => <NodeComponent ctx={ctx}/>\n }\n }, \n edges:{\n default:{\n overlays:[\n {\n jsx:(ctx) => <OverlayComponent ctx={ctx}/>\n }\n ]\n }\n }\n}}/>\n\n```","url":"https://visuallyjs.com/react/docs/apps/edges/overlays","lib":"react","topic":"apps"},"docs/apps/edges/overview.md":{"title":"Overview","body":"# Edges\n\nEdges map relationships between the vertices in your UI. In the data model, an edge consists of a source vertex (node, group or port) or canvas location, a target vertex or canvas location, and some optional backing data, such as ID, type, label etc.\n\nIn the UI, an edge is represented by a few concepts that work in tandem:\n\n* **Anchor** The location of each end of an edge on a vertex is determined by its source and target [anchors](#anchors)\n* **Connector** The path inscribed by the edge is determined by its [connector type](/react/docs/apps/edges/connectors.md), and also by any [path edits made by the user](/react/docs/apps/edges/path-editing.md)\n* **Overlays** An edge may have zero or more [overlays](/react/docs/apps/edges/overlays.md), which are adornments that can be placed at any point along the path inscribed by the edge.\n* **Markers** A [marker](/react/docs/apps/edges/markers.md) is an overlay that is placed at the start or end of an edge (equivalent to location 0 or location 1). When a marker is located at the start or end of an edge, the path is automatically trimmed so that it terminates at the marker.\n\nEdges may also be detached from the source and/or target and terminate in whitespace, if you [configure this behaviour](/react/docs/apps/edges/unattached-edges.md).\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n sourceMarker: \"Dot\",\n targetMarker: \"PlainArrow\",\n connector: \"QuadraticBezier\",\n overlays: [\n {\n type: \"Label\",\n options: {\n label: \"{{label}}\"\n }\n }\n ]\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n<!-- -->\n\n## Anchors[](#anchors)\n\nThe location of each end of an edge is specified by an `Anchor`, of which there are several different types in VisuallyJs: you can choose to anchor an edge at some specific location and not let it move, or you can choose from a few different approaches for dynamic selection of the anchor location. Take a look at the [Anchors reference](/react/docs/apps/edges/anchors.md) for a thorough discussion.\n\n## Adding edges[](#adding-edges)\n\nEdges can be added to your app in a few different ways:\n\n* Via [drag and drop](/react/docs/apps/edges/dragging-edges.md) with the mouse or touch events\n* Via [click to add](/react/docs/apps/edges/click-to-add-edges.md) with the mouse or touch events\n* By a [data load](/react/docs/apps/model/io/loading-and-saving-data.md)\n* By programmatically [adding an edge to the model](/react/docs/apps/model/edges.md#add)\n\n## Defining appearance and behaviour[](#defining-appearance-and-behaviour)\n\nVisuallyJs will use a `Straight` connector and a `Continuous` anchor by default for all edges, but for most use cases you'll almost certainly want to modify this behaviour, which you can do in one of two ways:\n\n* For basic settings that will apply to all edges, you can set [defaults](#defaults)\n* For fine-grained control of edges on a per-type basis, you can map edge types in a [view](#view)","url":"https://visuallyjs.com/react/docs/apps/edges/overview","lib":"react","topic":"apps"},"docs/apps/edges/path-editing.md":{"title":"Path Editing","body":"# Editing edge paths\n\nVisuallyJs supports editing the path of edges for each of the different [connector types](/react/docs/apps/edges/connectors.md) that VisuallyJs ships with. The selection of the appropriate editor tool is managed automatically by VisuallyJs.\n\n## Setup[](#setup)\n\nTo setup your app for path editing, you need to set the `editable` flag in the `edges` section of your render options:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n editable: true\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nOnce you've setup path editing you'll need to invoke it at some point, for which you need to invoke the `startEditingPath` method on your surface. One common way to do this is by responding to a tap or click event on an edge:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { EVENT_CLICK, DEFAULT } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const viewOptions = {\n edges: {\n [DEFAULT]: {\n events: {\n [EVENT_CLICK]: (p) => { p.ui.startEditingPath(p.edge) }\n }\n }\n }\n}\n return <SurfaceComponent viewOptions={viewOptions}/>\n}\n\n```\n\nThe path editor will now stay active until you subsequently call `stopEditingPath()`. Another common setup for this is to do so in response to a click on a surface canvas (ie. a click on whitespace):\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { EVENT_CANVAS_CLICK, EVENT_CLICK, DEFAULT } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n events: {\n [EVENT_CANVAS_CLICK]: (p) => { p.renderer.stopEditingPath() }\n }\n}\n\n const viewOptions = {\n edges: {\n [DEFAULT]: {\n events: {\n [EVENT_CLICK]: (p) => { p.ui.startEditingPath(p.edge) }\n }\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions} viewOptions={viewOptions}/>\n}\n\n```\n\nEach editor offers a different interface for working with path edits.\n\n## Orthogonal editors[](#orthogonal-editors)\n\nThe orthogonal editor draws a handle on each segment of an edge, which can be dragged at 90 degrees to the direction of travel of the segment, ie. for a vertical segment, you can shift it horizontally, and for a horizontal segment you can shift it vertically.\n\nWhen you are shifting a segment, if you release the mouse at such a point that the segment you just dragged forms a straight line with a previous or subsequent segment, the segments are coalesced into one. If you drag some segment such that an existing segment ceases to be a straight line, the segment is split and new segment is inserted between them.\n\n#### Static anchors[](#static-anchors)\n\nIn this example we use an edge editor to edit the path of some edge whose anchors are at fixed points (in this case, `AnchorLocations.Bottom` and `AnchorLocations.Top`). We've also already called `startEditingPath(..)` on the surface for you:\n\n**********\n\n#### Dynamic anchors[](#dynamic-anchors)\n\nIf the edge you are editing has [dynamic anchors](/react/docs/apps/edges/anchors.md#dynamic), the edge editor will draw a placeholder at each end of the edge, which you can drag around to any supported position for the given anchor - here we use the `AutoDefault` dynamic anchor, which is an anchor that has one position on each of the four sides of the element on which it resides:\n\n**********\n\nWhen you start to drag an anchor placeholder, you'll see VisuallyJs adds an element indicating an allowed position to which that anchor can be moved.\n\n#### Continuous anchors[](#continuous-anchors)\n\nIf your edge is using anchor of type `AnchorLocations.Continuous` (which is the default), when you drag an anchor placeholder VisuallyJs will highlight the candidate face for the anchor relocation:\n\n**********\n\n#### User specified anchor positions[](#user-specified-anchor-positions)\n\nIf you have specified `anchorPositions` for some given vertex in your view, eg:\n\n```javascript\nnodes:{\n default:{\n ...,\n anchorPositions:[\n { x:0, y:0.5, ox:-1, oy:0, id:\"left\" },\n { x:1, y:0.5, ox:1, oy:0, id:\"right\" },\n { x:0.5, y:0, ox:0, oy:-1, id:\"top\" },\n { x:0.5, y:1, ox:0, oy:1, id:\"bottom\" }\n ]\n }\n}\n\n```\n\n...then the path editor will find these when you call `startEditingPath(...)`, and offer the ability to drag the end points of the edge to each of the available positions:\n\n**********\n\n### Avoiding vertices[](#avoiding-vertices)\n\nBy default, the orthogonal connector editor will avoid getting into a situation where either end of the connector intersects the source or target vertex. This is best illustrated with a picture:\n\n\n\ninfo\n\nThis functionality is only applied to the segments at either end of a connector. If you have some connector path that intersects the source or target vertex somewhere in the middle of the path, the path will not be re-routed to avoid the vertex.\n\nIf you want to switch this behaviour off, you can do so in the connector spec:\n\n```javascript\nconnector:{\n type:\"Orthogonal\",\n options:{\n vertexAvoidance:false\n }\n}\n\n```\n\nThis will be the resulting behaviour:\n\n\n\nYour users can still route the connector around in this setup but they'll have to move a lot more segments.\n\n***\n\n## Straight editors[](#straight-editors)\n\nThe straight editor draws a handle at the end of each segment of an edge, which can be dragged in any direction to alter its location. You can split a segment by clicking and holding the mouse at the location you wish to split the segment, and then dragging the new handle.\n\nTo delete a handle, click on it.\n\n#### Static anchors[](#static-anchors-1)\n\nIn this example we use an edge editor to edit the path of some edge whose anchors are at fixed points (in this case, `AnchorLocations.Right` and `AnchorLocations.Top`). We've also already called `startEditingPath(..)` for you:\n\n**********\n\n#### Dynamic anchors[](#dynamic-anchors-1)\n\nIf the edge you are editing has [dynamic anchors](/react/docs/apps/edges/anchors.md#dynamic), the edge editor will draw a placeholder at each end of the edge, which you can drag around to any supported position for the given anchor - here we use the `AutoDefault` dynamic anchor, which is an anchor that has one position on each of the four sides of the element on which it resides:\n\n**********\n\nWhen you start to drag an anchor placeholder, you'll see VisuallyJs adds an element indicating an allowed position to which that anchor can be moved.\n\n#### Continuous anchors[](#continuous-anchors-1)\n\nIf your edge is using anchor of type `AnchorLocations.Continuous`, when you drag an anchor placeholder VisuallyJs will highlight the candidate face for the anchor relocation:\n\n**********\n\n#### User specified anchor positions[](#user-specified-anchor-positions-1)\n\nIf you have specified `anchorPositions` for some given vertex in your view, eg:\n\n```text\nnodes:{\n default:{\n ...\n anchorPositions:[\n { x:0, y:0.5, ox:-1, oy:0, id:\"left\" },\n { x:1, y:0.5, ox:1, oy:0, id:\"right\" },\n { x:0.5, y:0, ox:0, oy:-1, id:\"top\" },\n { x:0.5, y:1, ox:0, oy:1, id:\"bottom\" }\n ]\n }\n}\n\n```\n\n...then the path editor will find these when you call `startEditingPath(...)`, and offer the ability to drag the end points of the edge to each of the available positions:\n\n**********\n\n### Smoothed connectors[](#smoothed-connectors)\n\nWhen you have `smooth:true` set on your connector, the editor functions slightly differently - the drag handles now represent the location of the control points for the splines that make up the Bezier curve, and when you drag them, the control points are moved accordingly. Also when `smooth` is set, the editor draws a guideline for each segment.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n editable: true,\n connector: {\n type: \"Straight\",\n options: {\n smooth: true\n }\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n***\n\n## Bezier editors[](#bezier-editors)\n\nThe bezier editor draws two handles - one for each control point in the connector. They are placed where the control point is, and as you drag them around the control points are updated accordingly.\n\n#### Static anchors[](#static-anchors-2)\n\nIn this example we use an edge editor to edit the path of some edge whose anchors are at fixed points (in this case, `AnchorLocations.Bottom` and `AnchorLocations.Top`). We've also already called `startEditingPath(..)` on the surface for you:\n\n**********\n\n***\n\n## QuadraticBezier editors[](#quadraticbezier-editors)\n\nThe QuadraticBezier editor draws one handle, located at the connector's control point. As you drag the handle around, the connector's control point is updated.\n\n**********\n\n***\n\n## Overlays[](#overlays)\n\nYou can supply a set of overlays to render on an edge for the duration of the edit, for example:\n\n```javascript\n\nsurface.startEditingPath(someEdge, {\n overlays:[\n {\n type:LabelOverlay.type,\n options:{\n label:\"editing...\",\n location:0.1\n }\n } \n ]\n})\n\n```\n\nWith this call we get a label overlay at location 0.1:\n\n**********\n\n## Delete button[](#delete-button)\n\nThe edge path editor offers a shortcut method to attach a delete button:\n\n```javascript\nsurface.startEditingPath(someEdge, {\n deleteButton:true\n})\n\n```\n\nThis results in:\n\n**********\n\nThis will delete the edge without prompting the user. If you'd like to hook into the edge deletion, you can provide an `onMaybeDelete` function.\n\n```javascript\nsurface.startEditingPath(someEdge, {\n deleteButton:true,\n onMaybeDelete:(edge, connection, doDelete) => {\n if (confirm(`Delete edge ${edge.id}?`)) {\n doDelete()\n }\n }\n})\n\n```\n\n**********\n\nNote that the operation is asynchronous - in the example above we use the windows `prompt` method, but you can invoke the `doDelete` callback at any stage.\n\n## Clearing path edits[](#clearing-path-edits)\n\nEdits made to a path can be cleared via `clearPathEdits` method on the `Surface` object.\n\n```javascript\nclearPathEdits (edgeOrConnection:string|Edge|Connection<BrowserElement>):boolean\n\n\n```","url":"https://visuallyjs.com/react/docs/apps/edges/path-editing","lib":"react","topic":"apps"},"docs/apps/edges/property-mapping.md":{"title":"Property Mapping","body":"# Property Mapping\n\nProperty mapping allows you to match specific values for a given property/properties to a set of config options - it's related to the concept of UI States, but it's a \"pull\" rather than \"push\": when you update the model, the UI figures out what config to apply for a given object, rather than you having to tell it.\n\nnote\n\nThis functionality is available only for edges. We are investigating options for how this could be usefully extended to nodes, groups and ports.\n\n### Example[](#example)\n\nThis example is drawn from the Flowchart starter app's source code:\n\n```javascript\n\nimport { ArrowOverlay } from \"@visuallyjs/browser-ui\"\n\nconst ARROW_WIDTH = 5\nconst ARROW_LENGTH = 10\nconst CLASS_DASHED_EDGE = \"some-css-class\"\n\nconst PROPERTY_LINE_STYLE = \"lineStyle\"\n\nconst EDGE_TYPE_SOURCE_ARROW = \"source\"\nconst EDGE_TYPE_TARGET_ARROW = \"target\"\nconst EDGE_TYPE_PLAIN = \"plain\"\nconst EDGE_TYPE_DASHED = \"dashed\"\n\nconst edgeMappings = [\n {\n property:PROPERTY_LINE_STYLE,\n mappings:{\n [EDGE_TYPE_SOURCE_ARROW]:{\n overlays:[\n {\n type:ArrowOverlay.type,\n options:{\n location:0,\n direction:-1,\n width:ARROW_WIDTH,\n Length:ARROW_LENGTH\n }\n } ]\n },\n [EDGE_TYPE_TARGET_ARROW]:{\n overlays:[\n {\n type:ArrowOverlay.type,\n options:{\n location:1,\n width:ARROW_WIDTH,\n length:ARROW_LENGTH\n }\n }\n ]\n },\n [EDGE_TYPE_PLAIN]:{},\n [EDGE_TYPE_DASHED]:{\n cssClass:CLASS_DASHED_EDGE\n }\n }\n }\n]\n\n\n```\n\nEach mapping consists of a property name (or list of names - see below) and a map of values to configs (the specific type of these configs is [EdgeMapping]()). Here we have declared a set of mappings for the property `lineStyle` in the backing data for an edge:\n\n```javascript\n{\n property:PROPERTY_LINE_STYLE,\n mappings: {\n [EDGE_TYPE_SOURCE_ARROW] : {\n ...\n }\n ...\n }\n}\n\n```\n\nSo if you had an edge with this definition:\n\n```javascript\n{\n source: \"1\",\n target: \"2\",\n data:{\n lineStyle:\"source\"\n }\n}\n\n```\n\nThen the corresponding connection would have an Arrow overlay at location 0.\n\n### Updating data[](#updating-data)\n\nWhen an edge is updated, the property mappings are inspected. Any that are no longer valid are removed, and any that are now valid are added:\n\n```javascript\nmodel.updateEdge(someEdge, {\n lineStyle:EDGE_TYPE_DASHED\n})\n\n```\n\nThis would result in the arrow overlay being removed, and `\"some-css-class\"` being added to the connection's class list, because there is a mapping for `EDGE_TYPE_DASHED`:\n\n```javascript\nmappings:{\n \n ... \n \n [EDGE_TYPE_DASHED]:{\n cssClass:CLASS_DASHED_EDGE\n }\n} \n\n```\n\n### Wildcard mappings[](#wildcard-mappings)\n\nYou can use \"\\*\" or `WILDCARD` from `@visuallyjs/browser-ui` as the value for some property, which will instruct the UI that the given config should be applied regardless of the value of the mapped property (as long as it is present, not null):\n\n```javascript\nimport { WILDCARD } from \"@visuallyjs/browser-ui\"\n\n{\n property:\"label\",\n mappings:{\n [WILDCARD]:{\n overlays:[\n {\n type:LabelOverlay.type,\n options:{\n label:\"{{label}}\",\n location:0.5,\n cssClass:\"some-label\"\n }\n }\n ]\n }\n }\n}\n\n```\n\nHere, we have instructed VisuallyJs to show a label whenever an edge's backing data has a `label` property. Incidentally, this specific requirement can actually be neatly handled by [Edge labels](/react/docs/apps/edges/edge-labels.md).\n\n### Multiple properties[](#multiple-properties)\n\nYou can map multiple properties instead of just a single property if you need the extra flexibility. For example, these are property mappings for an edge in a conceptual ERD, in which edges between entities and relationships show cardinality, but only at one end. We can model that with two properties:\n\n```javascript\npropertyMappings: [\n {\n property: [\"cardinality\", \"terminus\"],\n mappings:{\n \"one source\": {\n sourceMarker: OneOverlay.type\n },\n \"one target\": {\n targetMarker: OneOverlay.type\n }\n }\n }\n]\n\n```\n\nThen in our dataset we might have edges like this:\n\n```javascript\n[\n { source:\"1\", target:\"2\", data:{ cardinality:\"one\", terminus:\"source\" }},\n { source:\"2\", target:\"3\", data:{ cardinality:\"many\", terminus:\"target\" }}\n]\n\n```\n\nThe important point to note in the example mapping above is that the order of the keys must be reflected in the mapping keys: we declare `[\"cardiinality\", \"terminus\"]` as our properties, and our mapping keys are `\"one source\"` and `\"one target\"`, ie. the values to match are in the same order as the property keys.","url":"https://visuallyjs.com/react/docs/apps/edges/property-mapping","lib":"react","topic":"apps"},"docs/apps/edges/removing-edges.md":{"title":"Removing Edges","body":"# Removing edges\n\nThere are a few ways to remove edges in VisuallyJs. On this page we'll discuss edge deletion in the UI, but it's also possible (and quite common) to remove an edge programmatically, for which we direct you to our [model docs](/react/docs/apps/model/edges.md#removing-edges).\n\n## Removing via drag/drop[](#removing-via-dragdrop)\n\nBy default, VisuallyJs will let you grab an edge near one of its anchors and then drag it off the vertex. In the canvas below we have applied a CSS class to make these zones visible on hover; by default this does not occur (the CSS classes we target are `.vjs-connector-source-drag` and `.vjs-connector-target-drag`)\n\n**********\n\nNote: in the canvas above you cannot drop the edge back on to a vertex it was removed from, as the vertices are not marked up with the appropriate attributes to accept drag/drop edges.\n\n## Rettaching[](#rettaching)\n\nVisuallyJs's default behaviour is to discard any edges that a user has dropped in whitespace. You can override this via a setting:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n reattach: true\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nIn this canvas if you drag one end of the edge and drop it in whitespace VisuallyJs will reattach it:\n\n**********\n\n## Allowing unattached edges[](#allowing-unattached-edges)\n\nIn some circumstances you may wish to allow your users to detach edges and leave one end (or both ends in fact) of the edge unattached, but without removing the edge. You can do this by setting `allowUnattachedEdges`.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n allowUnattached: true\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nIn the canvas below, when you drag an edge off a vertex, you can drop it in whitespace:\n\n**********\n\n## Disabling detach[](#disabling-detach)\n\nYou can disable detach via mouse/touch events with the `detachable` setting in the `edges` options:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n detachable: false\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nIn this canvas VisuallyJs will not allow you to detach the edge using the mouse/touch events:\n\n**********\n\nHow, then, could your users delete an edge via the UI? One solution is to specify a **deleteButton**.\n\n## Showing a delete button[](#showing-a-delete-button)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n detachable: false\n }\n}\n\n const viewOptions = {\n edges: {\n default: {\n deleteButton: true\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions} viewOptions={viewOptions}/>\n}\n\n```\n\n**********\n\nThe delete button will be assigned a CSS class of `.jtk-edge-delete`.\n\n### Custom CSS class[](#custom-css-class)\n\nYou can provide one or more extra classes to set on the delete button via the `deleteButtonClass` property:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n detachable: false\n }\n}\n\n const viewOptions = {\n edges: {\n default: {\n deleteButton: true,\n deleteButtonClass: \"foo bar etc\"\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions} viewOptions={viewOptions}/>\n}\n\n```\n\n### Showing on hover only[](#showing-on-hover-only)\n\n`deleteButton` can be specified either as a boolean, or as a constant that specifies its `visibility`. To have a delete button that only appears on hover, for example:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { OVERLAY_VISIBILITY_HOVER } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n detachable: false\n }\n}\n\n const viewOptions = {\n edges: {\n default: {\n deleteButton: OVERLAY_VISIBILITY_HOVER\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions} viewOptions={viewOptions}/>\n}\n\n```\n\n**********\n\n### Managing edge removal[](#managing-edge-removal)\n\nYou may want to manage the removal of some specific edge - perhaps some condition is met in your app that means the edge cannot be removed, or perhaps you want to hit the server to confirm edge deletion first, etc. For that you can use the `deleteConfirm` property:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n detachable: false\n }\n}\n\n const viewOptions = {\n edges: {\n default: {\n deleteButton: true,\n deleteConfirm: (p, proceed) => {\n if(confirm('Delete edge?')) {\n proceed() \n } \n }\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions} viewOptions={viewOptions}/>\n}\n\n```\n\n**********\n\nThe argument for `deleteConfirm` should be a function of this type:\n\nEdgeDeleteConfirmationFunction\n\nDefinition of the function you can provide as `deleteConfirm` on an edge definition. VisuallyJs gives you the edge to be possibly deleted and the pointer event that instigated the deletion. If you wish to delete the edge you must invoke the `proceed()` function.\n\n`(params:{\n e:Event,\n edge:Edge\n}, proceed:() => any) => any`\n\nYou are given the edge that is a candidate for deletion, and the event that initiated the deletion. If you wish to confirm the edge removal, you must invoke the `proceed` method.","url":"https://visuallyjs.com/react/docs/apps/edges/removing-edges","lib":"react","topic":"apps"},"docs/apps/edges/styling-edges.md":{"title":"Styling Edges","body":"# Styling edges\n\nThere are a few approaches you can take when it comes to styling your edges - VisuallyJs provides an out of the box mapping from edge data to basic properties such as edge width, color etc, via the concept of [Simple edge styles](#simple-edge-styles). You can also [use CSS](#styling-with-css), or you can map a `PaintStyle` to your edges via a [view](#styling-with-paintstyles) or [in the UI defaults](#styling-with-ui-defaults). That's a lot of choice, so here we present a quick pros and cons for each option:\n\n| Method | Pros | Cons |\n| ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| [CSS](#styling-with-css) | Clean separation of presentation from code. Allows usage of various SVG CSS effects. Allows styling all edges of some type uniformly. | Does not support export to SVG. Does not support styling each edge individually. Does not support path outlines. |\n| [Paint styles](#styling-with-paintstyles) | Allows styling all edges of some type uniformly. Supports export to SVG. Supports path outlines. | Does not support styling each edge individually. |\n| [Simple edge styles](#simple-edge-styles) | Minimal setup. Allows each edge to be styled individually. Seamlessly integrated with update and undo/redo. Supports path outlines. Supports export to SVG. | Each edge needs its own styles declared in the backing data. Limited set of configurable properties. |\n| [UI Defaults](#styling-with-ui-defaults) | Allows configuration of default styles value which will apply, in the absence of some other value, to all edges. Supports export to SVG. Supports path outlines. | Does not support styling each edge individually. Applies to all types (but you can override on a per-type basis via [Paint styles](#styling-with-paintstyles)(. |\n\n### Styling with CSS[](#styling-with-css)\n\nSince VisuallyJs uses SVG to render edges, you can target the artifacts that VisuallyJs adds to the DOM via CSS. VisuallyJs uses a class of `vjs-connector` on the SVG element it uses for each edge, and the edge itself is written as one or more `path` elements inside of that, which each have a class according to their function:\n\n```html\n<svg class=\"vjs-connector\">\n <path d=\"...\" class=\"vjs-connector-outline\"></path>\n <path d=\"...\" class=\"vjs-connector-path\"></path>\n</svg>\n\n```\n\n#### Targeting the edge's SVG element[](#targeting-the-edges-svg-element)\n\nTo target the parent element for some path, for instance to assign `z-index`, you need a rule like this:\n\n```css\n.vjs-connector {\n z-index:50;\n}\n\n```\n\n#### Targeting the SVG path[](#targeting-the-svg-path)\n\nTo target the element used to render the path, you need a rule like this:\n\n```css\n.vjs-connector-path {\n stroke-width:2;\n stroke:cadetblue;\n stroke-dasharray: 2;\n}\n\n```\n\n#### Hover styles[](#hover-styles)\n\nTo change the appearance of an edge on hover, use the `:hover` css meta class:\n\n```css\n.vjs-connector-path:hover {\n stroke:orangered;\n}\n\n```\n\nNote that the above example targets the path element on hover, but you can also target the parent SVG element of course:\n\n```css\n.vjs-connector:hover {\n outline:1px solid orangered;\n}\n\n```\n\n#### Marching ants effect[](#marching-ants-effect)\n\nIt's simple to get this 'marching ants' effect via CSS with VisuallyJs:\n\n##### 1. Define the CSS animation[](#1-define-the-css-animation)\n\nDefine a CSS animation with a single keyframe that sets the dash offset:\n\n```css\n@keyframes dashdraw {\n 0% {\n stroke-dashoffset:10;\n }\n}\n\n```\n\n##### 2. Map the animation to a CSS rule[](#2-map-the-animation-to-a-css-rule)\n\n```css\n.animated-edge {\n stroke-dasharray:5;\n animation: dashdraw .5s linear infinite;\n}\n\n```\n\n##### 3. Use the cssClass property in an edge definition to map to this class (optional)[](#3-use-the-cssclass-property-in-an-edge-definition-to-map-to-this-class-optional)\n\n<!-- -->\n\nWe said that (3) is optional because if you just want to apply it to every edge in your dataset you can change the CSS rule shown in (2) to target every edge:\n\n```css\n.vjs-connector-path {\n stroke-dasharray:5;\n animation: dashdraw .5s linear infinite;\n}\n\n```\n\n#### Selected edges[](#selected-edges)\n\nWhen an edge is in the model's current selection, it has the CSS class `vjs-selected-connection` applied to it. You can target this class to change the appearance of either the connector's parent element:\n\n```css\n.vjs-selected-connection {\n outline:2px solid orangered;\n}\n\n```\n\nor the path element representing the edge:\n\n```css\n.vjs-selected-connection .vjs-connector-path {\n stroke:orangered;\n}\n\n```\n\n### Styling with PaintStyles[](#styling-with-paintstyles)\n\nA `PaintStyle` is an object containing various properties to apply to a given type of edge. The definition is:\n\nPaintStyle\n\nBasic style definition for an edge\n\n| Name | Type | Description |\n| -------------- | ------------------------ | ------------------------------------------------------------------------- |\n| dashArray? | string | Definition for stroke pattern |\n| fill? | string | Fill color for the edge. |\n| gradient? | Array<\\[number, string]> | Definition of a linear gradient to apply. Each entry is \\[offset, color]. |\n| outlineStroke? | string | Color for the outline path |\n| outlineWidth? | number | Width of the outline path |\n| stroke? | string | Stroke color for the edge |\n| strokeWidth? | number | Width of the stroke |\n\nAll properties are optional; VisuallyJs will use an default value where properties are not specified. To setup an outline path, you must provide both `outlineStroke` *and* `outlineWidth`.\n\n#### Mapping a PaintStyle in a view[](#mapping-a-paintstyle-in-a-view)\n\nYou can map a `PaintStyle` to some specific edge type inside a view:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const viewOptions = {\n edges: {\n redWithOutline: {\n paintStyle: {\n stroke: \"red\",\n strokeWidth: 3\n }\n }\n }\n}\n return <SurfaceComponent viewOptions={viewOptions}/>\n}\n\n```\n\n#### Mapping a PaintStyle in the UI defaults[](#mapping-a-paintstyle-in-the-ui-defaults)\n\nYou can also set a default paint style via the `defaults` for some surface:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n defaults: {\n paintStyle: {\n stroke: \"red\",\n strokeWidth: 3\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n#### Controlling the hit zone[](#controlling-the-hit-zone)\n\nBy default, VisuallyJs paints a single `path` element for each edge. If you want your users to be able to interact with your edges but your edges have a stroke width of only a couple of pixels, this can be difficult. To manage this with a `paintStyles` we recommend using the `outlineWidth` and `outlineStroke` paint style properties to setup a hit zone:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n defaults: {\n paintStyle: {\n stroke: \"red\",\n strokeWidth: 3,\n outlineStroke: \"transparent\",\n outlineWidth: 2\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nCalculating the outline width\n\nWhen you provide `outlineWidth` and `outlineStroke` properties in a `PaintStyle`, the visible width of the outline is computed as:\n\n`w = strokeWidth + (2 * outlineWidth)`\n\nwhich is to say that the `outlineWidth` value you provide is applied to each side of the connector's path.\n\nIn this example we've used `\"transparent\"` for the outline color, which gives us the expanded hit zone without altering the appearance of each edge. You can, of course, use any color you like.\n\n#### Hover styles[](#hover-styles-1)\n\nYou can also provide a `hoverPaintStyle` property in your view, which VisuallyJs will use to paint the edge when the mouse is hovering over it:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const viewOptions = {\n edges: {\n redWithOutline: {\n paintStyle: {\n stroke: \"red\",\n strokeWidth: 3,\n outlineStroke: \"orangered\",\n outlineWidth: 2\n },\n hoverPaintStyle: {\n stroke: \"green\",\n strokeWidth: 3,\n outlineStroke: \"yellowgreen\",\n outlineWidth: 4\n }\n }\n }\n}\n return <SurfaceComponent viewOptions={viewOptions}/>\n}\n\n```\n\n### Simple edge styles[](#simple-edge-styles)\n\nSimple edge styles allow you to map values from an edge's backing data to its appearance.\n\n#### Supported properties[](#supported-properties)\n\n* **color** A valid CSS color, which will be used to paint the connector\n* **lineWidth** An integer value denoting the width, in pixels, of the connector.\n* **outlineColor** A valid CSS color, which will be used to paint the connector's outline.\n* **outlineWidth** An integer value denoting the width of the connector's outline. Note that this is not added to the `lineWidth` value; this values describes the total width of the outline. For instance, a `lineWidth` of 3 and an `outlineWidth` of 5 would result in a 1 pixel outline on either side of the connector path.\n* **gradient** An array of \\[offset, color] values which will be used to apply a linear gradient to the path. When this is set, `color` is ignored.\n\nNone of these properties are mandatory. VisuallyJs will fall back to its defaults for these via the `paintStyle` mechanism if your edge data does not contain any of these properties.\n\n#### Example[](#example)\n\n<!-- -->\n\nIn this example the edge in our dataset will have a color of \"cadetblue\" and a stroke width of 3 pixels. It will also have an outline of 5 pixels each side, and the color of the outline will be pink. I think we can all agree it will look pretty fetching indeed.\n\nAnd..that's it, basically. There's not much else to it. If you call `updateEdge(...)` with some new values for these properties, the edge will be updated.\n\nLet's render that example from above. We'll render an edge with this backing data:\n\n```javascript\n{\n color:\"cadetblue\",\n lineWidth:3,\n outlineColor:\"pink\",\n outlineWidth:5,\n id:\"edge\" \n}\n\n```\n\n(we gave it an `id` because we want to access it when you press a button in a moment; id is not a mandatory property).\n\n**********\n\nIf you now click this button, we'll set these new values, and you'll see the edge update:\n\n```javascript\nmodel.updateEdge(\"edge\", {\n color:\"black\", \n outlineColor:\"yellow\",\n lineWidth:2,\n outlineWidth:3,\n label:\"New label\"\n})\n\n```\n\nnote\n\nSimple edge styles are switched on by default. If you do not want this behaviour in your app, you can save yourself some CPU cycles by setting `simpleEdgeStyles:false` in your render options.\n\n#### Gradient Example[](#gradient-example)\n\n<!-- -->\n\nIn this example the edge in our dataset will have a stroke width of 5 pixels, and will be painted with a linear gradient from \"lightblue\" to \"forestgreen\".\n\nLet's render that example from above. We'll render an edge with this backing data:\n\n```javascript\n{\n gradient:[[0,\"lightblue\"],[100, \"forestgreen\"]],\n lineWidth:5\n}\n\n```\n\n**********\n\n### Styling with UI Defaults[](#styling-with-ui-defaults)\n\nThe UI defaults support a few keys that allow you to configure default paint styles for your edges, and to setup a hit zone for edges that will apply to every edge in your app.\n\n#### Supported properties[](#supported-properties-1)\n\n| Key | Constant | Description |\n| ----------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `paintStyle` | `DEFAULT_KEY_PAINT_STYLE` | A `PaintStyle` object as discussed above, whose values will be used for all edges unless a more specific type mapping is found in the view. Defaults to a stroke width of 2 pixels and a stroke color of `#456`. |\n| `hoverPaintStyle` | `DEFAULT_KEY_HOVER_PAINT_STYLE` | A `PaintStyle` object as discussed above, whose values will be used for all edges when the mouse is hovering over it unless a more specific type mapping is found in the view. Defaults to null. |\n| `paintConnectorOutline` | `DEFAULT_KEY_PAINT_CONNECTOR_OUTLINE` | Defaults to false. When true, VisuallyJs will draw a second path underneath each edge, with, by default, a transparent stroke. This arrangement is a useful way to manage the hit zone for your edges, to make it easier for your users to click/tap on edges. The outline path is assigned a CSS class of `.vjs-connector-outline`, so you can override its transparent stroke via CSS if you wish. |\n| `connectorOutlineWidth` | `DEFAULT_KEY_CONNECTOR_OUTLINE_WIDTH` | Defaults to 10 pixels, but only takes effect if `paintConnectorOutline` is true. NOTE this value defines the total width of the outline path, not, as in the case of the `outlineWidth` property of a `PaintStyle`, the number of pixels to pad the main edge path with. |\n| `connectorOutlineColor` | `DEFAULT_KEY_CONNECTOR_OUTLINE_COLOR` | Defaults to \"transparent\". You can use any valid CSS3 color spec here. |\n\n#### Example[](#example)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n defaults: {\n paintStyle: {\n stroke: \"red\",\n strokeWidth: 3\n },\n hoverPaintStyle: {\n stroke: \"orangered\",\n strokeWidth: 5\n },\n paintConnectorOutline: true,\n connectorOutlineWidth: 15\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n#### Controlling the hit zone[](#controlling-the-hit-zone-1)\n\nAs discussed in the paint style section above, by default, VisuallyJs paints a single `path` element for each edge. If you want your users to be able to interact with your edges but your edges have a stroke width of only a couple of pixels, this can be difficult. To manage this via UI defaults you can use the `paintConnectorOutline` default:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n defaults: {\n paintConnectorOutline: true,\n connectorOutlineWidth: 30\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nIn this example we've instructed VisuallyJs to paint a connector outline on every edge, and we've also used the `connectorOutlineWidth` default to specify we want the outline to be 30 pixels. If you omit this flag VisuallyJs will use a default value of 10 pixels. By default this outline will be transparent, but you can also set `connectorOutlineColor` if you wish:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n defaults: {\n paintConnectorOutline: true,\n connectorOutlineWidth: 20,\n connectorOutlineColor: \"cadetblue\"\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********","url":"https://visuallyjs.com/react/docs/apps/edges/styling-edges","lib":"react","topic":"apps"},"docs/apps/edges/unattached-edges.md":{"title":"Unattached Edges","body":"# Unattached edges\n\nBy default, edges are expected to have a `source` and `target` vertex. But there are some use cases - in particular when diagramming - where you may want to support edges where the source and/or target of the edge is in whitespace and not attached to a vertex.\n\n## Configuration[](#configuration)\n\nUnattached edges are switched off by default. To turn them on, set `allowUnattached` in your render options:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n allowUnattached: true\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n## Data model[](#data-model)\n\nWhen an edge is unattached at the source or target, the data object for the replaces the ID of a vertex with a point on the canvas. In the example above, for instance, the dataset looks like this:\n\n```javascript\n{\n nodes:[\n { id:\"1\", left:50, top:50 },\n { id:\"2\", left:250, top:250 }\n ], \n edges:[\n { source:\"1\", target:{x:80, y:230} }\n ]\n}\n\n```\n\n## Rettaching an unattached edge[](#rettaching-an-unattached-edge)\n\nYou can relocate an unattached edge in the same way as an edge that is connected to a vertex - VisuallyJs writes a drag handle at the source and target which is not visible (although it could be, if you wanted, via CSS), but which changes the cursor on hover.\n\nHere's the same example as before, but we've applied a few CSS styles so that you can see the hidden elements - the blue boxes are the handles with which you can drag the edge; the red box is the dummy element.\n\n```css\n .vjs-connector-target-drag {\n fill:cornflowerblue;\n }\n \n .vjs-connector-source-drag {\n fill:cornflowerblue;\n }\n\n .vjs-dummy-vertex {\n width:10px !important;\n height:10px !important;\n background-color:orangered;\n }\n\n```\n\n**********\n\nIf you drag the edge to the unconnected vertex you'll see the dummy vertex gets removed from the canvas. Dragging it off and dropping it on whitespace will cause a new dummy vertex to be added at the appropriate location.","url":"https://visuallyjs.com/react/docs/apps/edges/unattached-edges","lib":"react","topic":"apps"},"docs/apps/edges/vertex-avoidance.md":{"title":"Vertex Avoidance","body":"# Vertex avoidance\n\nYou can instruct VisuallyJs to attempt to route edges around vertices, either for all edges in your app or just for some specific type(s) of edge.\n\n## Example[](#example)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n connector: \"Orthogonal\",\n avoidVertices: true\n },\n grid: {\n size: {\n width: 20,\n height: 20\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\nThe key option being `avoidVertices` in the `edges` config. Internally, vertex avoidance is computed using an A\\* algorithm, which is based upon a grid, and so we do recommend you use a `grid` in your app if you've got `avoidVertices` set. Without a grid set you can sometimes see an effect where a path segment's location changes as you drag an element, and then snaps back to some multiple of the A\\* grid. The A\\* grid has a cell size of 10 pixels and so the best results are obtained from setting your own grid to a multiple of that.\n\n## Path constrainment[](#path-constrainment)\n\nYou can constrain the travel of the path in a few different ways.\n\n### Orthogonal routing[](#orthogonal-routing)\n\nOrthogonal routing constrains path segments to travel either horizontally or vertically, as shown at the top of the page.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n avoidVertices: true,\n connector: {\n type: \"Straight\",\n options: {\n constrain: \"orthogonal\"\n }\n }\n },\n zoomToFit: true,\n grid: {\n size: {\n width: 20,\n height: 20\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n### Any angle[](#any-angle)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n avoidVertices: true,\n connector: {\n type: \"Straight\",\n options: {\n constrain: \"none\"\n }\n }\n },\n grid: {\n size: {\n width: 20,\n height: 20\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nWith this setup path segments can travel at any angle:\n\n**********\n\n### Smooth connectors[](#smooth-connectors)\n\nFor some applications the above can look a little jerky, and so one thing you can do is set `smooth` on your connector, to get that Graphviz effect:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n avoidVertices: true,\n connector: {\n type: \"Straight\",\n options: {\n smooth: true\n }\n }\n },\n zoomToFit: true,\n grid: {\n size: {\n width: 20,\n height: 20\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\ninfo\n\nStraight connectors with `smooth:true` set are aliased in VisuallyJs to the connector name `Smooth`:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n avoidVertices: true,\n connector: \"Smooth\"\n },\n grid: {\n size: {\n width: 20,\n height: 20\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n### Metro routing[](#metro-routing)\n\n\"Metro\" routing constrains path segments to travel either horizontally, vertically, or at 45 degrees.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n avoidVertices: true,\n connector: {\n type: \"Straight\",\n options: {\n constrain: \"metro\"\n }\n }\n },\n zoomToFit: true,\n grid: {\n size: {\n width: 20,\n height: 20\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n***\n\n## Applying to specific edge types only[](#applying-to-specific-edge-types-only)\n\nIf you want to setup your app such that only specific edge types will use the A\\* router, you can do this via your view. In this example, we map two edge types, and the `orthogonal` edge type has this key set:\n\n```javascript\n{\n avoidVertices:true\n}\n\n```\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n connector: {\n type: \"Straight\",\n options: {\n constrain: \"orthogonal\"\n }\n }\n },\n grid: {\n size: {\n width: 20,\n height: 20\n }\n }\n}\n\n const viewOptions = {\n edges: {\n straight: {\n connector: \"Straight\",\n paintStyle: {\n stroke: \"red\",\n strokeWidth: 2\n }\n },\n orthogonal: {\n avoidVertices: true,\n connector: \"Orthogonal\",\n paintStyle: {\n stroke: \"red\",\n strokeWidth: 2\n }\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions} viewOptions={viewOptions}/>\n}\n\n```\n\nSo the red lines - with the straight connector - travel through vertices without avoiding them, while the green lines route themselves around vertices:\n\n**********","url":"https://visuallyjs.com/react/docs/apps/edges/vertex-avoidance","lib":"react","topic":"apps"},"docs/apps/inspectors.md":{"title":"Inspectors","body":"# Inspectors\n\nAn inspector is a form that can be used to edit the properties of some object, or set of objects, in the VisuallyJs dataset. Inspectors listen to selection events from the underlying model and then draw a suitable UI for editing the selected object(s) based upon the configuration you provide.\n\nIn the canvas below we've setup a simple inspector and selected a vertex to begin with. You can edit the various fields in the form on the left. Note that with the text input, changes are persisted on blur and when the enter key is pressed, but for the textarea changes are only persisted on blur.\n\n**********\n\n<!-- -->\n\n## Setup[](#setup)\n\nCreate a React component that renders an `InspectorComponent`, and pass a function to its body that renders content based on the current selected object.\n\n```jsx\n\nimport { useState } from \"react\"\nimport { InspectorComponent} from \"@visuallyjs/browser-ui-react\"\nimport { Node, Edge } from \"@visuallyjs/browser-ui\"\n\nexport default function MyInspectorComponent(props) {\n\n return <InspectorComponent>\n\n {(current) => {\n\n { current.objectType === Node.objectType &&\n <div className=\"node-inspector\">\n <div>Text</div>\n <input type=\"text\" vjs-att=\"text\" vjs-focus=\"true\"/>\n <div>Fill</div>\n <input type=\"color\" vjs-att=\"fill\"/>\n </div>\n }\n\n { current.objectType === Edge.objectType &&\n <div className=\"edge-inspector\">\n <div>Label</div>\n <input type=\"text\" vjs-att=\"label\"/>\n <div>Color</div>\n <input type=\"color\" vjs-att=\"color\"/>\n </div>\n }\n \n }}\n\n </InspectorComponent>\n}\n \n\n```\n\n## Empty inspector[](#empty-inspector)\n\nTo render something when the inspector has no current selection, pass a function to the `renderEmptyContent` prop:\n\n```jsx\n\nimport { useState } from \"react\"\nimport { InspectorComponent} from \"@visuallyjs/browser-ui-react\"\nimport { Node, Edge } from \"@visuallyjs/browser-ui\"\n\nexport default function MyInspectorComponent(props) {\n\n function nothingSelected() {\n return <h3>Select a node to inspect its properties</h3>\n }\n \n return <InspectorComponent renderEmptyContent={nothingSelected}>\n\n {(current) => {\n ...\n }}\n\n </InspectorComponent>\n}\n \n\n```\n\n<!-- -->\n\nNow you just need to declare that component in your JSX, ensuring that it's inside a `SurfaceComponent` or `SurfaceProvider`:\n\n```jsx\n\nimport { SurfaceComponent, SurfaceProvider} from \"@visuallyjs/browser-ui-react\"\nimport MyInspectorComponent from \"./MyInspector.jsx\"\n\nexport function MyApp() {\n return <SurfaceProvider>\n <SurfaceComponent .../>\n <MyInspectorComponent/>\n </SurfaceProvider>\n}\n\n```\n\nThe InspectorComponent is discussed in detail in the reference docs [on this page](/react/docs/reference/InspectorComponent.md).\n\n## Binding data[](#binding-data)\n\nFields in your data objects are bound to HTML elements via an `vjs-att` attribute. For instance, here's the form we use in the example canvas above:\n\n```html\n<input type=\"text\" vjs-att=\"label\">\n<textarea vjs-att=\"description\" rows=\"10\" cols=\"10\"></textarea>\n<select vjs-att=\"someNumber\">\n <option value=\"1\">1</option>\n <option value=\"5\">5</option>\n <option value=\"10\">10</option>\n</select>\n\n```\n\nEach of the `vjs-att` attributes in the HTML above maps to a property in the backing data of the object(s) being inspected:\n\n```javascript\n{\n label:\"My Object\",\n description:\"This is my object, with a label and a description and some number\",\n someNumber:5\n}\n\n```\n\n## Supported input types[](#supported-input-types)\n\nThis is the list of supported input types. We show a simple example for each type, but keep in mind you can use all the available attributes on these in your markup - for instance, for a `number` field, perhaps you want to limit the allowed values. Or you could supply a regular expression to a `text` input, etc.\n\n### Text Input[](#text-input)\n\n```html\n<input type='text' vjs-att=\"someProperty\">\n\n```\n\n### Radio Button[](#radio-button)\n\n```html\n<input type='radio' vjs-att=\"someProperty\" value=\"radioValue\" name=\"someProperty\">\n\n```\n\n### Checkbox(es)[](#checkboxes)\n\n```html\n<input type='checkbox' vjs-att=\"someProperty\">\n\n```\n\nThe inspector supports rendering multiple checkboxes with the same `vjs-att`, for example:\n\n```html\n<div class=\"my-inspector\">\n <input type='checkbox' vjs-att=\"someProperty\" value=\"type1\">\n <input type='checkbox' vjs-att=\"someProperty\" value=\"type2\">\n</div>\n\n```\n\nYou need to be using an array in your data to support this:\n\n```javascript\n{\n id:\"my-vertex\",\n someProperty:[\"type1\", \"type2\"]\n}\n\n```\n\n### Number Input[](#number-input)\n\n```html\n<input type='number' vjs-att=\"someProperty\">\n\n```\n\n### Textarea[](#textarea)\n\n```html\n<textarea vjs-att=\"someProperty\" rows=\"10\" cols=\"5\">\n\n```\n\n### Select[](#select)\n\n```html\n<select vjs-att=\"someProperty\">\n <option value=\"someValue\">Some Value</option>\n <option value=\"someOtherValue\">Some Other Value</option>\n</select>\n\n```\n\n### Color Input[](#color-input)\n\n```html\n<input type='color' vjs-att=\"someProperty\">\n\n```\n\n### Hidden Input[](#hidden-input)\n\n```html\n<input type='hidden' vjs-att=\"someProperty\" value=\"someValue\">\n\n```\n\n## Non-string datatypes[](#non-string-datatypes)\n\nBy default, HTML element values are strings, which may not be ideal for your data model. You can instruct VisuallyJs to cast the value of certain elements to a number, by declaring a `vjs-datatype` attribute in your inspector template:\n\n```html\n<div>\n <select vjs-att=\"threshold\" vjs-datatype=\"integer\">\n <option value=\"5\">5</option>\n <option value=\"10\">10</option>\n <option value=\"15\">15</option>\n </select>\n</div>\n\n```\n\nIn this example, VisuallyJs will attempt to cast the value to an integer. Currently, supported values for `vjs-datatype` are:\n\n* **integer** Cast the value to an integer\n* **float** Cast the value to a float, eg 1.5, 2.0, etc.\n\nThe `vjs-datatype` attribute is supported on:\n\n* `<select.../>`\n* `<input type=\"radio\" .../>`\n* `<input type=\"text\" .../>`\n\nnote\n\nIf you're using an input of type `text` and you want a number, it's probably better to use an input of type `number` - see MDN's discussion [here](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/number).\n\n## Multiple selections[](#multiple-selections)\n\nBy default, an inspector supports selections containing multiple objects. When multiple objects are being edited, the inspector calculates a set of \"common data\", ie. the set of keys for which every object in the inspector has a value. For text inputs and text areas, if every value for some given key is the same across all the managed objects, that value is shown and can be edited, resulting in a change to all the managed objects. Otherwise, if not every value is the same, the text input or text area will display a blank value. If the user types in the input field then that change will be propagated to all the managed objects.\n\nTo switch off multiple selections you can do this:\n\n```jsx\n\nimport { useState } from \"react\"\nimport { InspectorComponent} from \"@visuallyjs/browser-ui-react\"\nimport { Node, Edge } from \"@visuallyjs/browser-ui\"\n\nexport default function MyInspectorComponent(props) {\n\n const [currentType, setCurrentType] = useState('')\n const renderEmptyContainer = () => setCurrentType('')\n \n // a Node, Edge, Group or Port\n const refresh= (obj, cb) => {\n setCurrentType(obj.objectType)\n }\n\n return <InspectorComponent refresh={refresh} \n multipleSelections={false}\n renderEmptyContainer={renderEmptyContainer}>\n ...\n\n </InspectorComponent>\n}\n\n```\n\ncaution\n\nIf you have \\`multipleSelections\\` switched on in your inspector (and remember it is switched on by default), then you might find yourself in a situation where you are editing different object \\_types\\_ at the same time (eg edges and nodes). This can, of course, be fine for some applications, but for others it is not. To avoid editing multiple different types at once, you can set a selection mode of isolated on the underlying model. See the [documentation on selections](/react/docs/apps/model/selections.md).","url":"https://visuallyjs.com/react/docs/apps/inspectors","lib":"react","topic":"apps"},"docs/apps/layouts/absolute.md":{"title":"Absolute","body":"# Absolute Layout\n\nThis layout, by default, retrieves positioning values from the `left` and `top` values in your vertex data and uses these as the \\`left\\` and \\`top\\` CSS properties in the DOM. However, you can provide your own function to extract appropriate values, should you need to.\n\nFor applications in which the positions of the nodes is determined by your users, the `Absolute` layout is a good choice. If you need to render a dataset that a human being has never manipulated, you can use the [ForceDirected layout](./force-directed), which extends the `Absolute` layout and only calculates a position for vertices that do not have values set for their position.\n\nThis is the default layout used by VisuallyJs.\n\n<!-- -->\n\n<!-- -->\n\n## Parameters[](#parameters)\n\nAbsoluteLayoutParameters\n\nConstructor parameters for an AbsoluteLayout.\n\n| Name | Type | Description |\n| ----------------- | -------------------- | -------------------------------------------------------------------------------------------------------------- |\n| absoluteBacked? | boolean | Defaults to false. If true, then the layout will use any position values found in the data for a given vertex. |\n| height? | number | Optional fixed height for the layout. |\n| locationFunction? | [LocationFunction]() | Optional function that, given some vertex, can provide the x/y location of the vertex on the canvas |\n| padding? | [PointXY]() | Optional padding to put around the elements. |\n| width? | number | Optional fixed width for the layout. |\n\n## Calculation of location[](#calculation-of-location)\n\n#### Location Function[](#location-function)\n\nIf you provide a `locationFunction`, it will be passed each vertex and is expected to return a position for the given vertex in the form `{x:number, y:number}`\n\n```javascript\nlocationFunction:(v:Vertex):PointXY =>{\n return {x:node.data.xPosition, y:node.data.yPosition }\n}\n\n```\n\n### Location inside a group[](#location-inside-a-group)\n\nIf a node is a child of a group, when the group performs a layout of its child nodes, it will pass itself as the second argument to the location function:\n\n```javascript\nlocationFunction:(v:Vertex, parent:Group):PointXY =>{\n // perhaps here you want to do something unique to each group\n}\n\n```\n\n`group` is only ever assigned a value during the group layout phase. When processing the layout of nodes and groups, `group` will be null.\n\n## Positioning properties[](#positioning-properties)\n\nFor Surface/Paper UIs the default positioning properties are `left` and `top`, for instance:\n\n```json\n{\n \"id\": \"node1\",\n \"left\": 50,\n \"top\": 250\n}\n\n```\n\nFor Diagram UIs the default positioning properties are `x` and `y`:\n\n```json\n{\n \"id\": \"node1\",\n \"type\": \"process\",\n \"x\": 50,\n \"y\": 250\n}\n\n```","url":"https://visuallyjs.com/react/docs/apps/layouts/absolute","lib":"react","topic":"apps"},"docs/apps/layouts/balloon.md":{"title":"Balloon","body":"# Balloon Layout\n\nThis layout groups vertices into clusters.\n\nThis layout is useful for unstructured data - database schemas, mind maps, graphs, etc. For a given input graph the structure of the layout will always be the same, but this layout does not extend the [Absolute](/react/docs/apps/layouts/absolute.md) layout as the [ForceDirected](/react/docs/apps/layouts/force-directed.md) layout does, so all vertex placement is decided upon by the layout.\n\n## Parameters[](#parameters)\n\nBalloonLayoutParameters\n\nConstructor parameters for a Balloon layout.\n\n| Name | Type | Description |\n| ----------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| absoluteBacked? | boolean | Defaults to false. If true, then the layout will use any position values found in the data for a given vertex. |\n| getChildEdges | [ChildEdgesFunction]() | The function that retrieves child edges for a given vertex. This function defines how the<br />layout walks your data model to generate the output. |\n| getChildVertices? | [HierarchicalLayoutChildVerticesFunction<]()[Vertex]()> | Optional function used to determine the edges to traverse to find children from some node |\n| getRootNode? | (dataSource:[DataSource]()) => Array<[Vertex]()> | Optional. A function that is given the data source instance as argument and is expected to return either a<br />single node/group, or an array of nodes/groups, to use as the root(s) for the layout |\n| groupPadding? | number | Minimum distance between a group of vertices and its neighbours. Defaults to 100 pixels. |\n| height? | number | Optional fixed height for the layout. |\n| ignoreLoops? | boolean | Defaults to true. If a loop is found during the layout it is usually ignored, unless this is set to true. |\n| ignorePorts? | boolean | Defaults to false, meaning that ports are taken into account when figuring the list of edges from some vertex.<br />If you set this to `true`, ports will be ignored and the layout will only consider edges connected directly to<br />each vertex. |\n| locationFunction? | [LocationFunction]() | Optional function that, given some vertex, can provide the x/y location of the vertex on the canvas |\n| padding? | [PointXY]() | Optional padding to put around the elements. |\n| rootNode? | Array<[Vertex]()> | Optional. Defines the nodes/groups to use as the root of the tree. These may be provided as an array of either a<br />node/group id or a node/group object. If this parameter is not specified and multipleRoots is not false then the<br />layout uses the result(s) of the `getRootNode` function; otherwise it uses the first node/group found in the<br />dataset. |\n| width? | number | Optional fixed width for the layout. |\n\n## Example[](#example)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { BalloonLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: BalloonLayout.type\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n## Behaviour after relayout[](#behaviour-after-relayout)\n\nA relayout will generate the exact same arrangement of vertices, since this layout is deterministic. But any changes to node/group dimensions will be taken into account.\n\n## Behaviour after refresh[](#behaviour-after-refresh)\n\nA refresh will generate the exact same arrangement of nodes/groups, since this layout is deterministic. But any changes to node/group dimensions will be taken into account.","url":"https://visuallyjs.com/react/docs/apps/layouts/balloon","lib":"react","topic":"apps"},"docs/apps/layouts/circular.md":{"title":"Circular","body":"# Circular Layout\n\nArranges all the nodes/groups in the model into a circle, with a radius sufficiently large that no two nodes/groups overlap.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { CircularLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: CircularLayout.type\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n***\n\n### Parameters[](#parameters)\n\nCircularLayoutParameters\n\nParameters for the circular layout.\n\n| Name | Type | Description |\n| ----------------- | -------------------- | ------------------------------------------------------------------------------------------------------ |\n| centerRoot? | boolean | If true, the first node in the data set will be placed in the center of the circle. Defaults to false. |\n| height? | number | Optional fixed height for the layout. |\n| locationFunction? | [LocationFunction]() | Optional function that, given some vertex, can provide the x/y location of the vertex on the canvas |\n| padding? | [PointXY]() | Optional padding to put around the elements. |\n| width? | number | Optional fixed width for the layout. |\n\n***\n\n### Centering the root node[](#centering-the-root-node)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { CircularLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: CircularLayout.type,\n options: {\n centerRoot: true\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```","url":"https://visuallyjs.com/react/docs/apps/layouts/circular","lib":"react","topic":"apps"},"docs/apps/layouts/column.md":{"title":"Column","body":"# Column Layout\n\nThis is a specialized instance of `GridLayout` with the number of columns fixed to 1.\n\n### Example[](#example)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ColumnLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: ColumnLayout.type\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n### Sorting entries[](#sorting-entries)\n\nYou can provide a `sort` function to the column layout to specify an order in which entries are placed. The layout will then arrange them in the specified order from top to bottom.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ColumnLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: ColumnLayout.type,\n options: {\n sort: (a,b) => parseInt(b.id, 10) - parseInt(a.id, 10)\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nThe `sort` function receives two arguments, `a` and `b`, which are either `Node` or `Group` objects, and it should return a number indicating their relative order.","url":"https://visuallyjs.com/react/docs/apps/layouts/column","lib":"react","topic":"apps"},"docs/apps/layouts/force-directed.md":{"title":"Force Directed","body":"# ForceDirected Layout\n\nThis layout models edges as springs, placing connected elements nearby, and ensuring adequate space between all elements. [Wikipedia](http://en.wikipedia.org/wiki/Force-directed_graph_drawing) has a good introduction to these types of layouts. It is useful for unstructured data - database schemas, mind maps, graphs, etc. Force-directed algorithms initially position nodes with a degree of randomness and so do not ever produce exactly the same result twice (try reloading this page) - for this reason it is recommended that you read the note on \\[refresh vs re-layout]/lib/layouts#refreshvsrelayout)\n\n### Parameters[](#parameters)\n\nForceDirectedLayoutParameters\n\nParameters for the force directed layout\n\n| Name | Type | Description |\n| ----------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| absoluteBacked? | boolean | Defaults to false. If true, then the layout will use any position values found in the data for a given vertex. |\n| height? | number | Optional fixed height for the layout. |\n| iterations? | number | Maximum number of iterations to run. Defaults to 50. Increasing this number may result in a nicer output, at the expense of run time. |\n| locationFunction? | [LocationFunction]() | Optional function that, given some vertex, can provide the x/y location of the vertex on the canvas |\n| padding? | [PointXY]() | Optional padding to put around the elements. |\n| r? | number | The amount of travel to impose on each element every time a repulsion or attraction event occurs during the calculation of the layout. This is expressed as a fraction of the distance the two elements would travel in order to be `spacing` pixels apart. Defaults to 0.25. A value of 1 here may seem desirable but in general will not provide the best results: moving one pair of elements by their ideal amount can negatively affect many others. It is better to provide a fractional value here and allow the layout to compromise. |\n| spacing? | number | Ideal spacing to leave between elements. Defaults to 250px, but this does not mean that elements end up separated by exactly 250px. |\n| width? | number | Optional fixed width for the layout. |\n\n### Example[](#example)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ForceDirectedLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: ForceDirectedLayout.type\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n### Placement of vertices[](#placement-of-vertices)\n\n#### Absolute Backing[](#absolute-backing)\n\nThe `ForceDirected` layout extends [AbsoluteLayout](/react/docs/apps/layouts/absolute.md), which means that, by default, the layout will defer to positions that are stored in the backing data for each vertex. This is a very useful feature for the majority of applications: you do not typically want the layout to run if a human being has already taken a look at the data and perhaps moved things around to be more to their liking.\n\n##### Specifying Position[](#specifying-position)\n\nThe default parameters used by `AbsoluteLayout` are, for Surfaces and Papers, `left` and `top`. So for instance you might have these nodes in your data:\n\n```javascript\nnodes:[\n { id:\"1\", left:50, top:150, label:\"One\" },\n { id:\"2\", left:150, top:250, label:\"Two\" }\n]\n\n```\n\nFor Diagrams the default positioning parameters are `x` and `y`.\n\nBy default, the Force Directed layout will honour these values if they are present, rather than processing the nodes.\n\nIf you do not wish to use `left` and `top`, you can provide your own `locationFunction`. This is discussed in the [documentation for the Absolute layout](/react/docs/apps/layouts/absolute.md#location-function).\n\n##### Switching off Absolute backing[](#switching-off-absolute-backing)\n\nYou can switch off Absolute backing via the `absoluteBacked` parameter:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ForceDirectedLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: ForceDirectedLayout.type,\n options: {\n absoluteBacked: false\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n### Behaviour after relayout[](#behaviour-after-relayout)\n\nA relayout will generate a brand new arrangement of elements, due to the fact that elements are placed randomly initially.\n\n### Behaviour after refresh[](#behaviour-after-refresh)\n\nA refresh of the layout locks the positions of any vertices that were positioned in a previous run of the layout, and these vertices do not move: only vertices that have not yet been positioned by the layout algorithm will move.\n\n### Fine tuning positioning[](#fine-tuning-positioning)\n\nFor vertices without positioning information, the layout will optimise their placement relative to vertices to which they are connected, and ensure that vertices do not overlap.\n\nWhen placing vertices dynamically, an initial random position is computed for each vertex. The bounding box that limits possible values for this random position is taken to be the size of the viewport in which the layout is being displayed, not the bounds of the dataset. This is to ensure that the new vertex appears somewhere the user can see it. Whilst initial positions are computed to lie within the bounds of the viewport, when the algorithm runs there is no reason that vertices won't be pushed out of the viewport.\n\nThe layout works by alternately pushing apart vertices so they do not overlap, and then pulling together vertices that have one or more edges between them. This is controlled by three parameters:\n\n* **iterations** The maximum number of iterations to run through until accepting the state of the layout as it is. More iterations will typically result in a finer grained output, but will take longer. This defaults to 50.\n\n* **spacing** This is the measure of how much padding you want to see between the vertices. It defaults to 250px. Note that the layout will never result in exactly this much padding between every vertex (unless, perhaps you have a very small number of vertices in the dataset); rather this number is your \"ideal\" padding, and the layout will strive to establish this amount of padding but will be constrained by the number of iterations it is allowed to run for and the complexity of the dataset.\n\n* **r** This is a measure of how far each vertex will be moved when two vertices need to be repelled or attracted. Mathematically, this number is the ratio of the amount of travel applied to each vertex versus the amount of travel that would be applied for the two vertices to be spaced according to the value of `spacing`. It defaults to 0.25. Increasing this number will result in a shorter run time but the quality of the output will be degraded. Reducing this value can improve the quality of the output but you may find you also need to increase the number of iterations you allow the layout to run for.","url":"https://visuallyjs.com/react/docs/apps/layouts/force-directed","lib":"react","topic":"apps"},"docs/apps/layouts/grid.md":{"title":"Grid","body":"# Grid Layout\n\nThis layout arranges elements into a grid. If you do not provide hints, the number of rows and columns is calculated such that the two values are as close to equal as possible. For instance, this dataset has 11 nodes, and is rendered with 3 rows of 3 columns, with the last row having 2 columns.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { GridLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: GridLayout.type\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n### Fixed column/row count[](#fixed-columnrow-count)\n\nYou can fix the number of columns/rows via the `columns` or `rows` option - here we display the same dataset but with 2 columns.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { GridLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: GridLayout.type,\n options: {\n columns: 2\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nnote\n\nIf you supply a fixed value for `columns` and for `rows`, the layout will only honour the `columns` value.\n\n### Sorting entries[](#sorting-entries)\n\nBy default, the order in which entries are placed into the grid depends on the order they are returned from the data source. You can provide a `sort` function to the grid layout to specify an order:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { GridLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: GridLayout.type,\n options: {\n sort: (a,b) => parseInt(b.id, 10) - parseInt(a.id, 10)\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nIn this example we sort based on reverse order of the node ids, so we see node `11` placed first:\n\nThe `sort` function receives two arguments, `a` and `b`, which are either `Node` or `Group` objects, and it should return a number indicating their relative order, just like a standard JavaScript sort function.\n\n### Parameters[](#parameters)\n\nGridLayoutParameters\n\nOptions for the GridLayout.\n\n| Name | Type | Description |\n| -------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| columns? | number | Optional fixed number of columns. By default this is set to -1 - meaning not fixed - which will result in the layout making its best effort at drawing a grid of equal width and height |\n| height? | number | Optional fixed height for the layout. |\n| horizontalAlignment? | [GridLayoutHorizontalAlignment]() | Optional alignment for horizontal placement in cells. Defaults to center. |\n| locationFunction? | [LocationFunction]() | Optional function that, given some vertex, can provide the x/y location of the vertex on the canvas |\n| orientation? | [GridLayoutOrientation]() | Whether to lay out items row first or column first. Additionally, this setting will determine where any extra items are placed if the dataset does not conform to a grid of equal width and height |\n| padding? | [PointXY]() | Optional padding to put around the elements. |\n| rows? | number | Optional fixed number of rows. By default this is set to -1 - meaning not fixed - which will result in the layout making its best effort at drawing a grid of equal width and height. |\n| sort? | (a:[Node]() \\| [Group](), b:[Node]() \\| [Group]()) => number | Optional sort function to run before layout. |\n| verticalAlignment? | [GridLayoutVerticalAlignment]() | Optional alignment for vertical placement in cells. Defaults to center. |\n| width? | number | Optional fixed width for the layout. |","url":"https://visuallyjs.com/react/docs/apps/layouts/grid","lib":"react","topic":"apps"},"docs/apps/layouts/hierarchy.md":{"title":"Hierarchy","body":"# Hierarchy Layout\n\nThe Hierarchy layout positions vertices in a hierarchy, oriented either vertically or horizontally, following a slightly modified version of the 'Sugiyama' method.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { HierarchyLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: HierarchyLayout.type\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n***\n\n### Orientation[](#orientation)\n\nThe layout at the top of this page shows the `horizontal` orientation, which is the default. Here we show the same dataset in the `vertical` orientation:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { HierarchyLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: HierarchyLayout.type,\n options: {\n axis: \"vertical\"\n }\n },\n defaults: {\n anchors: [\n \"Right\",\n \"Left\"\n ]\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n***\n\n### Placement Strategy[](#placement-strategy)\n\nYou can use a few different \"placement strategies\" with the Hierarchy layout. By default, the child elements of some parent are positioned with respect to the center of their parent element (you can see this in the layouts above). This behaviour corresponds to a `placementStrategy` of `parent`.\n\nYou can, instead, instruct the layout to position elements with respect to the layout's main axis, should you wish to, using a `placementStrategy` of `center`, `start` or `end`.\n\nHere we see `placementStrategy:'center'` in operation - each layer is positioned such that its center point lies on the main axis of the layout:\n\n##### Hierarchy layout with placementStrategy<!-- -->:center[](#hierarchy-layout-with-placementstrategy)\n\nIn the next two examples we use `start` and `end`. Note how these roughly correlate to the way `flex-start` and `flex-end` function in a flex layout.\n\n##### Hierarchy layout with placementStrategy<!-- -->:start[](#hierarchy-layout-with-placementstrategy-1)\n\n##### Hierarchy layout with placementStrategy<!-- -->:end[](#hierarchy-layout-with-placementstrategy-2)\n\n### Alignment[](#alignment)\n\nA separate, but related, concept to the `placementStrategy` is that of `alignment`, which instructs the layout how to place child elements with respect to their parent element, and is only used when `placementStrategy` is set to `parent`. Here's the first layout from above, but with `alignment:'start'` set:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { HierarchyLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: HierarchyLayout.type,\n options: {\n alignment: \"start\"\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n### Determining the root node(s)[](#determining-the-root-nodes)\n\nIn the Hierarchy layout there are always one or more \"root\" vertices, which are vertices that are to be placed at the root of the hierarchy. The layout calculates these by looking for vertices that are not the target of any edges. If it finds none, an arbitrary vertex will be used as the initial root. From each root, edges are followed and connected vertices are placed, until there are no more edges to follow. There may be more than one root in a given dataset.\n\nYou can specify a root node by setting it as the `rootNode`:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { HierarchyLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: HierarchyLayout.type,\n options: {\n rootNode: rootNode,\n axis: \"horizontal\"\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nNote that we said \"a\" root node, and not \"the\" root node, as after placing every node connected to your nominated root, the layout will continue to place other root nodes that it has found.\n\n### Edge routing[](#edge-routing)\n\nThe Hierarchy layout can generate routing information for edges, via the `generateRouting` flag:\n\nTo setup edge routing you need 3 things:\n\n* You must be using a `Hierarchy` layout and you need to have `generateRouting:true` in the layout options:\n\n* You must be using the [Straight](/react/docs/apps/edges/connectors.md#straight) connector type. This is the default connector type so if you haven't specifically set a connector anywhere you'll be using this.\n\n* You need to enable the [edge routing plugin](/react/docs/apps/plugins/edge-routing.md)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { HierarchyLayout, EdgeRoutingPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: HierarchyLayout.type,\n options: {\n generateRouting: true\n }\n },\n plugins: [\n {\n type: EdgeRoutingPlugin.type\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nA deeper discussion of edge routing can be on the [edge routing plugin page](/react/docs/apps/plugins/edge-routing.md), but to whet your appetite, here's the Hierarchy layout configured to use [orthogonal routing](/react/docs/apps/plugins/edge-routing.md#orthogonal):\n\n***\n\n### Parameters[](#parameters)\n\nHierarchyLayoutParameters\n\nOptional parameters for a Hierarchy layout\n\n| Name | Type | Description |\n| -------------------------------- | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| absoluteBacked? | boolean | Defaults to false. If true, then the layout will use any position values found in the data for a given vertex. |\n| alignment? | [HierarchyLayoutAlignment]() | Optional, defaults to `HierarchyLayoutAlignmentValues.center`. Instructs the layout how to place child nodes with respect to their parent nodes. By default, a group of child nodes is centered on its parent. The layout also supports \"start\" and \"end\" for this value, which work in much the same way as \"flex-start\" and \"flex-end\" do in CSS: for a layout with the root at the top of the tree and the child nodes underneath, a value of \"start\" for align would cause the first child of the root to be placed immediately under the root, with its first child immediately underneath, etc. The remainder of the content would fan out to the right. This option also works in conjunction with invert and axis<!-- -->:HierarchyLayoutAxisValues<!-- -->.vertical. |\n| axis? | [HierarchyLayoutAxis]() | Either `horizontal` (the default, groups of child vertices are laid out in rows) or `vertical` (groups of child vertices are laid out in columns) |\n| gatherUnattachedRoots? | boolean | If true root nodes that do not have children will be positioned adjacent to the last root node that does have children. When false (which is the default), unattached roots are spaced apart so that they do not overlap any child trees. |\n| generateRouting? | boolean | Defaults to false. If true, the layout generates routing information for the channels between layers and edge nodes, and for edge routing. |\n| getRootNode? | () => [AbstractEdgeTerminus]() | Optional function you can provide that will dynamically be invoked to get the root node to use. |\n| height? | number | Optional fixed height for the layout. |\n| invert? | boolean | If true, the layout will be inverted in its perpendicular axis. For instance, if `axis` is \"horizontal\" and `invert` is true, the root nodes of the layout will be placed at the bottom of the layout, and their children will be placed above them. |\n| leavesAtBottom? | boolean | If true, all of the leaf nodes will be placed at the bottom of the layout (or at the right hand side if the axis is `vertical`) |\n| locationFunction? | [LocationFunction]() | Optional function that, given some vertex, can provide the x/y location of the vertex on the canvas |\n| maxIterations? | number | Maximum number of iterations to run. Defaults to 24. |\n| maxIterationsWithoutImprovement? | number | Number of iterations to try rearranging the graph without an improvement in legibility before accepting the current state. Defaults to 2. |\n| padding? | [PointXY]() | Optional padding to put around the elements. |\n| placementStrategy? | PlacementStageStrategy | The strategy to use when placing vertices. Default is 'center', meaning every row is centered around the axis orthogonal to the axis in which the vertices are laid out. |\n| rootNode? | any | Optional node to use as the root. If this is not provided the layout calculates the best candidate based upon incoming and outgoing edges for each vertex. |\n| width? | number | Optional fixed width for the layout. |","url":"https://visuallyjs.com/react/docs/apps/layouts/hierarchy","lib":"react","topic":"apps"},"docs/apps/layouts/overview.md":{"title":"Overview","body":"# Layouts\n\nA core piece of functionality offered by the VisuallyJs UI is support for layouts - a means to control the positioning of the vertices in your application.\n\nThe default layout used is the [Absolute layout](/react/docs/apps/layouts/absolute.md).\n\n## Applying a layout[](#applying-a-layout)\n\nTo apply a layout to an app, supply the spec for the layout in your render options:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ForceDirectedLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: ForceDirectedLayout.type,\n options: {\n spacing: 150\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nThe contents of `options` depend on the specific layout you are configuring.\n\n<!-- -->\n\n## Available layouts[](#available-layouts)\n\nThe available layouts are:\n\n* [Absolute](/react/docs/apps/layouts/absolute.md) This layout positions vertices dependent on values in each vertex's backing data. For many applications in which the position of vertices is under the control of a user, this layout is a good choice. It can be combined with other layouts, such as the ForceDirected layout, to implement a scheme whereby vertices untouched by a user are placed automatically and vertices touched by a user are placed wherever the user chose.\n\n* [ForceDirected](/react/docs/apps/layouts/force-directed.md) Positions vertices in an optimum position relative to vertices to which they are connected. This layout is an extension of the Absolute layout, which can be instructed to honour user-supplied values for vertices if present.\n\n* [Balloon](/react/docs/apps/layouts/balloon.md) This layout groups vertices into clusters. This is a useful layout for certain types of unstructured data such as mind maps.\n\n* [Hierarchy](/react/docs/apps/layouts/hierarchy.md) Positions vertices in a hierarchy, oriented either vertically or horizontally. The classic use cases for this layout are such things as a family tree or an org chart.\n\n* [Circular](/react/docs/apps/layouts/circular.md) Arranges vertices instance into a circle, with a radius sufficiently large that no two vertices overlap.\n\n* [Grid](/react/docs/apps/layouts/grid.md) Arranges vertices into a grid, optionally with restrictions placed on the number of columns or rows.\n\n* [Column](/react/docs/apps/layouts/column.md) Arranges vertices into a column - a specialized instance of the Grid layout.\n\n* [Row](/react/docs/apps/layouts/row.md) Arranges vertices into a row - a specialized instance of the Grid layout.","url":"https://visuallyjs.com/react/docs/apps/layouts/overview","lib":"react","topic":"apps"},"docs/apps/layouts/row.md":{"title":"Row","body":"# Row Layout\n\nThis is a specialized instance of `GridLayout` with the number of rows fixed to 1.\n\n### Example[](#example)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { RowLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: RowLayout.type\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n### Sorting entries[](#sorting-entries)\n\nYou can provide a `sort` function to the row layout to specify an order in which entries are placed. The layout will then arrange them in the specified order from left to right.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { RowLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: RowLayout.type,\n options: {\n sort: (a,b) => parseInt(b.id, 10) - parseInt(a.id, 10)\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nThe `sort` function receives two arguments, `a` and `b`, which are either `Node` or `Group` objects, and it should return a number indicating their relative order.","url":"https://visuallyjs.com/react/docs/apps/layouts/row","lib":"react","topic":"apps"},"docs/apps/load-save-export/model-load-save.md":{"title":"Model Load Save","body":"# Model Data\n\n## Loading data into the model[](#loading-data-into-the-model)\n\nTo load data into the model, use the `load` method on an instance of `VisuallyJs`. You can load data from a remote source - using ajax - or directly from an object in memory.\n\ntip\n\nFor loading data it's usually more simple to load it straight into the `SurfaceComponent` (either as JS object or from a URL), rather than have to setup some code to run on load. See the [UI Load & Save](/react/docs/apps/load-save-export/ui-load-save.md) docs for details.\n\n### Loading data via ajax[](#loading-data-via-ajax)\n\n```jsx\nimport {useRef, useEffect} from \"react\"\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n \n const surfaceRef = useRef(null)\n const initialized = useRef(false)\n\n useEffect(() => {\n if(!initialized.current) {\n initialized.current = true\n const surface = surfaceRef.current.surface \n const model = surface.model\n \n model.load({\n type:\"json\",\n url:\"someUrl.json\",\n onload:() => { \n // called after the data has loaded.\t\n }\n })\n } \n \n })\n return <SurfaceComponent/>\n}\n\n```\n\n#### Specifying HTTP Headers[](#specifying-http-headers)\n\nBy default, VisuallyJs will set the HTTP header `Accept` to the value `application/json`. You can override this by providing your own HTTP headers in the `load` call:\n\n```jsx\nimport {useRef, useEffect} from \"react\"\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n \n const surfaceRef = useRef(null)\n const initialized = useRef(false)\n\n useEffect(() => {\n if(!initialized.current) {\n initialized.current = true\n const surface = surfaceRef.current.surface \n const model = surface.model\n \n model.load({\n type:\"xml\",\n url:\"someUrl.xml\",\n headers:{\n Accept:\"text/xml\",\n X-My-Header:\"FOO\"\n },\n onload:() => { \n // called after the data has loaded.\t\n }\n })\n } \n \n })\n return <SurfaceComponent/>\n}\n\n```\n\n*Note*: if you provide `headers` you must set an `Accept` header (if you want it to be set), because VisuallyJs will not write a value for `Accept` into an HTTP headers object that does not have it.\n\n### Loading data from memory[](#loading-data-from-memory)\n\n```jsx\nimport {useRef, useEffect} from \"react\"\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n \n const surfaceRef = useRef(null)\n const initialized = useRef(false)\n\n useEffect(() => {\n if(!initialized.current) {\n initialized.current = true\n const surface = surfaceRef.current.surface \n const model = surface.model\n \n model.load({\n data:{\n nodes:[\n { id:\"foo\", value1:\"foo\", value2:34 },\n { id:\"bar\", value1:\"bar\", value2:24 }\n ],\n edges:[\n { source:\"foo\", target:\"bar\", data: { value1:89 } }\n ]\n })\n } \n \n })\n return <SurfaceComponent/>\n}\n\n```\n\ncaution\n\nThe load method performs an incremental load: the existing data is not cleared when you call `load`. If you wish to replace the entire dataset, first call the `clear()` method. If you have not cleared the data when you reload some dataset, VisuallyJs will not load new items if an item of the given type with that id already exists, which is generally the case for nodes/groups, but often edges are not loaded with their own ids, and therefore on reload will be duplicated.\n\n### Decorators[](#decorators)\n\nThe default JSON parser (`json`) accepts an optional `parameters` object that allows you to specify \"decorator\" functions. These functions provide a way to modify or augment the data for nodes, groups, and edges as they are being loaded, before they are officially added to the model.\n\n#### Specifying Decorators[](#specifying-decorators)\n\nYou can pass these decorators within the `parameters` argument when calling the load/parse method:\n\n* **`nodeDecorator(data: ObjectData)`**: Called for every node. It receives the raw node data.\n* **`groupDecorator(data: ObjectData)`**: Called for every group. It receives the raw group data.\n* **`edgeDecorator(data: ObjectData, sourceData: ObjectData, targetData: ObjectData)`**: Called for every edge. It receives the edge's data payload along with the resolved data objects for both the source and the target.\n\n#### Example Usage[](#example-usage)\n\n## Saving the model[](#saving-the-model)\n\nYou can either tell the VisuallyJs model to save data on demand - using the `save` function - or configure it to save automatically, whenever it detects that the data model has changed.\n\nVisuallyJs uses an HTTP POST to save data. You cannot configure it to use anything other than a POST. If you absolutely do not want to use POST, then you can use the method described at the bottom of this page to export the data, then save it yourself.\n\n### Save on demand[](#save-on-demand)\n\n```javascript\nmodel.save({\n type:\"json\",\n url:\"http://foo.com\",\n parameters:{ \"foo\":1, \"bar\":2 },\n success:(responseText) => { },\n error:(responseText, responseStatus) => { },\n headers:{ \"Optional\":\"Http Headers\"}\n})\n\n```\n\nHere, as with the `load` function, the type of the dataset is assumed to be VisuallyJs's default JSON syntax (see below for an example of how to write a custom exporter).\n\nThe allowed parameters are:\n\n* **type** By default this is set to \"json\". Specifies the data type in which to format the data. This must match the name of a registered exporter.\n* **url** Required. URL to POST data to.\n* **parameters** Optional parameters to pass to the exporter. If you write a custom exporter you may wish to use this.\n* **success** Optional callback to execute once the data has saved successfully. The server response is provided to this callback, but note that it is provided as text: if your server responds with JSON you should use `JSON.parse(responseText)` to get the response as JSON.\n* **error** Optional callback to execute if there was an error saving the data. Both the server response and the response status code are passed to this callback.\n* **headers** Optional headers to set on the ajax request. By default, VisuallyJs will send a `Content-Type:\"application/json\"` header. If you provide your own headers this header will continue to be sent, unless of course you override it.\n\n### Save Automatically[](#save-automatically)\n\nYou can configure VisuallyJs to save automatically, either with its own ajax call, or by invoking a function you supply. The bare minimum setup requires the `autoSave` flag to be set, and then either a `saveUrl`:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n autoSave: true,\n saveUrl: \"http://foo.com\"\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n...or an `autoSaveHandler` function for VisuallyJs to invoke:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n autoSave: true,\n autoSaveHandler: (model) => {\n\n }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n#### Methods that invoke a save[](#methods-that-invoke-a-save)\n\nVisuallyJs will save the dataset whenever one of these methods is called:\n\n* `addNode`\n* `removeNode`\n* `addNodes`\n* `addGroup`\n* `removeGroup`\n* `addEdge`\n* `removeEdge`\n* `addPort`\n* `addNewPort`\n* `removePort`\n* `updateNode`\n* `updateGroup`\n* `updateEdge`\n* `updatePort`\n* `addToGroup`\n* `removeFromGroup`\n\nnote\n\nThe dataset will *not* be saved automatically when you call the `clear` method.\n\n#### Debouncing save operations[](#debouncing-save-operations)\n\nIf you find that having this switched on is causing too much network traffic due to rapid changes in the dataset, you can instruct VisuallyJs to \"debounce\" these requests - limit the rate at which save requests will be made, via the `autoSaveDebounceTimeout` constructor parameter:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n autoSave: true,\n saveUrl: \"http://foo.com\",\n autoSaveDebounceTimeout: 1000\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\nThis is a value in milliseconds.\n\n#### Autosave Callbacks[](#autosave-callbacks)\n\nYou can supply callbacks for auto save success and error, as well as functions to run before and after an auto save operation. These functions are not invoked if you supply an `autoSaveHandler`, since VisuallyJs in that case does not perform the save operation itself.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n autoSave: true,\n saveUrl: \"http://foo.com\",\n onAutoSaveError: (msg) => { ... },\n onAutoSaveSuccess: (response) => { ... },\n onBeforeAutoSave: () => { ... },\n onAfterAutoSave: () => { ... }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n#### Autosave HTTP Headers[](#autosave-http-headers)\n\nTo set headers as discussed [below](#setting-http-headers) when auto-saving, provide a `saveHeaders` object in VisuallyJs's model options.\n\nThese are only used when you supply a `saveUrl`. If you supply an `autoSaveHandler` these are ignored.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n autoSave: true,\n saveUrl: \"http://foo.com\",\n saveHeaders: {\n X-My-Header: \"My Header Value\"\n }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n#### Content Type[](#content-type)\n\nVisuallyJs will, by default, set the `Content-Type` header on a save POST to:\n\n```javascript\nContent-Type:\"application/json\"\n\n```\n\n#### Specifying HTTP Headers[](#specifying-http-headers-1)\n\nYou can set arbitrary headers (including to override `Content-Type`) via the `headers` parameter on a `save` call:\n\n```javascript\nmodel.save({\n url:\"http://save-data.com\",\n headers:{\n \"X-My-Header\":\"headerValue\"\n }\n});\n\n```\n\n## Exporting[](#exporting)\n\nIf you want to just export the data, you can do so from a `VisuallyJsModel` instance for the model data:\n\n```javascript\nconst data = model.exportData();\n\n```\n\nThis will assume you want the data in the default JSON syntax. If you have a custom exporter you wish to use, you can specify that using the `type` parameter. You can also pass in parameters for the export:\n\n```javascript\nconst data = model.exportData({\n type:\"myFormat\",\n parameters:{\n importantNumber:34,\n somePrefix:\"foo-\"\n }\n})\n\n```","url":"https://visuallyjs.com/react/docs/apps/load-save-export/model-load-save","lib":"react","topic":"apps"},"docs/apps/load-save-export/overview.md":{"title":"Overview","body":"# Loading and saving\n\nGetting data into and out of VisuallyJs is easy. There are a few different approaches you can use:\n\n* You can load/save to/from the underlying model directly, either using JS objects or via ajax. When you do this the dataset consists of just the nodes, edges and groups in your model, without any UI specific information such as the current state of the pan, zoom etc. Loading and saving to/from the model is discussed [here](/react/docs/apps/load-save-export/model-load-save.md)\n\n* You can supply an initial dataset or URL to load data into certain UI components - read more here]\\(component-load)\n\n* The `Surface` component offers `exportData`, `load` and `save` methods which export/load/save the dataset as well as the pan/zoom of the Surface, plus any context for attached inspectors.\n\n## Appending Data[](#appending-data)\n\nData can be appended via the `load` method, since it does not cause the underlying Graph to be cleared.\n\n***\n\n## Data Formats[](#data-formats)\n\nVisuallyJs ships with support for two JSON formats for loading and saving data. Should you need to, you can create custom load/save handlers for your own syntax.\n\n### Graph JSON Syntax[](#graph-json-syntax)\n\nThis JSON syntax - the default - consists of a JSON object with an array for `nodes`, `groups` and `edges`. All of these are optional, but of course if you declare an edge then the nodes/groups for that edge must be present in the dataset.\n\n#### Example: Nodes and Edges[](#example-nodes-and-edges)\n\n```javascript\n{\n \"nodes\": [\n { id:\"1\", name:\"foo\" },\n { id:\"2\", name:\"baz\" },\n { id:\"3\", name:\"foo\" },\n { id:\"4\", name:\"ding\" },\n { id:\"5\", name:\"dong\" },\n { id:\"6\", name:\"ping\" },\n { id:\"7\", name:\"pong\" }\n ],\n \"edges\":[\n { source:\"1\", target:\"2\" },\n { source:\"1\", target:\"3\" },\n { source:\"2\", target:\"4\" },\n { source:\"2\", target:\"5\" },\n { source:\"3\", target:\"6\" },\n { source:\"3\", target:\"7\" } \n ]\n}\n\n```\n\n#### Example: Groups, Nodes and Edges[](#example-groups-nodes-and-edges)\n\n```javascript\n{\n \"groups\":[\n { \"id\":\"group1\", name:\"Group One\" },\n { \"id\":\"group2\", name:\"Group Two\" }\n ],\n \"nodes\": [\n { id:\"1\", name:\"foo\", group:\"group1\" },\n { id:\"2\", name:\"baz\" },\n { id:\"3\", name:\"foo\" },\n { id:\"4\", name:\"ding\", group:\"group2\" },\n { id:\"5\", name:\"dong\", group:\"group2\" },\n { id:\"6\", name:\"ping\" },\n { id:\"7\", name:\"pong\" }\n ],\n \"edges\":[\n { source:\"1\", target:\"2\" },\n { source:\"1\", target:\"3\" },\n { source:\"2\", target:\"4\" },\n { source:\"2\", target:\"5\" },\n { source:\"3\", target:\"6\" },\n { source:\"3\", target:\"7\" } \n ]\n}\n\n```\n\n#### Loading Graph JSON[](#loading-graph-json)\n\n```javascript\nmodel.load({\n type:\"json\",\n url:\"http://mydata.com?xyz\"\n});\n\n```\n\nSince Graph JSON is the default syntax, you can in fact omit the `type` parameter in the above example:\n\n```javascript\nmodel.load({\n url:\"http://mydata.com?xyz\"\n});\n\n```\n\n### Hierarchical JSON Syntax[](#hierarchical-json-syntax)\n\nThis JSON syntax represents hierarchical data, in which every node may have zero or more child nodes. It is assumed that there is an edge between a node and each of its child nodes. Note that the `children` member on each node's data is optional.\n\n```javascript\n{\n \"id\":\"foo\",\n \"name\":\"FOO!\",\n \"children\":[\n {\n \"id\":\"bar\",\n \"name\":\"BAR!\",\n \"children\":[\n {\n \"id\":\"baz\",\n \"name\":\"BAZ!\"\n }\n ]\n },\n {\n \"id\":\"qux\",\n \"name\":\"QUX!\"\n }\n ]\n}\n\n```\n\n#### Loading Hierarchical JSON[](#loading-hierarchical-json)\n\n```javascript\nmodel.load({\n type:\"hierarchical-json\",\n url:\"http://myhierarchicaldata.com?xyz\"\n});\n\n```\n\n***","url":"https://visuallyjs.com/react/docs/apps/load-save-export/overview","lib":"react","topic":"apps"},"docs/apps/load-save-export/ui-load-save.md":{"title":"Ui Load Save","body":"# UI Data & State","url":"https://visuallyjs.com/react/docs/apps/load-save-export/ui-load-save","lib":"react","topic":"apps"},"docs/apps/magnetizer.md":{"title":"Magnetizer","body":"# Magnetizer\n\nThe magnetizer is a useful piece of VisuallyJs's UI functionality, providing a means to nudge elements around in your UI so that things don't overlap. There are a few different ways to use the magnetizer - you can instruct your layout to apply the magnetizer after the layout is run, or you can use it to manage element dragging. You can also call it programmatically on an ad-hoc basis.\n\n## Layout magnetization[](#layout-magnetization)\n\nAll layouts support the option of switching on magnetization, which is invoked after the layout runs. For some layouts this ability is theoretically of no use, for instance the [Force directed layout](/react/docs/apps/layouts/force-directed.md), because in that layout the elements in your UI have already been moved apart by the layout itself. But if you're using, for instance, the [Absolute layout](/react/docs/apps/layouts/absolute.md), then there is a chance one or more elements are overlapping.\n\nYou can switch on magnetization in a layout by setting it as a layout option:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { AbsoluteLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: AbsoluteLayout.type,\n options: {\n magnetizer: true\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nEach time the layout runs, the magnetizer will be run afterwards.\n\n## Magnetizing after dragging[](#magnetizing-after-dragging)\n\nYou can instruct the magnetizer to run after some vertex has been dragged:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n magnetizer: {\n afterDrag: true\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nTry dragging one element on top of another element in the canvas below. At the end of the drag the magnetizer will run. The element you just dragged will be the \"focus\", and will not move from where you placed it:\n\n**********\n\n#### Repositioning the dragged element[](#repositioning-the-dragged-element)\n\nAs mentioned above, the dragged element will remain stationary if the magnetize is run after a drag. You can change that behaviour, though:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n magnetizer: {\n afterDrag: true,\n repositionDraggedElement: true\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nTry dragging one element on top of another element in the canvas below. At the end of the drag the magnetizer will run, but this time the dragged element will be the one that is moved if there is any overlap:\n\n**********\n\n## Magnetizing while dragging[](#magnetizing-while-dragging)\n\nYou can run the magnetizer while dragging an element by using the `constant` flag:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n magnetizer: {\n constant: true\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nTry dragging node 1 through the gap between nodes 2 and 3 in this canvas - they'll move out of the way as node 1 moves through, and then spring back. Once you release the mouse button, the position of each node is fixed.\n\n**********\n\nThe vertices spring back to their original position in the canvas above because when you switch on `constant` mode, the UI automatically also switches on `trackback`. You can switch off trackback if you wish - see the section [below](#trackback).\n\ntip\n\nIf you have `trackback` switched on, your users can switch if off temporarily while dragging by holding down the `shift` key.\n\n## Trackback[](#trackback)\n\nTo switch off trackback:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n magnetizer: {\n constant: true,\n trackback: false\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nTry dragging node 1 through the gap between nodes 2 and 3 in this canvas - they'll move out of the way as node 1 moves through, but this time they won't spring back:\n\n**********\n\ntip\n\nIf you have switched off `trackback` your users can still switch it on temporarily, by holding down the `shift` key while dragging.\n\n## Adhoc magnetization[](#adhoc-magnetization)\n\nYou can instruct the Surface widget to run the magnetizer over the entire contents of the UI at any time via the `magnetize` method:\n\n<!-- -->\n\nBy default, the magnetizer will use the computed center of all the elements as its origin, and all elements will be pushed away from that point, as in this call:\n\n```javascript\nsurface.magnetize()\n\n```\n\nAn alternative, though, is to supply a vertex that you wish to act as the origin, and which you do not wish to move:\n\n```javascript\nsurface.magnetize(\"nodeId\")\n\n```\n\nHere we passed the ID of some node, but we could also have passed the node itself. The signature of the `magnetize` method is:\n\n```text\nmagnetize(focus?:string|Vertex):void\n\n```\n\n## Setting a vertex position and magnetizing[](#setting-a-vertex-position-and-magnetizing)\n\nAnother feature the Surface offers is the ability to set the position of some element and to immediately magnetize the UI after setting the element's position, using that element as the focus:\n\n```javascript\nsetMagnetizedPosition(element:string|Vertex, x:number, y:number):void\n\n```\n\nThis is effectively the same as:\n\n```javascript\nsurface.setPosition(element, x, y)\nsurface.magnetize(element)\n\n```\n\nThis operation is wrapped in a transaction on the model so if undo is called then every element affected by the magnetize is relocated to its original position.\n\n## Gathering Elements[](#gathering-elements)\n\nThe magnetizer can also gather elements to bring them closer together around some origin. Internally this works by pulling each affected element in on its radial from the origin to the element's center, and then running the magnetizer to nudge everything back out so that nothing overlaps.\n\n```text\ngather(focus?:string|Vertex):void\n\n```\n\nTo gather all the elements in the UI around their computed center, don't supply a focus element:\n\n```text\nsurface.gather()\n\n```\n\nTo gather all the elements in the UI around some focus element:\n\n```text\nsurface.gather(idOrVertex)\n\n```\n\nThis code sets up a surface so that when you click on one of the nodes, the other nodes in the surface are gathered around it:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n zoomToFit: true\n}\n\n const viewOptions = {\n nodes: {\n default: {\n events: {\n tap: (p) => {\n p.ui.gather(p.obj)\n }\n }\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions} viewOptions={viewOptions}/>\n}\n\n```\n\nTry clicking one of the nodes in the canvas below. You'll see the other two nodes are gathered in to it. Note that nodes are gathered along a path from the current location to the focus node, and so other nodes may still obstruct their travel. A good example of that is if you click node 1: node 2 is pulled in close to node 1, but node 3 can only travel until it is blocked by node 2.\n\n**********\n\n## All options[](#all-options)\n\nThe Surface offers many options for configuring the magnetizer. The full list is:\n\nMagnetizeOptions\n\nOptions for the magnetize functionality of the UI.\n\n| Name | Type | Description |\n| ------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| afterDrag? | boolean | If true, magnetizer will be run after a vertex is dragged. Defaults to false. |\n| afterGroupCollapse? | boolean | Defaults to false. Indicates the UI should gather nodes around a newly collapsed group |\n| afterGroupExpand? | boolean | Defaults to false. Indicates the UI should magnetize nodes around a newly expanded group |\n| afterGroupGrow? | boolean | Defaults to false. Indicates the UI should magnetize/gather nodes around a newly resized group if the group size was enlarged. |\n| afterGroupResize? | boolean | Defaults to false. Indicates the surface should magnetize/gather nodes around a newly resized group, regardless of whether the group size grew or if it shrunk. This flag is the same as setting `afterGroupShrink` and `afterGroupGrow` |\n| afterGroupShrink? | boolean | Defaults to false. Indicates the UI should magnetize/gather nodes around a newly resized group if the group size was reduced. |\n| afterLayout? | boolean | If true, magnetizer will be run after the layout is run. |\n| constant? | boolean | If true, magnetizer will be run constantly as a vertex is being dragged, pushing other vertices out of the way of the vertex that is being dragged. Defaults to false. By default, `constant` magnetize will also set `trackback:true`, but you can disable that behaviour by setting `trackback:false`. |\n| constrainToViewport? | boolean | If true, vertices moved by the magnetizer will be constrained to move within the visible viewport, which is a function of the current zoom/pan of the UI. Otherwise, vertices will be able to be pushed out of the visible viewport. |\n| padding? | [PointXY]() | How much padding to leave between elements. Defaults to 100 pixels in each axis. |\n| repositionDraggedElement? | boolean | If true, and `afterDrag` is true, when the magnetizer is run after a drag it will be the recently dragged element that moves in precedence to the other elements. By default, the recently dragged element is *not* moved by the magnetize operation - it stays where you dragged it. |\n| trackback? | boolean | Used in conjunction with `constant`: attempts to track any moved elements to their original positions (or as close as possible) once the path is clear, each time the magnetizer runs a sweep. Defaults to true (when `constant` is true). |\n| trackbackThreshold? | number | When in `constant` mode and `trackback` is set, this value specifies a threshold for elements that have been pushed from their original position. Beyond this threshold, the magnetizer will no longer attempt to track an element back. This can be useful in certain situations where the user does want to move an element by pushing it via the magnetizer |","url":"https://visuallyjs.com/react/docs/apps/magnetizer","lib":"react","topic":"apps"},"docs/apps/model/add-remove-update.md":{"title":"Add Remove Update","body":"# Adding, removing and updating data\n\nThere is a full API available for you to manage your data model programmatically. Broadly, the operations on the data model can be broken up into three main categories:\n\n* [Adding model objects](#adding-model-objects)\n* [Deleting model objects](#deleting)\n* [Updating model objects](#updating)\n\nThere are also some additional operations available on groups - the addition/removal of child vertices.\n\nWhenever an operation occurs on the model, VisuallyJs advises all of its attached renders to update themselves accordingly.\n\ninfo\n\nThe methods discussed on this page are on the model - which is an instance of the class [BrowserUIReactModel](). To read about how to access the model, [see the model overview](/react/docs/apps/model/overview.md#accessing-the-model).\n\n## Adding model objects[](#adding-model-objects)\n\n### Nodes[](#nodes)\n\nThere are two ways to add a node, either directly via the `addNode` method, whose signature is:\n\n```typescript\naddNode(data: ObjectData, eventInfo?: any): Node\n\n```\n\nfor example:\n\n```javascript\nmodel.addNode({id:\"1\", foo:\"a value\", type:\"someType\"})\n\n```\n\nor, if you have a [node factory](/react/docs/apps/model/overview.md#node-factory) setup on your instance, you can add a node by invoking the factory, via the `addFactoryNode` method, whose signature is:\n\n```javascript\naddFactoryNode(type: string, data?: ObjectData, continueCallback?: Function): void\n\n```\n\nConsider that you have a node factory that does a fetch to some endpoint, providing the type for the new node, and the endpoint responds with the data for your new node:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n nodeFactory: (type, data, callback, evt, native) =>{\n fetch({type:'post', body:{type}}).then(v => callback(v))\n }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\nYou can invoke the factory in a few ways. Firstly you can invoke the factory without supplying any data of your own:\n\n```javascript\nmodel.addFactoryNode(\"someType\");\n\n```\n\nIt is possible to also provide some seed data for the new node, which will be passed in to the node factory as `data`:\n\n```javascript\nmodel.addFactoryNode(\"someType\", { foo:\"bar\" });\n\n```\n\nAnd also you can provide a callback which will be run after the node factory has finished adding the new node:\n\n```typescript\nmodel.addFactoryNode(\"someType\", { foo:\"bar\" }, (newNode:Node) => {\n // newNode is your new node.\n});\n\n```\n\n### Groups[](#groups)\n\nAs with nodes, you can add a group directly using `addGroup`, whose signature is:\n\n```typescript\naddGroup(data: ObjectData, eventInfo?: any): Group\n\n```\n\nfor example:\n\n```javascript\nmodel.addGroup({id:\"1\", foo:\"a value\", type:\"someType\"})\n\n```\n\nor you can setup a [group factory](/react/docs/apps/model/overview.md#group-factory) and use the `addFactoryGroup` method, whose signature is:\n\n```typescript\naddFactoryGroup(type: string, data?: ObjectData, continueCallback?: Function): void\n\n```\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n groupFactory: (type, data, callback, evt, native) {\n fetch({type:'post', body:{type}}).then(v => callback(v))\n }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\nYou can call `addFactoryGroup` just by supplying the desired type for your new group:\n\n```javascript\nmodel.addFactoryGroup(\"someType\");\n\n```\n\nOr by supplying type and initial data:\n\n```javascript\nmodel.addFactoryGroup(\"someType\", { foo:\"bar\" })\n\n```\n\nOr by supplying type, data and a callback:\n\n```javascript\nmodel.addFactoryGroup(\"someType\", { foo:\"bar\" }, (newGroup:Group) => {\n // newGroup is your new group\n});\n\n```\n\n### Ports[](#ports)\n\nPorts reside on nodes or groups, and so to add a port you have to supply the vertex you wish to add the port to. To add a port directly to a node or group you use `addPort`:\n\n```javascript\naddPort(vertex: string | Node | Group, data: ObjectData): Port\n\n```\n\nSo, for instance:\n\n```javascript\nconst node = model.addNode({id:\"one\", type:\"someType\"})\nconst port = model.addPort(node, {id:\"p1\", type:\"somePortType\"})\n\n```\n\nThe equivalent to the `addFactoryNode` and `addFactoryGroup` method for ports is:\n\n```javascript\naddNewPort(obj: string | Node | Group, type: string, portData?: ObjectData)\n\n```\n\n`addNewPort` will invoke VisuallyJs's [port factory](/react/docs/apps/model/overview.md#port-factory) and then call `addPort` with the port factory's result.\n\nAs an example, this is the port factory from an early version of our Schema Builder starter app, in which table columns are represented as ports on table nodes:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n portFactory: (node, type, data, callback) => {\n let column = {\n id:data.columnName,\n name:data.columnName[0].toUpperCase() + data.columnName.slice(1), \n datatype:\\varchar\\\",\n type:\\\"column\\\"\n };\n \n // handoff the new column.\n callback(column); \n }\"\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\nnote\n\nThe `addPort` and `addNewPort` methods discussed here will add ports to model objects, but they will not necessarily update the underlying JSON dataset. It is important to be across the concepts discussed [regarding the synchronization of port data](/react/docs/apps/model/overview.md#extracting-and-synchronizing-port-data)\n\n### Edges[](#edges)\n\nYou can add an edge programmatically to the dataset via the `addEdge` method, which takes an argument of type [AddEdgeOptions]():\n\n```typescript\n\naddEdge(params: AddEdgeOptions): Edge\n\n```\n\nAdding an edge is slightly different to adding vertices, in that the backing data for an edge should be provided in a `data` object inside the payload you pass to this method. With nodes, groups and ports the backing data is at the top level.\n\nThe `source` and `target` you pass to this method can be one of three things:\n\n* an object of type `Vertex` (`Node`, `Group` or `Port`);\n* the ID of some vertex, in the case of ports this being a fully qualified port id in dotted notation;\n* a [PointXY](), defining a location on the canvas, for when you want to add an edge that is initially not connected to a source and/or target vertex.\n\nSome examples:\n\nHere we add an edge from some `Node` to a port which we specify by id. We also supply some data for the edge - in this case, a label. The resulting edge has an ID that the model assigns:\n\n```javascript\nconst edge = model.addEdge({\n source:someNode, \n target:\"someOtherNode.somePortId\", \n data:{label:\"My Edge Label\"}\n})\n\n```\n\nHere we add an edge between two vertices specified by id. We also supply some data for the edge - in this case, the edge's ID, and also a label:\n\n```javascript\nconst edge = model.addEdge({\n source:\"node1\", \n target:\"node2\", \n data:{\n label:\"Label\",\n id:\"edgeId\"\n }\n})\n\n```\n\n## Removing model objects[](#removing-model-objects)\n\n### Nodes[](#nodes-1)\n\nNodes can be removed with the `removeNode` method, whose signature is:\n\n<!-- -->\n\n```typescript\nremoveNode(node: string | Node):void\n\n```\n\nfor example:\n\n```javascript\nmodel.removeNode(\"someNodeId\")\n\n```\n\n### Groups[](#groups-1)\n\nGroups can be removed with the `removeGroup` method:\n\n```typescript\nremoveGroup(group: string | Group, removeChildren?: boolean):void\n\n```\n\nNote the `removeChildren` option to this method. By default when you remove a group its child vertices are orphaned, or if the group is itself a child of some other groups its child vertices are added to the group's parent.\n\nThis will remove a group and leave its child vertices in the dataset:\n\n```javascript\nmodel.removeGroup(\"someNodeId\")\n\n```\n\nThis will remove a group and its child vertices (and if any of those child vertices is a group, its children will be removed etc):\n\n```javascript\nmodel.removeGroup(\"someNodeId\", true)\n\n```\n\n### Ports[](#ports-1)\n\nUse the `removePort` method to remove a port from the dataset:\n\n```typescript\nremovePort(vertexOrId: string | Node | Group | Port, portId?: string): boolean\n\n```\n\nThis method can be called in a few ways.\n\n#### With full port id[](#with-full-port-id)\n\nYou can provide the full port id in dotted notation, from which VisuallyJs will resolve the node/group and the port:\n\n```javascript\nmodel.removePort(\"someNode.somePortId\")\n\n```\n\n#### With a port object[](#with-a-port-object)\n\nYou can provide a `Port` model object:\n\n```javascript\nconst port = model.addPort(someNode, { id:\"portId\", foo:\"foo\"})\n\n...\n\nmodel.removePort(port)\n\n```\n\n#### With a node/group and port id[](#with-a-nodegroup-and-port-id)\n\nLastly, you can provide the node/group that is the port's parent, and the port id:\n\n```javascript\nmodel.removePort(someNode, \"portId\")\n\n```\n\nnote\n\nWe again refer you to the documentation [regarding the synchronization of port data](/react/docs/apps/model/overview.md#extracting-and-synchronizing-port-data). Removing ports using these methods will remove the ports from the model, but to ensure the data is removed from the dataset you will need to have configured the model to recognize where your port data is stored on your nodes/groups.\n\n### Edges[](#edges-1)\n\nYou can remove an edge via `removeEdge`, whose signature is:\n\n```typescript\nremoveEdge(edge: string | Edge):void\n\n```\n\nEdges can be removed by supplying the edge ID (see the example above for how to set an edge id):\n\n```javascript\nmodel.removeEdge(\"edgeId\")\n\n```\n\nor by supplying an `Edge` model object:\n\n```javascript\n\nconst edge = model.addEdge({source:someNode, target:\"someOtherNode.somePortId\", data:{label:\"My Edge Label\"}})\n\n...\n\nmodel.removeEdge(edge)\n\n```\n\n***\n\n## Updating model objects[](#updating-model-objects)\n\n### Nodes[](#nodes-2)\n\nTo update a node, use `updateNode` or `updateVertex`:\n\n```typescript\nupdateNode(node: string | Node | ObjectData, updates?: ObjectData): void\n\nupdateVertex(vertex: string | Node | Group | Port | ObjectData, updates?: ObjectData): void\n\n```\n\n```javascript\nmodel.updateNode(\"someNodeId\", { foo:\"new value\"})\n\n```\n\n### Groups[](#groups-2)\n\nTo update a group, use `updateGroup` (or `updateVertex` as shown above for Nodes)\n\n```javascript\nmodel.updateGroup(\"someNodeId\", { foo:\"new value\"})\n\n```\n\n### Ports[](#ports-2)\n\nTo update a port, use the `updatePort` method, whose signature is:\n\n```typescript\nupdatePort(port: Port | string, updates?: ObjectData): void\n\n```\n\nYou can call this method with either a full port id:\n\n```javascript\nmodel.updatePort(\"someNode.somePortId\", {field:\"updatedValue\"})\n\n```\n\nor with a `Port` model object:\n\n```javascript\nconst port = model.addPort(someNode, { id:\"portId\", field:\"originalValue\"})\nmodel.updatePort(port, {field:\"updatedValue\"})\n\n```\n\n### Edges[](#edges-2)\n\nEdges can be updated with the `updateEdge` method, whose signature is:\n\n```typescript\nupdateEdge(obj: Edge | string, updates?: ObjectData): void\n\n```\n\nAs with `removeEdge`, the edge in question can be identified by its id or by an `Edge` object. Here we update our edge from before via its id with a new label:\n\n```javascript\nmodel.updateEdge(\"edgeId\", {label:\"New Label\"})\n\n```\n\n***\n\ntip\n\n## Transactions[](#transactions)\n\nAll of the methods discussed on this page are connected to the underlying [undo/redo stack](/react/docs/apps/model/undo-redo.md), and run inside a transaction.\n\nCertain methods can cause a cascade of other operations on the data model:\n\n* removal of a vertex causes the removal of all edges to that vertex and to any ports on the vertex\n* removal of a group with `removeChildren:true` will cause the removal of any child vertices, and edges connected to them\n\nSince each method runs inside a transaction, calling `undo()` on a model instance will result in the rollback of every operation executed on the data model in response to some specific method call. Calling `redo()` will result in the re-application of every operation executed by the original method call.\n\n***\n\n## Events[](#events)\n\nThe various add, update and remove methods discussed on this page will each cause a corresponding event to be fired:\n\n| Method | Event | Payload |\n| ------------- | --------------------- | ---------------------- |\n| `addNode` | `EVENT_NODE_ADDED` | [NodeAddedParams]() |\n| `updateNode` | `EVENT_NODE_UPDATED` | [NodeUpdatedParams]() |\n| `removeNode` | `EVENT_NODE_REMOVED` | [NodeRemovedParams]() |\n| `addGroup` | `EVENT_GROUP_ADDED` | [GroupAddedParams]() |\n| `updateGroup` | `EVENT_GROUP_UPDATED` | [GroupUpdatedParams]() |\n| `removeGroup` | `EVENT_GROUP_REMOVED` | [GroupRemovedParams]() |\n| `addPort` | `EVENT_PORT_ADDED` | [PortAddedParams]() |\n| `updatePort` | `EVENT_PORT_UPDATED` | [PortUpdatedParams]() |\n| `removePort` | `EVENT_PORT_REMOVED` | [PortRemovedParams]() |","url":"https://visuallyjs.com/react/docs/apps/model/add-remove-update","lib":"react","topic":"apps"},"docs/apps/model/edges.md":{"title":"Edges","body":"# Edges\n\n## Model object[](#model-object)\n\n### Edge\n\nAn edge connects two vertices.\n\n### Class Members[](#class-members)\n\n| Name | Type | Description |\n| ------ | ---------- | ------------------- |\n| cost | number | Edge cost |\n| source | [Vertex]() | Source of the Edge. |\n| target | [Vertex]() | Target of the Edge. |\n| type | string | Object's type. |\n\n### Class Methods[](#class-methods)\n\n#### getCost[](#getcost)\n\nGets the cost for this edge. Defaults to 1.\n\nSignature\n\ngetCost()\n\nReturn value\n\nnumber\n\n#### getFullId[](#getfullid)\n\nAlias for the getId method.\n\nSignature\n\ngetFullId()\n\nReturn value\n\nstring\n\n#### getId[](#getid)\n\nGets the id for this Edge.\n\nSignature\n\ngetId()\n\nReturn value\n\nstring\n\n#### isDirected[](#isdirected)\n\nGets whether or not the Edge is directed.\n\nSignature\n\nisDirected()\n\nReturn value\n\nboolean\n\nInternally, the model class represents an edge.\n\n## Data format[](#data-format)\n\nOn load and save, edges are represented by a `EdgeData` object with this definition:\n\nEdgeData\n\nThe default type that represents an edge in a dataset to load or a saved dataset\n\n| Name | Type | Description |\n| --------- | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |\n| anchors? | {<br /> source:[ObjectAnchorSpec](),<br /> target:[ObjectAnchorSpec]()<br />} | Optional anchors for the edge. |\n| cost? | number | Cost to associate with the edge. Defaults to 1. This value can be used when computing shortest paths. |\n| data? | [ObjectData]() | Optional data to associate with the edge |\n| directed? | boolean | Whether or not the given edge is directed, ie. when computing a path the edge can only be traversed from source to target. Defaults to false. |\n| geometry? | [Geometry]() | Optional geometry that defines the edge's path |\n| source | string \\| [PointXY]() | Either the ID of the source vertex or a canvas location. |\n| target | string \\| [PointXY]() | Either the ID of the target vertex or a canvas location. |\n\n## Adding Edges[](#adding-edges)\n\nTBD\n\n## Removing Edges[](#removing-edges)\n\nTBD","url":"https://visuallyjs.com/react/docs/apps/model/edges","lib":"react","topic":"apps"},"docs/apps/model/groups.md":{"title":"Groups","body":"# Groups\n\n## Model object[](#model-object)\n\n### Group\n\nA group is an extension of node that can contain other nodes and groups.\n\n### Class Members[](#class-members)\n\n| Name | Type | Description |\n| ------- | --------------- | ------------------------------------------------------------------------------------------ |\n| group | [Group]() | Group the node is a member of, if any. This property should never be written by your code. |\n| id | string | The vertex's id. Must be a string. |\n| members | Array<[Node]()> | Members of the group. Do not write to, or manipulate in any way, this array. |\n| type | string | Object's type. |\n\n### Class Methods[](#class-methods)\n\n#### getAllDirectEdges[](#getalldirectedges)\n\nGets all the edges connecting to this group and any ports on the group.\n\nSignature\n\ngetAllDirectEdges(filter:(e:[Edge]()) => boolean)\n\nParameters\n\n| | | |\n| ------ | ----------------------- | --------------------- |\n| filter | (e:[Edge]()) => boolean | Optional edge filter. |\n\nReturn value\n\nArray<[Edge]()>\n\n#### getAllEdges[](#getalledges)\n\nGets all of the edges connected to this node, both on the node itself and on all of its ports.\n\nSignature\n\ngetAllEdges(filter:(e:[Edge]()) => boolean)\n\nParameters\n\n| | | |\n| ------ | ----------------------- | --------------------- |\n| filter | (e:[Edge]()) => boolean | Optional Edge filter. |\n\nReturn value\n\nArray<[Edge]()>\n\n#### getAllSourceEdges[](#getallsourceedges)\n\nGets all of the Edges connected to this Node, both on the Node itself and on all of its Ports, where this node/port is the source of edge\n\nSignature\n\ngetAllSourceEdges()\n\nReturn value\n\nArray<[Edge]()>\n\n#### getAllTargetEdges[](#getalltargetedges)\n\nGets all of the Edges connected to this Node, both on the Node itself and on all of its Ports, where this node/port is the target of edge\n\nSignature\n\ngetAllTargetEdges()\n\nReturn value\n\nArray<[Edge]()>\n\n#### getDirectEdges[](#getdirectedges)\n\nGets all Edges directly connected to this Vertex, ie. not to one of the Ports on the Vertex. This is an alias for `getEdges`.\n\nSignature\n\ngetDirectEdges(filter:(e:[Edge]()) => boolean)\n\nParameters\n\n| | | |\n| ------ | ----------------------- | --------------------- |\n| filter | (e:[Edge]()) => boolean | Optional Edge filter. |\n\nReturn value\n\nArray<[Edge]()>\n\n#### getDirectSourceEdges[](#getdirectsourceedges)\n\nGets all Edges directly connected to this Vertex, ie. not to one of the Ports on the Vertex, where this Vertex is the source.\n\n<br />\n\nThis is an alias for `getSourceEdges`.\n\nSignature\n\ngetDirectSourceEdges()\n\nReturn value\n\nArray<[Edge]()>\n\n#### getDirectTargetEdges[](#getdirecttargetedges)\n\nGets all Edges directly connected to this Vertex, ie. not to one of the Ports on the Vertex, where this Vertex is the target.\n\n<br />\n\nThis is an alias for `getTargetEdges`.\n\nSignature\n\ngetDirectTargetEdges()\n\nReturn value\n\nArray<[Edge]()>\n\n#### getEdges[](#getedges)\n\nGets all edges where this vertex is either the source or the target of the edge.\n\n<br />\n\nNote that this does *not* retrieve edges on any ports associated with this Vertex - for that,\n\nSignature\n\ngetEdges(params:{\n\n<br />\n\n filter:(e:[Edge]()) => boolean\n\n<br />\n\n})\n\nParameters\n\n| | | |\n| ------ | ---------------------------------------------- | - |\n| params | {<br /> filter:(e:[Edge]()) => boolean<br />} | |\n\nReturn value\n\nArray<[Edge]()>\n\n#### getFullId[](#getfullid)\n\nGets the Vertex's id, which, for Nodes and Groups, is just the `id` property. This method is overridden by Ports.\n\nSignature\n\ngetFullId()\n\nReturn value\n\nstring\n\n#### getIndegreeCentrality[](#getindegreecentrality)\n\nGets this Node's \"indegree\" centrality; a measure of how many other Nodes are connected to this Node as the target of some Edge.\n\nSignature\n\ngetIndegreeCentrality()\n\nReturn value\n\nnumber\n\n#### getInternalEdges[](#getinternaledges)\n\nGets all the edges to/from the group, any ports the Group has, and any edges connected to all child vertices of the group.\n\nSignature\n\ngetInternalEdges(filter:(e:[Edge]()) => boolean)\n\nParameters\n\n| | | |\n| ------ | ----------------------- | ------------------------------------------------------------------ |\n| filter | (e:[Edge]()) => boolean | Optional edge filter to apply to all members and the group itself. |\n\nReturn value\n\nArray<[Edge]()>\n\n#### getMemberCount[](#getmembercount)\n\nGets how many members the group has.\n\nSignature\n\ngetMemberCount()\n\nReturn value\n\nnumber\n\n#### getMembers[](#getmembers)\n\nGets the group members\n\nSignature\n\ngetMembers()\n\nReturn value\n\nArray<[Node]()>\n\n#### getOutdegreeCentrality[](#getoutdegreecentrality)\n\nGets this Node's \"outdegree\" centrality; a measure of how many other Nodes this Node is connected to as the source of some Edge.\n\nSignature\n\ngetOutdegreeCentrality()\n\nReturn value\n\nnumber\n\n#### getPort[](#getport)\n\nGets the Port with the given id, null if nothing found.\n\nSignature\n\ngetPort(portId:string)\n\nParameters\n\n| | | |\n| ------ | ------ | -------- |\n| portId | string | Port id. |\n\nReturn value\n\n[Port]()\n\n#### getPortEdges[](#getportedges)\n\nGets all Edges that are connected to Ports on this Node, not directly to the Node itself.\n\nSignature\n\ngetPortEdges(filter:(e:[Edge]()) => boolean)\n\nParameters\n\n| | | |\n| ------ | ----------------------- | -------------------- |\n| filter | (e:[Edge]()) => boolean | Optional edge filter |\n\nReturn value\n\nArray<[Edge]()>\n\n#### getPorts[](#getports)\n\nGets all Ports associated with this Node.\n\nSignature\n\ngetPorts()\n\nReturn value\n\nArray<[Port]()>\n\n#### getPortSourceEdges[](#getportsourceedges)\n\nGets all Edges that are connected to Ports on this Node, not directly to the Node itself, where the Port on this Node is the source of the edge.\n\nSignature\n\ngetPortSourceEdges()\n\nReturn value\n\nArray<[Edge]()>\n\n#### getPortTargetEdges[](#getporttargetedges)\n\nGets all Edges that are connected to Ports on this Node, not directly to the Node itself, where the Port on this Node is the target of the edge.\n\nSignature\n\ngetPortTargetEdges()\n\nReturn value\n\nArray<[Edge]()>\n\n#### getSourceEdges[](#getsourceedges)\n\nGets all Edges where this Vertex is the source.\n\nSignature\n\ngetSourceEdges()\n\nReturn value\n\nArray<[Edge]()>\n\n#### getTargetEdges[](#gettargetedges)\n\nGets all Edges where this Vertex is the target.\n\nSignature\n\ngetTargetEdges()\n\nReturn value\n\nArray<[Edge]()>\n\n#### inspect[](#inspect)\n\nReturns a string representation of the Vertex.\n\n<br />\n\n\\*\n\nSignature\n\ninspect()\n\nReturn value\n\nstring\n\n## Data format[](#data-format)\n\nOn load and save, groups are represented by a `GroupData` object with this definition:\n\nSorry - we could not find this document.\n\n## Adding Groups[](#adding-groups)\n\nTBD\n\n## Removing Groups[](#removing-groups)\n\nTBD","url":"https://visuallyjs.com/react/docs/apps/model/groups","lib":"react","topic":"apps"},"docs/apps/model/io/loading-and-saving-data.md":{"title":"Loading And Saving Data","body":"# Loading and saving data\n\nloading-and-saving-data.mdx","url":"https://visuallyjs.com/react/docs/apps/model/io/loading-and-saving-data","lib":"react","topic":"apps"},"docs/apps/model/nodes.md":{"title":"Nodes","body":"# Nodes\n\n## Model object[](#model-object)\n\n### Node\n\nextended by: [Group]()\n\nA Node is a Vertex that does not contain other nodes/groups.\n\n### Class Members[](#class-members)\n\n| Name | Type | Description |\n| ----- | --------- | ------------------------------------------------------------------------------------------ |\n| group | [Group]() | Group the node is a member of, if any. This property should never be written by your code. |\n| id | string | The vertex's id. Must be a string. |\n| type | string | Object's type. |\n\n### Class Methods[](#class-methods)\n\n#### getAllEdges[](#getalledges)\n\nGets all of the edges connected to this node, both on the node itself and on all of its ports.\n\nSignature\n\ngetAllEdges(filter:(e:[Edge]()) => boolean)\n\nParameters\n\n| | | |\n| ------ | ----------------------- | --------------------- |\n| filter | (e:[Edge]()) => boolean | Optional Edge filter. |\n\nReturn value\n\nArray<[Edge]()>\n\n#### getAllSourceEdges[](#getallsourceedges)\n\nGets all of the Edges connected to this Node, both on the Node itself and on all of its Ports, where this node/port is the source of edge\n\nSignature\n\ngetAllSourceEdges()\n\nReturn value\n\nArray<[Edge]()>\n\n#### getAllTargetEdges[](#getalltargetedges)\n\nGets all of the Edges connected to this Node, both on the Node itself and on all of its Ports, where this node/port is the target of edge\n\nSignature\n\ngetAllTargetEdges()\n\nReturn value\n\nArray<[Edge]()>\n\n#### getDirectEdges[](#getdirectedges)\n\nGets all Edges directly connected to this Vertex, ie. not to one of the Ports on the Vertex. This is an alias for `getEdges`.\n\nSignature\n\ngetDirectEdges(filter:(e:[Edge]()) => boolean)\n\nParameters\n\n| | | |\n| ------ | ----------------------- | --------------------- |\n| filter | (e:[Edge]()) => boolean | Optional Edge filter. |\n\nReturn value\n\nArray<[Edge]()>\n\n#### getDirectSourceEdges[](#getdirectsourceedges)\n\nGets all Edges directly connected to this Vertex, ie. not to one of the Ports on the Vertex, where this Vertex is the source.\n\n<br />\n\nThis is an alias for `getSourceEdges`.\n\nSignature\n\ngetDirectSourceEdges()\n\nReturn value\n\nArray<[Edge]()>\n\n#### getDirectTargetEdges[](#getdirecttargetedges)\n\nGets all Edges directly connected to this Vertex, ie. not to one of the Ports on the Vertex, where this Vertex is the target.\n\n<br />\n\nThis is an alias for `getTargetEdges`.\n\nSignature\n\ngetDirectTargetEdges()\n\nReturn value\n\nArray<[Edge]()>\n\n#### getEdges[](#getedges)\n\nGets all edges where this vertex is either the source or the target of the edge.\n\n<br />\n\nNote that this does *not* retrieve edges on any ports associated with this Vertex - for that,\n\nSignature\n\ngetEdges(params:{\n\n<br />\n\n filter:(e:[Edge]()) => boolean\n\n<br />\n\n})\n\nParameters\n\n| | | |\n| ------ | ---------------------------------------------- | - |\n| params | {<br /> filter:(e:[Edge]()) => boolean<br />} | |\n\nReturn value\n\nArray<[Edge]()>\n\n#### getFullId[](#getfullid)\n\nGets the Vertex's id, which, for Nodes and Groups, is just the `id` property. This method is overridden by Ports.\n\nSignature\n\ngetFullId()\n\nReturn value\n\nstring\n\n#### getIndegreeCentrality[](#getindegreecentrality)\n\nGets this Node's \"indegree\" centrality; a measure of how many other Nodes are connected to this Node as the target of some Edge.\n\nSignature\n\ngetIndegreeCentrality()\n\nReturn value\n\nnumber\n\n#### getOutdegreeCentrality[](#getoutdegreecentrality)\n\nGets this Node's \"outdegree\" centrality; a measure of how many other Nodes this Node is connected to as the source of some Edge.\n\nSignature\n\ngetOutdegreeCentrality()\n\nReturn value\n\nnumber\n\n#### getPort[](#getport)\n\nGets the Port with the given id, null if nothing found.\n\nSignature\n\ngetPort(portId:string)\n\nParameters\n\n| | | |\n| ------ | ------ | -------- |\n| portId | string | Port id. |\n\nReturn value\n\n[Port]()\n\n#### getPortEdges[](#getportedges)\n\nGets all Edges that are connected to Ports on this Node, not directly to the Node itself.\n\nSignature\n\ngetPortEdges(filter:(e:[Edge]()) => boolean)\n\nParameters\n\n| | | |\n| ------ | ----------------------- | -------------------- |\n| filter | (e:[Edge]()) => boolean | Optional edge filter |\n\nReturn value\n\nArray<[Edge]()>\n\n#### getPorts[](#getports)\n\nGets all Ports associated with this Node.\n\nSignature\n\ngetPorts()\n\nReturn value\n\nArray<[Port]()>\n\n#### getPortSourceEdges[](#getportsourceedges)\n\nGets all Edges that are connected to Ports on this Node, not directly to the Node itself, where the Port on this Node is the source of the edge.\n\nSignature\n\ngetPortSourceEdges()\n\nReturn value\n\nArray<[Edge]()>\n\n#### getPortTargetEdges[](#getporttargetedges)\n\nGets all Edges that are connected to Ports on this Node, not directly to the Node itself, where the Port on this Node is the target of the edge.\n\nSignature\n\ngetPortTargetEdges()\n\nReturn value\n\nArray<[Edge]()>\n\n#### getSourceEdges[](#getsourceedges)\n\nGets all Edges where this Vertex is the source.\n\nSignature\n\ngetSourceEdges()\n\nReturn value\n\nArray<[Edge]()>\n\n#### getTargetEdges[](#gettargetedges)\n\nGets all Edges where this Vertex is the target.\n\nSignature\n\ngetTargetEdges()\n\nReturn value\n\nArray<[Edge]()>\n\n#### inspect[](#inspect)\n\nReturns a string representation of the Vertex.\n\n<br />\n\n\\*\n\nSignature\n\ninspect()\n\nReturn value\n\nstring\n\n## Data format[](#data-format)\n\nOn load and save, nodes are represented by a `NodeData` object with this definition:\n\nSorry - we could not find this document.\n\n## Adding Nodes[](#adding-nodes)\n\nTBD\n\n## Removing Nodes[](#removing-nodes)\n\nTBD","url":"https://visuallyjs.com/react/docs/apps/model/nodes","lib":"react","topic":"apps"},"docs/apps/model/overview.md":{"title":"Overview","body":"# Data Model\n\nThe core data model in VisuallyJs is that of a graph, as discussed [here on Wikipedia](https://en.wikipedia.org/wiki/Graph_\\(discrete_mathematics\\)).\n\nA graph is a collection of nodes, groups, edges and ports.\n\n* **Nodes** map to entities in your data model.\n* **Groups** are collections of nodes/groups. They map to entities in your data model.\n* **Ports** are logical and/or physical locations on nodes/groups that are the terminus for an edge. Not all apps use ports in their data model. The simplest example of the usage of ports is perhaps a database schema: you'd represent your tables as nodes, and then the columns on each table would be represented as ports. Another good analogy is ports in TCP/IP.\n* **Edges** are relationships between nodes, groups or ports.\n\ntip\n\nIn the VisuallyJs documentation you'll see references to `Vertex` and `vertices` - this is a node, port or group. We often use \"vertex\" to refer to the source and target terminus for an edge throughout the documentation as it's easier than typing \"Node/Group/Port\"...and also, conceptually, its correct!\n\n## What do I need the model for?[](#what-do-i-need-the-model-for)\n\nA brief list of the sorts of things you can do with the model:\n\n* add/remove/update nodes, groups and edges\n* undo/redo operations\n* impose constraints on connectivity between objects\n* specify object factories for the creation of new objects\n* import/export the dataset\n* execute multiple operations within a transaction\n* select specific contents via filtering\n* check for the existence of and retrieve paths between vertices\n\nChanges to the model are automatically reflected in the UI.\n\n## Accessing the model[](#accessing-the-model)\n\n### From your app component[](#from-your-app-component)\n\nTo access the model from inside a component that uses a `SurfaceComponent`, declare a ref of type [SurfaceComponentRef]() and assign it in the JSX.\n\nYou can then use the `getModel()` method to access the model, which is of type [BrowserUIReactModel]()\n\n```jsx\nimport { useRef } from \"react\"\nimport { SurfaceComponent, SurfaceComponentRef } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n \n const surfaceRef = useRef<SurfaceComponentRef>(null)\n \n function addANode() {\n surfaceRef.current.getModel().addNode({id:\"1\", left:50, top:50})\n }\n \n return <SurfaceProvider> \n <SurfaceComponent ref={surfaceRef}/>\n <button onClick={() => addANode()}>Add a node!</button>\n </SurfaceProvider>\n}\n\n```\n\n### From a different component[](#from-a-different-component)\n\nIf you have a component somewhere in your tree from which you wish the manipulate the model, you can use the `useSurface()` hook in conjunction with a `SurfaceProvider` to access the surface. Your app component should look something like this:\n\n```jsx\nimport { useRef } from \"react\"\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n \n return <SurfaceProvider> \n <SurfaceComponent ref={surfaceRef}/>\n <MyOtherComponent/>\n </SurfaceProvider>\n}\n\n```\n\nThen the implementation of `MyOtherComponent` can use the `useSurface` hook:\n\n```jsx\nimport { useRef } from \"react\"\nimport { SurfaceComponent, useSurface } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyOtherComponent() {\n \n const surfaceRef = useRef<Surface>(null)\n useSurface().then(s => surfaceRef.current = s)\n \n function addANode() {\n surfaceRef.current.model.addNode({id:\"1\", left:50, top:50})\n }\n \n return <div><button onClick={() => addANode()}>Add a node!</button></div>\n}\n\n```\n\ninfo\n\nNote the difference between the ref type in the above example from the first example: when you use the `useSurface` hook the value passed into the promise is a [Surface](), *not* a `SurfaceComponentRef`.\n\n***\n\n## Data Format[](#data-format)\n\nThe various parts of your data model can be represented as any valid Javascript type. As an example, here is the backing data for the `Book` table in the Schema Builder starter app:\n\n```json\n{\n \"id\":\"book\",\n \"name\":\"Book\",\n \"type\":\"table\",\n \"columns\":[\n { \"id\":\"123\", \"name\":\"id\", \"datatype\":\"integer\", \"primaryKey\":true },\n { \"id\":\"456\", \"name\":\"isbn\", \"datatype\":\"varchar\" },\n { \"id\":\"789\", \"name\":\"title\", \"datatype\":\"varchar\" }\n ]\n}\n\n```\n\n## Object IDs[](#object-ids)\n\nEvery vertex is required to have a unique ID. VisuallyJs attempts to derive this automatically from your data, by looking for an `id` member, which should be a **string**.\n\ntip\n\nFor the vast majority of applications this setup will work fine. Should you wish to implement a different strategy, though, you can supply your own `idFunction` in your model options:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ObjectData } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n idFunction: (data:ObjectData):string {\n return SomeCustomComputing(data);\n }\n})\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\nRemember to pass back the ID as a string. This method will be used to attempt to derive an ID for any model object.\n\nAgain note this is optional - you do not need to supply this function, but if you do not then VisuallyJs will expect an `id` member in your data.\n\n### Group IDs[](#group-ids)\n\nIDs for groups are derived using whatever method VisuallyJs is using to derive IDs for nodes - either by looking for an `id` value in your data, or by using a supplied `idFunction`. group IDs must be unique across all groups *and nodes* in the dataset: you cannot have a group that has the same ID as some node.\n\n### Edge IDs[](#edge-ids)\n\nYou are not required to supply an ID for every edge, and if you do not, VisuallyJs will assign one automatically.\n\n### Port IDs[](#port-ids)\n\nPort IDs are required to be unique on the node/group on which the port exists, but may be the same as the ID of a port on some other node (and in fact this is quite common).\n\n#### Referencing ports by ID[](#referencing-ports-by-id)\n\nWhen adding an edge to a VisuallyJs instance, you can reference a port on some node using, by default, dotted notation. In the data given above there were three ports. We could connect one of them to a column on another table like this:\n\n```javascript\nmodel.connect({\n source:\"book.id\", \n target:\"book_author.book_id\"\n})\n\n```\n\n`book_author` is another table in the schema from the SchemaBuilderDemoLink title=\"Schema Builder\"/> starter app.\n\n#### Custom port ID Separator[](#custom-port-id-separator)\n\nIf you find that using a period as the separator in a port ID does not work for your data model, you can override what VisuallyJs will use by doing this:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n portSeparator: \"#\"\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n***\n\n## Object type[](#object-type)\n\nEvery object has an associated `type`. This is an important concept in VisuallyJs, as it is the basic means by which the data model is bound to any renderers, via views.\n\nThe `type` of a model object is, by default, mapped by the object's `type` in its backing data. It is used by the view in the UI to determine the appearance and behaviour of the object.\n\nTo change the type of some object after it has been initially created, use the `setType` method on a model instance. For a discussion, see [this page](/react/docs/apps/model/add-remove-update.md#setting-object-types)\n\ntip\n\nAs with ID, you can provide your own function to retrieve the type for some object, should you need to.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ObjectData } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n typeFunction: (data:ObjectData):string => {\n return SomeOtherComputing(data);\n}\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n***\n\n## Constraining connectivity[](#constraining-connectivity)\n\nConnectivity can be controlled at runtime by **interceptors** - callbacks that can be used to cancel some proposed activity, and that are bound on an instance of the VisuallyJs model by supplying a specific function in the model constructor options.\n\n#### beforeConnect[](#beforeconnect)\n\nA function to run before an edge with the given data can be established between the given source and target. Returning false from this method aborts the connection. Note that this method fires regardless of the source of the new edge, meaning it will be called when loading data programmatically.\n\n##### Method signature[](#method-signature)\n\n`beforeConnect(source: Vertex, target: Vertex): any`\n\n##### Parameters[](#parameters)\n\n* *source* The source vertex for the new edge\n* *target* The target vertex for the new edge\n\n##### Return value[](#return-value)\n\n* `false` - aborts the connection\n* all other values are ignored and will allow the edge to be established\n\n##### Example[](#example)\n\nHere, we reject connections from any vertex to itself.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n beforeConnect: (source: Vertex, target: Vertex) => {\n return (source !== target)\n }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n#### beforeMoveConnection[](#beforemoveconnection)\n\nA function to run before an edge of the given type is relocated from its current source or target to a new source or target. Returning false from this method will abort the move.\n\n##### Method signature[](#method-signature-1)\n\n`beforeMoveConnection(source: Vertex, target: Vertex, edge: Edge): any`\n\n##### Parameters[](#parameters-1)\n\n* *source* Candidate source. May be the edge's current source, or may be a new source.\n* *target* Candidate target. May be the edge's current target, or may be a new target.\n* *edge* The edge that is being moved.\n\nThe parameters `source` and `target` reflect the source and target of the edge if the move were to be accepted. So if, for example, your user drags a connection by its target and drops it elsewhere, `target` will be the drop target, not the edge's current target, but `source` will be the edge's current source. You can access the current source/target via the `source` and `target` properties of `edge`.\n\n##### Return value[](#return-value-1)\n\n* `false` - aborts the move\n* all other values are ignored and will allow the move to occur\n\n##### Example[](#example-1)\n\nHere, we reject moving any edge that has `fixed:true` in it backing data:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n beforeMoveConnection: (source: Vertex, target: Vertex, edge:Edge) => {\n return (edge.data.fixed !== true)\n }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n#### beforeStartConnect[](#beforestartconnect)\n\nA function to run before an edge of the given type is dragged from the given source (ie. before the mouse starts moving). This interceptor is slightly different to the others in that it's not just a yes/no question: as with the other interceptors, returning false from this method will reject the action, that is in this case it will not allow a connection drag to begin. But you can also return an object from this method, and when you do that, the connection start is allowed, and the object you returned becomes the payload for the new edge.\n\n##### Method signature[](#method-signature-2)\n\n`beforeStartConnect(source: Vertex, type: string): any`\n\n##### Parameters[](#parameters-2)\n\n* *source* The vertex that is the source for the new edge\n* *type* The computed type for this new edge.\n\n##### Return value[](#return-value-2)\n\n* `false` - aborts the connection\n* `Object` - An object returned from this method will be used as the initial payload for the new edge\n* all other values are ignored and will allow the connection start to continue\n\n##### Example - reject a connection start[](#example---reject-a-connection-start)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n beforeStartConnect: (source: Vertex, type:string) => {\n return type !== 'not-connectable'\n }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n##### Example - provide an initial payload[](#example---provide-an-initial-payload)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n beforeStartConnect: (source: Vertex, type:string) => {\n return {\n type,\n message:`initial payload for vertex ${source.id}`\n }\n }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n#### beforeDetach[](#beforedetach)\n\nA function to run before the given edge is detached from the given source vertex. If this method returns false, the detach will be aborted.\n\n##### Method signature[](#method-signature-3)\n\n`beforeDetach(source: Vertex, target: Vertex, edge: Edge, isDiscard?: boolean): any`\n\n##### Parameters[](#parameters-3)\n\n* *source* The source vertex for the edge that is to be detached.\n* *target* The candidate target for the edge - may be null, if the edge is being discarded\n* *edge* The edge that is being detached.\n* *isDiscard* True if the edge is not now connected to a target.\n\n##### Return value[](#return-value-3)\n\n* `false` Returning false will abort the edge detach\n* all other values are ignored and will allow the detach to occur\n\n##### Example[](#example-2)\n\nHere, we reject the detach if the target is null, ie. the user is trying to discard the edge, not relocate it.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n beforeDetach: (source: Vertex, target: Vertex, edge: Edge, isDiscard?: boolean) => {\n return target != null\n }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n#### beforeStartDetach[](#beforestartdetach)\n\n##### Method signature[](#method-signature-4)\n\n`beforeStartDetach(source: Vertex, edge: Edge): any`\n\nA function to run before the given edge is detached from the given source vertex. If this method returns false, the detach will be aborted. The difference between this and `beforeDetach` is that this method is fired as soon as a user tries to detach an edge from an anchor in the UI, whereas `beforeDetach` allows a user to detach the edge in the UI.\n\n##### Parameters[](#parameters-4)\n\n* *source* The source vertex for the edge that the user has started to detach\n* *edge* The edge that the user has started to detach\n\n##### Return value[](#return-value-4)\n\n* `false` Returning false will abort the edge detach\n* all other values are ignored and will allow the user to begin the detach\n\n##### Example[](#example-3)\n\nHere, we reject the detach if the source vertex has `doNotDetachEdges:true` in its backing data.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n beforeDetach: (source: Vertex, edge: Edge) => {\n return source.data.doNotDetachEdges !== true\n }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n##### Multiple interceptors[](#multiple-interceptors)\n\nYou can provide multiple interceptors - in this example we provide a `beforeStartConnect` and `beforeDetach` interceptor to the model. The `beforeStartConnect` interceptor prevents the user from dragging connections from any vertex whose ID is not an even number. The `beforeDetach` interceptor reattaches detached connections whose source ID is not an event number\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n beforeStartConnect: (source, type) => {\n // only allow connections from nodes whose \n // ID is an even number\n return parseInt(source.id, 10) % 2 === 0\n },\n beforeDetach: (source, target, edge, isDiscard) => {\n // only allow connections to be detached whose \n // source ID is an even number\n return parseInt(edge.source.id, 10) % 2 === 0\n }\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\n**********\n\n## Next Steps[](#next-steps)\n\n[Add, remove and update](/react/apps/model/add-remove-update)\n\n[Read about how to add, remove and update data](/react/apps/model/add-remove-update)\n\n[Undo/redo and transactions](/react/apps/model/undo-redo)\n\n[Read about how to undo/redo operations, and work with transactions](/react/apps/model/undo-redo)\n\n[Selections](/react/apps/model/selections)\n\n[Read about how to generate and work with selections](/react/apps/model/selections)","url":"https://visuallyjs.com/react/docs/apps/model/overview","lib":"react","topic":"apps"},"docs/apps/model/paths.md":{"title":"Paths","body":"# Paths\n\nA `Path` represents the path from one vertex (a node/port/group) through a series of edges and intermediate vertices to another vertex. VisuallyJs provides several methods for the creation and manipulation of paths, as well as animating overlays along a path.\n\nYou can work with paths through both an instance of the VisuallyJs model and any Surfaces. The object representing a path differs slightly between the two, in that paths created from a Surface support a few extra (UI-related) methods, such as `setVisible`.\n\n## Getting a Path[](#getting-a-path)\n\nTo get a Path, you call `getPath` on either a model instance or a Surface, with a valid path spec. A quick example to kick off:\n\n```javascript\nmodel.getPath({\n source:someNode,\n target:someOtherNode\n});\n\n```\n\nThis will return you the **shortest path** from `someNode` to `someOtherNode`, where the path length is related to its `cost`.\n\n### Paths including ports[](#paths-including-ports)\n\nBy default, VisuallyJs will search for paths in \"strict\" mode, meaning if you supply a node/group as source/target, then only edges directly connected to that node/group will be traversed in the search for a path. Switching off \"strict\" mode relaxes this restriction, and also includes edges connected to any ports on the given node/group. See below.\n\n## Path specs[](#path-specs)\n\nThis is the full list of supported parameters to the `getPath` method.\n\nPathOptions\n\nOptions for a Path.\n\n| Name | Type | Description |\n| ----------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| edgeFilter? | (n:[Edge]()) => boolean | This function is given each Edge's backing data and asked to return true or false - true means include the Edge, false means exclude it. |\n| nodeFilter? | (n:[Node]()) => boolean | This function is given each Node/Group's backing data and asked to return true or false - true means include the Node/Group, false means exclude it. |\n| source | string \\| [Vertex]() | Path source. Either a vertex (node/group/port) or a vertex id. |\n| strict? | boolean | Sets whether or not paths are searched strictly by the given source/target. If you supply a node as the source, but there are only edges connected to ports on that node, by default these edges will be ignored. Switching `strict` to false will mean these edges are considered. |\n| target | string \\| [Vertex]() | Path target. Either a vertex (node/group/port) or a vertex id. |\n\n### Filtering nodes[](#filtering-nodes)\n\n```javascript\nmodel.getPath({\n source:someNode,\n target:someOtherNode,\n nodeFilter:(n) => {\n return n.data.type != \"aTypeIWantToIgnore\";\n }\n});\n\n```\n\nHere we pass in a function that will be called for every prospective node in the path. If it returns false then the graph treats the node as if it were at a distance of Infinity - not reachable.\n\n### Filtering edges[](#filtering-edges)\n\nYou can also provide an `edgeFilter` to control which edges your path will traverse:\n\n```javascript\nmodel.getPath({\n source:someNode,\n target:someOtherNode,\n edgeFilter:function(e) {\n return e.data.type != \"aTypeIWantToIgnore\";\n }\n});\n\n```\n\ntip\n\nThe arguments to these functions are `Node` or `Edge` objects from the model. You may wish to use information contained in those classes to make your decisions, but if you just want to access the original data, you use the `data` member as shown above.\n\n***\n\n## Paths in the UI[](#paths-in-the-ui)\n\nCalling `getPath(...)` on a Surface returns you a `UIPath` object, which contains a `Path` and offers a few extra methods for manipulating the appearance of the components of the path. All of the class manipulation methods take a space-delimited string as argument. See below for a detailed list of the available methods on a `UIPath`.\n\nnote\n\nCalling any of the methods from the basic Path object on the result of a `getPath` call to a Surface that result in a change to the data model will cause those data model changes to be communicated automatically to any other Surface registered on the given model instance.\n\n### Animating paths[](#animating-paths)\n\nThe surface component supports tracing a path between a given source and target node using an overlay.\n\n**********\n\n```javascript\n\nimport { newInstance } from \"@visuallyjs/browser-ui\"\n\n// setup two nodes and connect\n\nlet model = newInstance()\nlet renderer = model.render(someElement)\nmodel.load({\n data:{\n nodes: [ a bunch of nodes. let's pretend they have IDs from 1 - 34 ],\n edges:[ a bunch of edges ]\n }\n});\n\nlet transport = renderer.tracePath({\n source:1,\n target:23,\n overlay:\"Arrow\"\n});\n\nif (!transport.pathExists) {\n alert(\"There was no such path\");\n}\n\n\n```\n\nIn this example we've attempted to trace an arrow overlay along the *shortest path* from node 1 to node 23, using the default animation options, which are:\n\n* travel at 100 pixels per second\n* use a frame rate of 30 frames per second\n* dwell on each intermediate element for 250 milliseconds\n\nThe return values from the `tracePath` method is a `PathTransport` object, which offers the following methods:\n\n* `play()` Starts the animation\n* `pause()` Pauses the animation\n* `cancel()` Cancels the animation\n* `bind(event:string, handler:Function)` Binds an event handler. Only one event - \"state\" - is fired, in fact, and it's generally better practise to supply a `listener` to the `tracePath` method call instead, because binding to the transport after it has been created means you will miss the initial `start` state event change.\n\nWe can enhance the previous call, then, with an event listener like this:\n\n```javascript\n\nimport { newInstance } from \"@visuallyjs/browser-ui\"\n\nfunction stateChange(newState) {\n console.log(\"The new state is \" + newState);\n}\n\n// setup two nodes and connect\nlet model = newInstance()\nlet renderer = model.render(someElement)\nmodel.load({\n data:{\n nodes: [ a bunch of nodes. let's pretend they have IDs from 1 - 34 ],\n edges:[ a bunch of edges ]\n }\n});\n\nlet transport = renderer.tracePath({\n source:1,\n target:23,\n overlay:\"Arrow\",\n listener: stateChange\n});\n\nif (!transport.pathExists) {\n alert(\"There was no such path\");\n}\n\n\n```\n\nThe DemoLink title=\"Path Tracing demonstration\" id=\"paths\" /> has an example of a full setup with an event listener and play/pause/cancel controls.\n\n### Animation Options[](#animation-options)\n\nYou can change the default animation options if you need to:\n\n```javascript\nconst transport = renderer.tracePath({\n source:1,\n target:23,\n overlay:\"Arrow\",\n options:{\n speed: 25, // pixels per second\n rate: 60 // frames per second\n dwell: 50 // dwell on intermediate elements for 50 milliseconds\n }\n});\n\n```\n\n### Tracing a specific Path[](#tracing-a-specific-path)\n\nThe two examples given so far do not mandate any specific path to travel from the source to the target, so VisuallyJs will pick the shortest path (which is controlled by both number of hops and edge *cost* if you have provided that for any of your edges). However, you can supply any path to this method, should you want to.\n\nTo get a path that is not the shortest path you will need to make use of a `nodeFilter` and/or `edgeFilter` when you call `getPath` on some model instance, as discussed above. An example:\n\n```javascript\nlet path = model.getPath({\n source:1,\n target:23,\n edgeFilter:(edge) => {\n return !edge.data.type === \"aTypeIWouldIgnore\"\n }\n});\n\n```\n\nThis path can then be passed to `tracePath` instead of providing a `source` and `target`:\n\n```javascript\nrenderer.tracePath({\n path:path,\n overlay:\"Arrow\",\n options:{\n speed: 25, // pixels per second\n rate: 60, // frames per second\n dwell: 50 // dwell on intermediate elements for 50 milliseconds\n }\n});\n\n```\n\n***\n\n### CSS Classes[](#css-classes)\n\nClassTable id=\"pathTraversal\"/>\n\n***\n\n### Events[](#events)\n\nThese events will be fired by the renderer during a path traversal:\n\nEventTable id=\"surface\" topic=\"pathTraversal\"/>\n\n## API details[](#api-details)\n\n### The Path object[](#the-path-object)\n\nAPI docs for the basic Path object, as used by an instance of VisuallyJs, can be found [Path]()\n\nPath\n\nModels the path between two vertices, which consists of a series of vertices connected by edges.\n\n| Name | Type | Description |\n| -------------- | ---- | -------------- |\n| contains | | no description |\n| deleteAll | | no description |\n| deleteEdges | | no description |\n| deleteVertices | | no description |\n| each | | no description |\n| eachEdge | | no description |\n| eachGroup | | no description |\n| eachNode | | no description |\n| eachVertex | | no description |\n| exists | | no description |\n| filter | | no description |\n| getAllEdgesFor | | no description |\n| getCost | | no description |\n| getEdgeAt | | no description |\n| getEdgeCount | | no description |\n| getNodeAt | | no description |\n| getVertex | | no description |\n| getVertexCount | | no description |\n| getVertices | | no description |\n| isEmpty | | no description |\n\ncaution\n\nOnce you have executed one of the `delete***` methods on a path, your path may contain references to objects that no longer exist in VisuallyJs.\n\n### The UIPath object[](#the-uipath-object)\n\nAPI docs for the UIPath object, returned from a `getPath` call on a Surface, can be found [UIPath]()","url":"https://visuallyjs.com/react/docs/apps/model/paths","lib":"react","topic":"apps"},"docs/apps/model/querying.md":{"title":"Querying","body":"# Querying the model\n\nThe VisuallyJs model offers several methods to query the hierarchy of nodes and groups.\n\n## Groups[](#groups)\n\nWhen you have a hierarchical model where nodes or groups can be nested within other groups, you can use these methods to navigate the hierarchy.\n\n### Ancestor groups[](#ancestor-groups)\n\n#### getAncestors[](#getancestors)\n\nGets a list of groups that are ancestors of the given node/group. The list of ancestors is ordered in terms of their proximity to the focus, ie. the first entry is the focus vertex's immediate parent.\n\nSignature\n\ngetAncestors(vertex:[Node]() | [Group]())\n\nParameters\n\n| | | |\n| ------ | --------------------- | - |\n| vertex | [Node]() \\| [Group]() | |\n\nReturn value\n\nArray<[Group]()>\n\n### Descendants of a group[](#descendants-of-a-group)\n\n#### getDescendants[](#getdescendants)\n\nGets a list of nodes/groups that are descendants of the given group.\n\nSignature\n\ngetDescendants(vertex:[Group]())\n\nParameters\n\n| | | |\n| ------ | --------- | - |\n| vertex | [Group]() | |\n\nReturn value\n\nArray<[Node]() | [Group]()>\n\n### Testing for ancestor[](#testing-for-ancestor)\n\n#### isAncestor[](#isancestor)\n\nReturns whether or not `possibleAncestor` is in fact an ancestor of the given focus node/group\n\nSignature\n\nisAncestor(focus:[Vertex](), possibleAncestor:[Group]())\n\nParameters\n\n| | | |\n| ---------------- | ---------- | ----------------------------------------- |\n| focus | [Vertex]() | Vertex to test |\n| possibleAncestor | [Group]() | Group which may be an ancestor of `focus` |\n\nReturn value\n\nboolean\n\n### Testing for descendant[](#testing-for-descendant)\n\n#### isDescendantGroup[](#isdescendantgroup)\n\nDetermine whether `possibleDescendant` is in fact a descendant of the `ancestor` group\n\nSignature\n\nisDescendantGroup(possibleDescendant:[Group](), ancestor:[Group]())\n\nParameters\n\n| | | |\n| ------------------ | --------- | -------------- |\n| possibleDescendant | [Group]() | Group to test |\n| ancestor | [Group]() | Ancestor group |\n\nReturn value\n\nboolean\n\n### Selecting descendants[](#selecting-descendants)\n\nWhile the methods above return arrays of objects, you may sometimes want to perform selection-based operations on a hierarchy.\n\n#### selectDescendants[](#selectdescendants)\n\nSelects all descendants of some Node or Group, and, optionally, the Node/Group itself.\n\nSignature\n\nselectDescendants(obj:string | [Node]() | [Group](), includeFocus:boolean, includeEdges:boolean)\n\nParameters\n\n| | | |\n| ------------ | ------------------------------- | ------------------------------------------------------------------------------------------ |\n| obj | string \\| [Node]() \\| [Group]() | Node/Group, or ID of Node/Group, to select |\n| includeFocus | boolean | Whether or not to include the focus node/group in the returned dataset. Defaults to false. |\n| includeEdges | boolean | Whether or not to include edges in the returned dataset. Defaults to false. |\n\nReturn value\n\n[VisuallyJsSelection]()","url":"https://visuallyjs.com/react/docs/apps/model/querying","lib":"react","topic":"apps"},"docs/apps/model/selections.md":{"title":"Selections","body":"# Selections\n\nA `Selection` is a collection of nodes, groups, ports and edges (zero or more of each), upon which operations can be made that affect the entire set at once.\n\nYou can work with these in one of two ways - either use the model's [current selection](#currentSelection), or [create an ad-hoc selection](#adhoc-selection).\n\n## Current selection[](#current-selection)\n\nEach instance of the VisuallyJs model maintains a `currentSelection` - the currently selected set of objects. Several methods are available for you to manipulate the contents of the current selection. Changes to the selection are propagated to all registered UI components for some model, which take appropriate action as they need to.\n\nSome examples of the current selection in use in the UI are:\n\n* the Surface and Paper components will assign a CSS class to any object that is in the current selection;\n* an Inspector will extract data from the object(s) in the current selection and allow users to edit the values;\n* the [ResizingToolsPlugin](/react/docs/apps/plugins/resizing-tools.md) will attach resize (and possibly rotate) controls to objects in the current selection;\n* the [LassoPlugin](/react/docs/apps/plugins/lasso.md) adds snagged vertices to the current selection\n\n### setSelection(obj)[](#setselectionobj)\n\nSet the current selection. Here, `obj` can take a number of forms:\n\n* A node, group, port or edge object\n* A list of nodes/groups/ports/edges\n* Another `Selection`\n* A `Path`\n\n### addToSelection(obj)[](#addtoselectionobj)\n\nAdd something to the current selection. Here, `obj` can take a number of forms:\n\n* A node, group, port or edge object\n* A list of nodes/groups/ports/edges\n* Another selection\n* A path\n\n### addPathToSelection(params)[](#addpathtoselectionparams)\n\nA helper method to get a path (see [the Paths docs](/react/docs/apps/model/paths.md)) and add it to the current selection.\n\n### removeFromSelection(obj)[](#removefromselectionobj)\n\nRemove something from the current selection. Valid values for `obj` are the same as for the `addToSelection` and `setSelection` methods.\n\n### getSelection()[](#getselection)\n\nGet the current selection. This returns a [Selection](), which is a selector-like object that offers a number of methods for performing operations on the selection as a whole.\n\n### clearSelection()[](#clearselection)\n\nClears the current selection. This method is analogous to calling `getSelection().clear()`.\n\n***\n\n## AdHoc selections[](#adhoc-selections)\n\nIn addition to the current selection, you can also select a set of vertices and/or edges on an adhoc basis:\n\n* **select(obj)**\n\nHere, `obj` can be some node/group/port/edge, or the ID of some node, group or port, or an array of a combination of these.\n\nFor example, here we create an adhoc selection consisting of 3 nodes, which we nominated by their IDs:\n\n```typescript\nconst mySelection = model.select([\"1\", \"2\", \"7\"])\n\n```\n\n***\n\n### Filtering objects[](#filtering-objects)\n\nA more powerful method to use to get a set of objects is `filter`, which, as the name suggests, can filter the contents of some model instance according to a few criteria. There are two ways to call this method.\n\n#### Filtering with a function[](#filtering-with-a-function)\n\nYou can pass a Function as argument to the `filter` method, which is expected to return true to indicate that a given object should be included:\n\n```javascript\nimport { Node } from \"@visuallyjs/browser-ui\"\n\nlet selection = model.filter((obj) => {\n return (obj.objectType === Node.objectType) \n})\n\n```\n\nNote here that this function is given *every* object managed by VisuallyJs - meaning all groups, nodes and edges. So you can use `objectType` to test if the object is a node or an edge. In this simple example we have simply returned all the nodes in the model.\n\nAnother example of using a function:\n\n```javascript\nimport { Node } from \"@visuallyjs/browser-ui\"\n\nlet selection = model.filter((obj) => {\n return obj.objType === Node.objectType && obj.data.maxValue < 150\n});\n\n```\n\nHere we return only nodes whose `maxValue` is less than 150.\n\n#### Filtering with a match object[](#filtering-with-a-match-object)\n\nAlternatively, you can pass a match object in to the `filter` method:\n\n```javascript\nlet selection = model.filter({\n maxValue:150\n});\n\n```\n\nHere we've told VisuallyJs we are interested only in vertices whose `maxValue` is exactly 150. Note that with a match object only exact matches are supported: we cannot recreate the previous example in which vertices whose `maxValue` was less than 150 are returned.\n\nYou can match an arbitrary number of values:\n\n```javascript\nlet selection = model.filter({\n maxValue:150,\n lorem:\"ipsum\"\n});\n\n```\n\nHere we get vertices with a `maxValue` of 150 and a `lorem` of \"ipsum\".\n\n#### Partial matches with a match object[](#partial-matches-with-a-match-object)\n\nYou can instruct VisuallyJs that an object that matches at least one entry in the match object should be included in the output (by default, every value must match):\n\n```javascript\nlet selection = model.filter({\n maxValue:150,\n lorem:\"ipsum\"\n}, true)\n\n```\n\n...by passing in `true` as the second argument to the `filter` function. So in this example we now get vertices that have a `maxValue` of 150 and/or a `lorem` of \"ipsum\".\n\n***\n\n### Selection mode[](#selection-mode)\n\nThis concept allows you to control what can be added to the selection by its type - it's basically a higher level version of the `filter` we just discussed.\n\nThere are 5 modes supported by a selection, of which the default is `mixed`:\n\n* **SelectionModes.mixed** Any combination of nodes, edges and groups is supported\n* **SelectionModes.isolated** Only a set of nodes/groups, OR a set of edges, but not a mix. Conceptually this means the selection works in a \"vertices only\" or \"edges only\" mode, where the selection object decides which of these is appropriate when a new addition is made. For instance, if you have a selection in isolated mode that already has one node, then no new edges may be added. If you subsequently remove that node, making the selection empty, you could then add an edge.\n* **SelectionModes.nodesOnly** Only nodes. No groups or edges.\n* **SelectionModes.groupsOnly** Only groups. No nodes or edges.\n* **SelectionModes.edgesOnly** Only nodes. No groups or nodes.\n\nThe mode for a selection can be set in its constructor:\n\n```javascript\nconst sel = new Selection(modelInstance, {\n mode: SelectionModes.edgesOnly\n})\n\n```\n\nor it can be set on an existing selection object:\n\n```javascript\nmySelection.setMode(SelectionModes.isolated)\n\n```\n\nIf you want to change the mode for the current selection of some model instance, you can do that programmatically:\n\n```javascript\nmodel.getSelection().setMode(SelectionModes.mixed)\n\n```\n\n***\n\n## Selecting Descendants[](#selecting-descendants)\n\nIf you are working with hierarchical data, you can use VisuallyJs to get a list of descendants of some vertex (and, optionally, the edges to and from each vertex):\n\n```javascript\nconst descendants = model.selectDescendants(someVertex)\n\n```\n\nThe return value is a [Selection](), with all of the methods discussed above available. By default this selection does not include the focus node or any edges, but there are a number of options you can provide to modify the behaviour:\n\n#### selectDescendants[](#selectdescendants)\n\nSelects all descendants of some Node or Group, and, optionally, the Node/Group itself.\n\nSignature\n\nselectDescendants(obj:string | [Node]() | [Group](), includeFocus:boolean, includeEdges:boolean)\n\nParameters\n\n| | | |\n| ------------ | ------------------------------- | ------------------------------------------------------------------------------------------ |\n| obj | string \\| [Node]() \\| [Group]() | Node/Group, or ID of Node/Group, to select |\n| includeFocus | boolean | Whether or not to include the focus node/group in the returned dataset. Defaults to false. |\n| includeEdges | boolean | Whether or not to include edges in the returned dataset. Defaults to false. |\n\nReturn value\n\n[VisuallyJsSelection]()\n\nSo this call would return all of a vertex's descendants plus the vertex itself:\n\n```javascript\nvar descendants = model.selectDescendants(someNode, true);\n\n```\n\nAnd this would get the descendants, the node itself, and any edges connecting the nodes in the set:\n\n```javascript\nvar descendants = model.selectDescendants(someNode, true, true);\n\n```\n\n***\n\n## Removing everything in a selection[](#removing-everything-in-a-selection)\n\nThis is a fairly common use case when working with a selection:\n\n```javascript\nlet selection = model.selectDescendants(someNode)\nmodel.remove(selection)\n\n```\n\nHere we used the `selectDescendants` method, but we could have used any method that returns a selection or path - `select`, `selectDescendants`, `filter` or `getPath`.\n\n***\n\n## Appending to selections[](#appending-to-selections)\n\nYou can append individual objects, other selections and also paths to a selection:\n\n```javascript\n// get a selection containing nodes 1, 2 and 3\nlet selection1 = model.select([\"1\", \"2\", \"3\"]);\n\n// get a path from node 1 to node 17\nlet path = model.getPath({source:\"1\", target:\"17\"});\n\n// append the path\nselection1.append(path);\n\n// append node 34\nselection1.append(\"34\")\n\n// get another selection\nlet selection2 = model.select([\"36\", \"25\"]);\n\n// append it\nselection1.append(selection2)\n\n\n```\n\n***\n\n## Limiting selection size[](#limiting-selection-size)\n\nYou can limit the number of group, nodes and/or edges in a selection or model's `currentSelection`. This can be useful in a few ways: maybe your app wants to enforce that only one node is selected at any point in time, for instance. Or maybe you want to maintain a selection queue of fixed size for some purpose.\n\n#### Limiting the model's current selection[](#limiting-the-models-current-selection)\n\nYou can provide constructor parameters to control this behaviour:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { Selection } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const modelOptions = {\n maxSelectedNodes: 1,\n maxSelectedGroups: 1,\n maxSelectedEdges: 1,\n selectionCapacityPolicy: \"discardNew\"\n}\n return <SurfaceComponent modelOptions={modelOptions}/>\n}\n\n```\n\nHere we have specified that at most 1 node, 1 group and 1 edge may be selected, and that when the user tries to add a new node or edge to the current selection, it should be discarded. The other option - the default option - for `selectionCapacityPolicy` is `Selection.DISCARD_EXISTING`, which takes the 0th element from the underlying list.\n\nYou can also control these values with setter methods:\n\n```javascript\ntk.setMaxSelectedNodes(4)\ntk.setMaxSelectedGroups(3)\ntk.setMaxSelectedEdges(3)\ntk.setSelectionCapacityPolicy(Selection.DISCARD_EXISTING)\n\n```\n\n### Limiting an AdHoc selection[](#limiting-an-adhoc-selection)\n\nTo set limits and control the capacity policy of an ad-hoc selection, these methods are available:\n\n```javascript\nvar sel = model.select() // create an empty selection\nsel.setMaxNodes(4)\nsel.setMaxEdges(3)\nsel.setCapacityPolicy(Selection.DISCARD_EXISTING);\n\n```","url":"https://visuallyjs.com/react/docs/apps/model/selections","lib":"react","topic":"apps"},"docs/apps/model/undo-redo.md":{"title":"Undo Redo","body":"# Undo/redo\n\nVisuallyJs offers a comprehensive undo/redo manager, which is fully integrated into all the model and UI operations.\n\n## Transactions[](#transactions)\n\nAt the core of the undo/redo mechanism now is the concept of a `Transaction` - a set of operations which should be treated as an atomic unit. Certain internal methods in VisuallyJs use transactions, and it is also possible for a library user to declare their own.\n\nThe most direct way to work with transactions is via the `transaction` method on the model, which takes as argument a function to run inside the transaction. For instance, in this code snippet, we have some node that we wish to delete, and we're going to delete every other node this is connected to, inside a transaction. If the user subsequently undoes the operation, VisuallyJs will restore every node that was deleted, along with the edges that were deleted:\n\n```typescript\n\nconst someNode:Node = ....\n\nmodel.transaction(() => {\n\n // map all the edges for which this node is the source and get the target vertex\n const otherNodes = someNode.getSourceEdges().map(e => e.target)\n // remove them\n otherNodes.forEach(n => model.removeNode(n))\n // remove the focus node\n model.removeNode(someNode)\n \n})\n\n```\n\n### Opening a transaction[](#opening-a-transaction)\n\nTo open a new transaction the basic call is:\n\n```text\nmodel.openTransaction()\n\n```\n\nAssuming you do not have a transaction already open this will create a new transaction in VisuallyJs. If you do have a transaction already open the method call as shown will throw an Error. VisuallyJs offers three flags you can use to instruct it what to do if a transaction is already open:\n\n***Commit the current transaction and open a new one***\n\n```text\nimport { COMMIT_CURRENT } from '@visuallyjs/browser-ui'\n\nmodel.openTransaction(COMMIT_CURRENT)\n\n```\n\n***Rollback the current transaction and open a new one***\n\n```text\nimport { ROLLBACK_CURRENT } from '@visuallyjs/browser-ui'\n\nmodel.openTransaction(ROLLBACK_CURRENT)\n\n```\n\n***Append to the current transaction without opening a new one***\n\n```text\nimport { APPEND_TO_CURRENT } from '@visuallyjs/browser-ui'\n\nmodel.openTransaction(APPEND_TO_CURRENT)\n\n```\n\n### Closing a transaction[](#closing-a-transaction)\n\nTo close the current transaction you can either commit it or roll it back:\n\n```javascript\nmodel.commitTransaction()\n\n```\n\n```js\nmodel.rollbackTransaction()\n\n```\n\nIf there is no current transaction when these methods are called no action is taken.\n\n### Closing a transaction that has been appended to[](#closing-a-transaction-that-has-been-appended-to)\n\nIf you use `APPEND_TO_CURRENT` when opening a transaction, and there was a current transaction at the time, you cannot directly commit or rollback the transaction: calling either of the above methods will result in a log message, but the transaction will remain open. VisuallyJs maintains a stack of append calls for the current transaction, and if you call `commitTransaction()` or `rollbackTransaction()` when there are append calls on the stack, VisuallyJs pops the stack instead of closing the transaction. Only when the append stack is empty will a `commitTransaction()` or `rollbackTransaction()` call succeed.\n\n***\n\n## Internal transactions[](#internal-transactions)\n\nAs mentioned above, VisuallyJs performs a few key operations inside a transaction, These occur without user intervention and are included here purely for information.\n\n* When a drag starts, a transaction is opened, and when the drag stops the transaction is closed. Since a drag cannot start in the middle of the execution of some other code (except perhaps in the case of a testing scenario), this transaction is opened with no flag to define how it should behave if there is an existing transaction: no transaction should already exist. If you see an error logged about opening a transaction when a drag starts then you have forgotten to close a transaction somewhere.\n\n* `setMagnetizedPosition` operates within a transaction. All repositioning that occurs when a vertex is set and magnetized is bundled up into a single transaction (as more than one vertex generally moves when using the magnetizer).\n\n* When a vertex is removed, a transaction is created and the vertex is removed along with any edges connected to it inside that transaction. The user can then undo the vertex and edge deletions as one operation.\n\n***\n\n## Constants[](#constants)\n\nIf you're using Javascript instead of Typescript, the constants you need are:\n\n```javascript\nexport const COMMIT_CURRENT = \"commitCurrent\"\nexport const ROLLBACK_CURRENT = \"rollbackCurrent\"\nexport const APPEND_TO_CURRENT = \"appendToCurrent\"\n\n```","url":"https://visuallyjs.com/react/docs/apps/model/undo-redo","lib":"react","topic":"apps"},"docs/apps/nodes-and-groups/dragging.md":{"title":"Dragging","body":"# Dragging Nodes and Groups\n\nBy default, all node/group elements rendered by the UI will be made draggable, and the default behaviour of a draggable element is that it can be dragged to anywhere on the canvas. No special treatment is needed for touch devices - VisuallyJs abstracts that away.\n\n## Drag options[](#drag-options)\n\nYou can provide `dragOptions` when you render a UI. The most common reason for doing this is that you want to restrict the areas of your elements that your users can use to drag the element, for which you can provide a `cssFilter`:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n dragOptions: {\n cssFilter: \".someClass, .someClass *, .someOtherClass *\"\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nThis instructs VisuallyJs to not allow dragging to start when the mousedown/touchstart event occurs on an element that matches the given selector.\n\nThe full list of options is:\n\nDragOptions\n\nOptions for element drag\n\n| Name | Type | Description |\n| ------------------ | -------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| autoPan? | boolean | Defaults to true, meaning the canvas will pan automatically to track elements that have been dragged out of the visible area. |\n| autoPanDelta? | number | When auto-panning, this is the number of pixels that the canvas repositions itself on each tick. Defaults to 5. |\n| autoPanRepeat? | number | When auto-panning, this is the speed (in milliseconds) at which the canvas repositions itself. Defaults to 15ms. |\n| canDrop? | (candidate:[Node]() \\| [Group](), target:[Node]() \\| [Group](), onCanvas:boolean) => boolean | Optional function that is invoked at the start of a drag, and which identifies allowed drop targets. Each target - the canvas, nodes and groups - is passed in turn to this method; returning false indicates that the given target is not valid for that drag. |\n| constrainFunction? | [DragConstrainFunction\\<E>]() | Optional function to use to constrain element dragging. |\n| cssFilter? | string | Optional CSS3 selector identifying parts of nodes/groups that should not cause a drag to start. |\n| filter? | [VertexDragFilter\\<E>]() | Optional function to invoke prior to a drag starting. |\n\n## Preventing dragging[](#preventing-dragging)\n\nDragging can be switched off in a few ways.\n\n### All elements[](#all-elements)\n\nIf you wish to switch off dragging for all elements you can set that in your render options:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n elementsDraggable: false\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n### Per element[](#per-element)\n\nYou can also control element dragging by writing a `data-vjs-not-draggable` attribute onto your node/group DOM element:\n\n```html\n<div data-vjs-not-draggable=\"true\">\n This vertex is not draggable.\n</div>\n\n```\n\n### Programmatically[](#programmatically)\n\nIf you want to enable/disable dragging for some specific element on an ad-hoc basis you can use the `setDraggable` method:\n\n```javascript\n\nsurface.setDraggable(\"1\", false) // mark node \"1\" as not draggable, using its id\n\n\n```\n\n`setDraggable` takes as argument either a vertex id, a vertex object, or a DOM element.\n\n## Dragging on a grid[](#dragging-on-a-grid)\n\nYou can impose a grid on the elements in a surface:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n grid: {\n size: {\n width: 50,\n height: 50\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nThe full list of options supported by grid are defined in the [GridOptions]() interface:\n\nGridOptions\n\nOptions for a grid in the UI\n\n| Name | Type | Description |\n| ---------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------- |\n| fitGroupsToGrid? | boolean | Whether or not to ensure calculated group sizes (from auto sized groups) are a multiple of the grid size in each axis. Defaults to false. |\n| size? | [Grid]() | Width/height of the grid cells |\n| snap? | boolean | Whether or not to snap elements to the grid when dragging. Defaults to false. |\n\n## Magnetizing[](#magnetizing)\n\nVisuallyJs has a built in \"magnetizer\", which provides a means to nudge elements around in your UI so that things don't overlap. There are a few different ways to use the magnetizer, and it is covered in full [on this page](/react/docs/apps/magnetizer.md). In the canvas below we're using the magnetizer in `constant` mode, so that as you drag a vertex the other vertices are moved aside. We've also switched on `trackback`, which causes vertices to try to move back to their original position wherever possible.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n magnetizer: {\n constant: true,\n trackback: true\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n## Drag events[](#drag-events)\n\nThe UI posts a few events to which you can subscribe in order to track the movement of vertices on your canvas. These events can be subscribed to either when creating the surface:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { EVENT_NODE_MOVE_END } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n dragOptions: {\n events: {\n $[EVENT_NODE_MOVE_END]: (params) => {\n // a node was moved\n }\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nor you can bind to them after creating the surface:\n\n```javascript\n\nsurface.bind(EVENT_NODE_MOVE_END, (params) => {\n // a node was moved\n})\n\n```\n\nThe full list of events you can map to is:\n\n| Name | Value | Payload | Description |\n| ------------------------- | ---------------------------------- | ------------------------- | ----------------------------------------------------------------------- |\n| EVENT\\_GROUP\\_MOVE | \"group<!-- -->:move<!-- -->\" | [VertexMoveParams]() | Fired each time the mouse/pointer moves while a group is being dragged. |\n| EVENT\\_GROUP\\_MOVE\\_END | \"group:move<!-- -->:end<!-- -->\" | [VertexMoveEndParams]() | Fired at the end of a group drag |\n| EVENT\\_GROUP\\_MOVE\\_START | \"group:move<!-- -->:start<!-- -->\" | [VertexMoveStartParams]() | Fired as the user starts to drag a group |\n| EVENT\\_NODE\\_MOVE | \"node<!-- -->:move<!-- -->\" | [VertexMoveParams]() | Fired each time the mouse/pointer moves while a node is being dragged. |\n| EVENT\\_NODE\\_MOVE\\_ABORT | \"node:move<!-- -->:abort<!-- -->\" | [VertexMoveStartParams]() | Fired if a node drag is aborted |\n| EVENT\\_NODE\\_MOVE\\_END | \"node:move<!-- -->:end<!-- -->\" | [VertexMoveEndParams]() | Fired at the end of a node drag |\n| EVENT\\_NODE\\_MOVE\\_START | \"node:move<!-- -->:start<!-- -->\" | [VertexMoveStartParams]() | Fired as the user starts to drag a node |\n\n## Auto pan[](#auto-pan)\n\nVisuallyJs will auto pan a canvas when a node/group is dragged outside of the visible bounds. This can be controlled with a few flags set inside the `dragOptions`:\n\n* **autoPan** Set to false if you wish to switch off auto panning.\n* **autoPanDelta** Defaults to 5 pixels. This is the amount by which the canvas will pan on each tick of the timer.\n* **autoPanRepeat** The time in milliseconds between each tick of the auto pan timer. Defaults to 10 milliseconds.\n\n### Switching off auto pan[](#switching-off-auto-pan)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n dragOptions: {\n autoPan: false\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n### Changing auto pan repeat time[](#changing-auto-pan-repeat-time)\n\nHere we tell VisuallyJs to pan the canvas every 5ms instead of the default:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n dragOptions: {\n autoPanRepeat: 5\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n### Changing auto pan delta[](#changing-auto-pan-delta)\n\nHere we tell VisuallyJs to move 15 pixels on each step instead of the default:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n dragOptions: {\n autoPanDelta: 15\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n## Identifying drop targets[](#identifying-drop-targets)\n\nBy default, an element can be dragged to any position on the canvas, and into any group. You can use the `canDrop` option of `dragOptions` to restrict where an element can be dropped:\n\n```javascript\ndragOptions:{\n canDrop:(candidate, target, onCanvas) => {\n // return true if the candidate can be dropped on the target\n }\n}\n\n```\n\nThe arguments passed to `canDrop` are:\n\n* **candidate** The node or group being dragged.\n* **target** The node, group, or canvas that is a potential drop target.\n* **onCanvas** A boolean indicating if the target is the canvas.\n\nVisuallyJs calls this function for every possible drop target when a drag starts. If you return `false` for a given target, VisuallyJs will not allow the candidate to be dropped there.\n\n## Drag groups[](#drag-groups)\n\nA `DragGroup` models a group of vertices that should be dragged together. You can have any number of drag groups in your canvas. When you assign a vertex to a drag group you indicate to VisuallyJs whether that vertex should be an `active` member - meaning that when it is dragged all of the other vertices in the drag group are also dragged - or that it should be a `passive` member - meaning that when it is dragged no other members should be dragged, but that it should be dragged whenever an `active` member is dragged.\n\n### Assigning drag groups[](#assigning-drag-groups)\n\nTo assign vertices to drag groups you need to include the `DragGroupsPlugin`:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { DragGroupsPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: DragGroupsPlugin.type,\n options: {\n assignDragGroup: (v) => {\n return { id:'dragGroup', active:v.type === 'main' }\n }\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nThe key piece to note is the `assignDragGroup` function that you provide. In the above example our `assignDragGroup` function instructs VisuallyJs to add every vertex to a group called `\"dragGroup\"`, but that the vertex should only be an `active` member if it has a `type` of `\"main\"`.\n\nConsider this dataset:\n\n```javascript\n{\n nodes:[\n {\"id\":\"1\",\"left\":50,\"top\":50,\"type\":\"main\"},\n {\"id\":\"2\",\"left\":250,\"top\":160},\n {\"id\":\"3\",\"left\":350,\"top\":100},\n]\n\n```\n\nWe have one `\"main\"` vertex and two other vertices. In the canvas below, try dragging the large green box around. You'll see the two red boxes drag along with it. Now try dragging one of the red boxes - nothing else moves. This is because all of the nodes are inside a drag group, but the large green node is marked `active` and the red nodes are marked `passive`, due to the `assignDragGroup` function shown above:\n\n**********\n\nThe key is the `assignDragGroup` function that we provide. In the implementation above we do two things:\n\n* all vertices are assigned to a drag group called `\"dragGroup\"`\n* The vertex whose `type` is `\"main\"` is marked `active:true`; the others are marked `active:false`\n\n### Multiple drag groups[](#multiple-drag-groups)\n\nOur example above just used a single drag group, but we can have as many of these as we want. For instance, here's a canvas in which all the red elements are dragged in a single group, and all the green elements are dragged in a different group:\n\n**********\n\nThis was an even simpler setup - we just use each node's `type` to specify its drag group:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { DragGroupsPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: DragGroupsPlugin.type,\n options: {\n assignDragGroup: (v) => {\n return v.type\n }\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nEvery element in this example is marked `active` because that's the default if you do not specify it. All we had to do in this example is return the name of a drag group and VisuallyJs adds the vertex as an active participant to that group.\n\nOur dataset in this example is:\n\n```javascript\n{\n nodes:[\n {\"id\":\"1\",\"left\":50,\"top\":50,\"type\":\"green\"},\n {\"id\":\"2\",\"left\":150,\"top\":160,\"type\":\"red\"},\n {\"id\":\"3\",\"left\":200,\"top\":30,\"type\":\"red\"},\n {\"id\":\"4\",\"left\":250,\"top\":100,\"type\":\"green\"},\n]\n\n```\n\n### Example - annotating objects[](#example---annotating-objects)\n\nA good example of how this functionality is useful is the concept of annotating objects in a diagram - explanatory notes for some given vertex that you want to place near the vertex, but whose positioning you want to adjust in each case to suit the diagram. When you drag a vertex that has annotations you want the annotations to move with the vertex, but you want to be able to position the annotations without moving the vertex itself.\n\nConsider this dataset:\n\n```javascript\n{\n nodes:[\n {\"id\":\"1\",\"type\":\"main\",\"left\":50,\"top\":50},\n {\"id\":\"2\",\"type\":\"main\",\"left\":300,\"top\":50},\n {\"id\":\"3\",\"type\":\"annotation\",\"text\":\"I belong to node 1\",\"ref\":\"1\",\"left\":70,\"top\":-40},\n {\"id\":\"4\",\"type\":\"annotation\",\"text\":\"I belong to node 1\",\"ref\":\"1\",\"left\":-90,\"top\":120},\n {\"id\":\"5\",\"type\":\"annotation\",\"text\":\"I belong to node 2\",\"ref\":\"2\",\"left\":380,\"top\":160},\n]\n\n```\n\nWe've got two nodes of type `main`, and three nodes of type `annotation`, each of which have a `ref` member, which points to a `main` node. We want to be able to drag our `main` nodes around and have the `annotation` nodes follow, but we also want to be able to position the `annotation` nodes around the `main` nodes where we please. This is easily achieved:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { DragGroupsPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: DragGroupsPlugin.type,\n options: {\n assignDragGroup: (v) => {\n return v.type === 'main' ? v.id : {id:v.data.ref, active:false}\n }\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n* For nodes of type `main`, we just return the node's id: `v.id`\n* For nodes of type `annotation`, we return the `ref` as the drag group id, and mark the vertex passive: `{id:v.data.ref, active:false}`.\n\nWhich gives us this arrangement:\n\n**********\n\nAnd there you have it! Annotated objects using just a few lines of configuration.\n\n#### Cleaning up annotations[](#cleaning-up-annotations)\n\nOne thing to keep in mind is that the annotations and the edges that connect them to their reference nodes will not automatically be removed by VisuallyJs if the reference node is removed from the dataset. To handle this we can use another of VisuallyJs's capabilities you won't find in other libraries in this space - [Transactions](/react/docs/apps/model/undo-redo.md#transactions) - to cleanup the annotations, but in an undo/redo friendly way.\n\nTry clicking one of the red circle buttons below. We'll remove the node the button belongs to, and we'll also remove any annotations that are attached to it (code follows below) :\n\n**********\n\nTo remove a node and its annotations in an undo-friendly way, we find everything we want to delete and then perform all the removals inside a transaction. An example function, into which you'd pass the model and the ID of the node to cleanup, is:\n\n```typescript\nfunction removeNode(model:VisuallyJsModel, nodeId:string) {\n \n // find all annotation nodes that reference this node\n const annotations = model.getNodes().filter(n => n.data.ref === nodeId)\n\n // in a transaction, remove all the annotation nodes and then the focus node. Edges will be cleaned up automatically, and if the user clicks undo, the entire transaction is rolled back as one.\n model.transaction(() => {\n annotations.forEach(a => model.removeNode(a))\n model.removeNode(nodeId)\n })\n}\n\n```\n\n<br />\n\nWe can integrate that snippet into our component as shown below. We have a click listener on a specific button, in which we get the model and the node ID from the context used to render the node:\n\n```jsx\nviewOptions={{\n nodes:{\n main:{\n jsx:(ctx) => <div>\n <div data-vjs-delete={true} onClick={() => {\n const annotations = ctx.model.getNodes().filter(n => n.data.ref === ctx.data.id) \n ctx.model.transaction(() => {\n annotations.forEach(a => ctx.model.removeNode(a))\n ctx.model.removeNode(ctx.data.id)\n }) \n }}/>\n </div>\n }\n }\n}}\n\n```\n\n## CSS Classes[](#css-classes)\n\nThere are a number of CSS classes assigned to various parts of the UI during a node/group drag. These can be used to easily add visual cues for your users, and also to manage z-index for the best user experience.\n\n| Class | Description |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `vjs-drag-active` | Assigned to any element that is a candidate drop target for an edge that is being dragged |\n| `vjs-drag-hover` | Assigned to any element that is the current drop target for an edge that is being dragged |\n| `vjs-drag-hover-cannot-drop` | Assigned to a vertex or the canvas when an element that is being dragged on the canvas is hovering over it but drop is not allowed. |\n| `vjs-drag-original-group` | Assigned to a group element when one of its children is being dragged. This can be useful to help manage z-index: we recommend using this class to set a z-index for the drag parent group above that of the other groups, which will ensure that the element you are dragging will appear on top of other groups. |\n| `vjs-element-dragging` | Assigned by the Surface to a vertex element that is being dragged |\n| `vjs-group-child-element-dragging` | Assigned by the Surface to the group parent of a vertex element that is being dragged, if applicable. You can use this class for a couple of things - to show that a child element is being dragged, of course, but also a good idea is to use this class to bump the z-index for any group that has it assigned, to put that group above other groups. This ensures that as you drag a child vertex over to some other group, it appears on top of that group in the UI. |\n| `vjs-most-recently-dragged` | Assigned by the Surface to the vertex element(s) that was/were the most recently dragged elements. |\n| `vjs-surface-element-dragging` | Assigned by the Surface to its container when a node or group is being dragged |","url":"https://visuallyjs.com/react/docs/apps/nodes-and-groups/dragging","lib":"react","topic":"apps"},"docs/apps/nodes-and-groups/events.md":{"title":"Events","body":"# Events\n\nYou can map a number of events to nodes and groups in a view, and when the event fires, VisuallyJs will supply the event from the browser, the DOM element on which the event occurred, and the model object related to the event.\n\nYou can bind a listener to anything listed as a **BindableViewEvent**:\n\nBindableViewEvent\n\nEvents that can be bound in a view.\n\n`EVENT_CLICK | EVENT_DBLCLICK | EVENT_TAP | EVENT_DBLTAP | EVENT_CONTEXTMENU | EVENT_MOUSEDOWN | EVENT_MOUSEOUT | EVENT_MOUSEUP | EVENT_MOUSEOVER | EVENT_MOUSEMOVE`\n\n## Mapping events[](#mapping-events)\n\nTo map an event, provide an `events` object inside a node or group definition:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { NodeEventCallbackPayload, GroupEventCallbackPayload, DEFAULT, EVENT_TAP, EVENT_MOUSEOVER } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const viewOptions = {\n nodes: {\n [DEFAULT]: {\n jsx: (ctx) => <div className='aNode'>{ctx.data.id}</div>,\n events: {\n [EVENT_TAP]: (p:NodeEventCallbackPayload) => {\n alert('You tapped on node ' + p.obj.id)\n }\n }\n }\n },\n groups: {\n [DEFAULT]: {\n jsx: (ctx) => <div className='aGroup'>{ctx.data.id}</div>,\n events: {\n [EVENT_MOUSEOVER]: (p:GroupEventCallbackPayload) => {\n console.log('Mouse over ' + p.obj.id)\n }\n }\n }\n }\n}\n return <SurfaceComponent viewOptions={viewOptions}/>\n}\n\n```\n\n## Event Payload[](#event-payload)\n\nThe payload for events mapped in a view depends on the vertex type:\n\n### Nodes[](#nodes)\n\nNodeEventCallbackPayload\n\nThe payload passed to a NodeEventCallback\n\n| Name | Type | Description |\n| ----- | ------------------- | ------------------------------------------------------------- |\n| e | MouseEvent | The pointer event that caused the event handler to be invoked |\n| el | EL | Element that represents the vertex in the UI |\n| model | [VisuallyJsModel]() | The underlying VisuallyJs model |\n| obj | [Node]() | The model object for the vertex |\n| ui | UICore\\<EL> | The UI that rendered this vertex |\n\n### Groups[](#groups)\n\nGroupEventCallbackPayload\n\nThe payload passed to a GroupEventCallback\n\n| Name | Type | Description |\n| ----- | ------------------- | ------------------------------------------------------------- |\n| e | MouseEvent | The pointer event that caused the event handler to be invoked |\n| el | EL | Element that represents the vertex in the UI |\n| model | [VisuallyJsModel]() | The underlying VisuallyJs model |\n| obj | [Group]() | The group in the model |\n| ui | UICore\\<EL> | The UI that rendered this vertex |","url":"https://visuallyjs.com/react/docs/apps/nodes-and-groups/events","lib":"react","topic":"apps"},"docs/apps/nodes-and-groups/groups.md":{"title":"Groups","body":"# Groups\n\nGroups act as a container for zero or more nodes or other groups. In the UI, these can be collapsed, and edges to/from the nodes/groups inside the group are then temporarily relocated to the group container. There is no limit imposed on how deeply groups may be nested.\n\nGroups have in common with nodes, edges and ports the two concepts of `id` and of `type`, and as with the other graph objects, `type` will be set to `\"default\"` if it cannot be determined. Group IDs and types either follow the default rules (ie. they are given by the `id` and `type` parameters, respectively, in the group's data), or they are derived by applying the current `idFunction` and `typeFunction`.\n\nGroups, as with the other graph objects, can have arbitrary JSON data associated with them.\n\n## Rendering[](#rendering)\n\nAs shown in the various examples at the start of this page, groups are rendered using client side templates just as nodes are. They are declared inside a view alongside nodes, edges and ports, and broadly follow the same syntax as node definitions - but there are a number of extra flags that can be set on a group definition.\n\nA simple example to start:\n\n```jsx\n viewOptions = {\n nodes:{\n [DEFAULT]:{\n jsx:(ctx) => <div className=\"aNode\">{ctx.data.id}</div>\n }\n },\n groups:{\n groupType1:{\n jsx:(ctx) => <div className=\"aGroup\">\n <h1>{ctx.data.id}</h1>\n <div data-vjs-group-content=\"true\"/>\n </div>,\n constrain:true\n }\n } \n}\n\n```\n\nHere we declare that member of groups of type `groupType1` are constrained to the group element (that is, they cannot be dragged outside of the group's bounds).\n\n## Collapse/Expand[](#collapseexpand)\n\nYou can collapse/expand a group using the `collapseGroup` and `expandGroup` methods on the `Surface` widget. When you collapse a group, any edges from any of the member nodes/groups in the group to nodes/groups outside of the group are relocated to the group's container, and a CSS class is applied to the group's container, indicating the collapsed state. When you subsequently expand the group, the edges are placed back onto their appropriate nodes/groups.\n\nIt is important to note that when a group is collapsed, VisuallyJs does not hide the member nodes/groups automatically for you. But a CSS class of `vjs-group-collapsed` is added to the group's container, for you to handle this in your CSS.\n\nThe anchor to be used in the collapsed state can be specified in the group definition in the `viewOptions`:\n\n```jsx\nimport { AnchorLocations } from \"@visuallyjs/browser-ui\"\n\nconst viewOptions = {\n groups:{\n \"groupType1\":{\n jsx:(ctx) => <div className=\"foo\"><h1>A GROUP</h1></div>,\n anchor:AnchorLocations.Continuous\n }\n } \n}\n\n```\n\nAny valid anchor can be used here.\n\n### Collapsed Group Size[](#collapsed-group-size)\n\nWhen you're using the model for your vertex sizes (ie. you're not relying on CSS to establish sizes), and a group is collapsed, the UI resolves the size to render it at by working through a chain of four sources, from highest to lowest priority.\n\n***\n\n#### 1. `getGroupCollapsedSize` (constructor option)[](#1-getgroupcollapsedsize-constructor-option)\n\nAn optional function `(group: Group, currentSize: Size) => Size` passed when constructing the surface or UI instance. It is called first on every collapse. If it returns a non-null value, that value is used and the chain stops.\n\nReturn `null` or `undefined` to fall through to the next source. This is the right place for size logic that depends on runtime state or per-instance group data.\n\n***\n\n#### 2. `collapsedSize` on `GroupMapping`[](#2-collapsedsize-on-groupmapping)\n\nA static `Size` value declared in the view definition for a group type. Used when `getGroupCollapsedSize` was not supplied or returned null. Applies uniformly to every group of that type.\n\n***\n\n#### 3. `collapsedSize` on `ShapeType`[](#3-collapsedsize-on-shapetype)\n\nA static `Size` value on a shape library shape definition. Only consulted when the shape's `objectType` is `Group`. Useful in shape-library-driven UIs where group appearance is controlled through the shape library rather than the view.\n\n***\n\n#### 4. `defaultCollapsedGroupSize` (constructor option)[](#4-defaultcollapsedgroupsize-constructor-option)\n\nA `Size` value passed when constructing the surface or UI instance. Acts as a global fallback for all groups when none of the above sources produce a value. If omitted, the built-in default of `{ width: 200, height: 150 }` is used.\n\n***\n\n### Magnetizing when collapsed/expanded[](#magnetizing-when-collapsedexpanded)\n\nBy default, the surface widget will run the [Magnetizer](/react/docs/apps/magnetizer.md) whenever a group is collapsed or expanded: when a group is expanded, surrounding elements are adjusted so as to ensure the group does not intersect with any other element. When a group is collapsed, the rest of the elements in the view are gathered in towards the collapsed group. This behaviour can be switched off - see the `afterGroupChange` flag in the [Surface widget magnetizer options](/react/docs/apps/magnetizer.md#surface-widget)\n\n## Templating[](#templating)\n\n### Specifying the canvas[](#specifying-the-canvas)\n\nIt is not necessarily the case that you wish to use your entire group template as the parent of the group's members. You can set a `data-vjs-group-content` attribute on the element that you wish to have acting as the parent for the members (you might have noticed this in the examples above):\n\n```jsx\nexport default MyComponent() {\n ...\n return <div className=\"aGroup\">\n <h1>{ctx.data.title}</h1>\n <div data-vjs-group-content={true} className=\"aGroupInner\">\n { /* Child elements go here */ }\n </div>\n </div>\n}\n\n```\n\nWhenever a group is resized by the [auto sizing code](#autosizing-groups) in the surface, the surface looks for an element in the group with this attribute, and if found, this is the element to which the surface applies the change of size. Otherwise the size is applied to the group's main element. Keep this in mind from a CSS perspective: your CSS should allow the size of the content area to mandate the size of its parent. Scroll/auto overflow is not supported inside a group element.\n\n## Autosizing Groups[](#autosizing-groups)\n\nGroups can be configured to automatically resize themselves to encompass the extents of their child nodes/groups, via the `autoSize` flag on a group definition in a view:\n\n```javascript\n{\n groups:{\n \"groupType1\":{\n ...\n autoSize:true\n ...\n },\n \"groupType2\":{\n ...\n autoSize:true,\n maxSize:{width:600, height:600}\n ...\n }\n }\n}\n\n```\n\nIn this example, both group types are declared to auto size, but `groupType2` will grow to a maximum of 600 pixels in each axis.\n\nAutosizing is run after a data load or when data exists in a model instance and it is rendered to some surface.\n\n### On-demand autosizing[](#on-demand-autosizing)\n\nYou can run auto sizing on demand on a list of groups, or on all groups, with the `autoSizeGroups` method of the UI:\n\nautoSizeGroups(groups:Array<[Group]()>, force:boolean)\n\n[show definition]()\n\nor on a single group:\n\nautoSizeGroup(group:[Group](), force:boolean)\n\n[show definition]()\n\n## Layouts[](#layouts)\n\nBy default, every group has an `Absolute` layout assigned to it. If your node data has `left`/`top` properties in it, these values will automatically be used to place nodes/groups inside of their parent groups.\n\n### Specifying in the view[](#specifying-in-the-view)\n\nTo specify the layout for a specific type of group, set it in that group's entry in your view:\n\n```javascript\n {\n ...\n groups:{\n \"someGroupType\":{\n ...\n layout:{\n type:HierarchyLayout.type, \n options:{\n orientation:\"vertical\"\n }\n }\n }\n }\n \n ...\n }\n\n```\n\nThe format of the `layout` parameter is identical to the `layout` parameter in the root of the `view`.\n\n### Layout on demand[](#layout-on-demand)\n\nYou can force a layout in a group with the `relayoutGroup` method:\n\nrelayoutGroup(groupOrId:string | [Group](), reason:GroupRelayoutReason)\n\n[show definition]()\n\nThis will cause a layout to be run immediately on the given group (which may be passed in as the group object, or just its id)\n\n### Ad-hoc group layout[](#ad-hoc-group-layout)\n\nYou can run an ad-hoc layout on a group at any time:\n\nadHocGroupLayout(group:string | [Group](), layoutParams:{\n\n<br />\n\n options:[LayoutParameters](),\n\n<br />\n\n type:string\n\n<br />\n\n})\n\n[show definition]()\n\nThis will cause the group's layout to be temporarily swapped out with a layout conforming to the spec you provide in `layoutParams`, the ad-hoc layout will then be run, and the original group layout reinstated (but without running the original layout again of course!)\n\n#### Relationship to group size[](#relationship-to-group-size)\n\nBy default, a layout in a group will cause the auto size routine to be run for the group immediately afterwards.\n\n***\n\n## Elastic groups[](#elastic-groups)\n\nElastic groups allow your users to dynamically resize a group by dragging its child elements around inside of it. To setup a group as elastic:\n\n```javascript\n{\n groups:{\n default:{\n elastic:true,\n minSize:{ width:250, height:250 } // optional, but it does tend to help aesthetically to have a minSize.\n }\n }\n}\n\n```\n\n### Dragging elements out of an elastic group[](#dragging-elements-out-of-an-elastic-group)\n\nTo drag a child node out of an elastic group, hold down the Shift key prior to the drag (and hold it for the duration of the drag):\n\n**********\n\nSuppressing resize\n\nOrdinarily, dragging a child vertex of an elastic group will cause the group to resize to fit its content. Holding the `shift` key can also be used to switch off elastic resize while an element is being dragged.\n\n### Resizing an elastic group from left/top[](#resizing-an-elastic-group-from-lefttop)\n\nBy default an elastic group (in fact *any* group) will not resize from the left and/or top edge. We call this \"shrink from origin\", and you can switch it on via a flag on a group definition:\n\n```javascript\n {\n groups:{\n default:{\n elastic:true,\n allowShrinkFromOrigin:true,\n minSize:{ width:250, height:250 } // optional, but it does tend to help aesthetically to have a minSize.\n }\n }\n }\n\n```\n\nor on an ad-hoc basis by holding down the meta key (command on Macs) prior to the drag.\n\n### Nested elastic groups[](#nested-elastic-groups)\n\nElastic groups which are themselves children of another elastic group will relay size changes during dragging to their parent, so that the user can see what changes will be made to all the groups.\n\n***\n\n## View options[](#view-options)\n\nThe full list of options that are available on a group mapping is:\n\nReactGroupMapping\n\nDefinition of a group - its jsx, and behaviour.\n\n| Name | Type | Description |\n| --------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| jsx? | (ctx:[JsxWrapperProps<]()[Group]()>) => any | JSX used to render this group type. Optional; if you do not supply it a default template will be used. |\n| allowLoopback? | boolean | Whether or not to allow edges from this vertex back to itself. Defaults to true. This flag will not prevent an edge from a port back to the node/group to which it belongs - for that, see `allowVertexLoopback`. |\n| allowVertexLoopback? | boolean | Whether or not to allow edges from a port back to the vertex it belongs to. Defaults to true. |\n| anchor? | [AnchorSpec]() | Spec for the anchor to use for connections to children of the group when they are transferred to the group in its collapsed state. |\n| anchorPositionFinder? | [AnchorPositionFinder\\<any>]() | Optional function to call on connection drop, to determine the location for the target anchor for the new connection. Returning null from this indicates no preference, and VisuallyJs will use its own computed value. |\n| anchorPositions? | Array<[ObjectAnchorSpec]()> | Optional array of anchor positions to use. |\n| autoGrow? | boolean | Defaults to false, meaning that the group will not be resized if an item addition/removal or drag causes the bounds of the child members to change and the new size is greater than the previous size. |\n| autoShrink? | boolean | False by default. If true indicates that if a child member is dragged/added/removed and the group's size is recalculated to be smaller than the previous size, the new size should be applied. This also works if the group needs to shrink from its left and/or top edge. If you don't want that behaviour, set `allowShrinkFromOrigin` to false. |\n| autoSize? | boolean | False by default. This flag switches on both `autoShrink` and `autoGrow` and also enables support for shrinking a group from its left or top edge |\n| canDrop? | (v:[Node]() \\| [Group]()) => boolean | Optional interceptor that will be invoked to test whether a given node/group may be dropped onto this group. |\n| collapsedSize? | [Size]() | The size to use for this group type when it is collapsed. |\n| constrain? | boolean | False by default - nodes/groups may be dragged outside of the bounds of the group. |\n| defaultSize? | [Size]() | Optional default size to use for the vertex. This is not used to set the size in the DOM for a vertex - it is used to insert `width` and `height` values into the backing data for any vertex of this type that does not have them set. |\n| edgeType? | string | Type to assign to edges connected to this vertex as a source. |\n| elastic? | boolean | Similar to autoGrow, but the UI shows a visual prompt when a group will be resized as a result of dragging a child. |\n| elementsDraggable? | boolean | True by default - indicates that child members may be dragged around inside the group. |\n| events? | [GroupEventOptions\\<EL>]() | Optional map of event bindings. |\n| fitToGrid? | boolean | When sizing the group, ensure it fits the underlying grid, if there is one. |\n| ignore? | boolean | If true, vertices of this type will be ignored by this UI and not rendered. |\n| layout? | {<br /> options:[LayoutParameters](),<br /> type:string<br />} | Options for the group's layout. |\n| maxConnections? | number | Maximum number of connections this vertex supports. Default is 1. A value of -1 means no limit. |\n| maxSize? | [Size]() | Maximum size the group can grow to. If not specified the group can grow to an arbitrary size. Note that this behaviour can also be enforced via CSS. |\n| mergeStrategy? | string | When merging a type description into its parent(s), values in the child for `connector`, `anchor` and `anchors` will always overwrite any such values in the parent. But other values, such as `overlays`, will be merged with their parent's entry for that key. You can force a child's type to override *every* corresponding value in its parent by setting `mergeStrategy:'override'`. |\n| minSize? | [Size]() | Minimum size the group can be. |\n| padding? | number | Optional padding to set inside a group when computing an auto size. |\n| parent? | string \\| Array\\<string> | Optional ID of one or more edge definitions to include in this definition. The child definition is merged on top of the parent definition(s). Circular references are not allowed and will throw an error. |","url":"https://visuallyjs.com/react/docs/apps/nodes-and-groups/groups","lib":"react","topic":"apps"},"docs/apps/nodes-and-groups/overview.md":{"title":"Overview","body":"# Nodes and Groups\n\n## Nodes[](#nodes)\n\nA node represents some entity in your application - examples from the VisuallyJs starter apps are the various actions/questions etc in the flowchart, or a table or view in the schema builder, a step in the chatbot builder, etc. They can be rendered with any HTML you like - for instance, here we have a rendering of the sort of node you might find in a workflow builder application:\n\n**********\n\n## Groups[](#groups)\n\nGroups also represent an entity in your application, and they act as a container for zero or more nodes or other groups. A good example of this are the various groups in our network topology builder - a region, or a VPC, etc. Each of these represents an entity in the application which itself contains other nodes and/or groups. On this page we provide an overview of how to render nodes and groups, but groups are covered in more detail [on their own page](/react/docs/apps/nodes-and-groups/groups.md).\n\n**********","url":"https://visuallyjs.com/react/docs/apps/nodes-and-groups/overview","lib":"react","topic":"apps"},"docs/apps/nodes-and-groups/rendering-groups.md":{"title":"Rendering Groups","body":"# Rendering Groups\n\nGroups are declared inside a view alongside nodes and edges, and broadly follow the same syntax as node definitions - but there are a number of extra flags that can be set on a group definition.\n\n```jsx\n const viewOptions = {\n groups:{\n default:{\n jsx:(ctx) => <div className=\"workflow-group\">\n <div className=\"group-header\">\n <span className=\"group-icon\">📁</span>\n <span className=\"group-title\">{ctx.data.label || \"Process Group\"}</span>\n <span className=\"vjs-toggle-group-collapse\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"18 15 12 9 6 15\"></polyline>\n </svg>\n </span> \n </div>\n\n {/* The child nodes will be rendered inside this div */}\n <div className=\"group-content\" data-vjs-group-content></div>\n\n <div className=\"group-footer\">\n {ctx.data.items?.length || 0} items\n </div>\n </div>\n }\n } \n}\n\n```\n\nThe JSX shown above is what we use for the example group on the node/group overview page, which - with a dash of CSS - looks like this:\n\n**********\n\nTry clicking the caret in the top right corner - the group collapses and expands. We discuss this [below](#collapse/expand).\n\n## Specifying the canvas[](#specifying-the-canvas)\n\nIt is not necessarily the case that you wish to use your entire group template as the parent of the group's members. To specify where in your group you want to host child nodes/groups, set a `data-vjs-group-content` attribute on an element - for instance, in the example above, we have this:\n\n```jsx\n<div className=\"group-content\" data-vjs-group-content></div>\n\n```\n\nFor complex group representations this is something you'll often want to use.\n\nnote\n\nWhenever a group is resized by the [auto sizing code](#autosizing-groups) in the surface, the surface looks for an element in the group with this attribute, and if found, this is the element to which the surface applies the change of size. Otherwise the size is applied to the group's main element. Keep this in mind from a CSS perspective: your CSS should allow the size of the content area to mandate the size of its parent. Scroll/auto overflow is not supported inside a group element.\n\n## Nested groups[](#nested-groups)\n\nGroups may be nested to an arbitrary level:\n\n**********\n\nDepending on how your UI is configured (meaning how your CSS works to establish the size of the group elements in your UI), you may wish to switch on `autoSize` for your groups. In our example workflow group we set a `min-size` of `300px`, so we switched on `autoSize` (which is discussed [below](#autosizing-groups)) in order to get the parent group to expand:\n\n```jsx\nconst viewOptions = { \n groups:{\n default:{\n jsx:(ctx)=> <IntroGroup ctx={ctx}/>,\n autoSize:true,\n padding:10\n }\n }\n}\n\n```\n\nWe also specified `padding:10` so that some space appears around the child group.\n\n***\n\n## Autosizing Groups[](#autosizing-groups)\n\nGroups can be configured to automatically resize themselves to encompass the extents of their child nodes/groups, via the `autoSize` flag on a group definition in a view:\n\n```javascript\n{\n groups:{\n \"groupType1\":{\n ...\n autoSize:true\n ...\n },\n \"groupType2\":{\n ...\n autoSize:true,\n maxSize:{width:600, height:600}\n ...\n }\n }\n}\n\n```\n\nIn this example, both group types are declared to auto size, but `groupType2` will grow to a maximum of 600 pixels in each axis.\n\nAutosizing is run after a data load or when data exists in a model instance and it is rendered to some surface.\n\n***\n\n## Layouts[](#layouts)\n\nBy default, every group has an [AbsoluteLayout]() assigned to it. If your node data has `left`/`top` properties in it, these values will automatically be used to place nodes/groups inside of their parent groups.\n\n### Specifying in the view[](#specifying-in-the-view)\n\nTo specify the layout for a specific type of group, set it in that group's entry in your view:\n\n```javascript\n {\n ...\n groups:{\n \"someGroupType\":{\n ...\n layout:{\n type:HierarchyLayout.type, \n options:{\n orientation:\"vertical\"\n }\n }\n }\n }\n \n ...\n }\n\n```\n\nThe format of the `layout` parameter is identical to the `layout` parameter in the root of the `view`.\n\n#### Relationship to group size[](#relationship-to-group-size)\n\nBy default, a layout in a group will cause the auto size routine to be run for the group immediately afterwards.\n\n***\n\n## Collapse/Expand[](#collapseexpand)\n\nGroups can be collapsed and expanded. To add a control to your group to manage collapse/expand, you just need to add a CSS class of `.vjs-toggle-group-collapse` to some element.\n\n```jsx\n<span className=\"vjs-toggle-group-collapse\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\">\n <polyline points=\"18 15 12 9 6 15\"></polyline>\n </svg>\n</span>\n\n```\n\nWhen you collapse a group, any edges from any of the member nodes/groups in the group to nodes/groups outside of the group are relocated to the group's container, and a CSS class is applied to the group's container, indicating the collapsed state. When you subsequently expand the group, the edges are placed back onto their appropriate nodes/groups.\n\nIt is important to note that when a group is collapsed, VisuallyJs does not hide the member nodes/groups automatically for you. But a CSS class of `vjs-group-collapsed` is added to the group's container, for you to handle this in your CSS.\n\nThe anchor to be used in the collapsed state can be specified in the group definition in the `viewOptions`:\n\n```jsx\nimport { AnchorLocations } from \"@visuallyjs/browser-ui\"\n\nconst viewOptions = {\n groups:{\n \"groupType1\":{\n jsx:(ctx) => <div className=\"foo\"><h1>A GROUP</h1></div>,\n anchor:AnchorLocations.Continuous\n }\n } \n}\n\n```\n\nAny valid anchor can be used here.\n\n### Collapsed Group Size[](#collapsed-group-size)\n\nWhen you're using the model for your vertex sizes (ie. you're not relying on CSS to establish sizes), and a group is collapsed, the UI resolves the size to render it at by working through a chain of decision sources, from highest to lowest priority.\n\n* `getGroupCollapsedSize`\n\nAn optional function `(group: Group, currentSize: Size) => Size` passed into the `renderOptions` of your `SurfaceComponent`. It is called first on every collapse. If it returns a non-null value, that value is used and the chain stops.\n\nReturn `null` or `undefined` to fall through to the next source. This is the right place for size logic that depends on runtime state or per-instance group data.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n getGroupCollapsedSize: (group, currentSize) => {\n return { width:200, height:60 }\n}\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n* `collapsedSize`\n\nA static `Size` value declared in the view definition for a group type. Used when `getGroupCollapsedSize` was not supplied or returned null. Applies uniformly to every group of that type.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const viewOptions = {\n groups: {\n default: {\n collapsedSize: {\n width: 200,\n height: 60\n }\n }\n }\n}\n return <SurfaceComponent viewOptions={viewOptions}/>\n}\n\n```\n\n* `defaultCollapsedGroupSize`\n\nA `Size` value passed when constructing the surface or UI instance. Acts as a global fallback for all groups when none of the above sources produce a value.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n defaultCollapsedGroupSize: {\n width: 200,\n height: 60\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nLastly, if none of the previous sources returns a value, the built-in default of `{ width: 200, height: 150 }` is used.\n\nMagnetizing when collapsed/expanded\n\nBy default, the surface widget will run the [Magnetizer](/react/docs/apps/magnetizer.md) whenever a group is collapsed or expanded: when a group is expanded, surrounding elements are adjusted so as to ensure the group does not intersect with any other element. When a group is collapsed, the rest of the elements in the view are gathered in towards the collapsed group. This behaviour can be switched off - see the `afterGroupChange` flag in the [Surface widget magnetizer options](/react/docs/apps/magnetizer.md#surface-widget)\n\n## Elastic groups[](#elastic-groups)\n\nElastic groups allow your users to dynamically resize a group by dragging its child elements around inside of it. To setup a group as elastic:\n\n```javascript\n{\n groups:{\n default:{\n elastic:true,\n minSize:{ width:250, height:250 } // optional, but it does tend to help aesthetically to have a minSize.\n }\n }\n}\n\n```\n\nTry dragging the node inside the group - you'll see the group displays a skeleton element showing how it would be resized to accommodate the node's new position. On mouseup the group is then resized:\n\n**********\n\n### Dragging elements out of an elastic group[](#dragging-elements-out-of-an-elastic-group)\n\nTo drag a child node out of an elastic group, hold down the Shift key prior to the drag.\n\n### Suppressing resize[](#suppressing-resize)\n\nOrdinarily, dragging a child vertex of an elastic group will cause the group to resize to fit its content. Holding the `shift` key can also be used to switch off elastic resize while an element is being dragged.\n\n### Dragging the group and the node[](#dragging-the-group-and-the-node)\n\nIf you hold down the Meta key (Command on macs), you can drag child nodes/groups within their parent, and when the node reaches the bounds of the parent, the parent will relocate along with the child. It's easier to show this than explain it - try it on the canvas above.\n\n### Nested elastic groups[](#nested-elastic-groups)\n\nElastic groups which are themselves children of another elastic group will relay size changes during dragging to their parent, so that the user can see what changes will be made to all the groups.\n\n## Rendering content based on zoom[](#rendering-content-based-on-zoom)\n\nYou might want to show more detail when zoomed in and less detail when zoomed out. VisuallyJs provides a `useZoom` hook to assist you with this.\n\n```tsx\nimport { useZoom } from '@visuallyjs/browser-ui-react';\n\nexport default function ZoomDisplay({ ui, obj, model }) {\n const zoom = useZoom(ui);\n\n return (\n <div style={{ position: 'absolute', top: 10, left: 10, background: 'white', padding: '5px' }}>\n Current Zoom: {(zoom * 100).toFixed(0)}%\n {zoom > 1.5 && <p>High magnification active</p>}\n {zoom < 0.5 && <p>Low magnification active</p>}\n </div>\n );\n}\n\n```\n\n## View options[](#view-options)\n\nThe full list of options that are available on a group mapping is:\n\nReactGroupMapping\n\nDefinition of a group - its jsx, and behaviour.\n\n| Name | Type | Description |\n| --------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| jsx? | (ctx:[JsxWrapperProps<]()[Group]()>) => any | JSX used to render this group type. Optional; if you do not supply it a default template will be used. |\n| allowLoopback? | boolean | Whether or not to allow edges from this vertex back to itself. Defaults to true. This flag will not prevent an edge from a port back to the node/group to which it belongs - for that, see `allowVertexLoopback`. |\n| allowVertexLoopback? | boolean | Whether or not to allow edges from a port back to the vertex it belongs to. Defaults to true. |\n| anchor? | [AnchorSpec]() | Spec for the anchor to use for connections to children of the group when they are transferred to the group in its collapsed state. |\n| anchorPositionFinder? | [AnchorPositionFinder\\<any>]() | Optional function to call on connection drop, to determine the location for the target anchor for the new connection. Returning null from this indicates no preference, and VisuallyJs will use its own computed value. |\n| anchorPositions? | Array<[ObjectAnchorSpec]()> | Optional array of anchor positions to use. |\n| autoGrow? | boolean | Defaults to false, meaning that the group will not be resized if an item addition/removal or drag causes the bounds of the child members to change and the new size is greater than the previous size. |\n| autoShrink? | boolean | False by default. If true indicates that if a child member is dragged/added/removed and the group's size is recalculated to be smaller than the previous size, the new size should be applied. This also works if the group needs to shrink from its left and/or top edge. If you don't want that behaviour, set `allowShrinkFromOrigin` to false. |\n| autoSize? | boolean | False by default. This flag switches on both `autoShrink` and `autoGrow` and also enables support for shrinking a group from its left or top edge |\n| canDrop? | (v:[Node]() \\| [Group]()) => boolean | Optional interceptor that will be invoked to test whether a given node/group may be dropped onto this group. |\n| collapsedSize? | [Size]() | The size to use for this group type when it is collapsed. |\n| constrain? | boolean | False by default - nodes/groups may be dragged outside of the bounds of the group. |\n| defaultSize? | [Size]() | Optional default size to use for the vertex. This is not used to set the size in the DOM for a vertex - it is used to insert `width` and `height` values into the backing data for any vertex of this type that does not have them set. |\n| edgeType? | string | Type to assign to edges connected to this vertex as a source. |\n| elastic? | boolean | Similar to autoGrow, but the UI shows a visual prompt when a group will be resized as a result of dragging a child. |\n| elementsDraggable? | boolean | True by default - indicates that child members may be dragged around inside the group. |\n| events? | [GroupEventOptions\\<EL>]() | Optional map of event bindings. |\n| fitToGrid? | boolean | When sizing the group, ensure it fits the underlying grid, if there is one. |\n| ignore? | boolean | If true, vertices of this type will be ignored by this UI and not rendered. |\n| layout? | {<br /> options:[LayoutParameters](),<br /> type:string<br />} | Options for the group's layout. |\n| maxConnections? | number | Maximum number of connections this vertex supports. Default is 1. A value of -1 means no limit. |\n| maxSize? | [Size]() | Maximum size the group can grow to. If not specified the group can grow to an arbitrary size. Note that this behaviour can also be enforced via CSS. |\n| mergeStrategy? | string | When merging a type description into its parent(s), values in the child for `connector`, `anchor` and `anchors` will always overwrite any such values in the parent. But other values, such as `overlays`, will be merged with their parent's entry for that key. You can force a child's type to override *every* corresponding value in its parent by setting `mergeStrategy:'override'`. |\n| minSize? | [Size]() | Minimum size the group can be. |\n| padding? | number | Optional padding to set inside a group when computing an auto size. |\n| parent? | string \\| Array\\<string> | Optional ID of one or more edge definitions to include in this definition. The child definition is merged on top of the parent definition(s). Circular references are not allowed and will throw an error. |\n\nThe `ctx` member passed in to your jsx is of type `JsxWrapperProps`:\n\nJsxWrapperProps\n\nThese are the props that are passed to the `jsx` you provide to map a node, group or overlay component in the `viewOptions` of a SurfaceComponent or PaperComponent. VisuallyJs passes in the UI, the model (which you can get from the UI anyway), the object being rendered, the object's data, and any `childProps` that have been configured.\n\n| Name | Type | Description |\n| ----- | ------------------ | -------------------------------------------------------------- |\n| data | [ObjectData]() | The object's backing data |\n| model | [BrowserUIModel]() | Underlying model. Can also be accessed via `ui.model`. |\n| obj | T | The object to be rendered - a Node, Group or Edge. |\n| props | any | Any extra props configured by the view to present to this JSX. |\n| ui | BrowserUI | The UI that is rendering this object. |\n\n## Managing element size[](#managing-element-size)\n\nThe default behaviour of VisuallyJs is to render a <!-- -->group<!-- --> using whatever HTML is provided, and then after the element has been rendered, read back the size of the element from the DOM. For many types of applications this approach is really useful - you can draw whatever you like for your <!-- -->group<!-- -->s and VisuallyJs will figure out where any connected edges need to be placed, based on the size of the elements, which has been determined by their content and the CSS in your page.\n\nIn some applications, though, you'll want to give your users control over the size of <!-- -->group<!-- -->s, and VisuallyJs supports that too via the `useModelForSizes` rendering option.\n\n### useModelForSizes[](#usemodelforsizes)\n\nYou can instruct VisuallyJs to extract `width` and `height` from your <!-- -->group<!-- --> data and to set the DOM element to these values, via the `useModelForSizes` flag:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n useModelForSizes: true\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nVisuallyJs will now set the width and height of rendered DOM elements from the `width` and `height` properties in their data. When either of those values are updated, VisuallyJs will update the size of the DOM element accordingly.\n\n### Default size[](#default-size)\n\nIf a given <!-- -->group<!-- --> does not have width or height values in its data, VisuallyJs will use a default value, which you can specify in one of two places - either the `defaults` section of some render options:\n\n<!-- -->\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n useModelForSizes: true,\n defaults: {\n groupSize: {\n width: 300,\n height: 300\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nor inside a <!-- -->group<!-- --> definition in the view:\n\n<!-- -->\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { DEFAULT } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n useModelForSizes: true,\n defaults: {\n groupSize: {\n width: 300,\n height: 300\n }\n }\n}\n\n const viewOptions = {\n groups: {\n [DEFAULT]: {\n defaultSize: {\n width: 400,\n height: 400\n }\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions} viewOptions={viewOptions}/>\n}\n\n```\n\nYou can in fact provide values in both places - as shown above - and VisuallyJs will use the values from a <!-- -->group<!-- --> definition first. <!-- --><!-- -->In the example above, the default group definition does have a `defaultSize`, so that will be used for any groups that do not have width or height information in their backing data.\n\nIn the absence of any default values, VisuallyJs will <!-- -->render groups with a width and height of 300 pixels<!-- -->.","url":"https://visuallyjs.com/react/docs/apps/nodes-and-groups/rendering-groups","lib":"react","topic":"apps"},"docs/apps/nodes-and-groups/rendering-nodes.md":{"title":"Rendering Nodes","body":"# Rendering Nodes\n\n<!-- -->\n\n<!-- -->\n\nIn VisuallyJs, you render your nodes using React components, which you map to node types via a set of [ReactNodeMapping]() objects in `viewOptions` prop on a `SurfaceComponent`. You can map JSX directly inside the view like this:\n\n## Rendering with JSX[](#rendering-with-jsx)\n\n```jsx\n\nimport { DEFAULT } from \"@visuallyjs/browser-ui\"\nimport { SurfaceComponent, JsxWrapperProps } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyAppComponent() {\n const viewOptions = {\n nodes:{\n [DEFAULT]:{\n jsx:(ctx:JsxWrapperProps) => <div className=\"aNode\">{ctx.data.id}</div>\n }\n },\n \"type1\":{\n jsx:(ctx:JsxWrapperProps) => <div className=\"aNode\">\n <h1>TYPE 1</h1>\n <p>{ctx.data.id}</p>\n </div>\n }\n }\n }\n \n return <div><SurfaceComponent viewOptions={viewOptions}/></div>\n}\n\n\n```\n\nHere, nodes of type `type1` have their own mapping to a specific piece of JSX. Any other node type is mapped to the \"default\" mapping, which declares some other JSX. Any valid JSX is supported.\n\n## Rendering with React components[](#rendering-with-react-components)\n\nYou do not need to use inline JSX as shown in the example above; in fact a more modular approach is to define JSX components separately and then map those. For instance, this is the JSX for the mockup workflow node in the node/group overview page:\n\n```jsx\n\nexport function IntroNode({ctx}) {\n return <div className=\"workflow-node\">\n <div className=\"node-header\">\n <span className=\"node-type\">TASK</span>\n <div className=\"node-status-dot\"></div>\n </div>\n \n <div className=\"node-body\">\n <div className=\"node-icon\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M12 2v20M2 12h20\" />\n </svg>\n </div>\n <div className=\"node-label\">\n {ctx.data.label || \"New Task\"}\n </div>\n </div>\n\n <div className=\"node-port\"></div>\n </div>\n}\n\n```\n\n...which - with a dash of CSS - looks like this:\n\n**********\n\nand which we mapped like this:\n\n```jsx\n\nimport { DEFAULT } from \"@visuallyjs/browser-ui\"\nimport { SurfaceComponent, JsxWrapperProps } from \"@visuallyjs/browser-ui-react\"\nimport IntroNode from \"./IntroNode\"\n\nexport default function MyAppComponent() {\n const viewOptions = {\n nodes:{\n [DEFAULT]:{\n jsx:(ctx:JsxWrapperProps) => <IntroNode ctx={ctx}/>\n }\n }\n }\n }\n \n return <div><SurfaceComponent viewOptions={viewOptions}/></div>\n}\n\n```\n\nYou can encapsulate as much behaviour as you like inside the components you use to render your nodes.\n\n## Accessing the context[](#accessing-the-context)\n\nYou can access the underlying model, vertex and UI from inside your JSX via the `ctx`. This is an object of type [VisuallyJsModel]()\n\n```jsx\n\nimport { DEFAULT } from \"@visuallyjs/browser-ui\"\nimport { SurfaceComponent, JsxWrapperProps } from \"@visuallyjs/browser-ui-react\"\nimport IntroNode from \"./IntroNode\"\n\nexport default function MyAppComponent() {\n \n function countNodes(ctx) {\n alert(`There are ${ctx.model.getNodes().length} nodes in the dataset. My ID is ${ctx.data.id}.`)\n }\n \n const viewOptions = {\n nodes:{\n [DEFAULT]:{\n jsx:(ctx):JsxWrapperProps => <div>\n <button onClick={() => countNodes(ctx)}>Click me</button>\n </div>\n }\n }\n }\n }\n \n return <div><SurfaceComponent viewOptions={viewOptions}/></div>\n}\n\n```\n\n**********\n\nThe `ctx` member passed in to your jsx is of type `JsxWrapperProps`:\n\nJsxWrapperProps\n\nThese are the props that are passed to the `jsx` you provide to map a node, group or overlay component in the `viewOptions` of a SurfaceComponent or PaperComponent. VisuallyJs passes in the UI, the model (which you can get from the UI anyway), the object being rendered, the object's data, and any `childProps` that have been configured.\n\n| Name | Type | Description |\n| ----- | ------------------ | -------------------------------------------------------------- |\n| data | [ObjectData]() | The object's backing data |\n| model | [BrowserUIModel]() | Underlying model. Can also be accessed via `ui.model`. |\n| obj | T | The object to be rendered - a Node, Group or Edge. |\n| props | any | Any extra props configured by the view to present to this JSX. |\n| ui | BrowserUI | The UI that is rendering this object. |\n\n## Rendering content based on zoom[](#rendering-content-based-on-zoom)\n\nYou might want to show more detail when zoomed in and less detail when zoomed out. VisuallyJs provides a `useZoom` hook to assist you with this.\n\n```tsx\nimport { useZoom } from '@visuallyjs/browser-ui-react';\n\nexport default function ZoomDisplay({ ui, obj, model }) {\n const zoom = useZoom(ui);\n\n return (\n <div style={{ position: 'absolute', top: 10, left: 10, background: 'white', padding: '5px' }}>\n Current Zoom: {(zoom * 100).toFixed(0)}%\n {zoom > 1.5 && <p>High magnification active</p>}\n {zoom < 0.5 && <p>Low magnification active</p>}\n </div>\n );\n}\n\n```\n\n## Managing element size[](#managing-element-size)\n\nThe default behaviour of VisuallyJs is to render a <!-- -->node<!-- --> using whatever HTML is provided, and then after the element has been rendered, read back the size of the element from the DOM. For many types of applications this approach is really useful - you can draw whatever you like for your <!-- -->node<!-- -->s and VisuallyJs will figure out where any connected edges need to be placed, based on the size of the elements, which has been determined by their content and the CSS in your page.\n\nIn some applications, though, you'll want to give your users control over the size of <!-- -->node<!-- -->s, and VisuallyJs supports that too via the `useModelForSizes` rendering option.\n\n### useModelForSizes[](#usemodelforsizes)\n\nYou can instruct VisuallyJs to extract `width` and `height` from your <!-- -->node<!-- --> data and to set the DOM element to these values, via the `useModelForSizes` flag:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n useModelForSizes: true\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nVisuallyJs will now set the width and height of rendered DOM elements from the `width` and `height` properties in their data. When either of those values are updated, VisuallyJs will update the size of the DOM element accordingly.\n\n### Default size[](#default-size)\n\nIf a given <!-- -->node<!-- --> does not have width or height values in its data, VisuallyJs will use a default value, which you can specify in one of two places - either the `defaults` section of some render options:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n useModelForSizes: true,\n defaults: {\n nodeSize: {\n width: 150,\n height: 100\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n<!-- -->\n\nor inside a <!-- -->node<!-- --> definition in the view:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { DEFAULT } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n useModelForSizes: true,\n defaults: {\n nodeSize: {\n width: 150,\n height: 100\n }\n }\n}\n\n const viewOptions = {\n nodes: {\n [DEFAULT]: {\n defaultSize: {\n width: 150,\n height: 100\n }\n },\n type1: {}\n }\n}\n return <SurfaceComponent renderOptions={renderOptions} viewOptions={viewOptions}/>\n}\n\n```\n\n<!-- -->\n\nYou can in fact provide values in both places - as shown above - and VisuallyJs will use the values from a <!-- -->node<!-- --> definition first. <!-- -->In the above example we see that `type1` has no default size set, so VisuallyJs will use `nodeSize` from the defaults block.<!-- -->\n\nIn the absence of any default values, VisuallyJs will <!-- -->render nodes with width 100 pixels and height 80 pixels<!-- -->.","url":"https://visuallyjs.com/react/docs/apps/nodes-and-groups/rendering-nodes","lib":"react","topic":"apps"},"docs/apps/panning-and-zooming.md":{"title":"Panning And Zooming","body":"# Panning and zooming\n\nVisuallyJs has the smoothest pan/zoom for miles around, and exposes a number of hooks for you to inject your own behaviour.\n\nBy default, the UI is setup to support an infinite canvas. This means the canvas element is positioned `absolute`, we set `overflow:hidden` on the container element (which disables the browser's scrolling mechanism), and the transform origin for the canvas is set to wherever the user last used the mouse or performed a pinch to zoom.\n\n### Panning[](#panning)\n\nIn the default configuration, panning is performed by dragging the canvas with the mouse, or via touch. You can configure pan options via the `panOptions` property:\n\nPanOptions\n\nOptions to control how a user pans the canvas.\n\n| Name | Type | Description |\n| ----------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| axis? | [PanAxis]() | Optional axes in which to constrain pan - 'x', 'y' or 'both'. Defaults to 'both'. |\n| enabled? | boolean | Defaults to true, meaning panning is enabled. |\n| filter? | (el:Element) => boolean | Optional function which is called at the start of panning and can return false to reject pan starting. |\n| useMetaKey? | boolean | Optional, defaults to false. When true, the user must hold down the meta key (ctrl on windows) in order to pan. |\n| wheel? | boolean | Defaults to false, meaning panning works via canvas drag. If you set this to true, the mousewheel (or move events on a touchpad) will pan the canvas. This will also override any zoom wheel flag. |\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n panOptions: {\n axis: \"x\",\n metaKey: true\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n<!-- -->\n\nAuto pan\n\nThe default behaviour of the UI is to automatically pan the canvas whenever a vertex is dragged out of the viewport. We're mentioning it here as it is related to pan, but this is controlled in the vertex drag options.\n\nFor more information see [this page](/react/docs/apps/nodes-and-groups/dragging.md#auto-pan).\n\n### Zooming[](#zooming)\n\nThe canvas supports zooming both programmatically and via the mouse wheel (or pinch, on touch devices or a trackpad). A Surface has an associated `zoom range`, which is the minimum and maximum zoom that can be applied. When using the mouse wheel or pinch, these limits are applied automatically. If you attempt to set a zoom value outside of the zoom range programmatically (via `setZoom`), the zoom value will be clamped to the current range.\n\nZooming is configured via the `zoomOptions` property:\n\nZoomOptions\n\nOptions to control how a user manages zoom on the canvas.\n\n| Name | Type | Description |\n| --------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| fixedTransformOrigin? | [PointXY]() | Optional fixed transform origin for the canvas. Defaults to null.When this is supplied the zoom function does not change the transform origin You can still zoom and pan but the zoom/pan is applied relative to the top/left corner of the content. |\n| initialValue? | number | Initial zoom value. Defaults to 1. |\n| range? | [ZoomRange]() | Zoom range to support. The default is \\[0.05, 3] |\n| step? | number | When zooming by step, this defines the change in zoom for each step. Defaults to 0.25. |\n| wheel? | boolean | When true - which is the default - the wheel will be used for zoom. |\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n zoomOptions: {\n range: [\n 0.1,\n 5\n ],\n step: 0.1\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n<!-- -->\n\n### Mouse Wheel/Pinch[](#mouse-wheelpinch)\n\nThe `wheelOptions` property provides more granular control over how the mouse wheel (and pinch, on trackpads and touch screens) interacts with the UI for both zooming and panning. By default, the wheel controls zoom.\n\nWheelOptions\n\nOptions for how to respond to wheel events.\n\n| Name | Type | Description |\n| ------------ | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| cssFilter? | string | Optional CSS 3 selector to check if the wheel should be enabled for the current event target. |\n| filter? | (e:MouseEvent) => boolean | Optional function to call to check if wheel zooming should be enabled for the current event target. |\n| reverse? | boolean | Defaults to false. If true, the zoom direction is reversed: wheel up zooms out, and wheel down zooms in. |\n| sensitivity? | number | How sensitive the wheel should be. |\n| useMetaKey? | boolean | If true, the \"meta\" key (CMD on Mac, Ctrl on windows/linux) must be pressed in order for wheel zoom to operate. This can be useful if your UI fills the screen in one or more axes and your users would not be able to scroll past the Surface widget. |\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n wheelOptions: {\n useMetaKey: true,\n sensitivity: 0.5\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n<!-- -->\n\nNote that if you set `wheel: true` in `panOptions`, the mouse wheel will pan the canvas, and this will take precedence over any zoom wheel configuration.","url":"https://visuallyjs.com/react/docs/apps/panning-and-zooming","lib":"react","topic":"apps"},"docs/apps/plugins/background.md":{"title":"Background","body":"# Backgrounds\n\nThe surface widget supports the addition of backgrounds via a plugin. Two different background types are supported - images, and generated grids.\n\n## Setup[](#setup)\n\nAs this is a plugin, you will provide its configuration in the `plugins` section of the render parameters for a surface.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { BackgroundPlugin, SimpleBackground } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: BackgroundPlugin.type,\n options: {\n type: SimpleBackground.type,\n url: \"/img/351032562.jpg\"\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n## Image backgrounds[](#image-backgrounds)\n\nImages can be used as a background in one of two ways - either as an image that is retrieved in one piece and displayed, or as a set of tiles.\n\n### Simple backgrounds[](#simple-backgrounds)\n\nThese are backgrounds consisting of a single image, positioned at the Surface's origin. This type of background can be useful, for example, if you're building an app in which your users can markup drawings.\n\n### Single image example[](#single-image-example)\n\nIn this example (using the code shown above) we load a simple background, ie. a static image:\n\n**********\n\nRemember that we paste the image at the canvas origin, at its original size. So in this case the image has loaded but we cannot see all of it. It is possible to get a notification when the background image has loaded, though, so we can hook into that and have the image fully visible after load:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { BackgroundPlugin, SimpleBackground } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: BackgroundPlugin.type,\n options: {\n type: SimpleBackground.type,\n url: \"/img/351032562.jpg\",\n onBackgroundReady: (bg, surface) => {\n surface.zoomToBackground() \n }\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n<!-- -->\n\n### Tiled backgrounds[](#tiled-backgrounds)\n\nThis type of background consists of a set of tiles, which the Surface element requests from you as the canvas is panned and zoomed. This type of background has various usages: if you have a large background image, for instance, you may wish to serve it in pieces as the Surface needs it. Alternatively, you may wish to change the background based on the current zoom (in the way that Google maps does). Another great use for this type of background is to provide a grid for your canvas.\n\n### Tiled image example[](#tiled-image-example)\n\nIn this example we use a tiled background. Each of our tiles looks like this:\n\n\n\nWhen the surface has rendered, only the required tiles will have been loaded. If you tap on one of the nodes, the display will pan left and up by 350 pixels in each axis, and you will (probably) see new tiles appearing as they get loaded (unless the network is too fast for the load to be evident):\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { BackgroundPlugin, TiledBackground, TilingStrategies } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: BackgroundPlugin.type,\n options: {\n type: TiledBackground.type,\n tiling: TilingStrategies.absolute,\n url: \"/img/tiles/{z}/{x}_{y}.jpg\",\n tileSize: {\n width: 200,\n height: 200\n },\n width: 800,\n height: 800,\n maxZoom: 0\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n### Tiling strategies[](#tiling-strategies)\n\nYou may have noticed that in the example above we declared `tiling:TilingStrategies.absolute` in the background options. The tiled background supports two different approaches to the way tiles are arranged:\n\n* `TilingStrategies.absolute` - Divides the entire image dimensions by the tile size. For instance, if you declare your background has a width and height of 800px, and your tiles are of width and height 50px, then - at zoom 0 - the background expects 16 tiles in each axis. At zoom 1, the expected value is doubled to 32, at zoom 2 it doubles again to 64, etc. With this strategy, each zoom level has the same number of tiles.\n\n* `TilingStrategies.logarithmic` - With this strategy, there are (2^level+1) tiles in each axis. For instance at zoom 0, there are 2 tiles. At zoom 1 there are 4. At zoom 2, there are 8. Etc. This strategy is how applications like Google maps operate.\n\nA tiled background is served as a series of layers, one for each zoom level supported. The number of zoom levels you intend to support is specified by the `maxZoom` option, which is a zero-indexed integer value. A value of 0 is the base value, covering the entire background. The background will determine which zoom level is appropriate based upon the current zoom of the surface.\n\nThere is no need to support any zoom level beyond 0; the background will retrieve tiles for the most appropriate level that is available to it, but serving up different tiles at different levels can allow you to implement things like serving more visual complexity the further a user zooms in.\n\n### URL pattern[](#url-pattern)\n\nThe URL you supply for a tiled background should have a placeholder for each of `z` (zoom), `x` (index in horizontal axis) and `y` (index in vertical axis), as in the example above. In the above example we provided this url pattern:\n\n```javascript\n{\n url:\"/img/tiles/{z}/{x}_{y}.jpg\",\n}\n\n```\n\nTiles are zero-indexed, so, for example, the top left tile at zoom level 0 would, in the previous example, expand to this url:\n\n```javascript\ntiles/0/tile_0_0.png\n\n```\n\nThe surface's tiled background does not support the concept of a \"continuous world\", in which tiles with negative indices may be requested.\n\n### Clamping to the background image[](#clamping-to-the-background-image)\n\nDepending on your use case, you may wish to force the surface to clamp the pan/zoom such that some portion of the background image is always visible. You do this by setting the `clampToBackground` parameter on a `render` call:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { BackgroundPlugin, SimpleBackground } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n clampToBackground: true,\n plugins: [\n {\n type: BackgroundPlugin.type,\n options: {\n type: SimpleBackground.type,\n url: \"myBackground.png\"\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n### Zooming to the background image[](#zooming-to-the-background-image)\n\nIf you wish to zoom out to the point that the entire background image is visible:\n\n```javascript\nsurface.zoomToBackground()\n\n```\n\n***\n\n## Generated grid backgrounds[](#generated-grid-backgrounds)\n\nGenerated grid backgrounds place an SVG element into the background of the UI, repositioning and resizing it as needed as the bounds of your content changes. You can choose between a background using lines or dots. The default is for lines.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { BackgroundPlugin, GeneratedGridBackground } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n grid: {\n size: {\n width: 50,\n height: 50\n }\n },\n plugins: [\n {\n type: BackgroundPlugin.type,\n options: {\n type: GeneratedGridBackground.type\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\nIn this example we didn't specify the size of the grid in the background's options: the background will get this information from the surface, if possible. You can override the surface grid, however, should you wish to, or you may use the grid background on a surface that does not have a drag grid in effect.\n\n### Dotted backgrounds[](#dotted-backgrounds)\n\nThe background in this example is rendered as lines, which is the default. Here's the same example with `gridType:GridTypes.dotted`:\n\n**********\n\nThe full list of options for the generated grid background are:\n\nGeneratedGridBackgroundOptions\n\nOptions for the generated grid background.\n\n| Name | Type | Description |\n| ------------------ | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| autoShrink? | boolean | Defaults to true, and instructs the grid that if the grid has grown beyond any minimum value set in either axis, if the content bounds subsequently shrink in that axis below the minimum, the grid should shrink back to the minimum. If you set this to false the grid will never shrink back to its minimum values once they have been exceeded. |\n| dotRadius? | number | The radius for dots representing grid positions (when gridType id GridTypes.dotted). Defaults to 2. |\n| grid? | [Grid]() | The grid to use. This is optional; if you do not supply one the background will attempt to read the grid definition from the Surface. If that is also not set then a default grid of 50x50 pixels will be used. |\n| gridType? | [GridType]() | Type of grid - lines or dots. Defaults to lines. |\n| maxHeight? | number | The maximum height for the grid. The value you provided is divided by 2 and then the grid is guaranteed to never exceed the range of (-maxHeight / 2) - (maxHeight / 2). maxHeight takes precedence over minHeight. |\n| maxWidth? | number | The maximum width for the grid. The value you provided is divided by 2 and then the grid is guaranteed to never exceed the range of (-maxWidth / 2) - (maxWidth / 2). maxWidth takes precedence over minWidth. |\n| minHeight? | number | The minimum height for the grid. The value you provided is divided by 2 and then the grid is guaranteed to always at least span the range of (-minHeight / 2) - (minHeight / 2). Defaults to 20 000. |\n| minWidth? | number | The minimum width for the grid. The value you provided is divided by 2 and then the grid is guaranteed to always at least span the range of (-minWidth / 2) - (minWidth / 2). Defaults to 20 000. |\n| onBackgroundReady? | [OnBackgroundReadyCallback]() | Optional function to call when the image has loaded (or otherwise claims to be ready) |\n| showBorder? | boolean | Whether or not to show a thick border around the entire background. Defaults to false. |\n| showTickMarks? | boolean | Defaults to false. If true, the grid will also draw tick marks between the grid lines. |\n| tickDotRadius? | number | The radius for dots representing grid tick marks (when gridType id GridTypes.dotted). Defaults to 1. |\n| tickMarksPerCell? | number | Number of tick marks to draw per cell. Defaults to 2. |\n| type | string | Type of background to render. |\n| visible? | boolean | Whether or not the background is initially visible. Defaults to true. |\n\n### Autoscaling[](#autoscaling)\n\nThe grid background has a minimum width and height, which are set by default to quite large numbers, and so users typically do not see the edges of the grid. However, you can supply your own `minWidth` and/or `minHeight` values, and if these are quite small with respect to the bounds of the dataset, VisuallyJs will autoscale the grid as necessary.\n\nIn this example we've set our grid minimum width and height to be 500 pixels. If you drag one of the nodes in the canvas below towards the edge of the grid, you'll see the grid expand in order to ensure there are always at least 2 grid squares between the content bounds and the edge of the grid. The grid will also shrink subsequently back to any minimum boundaries if the content bounds shrinks appropriately.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { BackgroundPlugin, GeneratedGridBackground } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n grid: {\n size: {\n width: 50,\n height: 50\n }\n },\n plugins: [\n {\n type: BackgroundPlugin.type,\n options: {\n type: GeneratedGridBackground.type,\n minWidth: 500,\n minHeight: 500,\n autoShrink: false\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n### Autoshrink[](#autoshrink)\n\nIn the above example the grid scales up and down as the bounds of the content changes. If you wish, you can switch off the `autoShrink` functionality:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { BackgroundPlugin, GeneratedGridBackground } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n grid: {\n size: {\n width: 50,\n height: 50\n }\n },\n plugins: [\n {\n type: BackgroundPlugin.type,\n options: {\n type: GeneratedGridBackground.type,\n minWidth: 1500,\n minHeight: 1500,\n autoShrink: false\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n### Tick marks[](#tick-marks)\n\nBy default, the grid will be drawn without tick marks in each cell. You can change this behaviour with the `showTickMarks` and `tickMarksPerCell` options. In this first example we show the tick marks:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { BackgroundPlugin, GeneratedGridBackground } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n grid: {\n size: {\n width: 50,\n height: 50\n }\n },\n plugins: [\n {\n type: BackgroundPlugin.type,\n options: {\n type: GeneratedGridBackground.type,\n showTickMarks: true\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\nIn this next example, we leave the drag grid at 50x50 on the Surface, but we expand the background grid to 250x250, and request 4 tick marks per cell:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { BackgroundPlugin, GeneratedGridBackground } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n grid: {\n size: {\n width: 50,\n height: 50\n }\n },\n plugins: [\n {\n type: BackgroundPlugin.type,\n options: {\n type: GeneratedGridBackground.type,\n showTickMarks: true,\n tickMarksPerCell: 5,\n grid: {\n width: 250,\n height: 250\n }\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n### Grid border[](#grid-border)\n\nYou can add a border to the background grid with the `showBorder` option:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { BackgroundPlugin, GeneratedGridBackground } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n grid: {\n size: {\n width: 50,\n height: 50\n }\n },\n plugins: [\n {\n type: BackgroundPlugin.type,\n options: {\n type: GeneratedGridBackground.type,\n minWidth: 1500,\n minHeight: 1500,\n showBorder: true\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n### CSS classes[](#css-classes)\n\nVisuallyJs exposes a number of CSS classes to assist you in managing the appearance of grid backgrounds.\n\n| Class | Description |\n| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |\n| `vjs-background` | The css class that will be added to a grid background's main element |\n| `vjs-background-border` | The css class that will be added to a grid background's border |\n| `vjs-background-grid` | The css class that will be added to the major and minor dots/lines in a grid background |\n| `vjs-background-grid-dotted-major` | The class that will be added to the dots representing a grid background's grid lines (when gridType is GridTypes.dotted) |\n| `vjs-background-grid-dotted-minor` | The class that will be added to the dots representing a grid background's grid tick marks (when gridType is GridTypes.dotted) |\n| `vjs-background-grid-major` | The class that will be added to the lines representing a grid background's grid lines (when gridType is GridTypes.lines) |\n| `vjs-background-grid-minor` | The class that will be added to the lines representing a grid background's tick marks (when gridType is GridTypes.lines) |\n\n***","url":"https://visuallyjs.com/react/docs/apps/plugins/background","lib":"react","topic":"apps"},"docs/apps/plugins/drag-groups.md":{"title":"Drag Groups","body":"# Drag Groups\n\nA `DragGroup` models a group of vertices that should be dragged together. You can have any number of drag groups in your canvas. When you assign a vertex to a drag group you indicate to VisuallyJs whether that vertex should be an `active` member - meaning that when it is dragged all of the other vertices in the drag group are also dragged - or that it should be a `passive` member - meaning that when it is dragged no other members should be dragged, but that it should be dragged whenever an `active` member is dragged.\n\n### Assigning drag groups[](#assigning-drag-groups)\n\nTo assign vertices to drag groups you need to include the `DragGroupsPlugin`:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { DragGroupsPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: DragGroupsPlugin.type,\n options: {\n assignDragGroup: (v) => {\n return { id:'dragGroup', active:v.type === 'main' }\n }\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nThe key piece to note is the `assignDragGroup` function that you provide. In the above example our `assignDragGroup` function instructs VisuallyJs to add every vertex to a group called `\"dragGroup\"`, but that the vertex should only be an `active` member if it has a `type` of `\"main\"`.\n\nConsider this dataset:\n\n```javascript\n{\n nodes:[\n {\"id\":\"1\",\"left\":50,\"top\":50,\"type\":\"main\"},\n {\"id\":\"2\",\"left\":250,\"top\":160},\n {\"id\":\"3\",\"left\":350,\"top\":100},\n]\n\n```\n\nWe have one `\"main\"` vertex and two other vertices. In the canvas below, try dragging the large green box around. You'll see the two red boxes drag along with it. Now try dragging one of the red boxes - nothing else moves. This is because all of the nodes are inside a drag group, but the large green node is marked `active` and the red nodes are marked `passive`, due to the `assignDragGroup` function shown above:\n\n**********\n\nThe key is the `assignDragGroup` function that we provide. In the implementation above we do two things:\n\n* all vertices are assigned to a drag group called `\"dragGroup\"`\n* The vertex whose `type` is `\"main\"` is marked `active:true`; the others are marked `active:false`\n\n### Multiple drag groups[](#multiple-drag-groups)\n\nOur example above just used a single drag group, but we can have as many of these as we want. For instance, here's a canvas in which all the red elements are dragged in a single group, and all the green elements are dragged in a different group:\n\n**********\n\nThis was an even simpler setup - we just use each node's `type` to specify its drag group:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { DragGroupsPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: DragGroupsPlugin.type,\n options: {\n assignDragGroup: (v) => {\n return v.type\n }\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nEvery element in this example is marked `active` because that's the default if you do not specify it. All we had to do in this example is return the name of a drag group and VisuallyJs adds the vertex as an active participant to that group.\n\nOur dataset in this example is:\n\n```javascript\n{\n nodes:[\n {\"id\":\"1\",\"left\":50,\"top\":50,\"type\":\"green\"},\n {\"id\":\"2\",\"left\":150,\"top\":160,\"type\":\"red\"},\n {\"id\":\"3\",\"left\":200,\"top\":30,\"type\":\"red\"},\n {\"id\":\"4\",\"left\":250,\"top\":100,\"type\":\"green\"},\n]\n\n```\n\n### Example - annotating objects[](#example---annotating-objects)\n\nA good example of how this functionality is useful is the concept of annotating objects in a diagram - explanatory notes for some given vertex that you want to place near the vertex, but whose positioning you want to adjust in each case to suit the diagram. When you drag a vertex that has annotations you want the annotations to move with the vertex, but you want to be able to position the annotations without moving the vertex itself.\n\nConsider this dataset:\n\n```javascript\n{\n nodes:[\n {\"id\":\"1\",\"type\":\"main\",\"left\":50,\"top\":50},\n {\"id\":\"2\",\"type\":\"main\",\"left\":300,\"top\":50},\n {\"id\":\"3\",\"type\":\"annotation\",\"text\":\"I belong to node 1\",\"ref\":\"1\",\"left\":70,\"top\":-40},\n {\"id\":\"4\",\"type\":\"annotation\",\"text\":\"I belong to node 1\",\"ref\":\"1\",\"left\":-90,\"top\":120},\n {\"id\":\"5\",\"type\":\"annotation\",\"text\":\"I belong to node 2\",\"ref\":\"2\",\"left\":380,\"top\":160},\n]\n\n```\n\nWe've got two nodes of type `main`, and three nodes of type `annotation`, each of which have a `ref` member, which points to a `main` node. We want to be able to drag our `main` nodes around and have the `annotation` nodes follow, but we also want to be able to position the `annotation` nodes around the `main` nodes where we please. This is easily achieved:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { DragGroupsPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: DragGroupsPlugin.type,\n options: {\n assignDragGroup: (v) => {\n return v.type === 'main' ? v.id : {id:v.data.ref, active:false}\n }\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n* For nodes of type `main`, we just return the node's id: `v.id`\n* For nodes of type `annotation`, we return the `ref` as the drag group id, and mark the vertex passive: `{id:v.data.ref, active:false}`.\n\nWhich gives us this arrangement:\n\n**********\n\nAnd there you have it! Annotated objects using just a few lines of configuration.\n\n#### Cleaning up annotations[](#cleaning-up-annotations)\n\nOne thing to keep in mind is that the annotations and the edges that connect them to their reference nodes will not automatically be removed by VisuallyJs if the reference node is removed from the dataset. To handle this we can use another of VisuallyJs's capabilities you won't find in other libraries in this space - [Transactions](/react/docs/apps/model/undo-redo.md#transactions) - to cleanup the annotations, but in an undo/redo friendly way.\n\nTry clicking one of the red circle buttons below. We'll remove the node the button belongs to, and we'll also remove any annotations that are attached to it (code follows below) :\n\n**********\n\nTo remove a node and its annotations in an undo-friendly way, we find everything we want to delete and then perform all the removals inside a transaction. An example function, into which you'd pass the model and the ID of the node to cleanup, is:\n\n```typescript\nfunction removeNode(model:VisuallyJsModel, nodeId:string) {\n \n // find all annotation nodes that reference this node\n const annotations = model.getNodes().filter(n => n.data.ref === nodeId)\n\n // in a transaction, remove all the annotation nodes and then the focus node. Edges will be cleaned up automatically, and if the user clicks undo, the entire transaction is rolled back as one.\n model.transaction(() => {\n annotations.forEach(a => model.removeNode(a))\n model.removeNode(nodeId)\n })\n}\n\n```\n\n<br />\n\nWe can integrate that snippet into our component as shown below. We have a click listener on a specific button, in which we get the model and the node ID from the context used to render the node:\n\n```jsx\nviewOptions={{\n nodes:{\n main:{\n jsx:(ctx) => <div>\n <div data-vjs-delete={true} onClick={() => {\n const annotations = ctx.model.getNodes().filter(n => n.data.ref === ctx.data.id) \n ctx.model.transaction(() => {\n annotations.forEach(a => ctx.model.removeNode(a))\n ctx.model.removeNode(ctx.data.id)\n }) \n }}/>\n </div>\n }\n }\n}}\n\n```","url":"https://visuallyjs.com/react/docs/apps/plugins/drag-groups","lib":"react","topic":"apps"},"docs/apps/plugins/edge-routing.md":{"title":"Edge Routing","body":"# Edge Routing\n\nThe [Hierarchy Layout](/react/docs/apps/layouts/Hierarchy) has the ability to generate routing information for edges. This routing information generates paths in such a way that each edge avoids any nodes in the UI.\n\nThe edge routing plugin operates in one of two modes - either 'direct' or 'orthogonal'. Additionally, in orthogonal mode, you can switch on [bus routing](#bus-routing)\n\n## Setup[](#setup)\n\nYou add this plugin as you would any other - but you must also be using a `Hierarchy` layout, so we've included that here:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { EdgeRoutingPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: HierarchyLayout.type,\n options: {\n generateRouting: true\n }\n },\n plugins: [\n {\n type: EdgeRoutingPlugin.type\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n***\n\n## Direct routing[](#direct-routing)\n\nThis is the default you'll get when you configure an edge routing plugin on your UI, as shown in the code above:\n\n**********\n\ntip\n\nThis concept is related to [vertex avoidance](/react/docs/apps/edges/vertex-avoidance.md), but in this plugin the routing data is calculated statically at layout time, and not recomputed until the layout is re-run. We're looking at ways to fold these two related approaches into a single configuration.\n\n## Orthogonal routing[](#orthogonal-routing)\n\nOrthogonal routing uses horizontal and vertical line segments and ensures that lines do not overlap.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { EdgeRoutingPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: HierarchyLayout.type,\n options: {\n generateRouting: true\n }\n },\n plugins: [\n {\n type: EdgeRoutingPlugin.type,\n options: {\n mode: \"orthogonal\"\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n### Bus routing[](#bus-routing)\n\nBus routing is orthogonal routing where instead of assigning a separate slot for each edge, edges travelling along the same path are grouped as a bus.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { EdgeRoutingPlugin, OrthogonalRouterModes } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: HierarchyLayout.type,\n options: {\n generateRouting: true\n }\n },\n plugins: [\n {\n type: EdgeRoutingPlugin.type,\n options: {\n mode: \"orthogonal\",\n orthogonalMode: OrthogonalRouterModes.bus\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n***\n\n## Options[](#options)\n\nEdgeRoutingPluginOptions\n\nOptions for the edge routing plugin.\n\n| Name | Type | Description |\n| ------------------ | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| mode | [EdgeRoutingPluginMode]() | Mode to use to draw edges. 'orthogonal' is like the orthogonal connector - segments that are either vertical or horizontal.<br />`direct` draws straight lines through regions. Both modes assign a separate anchor point to each edge. |\n| orthogonalMode? | [OrthogonalRouterMode]() | When mode is 'orthogonal' this instructs VisuallyJs whether to group edges in buses, or to route each edge separately. |\n| orthogonalPadding? | number | How much space to leave between stacked orthogonal edges. Defaults to 10 pixels. |","url":"https://visuallyjs.com/react/docs/apps/plugins/edge-routing","lib":"react","topic":"apps"},"docs/apps/plugins/lasso.md":{"title":"Lasso","body":"# Lasso\n\nThe lasso plugin allows users to select nodes, group and edges with the mouse. We've activated it on page load so you can try it out below. After you've tried it once the surface will revert to pan mode and you'll need to select the lasso from the controls.\n\nAny vertices snagged by your lasso are added to the model's current selection.\n\nThe lasso works like the lasso in AutoCAD: when you drag from left to right, any vertices that intersect with your lasso are added to the selection. When you drag from right to left, though, only vertices that your lasso fully encloses are added to the selection.\n\n**********\n\n## Setup[](#setup)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { LassoPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: LassoPlugin.type,\n options: {\n invert: true\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n<!-- -->\n\n## CSS Classes[](#css-classes)\n\n| Class | Description |\n| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `vjs-lasso` | Assigned to the DOM element representing a lasso |\n| `vjs-lasso-mask` | Assigned to each DOM element representing part of the lasso mask, when the lasso is inverted mode. The lasso mask consists of four parts, one to the left, right, top and bottom of the area that has been lassoed. |\n| `vjs-lasso-mask-bottom` | Assigned to the DOM element representing the bottom part of the lasso mask, when the lasso is inverted mode. |\n| `vjs-lasso-mask-left` | Assigned to the DOM element representing the left part of the lasso mask, when the lasso is inverted mode. |\n| `vjs-lasso-mask-right` | Assigned to the DOM element representing the right part of the lasso mask, when the lasso is inverted mode. |\n| `vjs-lasso-mask-top` | Assigned to the DOM element representing the top part of the lasso mask, when the lasso is inverted mode. |\n\n## Options[](#options)\n\nLassoPluginOptions\n\n| Name | Type | Description |\n| --------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| autoExit? | boolean | When true (which is the default) the lasso exits after a selection has been made. |\n| cssClass? | string | Extra class(es) to add to the lasso's DOM element |\n| filter? | string \\| (e:MouseEvent) => boolean | Optional CSS3 filter identifying elements you do not want to lasso |\n| generateLassoContent? | (origin:[PointXY](), e:MouseEvent) => [BrowserElement]() | Optional function that generates the DOM element for the lasso to use. This is<br />for advanced usage scenarios and most users will not need to supply this. |\n| includeEdges? | boolean | Defaults to false. If true, edges are included in the lasso selection. |\n| invert? | boolean | Defaults to false, meaning the lasso is drawn as a rectangle. If true, the lasso is drawn as a set of masks,<br />with the lasso area drawn as a \"hole\" in the masks. |\n| onEnd? | Function | Optional function to call when lasso selection ends. |\n| onSelect? | (vertices:Array<[Vertex]()>) => any | Optional function to call when one or more objects has been selected by the lasso. |\n| onStart? | Function | Optional function to call when lasso selection starts. |\n| selectionFilter? | (o:[Edge]() \\| [Vertex]()) => boolean | Optional filter that is passed every vertex/edge that the lasso would ordinarily select, and if this function returns false<br />then the vertex/edge is not added to the selection |","url":"https://visuallyjs.com/react/docs/apps/plugins/lasso","lib":"react","topic":"apps"},"docs/apps/plugins/list-manager.md":{"title":"List Manager","body":"# Scrollable Lists\n\nThe `ListManagerPlugin` is used to manage lists within groups in VisuallyJS, and is great for applications such as data mappers. It handles the visibility and connection management of nodes within a scrollable list, ensuring that connections remain visible or are hidden appropriately as list items are scrolled out of view. In this canvas, try scrolling the groups - you'll see the edges scroll with their vertices, until one or both of the vertices is scrolled out of the view, at which point the edge is proxied onto the group element.\n\n**********\n\n## Configuration[](#configuration)\n\nTo tell VisuallyJS to configure a list, you must add the `data-vjs-list=\"true\"` attribute to the element you wish to act as the list container.\n\n### Groups and CSS[](#groups-and-css)\n\nIt is important to note that the setup **must be a Group, not a node**. CSS plays a critical part in the correct functioning of a list:\n\n1. The Group must have an element with the `data-vjs-group-content` attribute.\n2. This content element must have a `max-size` and `overflow: auto`. (Without the `max-size` the list will just be drawn as big as it needs to be)\n\n```css\n.my-list-container {\n max-height: 200px;\n overflow: auto;\n}\n\n```\n\n<!-- -->\n\n## Setup[](#setup)\n\nConfiguration is in two parts.\n\n### Register the plugin[](#register-the-plugin)\n\nFirstly, you need to register the plugin in your render options:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ListManagerPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n ListManagerPlugin.type\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n### Configure UI[](#configure-ui)\n\nHow you configure\n\n## Behaviors[](#behaviors)\n\nThe `ListManagerPlugin` supports two main behaviors when a node is scrolled out of view:\n\n### Proxy (Default)[](#proxy-default)\n\nThe default behavior is \"proxy\". When an item is scrolled out of view, any edges connected to it are \"proxied\" to the edge of the list container. This keeps the connection visible and indicates that it is connected to something currently off-screen within the list.\n\n### Hide[](#hide)\n\nIn the \"hide\" behavior, edges connected to an item are simply hidden when that item is scrolled out of view.\n\nYou can configure the behavior globally in the plugin options:\n\n```javascript\nplugins:[\n {\n type:ListManagerPlugin.type,\n options: {\n behavior: \"hide\"\n }\n }\n]\n\n```\n\nOr you can override it on a per-list basis using the `data-vjs-list-behavior` attribute:\n\n```html\n<div data-vjs-list=\"true\" data-vjs-list-behavior=\"hide\">\n ...\n</div>\n\n```\n\n## Options[](#options)\n\nListManagerPluginOptions\n\nOptions for the list manager plugin.\n\n| Name | Type | Description |\n| --------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------- |\n| behavior? | \"hide\" \\| \"proxy\" | Whether to proxy edges that are scrolled out of view, or to hide them. Possible values are \"proxy\" or \"hide\". Defaults to \"proxy\". |","url":"https://visuallyjs.com/react/docs/apps/plugins/list-manager","lib":"react","topic":"apps"},"docs/apps/plugins/pan-buttons.md":{"title":"Pan Buttons","body":"# Pan Buttons\n\nProvides buttons around the perimeter of the Surface canvas that allow the user to nudge the pan. Users can click and hold to auto pan.\n\n**********\n\n## Setup[](#setup)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { PanButtonsPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n PanButtonsPlugin.type\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n## CSS Classes[](#css-classes)\n\nThere are a number of classes added to the elements this plugin creates, allowing you to style the buttons as you like:\n\n| Class | Description |\n| ------------------------ | ----------------------------------------------------------------------- |\n| `vjs-surface-pan` | Assigned to each of the pan buttons added around the surface. |\n| `vjs-surface-pan-active` | Assigned when the user is pressing a pan button and a pan is in motion. |\n| `vjs-surface-pan-bottom` | Assigned to the pan button on the bottom edge of the surface. |\n| `vjs-surface-pan-left` | Assigned to the pan button added on the left edge of the surface. |\n| `vjs-surface-pan-right` | Assigned to the pan button on the right edge of the surface. |\n| `vjs-surface-pan-top` | Assigned by to the pan button on the top edge of the surface. |\n\n## Options[](#options)\n\nPanButtonsPluginOptions\n\nOptions for the pan buttons plugin.\n\n| Name | Type | Description |\n| ------------------ | ------ | ------------------------------------------------------------------------------------------------------- |\n| panDistance? | number | Amount in pixels to pan the surface by when one of the buttons is pressed and released. Defaults to 50. |\n| panRepeatDistance? | number | Amount in pixels to adjust pan by each time the timer fires. Defaults to 10. |\n| panRepeatInterval? | number | Time in milliseconds between successive adjustment to the pan. Defaults to 60. |\n| startPanTimeout? | number | Time in milliseconds after the mouse button is pressed before panning should start. Defaults to 150. |","url":"https://visuallyjs.com/react/docs/apps/plugins/pan-buttons","lib":"react","topic":"apps"},"docs/apps/plugins/resizing-tools.md":{"title":"Resizing Tools","body":"# Resizing tools\n\nProvides the tools to assist in resizing nodes/groups.\n\n**********\n\nThe plugin automatically attaches resizing tools to any vertex that is added to VisuallyJs's current selection, and removes the resizing tools when the vertex is removed from the selection. This behaviour can be changed by setting `onDemand:true` in the plugin options.\n\nThe default settings for the resizing tools plugin attach a handle at each corner, and at the midpoint of each edge, that your users can drag to resize, but you can also instruct the plugin to allow users to resize by [dragging an element's borders](#resizing-by-border)\n\n## Setup[](#setup)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ResizingToolsPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n ResizingToolsPlugin.type\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nWe show the plugin here without any constructor options as it \"just works\" for the most part, but there are a few configurable options.\n\nIn the canvas above we've selected one of the vertices after loading the dataset. You can click on other vertices to select them.\n\n## Resizing by handle[](#resizing-by-handle)\n\n### Handle Shape[](#handle-shape)\n\nBy default, the plugin will use circular handles. You can change this to use rectangular handles by setting `handleShape:\"rectangle\"` in the plugin options:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: ResizingToolsPlugin.type,\n options: {\n handleShape: \"rectangle\"\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n<br />\n\n#### Handle size[](#handle-size)\n\nYou can also change the size of the handles by setting `handleSize`:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ResizingToolsPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: ResizingToolsPlugin.type,\n options: {\n handleShape: \"rectangle\",\n handleSize: 20\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n## Resizing by border[](#resizing-by-border)\n\nInstead of attaching a handle at each corner to enable resize, you can setup the resizing tools to allow resize by dragging the borders of the element:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ResizingToolsPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: ResizingToolsPlugin.type,\n options: {\n resizeMethod: \"borders\"\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n#### Border visibility[](#border-visibility)\n\nBy default, the borders for resizing will be visible to the user. You can set `bordersVisible:false` to hide the borders - the user will still see the cursor change when hovering over a border, but the border itself will not be shown:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ResizingToolsPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: ResizingToolsPlugin.type,\n options: {\n resizeMethod: \"borders\",\n bordersVisible: false\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n## Rotation[](#rotation)\n\nYou can allow your users to rotate objects by setting `rotatable:true` on the plugin options:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ResizingToolsPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: ResizingToolsPlugin.type,\n options: {\n rotatable: true\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n### Per-vertex disable[](#per-vertex-disable)\n\nIf you have the rotation tool enabled but you wish to switch it off for some specific vertex, you can do so by setting a `data-vjs-rotatable` attribute on the vertex element:\n\n```html\n<div data-vjs-rotatable=\"false\">\n <h2>My non-rotatable vertex</h2>\n</div>\n\n```\n\nIn this example, every node except node 2 is rotatable - but node 2 has `data-vjs-rotatable:false` set:\n\n**********\n\n### Rotation stops[](#rotation-stops)\n\nThe default behaviour is to support rotation to any angle, but you can specify the number of rotation stops VisuallyJs should use:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ResizingToolsPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: ResizingToolsPlugin.type,\n options: {\n rotatable: true,\n rotationStops: 12\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n## Grids[](#grids)\n\nWhen the associated surface has a grid, this plugin will constrain node/group resizing so that the dimensions of the vertex are a multiple of the grid in each axis.\n\n**********\n\nThis is controlled by the `ignoreGrid` option, which is set to false by default. You can change that:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ResizingToolsPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: ResizingToolsPlugin.type,\n options: {\n ignoreGrid: true\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********\n\n## Constraining size[](#constraining-size)\n\nThere are 3 options you can use to constrain the size when resizing elements:\n\n* **minimumWidth** The minimum width the user can drag any element to\n* **minimumHeight** The minimum height the user can drag any element to\n* **constrainGroups** When true, the minimum size for groups when resizing will be calculated as the bounds of their child elements.\n\nnote\n\nThe resizing tools plugin will not resize collapsed groups.\n\n## Attaching tools on demand[](#attaching-tools-on-demand)\n\nBy default the resizing tools will attach themselves to any element that is in VisuallyJs's current selection, but you can switch to \"on demand\" mode like this:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ResizingToolsPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: ResizingToolsPlugin.type,\n options: {\n onDemand: true\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n## Constraining resize axes[](#constraining-resize-axes)\n\nBy default, the resizing tools plugin will allow users to resize an element's width and height. This behaviour can be changed, in one of two ways:\n\n* By setting the attribute `data-vjs-y-resize` or `data-vjs-x-resize` to \"false\" on some node/group template:\n\n```html\n<div data-vjs-x-resize=\"false\">...</div>\n\n```\n\n* By setting `resizeX` or `resizeY` to \"false\" in the plugin options.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ResizingToolsPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: ResizingToolsPlugin.type,\n options: {\n resizeX: false\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nThe above configuration would result in a setup where your users can only resize the height of elements:\n\n**********\n\n## Excluding elements[](#excluding-elements)\n\nYou can exclude specific elements from being resizable by writing a `data-vjs-resizable` attribute on them:\n\n```html\n<div data-vjs-resizable=\"false\">{{name}}</div>\n\n```\n\n## Custom payloads[](#custom-payloads)\n\nYou can provide a `payloadGenerator` to the resizing tools which will be invoked before the resizing tools commits a change to a model object. This method allows you to customize the changes that will be made to the model object (or it can be used as a hook to make other changes in your model of course):\n\n```text\npayloadGenerator?:(v:any, p:any) => any\n\n```\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ResizingToolsPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: ResizingToolsPlugin.type,\n options: {\n payloadGenerator: (vertex, data) => {\n return {\n someDynamicValue:data.w * something etc\n } \n }\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nIn this example the model object's data will be updated with the `someDynamicValue` we calculated.\n\ncaution\n\nA payload generator function cannot override the value of any attributes the resizing tools needs to set, ie. the position or size of the object. The resizing tools will merge its attributes on top of any you return from a payload generator.\n\n## Updating the model on resize[](#updating-the-model-on-resize)\n\nIn some applications you may wish to respond to a vertex resize by making additional changes to the model. An example of this is in our <!-- -->[BPMN](/demonstrations/bpmn.md) starter app - when you resize a `pool` you also want to resize the pool's `lanes`.\n\nTo support this, the resizing tools allow you to provide a `handlerFactory`. This is a function that is invoked when a resize starts, and it returns a function that will be called for each mouse move during the resize. The type definition of `ResizingToolsHandlerFactory` is:\n\n`(ui:Surface, vertex:Node | Group, resizeDirection:ResizeDirection, defaultHandler:ResizeFunction) => ResizeFunction`\n\n* `ui` is the surface on which the vertex is displayed\n* `vertex` is the vertex being resized\n* `resizeDirection` is the [ResizeDirection]().\n* `defaultHandler` is the function that the resizing tools would normally use to resize the element. Your custom handler can call this default handler and then modify the result, or it can return an entirely custom set of changes.\n\n### Example: BPMN Lanes and Pools[](#example-bpmn-lanes-and-pools)\n\nIn the BPMN starter app, we use a `handlerFactory` to ensure that when a pool is resized, its lanes are also resized to match, and vice versa.\n\n```typescript\nimport { Surface, Node, Group, ResizeFunction } from \"@visuallyjs/core\"\n\nexport const resizeFactory: ResizingToolsHandlerFactory = (\n ui: Surface, \n vertex: Node | Group, \n direction: string, \n defaultHandler: ResizeFunction\n) => {\n if (vertex.type === 'POOL') {\n const lanes = vertex.getMembers().filter(m => m.type === 'LANE')\n \n return (dx: number, dy: number) => {\n // Get the default resize changes\n const def = defaultHandler(dx, dy)\n def.updates = {}\n\n if (lanes.length > 0) {\n // ... calculate new sizes for lanes ...\n lanes.forEach((lane, i) => {\n def.updates[lane.id] = {\n width: def.width - 20,\n height: newHeight,\n y: currentY\n }\n currentY += newHeight\n })\n // Adjust pool height to match sum of lanes\n def.height = currentY\n }\n return def\n }\n }\n // ... handle other types or return default ...\n}\n\n```\n\nBy returning a `updates` object in the result of your handler, you can specify additional changes to be made to other elements in the model.\n\n## Handle offset[](#handle-offset)\n\n## CSS[](#css)\n\n| Class | Description |\n| ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `vjs-resize-border` | Set on the border handles |\n| `vjs-resize-border-b` | Set on the bottom border handle |\n| `vjs-resize-border-l` | Set on the left border handle |\n| `vjs-resize-border-r` | Set on the right border handle |\n| `vjs-resize-border-t` | Set on the top border handle |\n| `vjs-resize-frame` | Set on the frame the resize tool draws around an object it is currently editing. |\n| `vjs-resize-handle` | Set on the resize handles by the resizing/diagram tools |\n| `vjs-resize-handle-active` | Set on a resize handle when it is being actively used |\n| `vjs-resize-handle-b` | Set on the bottom center resize handle |\n| `vjs-resize-handle-bl` | Set on the bottom left corner resize handle |\n| `vjs-resize-handle-br` | Set on the bottom right corner resize handle |\n| `vjs-resize-handle-l` | Set on the left center resize handle |\n| `vjs-resize-handle-r` | Set on the right center resize handle |\n| `vjs-resize-handle-t` | Set on the top center resize handle |\n| `vjs-resize-handle-tl` | Set on the top left corner resize handle |\n| `vjs-resize-handle-tr` | Set on the top right corner resize handle |\n| `vjs-resize-skeleton` | Set on the element that is the parent of drag handles when in `handles` resize mode. |\n| `vjs-resize-skeleton-borders` | Set on the element that is the parent of drag borders when in `borders` resize mode. |\n| `vjs-resize-skeleton-borders-visible` | Set on the resize tool's main group element for some vertex when `bordersVisible` is set to true and the resize mode is RESIZING\\_TOOLS\\_RESIZE\\_METHOD\\_BORDERS |\n| `vjs-rotate-handle` | Set on the rotation handle |\n| `vjs-rotate-leader` | Set on the leader to the rotation handle. |\n\n## Options[](#options)\n\nResizingToolsPluginOptions\n\nOptions for the resizing tool plugin.\n\n| Name | Type | Description |\n| ------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| borderHandleSize? | number | Size of handles when using \"border\" resize. Defaults to 6 pixels. |\n| bordersVisible? | boolean | When resizeMethod is \"borders\", set this to make the borders visible. Internally this just sets a CSS class on the draw skeleton's parent DOM element, and the appearance of the borders is then controlled via CSS. |\n| canResizeFilter? | (v:[Vertex](), el:[BrowserElement]()) => boolean | Optional function that can decide on whether or not the given vertex should be resizable |\n| canRotateFilter? | (v:[Vertex](), el:[BrowserElement]()) => boolean | Optional function that can decide on whether or not the given vertex should be rotatable |\n| constrainGroups? | boolean | Defaults to true, meaning groups will not be shrunk to the point that one or more of their child vertices is no longer visible. |\n| handleOffset? | number | How much to offset the resize frame and handles from the bounds of the shape. Defaults to 5 pixels. |\n| handlerFactory? | [ResizingToolsHandlerFactory]() | Optional factory that can return a resize handler for some given vertex. You can use this to override the default behaviour for any vertex you choose |\n| handleShape? | \"circle\" \\| \"rectangle\" | Shape of resize handles. Defaults to circle. |\n| handleSize? | number | Width/height to use for handles. Defaults to 20 pixels. |\n| heightAttribute? | string | Attribute to use for vertex height - defaults to 'height' |\n| ignoreGrid? | boolean | Defaults to false, meaning size changes conform to an underlying grid, if present |\n| leftAttribute? | string | Attribute to use for vertex left position - defaults to 'left' |\n| minimumHeight? | number | Minimum height the user can shrink a vertex to. Defaults to 30. |\n| minimumWidth? | number | Minimum width the user can shrink a vertex to. Defaults to 30. |\n| modelUpdater? | [ResizingToolsModelUpdater]() | Optional function that can inject extra model updates each time a vertex is resized. |\n| onDemand? | boolean | Defaults to false, meaning the resizing tool plugin switches on whenever a new vertex is selected. |\n| onEdit? | (o:[Node]() \\| [Group](), surface:[Surface](), toolkit:[VisuallyJsModel]()) => any | Optional callback invoked after an edit has occurred |\n| payloadGenerator? | (v:[Node](), p:[ObjectData]()) => [ObjectData]() | Optional function to invoke when a resize has occurred. The values the resizing plugin wants to write for the vertex are merged on top of the value returned from this function, and the combined payload is written as an update to the vertex in the data model. This exists for internal use mostly but there's no harm in it being exposed for your enjoyment. |\n| resizeMethod? | [ResizingToolsResizeMethod]() | Method to use for resize - handles on the corners, or borders. Defaults to handles. |\n| resizeX? | boolean | Whether or not to support resize in the X axis. Defaults to true. |\n| resizeY? | boolean | Whether or not to support resize in the Y axis. Defaults to true. |\n| rotatable? | boolean | Whether or not to support rotation on all elements.. Defaults to false. |\n| rotateHandleSize? | number | Size of the rotate handle. Defaults to 16 pixels. |\n| rotateLeaderLength? | number | Length of the leader line to the resize handle when using the resizing tools in an SVG container. Defaults to 30 pixels. |\n| rotationStops? | number | Optional number of stops to use when rotating. If not provided vertices can be rotated to any angle. If provided, the value is divided into 360 and the result is the angle between each stop. For example, a value of 12 means each stop is 30 degrees. |\n| topAttribute? | string | Attribute to use for vertex top position - defaults to 'top' |\n| widthAttribute? | string | Attribute to use for vertex width - defaults to 'width' |","url":"https://visuallyjs.com/react/docs/apps/plugins/resizing-tools","lib":"react","topic":"apps"},"docs/apps/plugins/snaplines.md":{"title":"Snaplines","body":"# Snaplines\n\nSnaplines provide visual cues to allow your users to fine-tune their layouts. When two edges are in proximity a snapline is shown, or when the center of some vertex is in proximity with the edge(s) of some other vertex/vertices. When the two objects are aligned exactly, an additional class is written to the snapline, allowing you to provide your users with a visual cue.\n\n**********\n\n## Instantiation[](#instantiation)\n\nSnaplines can be specified in the `plugins` of the render options for some surface:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { SnaplinesPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: \"snaplines\",\n options: {}\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n## Configuration[](#configuration)\n\nSnaplinesPluginOptions\n\nOptions for the SnaplinesPlugin\n\n| Name | Type | Description |\n| ------------ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| enabled? | boolean | Defaults to true. If false, you can start the plugin in disabled mode. |\n| showCenters? | boolean | Whether or not to show center snaplines. Defaults to true. |\n| showEdges? | boolean | Whether or not to show edge snaplines. Defaults to true. |\n| tolerance? | number | The tolerance either side of a snapline inside which an element must be before the snapline is activated. Defaults to 10 pixels (either side of the line). |\n\n## Enable/disable[](#enabledisable)\n\nYou can switch the snaplines plugin on and off via its `setEnabled(..)` method. To do this, you need to get a reference to the plugin and then call the method:\n\n```javascript\nconst snaplinesPlugin = surface.getPlugin(SnaplinesPlugin.type)\nsnaplinesPlugin.setEnabled(false)\n\n```\n\n## CSS Classes[](#css-classes)\n\nSnaplines are drawn as DIV elements, and several CSS classes are exposed to allow you to control their appearance.\n\n| Class | Description |\n| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |\n| `vjs-snapline` | Assigned to both horizontal and vertical snaplines when active |\n| `vjs-snapline-active` | Assigned to an element attached to an active snapline |\n| `vjs-snapline-active-exact` | Assigned to an element attached to an active snapline and the elements on the snapline are exactly aligned (parsed to integers). |\n| `vjs-snapline-exact` | Assigned to both horizontal and vertical snaplines when the elements are exactly aligned |\n| `vjs-snapline-horizontal` | Assigned to horizontal snaplines when active |\n| `vjs-snapline-vertical` | Assigned to vertical snaplines when active |\n\n## Options[](#options)\n\nSnaplinesPluginOptions\n\nOptions for the SnaplinesPlugin\n\n| Name | Type | Description |\n| ------------ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| enabled? | boolean | Defaults to true. If false, you can start the plugin in disabled mode. |\n| showCenters? | boolean | Whether or not to show center snaplines. Defaults to true. |\n| showEdges? | boolean | Whether or not to show edge snaplines. Defaults to true. |\n| tolerance? | number | The tolerance either side of a snapline inside which an element must be before the snapline is activated. Defaults to 10 pixels (either side of the line). |","url":"https://visuallyjs.com/react/docs/apps/plugins/snaplines","lib":"react","topic":"apps"},"docs/apps/plugins/vertex-drawing.md":{"title":"Vertex Drawing","body":"# Vertex drawing\n\nThis plugin provides a means for users to draw new nodes and groups onto the canvas, or into existing groups. When drawing a group users can snag existing vertices on the canvas for inclusion in the new group.\n\n## Instantiation[](#instantiation)\n\n### Manual mode[](#manual-mode)\n\nTo use this plugin \"manually\" (discussed [below](#manual-usage)), you declare it in the `plugins` section of the render options for some Surface:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { VertexDrawingPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n useModelForSizes: true,\n plugins: [\n VertexDrawingPlugin.type\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nNote the `useModelForSizes:true` declaration: this is recommended, if you intend to let your users drag new vertices via a lasso. There is also a mode in which your users can click on the canvas to add new vertices, and in that mode you may not need to use the model for sizes. This is [discussed below](#clicking-to-add-vertices)\n\n### Integrated with ShapePalette[](#integrated-with-shapepalette)\n\nTo use this plugin with a `ShapePalette`, you need to instruct the palette to run in \"tap\" mode:\n\n```jsx\n\nimport { SURFACE_MODE_TAP, FLOWCHART_SHAPES } from \"@visuallyjs/browser-ui\"\nimport { ShapePaletteComponent, SurfaceProvider, SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyApp() {\n return <SurfaceProvider>\n <SurfaceComponent renderOptions={renderOptions}/>\n <ShapePaletteComponent mode={SURFACE_MODE_TAP}/>\n </SurfaceProvider>\n}\n\n\n\n```\n\nWith this setup, the `ShapeLibraryPalette` will register a suitable configured instance of the vertex drawing plugin on the surface. It also handles setting the surface into `vertexDrawing` mode in order to activate the plugin at the appropriate time.\n\nFor a full discussion of dragging/drawing new SVG shapes, please see [this page](/react/docs/apps/nodes-and-groups/shape-libraries)\n\n***\n\n## Manual usage[](#manual-usage)\n\nWith the declaration shown above you get a default setup of the plugin, which will draw groups, of type `default`. In order to switch on the plugin, you have to set the appropriate mode in the surface:\n\n```javascript\nimport { SURFACE_MODE_VERTEX_DRAWING } from \"@visuallyjs/browser-ui\"\n\nmySurface.setMode(SURFACE_MODE_VERTEX_DRAWING)\n\n```\n\nIn this first example we've declared a vertex drawing plugin and then made the call shown above to activate the plugin. Try clicking and dragging on the canvas below - the plugin will add new groups. You can also draw groups inside other groups.\n\n**********\n\nWe setup the surface using the code snippet shown above - with the default options on the vertex drawing plugin, but also with `useModelForSizes` switched on:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { VertexDrawingPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n useModelForSizes: true,\n plugins: [\n VertexDrawingPlugin.type\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nnote\n\nFor comparison, here's the same setup but without `useModelForSizes:true`. Notice how the groups you add always end up the same size, regardless of the size you draw them:\n\n**********\n\n### Specifying vertex details[](#specifying-vertex-details)\n\nThe default setup of this plugin will always create new groups, and those groups will have `type` of `default`. For a more fine-grained control of the plugin, you have a few options.\n\n### Specifying group type[](#specifying-group-type)\n\nYou can instruct the plugin to use a specific group type via the `groupType` parameter:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { VertexDrawingPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n useModelForSizes: true,\n plugins: [\n {\n type: VertexDrawingPlugin.type,\n options: {\n groupType: \"userDrawn\"\n }\n }\n ]\n}\n\n const viewOptions = {\n groups: {\n default: {\n jsx: (ctx) => <div style={{backgroundColor:'orangered'}}/>\n },\n userDrawn: {\n jsx: (ctx) => <div style={{backgroundColor:'cadetblue'}}/>\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions} viewOptions={viewOptions}/>\n}\n\n```\n\nIn this example we've added a couple of groups manually, whose type is \"default\", and so, per the view above, they are drawn with an orange-red box. But if you drag new groups in this canvas, their type will be `userDrawn`, resulting in a `cadetblue` box (one of my favourite default HTML colors).\n\n**********\n\n### Drawing nodes[](#drawing-nodes)\n\nTo draw nodes instead of groups, supply a `nodeType` parameter to the plugin:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { VertexDrawingPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n useModelForSizes: true,\n plugins: [\n {\n type: VertexDrawingPlugin.type,\n options: {\n nodeType: \"userDrawn\"\n }\n }\n ]\n}\n\n const viewOptions = {\n groups: {\n default: {\n jsx: (ctx) => <div style={{backgroundColor:'orangered'}}/>\n },\n userDrawn: {\n jsx: (ctx) => <div style={{backgroundColor:'cadetblue'}}/>\n }\n },\n nodes: {\n default: {\n jsx: (ctx) => <div style={{backgroundColor:'forestgreen'}}/>\n },\n userDrawn: {\n template: (ctx) => <div style={{backgroundColor:'darkmagenta'}}/>\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions} viewOptions={viewOptions}/>\n}\n\n```\n\nFor the sake of clarity here we've declared a `default` and also a `userDrawn` type for groups and for nodes. On the canvas we've added a group and a node, both of type `default`. But if you now draw a new vertex on here, the `nodeType` parameter set on the plugin will instruct the plugin to draw nodes, of type `userDrawn`, in this case. So you'll see a box that is coloured `darkmagenta` when you draw:\n\n**********\n\n### Choosing type at runtime[](#choosing-type-at-runtime)\n\nA common use case for this plugin is to draw vertices of some type that a user has selected in the UI (that's the case for the `ShapePalette`, for instance, which is discussed below). To support this, instead of supply a hard-coded `groupType` or `nodeType`, you can supply a `typeGenerator`, which allows you to not only choose the type of vertex to create, it allows you to choose between a node or a group, and also to provide an initial payload. The signature for the `typeGenerator` function is:\n\n```javascript\nexport type VertexDrawingPluginTypeGenerator = (origin:PointXY, e:MouseEvent) => {objectType:typeof Node.objectType | typeof Group.objectType, type:string, data?:ObjectData}\n\n```\n\nSo it is given the `origin` of the event (in canvas coordinates) and the originating mouse event, and is expected to return an object of this type:\n\n```javascript\n{\n type:string,\n objectType:\"Group\"|\"Node\",\n data?:ObjectData\n}\n\n```\n\nHere we have the same example as just above, but in this case we've added radio button to allow you to specify what type of object to draw. Remember, groups are `cadetblue` and nodes are `darkmagenta`.\n\nOur plugin spec looks like this:\n\n```javascript\nplugins:[\n {\n type:tk.VertexDrawingPlugin.type,\n options:{\n typeGenerator:(origin, evt) => {\n return {\n objectType:document.querySelector(\"[type='radio']:checked\").value,\n type:\"userDrawn\"\n }\n }\n }\n }\n]\n\n```\n\n...we return the value of the currently checked radio button. How you go about determining this value will depend on your app. Notice also that here we've hard-coded the `type`, but that is also, of course, something you can derive dynamically.\n\n**********\n\n\\[ ]Group\\[x]Node\n\n### Clicking to add vertices[](#clicking-to-add-vertices)\n\nAll of the preceding examples have been focused on the user dragging an area on the screen to draw new vertices, but it is also possible to allow \"click to add\":\n\n```javascript\nplugins:[\n {\n type:tk.VertexDrawingPlugin.type,\n options:{\n typeGenerator:(origin, evt) => {\n return {\n objectType:document.querySelector(\"[type='radio']:checked\").value,\n type:\"userDrawn\"\n },\n allowClickToAdd:true\n }\n }\n }\n]\n\n```\n\n**********\n\n\\[ ]Group\\[x]Node\n\nWhen you have this enabled, the plugin will use a default size for nodes of 80 pixels width and height, and for groups of 250 pixels width and height. You can set those values:\n\n```javascript\nplugins:[\n {\n type:tk.VertexDrawingPlugin.type,\n options:{\n typeGenerator:(origin, evt) => {\n return {\n objectType:document.querySelector(\"[type='radio']:checked\").value,\n type:\"userDrawn\",\n defaultNodeSize:{width:100, height:80},\n defaultGroupSize:{width:500, height:350}\n },\n allowClickToAdd:true\n }\n }\n }\n]\n\n```\n\n## Advanced usage[](#advanced-usage)\n\n### Providing a vertex preview element[](#providing-a-vertex-preview-element)\n\nBy default, the vertex drawing plugin uses a `[lasso](plugins-overview#lasso)` to draw an area on the canvas that the new vertex will occupy. You can, though, provide a function that will generate an element at the start of a drag to be drawn as a child of the lasso:\n\n```javascript\nvertexPreviewGenerator?:(p:PointXY, e:MouseEvent) => BrowserElement\n\n```\n\n**********\n\nThis is the code for the example above:\n\n```javascript\nplugins:[\n {\n type:tk.VertexDrawingPlugin.type,\n options:{\n vertexPreviewGenerator:(p, e) => {\n\n const div = document.createElement(\"div\")\n div.style.position=\"absolute\"\n div.style.width=\"100%\"\n div.style.height=\"100%\"\n div.style.display=\"flex\"\n div.style.alignItems=\"center\"\n\n const d = document.createElement(\"marquee\")\n d.style.width=\"100%\"\n d.setAttribute(\"scrollamount\", 15)\n d.innerHTML = \"I am drawing a new element\"\n div.appendChild(d)\n\n return div\n }\n }\n }\n]\n\n```\n\nIt's almost certain if you use this functionality you'll do something more sensible with it. The `ShapeLibraryPalette`, for example, draws the current selected shape into an element and returns that.\n\n### Updating the preview element[](#updating-the-preview-element)\n\nDepending on what the HTML for your preview element looks like, you may need to update it as the user drags. In our example above we did not; we used some HTML elements and had CSS take care of the positioning for us. But in some cases - particularly if working with SVG - you might want to update the element. For that you can provide a `vertexPreviewUpdater`:\n\n```javascript\nvertexPreviewUpdater?:(p:PointXY, size:Size, el:BrowserElement) => any\n\n```\n\nTry dragging a new group here:\n\n**********\n\nFor this we provided a `vertexPreviewGenerator` and also a `vertexPreviewUpdater`:\n\n```javascript\nplugins:[\n {\n type:VertexDrawingPlugin.type,\n options:{\n vertexPreviewGenerator:(p, e) => {\n\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\")\n const rect = document.createElementNS(\"http://www.w3.org/2000/svg\", \"rect\")\n rect.setAttribute(\"fill\", \"#567567\")\n rect.setAttribute(\"x\", \"0\")\n rect.setAttribute(\"y\", \"0\")\n rect.setAttribute(\"width\", \"50%\")\n rect.setAttribute(\"height\", \"50%\")\n svg.appendChild(rect)\n\n const rect2 = document.createElementNS(\"http://www.w3.org/2000/svg\", \"rect\")\n rect2.setAttribute(\"fill\", \"#984267\")\n rect2.setAttribute(\"x\", \"50%\")\n rect2.setAttribute(\"y\", \"50%\")\n rect2.setAttribute(\"width\", \"50%\")\n rect2.setAttribute(\"height\", \"50%\")\n svg.appendChild(rect2)\n\n return svg\n },\n vertexPreviewUpdater:(p, size, el) => {\n el.setAttribute(\"width\", size.width)\n el.setAttribute(\"height\", size.height)\n }\n }\n }\n]\n\n```\n\nThe preview element is an SVG element, and the updater sets its width and height. It could probably be argued, in fact, that this case could also have been handled via CSS, but there are internal use cases in VisuallyJs that cannot, and so there may well be use cases in your app that cannot either.\n\n***\n\n### Usage with ShapePalette[](#usage-with-shapepalette)\n\nThe `ShapePalette` can integrate with a vertex drawing plugin. The way to switch this on is to set the `mode` flag on the palette to `SURFACE_MODE_TAP` (or \"tap\", if you just want to use a string):\n\n```javascript\n\nimport { SURFACE_MODE_TAP, ShapeLibraryPalette, ShapeLibraryImpl } from \"@visuallyjs/browser-ui\"\n\nconst shapeLibrary = new ShapeLibraryImpl(...)\n\nnew ShapePalette({\n container:document.querySelector(\".node-palette\"),\n surface,\n mode:SURFACE_MODE_TAP,\n shapeLibrary,\n dataGenerator:(el) => {\n return {\n name:el.getAttribute(\"data-type\"),\n details:\"\"\n }\n }\n})\n\n```\n\nThe palette will now create a vertex drawing plugin and attach it to the surface. The palette takes advantage of several of the capabilities discussed above:\n\n* A `typeGenerator` is provided to the plugin which returns the `objectType` and `type` of the currently selected item in the palette. Additionally, any `dataGenerator` set on the palette will be invoked and used to prepare an initial dataset for a new vertex.\n* A `vertexPreviewGenerator` is provided, which draws a copy of the currently selected element (which is SVG).\n* A `vertexPreviewUpdater` function is provided, which redraws the SVG according to the new dimensions.\n\nTry clicking an element in the palette here and dragging new nodes on the canvas:\n\n**********\n\n***\n\n### Grids[](#grids)\n\nWhen the associated surface has a grid, this plugin will constrain node/group sizes so that the dimensions of new vertices are a multiple of the grid in each axis.\n\n***\n\n### CSS[](#css)\n\nClassTable id=\"vertexDrawing\"/>\n\n***\n\n### Options[](#options)\n\nVertexDrawingPluginOptions\n\nOptions for the vertex drawing plugin\n\n| Name | Type | Description |\n| ----------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| allowClickToAdd? | boolean | Defaults to false. When true, users can click on the canvas to \"draw\" a new element, and the plugin will use a default size for the element. When this flag is set, drag to add is still also enabled. |\n| autoExit? | boolean | When true (which is the default) the lasso exits after a group has been drawn |\n| clickToAddOnly? | boolean | Defaults to false. When true, the plugin only supports click to add new vertices, not drag. This flag is forced to true if the associated UI does not have `useModelForSizes` set, since there is no point in allowing a user to drag a vertex to some size if its not going to be honoured. When you set this flag and associated UI does have `useModelForSizes` set, the plugin will use default sizes for new nodes/groups. |\n| defaultGroupSize? | [Size]() | Optional default size for groups, used when `allowClickToAdd` is set to true. Defaults to width and height of 250 pixels. |\n| defaultNodeSize? | [Size]() | Optional default size for nodes, used when `allowClickToAdd` is set to true. Defaults to width and height of 80 pixels. |\n| groupType? | string | The type identifier for new groups. If you have also provided a typeGenerator this will be ignored. If you have not provided a typeGenerator but you have provided a nodeType, this will be ignored. |\n| invert? | boolean | Defaults to false, meaning the lasso is drawn as a rectangle. If true, the lasso is drawn as a set of masks, with the lasso area drawn as a \"hole\" in the masks. |\n| lassoClass? | string | Optional extra class(es) to set on the lasso used for drawing. |\n| minSize? | [Size]() | The minimum size for vertices. If your user draws a vertex smaller than this it will be discarded. Defaults to a width/height of 50 pixels. |\n| nodeType? | string | The type identifier for new nodes. If you have also provided a typeGenerator this will be ignored. |\n| onVertexAdded? | (v:[Vertex]()) => any | Callback to invoke when a vertex has been added |\n| typeGenerator? | [VertexDrawingPluginTypeGenerator]() | Optional function that will be invoked when a new drag commences, and which is responsible for returning the type of object to add (Node or Group), as well as that object's own type, and, optionally, an initial payload for the new object. |\n| vertexPreviewGenerator? | (p:[PointXY](), e:MouseEvent) => [BrowserElement]() | A function that will be invoked at the start of a drawing operation, and can return an element to draw into the lasso. This is an optional function; if you don't provide it VisuallyJs will draw a basic SVG rectangle to indicate the drawing area. |\n| vertexPreviewUpdater? | (p:[PointXY](), size:[Size](), el:[BrowserElement]()) => any | A function that is invoked during mouse drag, to be used in conjunction with `vertexPreviewGenerator`. This function gives you a hook to use to make any changes to your preview element, should you need to. This is optional. |","url":"https://visuallyjs.com/react/docs/apps/plugins/vertex-drawing","lib":"react","topic":"apps"},"docs/apps/reference/overlays.md":{"title":"Overlays","body":"# Overlays\n\nThis page provides a reference for the various simple overlays that ship with VisuallyJs.\n\n## Arrow[](#arrow)\n\nAn arrow with a configurable `foldback` point.\n\n```javascript\n\n{\n \"type\": \"Arrow\",\n \"options\": {\n \"location\": 1\n }\n}\n\n```\n\n**********\n\nArrowOverlayOptions\n\nOptions for an Arrow overlay.\n\n| Name | Type | Description |\n| ----------- | ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |\n| attributes? | Record\\<string,string> | Optional custom attributes to write to the overlay's element. |\n| cssClass? | string | Optional CSS class(es) to add to the overlay's element. |\n| direction? | number | 1 to point forwards (the default), -1 to point backwards. Only taken into consideration in some overlay types. |\n| events? | Record<[OverlayEvents](),(value:any, event:any) => any> | Optional event handlers to attach to the overlay. |\n| foldback? | number | How far, as a decimal, along the line from head to baseline to fold back into. Defaults to 0.623. |\n| hollow? | boolean | Defaults to false. When true, the arrow is stroked but not filled. |\n| id? | string | Optional ID for the overlay. Can be used to retrieve the overlay from a connection. |\n| length? | number | Length from the head to the baseline. Defaults to 20. |\n| location? | number | Defaults to 0.5. See docs. |\n| paintStyle? | [PaintStyle]() | Optional paint style to use. |\n| visibility? | [OverlayVisibility]() | Whether the overlay is always visible, or only on hover. Defaults to OVERLAY\\_VISIBILITY\\_ALWAYS. |\n| width? | number | Width of the arrow's baseline. Defaults to 20. |\n\n### Arrow direction[](#arrow-direction)\n\nA point to note is that `location:0` for arrow overlays will not reverse the direction in which the arrow is pointing. To have the arrow point backwards along the path you have to provide a value for `direction`:\n\n```javascript\noverlays:[ \n {\n type:\"Arrow\",\n options:{\n width:10,\n length:15,\n location:0,\n direction:-1\n }\n } \n]\n\n```\n\nThe `direction:-1` here instructs VisuallyJs to draw the arrow painting backwards. There are only two valid values for `direction` - `1` and `-1`. If you provide any other value - or no value - then VisuallyJs will use a value of 1, meaning the arrow points forwards.\n\n***\n\n## PlainArrow[](#plainarrow)\n\nThis overlay is an extension of `Arrow` with the `foldback` parameter's value fixed to `1`. This results in an arrow with a flat back.\n\n```javascript\n\n{\n \"type\": \"PlainArrow\",\n \"options\": {\n \"location\": 1\n }\n}\n\n```\n\n**********\n\n***\n\n## Diamond[](#diamond)\n\nThis overlay is an extension of `Arrow` with the `foldback` parameter's value fixed to `2`. This results in an arrow shaped like a diamond.\n\n```javascript\n\n{\n \"type\": \"Diamond\",\n \"options\": {\n \"location\": 0.3\n }\n}\n\n```\n\n**********\n\n***\n\n## Dot[](#dot)\n\nThis is a circle, with configurable radius.\n\n```javascript\n\n{\n \"type\": \"Dot\",\n \"options\": {\n \"location\": 0,\n \"radius\": 13\n }\n}\n\n```\n\n**********\n\nnote\n\nIf you are a JsPlumb Toolkit user, note that a `Dot` overlay at location 0 or 1 is equivalent to using a `Dot` endpoint in JsPlumb.\n\nDotOverlayOptions\n\nOptions for a Dot overlay\n\n| Name | Type | Description |\n| ----------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| align? | \"center\" \\| \"flush\" | When the overlay is at position 1 or 0 (or is being used a source/target marker), this determines how the dot intersects the vertex. A value of 'flush', which is the default, means a point on the circumference of the dot touches the vertex boundary. A value of 'center' means the dot's center is on the vertex boundary. |\n| attributes? | Record\\<string,string> | Optional custom attributes to write to the overlay's element. |\n| cssClass? | string | Optional CSS class(es) to add to the overlay's element. |\n| direction? | number | 1 to point forwards (the default), -1 to point backwards. Only taken into consideration in some overlay types. |\n| events? | Record<[OverlayEvents](),(value:any, event:any) => any> | Optional event handlers to attach to the overlay. |\n| hollow? | boolean | Defaults to false. When true, the arrow is stroked but not filled. |\n| id? | string | Optional ID for the overlay. Can be used to retrieve the overlay from a connection. |\n| location? | number | Defaults to 0.5. See docs. |\n| paintStyle? | [PaintStyle]() | Optional paint style to use. |\n| radius? | number | Radius of the dot. Defaults to 5. |\n| visibility? | [OverlayVisibility]() | Whether the overlay is always visible, or only on hover. Defaults to OVERLAY\\_VISIBILITY\\_ALWAYS. |\n\n***\n\n## Rectangle[](#rectangle)\n\nThis is a rectangle, with configurable width and height.\n\n```javascript\n\n{\n \"type\": \"Rectangle\",\n \"options\": {\n \"location\": 1,\n \"width\": 15,\n \"height\": 10\n }\n}\n\n```\n\n**********\n\nnote\n\nIf you are a JsPlumb user, note that a `Rectangle` overlay at location 0 or 1 is equivalent to using a `Rectangle` endpoint in JsPlumb.\n\nRectangleOverlayOptions\n\nOptions for a Rectangle overlay\n\n| Name | Type | Description |\n| ----------- | ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| align? | \"center\" \\| \"flush\" | When the overlay is at position 1 or 0 (or is being used a source/target marker), this determines how the rectangle intersects the vertex. A value of 'flush', which is the default, means a point on the boundary of the rectangle touches the vertex boundary. A value of 'center' means the rectangle's center is on the vertex boundary. |\n| attributes? | Record\\<string,string> | Optional custom attributes to write to the overlay's element. |\n| cssClass? | string | Optional CSS class(es) to add to the overlay's element. |\n| direction? | number | 1 to point forwards (the default), -1 to point backwards. Only taken into consideration in some overlay types. |\n| events? | Record<[OverlayEvents](),(value:any, event:any) => any> | Optional event handlers to attach to the overlay. |\n| height? | number | Height of the rectangle. Defaults to 10. |\n| hollow? | boolean | Defaults to false. When true, the arrow is stroked but not filled. |\n| id? | string | Optional ID for the overlay. Can be used to retrieve the overlay from a connection. |\n| location? | number | Defaults to 0.5. See docs. |\n| paintStyle? | [PaintStyle]() | Optional paint style to use. |\n| rotate? | boolean | Whether or not to rotate the rectangle so that it is always perpendicular to the connector path. Defaults to false. |\n| visibility? | [OverlayVisibility]() | Whether the overlay is always visible, or only on hover. Defaults to OVERLAY\\_VISIBILITY\\_ALWAYS. |\n| width? | number | Width of the rectangle. Defaults to 10. |\n\n***\n\n## Label[](#label)\n\n```javascript\n\n{\n \"type\": \"Label\",\n \"options\": {\n \"label\": \"Hello\"\n }\n}\n\n```\n\n**********\n\nLabelOverlayOptions\n\nOptions for a label overlay\n\n| Name | Type | Description |\n| ----------------------- | ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |\n| attributes? | Record\\<string,string> | Optional custom attributes to write to the overlay's element. |\n| cssClass? | string | Optional CSS class(es) to add to the overlay's element. |\n| direction? | number | 1 to point forwards (the default), -1 to point backwards. Only taken into consideration in some overlay types. |\n| events? | Record<[OverlayEvents](),(value:any, event:any) => any> | Optional event handlers to attach to the overlay. |\n| font? | [FontSpec]() | Optional spec for the font to use on this label. |\n| id? | string | Optional ID for the overlay. Can be used to retrieve the overlay from a connection. |\n| label | string \\| Function | String, or a function returning a string, for the label. |\n| labelLocationAttribute? | string | Optional name of the attribute that identifies this overlay's location on the path. Defaults to `location`. |\n| location? | number | Defaults to 0.5. See docs. |\n| useHTMLElement? | boolean | Whether or not to use an HTML element. Defaults to false (uses an SVG element) |\n| visibility? | [OverlayVisibility]() | Whether the overlay is always visible, or only on hover. Defaults to OVERLAY\\_VISIBILITY\\_ALWAYS. |\n\nThe `label` for a label overlay can be a string or a function, but in practice with VisuallyJs you'll generally be defining labels as strings, as the values presented to the renderer are extracted from the JSON backing data for each edge.\n\n#### SVG vs HTML elements[](#svg-vs-html-elements)\n\nBy default, regardless of whether or not the container is an SVG element, a label overlay will be rendered as an SVG element. This is the most memory efficient and also allows a label to be printed by an SVG exporter. You can instruct VisuallyJs to use an HTML element via the `useHTMLElement` option for the label.\n\n***\n\n## Custom[](#custom)\n\nThe custom overlay allows you to create your own overlays, which VisuallyJs will position for you. You need to implement one method - `create(component)` - which is passed the component on which the overlay is located as an argument, and which returns a DOM element:\n\n```javascript\n\n overlays:[\n {\n type:\"Custom\",\n options:{\n create:(component) => {\n const d = document.createElement(\"select\")\n d.innerHTML = \"<option value='foo'>foo</option><option value='bar'>bar</option>\"\n return d\n },\n location:0.7\n }\n }\n ]\n\n```\n\nHere we have created a select box with a couple of values, assigned to it the id of 'customOverlay' and placed it at location 0.7.\n\nnote\n\nA custom overlay is a plain HTML element - you may wish to consider using a component overlay instead.","url":"https://visuallyjs.com/react/docs/apps/reference/overlays","lib":"react","topic":"apps"},"docs/apps/reference/templating.md":{"title":"Templating","body":"# Templating\n\nThis page discusses how to write templates for VisuallyJs's internal template engine.\n\nThis template engine is used by the Vanilla VisuallyJs to render nodes and groups, but not in <!-- -->React<!-- -->. In <!-- -->React<!-- -->, though, this engine is used to define the appearance of SVG shapes - see the [Shape Sets](/react/docs/apps/nodes-and-groups/shape-libraries#shape-sets) docs.\n\n## Template format[](#template-format)\n\n* Format is **strict** XHTML: *all* tags must be closed. This means:\n\n```html\n<input type=\"text\"></input>\n\n```\n\nfor example. You can also self-close an element:\n\n```html\n<input type=\"text\"/>\n\n```\n\n* Use **only double quotes** for attributes:\n\n```html\n<div class=\"foo\"></div>\n\n```\n\n*not*\n\n```html\n<div class='foo'></div>\n\n```\n\nInside attribute values, however, you can use single quotes:\n\n```html\n<r-if test=\"value == 'foo'\">...</r-if>\n\n```\n\ncaution\n\nYour templates must return a *single root node*. If you return multiple nodes, VisuallyJs will use the first node only.\n\n## Interpolating values[](#interpolating-values)\n\nTo extract some value from a data object that a given template is rendering, use this syntax:\n\n```html\n<h1>{{name}}</h1>\n\n```\n\nSo for some data object:\n\n```javascript\n{\n name:\"My Node\"\n}\n\n```\n\nYou'd get this output:\n\n```html\n<h1>My Node</h1>\n\n```\n\n### Providing defaults[](#providing-defaults)\n\nYou can use the `||` operator inside your templates to provide defaults, for instance:\n\n```html\n<h1>{{name || 'Empty'}}</h1>\n\n```\n\n### Values within attributes[](#values-within-attributes)\n\nThe template engine will extract values from the dataset within attributes, with some limitations. Let's enhance the heading example from above with a title attribute:\n\n```html\n<h1 aria-label=\"{{title}}\" title=\"{{title}}\">{{name}}</h1>\n\n```\n\nSo for some node with this dataset:\n\n```javascript\n{\n name:\"My Node\",\n title:\"This is the name of the node\"\n}\n\n```\n\nYou'd get this output:\n\n```html\n<h1 aria-label=\"This is the name of the node\" title=\"This is the name of the node\">My Node</h1>\n\n```\n\ntip\n\nFallback values also work for attribute interpolation. For example, say we render a node that may or may not have a `title` data member. If it does have `title`, it will be rendered. If not, we'll use \"No Title\" instead:\n\n```html\n<h1 title=\"{{title || 'No title'}}\">{{name}}</h1>\n\n```\n\n### Expressions[](#expressions)\n\nYou can use some basic maths inside an attribute value, for instance:\n\n```html\n<div>\n <svg:svg width=\"{{width}}\" height=\"{{height}}\">\n <svg:circle cx=\"{{width / 2}}\" cy=\"{{height / 2}}\" rx=\"{{width / 2}}\" ry=\"{{height / 2}}\"\n </svg:svg>\n</div>\n\n```\n\nExpressions are limited to the format `LHS operator RHS` - so, above, `width / 2`, has a LHS of `width`, a RHS of `2` and a division operator. You can use parentheses to construct more complex expressions:\n\n```html\n<div>\n <svg:svg width=\"{{width}}\" height=\"{{height}}\">\n <svg:circle cx=\"{{(width-10) / 2}}\" cy=\"{{(height-10) / 2}}\" rx=\"{{(width-10) / 2}}\" ry=\"{{(height-10) / 2}}\"\n </svg:svg>\n</div>\n\n```\n\n#### Evaluating Javascript[](#evaluating-javascript)\n\nYou cannot eval arbitrary Javascript inside an expression:\n\n```html\n<div>\n <svg:svg width=\"{{width}}\" height=\"{{height}}\">\n <svg:circle cx=\"{{calcCenterX(width)}}\" cy=\"{{calcCenterHeight(height)}}\" rx=\"{{calcRx(width)}}\" ry=\"{{calcRy(height)}}\"\n </svg:svg>\n</div>\n\n```\n\nThis will **not** work. You can use [macros](#template-macros) to insert computed values.\n\n### Evaluating once only[](#evaluating-once-only)\n\nIf you have an expression you want VisuallyJs to evaluate only on the initial render, you can prefix the expression with a `:`, as with the `data-direction` and `data-vertex-id` attributes in this example:\n\n```html\n<svg:svg data-direction=\"{{:dir}}\" data-vertex-id=\"{{:vertexId}}\" x=\"{{x}}\" y=\"{{y}}\" width=\"{{width}}\" height=\"{{height}}\">\n ...\n</svg:svg>\n\n```\n\nThis example is based on the elements we use to attach border handles in the Resizing Tools plugin: when we first create them, we want to specify what vertex they belong to, what direction to drag in, and their dimensions. On update, though, we only want to supply the dimensions, and the default behaviour of the update method is to clear any interpolated values for which no value is present in the updated payload. Marking them \"evaluate once\" will cause VisuallyJs to write their initial value and then subsequently ignore them.\n\n## Rendering SVG[](#rendering-svg)\n\nTo render SVG elements you must prefix the tag with a namespace:\n\n```html\n<svg:svg width=\"50\" height=\"50\">\n <svg:rect x=\"10\" y=\"10\" width=\"10\" height=\"10\"></svg:rect>\n</svg:svg>\n\n```\n\nThis is due to the fact that the templating code uses `createElementNS` to create elements.\n\n<!-- -->\n\n## Tag reference[](#tag-reference)\n\n### Each[](#each)\n\nThe `r-each` element lets you loop over some data.\n\n#### With objects in an array[](#with-objects-in-an-array)\n\n```javascript\n{\n someDataMember:[\n { id:\"one\", label:\"value1\" },\n { id:\"two\", label:\"value2\" }\n ]\n\n```\n\n```html\n<ul>\n <r-each in=\"someDataMember\">\n <li id=\"{{id}}\">{{label}}</li>\n </r-each>\n</ul> \n\n```\n\n#### With arrays in an array[](#with-arrays-in-an-array)\n\n```javascript\n{\n someDataMember:[\n [ \"one\", \"value1\" ],\n [ \"two\", \"value2\" ]\n ]\n\n```\n\n```html\n<ul>\n <r-each in=\"someDataMember\">\n <li id=\"{{$value[0]}}\">{{$value[1]}}</li>\n </r-each>\n</ul> \n\n```\n\nThe point to note here is that the current array is exposed as the variable `$value`.\n\n#### With an Object[](#with-an-object)\n\n```javascript\n{\n someData : {\n id:\"foo\",\n label:\"FOO is the label\",\n active:true,\n count:14\n }\n\n```\n\n```html\n<table>\n <r-each in=\"someData\">\n <tr><td>{{$key}}</td><td>{{$value}}</td></tr>\n </r-each>\n</table>\n\n```\n\nThe point to note here is that each entry is presented to the template as an object with `$key` and `$value` members.\n\n#### Uniquely identifying child nodes[](#uniquely-identifying-child-nodes)\n\nIf you want to update a template that contains an `r-each` element, you need to ensure you set a `key` for each child of the loop. In this example, `id` is extracted from each child object that is rendered, and used internally to uniquely identify that element within the loop:\n\n```html\n<ul class=\"table-columns\">\n <r-each in=\"columns\" key=\"id\">\n <r-tmpl id=\"tmplColumn\"/>\n </r-each>\n</ul>\n\n```\n\nIf you change the data in some array that you have looped over VisuallyJs can update the appropriate DOM element, since it can use the `key` property to identify the existing element. Similarly, if you add a new entry to an array, VisuallyJs will use the `key` to determine that it has no current matching element, and if you remove an element from an array, VisuallyJs will use the `key` to determine that the element corresponding to that member is no longer needed, and will remove it.\n\nVisuallyJs will log a message to the console any time the `r-each` element is used without a `key`. If you do not supply a `key` then VisuallyJs will not be able to perform an update of the loop.\n\n### If[](#if)\n\nThe `r-if` element allows you to selectively include/exclude content from a template. You need to provide a `test` attribute, which contains a simple expression that determines the existence - or not - of some condition.\n\n#### Existence[](#existence)\n\nYou can check on the existence of some value in a few different ways:\n\n##### Not Falsy check[](#not-falsy-check)\n\nThis test is the equivalent of writing `someValue != false`:\n\n```html\n<r-if test=\"someValue\">\n <div>hola</div>\n</r-if>\n\n```\n\nAn existence test will be evaluated according to Javascript's \"falsy\" rules. If you are unfamiliar with falsiness in Javascript, you might like to [take a look here](https://developer.mozilla.org/en-US/docs/Glossary/Falsy)\n\n##### Falsy check[](#falsy-check)\n\nThis test is the equivalent of writing `someValue == false`:\n\n```html\n<r-if test=\"!someValue\">\n <div>hola</div>\n</r-if>\n\n```\n\n##### Not strict false[](#not-strict-false)\n\nThis test is the equivalent of writing `someValue !== false`. It is useful when you've got some setting that should be considered `true` by default, ie. the absence of the value is acceptable as true:\n\n```html\n<r-if test=\"!!someValue\">\n <div>hola</div>\n</r-if>\n\n```\n\ncaution\n\nThis operator does not function exactly like the equivalent operation in Javascript - specifically, if `someValue` is null, this operator will resolve to true in the template expression, but would resolve to false in Javascript\n\n#### Comparisons[](#comparisons)\n\n```html\n<r-if test=\"foo == 5\">\n <div>hola</div>\n</r-if>\n\n```\n\nComparisons are limited by the following rules:\n\n* Supported comparators are `==`, `===`, `<=`, `<`, `>`, `>=`, `!==`\n* Javascript expressions are not supported (eg **`someMethod(foo) == 5`**)\n\nnote\n\nInline `{{if ...}}` statements in attributes are not supported.\n\n### Comments[](#comments)\n\nComments follow the standard XHTML syntax:\n\n```html\n<div>\n<!--\n a comment\n <span>Maybe some code was commented</span>\n-->\n</div>\n\n```\n\nComments are stored in the parse tree for a template. This may or may not prove useful.\n\n### Nested Templates[](#nested-templates)\n\n#### With specific context[](#with-specific-context)\n\n```html\n<div>\n <r-tmpl id=\"nested\" context=\"someItem\"></r-tmpl>\n</div>\n\n```\n\n#### Inheriting parent context[](#inheriting-parent-context)\n\n```html\n<div>\n <r-tmpl id=\"nested\"></r-tmpl>\n</div>\n\n```\n\nThe difference between these two examples is that in the first, an item called `someItem` is extracted from the current dataset, and passed in to the `nested` template, whereas in the second, the `nested` template is passed the exact same data that the parent is currently using to render itself.\n\n#### Inside an r-each loop[](#inside-an-r-each-loop)\n\n```html\n<div>\n <r-each in=\"someList\">\n <r-tmpl id=\"nested\"></r-tmpl>\n </r-each>\n</div>\n\n```\n\nThis is similar to the example immediately above - the nested template inherits its parent's context, but in this case the parent's context is currently some item from the list. You can also use `context` in this situation:\n\n```html\n<div>\n <r-each in=\"someList\">\n <r-tmpl id=\"nested\" context=\"someMemberOfTheListItem\"></r-tmpl>\n </r-each>\n</div>\n\n```\n\nThe context for the nested element here is the `someMemberOfTheListItem` member of each list item.\n\n#### With complex context[](#with-complex-context)\n\nYou are not limited to extracting single variables from the current context to pass in to a nested template. You can specify a complex object too:\n\n```html\n<div>\n <r-tmpl id=\"nested\" context=\"{id:foo, label:'Hello'}\"/>\n</div>\n\n```\n\nIn this example, `foo` will be extracted from the context in which the current template is executing, and `Hello` is a hardcoded string.\n\n##### Accessing nested properties[](#accessing-nested-properties)\n\nYou can also specify properties that are nested inside the current context, either with dotted notation:\n\n```html\n<div>\n <r-tmpl id=\"nested\" context=\"{id:record.id, label:'Hello'}\"/>\n</div>\n\n```\n\nor by naming the property:\n\n```html\n<div>\n <r-tmpl id=\"nested\" context=\"{id:record['id'], label:'Hello'}\"/>\n</div>\n\n```\n\n#### Dynamic Template Names[](#dynamic-template-names)\n\nYou can lookup the name of a nested template at runtime, for example consider these templates:\n\n```javascript\n<script type=\"vjs\" id=\"someTemplate\">\n <h3>{{title}}</h3>\n <r-tmpl lookup=\"{{nestedId}}\" default=\"def\"/>\n</script>\n\n<script type=\"vjs\" id=\"green\">\n <h3>GREEN</h3>\n</script>\n\n```\n\nHere we see the ID of the nested template is derived from the `nestedId` property of the data we are rendering:\n\n```javascript\n{\n title:\"example\",\n nestedId:\"green\"\n}\n\n```\n\n`default` allows you to provide the ID of a template to use if the lookup fails.","url":"https://visuallyjs.com/react/docs/apps/reference/templating","lib":"react","topic":"apps"},"docs/apps.md":{"title":"Apps","body":"# Overview\n\nA VisuallyJs <!-- -->React<!-- --> app has the following basic structure:\n\n**********\n\n**Controls**\n\n**Miniview**\n\n## Nodes[](#nodes)\n\nYou can provide arbitrary JSX to render your nodes. In the above example we have drawn our nodes as basic coloured boxes, but your JSX can be as complex or as simple as you want, interacting with other parts of your app, communicating to the backend - whatever you like. VisuallyJs will take care of rendering and unloading nodes as needed. This is extremely powerful and its possibilities are only limited by your imagination (or perhaps your manager's budget).\n\nNodes are mapped by their `type` in VisuallyJs by an object we call a `View`, which allows you to configure different JSX for different types of nodes, and these mappings can inherit from each other - you can setup some behaviour in a base node type and then extend this type for specific subtypes. VisuallyJs also lets you declare various other behaviours for a node type - events such as tap, click, mouseover, etc can be mapped to listeners.\n\nFor a full discussion of rendering nodes, see the [Nodes and Groups documentation](/react/docs/apps/nodes-and-groups/overview.md).\n\n## Groups[](#groups)\n\nA group contains nodes or other groups (which may be nested to an arbitrary level). As with nodes, you provide the JSX you wish to use to render each group, and any group specific behaviours, by mapping a group type inside a view.\n\nGroups offer a number of options for how to control their child nodes or groups: the above example prevents the node from being dragged outside of the group, but you can instruct VisuallyJs to allow nodes to be dragged out of groups, and you can also control what nodes/groups can be dropped on a group.\n\nFor a full discussion of rendering groups, see the [Nodes and Groups documentation](/react/docs/apps/nodes-and-groups/overview.md).\n\n## Edges[](#edges)\n\nEdges join nodes/groups, and they can be represented in several different ways - the representation of an edge is called a `Connector`. In the above example we use a straight connector, which is the default, but VisuallyJs ships with `Orthogonal` (horizontal and vertical lines only), `Bezier` (a cubic Bézier curve) and `QuadraticBezier` (a Bézier curve with a single control point), and you can also create your own.\n\nAs with nodes and groups, edges are mapped via a `type` in a view. This type can declare various aspect of how an edge appears, such as the connector used, where on the vertex the edge should be anchored, the appearance of the edge, its label, etc. You can also map event handlers in an edge type to hook in to mouse/touch events with your edges.\n\n### Anchors[](#anchors)\n\nA key concept with edges is where they are anchored to the vertices to which they are connected.\n\n### Overlays[](#overlays)\n\nEdges can have any number of `Overlays` attached to them. In the above example each edge has a `Label` overlay positioned halfway along the path, and an `Arrow` overlay at the target vertex.\n\nFor a full discussion of how to render edges, see the [Edges documentation](/react/docs/apps/edges/overview.md).\n\n## Controls[](#controls)\n\nThis component provides a set of controls for a surface - such operations as zoom to extents, undo/redo, clear, etc. The operations that are available can be specified on the controls element, and you can also add your own buttons.\n\nThe reference page for this component can be [found here](/react/docs/reference/ControlsComponent.md).\n\n## Miniview[](#miniview)\n\nProvides a miniaturized view of a Surface, showing the nodes/groups in the Surface canvas. Users can pan/zoom the surface via pointer/touch events on the Miniview, and click on specific vertices to have the Surface center itself on the clicked vertex.\n\nThe reference page for this component can be [found here](/react/docs/reference/MiniviewComponent.md).\n\n## Next Steps[](#next-steps)\n\n[Building an app](/react/docs/apps/building-an-app.md)\n\n[A guided step-by-step on building your first app](/react/docs/apps/building-an-app.md)\n\n[Edges](/react/docs/apps/edges/overview.md)\n\n[Read about the various ways you can create and interact with edges](/react/docs/apps/edges/overview.md)\n\n[Nodes and Groups](/react/docs/apps/nodes-and-groups/overview.md)\n\n[Read about the various ways you can create and interact with nodes and groups](/react/docs/apps/nodes-and-groups/overview.md)\n\n[Data Model](/react/docs/apps/model/overview.md)\n\n[Read an in-depth guide to the VisuallyJs data model](/react/docs/apps/model/overview.md)","url":"https://visuallyjs.com/react/docs/apps","lib":"react","topic":""},"docs/charts/concepts/axes.md":{"title":"Axes","body":"# Axes\n\nMost charts use two axes to display data - a vertical axis, or Y axis, and a horizontal axis, or X axis. Each axis can display:\n\n* a title, positioned in the center of the axis or aligned to one end;\n* labels, showing either values the axis is measuring, or the names of categories plotted on the axis;\n* a marker line demarcating the axis from the plot area\n\nAll of these are optional.\n\nIn the chart above,\n\n* \"Millions of inhabitants\" is the `title` for the y axis;\n* The numbers 0 - 70 on the y axis are the y axis `labels`;\n* 'UK' and 'Canada' are the x axis `labels`\n\nAlso, the chart has a [title and subtitle](/react/docs/charts/concepts/title.md), and a [legend](/react/docs/charts/concepts/legend.md). See the linked pages for a discussion of these.\n\n## Axis Types[](#axis-types)\n\nThere are two types of axis:\n\n* [Category Axis](#category-axis) This axis type contains the various categories in the dataset. In the chart above, we plotted the population of several countries, and the category axis contains the country names.\n* [Value Axis](#value-axis) This axis type plots values from the dataset. In the chart above, the value axis contains the population figures. Note that in VisuallyJs, value axes are always **linear**, that is the values advance in a linear progression. Support for logarithmic and datetime axes is scheduled for an upcoming release.\n\nNot every chart has both a category axis and a value axis - `Scatter` and `Bubble` charts, for instance, have two value axes, as they plot two values from the dataset. But `Column`, `Bar`, `Line` and `Area` charts have a category axis and a value axis.\n\n## Specifying axes[](#specifying-axes)\n\nHow you specify axes depends on the type of chart you're creating.\n\n### CategoryValueCharts[](#categoryvaluecharts)\n\nFor this type of chart (`Column`, `Bar`, `Line` and `Area`), your chart options will contain a `categoryAxis` and a `valueAxis` definition:\n\n```jsx\nimport {ColumnChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n categoryAxis: {\n title: {\n text: \"Country\"\n }\n },\n valueAxis: {\n title: {\n text: \"Country\"\n }\n }\n} \n \n return <ColumnChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### DualValueCharts[](#dualvaluecharts)\n\nFor this type of chart (`Scatter`, `Bubble`), your chart options will contain an `xAxis` and a `yAxis` definition, each of which describes a value axis:\n\n```jsx\nimport {ScatterChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n xAxis: {\n title: {\n text: \"Age\"\n },\n valueField: \"age\"\n },\n yAxis: {\n title: {\n text: \"height\"\n },\n valueField: \"height\"\n }\n} \n \n return <ScatterChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n## Axis Title[](#axis-title)\n\nThe title for an axis is specified by [AxisTitleSpec](). The simplest title contains just the text to display:\n\n```javascript\ntitle:{\n text:\"Axis Title\"\n}\n\n```\n\n### Title alignment[](#title-alignment)\n\nAxis titles are, by default, aligned to the middle of their axis. You can control this via the `align` option:\n\n## Configuring an axis[](#configuring-an-axis)\n\n### CategoryValueCharts[](#categoryvaluecharts-1)\n\n#### Category Axis[](#category-axis)\n\nThis is the axis containing the various categories in the dataset. In the example above of country populations, the category axis lists the countries in the dataset.\n\nThis is an optional config; VisuallyJs will use defaults if you do not provide a `categoryAxis` in your chart options.\n\n```jsx\nimport {ColumnChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n categoryAxis: {\n title: {\n text: \"Country\"\n }\n }\n} \n \n return <ColumnChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\nThere are a number of configurable options on the category axis:\n\nCategoryAxisDefinition\n\nDefinition of a category axis\n\n| Name | Type | Description |\n| ---------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| crosshair? | boolean \\| [CrosshairOptions]() | Whether to show a crosshair for this axis. If you supply 'true', defaults will be used. Otherwise you can supply options to customise the crosshair. |\n| font? | [FontSpec]() | Spec for the font to use for all text on the axis. If you provide a `title` spec for this axis, any font settings in that spec will override these for the title. |\n| id? | string | Axis ID. |\n| lineSize? | number | The width of the baseline (if visible). Defaults to 2 pixels. |\n| position? | AxisPosition | The position for the axis: for a Y axis, AXIS\\_POSITION\\_START means on the left (this is the default for a y axis), and AXIS\\_POSITION\\_END means on the right. For an X axis, AXIS\\_POSITION\\_START means on the top, and AXIS\\_POSITION\\_END means on the bottom (the default for an X axis). |\n| showLine? | boolean | Whether or not to show a solid line representing the axis' baseline. Defaults to false. |\n| title? | [AxisTitleSpec]() | Title for the axis. Defaults to empty. |\n\n#### Value Axis[](#value-axis)\n\nThis axis contains the values from the dataset. In the example above of country populations, the value axis plots the population figures.\n\nThis is an optional config; VisuallyJs will use defaults if you do not provide a `valueAxis` in your chart options.\n\n```jsx\nimport {ColumnChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n valueAxis: {\n title: {\n text: \"Country\"\n }\n }\n} \n \n return <ColumnChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\nThere are a number of configurable options on the value axis:\n\nValueAxisDefinition\n\nA value axis displays a set of values. It may be in either the X or Y axis, depending on how the chart is setup. For example, in a bar chart, the value axis is on the X axis, and the category axis is on the Y axis, but for a column chart it's the other way around. Scatter and bubble charts have a value axis in both X and Y.\n\n| Name | Type | Description |\n| --------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| crosshair? | boolean \\| [CrosshairOptions]() | Whether to show a crosshair for this axis. If you supply 'true', defaults will be used. Otherwise you can supply options to customise the crosshair. |\n| font? | [FontSpec]() | Spec for the font to use for all text on the axis. If you provide a `title` spec for this axis, any font settings in that spec will override these for the title. |\n| gridLineSize? | number | Width of the grid lines. Defaults to 1 pixel. |\n| id? | string | Axis ID. |\n| inverted? | boolean | Whether or not to invert the axis. If true, the axis will run from max to min instead of min to max. |\n| labelFormatter? | (value:number) => string | Optional formatter for all value labels. |\n| labelPrefix? | string | Optional prefix for all value labels. Will be ignored if you provide a `labelFormatter`. |\n| labelSuffix? | string | Optional suffix for all value labels. Will be ignored if you provide a `labelFormatter`. |\n| lineSize? | number | The width of the baseline (if visible). Defaults to 2 pixels. |\n| max? | number | Maximum value for the axis. Defaults to not set. If this is set and your dataset has values above this value their visual representation in bar/column charts will be truncated. If you have a chart with multiple value axes and one or more of them declares a `max`, the largest value for `max` will be used for all axes. |\n| min? | number | Minimum value for the axis. Defaults to not set. If this is set and your dataset has values below this value their visual representation in bar/column charts will be truncated. If you have a chart with multiple value axes and one or more of them declares a `min`, the smallest value for `min` will be used for all axes. |\n| position? | AxisPosition | The position for the axis: for a Y axis, AXIS\\_POSITION\\_START means on the left (this is the default for a y axis), and AXIS\\_POSITION\\_END means on the right. For an X axis, AXIS\\_POSITION\\_START means on the top, and AXIS\\_POSITION\\_END means on the bottom (the default for an X axis). |\n| showGrid? | boolean | Whether or not to show grid lines for each value in the scale. Defaults to false. |\n| showLine? | boolean | Whether or not to show a solid line representing the axis' baseline. Defaults to false. |\n| step? | number | Optional fixed step size for the axis scale. |\n| title? | [AxisTitleSpec]() | Title for the axis. Defaults to empty. |\n\n## CSS Classes[](#css-classes)\n\n| Class | Description |\n| ----------------------------------- | -------------------------------------------------------- |\n| `vjs-chart-crosshair` | Added to the crosshairs element of a chart |\n| `vjs-chart-crosshair-label` | Added to the label of a value axis crosshair element |\n| `vjs-chart-subtitle` | Added to the subtitle element of a chart |\n| `vjs-chart-title` | Added to the title element of a chart |\n| `vjs-chart-crosshair-category-axis` | Added to the category axis crosshair elements of a chart |\n| `vjs-chart-crosshair-value-axis` | Added to the value axis crosshair elements of a chart |","url":"https://visuallyjs.com/react/docs/charts/concepts/axes","lib":"react","topic":"charts"},"docs/charts/concepts/colors.md":{"title":"Colors","body":"# Colors\n\nThere are several parts of a chart that you can configure colors for:\n\n* [Chart background](#chart-background)\n* [Plot background](#plot-background)\n* [Grid lines](#grid-lines)\n* Chart data points/lines/areas\n* Chart axes/labels\n\n## Chart background[](#chart-background)\n\nYou can set the background color of the chart using the `backgroundColor` property of a chart's `style`. It defaults to `#FFFFFF`. Alternatively, you can use the `.vjs-chart-background` CSS class to style the background.\n\n```jsx\nimport {LineChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {x:1,id:\"Value 1\"},\n {x:2,id:\"Value 2\"},\n {x:3,id:\"Value 3\"}\n]\n \n const options = {\n style: {\n backgroundColor: \"#f0f0f0\"\n },\n series: [\n {\n valueField: \"x\"\n }\n ]\n} \n \n return <LineChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\n## Plot background[](#plot-background)\n\nMost charts support the concept of the 'plot' area - the part of the chart where the data points are drawn. By default, the plot background will be the same color as the chart background, but you can set it independently in one of two ways: you can set the `plotBackgroundColor` property on a chart's `style`, or you can use the `.vjs-chart-plot-background` CSS class to style the background (but note using CSS means the color will not be set in an SVG export of the chart).\n\n```jsx\nimport {LineChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {x:1,id:\"Value 1\"},\n {x:2,id:\"Value 2\"},\n {x:3,id:\"Value 3\"}\n]\n \n const options = {\n style: {\n plotBackgroundColor: \"#f0f0f0\"\n },\n series: [\n {\n valueField: \"x\"\n }\n ]\n} \n \n return <LineChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\n## Grid lines[](#grid-lines)\n\nGrid lines, in charts that use them, have a default color of `#AAAAAA`. This can be overridden by supplying a `gridLineColor` in the `style` option for a chart:\n\n```jsx\nimport {LineChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {x:1,id:\"Value 1\"},\n {x:2,id:\"Value 2\"},\n {x:3,id:\"Value 3\"}\n]\n \n const options = {\n style: {\n gridLineColor: \"#FF0000\"\n },\n series: [\n {\n valueField: \"x\"\n }\n ]\n} \n \n return <LineChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\n## Labels[](#labels)\n\nThe labels on each axis default to the system color for their text. You can change this by providing a `labelColor` config on the style config:\n\n```jsx\nimport {LineChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {x:1,id:\"Value 1\"},\n {x:2,id:\"Value 2\"},\n {x:3,id:\"Value 3\"}\n]\n \n const options = {\n style: {\n labelColor: \"#2233ee\"\n },\n series: [\n {\n valueField: \"x\"\n }\n ]\n} \n \n return <LineChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\n### Per-label color[](#per-label-color)\n\nYou can also provide a `labelColorGenerator` function, if you want to be able to specify custom colors per label. In this example we mark whole number values as red (and returning null for other values means the default is used, which you may have set via a `labelColor` config):\n\n```jsx\nimport {LineChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {x:1,id:\"Value 1\"},\n {x:2,id:\"Value 2\"},\n {x:3,id:\"Value 3\"}\n]\n \n const options = {\n style: {},\n series: [\n {\n valueField: \"x\"\n }\n ]\n} \n \n return <LineChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\n## Data points[](#data-points)\n\nDifferent charts represent their data points in various ways.\n\n### Default Data Color[](#default-data-color)\n\nThe `defaultColor` property in `BaseChartOptions` allows you to set a single color that will be used for all data series in the chart. This property, if set, overrides any `colorGenerator` that might be present. Each of the 2D charts will honor this setting. Here's a bar chart with a default color, for example:\n\n```jsx\nimport {BarChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {id:\"A\",value:10},\n {id:\"B\",value:20},\n {id:\"C\",value:15}\n]\n \n const options = {\n defaultColor: \"royalblue\",\n series: [\n {\n valueField: \"value\"\n }\n ]\n} \n \n return <BarChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\n...and here's an area chart showing the default color:\n\n```jsx\nimport {AreaChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {id:\"A\",value:10},\n {id:\"B\",value:20},\n {id:\"C\",value:15}\n]\n \n const options = {\n defaultColor: \"royalblue\",\n series: [\n {\n valueField: \"value\"\n }\n ]\n} \n \n return <AreaChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\n## Color Generators[](#color-generators)\n\nFor charts with multiple series, or where you want more variety in colors, you can use a `ColorGenerator`. The `ColorGenerator` interface defines an object that can generate colors for a specific context.\n\n```typescript\ninterface ColorGenerator {\n generate(ctx: any): string;\n}\n\n```\n\nThere are several concrete implementations of `ColorGenerator` available:\n\n### StaticColorGenerator[](#staticcolorgenerator)\n\nA `StaticColorGenerator` perpetually cycles through a given list of colors. This is useful when you have a specific palette you want to use.\n\n```jsx\nimport {PieChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {label:\"Red\",value:300},\n {label:\"Blue\",value:50},\n {label:\"Purple\",value:100},\n {label:\"Yellow\",value:40}\n]\n \n const options = {\n colorGenerator: new StaticColorGenerator(['#ff6384', '#36a2eb', '#cc65fe', '#ffce56'])\n} \n \n return <PieChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\n### RandomColorGenerator[](#randomcolorgenerator)\n\nA `RandomColorGenerator` generates random colors within certain bounds. It attempts to ensure that it doesn't return colors that are too similar and keeps colors within the range (20, 245).\n\n```jsx\nimport {BarChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {category:\"A\",value:10},\n {category:\"B\",value:20},\n {category:\"C\",value:15}\n]\n \n const options = {\n colorGenerator: new RandomColorGenerator()\n} \n \n return <BarChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\ntip\n\nThe same color is applied to each datapoint in a bar chart - if you want to confirm that the selected color was random, you'll have to reload this page!\n\n### SingleColorGenerator[](#singlecolorgenerator)\n\nA `SingleColorGenerator` always returns the same color. It's essentially a generator wrapper around a single color value.\n\n```jsx\nimport {AreaChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {x:1,y:5},\n {x:2,y:10},\n {x:3,y:7}\n]\n \n const options = {\n colorGenerator: new SingleColorGenerator('seagreen'),\n series: [\n {\n valueField: \"x\"\n }\n ],\n categoryAxis: {\n labelField: \"y\"\n }\n} \n \n return <AreaChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```","url":"https://visuallyjs.com/react/docs/charts/concepts/colors","lib":"react","topic":"charts"},"docs/charts/concepts/crosshairs.md":{"title":"Crosshairs","body":"# Crosshairs\n\nCrosshairs are lines that follow the mouse as it moves across an XY Chart. They can be attached to any value or category axis.\n\n## Behavior by Axis Type[](#behavior-by-axis-type)\n\nThe appearance of a crosshair depends on the type of axis it is attached to:\n\n* **Category Axis**: On a category axis, the crosshair is represented by a rectangle that is as wide (on X) or as high (on Y) as the entire category. This helps highlight the specific category being hovered.\n* **Value Axis**: On a value axis, the crosshair is a thin line (by default 1 pixel wide). It allows for precise tracking of values across the chart.\n\n## Configuration Options[](#configuration-options)\n\nCrosshairs are configured using the `crosshair` property on an axis definition. You can set it to `true` to use default settings, or provide a `CrosshairOptions` object:\n\nCrosshairOptions\n\nOptions for the crosshair display on an axis.\n\n| Name | Type | Description |\n| ----------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| color? | string | Color of the crosshair line. |\n| cssClass? | string | Optional CSS class to write to the crosshair element. |\n| labelColor? | string | Color for the label text. Defaults to the same color as the line. |\n| labelFont? | [FontSpec]() | Font for the label. |\n| labelFormat? | string | Formatter for the label. |\n| labelPosition? | \"end\" \\| \"start\" | Position of the label on the crosshair. For a horizontal line, 'start' means 'left' and 'end' means 'right'. For a vertical line, 'start' means 'bottom' and 'end' means 'top'. |\n| labelValueFormat? | number \\| \"float\" \\| \"int\" | Standard number format for the value (e.g. 'int', 'float', or a number for decimal places). |\n| showLabel? | boolean | Whether or not to show the current value on the crosshair. Defaults to true. |\n| width? | number | Width of the crosshair line. Defaults to 1. |\n\n## Labelling on Value Axes[](#labelling-on-value-axes)\n\nWhen attached to a value axis, a crosshair can display the current value corresponding to the mouse position.\n\n* **Automatic Positioning**: Labels are automatically positioned to remain within the chart area. If a label on a vertical crosshair would go outside the chart to the right, it is shifted to the left. For horizontal crosshairs, if it would go above the chart, it is shifted below.\n* **Custom Formatting**: You can use the `labelFormat` option to customize how the value is displayed. This supports the same template engine as tooltips, allowing for rich text (e.g., `<b>{{value}}</b>`) and access to the `value` and `rawValue` variables.\n* **Font Specification**: The `labelFont` property accepts a `FontSpec` object to control the size and style of the label text.\n* **Start/End Positioning**: Use `labelPosition` to decide which end of the crosshair the label should appear on by default ('start' for bottom/left, 'end' for top/right).\n\n#### Example[](#example)\n\n```jsx\nimport {LineChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n categoryAxis: {\n crosshair: true\n },\n valueAxis: {\n crosshair: {\n color: \"red\",\n width: 2,\n showLabel: true,\n labelPosition: \"end\",\n labelFormat: \"Value: <b>{{value}}</b>\"\n }\n }\n} \n \n return <LineChartComponent options={options} className=\"my-chart\"/>\n}\n\n```","url":"https://visuallyjs.com/react/docs/charts/concepts/crosshairs","lib":"react","topic":"charts"},"docs/charts/concepts/legend.md":{"title":"Legend","body":"# Legend\n\nThe legend provides a visual key for the series displayed in the chart. By default, the legend is visible and automatically includes all series with a `label` defined.\n\n## Visibility[](#visibility)\n\nLegends are shown by default. However, if a chart contains only a single series, the legend is hidden by default to save space. You can control this behavior using the `hide` and `hideForSingleSeries` properties.\n\n* `hide`: Set to `true` to always hide the legend.\n* `hideForSingleSeries`: Defaults to `true`. Set to `false` if you want to show the legend even when there is only one series.\n\n## Positioning[](#positioning)\n\nThe legend can be positioned relative to the chart area or at an absolute position within the chart container.\n\n### Relative Positioning[](#relative-positioning)\n\nUse the `valign` and `align` properties to position the legend relative to the chart.\n\n* **Above**: Set `valign` to `\"top\"`.\n* **Below**: Set `valign` to `\"bottom\"` (default).\n* **Left/Right**: When `valign` is set to `\"middle\"`, the legend is positioned to the left or right of the chart area based on the `align` property (`\"left\"` or `\"right\"`).\n\n### Absolute (Floating) Positioning[](#absolute-floating-positioning)\n\nFor more precise control, you can \"float\" the legend by setting `floating: true`. This allows you to position the legend anywhere within the chart container using `x` and `y` coordinates.\n\n```javascript\nlegend: {\n floating: true,\n x: 100,\n y: 50\n}\n\n```\n\n## Layout and Orientation[](#layout-and-orientation)\n\nThe legend items can be arranged in a row or a column using the `orientation` property:\n\n* **Row**: Set `orientation` to `\"horizontal\"`.\n* **Column**: Set `orientation` to `\"vertical\"` (default).\n\n## API Reference[](#api-reference)\n\n### LegendSpec[](#legendspec)\n\nThe `legend` object in the chart options is of type [LegendSpec]() and supports the following properties:\n\nLegendSpec\n\nOptions for a chart legend.\n\n| Name | Type | Description |\n| -------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| align? | \"center\" \\| \"left\" \\| \"right\" | How to align the content of the legend. Defaults to center align. |\n| floating? | boolean | Defaults to false, meaning the legend is positioned inline with the chart. When this is set to true, the legend can be floated anywhere in the chart (for which you need to provide values for `x` and `y`). |\n| font? | [FontSpec]() | Optional font specification for the legend. |\n| hide? | boolean | Defaults to false. If true, the legend will not be shown. |\n| hideForSingleSeries? | boolean | Defaults to true: when there is a single series in the chart, the legend is not drawn. Set this to false to override that behaviour. |\n| hover? | boolean | Defaults to true - when user hovers over a series in the legend, the series is highlighted in the chart |\n| orientation? | \"horizontal\" \\| \"vertical\" | Defaults to vertical. The orientation in which to align the items. |\n| padding? | number | When not floating, padding to draw around the legend. |\n| valign? | \"top\" \\| \"bottom\" \\| \"middle\" | Where to position the legend vertically (when floating is false). Defaults to bottom; you can choose to place the legend at the top (underneath the title), or to the left/right of the chart area. |\n| x? | number | When floating is true, the X position of the legend. |\n| y? | number | When floating is true, the Y position of the legend. |","url":"https://visuallyjs.com/react/docs/charts/concepts/legend","lib":"react","topic":"charts"},"docs/charts/concepts/overview.md":{"title":"Overview","body":"# Charts\n\nVisuallyJs offers a number of different charts, many of which are what we refer to as a `CategoryValueChart` - the data is presented with an X and Y axis, where one axis notates the values in the dataset and the other notates the categories. Examples of `CategoryValueChart` include [BarChart](/react/docs/charts/types/bar-chart.md), [ColumnChart](/react/docs/charts/types/column-chart.md), [LineChart](/react/docs/charts/types/line-chart.md) and [AreaChart](/react/docs/charts/types/area-chart.md).\n\nAnother common type is a `DualValueChart`, in which both the X and Y axes plot a value from the dataset. Example of these include [ScatterChart](/react/docs/charts/types/scatter-chart.md) and [BubbleChart](/react/docs/charts/types/bubble-chart.md).\n\n<!-- -->\n\nSeveral other chart types are supported, including [Pie charts](/react/docs/charts/types/pie-chart.md), [Sankey charts](/react/docs/charts/types/sankey.md), and more.\n\n### Title / Subtitle[](#title--subtitle)\n\nUser-supplied text describing the chart. By default this appears at the top center of the chart, but can be relocated to any axis and left/right aligned. Can also be omitted. For more information see [Title and subtitle](/react/docs/charts/concepts/title.md).\n\n### Series[](#series)\n\nEvery chart is a representation of one or more data series'. In the above example we show two data series. In VisuallyJs you can supply data series information directly to a chart, but you can also extract the series data by defining a filter on some model that is backing an app or diagram in your UI. This is a powerful mechanism that lets you easily construct sophisticated applications in which your charts respond dynamically to actions taken elsewhere in the UI.\n\nFor more information see [Series](/react/docs/charts/concepts/title.md).\n\n### Axes[](#axes)\n\nMany charts use two axes to display data - a vertical axis, or Y axis, and a horizontal axis, or X axis. VisuallyJs offers a number of charts that use an X and Y axis to plot data. For more information about axes see [Axes](/react/docs/charts/concepts/axes.md).\n\n### Legend[](#legend)\n\nProvides information to your users about the data that is displayed. Legends appear, by default, at the bottom center of the chart, but can be moved to any axis or positioned absolute, or omitted.\n\nFor more information see [Legend](/react/docs/charts/concepts/legend.md).\n\n### Tooltips[](#tooltips)\n\nSeveral chart types support tooltips on hover - configurable popups containing a summary of a data point or data series.\n\nFor more information see [Tooltips](/react/docs/charts/concepts/tooltips.md).\n\n### Crosshairs[](#crosshairs)\n\nCrosshairs provide visual cues to a user for how the location of the pointer relates to the chart data. They're switched off by default but you can see them in the chart above.\n\nFor more information see [Crosshairs](/react/docs/charts/concepts/crosshairs.md).","url":"https://visuallyjs.com/react/docs/charts/concepts/overview","lib":"react","topic":"charts"},"docs/charts/concepts/series.md":{"title":"Series","body":"# Series\n\nCharts display data sourced from one or more data series. VisuallyJs supports several types of data series:\n\n* [RecordBasedSeries](#recordbased-series) In which the data is stored in a list of objects, and values are extracted from these objects via key names that you specify;\n* [ArrayBasedSeries](#arraybased-series) In which the data is stored in an array inside some object. This type of series is what you'll use when you want to plot time-based information;\n* [CollationSeries](#collation-series) In which occurrences of a specific field's values are counted;\n* [SummingSeries](#summing-series) In which values from multiple fields in each data object are summed;\n* [SummingCollationSeries](#summing-collation-series) In which records are grouped by the occurrence of some specific field, whose value is then summed per group.\n\n## RecordBased series[](#recordbased-series)\n\nData in a `RecordBasedSeries` is stored in a list of objects, each of which contains the data for some specific category in the chart. The number of records in the list corresponds to the number of categories in the chart. Each record in the list can be used as the datasource for multiple series, by defining multiple series with different value fields.\n\nFor example, consider a dataset containing population statistics for various countries, where the value for each year is a separately keyed value in the data for each country:\n\n```javascript\n[\n {\n id:\"uk\",\n \"2010\":62.8,\n \"2011\":63.5,\n \"2012\":63.7\n },\n {\n id:\"ca\",\n \"2010\":34,\n \"2011\":34.4,\n \"2012\":34.7\n }\n]\n\n```\n\nWe can create a chart of this by specifying a series for each year:\n\n```javascript\nconst chartOptions = {\n series:[\n {\n valueField:\"2010\",\n label:\"2010\"\n },\n {\n valueField:\"2011\",\n label:\"2011\"\n },\n {\n valueField:\"2012\",\n label:\"2012\"\n }\n ],\n valueAxis:{\n title:{\n text:\"Millions of inhabitants\"\n }\n },\n title:{\n text:\"Population growth\"\n },\n subtitle:{\n text:\"Source: https://macrotrends.net\",\n }\n}\n\n```\n\nVisuallyJs will, by default, use the `id` field of each object in this list to identify a category. In the dataset above we have used the ISO country code as the ID, so we see `uk` and `ca` as the category labels - for a discussion of axes, and how to label them, take a look at [the documentation for Axes](/react/docs/charts/charts/concepts/axes).\n\n## ArrayBased series[](#arraybased-series)\n\nIn an `ArrayBasedSeries`, data is stored in an array inside some object. The individual values from the array are used as the category values, ie. the number of entries in the array corresponds to the number of entries in the category axis. Each individual object represents a separate series.\n\nThis dataset demonstrates the structure. We are modelling the change of population across a few years:\n\n```javascript\n[\n {\n id:\"uk\",\n values:[55, 57, 59]\n },\n {\n id:\"ca\",\n values:[24, 26, 29]\n }\n]\n\n```\n\nVisuallyJs assumes a data series is object based by default, so we need to instruct it that we're using an array based series:\n\n```javascript\nconst chartOptions = {\n series:[\n {\n type:\"array\",\n startPoint:2010,\n step:1\n }\n ]\n}\n\n```\n\nHere, we have specified `type` to be `\"array\"`, and we also provided:\n\n* `startPoint` Tells VisuallyJs the number corresponding to the first entry in the list of values. In this case we have specified the year 2010. If you do not provide this, VisuallyJs will use a default value of 0.\n* `step` As shown above, this is optional, and defaults to 1. It tells VisuallyJs how much to increment the label by for each value.\n\n### Providing labels[](#providing-labels)\n\nIn the above example the labels for our data were numeric and increased at a constant rate. We provided a `startPoint` of 2010, and the chart incremented this value by one for each subsequent data point after the first one. This is fine for many types of numeric data, but it's not always what you want, and so there are a couple of ways you can provide your own labels array instead, in a series definition:\n\n#### In a list[](#in-a-list)\n\nThe series definition can contain an array of strings that are the labels for the data points.\n\n```javascript\n\nchartOptions = {\n ...,\n series:[\n {\n type:\"array\",\n labels:[\"Year 1\", \"Year 2\", \"Year 3\"]\n }\n ],\n ...\n}\n\n```\n\nIt is expected that the length of the `labels` array matches the values array in your data.\n\n#### Via a function[](#via-a-function)\n\nYou can also provide a `labelGenerator` function:\n\n```javascript\n\nchartOptions = {\n ...,\n series:[\n {\n type:\"array\",\n labelGenerator:(index, data) => {\n return `Label ${index}` \n }\n }\n ],\n ...\n}\n\n```\n\nThis is the most flexible option, as it allows you complete control over the labels that are displayed.\n\n## Collation series[](#collation-series)\n\nA `CollationSeries` is used to count the occurrences of specific values within a dataset. This is particularly useful for Pie charts where you want to show the distribution of a certain attribute across your data.\n\nFor example, given a list of people with a `meal` attribute:\n\n```javascript\nconst collatingData = [\n { name: 'Marek', meal: \"pizza\" },\n { name: 'Dalek', meal: \"pasta\" },\n { name: 'John', meal: \"pasta\" },\n { name: 'Sue', meal: \"steak\" },\n { name: 'Andrew', meal: \"steak\" },\n { name: 'Juanita', meal: \"pasta\" },\n { name: 'Boris', meal: \"pizza\" },\n]\n\n```\n\nYou can create a Pie chart that shows the count of each meal preference by using a series of type `\"collation\"`:\n\n```javascript\nconst chartOptions = {\n data: collatingData,\n series: [\n {\n type: \"collation\",\n valueField: \"meal\"\n }\n ]\n}\n\n```\n\nVisuallyJs will count the occurrences of each value in the `color` field and use these counts as the values for the chart segments.\n\n## Summing series[](#summing-series)\n\nA `SummingSeries` allows you to aggregate values from multiple fields within each data object. This is another great option for Pie charts when your data is structured such that each record contains multiple values that you want to compare as part of a whole.\n\nConsider a dataset where each record represents a set of values:\n\n```javascript\nconst summingData = [\n { name: 'record1', red: 4, green: 2, blue: 3 },\n { name: 'record2', red: 5, green: 2, blue: 3 },\n { name: 'record3', red: 1, green: 2, blue: 3 }\n]\n\n```\n\nYou can create a Pie chart that shows the total sum of each field across all records:\n\n```javascript\nconst chartOptions = {\n data: summingData,\n colors: [\"#FF0000\", \"#00FF00\", \"#0000FF\"],\n series: [\n {\n type: \"summing\",\n fields: [\"red\", \"green\", \"blue\"]\n }\n ]\n}\n\n```\n\nIn this example, VisuallyJs will sum the `red`, `blue`, and `green` fields across all objects in `summingData` and display the totals in the Pie chart.\n\n## Summing Collation series[](#summing-collation-series)\n\nA `SummingCollationSeries` combined the grouping from a collation series with summing.\n\nFor example, let's add a `qty` field to the list of people with a `meal` attribute that we used in the collation series above:\n\n```javascript\nconst summingCollatingData = [\n { name: 'Marek', meal: \"pizza\", qty:5 },\n { name: 'Dalek', meal: \"pasta\", qty:3 },\n { name: 'John', meal: \"pasta\", qty:4 },\n { name: 'Sue', meal: \"steak\", qty:2 },\n { name: 'Andrew', meal: \"steak\", qty:1 },\n { name: 'Juanita', meal: \"pasta\", qty:4 },\n { name: 'Boris', meal: \"pizza\", qty:1 },\n]\n\n```\n\nYou can create a Pie chart that first groups the record by `meal`, and then sums the `qty` for each meal:\n\n```javascript\nconst chartOptions = {\n data: summingCollatingData,\n series: [\n {\n type: \"summing-collation\",\n categoryField: \"meal\",\n sumField:\"qty\"\n }\n ]\n}\n\n```","url":"https://visuallyjs.com/react/docs/charts/concepts/series","lib":"react","topic":"charts"},"docs/charts/concepts/title.md":{"title":"Title","body":"# Title and subtitle\n\nCharts in VisuallyJs support both a `title` and `subtitle`, both of which are optional.\n\n```jsx\nimport {ColumnChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Population by year\"\n },\n subtitle: {\n text: \"Source: https://macrotrends.net\"\n }\n} \n \n return <ColumnChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n## Alignment[](#alignment)\n\nBy default, a chart title will be center aligned, as in the example above. You can control this via the `align` configuration:\n\n```jsx\nimport {ColumnChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Population by year\",\n align: CHART_TITLE_ALIGN_LEFT\n },\n subtitle: {\n text: \"Source: https://macrotrends.net\",\n align: CHART_TITLE_ALIGN_LEFT\n }\n} \n \n return <ColumnChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n## Placement[](#placement)\n\nBy default, a chart title will appear at the top of the chart. You can control this via the `placement` configuration:\n\n```jsx\nimport {ColumnChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Population by year\",\n placement: CHART_TITLE_PLACEMENT_BOTTOM\n },\n subtitle: {\n text: \"Source: https://macrotrends.net\",\n placement: CHART_TITLE_PLACEMENT_BOTTOM\n }\n} \n \n return <ColumnChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n## Wrapping[](#wrapping)\n\nBy default, a chart title will wrap if it is wider than the container the chart is displayed in.\n\n```jsx\nimport {ColumnChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"This chart shows you the figures corresponding to the population of two countries, from the year 2010 through to the year 2012\"\n },\n subtitle: {\n text: \"Source: https://macrotrends.net\"\n }\n} \n \n return <ColumnChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### Fill ratio[](#fill-ratio)\n\nWhen wrapping is enabled, the maximum length of any line of text is computed according to the current `fillRatio`, which defaults to 0.9, meaning that by default a wrapped line will fill up to 90% of the available width. You can change this value:\n\n```jsx\nimport {ColumnChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"This chart shows you the figures corresponding to the population of two countries, from the year 2010 through to the year 2012\",\n fillRatio: 0.75\n },\n subtitle: {\n text: \"Source: https://macrotrends.net\"\n }\n} \n \n return <ColumnChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### No wrapping[](#no-wrapping)\n\nWrapping can be switched off:\n\n```javascript\ntitle:{\n text:\"This chart shows you the figures corresponding to the population of two countries, from the year 2010 through to the year 2012\",\n wrap:false\n}\n\n```","url":"https://visuallyjs.com/react/docs/charts/concepts/title","lib":"react","topic":"charts"},"docs/charts/concepts/tooltips.md":{"title":"Tooltips","body":"# Tooltips\n\nTooltips provide extra information about data points when a user hovers over them. They are supported in most chart types, including all `BaseXYChart` subclasses (Column, Bar, Line, Area etc.), `DualValueChart` subclasses (Scatter, Bubble), and Pie/Donut charts.\n\n## Configuration[](#configuration)\n\nTooltips are configured via the `tooltip` object in the chart options.\n\n### Basic example[](#basic-example)\n\nThe simplest tooltip configuration uses a format string:\n\n```jsx\nimport {ColumnChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n data: [\n {\n category: \"A\",\n value: 10\n },\n {\n category: \"B\",\n value: 20\n },\n {\n category: \"C\",\n value: 15\n }\n ],\n series: [\n {\n valueField: \"value\",\n label: \"Quantity\"\n }\n ],\n tooltip: {\n format: \"{{category}}: {{point.value}}\"\n }\n} \n \n return <ColumnChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n## Format Template[](#format-template)\n\nThe `format` string uses a simple templating syntax where variables are enclosed in double curly braces: `{{variable}}`.\n\n### Context Variables[](#context-variables)\n\nThe following variables are available for use in the tooltip template:\n\n* ##### category[](#category)\n\nThe category name of the data point (for XY charts).\n\n* ##### series[](#series)\n\nTooltipDataSeries\n\nDefinition of the `series` object passed to a Tooltip\n\n{\n\n<br />\n\n color:string,\n\n<br />\n\n id:string,\n\n<br />\n\n label:string,\n\n<br />\n\n max:number,\n\n<br />\n\n min:number,\n\n<br />\n\n total:number\n\n<br />\n\n}\n\n* ##### point[](#point)\n\nTooltipDataPoint\n\nDefinition of the `point` object passed to a Tooltip. Not every chart type provides every field - see the individual chart docs for discussions.\n\n{\n\n<br />\n\n maxValue:string,\n\n<br />\n\n minValue:string,\n\n<br />\n\n rawMaxValue:number,\n\n<br />\n\n rawMinValue:number,\n\n<br />\n\n rawValue:number,\n\n<br />\n\n stackTotal:number,\n\n<br />\n\n value:string\n\n<br />\n\n}\n\n### HTML support[](#html-support)\n\nSeveral HTML tags are supported in your format string to style the tooltip:\n\n```javascript\ntooltip: {\n format: \"<b>{{category}}</b><br/>{{series.label}}: {{point.value}}\"\n}\n\n```\n\n* **b** Indicates the text inside of the element should be in bold face\n* **strong** An alias for **b**\n* **i** Indicates the text inside of the element should be italics\n* **em** An alias for **i**\n* **br** Inserts a line break. Ensure that you close this element - `<br/>`, not `<br>`.\n\n## Customizing appearance[](#customizing-appearance)\n\n### Font and Text Color[](#font-and-text-color)\n\nYou can customize the appearance of the tooltip's text using the `font` and `textColor` options.\n\n* ##### font[](#font)\n\nAn optional object of type `FontSpec` that allows you to set the following properties:\n\nFontSpec\n\nSpecs for a font. The default values depend on the context.\n\n| Name | Type | Description |\n| ------- | -------------- | -------------------------------------------------------------------------------------------------------------- |\n| family? | string | Font family to use. |\n| size? | number | Size of the font. Default value depends on the context this spec occurs in. |\n| style? | [FontStyle]() | Font style to use. Default value depends on the context this spec occurs in. |\n| weight? | [FontWeight]() | Font weight to use (e.g., \"normal\", \"bold\", \"100\", \"300\"). Defaults to null, which browsers treat as \"normal\". |\n\n* ##### textColor[](#textcolor)\n\nA string representing the color of the tooltip text (e.g., `\"#FF0000\"`, `\"rgb(45,67,89)\"`). Defaults to the system default. We recommend against the usage of named CSS colors - they can't be parsed and so effects like background highlights will fail.\n\n### Background and Border[](#background-and-border)\n\nThe tooltip's background rectangle can be styled using the following properties:\n\n* `fill`: The background color of the tooltip. Defaults to `\"#FFFFFF\"` (white).\n* `outline`: The color of the tooltip's border. Defaults to `\"#999999\"`.\n* `outlineWidth`: The width of the tooltip's border in pixels. Defaults to `1`.\n* `cornerRadius`: The radius of the tooltip's corners. Defaults to `3` pixels.\n\n## Additional options[](#additional-options)\n\n### valueSuffix[](#valuesuffix)\n\nA string to append to the end of any value displayed in the tooltip.\n\n```javascript\ntooltip: {\n format: \"{{category}}: {{point.value}}\",\n valueSuffix: \" kg\"\n}\n\n```\n\n### shared[](#shared)\n\nWhen set to `true`, the tooltip will display information for all series at the same category index in a single tooltip (supported in some XY charts).\n\n```javascript\ntooltip: {\n shared: true\n}\n\n```","url":"https://visuallyjs.com/react/docs/charts/concepts/tooltips","lib":"react","topic":"charts"},"docs/charts/css.md":{"title":"Css","body":"# CSS\n\nVisuallyJs assigns a number of CSS classes to charts, to enable you to easily establish your own themes.\n\n### Common chart classes[](#common-chart-classes)\n\n| Class | Description |\n| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |\n| `vjs-area-chart` | Set on the container element for an area chart |\n| `vjs-area-chart-area` | Added to the painted area element of an Area chart |\n| `vjs-bar-chart` | Added to the container element in a bar chart |\n| `vjs-bar-chart-bar` | Added to each bar element in a bar chart |\n| `vjs-bubble-chart` | Added to a bubble chart |\n| `vjs-bubble-chart-point` | Added to each point in a bubble chart |\n| `vjs-chart-axis` | Added to both the X and Y axes in an XY chart |\n| `vjs-chart-axis-labels` | Added to the parent container for the label elements in both the X and Y axes of an XY chart |\n| `vjs-chart-axis-line` | Added to the baseline marking the X or Y axis in an XY chart |\n| `vjs-chart-axis-title` | Added to the title element in both the X and Y axes of an XY chart |\n| `vjs-chart-background` | Added to the background element of a chart. |\n| `vjs-chart-body` | Added to the element that contains series data and crosshairs. |\n| `vjs-chart-crosshair` | Added to the crosshairs element of a chart |\n| `vjs-chart-crosshair-label` | Added to the label of a value axis crosshair element |\n| `vjs-chart-empty` | Added to the \"No data\" message that is shown when a chart is empty. |\n| `vjs-chart-gridline` | Added to each gridline element in an XY chart |\n| `vjs-chart-gridlines` | Added to the parent SVG group of the gridlines in an XY chart |\n| `vjs-chart-legend` | Added to a chart's legend element |\n| `vjs-chart-legend-dot` | Added to the dots for each item in a legend |\n| `vjs-chart-legend-item` | Added to an item in a chart's legend |\n| `vjs-chart-legend-label` | Added to the label in a chart's legend |\n| `vjs-chart-plot-background` | Added to element that is the parent of the chart's plot(s). |\n| `vjs-chart-point` | Added to each point in a scatter/bubble chart |\n| `vjs-chart-point-hit-area` | Added to the hit area elements that represent each data point. These are to assist users in selecting data points which are small. |\n| `vjs-chart-axis-scale-label` | Added to the labels of a value axis in an XY chart |\n| `vjs-chart-series` | Added to an SVG group element that represents a data series in an XY chart. |\n| `vjs-chart-subtitle` | Added to the subtitle element of a chart |\n| `vjs-chart-title` | Added to the title element of a chart |\n| `vjs-chart-x-axis` | Added to the X axis element in an XY chart |\n| `vjs-chart-x-axis-title` | Added to the X axis title element in an XY chart |\n| `vjs-chart-y-axis` | Added to the Y axis element in an XY chart |\n| `vjs-chart-y-axis-title` | Added to the Y axis title element in an XY chart |\n| `vjs-column-chart` | Added to the container element of a column chart |\n| `vjs-column-chart-column` | Added to each column element in a column chart |\n| `vjs-chart-crosshair-category-axis` | Added to the category axis crosshair elements of a chart |\n| `vjs-chart-crosshair-value-axis` | Added to the value axis crosshair elements of a chart |\n| `vjs-line-chart` | Set on the container element for a line chart |\n| `vjs-pie-chart` | CSS class set on a pie chart. |\n| `vjs-pie-slice` | CSS class set on a slice in a pie chart. |\n| `vjs-pie-slice-selected` | CSS class set on a selected slice in a pie chart. |\n| `vjs-scatter-chart` | Added to a scatter chart |\n| `vjs-scatter-chart-point` | Added to each point in a scatter chart |\n| `vjs-tooltip` | Added to a chart tooltip's main element |\n\n### Area Charts[](#area-charts)\n\n| Class | Description |\n| --------------------- | -------------------------------------------------- |\n| `vjs-area-chart` | Set on the container element for an area chart |\n| `vjs-area-chart-area` | Added to the painted area element of an Area chart |\n\n### Bar Charts[](#bar-charts)\n\n| Class | Description |\n| ------------------- | --------------------------------------------- |\n| `vjs-bar-chart` | Added to the container element in a bar chart |\n| `vjs-bar-chart-bar` | Added to each bar element in a bar chart |\n\n### Bubble Charts[](#bubble-charts)\n\n| Class | Description |\n| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |\n| `vjs-bubble-chart-point` | Added to each point in a bubble chart |\n| `vjs-chart-point` | Added to each point in a scatter/bubble chart |\n| `vjs-chart-point-hit-area` | Added to the hit area elements that represent each data point. These are to assist users in selecting data points which are small. |\n\n### Column Charts[](#column-charts)\n\n| Class | Description |\n| ------------------------- | ------------------------------------------------ |\n| `vjs-column-chart` | Added to the container element of a column chart |\n| `vjs-column-chart-column` | Added to each column element in a column chart |\n\n### Gauge Charts[](#gauge-charts)\n\n| Class | Description |\n| ------------------------ | ----------------------------------------------------- |\n| `vjs-gauge-chart` | Assigned to the container for a gauge chart |\n| `vjs-gauge-label` | Assigned to each label element in a GaugeChart. |\n| `vjs-gauge-needle` | Assigned to the needle element in a GaugeChart. |\n| `vjs-gauge-needle-pivot` | Assigned to the needle pivot element in a GaugeChart. |\n| `vjs-gauge-tick` | Assigned to each tick element in a GaugeChart. |\n| `vjs-gauge-track` | Assigned to the track element in a GaugeChart. |\n| `vjs-gauge-zone` | Assigned to each zone element in a GaugeChart. |\n\n### Line Charts[](#line-charts)\n\n| Class | Description |\n| ---------------- | --------------------------------------------- |\n| `vjs-line-chart` | Set on the container element for a line chart |\n\n### Pie Charts[](#pie-charts)\n\n| Class | Description |\n| ------------------------ | ------------------------------------------------- |\n| `vjs-pie-chart` | CSS class set on a pie chart. |\n| `vjs-pie-slice` | CSS class set on a slice in a pie chart. |\n| `vjs-pie-slice-selected` | CSS class set on a selected slice in a pie chart. |\n\n### Sankey Charts[](#sankey-charts)\n\n| Class | Description |\n| ----------------------- | ----------------------------------------------------------------------------------------------------------------- |\n| `vjs-sankey` | Assigned to the sankey chart container |\n| `vjs-sankey-edge` | Assigned to edges in Sankey chart |\n| `vjs-sankey-label` | Assigned to labels in a sankey chart |\n| `vjs-sankey-node` | Assigned to nodes in a sankey chart |\n| `vjs-sankey-selected` | Assigned to edges/nodes in Sankey chart when the edge/node forms part of the selected path. |\n| `vjs-sankey-unselected` | Assigned to edges/nodes in Sankey chart when something is selected but this edge/node is not in the selected path |\n\n### Scatter Charts[](#scatter-charts)\n\n| Class | Description |\n| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |\n| `vjs-bubble-chart` | Added to a bubble chart |\n| `vjs-chart-point` | Added to each point in a scatter/bubble chart |\n| `vjs-chart-point-hit-area` | Added to the hit area elements that represent each data point. These are to assist users in selecting data points which are small. |\n| `vjs-scatter-chart` | Added to a scatter chart |\n| `vjs-scatter-chart-point` | Added to each point in a scatter chart |","url":"https://visuallyjs.com/react/docs/charts/css","lib":"react","topic":"charts"},"docs/charts/types/area-chart.md":{"title":"Area Chart","body":"# Area Chart\n\nArea charts are similar to line charts, but the area below the line is filled with color.\n\n```jsx\nimport {AreaChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Corn & Wheat Production\"\n },\n valueAxis: {\n title: {\n text: \"1000 Metric Tons (MT)\"\n }\n },\n series: [\n {\n valueField: \"corn\",\n label: \"Corn\",\n color: \"rgb(223, 44, 184)\"\n },\n {\n valueField: \"wheat\",\n label: \"Wheat\",\n color: \"rgb(20, 119, 182)\"\n }\n ]\n} \n \n return <AreaChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### Inverting axes[](#inverting-axes)\n\nBy default, the area chart will use the X axis as the category axis, and the Y axis as the value axis. This behaviour can be changed by specifying you want the chart to be `inverted`.\n\n```jsx\nimport {AreaChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n inverted: true,\n ...\n} \n \n return <AreaChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n## Displaying a range[](#displaying-a-range)\n\nYou can display a range with an area chart - the area between the minimum and maximum values will be filled:\n\nThe only difference in the setup for a range vs a single series is that we specify `minValueField` and `maxValueField` instead of just `valueField`:\n\n```jsx\nimport {AreaChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Temperature Range\"\n },\n valueAxis: {\n title: {\n text: \"Degrees celsius\"\n }\n },\n legend: false,\n series: [\n {\n maxValueField: \"max\",\n minValueField: \"min\",\n label: \"Temperature\"\n }\n ]\n} \n \n return <AreaChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### Inverting axes[](#inverting-axes-1)\n\nAs with a single series area chart, set `inverted` if you wish to invert the axes:\n\n```jsx\nimport {AreaChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n inverted: true,\n ...\n} \n \n return <AreaChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n## Assigning Colors[](#assigning-colors)\n\nColors can be managed in several ways depending on whether you want a uniform look, series-specific styling, or dynamic color generation.\n\n### Chart Level[](#chart-level)\n\nSetting a `defaultColor` at the chart level applies a base color to all series unless overridden. This is useful for maintaining brand consistency across simple charts.\n\n```javascript\noptions: {\n defaultColor: '#3498db',\n // ...\n}\n\n```\n\n### Series Level[](#series-level)\n\nFor charts with multiple data series, you can assign specific colors to individual series to help distinguish between datasets.\n\n```javascript\nseries: [\n {\n valueField: \"corn\",\n label: \"Corn\",\n color: \"#f1c40f\"\n },\n {\n valueField: \"wheat\",\n label: \"Wheat\",\n color: \"#e67e22\"\n }\n]\n\n```\n\n### Color Generator[](#color-generator)\n\nIf you have a dynamic number of series or prefer an automated approach, you can provide a color generator (or an array of colors). The chart will then cycle through these colors for each new series or data point.\n\n```javascript\noptions: {\n colors: ['#1abc9c', '#2ecc71', '#3498db', '#9b59b6'],\n // ...\n}\n\n```\n\n### Background color[](#background-color)\n\nYou can set the background color of the chart using the `backgroundColor` property. It defaults to `#FFFFFF`. Alternatively, you can use the `.vjs-chart-background` CSS class to style the background.\n\n```jsx\nimport {AreaChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {x:1,id:\"Value 1\"},\n {x:2,id:\"Value 2\"},\n {x:3,id:\"Value 3\"}\n]\n \n const options = {\n backgroundColor: \"#f0f0f0\",\n title: \"Background Color Example\",\n series: [\n {\n valueField: \"x\"\n }\n ]\n} \n \n return <AreaChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\n## CSS Classes[](#css-classes)\n\n| Class | Description |\n| --------------------- | -------------------------------------------------- |\n| `vjs-area-chart` | Set on the container element for an area chart |\n| `vjs-area-chart-area` | Added to the painted area element of an Area chart |","url":"https://visuallyjs.com/react/docs/charts/types/area-chart","lib":"react","topic":"charts"},"docs/charts/types/bar-chart.md":{"title":"Bar Chart","body":"# Bar Chart\n\nIn a bar chart, values are presented on the X axis, and categories are presented on the Y axis.\n\n## Single series[](#single-series)\n\nThe simplest bar chart consists of a single data series:\n\n```jsx\nimport {BarChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Fuel Types\"\n },\n categoryAxis: {\n showLine: true,\n title: {\n text: \"Fuel Type\"\n }\n },\n valueAxis: {\n showLine: true,\n title: {\n text: \"Number of vehicles\"\n }\n },\n series: [\n {\n valueField: \"value\",\n label: \"Type\"\n }\n ],\n tooltip: {\n format: \"{{category}}:{{point.value}}\"\n }\n} \n \n return <BarChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n## Multiple series[](#multiple-series)\n\nMultiple series are supported.\n\n```jsx\nimport {BarChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Corn vs wheat estimated production for 2023\"\n },\n subtitle: {\n text: \"Source: https://www.indexmundi.com/agriculture/?commodity=corn\"\n },\n categoryAxis: {\n title: {\n text: \"Country\"\n }\n },\n valueAxis: {\n title: {\n text: \"1000 metric tons (MT)\"\n }\n },\n tooltip: {\n format: \"<b>{{category}}</b><br/>{{series.label}}:{{point.value}}\",\n valueSuffix: \" (1000 MT)\"\n },\n series: [\n {\n valueField: \"corn\",\n label: \"Corn\"\n },\n {\n valueField: \"wheat\",\n label: \"Wheat\"\n }\n ]\n} \n \n return <BarChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n## Ranged data[](#ranged-data)\n\nYou can display data that contains a minimum and maximum value:\n\n```jsx\nimport {BarChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Temperature range\",\n align: \"right\"\n },\n valueAxis: {\n title: {\n text: \"Degrees Celsius\"\n }\n },\n series: [\n {\n id: \"max\",\n maxValueField: \"max\",\n minValueField: \"min\",\n label: \"Temperature\"\n }\n ],\n legend: false,\n tooltip: {\n format: \"<b>{{category}}</b><br/>{{point.minValue}} - {{point.maxValue}}\",\n valueSuffix: \" C\"\n }\n} \n \n return <BarChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n```javascript\nconst data = [\n {id:\"Jan\", \"min\":-9.5, \"max\":8.0},\n {id:\"Feb\", min:-7.8,max:8.3},\n ...\n]\n\n```\n\n## Assigning Colors[](#assigning-colors)\n\nColors can be managed in several ways depending on whether you want a uniform look, series-specific styling, or dynamic color generation.\n\n### Chart Level[](#chart-level)\n\nSetting a `defaultColor` at the chart level applies a base color to all series unless overridden. This is useful for maintaining brand consistency across simple charts.\n\n```javascript\noptions: {\n defaultColor: '#3498db',\n // ...\n}\n\n```\n\n### Series Level[](#series-level)\n\nFor charts with multiple data series, you can assign specific colors to individual series to help distinguish between datasets.\n\n```javascript\nseries: [\n {\n valueField: \"corn\",\n label: \"Corn\",\n color: \"#f1c40f\"\n },\n {\n valueField: \"wheat\",\n label: \"Wheat\",\n color: \"#e67e22\"\n }\n]\n\n```\n\n### Color Generator[](#color-generator)\n\nIf you have a dynamic number of series or prefer an automated approach, you can provide a color generator (or an array of colors). The chart will then cycle through these colors for each new series or data point.\n\n```javascript\noptions: {\n colors: ['#1abc9c', '#2ecc71', '#3498db', '#9b59b6'],\n // ...\n}\n\n```\n\n### Background color[](#background-color)\n\nYou can set the background color of the chart using the `backgroundColor` property. It defaults to `#FFFFFF`. Alternatively, you can use the `.vjs-chart-background` CSS class to style the background.\n\n```jsx\nimport {BarChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {x:1,id:\"Value 1\"},\n {x:2,id:\"Value 2\"},\n {x:3,id:\"Value 3\"}\n]\n \n const options = {\n backgroundColor: \"#f0f0f0\",\n title: \"Background Color Example\",\n series: [\n {\n valueField: \"x\"\n }\n ]\n} \n \n return <BarChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\n## Stacking[](#stacking)\n\nThe `stacked` option determines how different series within the same category are displayed relative to each other. It can take one of the following values:\n\n* `false` (default): Series are displayed side-by-side within each category.\n* `true` or `\"default\"`:\n <!-- -->\n Series are stacked next to each other\n <!-- -->\n . The total\n <!-- -->\n width\n <!-- -->\n of the stack represents the sum of the values in that category.\n* `\"percent\"`: Series are stacked such that they always fill 100% of the available space on the value axis. Each segment's size represents its proportional contribution to the total for that category.\n\nAs an example, this is the corn/wheat production chart from above, with the two crops stacked for each country:\n\n```jsx\nimport {BarChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n \n const url = \"https://static.visuallyjs.com/data/chart/corn-vs-wheat-production-by-continent.json\"\n const options = {\n title: {\n text: \"Corn vs wheat estimated production for 2023\"\n },\n subtitle: {\n text: \"Source: https://www.indexmundi.com/agriculture/?commodity=corn\"\n },\n stacked: true,\n series: [\n {\n valueField: \"corn\",\n label: \"Corn\"\n },\n {\n valueField: \"wheat\",\n label: \"Wheat\"\n }\n ]\n} \n \n return <BarChartComponent options={options} className=\"my-chart\" url={url}/>\n}\n\n```\n\n### Percent stacking and the value axis[](#percent-stacking-and-the-value-axis)\n\nWhen `stacked` is set to `\"percent\"`, the chart automatically adjusts the value axis to reflect percentage values:\n\n* The value axis scale is set to range from 0 to 100.\n* Internally, the chart sets the `labelSuffix` of the value axis to `%`. This ensures that labels on the axis (e.g., 0, 25, 50, 75, 100) are displayed with a percentage sign (0%, 25%, etc.).\n* Note that if you have manually provided a `labelSuffix` or a `labelFormatter` in the axis definition, the automatic `%` suffix will not be applied.\n\n## Grouping[](#grouping)\n\nThe `grouped` option, combined with `groupField`, allows you to create more complex layouts where multiple stacks or bars are grouped side-by-side within a single category.\n\n* `grouped: true`: Enables grouping.\n* `groupField: string`: Specifies the field in your data objects that identifies which group/stack a record belongs to. Defaults to `\"group\"`.\n\nThis is particularly useful when you want to compare different sets of stacked data. Here we show the crop data chart again, with the figures grouped by the continent each country belongs to:\n\n```jsx\nimport {BarChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n \n const url = \"https://static.visuallyjs.com/data/chart/corn-vs-wheat-production-by-continent.json\"\n const options = {\n title: {\n text: \"Corn vs wheat estimated production for 2023\"\n },\n subtitle: {\n text: \"Source: https://www.indexmundi.com/agriculture/?commodity=corn\"\n },\n stacked: true,\n grouped: true,\n groupField: \"continent\",\n series: [\n {\n valueField: \"corn\",\n label: \"Corn\"\n },\n {\n valueField: \"wheat\",\n label: \"Wheat\"\n }\n ]\n} \n \n return <BarChartComponent options={options} className=\"my-chart\" url={url}/>\n}\n\n```\n\n## Pivoting[](#pivoting)\n\nThe `pivot` flag is an option for `BarChart`, `ColumnChart`, and other category-value charts in Visually.js. It allows you to quickly change the perspective of your data visualization without needing to restructure your underlying data source.\n\nWhen you enable `pivot: true`, the chart swaps the roles of **series** and **categories**:\n\n* **Categories become Series**: Each data record (which originally represented a single category) is transformed into a new series.\n* **Series become Categories**: The original series definitions (e.g., the different `valueField` entries) are transformed into the new categories on the category axis.\n\nConsider the following dataset of fruit consumption by different people:\n\n```javascript\nconst fruitData = [\n { id: \"Apples\", john: 10, jane: 15, joe: 7 },\n { id: \"Oranges\", john: 5, jane: 8, joe: 12 },\n { id: \"Bananas\", john: 12, jane: 6, joe: 9 }\n];\n\n```\n\n#### Without Pivoting (Default):[](#without-pivoting-default)\n\n```jsx\nimport {BarChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {id:\"Apples\",john:10,jane:15,joe:7},\n {id:\"Oranges\",john:5,jane:8,joe:12},\n {id:\"Bananas\",john:12,jane:6,joe:9}\n]\n \n const options = {\n title: {\n text: \"Fruit consumption\"\n },\n series: [\n {\n valueField: \"john\",\n label: \"John\"\n },\n {\n valueField: \"jane\",\n label: \"Jane\"\n },\n {\n valueField: \"joe\",\n label: \"Joe\"\n }\n ]\n} \n \n return <BarChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\nWhen you don't specify a value for `pivot` the chart is organised in this way:\n\n* **Categories**: Apples, Oranges, Bananas (each record is a category).\n* **Series**: John, Jane, Joe (each `valueField` is a series).\n* **Comparison**: You see how much fruit each person ate for a specific fruit (e.g., three columns for Apples).\n\n#### With Pivoting:[](#with-pivoting)\n\n```jsx\nimport {BarChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {id:\"Apples\",john:10,jane:15,joe:7},\n {id:\"Oranges\",john:5,jane:8,joe:12},\n {id:\"Bananas\",john:12,jane:6,joe:9}\n]\n \n const options = {\n title: {\n text: \"Fruit consumption\"\n },\n pivot: true,\n series: [\n {\n valueField: \"john\",\n label: \"John\"\n },\n {\n valueField: \"jane\",\n label: \"Jane\"\n },\n {\n valueField: \"joe\",\n label: \"Joe\"\n }\n ]\n} \n \n return <BarChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\nWith `pivot:true` set, the series and categories are swapped:\n\n* **Categories**: John, Jane, Joe (the original series names become the categories).\n* **Series**: Apples, Oranges, Bananas (each original record becomes a series).\n* **Comparison**: You see the breakdown of fruit types for each person (e.g., three columns for John).\n\n#### Notes[](#notes)\n\n* The chart automatically generates new series and labels based on the pivoted structure.\n* Pivoting is handled internally during the data loading phase, so it works seamlessly with both static data and data loaded via a URL.\n* Legend labels will also reflect the pivoted structure, showing the original record identifiers as the new series.\n\n## CSS Classes[](#css-classes)\n\n| Class | Description |\n| ------------------- | --------------------------------------------- |\n| `vjs-bar-chart` | Added to the container element in a bar chart |\n| `vjs-bar-chart-bar` | Added to each bar element in a bar chart |","url":"https://visuallyjs.com/react/docs/charts/types/bar-chart","lib":"react","topic":"charts"},"docs/charts/types/bubble-chart.md":{"title":"Bubble Chart","body":"# Bubble Chart\n\nBubble charts are scatter charts where each point has a size representing a third value.\n\n```jsx\nimport {BubbleChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {x:10,y:10,r:5},\n {x:20,y:20,r:10},\n {x:15,y:25,r:7}\n]\n \n const options = {\n title: {\n text: \"Fat/sugar consumption vs obesity\"\n },\n series: [\n {\n xAxisField: \"sugar\",\n yAxisField: \"fat\",\n valueField: \"obesity\",\n color: \"#456\"\n }\n ]\n} \n \n return <BubbleChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\n## Axis origin[](#axis-origin)\n\nBy default, the scatter chart will compute min/max values for each axis based upon the dataset, and the minimum value for each axis is not always 0 - you can see this in the chart above, where the minimum on the Y axis is 0, but the minimum on the X axis is 60.\n\nThis arrangement is aimed at providing the best visual layout for the user. In some cases, though, you might want to specify the minimum value for one or both axes - either in order to ensure that the user has a clear understanding of the magnitude of the values, or because one or more of your data points is placed on an axis and you wish to improve the clarity - for example:\n\n<br />\n\nIn this case you can specify `min` for your axes:\n\n## Specifying Marker[](#specifying-marker)\n\nBy default, bubble charts use circular markers for each data point. You can customize the marker's appearance using various options in the `ChartSeriesOptions`.\n\n### Marker Type[](#marker-type)\n\nYou can change the shape of the marker using the `markerType` option. For example, to use a square marker:\n\n```jsx\nimport {BubbleChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n series: [\n {\n xAxisField: \"sugar\",\n yAxisField: \"fat\",\n valueField: \"obesity\",\n markerType: \"square\"\n }\n ]\n} \n \n return <BubbleChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\nValid options are `\"circle\"` (the default), `\"square\"` and `\"cross\"`.\n\n### Marker Size[](#marker-size)\n\nIn a bubble chart, `markerSize` is ignored, as the size of each marker is determined by the `valueField` of each data point. You can, however, control the range of sizes that the bubbles can take by using the `minPointSize` and `maxPointSize` options.\n\nThe default value for `minPointSize` is 10. There is no default for `maxPointSize`.\n\n```jsx\nimport {BubbleChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n series: [\n {\n xAxisField: \"sugar\",\n yAxisField: \"fat\",\n valueField: \"obesity\",\n minPointSize: 5,\n maxPointSize: 30\n }\n ]\n} \n \n return <BubbleChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### Custom Marker Template[](#custom-marker-template)\n\nFor full control over the marker's appearance, you can provide an SVG template string using the `marker` option:\n\n```jsx\nimport {BubbleChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n series: [\n {\n xAxisField: \"sugar\",\n yAxisField: \"fat\",\n valueField: \"obesity\",\n marker: <svg:svg width='18' height='18' viewBox='0 0 6 6'>\n<svg:circle cx='3' cy='3' r='2.5' fill='yellow' stroke='black' stroke-width='0.2' />\n<svg:circle cx='2' cy='2.2' r='0.3' stroke='black' fill='yellow'/>\n<svg:circle cx='4' cy='2.2' r='0.3' stroke='black' fill='yellow' />\n<svg:path d='M 1.8 3.8 Q 3 5 4.2 3.8' fill='none' stroke='black' stroke-width='0.3' stroke-linecap='round' />\n</svg:svg>\n }\n ]\n} \n \n return <BubbleChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\nThis template must be in [VisuallyJs's template syntax](/vanilla/docs/reference/templating.md).\n\n## Options[](#options)\n\nBubbleChartOptions\n\nOptions for a bubble chart.\n\n| Name | Type | Description |\n| ------------------ | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| axisFont? | [FontSpec]() | Spec for the font to use for all text on the axes. |\n| axisLineSize? | number | The width to use if showing a line marking value/category axes. By default, axis lines are not painted. |\n| colorGenerator? | [ColorGenerator]() | Optional function to call in order to establish the color to be used for each series |\n| cornerRadius? | number | When rounding bar/column corners, use this radius. Defaults to 5 pixels. |\n| data? | Array<[ObjectData]()> | Optional data to load into the chart. |\n| dataSource? | [DataSource]() | Optional data source (of type `DataSource`, meaning both `VisuallyJsModel` and `Selection` are supported) from which to retrieve data to load into the chart. |\n| dataSourceFilter? | [ChartModelFilter]() | When you provide `dataSource`, you can also provide a filter which accepts or rejects specific nodes/groups in the data source. |\n| defaultColor? | string | Optional color to use for every series. Overrides any colorGenerator. |\n| emptyMessage? | string | Message to display when the chart has no data. Defaults to \"No data\". |\n| grouped? | boolean | If true, the data will be grouped, if the chart type supports it (eg Bar/Column). |\n| groupField? | string | The name of the field that identifies which group a data point belongs to. Defaults to `group`. |\n| height? | number | Height for the chart. If omitted, height is computed from the width of the chart's container |\n| legend? | boolean \\| [LegendSpec]() | Either a boolean true/false, indicating the legend should be shown/hidden, or a spec for a legend. |\n| legendPadding? | number | When the legend is not floating, this number defines how much whitespace to leave around it. |\n| maximumMarkerSize? | number | Maximum allowed size for a marker. Defaults to 50 pixels. Set to Infinity to have no maximum (this can have unpleasant UI side effects with some datasets) |\n| maxLabelSize? | number | The maximum size a category label can be as a ratio of the chart's overall size. Category labels are rotated to 45 degrees automatically when they start to overlap each other, but if the labels are long strings then there is a chance they'll use up too much of the available chart space. This value (whose default is 0.2), specifies a hard limit for label size, to avoid that situation. In a chart whose category axis is the X axis, this is applied relative to the height of the chart, and in a chart whose category axis is the Y axis, it's applied relative to the width. |\n| maxPointSize? | number | The maximum size (in pixels) for a bubble. No default. |\n| minimumMarkerSize? | number | Minimum allowed size for a marker. Defaults to 8 pixels. Set to -Infinity to have no minimum (this can have unpleasant UI side effects with some datasets) |\n| minPointSize? | number | The minimum size (in pixels) for a bubble. Defaults to 10. |\n| resizeObserver? | boolean | Defaults to true, meaning the chart will redraw when its container element resizes. |\n| roundCorners? | boolean | Whether or not to round the corners of bars/columns. Defaults to true |\n| series | Array<[BubbleChartSeriesOptions]()> | An array of bubble chart series options. |\n| style? | [ChartStyleOptions]() | Styles for legend and grid. |\n| subtitle? | [SubtitleSpec]() | Subtitle for the chart. |\n| title? | [ChartTitleSpec]() | Title for the chart. |\n| titlePadding? | number | Padding to leave underneath the title |\n| tooltip? | [TooltipOptions]() | Options for the info tooltip. |\n| url? | string | Optional URL from which to retrieve data to load into the chart |\n| width? | number | Width for the chart. If omitted, width is computed from the width of the chart's container |\n| xAxis? | [ValueAxisDefinition]() | Configuration for the X axis. |\n| yAxis? | [ValueAxisDefinition]() | Configuration for the Y axis. |\n| yAxisPadding? | number | How much padding to leave between the y axes decoration and the chart content area. |\n| zoom? | {<br /> enabled:boolean,<br /> initialValue:number,<br /> range:\\[number, number]<br />} | Optional zoom configuration. |\n\n## CSS Classes[](#css-classes)\n\n| Class | Description |\n| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |\n| `vjs-bubble-chart-point` | Added to each point in a bubble chart |\n| `vjs-chart-point` | Added to each point in a scatter/bubble chart |\n| `vjs-chart-point-hit-area` | Added to the hit area elements that represent each data point. These are to assist users in selecting data points which are small. |","url":"https://visuallyjs.com/react/docs/charts/types/bubble-chart","lib":"react","topic":"charts"},"docs/charts/types/column-chart.md":{"title":"Column Chart","body":"# Column Chart\n\nIn a column chart, values are presented on the Y axis, and categories are presented on the X axis.\n\n## Single series[](#single-series)\n\nThe simplest column chart consists of a single data series:\n\n```jsx\nimport {ColumnChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Fuel Types\"\n },\n categoryAxis: {\n showLine: true,\n title: {\n text: \"Fuel Type\"\n }\n },\n valueAxis: {\n showLine: true,\n title: {\n text: \"Number of vehicles\"\n }\n },\n series: [\n {\n valueField: \"value\",\n label: \"Type\"\n }\n ],\n tooltip: {\n format: \"{{category}}:{{point.value}}\"\n }\n} \n \n return <ColumnChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n## Multiple series[](#multiple-series)\n\nMultiple data series' are supported:\n\n```jsx\nimport {ColumnChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Corn vs wheat estimated production for 2023\"\n },\n subtitle: {\n text: \"Source: https://www.indexmundi.com/agriculture/?commodity=corn\"\n },\n categoryAxis: {\n accessibility: {\n description: \"Countries\"\n },\n title: {\n text: \"Country\"\n }\n },\n valueAxis: {\n title: {\n text: \"1000 metric tons (MT)\"\n }\n },\n tooltip: {\n format: \"<b>{{category}}</b><br/>{{series.label}}:{{point.value}}\",\n valueSuffix: \" (1000 MT)\"\n },\n series: [\n {\n valueField: \"corn\",\n label: \"Corn\"\n },\n {\n valueField: \"wheat\",\n label: \"Wheat\"\n }\n ]\n} \n \n return <ColumnChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n## Ranged data[](#ranged-data)\n\nYou can display data that contains a minimum and maximum value:\n\n```jsx\nimport {ColumnChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Temperature range\",\n align: \"right\"\n },\n valueAxis: {\n title: {\n text: \"Degrees Celsius\"\n }\n },\n series: [\n {\n id: \"max\",\n maxValueField: \"max\",\n minValueField: \"min\",\n label: \"Temperature\"\n }\n ],\n legend: false,\n tooltip: {\n format: \"<b>{{category}}</b><br/>{{point.minValue}} - {{point.maxValue}}\",\n valueSuffix: \" C\"\n }\n} \n \n return <ColumnChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\nNote how the chart options contain a `minValueField` and `maxValueField` specifier in the data series definition. The dataset used here looks like this:\n\n```javascript\nconst data = [\n {id:\"Jan\", \"min\":-9.5, \"max\":8.0},\n {id:\"Feb\", \"min\":-7.8, \"max\":8.3}\n]\n\n```\n\n## Assigning Colors[](#assigning-colors)\n\nColors can be managed in several ways depending on whether you want a uniform look, series-specific styling, or dynamic color generation.\n\n### Chart Level[](#chart-level)\n\nSetting a `defaultColor` at the chart level applies a base color to all series unless overridden. This is useful for maintaining brand consistency across simple charts.\n\n```javascript\noptions: {\n defaultColor: '#3498db',\n // ...\n}\n\n```\n\n### Series Level[](#series-level)\n\nFor charts with multiple data series, you can assign specific colors to individual series to help distinguish between datasets.\n\n```javascript\nseries: [\n {\n valueField: \"corn\",\n label: \"Corn\",\n color: \"#f1c40f\"\n },\n {\n valueField: \"wheat\",\n label: \"Wheat\",\n color: \"#e67e22\"\n }\n]\n\n```\n\n### Color Generator[](#color-generator)\n\nIf you have a dynamic number of series or prefer an automated approach, you can provide a color generator (or an array of colors). The chart will then cycle through these colors for each new series or data point.\n\n```javascript\noptions: {\n colors: ['#1abc9c', '#2ecc71', '#3498db', '#9b59b6'],\n // ...\n}\n\n```\n\n### Background color[](#background-color)\n\nYou can set the background color of the chart using the `backgroundColor` property. It defaults to `#FFFFFF`. Alternatively, you can use the `.vjs-chart-background` CSS class to style the background.\n\n```jsx\nimport {ColumnChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {x:1,id:\"Value 1\"},\n {x:2,id:\"Value 2\"},\n {x:3,id:\"Value 3\"}\n]\n \n const options = {\n backgroundColor: \"#f0f0f0\",\n title: \"Background Color Example\",\n series: [\n {\n valueField: \"x\"\n }\n ]\n} \n \n return <ColumnChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\n## Stacking[](#stacking)\n\nThe `stacked` option determines how different series within the same category are displayed relative to each other. It can take one of the following values:\n\n* `false` (default): Series are displayed side-by-side within each category.\n* `true` or `\"default\"`:\n <!-- -->\n Series are stacked on top of each other\n <!-- -->\n . The total\n <!-- -->\n height\n <!-- -->\n of the stack represents the sum of the values in that category.\n* `\"percent\"`: Series are stacked such that they always fill 100% of the available space on the value axis. Each segment's size represents its proportional contribution to the total for that category.\n\nAs an example, this is the corn/wheat production chart from above, with the two crops stacked for each country:\n\n```jsx\nimport {ColumnChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n \n const url = \"https://static.visuallyjs.com/data/chart/corn-vs-wheat-production-by-continent.json\"\n const options = {\n title: {\n text: \"Corn vs wheat estimated production for 2023\"\n },\n subtitle: {\n text: \"Source: https://www.indexmundi.com/agriculture/?commodity=corn\"\n },\n stacked: true,\n series: [\n {\n valueField: \"corn\",\n label: \"Corn\"\n },\n {\n valueField: \"wheat\",\n label: \"Wheat\"\n }\n ]\n} \n \n return <ColumnChartComponent options={options} className=\"my-chart\" url={url}/>\n}\n\n```\n\n### Percent stacking and the value axis[](#percent-stacking-and-the-value-axis)\n\nWhen `stacked` is set to `\"percent\"`, the chart automatically adjusts the value axis to reflect percentage values:\n\n* The value axis scale is set to range from 0 to 100.\n* Internally, the chart sets the `labelSuffix` of the value axis to `%`. This ensures that labels on the axis (e.g., 0, 25, 50, 75, 100) are displayed with a percentage sign (0%, 25%, etc.).\n* Note that if you have manually provided a `labelSuffix` or a `labelFormatter` in the axis definition, the automatic `%` suffix will not be applied.\n\n## Grouping[](#grouping)\n\nThe `grouped` option, combined with `groupField`, allows you to create more complex layouts where multiple stacks or bars are grouped side-by-side within a single category.\n\n* `grouped: true`: Enables grouping.\n* `groupField: string`: Specifies the field in your data objects that identifies which group/stack a record belongs to. Defaults to `\"group\"`.\n\nThis is particularly useful when you want to compare different sets of stacked data. Here we show the crop data chart again, with the figures grouped by the continent each country belongs to:\n\n```jsx\nimport {ColumnChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n \n const url = \"https://static.visuallyjs.com/data/chart/corn-vs-wheat-production-by-continent.json\"\n const options = {\n title: {\n text: \"Corn vs wheat estimated production for 2023\"\n },\n subtitle: {\n text: \"Source: https://www.indexmundi.com/agriculture/?commodity=corn\"\n },\n stacked: true,\n grouped: true,\n groupField: \"continent\",\n series: [\n {\n valueField: \"corn\",\n label: \"Corn\"\n },\n {\n valueField: \"wheat\",\n label: \"Wheat\"\n }\n ]\n} \n \n return <ColumnChartComponent options={options} className=\"my-chart\" url={url}/>\n}\n\n```\n\n## Pivoting[](#pivoting)\n\nThe `pivot` flag is an option for `BarChart`, `ColumnChart`, and other category-value charts in Visually.js. It allows you to quickly change the perspective of your data visualization without needing to restructure your underlying data source.\n\nWhen you enable `pivot: true`, the chart swaps the roles of **series** and **categories**:\n\n* **Categories become Series**: Each data record (which originally represented a single category) is transformed into a new series.\n* **Series become Categories**: The original series definitions (e.g., the different `valueField` entries) are transformed into the new categories on the category axis.\n\nConsider the following dataset of fruit consumption by different people:\n\n```javascript\nconst fruitData = [\n { id: \"Apples\", john: 10, jane: 15, joe: 7 },\n { id: \"Oranges\", john: 5, jane: 8, joe: 12 },\n { id: \"Bananas\", john: 12, jane: 6, joe: 9 }\n];\n\n```\n\n#### Without Pivoting (Default):[](#without-pivoting-default)\n\n```jsx\nimport {ColumnChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {id:\"Apples\",john:10,jane:15,joe:7},\n {id:\"Oranges\",john:5,jane:8,joe:12},\n {id:\"Bananas\",john:12,jane:6,joe:9}\n]\n \n const options = {\n title: {\n text: \"Fruit consumption\"\n },\n series: [\n {\n valueField: \"john\",\n label: \"John\"\n },\n {\n valueField: \"jane\",\n label: \"Jane\"\n },\n {\n valueField: \"joe\",\n label: \"Joe\"\n }\n ]\n} \n \n return <ColumnChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\nWhen you don't specify a value for `pivot` the chart is organised in this way:\n\n* **Categories**: Apples, Oranges, Bananas (each record is a category).\n* **Series**: John, Jane, Joe (each `valueField` is a series).\n* **Comparison**: You see how much fruit each person ate for a specific fruit (e.g., three columns for Apples).\n\n#### With Pivoting:[](#with-pivoting)\n\n```jsx\nimport {ColumnChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {id:\"Apples\",john:10,jane:15,joe:7},\n {id:\"Oranges\",john:5,jane:8,joe:12},\n {id:\"Bananas\",john:12,jane:6,joe:9}\n]\n \n const options = {\n title: {\n text: \"Fruit consumption\"\n },\n pivot: true,\n series: [\n {\n valueField: \"john\",\n label: \"John\"\n },\n {\n valueField: \"jane\",\n label: \"Jane\"\n },\n {\n valueField: \"joe\",\n label: \"Joe\"\n }\n ]\n} \n \n return <ColumnChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\nWith `pivot:true` set, the series and categories are swapped:\n\n* **Categories**: John, Jane, Joe (the original series names become the categories).\n* **Series**: Apples, Oranges, Bananas (each original record becomes a series).\n* **Comparison**: You see the breakdown of fruit types for each person (e.g., three columns for John).\n\n#### Notes[](#notes)\n\n* The chart automatically generates new series and labels based on the pivoted structure.\n* Pivoting is handled internally during the data loading phase, so it works seamlessly with both static data and data loaded via a URL.\n* Legend labels will also reflect the pivoted structure, showing the original record identifiers as the new series.\n\n## CSS Classes[](#css-classes)\n\n| Class | Description |\n| ------------------------- | ------------------------------------------------ |\n| `vjs-column-chart` | Added to the container element of a column chart |\n| `vjs-column-chart-column` | Added to each column element in a column chart |","url":"https://visuallyjs.com/react/docs/charts/types/column-chart","lib":"react","topic":"charts"},"docs/charts/types/gauge-chart.md":{"title":"Gauge Chart","body":"# Gauge Chart\n\nThe Gauge chart displays a single value within a defined range, often represented as a needle on a circular arc.\n\n### Default Gauge[](#default-gauge)\n\nA gauge with no zones that shows the needle by default.\n\n```jsx\nimport {GaugeChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Default Gauge\"\n },\n value: 65\n} \n \n return <GaugeChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### Zones and Needle[](#zones-and-needle)\n\nA gauge configured with multiple color zones and a needle.\n\n```jsx\nimport {GaugeChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Gauge with Zones and Needle\"\n },\n value: 75,\n zones: [\n {\n from: 0,\n to: 33,\n color: \"#ff4d4d\"\n },\n {\n from: 33,\n to: 66,\n color: \"#ffdb4d\"\n },\n {\n from: 66,\n to: 100,\n color: \"#4dff4d\"\n }\n ]\n} \n \n return <GaugeChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### Zones without Needle[](#zones-without-needle)\n\nA gauge that has zones but doesn't show the needle. In this case, the zones are only painted up to the current value.\n\n```jsx\nimport {GaugeChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Gauge with Zones, No Needle\"\n },\n value: 45,\n showNeedle: false,\n zones: [\n {\n from: 0,\n to: 100,\n color: \"#4d94ff\"\n }\n ]\n} \n \n return <GaugeChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### Gradient Zones[](#gradient-zones)\n\nA gauge with two zones that each have a gradient.\n\n```jsx\nimport {GaugeChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Gauge with Gradient Zones\"\n },\n value: 80,\n zones: [\n {\n from: 0,\n to: 50,\n gradient: {\n stops: [\n {\n offset: 0,\n color: \"#ff4d4d\"\n },\n {\n offset: 100,\n color: \"#ffdb4d\"\n }\n ]\n }\n },\n {\n from: 50,\n to: 100,\n gradient: {\n stops: [\n {\n offset: 0,\n color: \"#ffdb4d\"\n },\n {\n offset: 100,\n color: \"#4dff4d\"\n }\n ]\n }\n }\n ]\n} \n \n return <GaugeChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### Ticks[](#ticks)\n\nThe `ticks` object allows you to configure the appearance and interval of the tick marks on the gauge.\n\n```jsx\nimport {GaugeChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Gauge with Custom Ticks\"\n },\n value: 65,\n ticks: {\n interval: 10,\n show: true,\n width: 2,\n length: 10,\n color: \"#666\"\n }\n} \n \n return <GaugeChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### Labels[](#labels)\n\nThe `labels` object is used to configure the numeric labels displayed around the gauge arc.\n\n```jsx\nimport {GaugeChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Custom Labels\"\n },\n value: 45,\n labels: {\n show: true,\n fontSize: 14,\n fontWeight: \"bold\",\n fontColor: \"#4d94ff\"\n }\n} \n \n return <GaugeChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n## CSS Classes[](#css-classes)\n\n| Class | Description |\n| ------------------------ | ----------------------------------------------------- |\n| `vjs-gauge-chart` | Assigned to the container for a gauge chart |\n| `vjs-gauge-label` | Assigned to each label element in a GaugeChart. |\n| `vjs-gauge-needle` | Assigned to the needle element in a GaugeChart. |\n| `vjs-gauge-needle-pivot` | Assigned to the needle pivot element in a GaugeChart. |\n| `vjs-gauge-tick` | Assigned to each tick element in a GaugeChart. |\n| `vjs-gauge-track` | Assigned to the track element in a GaugeChart. |\n| `vjs-gauge-zone` | Assigned to each zone element in a GaugeChart. |","url":"https://visuallyjs.com/react/docs/charts/types/gauge-chart","lib":"react","topic":"charts"},"docs/charts/types/line-chart.md":{"title":"Line Chart","body":"# Line Chart\n\nLine charts connect a series of data points with a line, and are often used to represent changes over time, although that is not their only use - sometimes a line chart can be used in place of a bar or column chart because the fact they use less ink makes for a more appealing visual.\n\n## Single series[](#single-series)\n\nThe simplest line chart consists of a single series:\n\n```jsx\nimport {LineChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Maximum Temperature\",\n align: \"left\"\n },\n valueAxis: {\n title: {\n text: \"Degrees celsius\"\n }\n },\n legend: false,\n series: [\n {\n id: \"max\",\n valueField: \"max\",\n label: \"Temperature\"\n }\n ]\n} \n \n return <LineChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### Inverting axes[](#inverting-axes)\n\nBy default, the line chart will use the X axis as the category axis, and the Y axis as the value axis. This behaviour can be changed by specifying you want the chart to be `inverted`.\n\n```jsx\nimport {LineChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n inverted: true,\n ...\n} \n \n return <LineChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n## Displaying a range[](#displaying-a-range)\n\nYou can display a range with a line chart - a separate line will be drawn for the minimum and maximum values:\n\nThe only difference in the setup for a range vs a single series is that we specify `minValueField` and `maxValueField` instead of just `valueField`:\n\n```jsx\nimport {LineChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Temperature Range\"\n },\n valueAxis: {\n title: {\n text: \"Degrees celsius\"\n }\n },\n legend: false,\n series: [\n {\n maxValueField: \"max\",\n minValueField: \"min\",\n label: \"Temperature\"\n }\n ]\n} \n \n return <LineChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### Inverting axes[](#inverting-axes-1)\n\nAs with a single series line chart, set `inverted` if you wish to invert the axes:\n\n```jsx\nimport {LineChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n inverted: true,\n ...\n} \n \n return <LineChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n## Specifying Marker[](#specifying-marker)\n\nBy default, line charts use circular markers for each data point. You can customize the marker's appearance using various options in the `ChartSeriesOptions`.\n\n### Marker Type[](#marker-type)\n\nYou can change the shape of the marker using the `markerType` option. For example, to use a square marker:\n\n```jsx\nimport {LineChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n series: [\n {\n valueField: \"max\",\n markerType: \"square\"\n }\n ]\n} \n \n return <LineChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\nValid options are `\"circle\"` (the default), `\"square\"` and `\"cross\"`.\n\n### Marker Size[](#marker-size)\n\nThe size of the marker can be adjusted using the `markerSize` option, whose default value is 10. This is useful for making markers more prominent:\n\n```jsx\nimport {LineChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n series: [\n {\n valueField: \"max\",\n markerSize: 20\n }\n ]\n} \n \n return <LineChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### Custom Marker Template[](#custom-marker-template)\n\nFor full control over the marker's appearance, you can provide an SVG template string using the `marker` option:\n\n```jsx\nimport {LineChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n series: [\n {\n valueField: \"max\",\n marker: <svg:rect viewBox='0 0 30 30' width='30' height='10'/>\n }\n ]\n} \n \n return <LineChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\nThis template must be in VisuallyJs's template syntax.\n\n## Assigning Colors[](#assigning-colors)\n\nColors can be managed in several ways depending on whether you want a uniform look, series-specific styling, or dynamic color generation.\n\n### Chart Level[](#chart-level)\n\nSetting a `defaultColor` at the chart level applies a base color to all series unless overridden. This is useful for maintaining brand consistency across simple charts.\n\n```javascript\noptions: {\n defaultColor: '#3498db',\n // ...\n}\n\n```\n\n### Series Level[](#series-level)\n\nFor charts with multiple data series, you can assign specific colors to individual series to help distinguish between datasets.\n\n```javascript\nseries: [\n {\n valueField: \"corn\",\n label: \"Corn\",\n color: \"#f1c40f\"\n },\n {\n valueField: \"wheat\",\n label: \"Wheat\",\n color: \"#e67e22\"\n }\n]\n\n```\n\n### Color Generator[](#color-generator)\n\nIf you have a dynamic number of series or prefer an automated approach, you can provide a color generator (or an array of colors). The chart will then cycle through these colors for each new series or data point.\n\n```javascript\noptions: {\n colors: ['#1abc9c', '#2ecc71', '#3498db', '#9b59b6'],\n // ...\n}\n\n```\n\n### Background color[](#background-color)\n\nYou can set the background color of the chart using the `backgroundColor` property. It defaults to `#FFFFFF`. Alternatively, you can use the `.vjs-chart-background` CSS class to style the background.\n\n```jsx\nimport {LineChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {x:1,id:\"Value 1\"},\n {x:2,id:\"Value 2\"},\n {x:3,id:\"Value 3\"}\n]\n \n const options = {\n backgroundColor: \"#f0f0f0\",\n title: \"Background Color Example\",\n series: [\n {\n valueField: \"x\"\n }\n ]\n} \n \n return <LineChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\n## CSS Classes[](#css-classes)\n\n| Class | Description |\n| ---------------- | --------------------------------------------- |\n| `vjs-line-chart` | Set on the container element for a line chart |","url":"https://visuallyjs.com/react/docs/charts/types/line-chart","lib":"react","topic":"charts"},"docs/charts/types/pie-chart.md":{"title":"Pie Chart","body":"# Pie Chart\n\nPie charts show proportions of a whole by dividing a circle into slices.\n\n```jsx\nimport {PieChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Fuel Consumption\"\n },\n series: [\n {\n valueField: \"value\",\n label: \"Fuel Type\"\n }\n ]\n} \n \n return <PieChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\nThe data loaded into this example is:\n\n```javascript\nconst data = [\n { id: 'Petrol', value: 938899 },\n { id: 'Diesel', value: 1229600 },\n { id: 'Electricity', value: 325251 },\n { id: 'Other', value: 238751 }\n]\n\n```\n\nEach entry in the array is represented as a slice of the pie, with its value being extracted from whatever field you map as the `valueField` - in this case, `\"value\"`.\n\n### Selected Slice[](#selected-slice)\n\nYou can set the selected slice of the pie using the `selectedCategory` option. Setting `interactive: true` allows users to select different slices.\n\n```jsx\nimport {PieChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n title: {\n text: \"Fuel Consumption\"\n },\n subtitle: {\n text: \"Comparison of sources\"\n },\n selectedCategory: 0,\n interactive: true,\n series: [\n {\n valueField: \"value\",\n label: \"Fuel Type\"\n }\n ]\n} \n \n return <PieChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n## Doughnut Charts[](#doughnut-charts)\n\nYou can create a doughnut chart by specifying an `innerRadius`. The format of the value is that it is a fraction of the total radius (between 0 and 1). The chart will not throw an error if you provide a value outside that range.\n\n```jsx\nimport {PieChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n innerRadius: 0.55,\n series: [\n {\n valueField: \"value\",\n label: \"Fuel Type\"\n }\n ]\n} \n \n return <PieChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n## Labels[](#labels)\n\nThe `showLabels` config option determines what information is displayed on the chart labels. It has five possible values:\n\n### label[](#label)\n\nDisplays the label of the slice.\n\n```jsx\nimport {PieChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n showLabels: \"label\",\n series: [\n {\n valueField: \"value\",\n label: \"Fuel Type\"\n }\n ]\n} \n \n return <PieChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### value[](#value)\n\nDisplays the numeric value of the slice.\n\n```jsx\nimport {PieChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n showLabels: \"value\",\n series: [\n {\n valueField: \"value\",\n label: \"Fuel Type\"\n }\n ]\n} \n \n return <PieChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### percentage[](#percentage)\n\nDisplays the percentage of the whole that the slice represents.\n\n```jsx\nimport {PieChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n showLabels: \"percentage\",\n series: [\n {\n valueField: \"value\",\n label: \"Fuel Type\"\n }\n ]\n} \n \n return <PieChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### label-value[](#label-value)\n\nDisplays both the label and the value of the slice.\n\n```jsx\nimport {PieChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n showLabels: \"label-value\",\n series: [\n {\n valueField: \"value\",\n label: \"Fuel Type\"\n }\n ]\n} \n \n return <PieChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### label-percentage[](#label-percentage)\n\nDisplays both the label and the percentage of the slice.\n\n```jsx\nimport {PieChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n showLabels: \"label-percentage\",\n series: [\n {\n valueField: \"value\",\n label: \"Fuel Type\"\n }\n ]\n} \n \n return <PieChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n## Label Position[](#label-position)\n\nThe `labelPosition` config option determines where the labels are placed relative to the slices.\n\n### Outside[](#outside)\n\nThis is the default, which places the labels outside of the slices of pie.\n\n```jsx\nimport {PieChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n showLabels: \"label\",\n labelPosition: \"outside\",\n series: [\n {\n valueField: \"value\",\n label: \"Fuel Type\"\n }\n ]\n} \n \n return <PieChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### Inside[](#inside)\n\nWhen you set `labelPosition:\"inside\"`, labels are placed at 0.7 of the radius of the pie:\n\n```jsx\nimport {PieChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n showLabels: \"label\",\n labelPosition: \"inside\",\n series: [\n {\n valueField: \"value\",\n label: \"Fuel Type\"\n }\n ]\n} \n \n return <PieChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n## Label font[](#label-font)\n\nYou can specify details for the font to use in a pie chart's labels via the `labelFont` option:\n\n```jsx\nimport {PieChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n labelFont: {\n size: 14,\n weight: \"bold\"\n },\n series: [\n {\n valueField: \"value\",\n label: \"Fuel Type\"\n }\n ]\n} \n \n return <PieChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\nThis is of type [FontSpec]().\n\n## Summing data[](#summing-data)\n\nA common use case for pie charts is to sum the data prior to plotting. For example, consider this dataset:\n\n```javascript\nconst summingData = [\n { name: 'record1', red: 4, green: 2, blue: 3 },\n { name: 'record2', red: 5, green: 2, blue: 3 },\n { name: 'record3', red: 1, green: 2, blue: 3 }\n]\n\n```\n\nIt consists of 3 records, each of which has a name and a `red`, `green` and `blue` value. To create a pie chart which shows the sum of each of these, we use a [summing series](/react/docs/charts/concepts/series.md#summing-series):\n\n```jsx\nimport {PieChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n series: [\n {\n type: \"summing\",\n fields: [\n \"red\",\n \"green\",\n \"blue\"\n ]\n }\n ]\n} \n \n return <PieChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n## Assigning Colors[](#assigning-colors)\n\nTo assign colors in a Pie chart, you have four options:\n\n* Do nothing. You will get a randomly generated color for each slice of pie.\n* The `defaultColor` option from `BaseChartOptions` allows you to specify a color that will be used for every slice of the pie.\n* The `colors` option in `PieChartOptions` allows you to specify a list of colors to be used for the slices of the pie.\n* The `colorGenerator` option gives you finer-grained control over what color will be assigned to each slice.\n\n### Default color[](#default-color)\n\n```jsx\nimport {PieChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {name:\"record1\",red:4,green:2,blue:3},\n {name:\"record2\",red:5,green:2,blue:3},\n {name:\"record3\",red:1,green:2,blue:3}\n]\n \n const options = {\n defaultColor: \"forestgreen\",\n series: [\n {\n type: \"summing\",\n fields: [\n \"red\",\n \"green\",\n \"blue\"\n ]\n }\n ]\n} \n \n return <PieChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\n### List of colors[](#list-of-colors)\n\n```jsx\nimport {PieChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {name:\"record1\",red:4,green:2,blue:3},\n {name:\"record2\",red:5,green:2,blue:3},\n {name:\"record3\",red:1,green:2,blue:3}\n]\n \n const options = {\n colors: [\n \"#FF0000\",\n \"#00FF00\",\n \"#0000FF\"\n ],\n series: [\n {\n type: \"summing\",\n fields: [\n \"red\",\n \"green\",\n \"blue\"\n ]\n }\n ]\n} \n \n return <PieChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\nIn a `summing` series, the order of the `fields` array directly matches the order of the `colors` array. This makes it straightforward to assign specific colors to specific data fields:\n\nHowever, for a `collation` series, the order in which values are encountered in the dataset determines the order of the slices. Because this order can be unpredictable, matching a `colors` array to specific values in a `collation` series can be hit and miss, and you're better off using the `colorGenerator` option.\n\n### Color Generators[](#color-generators)\n\nThis is a function that returns a color for a given index or data point, providing more flexibility in how colors are assigned. You can provide this either as your own ad-hoc function, or use one of the color generators [that VisuallyJS ships with](/react/docs/charts/concepts/colors.md#color-generators).\n\n```typescript\nconst chartOptions = {\n // ... other options\n colorGenerator: {\n // return a color based on the data\n generate:(point:PieChartDataPoint) => point.data.color\n }\n}\n\n```\n\nPieChartDataPoint\n\nDefines the data point type used in a PieChart. The object that is passed to a color generator is of this type.\n\n{\n\n<br />\n\n arc:number,\n\n<br />\n\n arcStart:number,\n\n<br />\n\n data:[ObjectData](),\n\n<br />\n\n label:string,\n\n<br />\n\n p:number,\n\n<br />\n\n value:number\n\n<br />\n\n}\n\n## CSS Classes[](#css-classes)\n\n| Class | Description |\n| ------------------------ | ------------------------------------------------- |\n| `vjs-pie-chart` | CSS class set on a pie chart. |\n| `vjs-pie-slice` | CSS class set on a slice in a pie chart. |\n| `vjs-pie-slice-selected` | CSS class set on a selected slice in a pie chart. |","url":"https://visuallyjs.com/react/docs/charts/types/pie-chart","lib":"react","topic":"charts"},"docs/charts/types/sankey.md":{"title":"Sankey","body":"# Sankey Chart\n\nA Sankey chart is a type of flow diagram in which the width of the arrows is proportional to the flow rate. It is ideal for visualizing energy balances, material flows, or any system with defined quantities moving between nodes.\n\n## Example[](#example)\n\nThe following example demonstrates a Sankey chart visualizing energy flows. It uses data loaded from a CSV file.\n\n## Usage[](#usage)\n\nTo use the Sankey chart, you need to provide a container element and configuration options, including the source of the data. Data can be sourced from:\n\n* a CSV file, via URL or as a string;\n* JSON in the [VisuallyJsDefaultJSON]() format via URL;\n* A JS object in the [VisuallyJsDefaultJSON]() format;\n* a [DataSource]() - some existing instance of the VisuallyJs model.\n\n```jsx\nimport {SankeyComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n url: \"/data/sankey-energy-data.csv\",\n linkColorStrategy: \"source-target\",\n height: 600\n} \n \n return <SankeyComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### CSV Format[](#csv-format)\n\nThe Sankey chart expects data in a CSV format to have `source`, `target`, and `value` columns. For example:\n\n```csv\nsource,target,value\nAgricultural 'waste',Bio-conversion,124.729\nBio-conversion,Liquid,0.597\nBio-conversion,Losses,26.862\nBio-conversion,Solid,280.322\nBio-conversion,Gas,81.144\n...\n\n```\n\nThe header line should be present.\n\n## Loading data[](#loading-data)\n\n### Loading from a URL[](#loading-from-a-url)\n\nThe Sankey chart will use the extension of a URL to determine what type it expects the data to be in - `.json` or `.csv`.\n\n### Loading CSV data directly[](#loading-csv-data-directly)\n\nUse the `csvData` option if have CSV as a string that you wish to load:\n\n```javascript\nconst myCsvData =...\n\n```\n\n```jsx\nimport {SankeyComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n csvData: myCsvData,\n linkColorStrategy: \"source-target\",\n height: 600\n} \n \n return <SankeyComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### Loading JS data directly[](#loading-js-data-directly)\n\n```javascript\nconst myJson:VisuallyJsDefaultJSON =...\n\n```\n\n```jsx\nimport {SankeyComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n jsonData: myJson,\n linkColorStrategy: \"source-target\",\n height: 600\n} \n \n return <SankeyComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### Using a DataSource[](#using-a-datasource)\n\nSankey diagrams can also be given a `dataSource` as input, which is of type `VisuallyJsModel`. This is particularly useful for dashboards where you want to show a flow-based overview of an underlying interactive diagram model.\n\nIn React, you can inject a datasource into a Sankey by wrapping everything in a `SurfaceProvider`:\n\n```jsx\nimport { SurfaceProvider, SurfaceComponent, SankeyChartComponent, InspectorComponent } from \"@visuallyjs/browser-ui-react\";\n\nexport default function MyDashboard() {\n return (\n <SurfaceProvider>\n <div style={{ display: 'flex' }}>\n <SurfaceComponent url=\"/data/my-diagram.json\" />\n <SankeyChartComponent options={{\n linkColorStrategy: \"source\"\n }} />\n <InspectorComponent />\n </div>\n </SurfaceProvider>\n );\n}\n\n```\n\n## Pivoting[](#pivoting)\n\nYou can `pivot` a Sankey chart, providing the name of a property that is present on each edge in your data. Pivoting a Sankey diagram means that instead of just showing the direct flows between nodes, the diagram groups the edges by the value of the specified property.\n\nA classic example of this is in the Supply Chain demonstration. In that demo, the Sankey chart can be pivoted on `transitMode` (e.g., Air, Sea, Road) or `carrier` (e.g., FedEx, DHL). When pivoted on `transitMode`, the diagram shows the flow of goods broken down by how they were transported, even if they share the same source and target.\n\nHere we see the default Sankey for the supply chain, in which there's a node for each entity, and edges connecting them showing the flow between them:\n\nEdges in this dataset have this data:\n\n```javascript\n{\n \"value\": 300,\n \"label\": \"Global Distribution\",\n \"transitMode\": \"Air\",\n \"carrier\": \"FedEx\"\n}\n\n```\n\nWe can instruct the Sankey to pivot on an edge value to get a different view of the data. For instance, let's pivot on `transitMode`:\n\n```jsx\nimport {SankeyComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n jsonData: myJson,\n linkColorStrategy: \"source-target\",\n pivot: \"transitMode\"\n} \n \n return <SankeyComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### Dynamic pivot[](#dynamic-pivot)\n\nYou can provide the pivot value as a prop on the React component rather than in the chart options, and then your users can dynamically control how it pivots.\n\n```jsx\nimport { useState } from \"react\"\n\nimport { SurfaceProvider, SurfaceComponent, SankeyChartComponent, InspectorComponent } from \"@visuallyjs/browser-ui-react\";\n\nconst [pivot, setPivot ] = useState(\"transitMode\")\nconst options = {\n linkColorStrategy: \"source\"\n}\n\nexport default function MyDashboard() {\n return (\n <div style={{ display: 'flex' }}>\n <SurfaceComponent url=\"/data/my-diagram.json\" />\n <SankeyChartComponent options={} pivot={pivot}/>\n </div>\n <select value={pivot} onChange={(e) => setPivot(e.target.value)}>\n <option value=\"\">No pivot</option>\n <option value=\"transitMode\">Transit Mode</option>\n <option value=\"carrier\">Carrier</option>\n </select>\n \n );\n}\n\n```\n\nPivot: Transit Mode (transitMode)\n\n## Link color[](#link-color)\n\nThe `linkColorStrategy` option determines how the links (edges) between nodes are colored. The following strategies are available:\n\n* `static`: Uses a single color for all links. The color can be specified using the `linkColor` option, which defaults to `#444444`.\n* `source`: Links are colored using the color of their source node.\n* `target`: Links are colored using the color of their target node.\n* `source-target`: Links are colored using a gradient that transitions from the source node's color to the target node's color.\n\n## CSS Classes[](#css-classes)\n\n| Class | Description |\n| ----------------------- | ----------------------------------------------------------------------------------------------------------------- |\n| `vjs-sankey` | Assigned to the sankey chart container |\n| `vjs-sankey-edge` | Assigned to edges in Sankey chart |\n| `vjs-sankey-label` | Assigned to labels in a sankey chart |\n| `vjs-sankey-node` | Assigned to nodes in a sankey chart |\n| `vjs-sankey-selected` | Assigned to edges/nodes in Sankey chart when the edge/node forms part of the selected path. |\n| `vjs-sankey-unselected` | Assigned to edges/nodes in Sankey chart when something is selected but this edge/node is not in the selected path |","url":"https://visuallyjs.com/react/docs/charts/types/sankey","lib":"react","topic":"charts"},"docs/charts/types/scatter-chart.md":{"title":"Scatter Chart","body":"# Scatter Chart\n\nScatter charts plot points based on two numerical values. For instance, in this chart, we are plotting fat and sugar consumption across a range of different countries:\n\n```jsx\nimport {ScatterChartComponent} from \"@visuallyjs/browser-ui-react\";\n\nexport default function ScatterChartExample() {\n\n const options = {\n title:{\n text:\"Scatter Chart Example\",\n },\n series:[\n {\n xAxisField:\"x\",\n yAxisField:\"y\",\n label:\"Series 1\"\n }\n ],\n data:[\n {x:10, y:20},\n {x:10, y:10},\n {x:20, y:20},\n {x:15, y:25}\n ]\n }\n\n return <ScatterChartComponent options={options} \n className=\"vjs-inline-example\"/>\n\n}\n\n```\n\n## Axis origin[](#axis-origin)\n\nBy default, the scatter chart will compute min/max values for each axis based upon the dataset, and the minimum value for each axis is not always 0 - you can see this in the chart above, where the minimum on the Y axis is 0, but the minimum on the X axis is 60.\n\nThis arrangement is aimed at providing the best visual layout for the user. In some cases, though, you might want to specify the minimum value for one or both axes - either in order to ensure that the user has a clear understanding of the magnitude of the values, or because one or more of your data points is placed on an axis and you wish to improve the clarity - for example:\n\n<br />\n\nIn this case you can specify `min` for your axes:\n\n```jsx\nimport {ScatterChartComponent} from \"@visuallyjs/browser-ui-react\";\n\nexport default function ScatterChartExample() {\n\n const options = {\n title:{\n text:\"Scatter Chart Example\",\n },\n series:[\n {\n xAxisField:\"x\",\n yAxisField:\"y\",\n label:\"Series 1\"\n }\n ],\n xAxis:{\n min:0\n },\n yAxis:{\n min:0\n },\n data:[ {x:10, y:20}, {x:10, y:10}, {x:20, y:20}, {x:15, y:25} ]\n }\n\n return <ScatterChartComponent options={options} \n className=\"vjs-inline-example\"/>\n\n}\n\n```\n\n## Specifying Marker[](#specifying-marker)\n\nBy default, scatter charts use circular markers for each data point. You can customize the marker's appearance using various options in the `ChartSeriesOptions`.\n\n### Marker Type[](#marker-type)\n\nYou can change the shape of the marker using the `markerType` option. For example, to use a square marker:\n\n```jsx\nimport {ScatterChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n series: [\n {\n xAxisField: \"sugar\",\n yAxisField: \"fat\",\n markerType: \"square\"\n }\n ]\n} \n \n return <ScatterChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\nValid options are `\"circle\"` (the default), `\"square\"` and `\"cross\"`.\n\n### Marker Size[](#marker-size)\n\nThe size of the marker can be adjusted using the `markerSize` option, whose default value is 10. This is useful for making markers more prominent:\n\n```jsx\nimport {ScatterChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n series: [\n {\n xAxisField: \"sugar\",\n yAxisField: \"fat\",\n markerSize: 20\n }\n ]\n} \n \n return <ScatterChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\n### Custom Marker Template[](#custom-marker-template)\n\nFor full control over the marker's appearance, you can provide an SVG template string using the `marker` option:\n\n```jsx\nimport {ScatterChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = ...\n \n const options = {\n series: [\n {\n xAxisField: \"sugar\",\n yAxisField: \"fat\",\n marker: <svg:rect viewBox='0 0 30 30' width='30' height='10'/>\n }\n ]\n} \n \n return <ScatterChartComponent options={options} className=\"my-chart\"/>\n}\n\n```\n\nThis template must be in VisuallyJs's template syntax\n\n## Options[](#options)\n\nScatterChartOptions\n\nOptions for a Scatter chart\n\n| Name | Type | Description |\n| ------------------ | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| axisFont? | [FontSpec]() | Spec for the font to use for all text on the axes. |\n| axisLineSize? | number | The width to use if showing a line marking value/category axes. By default, axis lines are not painted. |\n| colorGenerator? | [ColorGenerator]() | Optional function to call in order to establish the color to be used for each series |\n| cornerRadius? | number | When rounding bar/column corners, use this radius. Defaults to 5 pixels. |\n| data? | Array<[ObjectData]()> | Optional data to load into the chart. |\n| dataSource? | [DataSource]() | Optional data source (of type `DataSource`, meaning both `VisuallyJsModel` and `Selection` are supported) from which to retrieve data to load into the chart. |\n| dataSourceFilter? | [ChartModelFilter]() | When you provide `dataSource`, you can also provide a filter which accepts or rejects specific nodes/groups in the data source. |\n| defaultColor? | string | Optional color to use for every series. Overrides any colorGenerator. |\n| emptyMessage? | string | Message to display when the chart has no data. Defaults to \"No data\". |\n| grouped? | boolean | If true, the data will be grouped, if the chart type supports it (eg Bar/Column). |\n| groupField? | string | The name of the field that identifies which group a data point belongs to. Defaults to `group`. |\n| height? | number | Height for the chart. If omitted, height is computed from the width of the chart's container |\n| legend? | boolean \\| [LegendSpec]() | Either a boolean true/false, indicating the legend should be shown/hidden, or a spec for a legend. |\n| legendPadding? | number | When the legend is not floating, this number defines how much whitespace to leave around it. |\n| maximumMarkerSize? | number | Maximum allowed size for a marker. Defaults to 50 pixels. Set to Infinity to have no maximum (this can have unpleasant UI side effects with some datasets) |\n| maxLabelSize? | number | The maximum size a category label can be as a ratio of the chart's overall size. Category labels are rotated to 45 degrees automatically when they start to overlap each other, but if the labels are long strings then there is a chance they'll use up too much of the available chart space. This value (whose default is 0.2), specifies a hard limit for label size, to avoid that situation. In a chart whose category axis is the X axis, this is applied relative to the height of the chart, and in a chart whose category axis is the Y axis, it's applied relative to the width. |\n| minimumMarkerSize? | number | Minimum allowed size for a marker. Defaults to 8 pixels. Set to -Infinity to have no minimum (this can have unpleasant UI side effects with some datasets) |\n| resizeObserver? | boolean | Defaults to true, meaning the chart will redraw when its container element resizes. |\n| roundCorners? | boolean | Whether or not to round the corners of bars/columns. Defaults to true |\n| series | Array<[DualValueSeriesOptions]()> | Definition of the chart series' to display. You can plot multiple series on a chart. |\n| style? | [ChartStyleOptions]() | Styles for legend and grid. |\n| subtitle? | [SubtitleSpec]() | Subtitle for the chart. |\n| title? | [ChartTitleSpec]() | Title for the chart. |\n| titlePadding? | number | Padding to leave underneath the title |\n| tooltip? | [TooltipOptions]() | Options for the info tooltip. |\n| url? | string | Optional URL from which to retrieve data to load into the chart |\n| width? | number | Width for the chart. If omitted, width is computed from the width of the chart's container |\n| xAxis? | [ValueAxisDefinition]() | Configuration for the X axis. |\n| yAxis? | [ValueAxisDefinition]() | Configuration for the Y axis. |\n| yAxisPadding? | number | How much padding to leave between the y axes decoration and the chart content area. |\n| zoom? | {<br /> enabled:boolean,<br /> initialValue:number,<br /> range:\\[number, number]<br />} | Optional zoom configuration. |\n\n## CSS Classes[](#css-classes)\n\n| Class | Description |\n| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |\n| `vjs-bubble-chart` | Added to a bubble chart |\n| `vjs-chart-point` | Added to each point in a scatter/bubble chart |\n| `vjs-chart-point-hit-area` | Added to the hit area elements that represent each data point. These are to assist users in selecting data points which are small. |\n| `vjs-scatter-chart` | Added to a scatter chart |\n| `vjs-scatter-chart-point` | Added to each point in a scatter chart |","url":"https://visuallyjs.com/react/docs/charts/types/scatter-chart","lib":"react","topic":"charts"},"docs/charts/types/xy-chart.md":{"title":"Xy Chart","body":"# XY Chart\n\nXY charts are base charts containing an X and a Y axis, one of which displays chart categories and the other values.\n\n## Example[](#example)\n\n```jsx\nimport {XYChartComponent} from \"@visuallyjs/browser-ui-react\";\n\nexport default function XYChartExample() {\n\n const options = {\n title:{\n text:\"XY Chart Example\",\n },\n series:[\n {\n valueField:\"value\",\n label:\"Series 1\"\n }\n ],\n data:[\n {id:\"A\", value:10},\n {id:\"B\", value:20},\n {id:\"C\", value:15}\n ]\n }\n\n return <XYChartComponent options={options} \n className=\"vjs-inline-example\"/>\n\n}\n\n```","url":"https://visuallyjs.com/react/docs/charts/types/xy-chart","lib":"react","topic":"charts"},"docs/dashboards/connecting-charts.md":{"title":"Connecting Charts","body":"# Connecting charts\n\nOne of the key requirements of a dashboard is the ability to connect charts to your model. VisuallyJs makes this a snap. On this page we'll run through various basic scenarios, to give you a feel for what's possible.\n\n## Series based charts[](#series-based-charts)\n\nWe'll start with a simple example - in this canvas we have a set of nodes that display a value they are tracking.\n\n* Click the +/- buttons to increment/decrement the value.\n* Click in whitespace to add a new node at the location you clicked, with a random new value between 0 and 15.\n\n**********\n\n### Column chart[](#column-chart)\n\nThere are 3 parts to this currently - the component we use to render each node, the component for the app, and then the wrapper for the app.\n\n* Component\n* Node\n* App\n\nThe component uses a `DashboardExampleNode` to render each node, and sets `zoomToFit:true`, to fit all the nodes in the canvas on load. Then it registers a `canvasClick` event handler, which adds a new node with a random value at the location the user clicked.\n\n```jsx\nexport default function DashboardExampleSurface1() {\n \n <SurfaceComponent viewOptions={{\n nodes: {\n default: {\n jsx: DashboardExampleNode\n }\n }\n }} data={data1} renderOptions={{\n zoomToFit: true,\n events: {\n \"canvasClick\": (s, e) => {\n const pos = s.mapEventLocation(e)\n s.model.addNode({\n left: pos.x,\n top: pos.y,\n id: (uuid()).substring(0, 6),\n value: Math.floor(Math.random() * 15)\n })\n }\n }\n }}>\n <ControlsComponent style={{zIndex: \"50\"}}/>\n <GridBackgroundComponent/>\n </SurfaceComponent>\n}\n\n```\n\nThe node component shows the node id and value, plus the +/- buttons to adjust the value. These buttons call `updateNode` to adjust the current value.\n\n```jsx\nexport default function DashboardExampleNode({data, obj, model}) {\n return <div className=\"vjs-dashboard-node\">\n <span className=\"vjs-dashboard-id\">{data.id}</span>\n <div className=\"df aic w-100\" style={{justifyContent: \"center\"}}>\n <button onClick={() => model.updateNode(obj, {value:Math.max(0, data.value - 1)})}>-</button>\n <span className=\"vjs-dashboard-value\">{data.value}</span>\n <button onClick={() => model.updateNode(obj, {value:data.value + 1})}>+</button>\n </div>\n </div>\n}\n\n```\n\nThe code for the component itself is in the 'Component' tab. We've written\n\n```jsx\n<div className=\"vjs-dashboard-example-1\">\n <DashboardExampleSurface1/>\n</div>\n\n```\n\n##### Node data[](#node-data)\n\nThe data for each node in this app looks like this:\n\n```javascript\n{ \n id:\"1\", \n left:50, \n top:190, \n label:\"One\", \n value:5 \n}\n\n```\n\n##### Adding the chart[](#adding-the-chart)\n\nTo help users make sense of what they're seeing, we're going to add a [column chart](/react/docs/charts/types/column-chart.md) to this UI, plotting the `value` field of each node.\n\n**********\n\nTo do this, we introduced a `SurfaceProvider` to our wrapper:\n\n```jsx\n<div className=\"vjs-dashboard-example-1\">\n <SurfaceProvider>\n <DashboardExampleSurface1/>\n <DashboardExampleChart1/>\n </SurfaceProvider>\n</div>\n\n```\n\nand the code for `DashboardExampleChart1` looks like this:\n\n```jsx\nexport default function DashboardExampleChart1() {\n return <ColumnChartComponent options={{\n title: { text: \"Node Values\" },\n categoryAxis: {\n title: { text: \"Node Id\" }\n },\n valueAxis: {\n title: { text: \"Value\" }\n },\n series: [{ valueField: \"value\", color:\"midnightblue\" }],\n tooltip: { format: \"{{category}}:{{point.value}}\" }\n }}/>\n}\n\n```\n\nThe key points to note are:\n\n* The column chart component is context aware, and finds the surface (and its model) to attach to automatically\n* The `valueField:\"value\"` chart option is what tells the chart where to find the values to display.\n\nNow whenever there are changes to the model, the chart is repainted. Try clicking the +/- buttons and seeing how the chart redraws, or clicking into whitespace to add a new node. The chart is also fully integrated with the undo/redo buttons.\n\n#### Pie Chart[](#pie-chart)\n\nThe above example uses a column chart, but there are a number of series based charts in VisuallyJs, each of which can be dropped in for the column chart above. For example, we'll use this code for the chart instead, to show a pie chart comparing the `value` field in each node:\n\n```jsx\n<div className=\"vjs-dashboard-example-1\">\n <SurfaceProvider>\n <DashboardExampleSurface1/>\n <PieChartComponent options={{\n colors:[\"#456789\"],\n title: { text: \"Node Values\" },\n series: [{ valueField: \"value\" }],\n tooltip: { format: \"{{category}}:{{point.value}}\" }\n }}/>\n </SurfaceProvider>\n</div>\n\n```\n\n**********\n\n## Dual value axis charts[](#dual-value-axis-charts)\n\nCharts with two value axes - such as bubble and scatter charts - are easily integrated too.\n\n### Scatter Chart[](#scatter-chart)\n\nHere's a [scatter chart](/react/docs/charts/types/scatter-chart.md) which tracks the location of the nodes on the canvas (perhaps not the most useful application, but fun!):\n\n**********\n\nThis is the code:\n\n```jsx\n<SurfaceProvider>\n <DashboardExampleSurface1/>\n <ScatterChartComponent options={{\n title:{ text:\"Node location\" },\n series:[{\n xAxisField:\"left\",\n yAxisField:\"top\",\n color:\"#569934\"\n }],\n yAxis:{\n inverted:true\n },\n tooltip:{\n format:\"<b>Node: </b>{{point.id}}<b>Value: </b>{{point.value}}<b>Left: </b>{{point.left}}<b>Top: </b>{{point.top}}\"\n }}}/>\n</SurfaceProvider>\n\n```\n\nPoints to note are:\n\n* We map `xAxisField` to `left` and `yAxisField` to `top` - these are the properties used to position nodes on the canvas.\n* We mark `yAxis` as `inverted:true`. By default, the Y axis in a dual value chart has its minimum value in the lower left corner, but that is the opposite way to the way that browsers measure Y. So marking the y axis `inverted` means that the scatter points correctly map the Y axis of the nodes in the canvas.\n\n### Bubble Chart[](#bubble-chart)\n\nThis [bubble chart](/react/docs/charts/types/bubble-chart.md) extends the view provided by the scatter chart above to map the `value` field from each node to the bubble size:\n\n**********\n\n* As with the scatter chart, we map `xAxisField` to `left` and `yAxisField` to `top`\n* We mark `yAxis` as `inverted:true` - see discussion for scatter chart above\n* We map `valueField` to `value`, meaning that the size of each bubble is proportional to the `value` in the node it represents.\n\nnote\n\nBubble charts have a default maximum bubble size of 50 pixels and a default minimum size of 8 pixels. This is to prevent large discrepancies in data values from resulting in bubbles of widely different sizes in the chart. This maximum and minimum can be changed in the chart options.\n\n## Pie Charts[](#pie-charts)","url":"https://visuallyjs.com/react/docs/dashboards/connecting-charts","lib":"react","topic":"dashboards"},"docs/dashboards.md":{"title":"Dashboards","body":"# Dashboards\n\nCreating dashboards - using the same model for both an interactive diagram (like a flowchart or process builder) and real-time charts - is a straightforward process, and makes for very powerful UIs. The chart consumes the model directly, so any interaction with the canvas is immediately reflected in any connected charts.\n\n## Real-World Applications[](#real-world-applications)\n\n### 1. Supply Chain Management[](#1-supply-chain-management)\n\nIn a supply chain management app, a user can use a flowchart-style interface to map out the movement of goods from \"Manufacturer\" to \"Warehouse\" to \"Retailer.\" Each node defines some specific location, and then the edges between the nodes can store the quantity of goods that passes between nodes, as well as other information such as the shipping method and carrier.\n\nA separate Sankey view can then provide the user with a summary of the flow, with the ability to pivot on specific values in the edge data such as the transit mode or carrier. You can see this in action in our <!-- -->[Supply Chain Analyzer](/demonstrations/supply-chain.md) starter app:\n\n\n\n### 2. Infrastructure & Cloud Resource Management[](#2-infrastructure--cloud-resource-management)\n\nCloud architects often use diagramming tools to design VPCs, subnets, and server clusters. Charts can be linked to these diagrams to show information such as projected monthly spend, or total number of assets, etc. Take a look at our <!-- -->[Network Infrastructure](/demonstrations/network-infrastructure.md) dashboard to see a working example of this.\n\n### 3. Business Process Optimization (BPMN)[](#3-business-process-optimization-bpmn)\n\nBusiness analysts use process builders to define workflows (e.g., an insurance claim approval process).\n\n* **The Model:** The steps and decision gateways of the business process.\n* **Real-time Charts:** While simulating or monitoring the process, a Histogram could show the \"Bottleneck Score\" for each node in the flowchart. If the user moves a \"Manual Review\" step to a different team in the diagram, the charts would update to show how that change impacts the overall \"Mean Time to Resolution.\"\n\n### 4. Smart Manufacturing[](#4-smart-manufacturing)\n\nDigital twins of factory floors are often represented as diagrams showing the connection between various machines (PLC units).\n\n* **The Model:** The physical layout and logical connection of the assembly line.\n* **Real-time Charts:** If a machine node in the diagram reports an error state (changing its color or icon), a linked Donut Chart could immediately show the impact on the day's OEE (Overall Equipment Effectiveness) or the percentage of the line that is currently \"Down.\"\n\n### 5. Financial Portfolio & Risk Mapping[](#5-financial-portfolio--risk-mapping)\n\nFinancial analysts often map out complex relationships between parent companies, subsidiaries, and investment vehicles.\n\n* **The Model:** The ownership structure and flow of capital.\n* **Real-time Charts:** As the user adjusts the \"Ownership %\" on an edge between two company nodes using an inspector, a Treemap chart could update to show the weighted risk exposure across the entire portfolio based on the new structural data.\n\n[Getting Started](./getting-started)\n\n[Learn how to build a simple dashboard with VisuallyJs](./getting-started)","url":"https://visuallyjs.com/react/docs/dashboards","lib":"react","topic":""},"docs/diagrams/building-a-diagram.md":{"title":"Building A Diagram","body":"# Building a diagram\n\nOn this page we'll run through how to build a basic diagram with VisuallyJs - we'll be creating the diagram from the [Overview](/react/docs/diagrams.md) page, from the initial setup of the diagram with a couple of helper components, to the addition of shapes and edges, and then we'll provide some suggestions for where you may wish to go next.\n\n## Installation[](#installation)\n\nYou'll need to ensure you've imported VisuallyJs:\n\n* npm\n* pnpm\n* yarn\n* bun\n\n```bash\nnpm install @visuallyjs/browser-ui-react\n\n```\n\n```bash\npnpm add @visuallyjs/browser-ui-react\n\n```\n\n```bash\nyarn add @visuallyjs/browser-ui-react\n\n```\n\n```bash\nbun add @visuallyjs/browser-ui-react\n\n```\n\n## Creating the diagram[](#creating-the-diagram)\n\n### 1. Import components and CSS[](#1-import-components-and-css)\n\nThe first step is to import `DiagramComponent`, `ControlsComponent`, `MiniviewComponent` and the VisuallyJs default stylesheet:\n\n```jsx\nimport { DiagramComponent, ControlsComponent, MiniviewComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\"\n\n```\n\n### 2. Create your diagram[](#2-create-your-diagram)\n\nAt the minimum, we need to tell our `DiagramComponent` which shape sets you want to use:\n\n```jsx\nexport default function MyApp() {\n return <div style={{width:\"600px\", height:\"500px\"}}>\n <DiagramComponent options={{\n shapes:[FLOWCHART_SHAPES]\n }}>\n <ControlsComponent/>\n <MiniviewComponent/>\n </DiagramComponent>\n </div>\n}\n\n```\n\nThis is the result - a blank canvas:\n\n**********\n\n### 3. Add shapes[](#3-add-shapes)\n\nNow we'll add some shapes. Note we also set `zoomToFit` so that after the data has been loaded the entire dataset is visible.\n\n```jsx\nexport default function MyApp() {\n \n const data = {\n nodes:[\n { id:\"1\", label:\"Start\", x:100, y:50, type:\"terminus\", width:80, height:80, outline:\"#000000\", fill:\"#ffffff\"}, \n { id:\"2\", label:\"Decide\", x:40, y:200, type:\"decision\", width:100, height:100, outline:\"#000000\", fill:\"#ffffff\"},\n { id:\"3\", label:\"Yes Path\", x:-150, y:250, type:\"decision\", width:100, height:100, outline:\"#000000\", fill:\"#ffffff\"}, \n { id:\"4\", label:\"No Path\", x:150, y:450, type:\"decision\", width:100, height:100, outline:\"#000000\", fill:\"#ffffff\"},\n ],\n edges:[\n { source:\"1\", target:\"2\"}, \n { source:\"2\", target:\"3\", data:{label:\"Yes\"}},\n { source:\"2\", target:\"4\", data:{label:\"No\"}}\n ]\n }\n\n return <div style={{width:\"600px\", height:\"500px\"}}>\n <DiagramComponent data={data} options={{\n shapes:[FLOWCHART_SHAPES],\n zoomToFit:true\n }}>\n <ControlsComponent/>\n <MiniviewComponent/>\n </DiagramComponent>\n </div>\n}\n\n```\n\nThis is the result. It's not bad, but those connector lines don't quite suit this type of diagram:\n\n**********\n\n### 4. Customise edges[](#4-customise-edges)\n\nLet's make a few updates to the edges in our diagram:\n\n* We'll update the connectors to use an `Orthogonal` connector instead - consisting of horizontal and vertical line segments, and we'll tell VisuallyJs to use a `cornerRadius` on the connector, to make the corners rounded\n* We'll set an `Arrow` as the target marker for our edges\n* We'll instruct VisuallyJs to show a label on edges (which requires that the edge data has a `label` declared)\n\n```jsx\n<div style={{width:\"600px\", height:\"500px\"}}>\n <DiagramComponent data={data} options={{\n shapes:[FLOWCHART_SHAPES], \n zoomToFit:true,\n edges:{\n connector: {\n type: \"Orthogonal\",\n options: {\n cornerRadius: 7\n }\n },\n targetMarker:\"Arrow\",\n showLabels:true \n }\n }}>\n <ControlsComponent/>\n <MiniviewComponent/>\n </DiagramComponent>\n</div>\n\n```\n\n**********\n\n### 5. Resize/rotate[](#5-resizerotate)\n\nBy default, a diagram is editable - try clicking on a shape in the canvas below. VisuallyJs attaches tools to the shape that allow you to resize, rotate, clone or delete a shape.\n\n**********\n\nYou can switch off editing altogether via the `editable:false` option, or you can switch off rotation via `rotatable:false`.\n\n### 6. Add a palette[](#6-add-a-palette)\n\nWe'll add a palette from which users can drag new shapes onto the canvas. To do this we'll introduce a `DiagramProvider`, which is a context object that allows component to access a Diagram in scope, and then we'll use a `DiagramPaletteComponent`.\n\n```jsx\n<div style={{width:\"600px\", height:\"500px\", display:\"flex\"}}>\n <DiagramProvider>\n <DiagramPaletteComponent style={{ flex:\"0 0 20%\" }}/>\n <DiagramComponent style={{ flex:\"0 0 80%\" }} data={data} options={{\n shapes:[FLOWCHART_SHAPES], \n zoomToFit:true,\n edges:{\n connector: {\n type: \"Orthogonal\",\n options: {\n cornerRadius: 7\n }\n },\n targetMarker:\"Arrow\",\n showLabels:true \n }\n }}>\n <ControlsComponent/>\n <MiniviewComponent/>\n </DiagramComponent>\n </DiagramProvider> \n</div>\n\n```\n\n**********\n\n## Next Steps[](#next-steps)\n\n[Shapes](./shapes/overview)\n\n[Read an in depth discussion of how to work with shapes in a diagram](./shapes/overview)\n\n[Controlling diagram actions](./controlling-diagram-actions)\n\n[Read about mediators, a simple but powerful means of controlling various diagram actions](./controlling-diagram-actions)","url":"https://visuallyjs.com/react/docs/diagrams/building-a-diagram","lib":"react","topic":"diagrams"},"docs/diagrams/controlling-diagram-actions.md":{"title":"Controlling Diagram Actions","body":"# Controlling actions\n\nVarious actions and capabilities of a Diagram can be controlled by a [DiagramActionMediator](). This is an interface from which you can implement one or more methods that allow you to decide at runtime whether a given shape should offer various actions in its shape editing tools, whether it can be dragged, or whether it can be dropped onto some other vertex or the diagram canvas.\n\nEach method in the mediator is optional. If a method is not provided, the diagram-wide settings for that operation are used. The mediator is only invoked if the diagram is in an editable state.\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n mediator: {\n canResize: (vertex, shape, el) => vertex.data.resizable === true,\n canLink: (vertex, shape, el) => vertex.data.linkable === true\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n## Actions[](#actions)\n\ninfo\n\nThe example implementations on this page come from our <!-- -->[BPMN](/demonstrations/bpmn.md) starter application.\n\n### canResize[](#canresize)\n\nReturns whether or not the given vertex should be resizable in the UI. Defaults to true, meaning the resize handles will be present in the diagram tools when the vertex is selected.\n\n```typescript\ncanResize:(vertex: Vertex, shape: Shape, el: HTMLElement) => {\n return vertex.type === \"pool\" || vertex.type === \"lane\" || vertex.type === \"group\"\n}\n\n```\n\n### canClone[](#canclone)\n\nBy default, Diagrams will display a clone icon - - on a selected shape. You can manage that on a per-shape basis by providing a `canClone` function:\n\n```typescript\ncanClone:(vertex: Vertex, shape: Shape, el: HTMLElement) => {\n return vertex.type !== \"pool\" && vertex.type !== \"lane\"\n}\n\n```\n\nReturning false will mean the icon is not shown.\n\n### canLink[](#canlink)\n\nReturns whether or not the given vertex should be linkable via edge drag in the UI. Defaults to true, meaning the link icon will be present in the diagram tools when the vertex is selected.\n\n```typescript\ncanLink:(vertex: Vertex, shape: Shape, el: HTMLElement) => {\n return vertex.type !== \"pool\" && vertex.type !== \"lane\"\n}\n\n```\n\n### canRotate[](#canrotate)\n\nReturns whether or not the given vertex should be resizable in the UI. Defaults to true, meaning the rotate handle and leader will be present in the diagram tools when the vertex is selected.\n\n```typescript\ncanRotate:(vertex: Vertex, shape: Shape, el: HTMLElement) => {\n return false\n}\n\n```\n\n### canDrag[](#candrag)\n\nThe `canDrag` method is invoked when the user begins to drag a shape. It is passed the underlying vertex that is being dragged, the definition for the shape representing that vertex, and the SVG element from the DOM. Return `false` from this method if you wish to prevent drag.\n\n```typescript\ncanDrag:(vertex: Vertex, shape: Shape, el: HTMLElement) => {\n return vertex.type !== \"lane\"\n}\n\n```\n\n### canDrop[](#candrop)\n\nReturns whether or not the given vertex should be droppable on the given target, which may either be another vertex (if `targetVertex` is set), or the diagram canvas (if `isOnCanvas` is set). This method will never be called with both `targetVertex` set an `isOnCanvas` true - it's one or the other.\n\n```typescript\ncanDrop:(candidate: Vertex, target: Vertex | null, onCanvas: boolean) => {\n // only allow lanes to be dropped into pools\n if (candidate.type === \"lane\") {\n return target != null && target.type === \"pool\"\n }\n\n // pools can only be dropped on the canvas\n if (candidate.type === \"pool\") {\n return onCanvas === true\n }\n\n // other types can be dropped on the canvas or into groups/lanes\n if (onCanvas) {\n return true\n }\n\n return target.type === \"lane\" || target.type === \"group\"\n}\n\n```\n\nThis action is invoked both when dragging shapes in the diagram and when dragging a shape onto the diagram from a palette.\n\n***\n\n## Interface definition[](#interface-definition)\n\nThe full definition for the `DiagramActionMediator` is:\n\nDiagramActionMediator\n\nDefines an object that can decide at runtime whether a given shape should offer various actions in its shape editing tools. Each method in this interface is optional, and does not override any diagram-wide settings for the specific operation. Also, the mediator will not be invoked if a diagram is not editable.\n\n| Name | Type | Description |\n| ------------ | ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| canClone? | (v:[Vertex](), shape:[ShapeType](), el:[BrowserElement]()) => boolean | Returns whether or not the given vertex should be clonable in the UI. Defaults to true, meaning the clone icon will be present in the diagram tools. |\n| canCollapse? | (group:[Group](), currentSize:[Size]()) => boolean \\| [ObjectData]() | Returns whether or not the given group can be collapsed |\n| canDelete? | (v:[Vertex](), shape:[ShapeType](), el:[BrowserElement]()) => boolean | Returns whether or not the given vertex should be deletable in the UI. Defaults to true, meaning the delete icon will be present in the diagram tools when the vertex is selected. |\n| canDrag? | (v:[Vertex](), shape:[ShapeType](), el:[BrowserElement]()) => boolean | Returns whether or not the given vertex should be draggable in the UI. Defaults to true. |\n| canDrop? | (vertex:[Node]() \\| [Group](), targetVertex:[Node]() \\| [Group](), isOnCanvas:boolean) => boolean | Returns whether or not the given vertex should be droppable on the given target, which may either be another vertex (if `targetVertex` is set), or the diagram canvas (if `isOnCanvas` is set). This method will never be called with both `targetVertex` set an `isOnCanvas` true - it's one or the other. |\n| canExpand? | (group:[Group](), currentSize:[Size]()) => boolean \\| [ObjectData]() | Returns whether or not the given group can be expanded |\n| canLink? | (v:[Vertex](), shape:[ShapeType](), el:[BrowserElement]()) => boolean | Returns whether or not the given vertex should be linkable via edge drag in the UI. Defaults to true, meaning the link icon will be present in the diagram tools when the vertex is selected. |\n| canResize? | (v:[Vertex](), shape:[ShapeType](), el:[BrowserElement]()) => boolean | Returns whether or not the given vertex should be resizable in the UI. Defaults to true, meaning the resize handles will be present in the diagram tools when the vertex is selected. |\n| canRotate? | (v:[Vertex](), shape:[ShapeType](), el:[BrowserElement]()) => boolean | Returns whether or not the given vertex should be resizable in the UI. Defaults to true, meaning the rotate handle and leader will be present in the diagram tools when the vertex is selected. |","url":"https://visuallyjs.com/react/docs/diagrams/controlling-diagram-actions","lib":"react","topic":"diagrams"},"docs/diagrams/drag-and-drop/palettes.md":{"title":"Palettes","body":"# Palettes\n\nWith some types of diagrams, you'll want to provide your users with the ability to drag new shapes onto the canvas.\n\n## Setup[](#setup)\n\nTo drag and drop SVG shapes, you can use a `DiagramPaletteComponent` - a palette that sources its draggable shapes from a `ShapeLibrary`.\n\n```jsx\nimport { useEffect, useRef} from 'react';\nimport { FLOWCHART_SHAPES } from \"@visuallyjs/browser-ui\"\nimport { DiagramPaletteComponent, DiagramComponent, DiagramProvider } from \"@visuallyjs/browser-ui-react\"\n\nexport default function FlowchartComponent() {\n\n const options = {\n shapes:FLOWCHART_SHAPES\n }\n \n return <div>\n <DiagramProvider>\n <DiagramComponent options={options}/>\n <DiagramPaletteComponent className=\"node-palette\"/>\n </DiagramProvider>\n </div>\n\n\n```\n\nThe `DiagramPaletteComponent` is context aware and can locate the canvas to use from a `DiagramProvider`.\n\n## Options[](#options)\n\nThe full list of available props is:\n\nDiagramPaletteComponentProps\n\nOptions for a palette for a diagram.\n\n| Name | Type | Description |\n| ------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| allowClickToAdd? | boolean | When in tap mode, allow addition of new vertices simply by clicking, instead of requiring a shape be drawn. (When this is true, the drawing method also still works) |\n| autoExitDrawMode? | boolean | Defaults to true: when in 'tap' mode and a new group/node has been drawn on the canvas, the UI is set back to pan mode. |\n| className? | string | Optional class name to set on the diagram palette root element. |\n| diagram? | [Diagram]() | Optional diagram to attach to. In most cases it is better to use a DiagramProvider to provision the diagram to this component. |\n| dragSize? | [Size]() | Optional size to use for dragged elements. |\n| fill? | string | Optional fill color to use for dragged elements. This should be in RGB format, *not* a color like 'white' or 'cyan' etc. |\n| iconSize? | [Size]() | Optional size to use for icons. Defaults to 150x100 pixels. If you provide this but not `dragSize` this size will also be used for an icon that is being dragged. |\n| inspector? | boolean | Indicates that when one or more vertices are selected, clicking on an entry in the palette will change the type of the selected vertices to that type. Defaults to true. |\n| mode? | PaletteMode | Mode to operate in - 'drag' or 'tap'. Defaults to 'drag' (PALETTE\\_MODE\\_DRAG). |\n| onCellAdded? | (dc:[DiagramCell]()) => any | Callback to invoke when a new diagram cell has been added. |\n| onVertexAdded? | [OnVertexAddedCallback]() | Optional callback that will be invoked after a new vertex has been dropped and added to the dataset. |\n| outline? | string | Optional color to use for outline of dragged elements. Should be in RGB format. |\n| paletteStrokeWidth? | number | Stroke width to use for shapes in palette. Defaults to 1. |\n| preparedShapes? | Array\\<PreparedShape> | Optional set of prepared shapes to show in the palette. When this is provided, the palette will only render these shapes, and not the contents of the shape library. |\n| selectAfterAdd? | boolean | When true (which is the default), a newly dropped shape will be set as the underlying model's selection. |\n| showAllMessage? | string | Message to use for the 'show all' option in the shape set drop down when there is more than one set of shapes. Defaults to `Show all`. |\n| showLabels? | boolean | Optionally show each shape icon's label underneath it |\n| style? | Record\\<string,string> | Optional style object to apply to the container element. |\n\n## Configuring appearance[](#configuring-appearance)\n\nShapes in a diagram use a set of common properties to determine their appearance - `fill`, `outline`, `color`, etc. Diagrams maintain an internal context which tracks the last set value for properties, so when you drag a shape out of a palette and onto the canvas, the diagram will populate the shape's data with the latest values, or with default values if nothing has yet been set.\n\nSupported properties depend on the shape set in question, but all shape sets that VisuallyJs ships support these optional properties:\n\n* `fill` - Color to fill the shape with. Defaults to `#FFFFFF`.\n* `outline` - Color to outline the shape with. Defaults to `#000000`.\n* `outlineWidth` - Width of the shape's outline. Defaults to 2px.\n* `color` - Color to use for the shape's label (if shown). Defaults to `#000000`.\n\n## Drawing vertices[](#drawing-vertices)\n\nThe diagram palette can be run in \"draw\" mode, which then gives your users the ability to draw new vertices with the mouse:\n\n```jsx\n<DiagramProvider>\n <DiagramPaletteComponent mode=\"draw\"/>\n <DiagramComponent options={{ shapes:[FLOWCHART_SHAPES] }} data={{ ... }}/>\n</DiagramProvider>\n\n```\n\n## Prepared Shapes[](#prepared-shapes)\n\nShape libraries give you a powerful mechanism for building diagrams, but at quite a low level - each shape needs to be individually configured with its fill, outline etc. Prepared shapes are a method you can use to define the shapes in your diagram at a slightly higher level.\n\nThe interface that defines a `PreparedShape` is as follows:\n\nSorry - we could not find this document.\n\n#### Example[](#example)\n\nAs a simple example, we'll define three prepared shapes:\n\n```javascript\nconst preparedShapes = [{\n shapeId:\"greenBox\",\n type:\"rectangle\",\n category:\"basic\",\n properties:{\n fill:\"#44ff44\",\n outline:\"#12F456\"\n }\n},\n{\n shapeId:\"redOctagon\",\n type:\"octagon\",\n category:\"basic\",\n properties:{\n fill:\"#FF3333\",\n outline:\"#F21456\"\n }\n},\n{\n shapeId:\"blueEllipse\",\n type:\"ellipse\",\n category:\"basic\",\n properties:{\n fill:\"#3333FF\",\n outline:\"#1214F6\"\n }\n}]\n\n```\n\nWe tell the palette about them like this:\n\n```jsx\n<DiagramProvider>\n <DiagramPaletteComponent preparedShapes={preparedShapes}/>\n <DiagramComponent options={{ shapes:[BASIC_SHAPES] }} data={{ ... }}/>\n</DiagramProvider>\n\n```\n\nand this is the result - the palette shows only the prepared shapes that we gave it:","url":"https://visuallyjs.com/react/docs/diagrams/drag-and-drop/palettes","lib":"react","topic":"diagrams"},"docs/diagrams/edges/anchors.md":{"title":"Anchors","body":"# Anchors\n\nAn anchor models the notion of where on an element an edge should connect. There are three main types:\n\n* **static** - These are fixed to some point on an element and do not move. They can be specified using a string to identify one of the defaults that VisuallyJs ships with, or an object describing the location and orientation of edges connected to it.\n\n* **dynamic** - These are lists of static anchors from which VisuallyJs selects the most appropriate one each time a connection is painted. The algorithm used to determine the most appropriate anchor picks the one that is closest to the center of the other element in the connection. A future version of VisuallyJs might support a pluggable algorithm to make this decision.\n\n* **continuous** - These anchors are not fixed to any specific location; they are assigned to one of the four faces of an element depending on that element's orientation to the other element in the associated connection. These are the default anchors used by VisuallyJs.\n\n## Static Anchors[](#static-anchors)\n\nVisuallyJs has nine default anchor locations you can use to specify where the connectors connect to elements: these are the four corners of an element, the center of the element, and the midpoint of each edge of the element:\n\nTopLeft\n\nTopRight\n\nTop\n\nBottomLeft\n\nBottomRight\n\nBottom\n\nCenter\n\nLeft\n\nRight\n\nEach of these string representations is just a wrapper around the underlying object-based syntax `{x, y, ox, oy}`, where `x` and `y `are coordinates in the interval `[0,1]` specifying the position of the anchor, and `ox` and `oy`, which specify the orientation of the curve incident to the anchor, can have a value of 0, 1 or -1. For example, `{x:0, y:0.5, ox:-1, oy:0}` defines a `Left` anchor with a connector curve that emanates leftward from the anchor. Similarly, `{x:0.5, y:0, ox:0, oy:-1}` defines a `Top` anchor with a connector curve emanating upwards.\n\n```javascript\nanchor:\"Bottom\"\n\n```\n\nis identical to:\n\n```javascript\nanchor:{ x:0.5, y:1, ox:0, oy:1 }\n\n```\n\n### Anchor Offsets[](#anchor-offsets)\n\nIn addition to supplying the location and orientation of an anchor, you can optionally supply two more parameters that define an offset in pixels from the given location. Here's the anchor specified above, but with a 50 pixel offset below the element in the y axis:\n\n```javascript\nanchor:{ x:0.5, y:1, ox:0, oy:1, offsetX:0, offsetY:50 } \n\n```\n\n## Dynamic Anchors[](#dynamic-anchors)\n\nThese are anchors that can be positioned in one of a number of locations, choosing the one that is most appropriate each time something moves or is painted in the UI.\n\nThere is no special syntax for creating a dynamic anchor; you just provide an array of individual static anchor specifications, eg:\n\n```javascript\n\nanchor:[\n {x:0.2, y:0, ox:0, oy:-1 },\n {x:1, y:0.2, ox:1, oy:0 },\n {x:0.8, y:1, ox:0, oy:1 },\n {x:0, y:0.8, ox:-1, oy:0 } \n]\n\n```\n\nNote that you can mix the types of these individual static anchor specifications:\n\n```javascript\nanchor:[\n {x:0.2, y:0, ox:0, oy:-1 },\n {x:1, y:0.2, ox:1, oy:0 },\n \"Top\",\n \"Bottom\"\n]\n\n\n```\n\n### Default[](#default)\n\nVisuallyJs provides a dynamic anchor called `AutoDefault` that chooses from `Top`, `Right`, `Bottom` and `Left`:\n\n```javascript\nanchor:\"AutoDefault\"\n\n```\n\nThese two nodes have an endpoint with an `AutoDefault` anchor - drag them around and see how they choose from `Top`, `Left`, `Bottom` and `Right` depending on their orientation.\n\n**********\n\n### Location selection[](#location-selection)\n\nThe algorithm that decides which location to choose just calculates which location is closest to the center of the other element in the edge. It is possible that future versions of VisuallyJs could support more sophisticated choice algorithms, if the need arose.\n\n## Continuous Anchors[](#continuous-anchors)\n\nAs discussed above, these are anchors whose positions are calculated by VisuallyJs according to the orientation between elements in a connection, and also how many other continuous anchors happen to be sharing the element. You specify that you want to use continuous anchors using the string syntax you would use to specify one of the default static anchors, for example:\n\n```javascript\nanchor:\"Continuous\"\n\n```\n\nNote in this example we specified only \"anchor\", rather than \"anchors\" - VisuallyJs will use the same spec for both anchors. But we could have said this:\n\n```javascript\nanchors:[\"Bottom\", \"Continuous\"]\n\n```\n\n...which would have resulted in the source element having a static anchor at `Bottom`. In practise, though, it seems the continuous anchors work best if both elements in a connection are using them.\n\nTry dragging these nodes around and see how the anchors adapt their positions:\n\n**********\n\n### Face selection[](#face-selection)\n\nBy default, a continuous anchor will choose points from all four faces of the element on which it resides. You can control this behaviour, though, with the `faces` parameter on the anchor spec:\n\n```javascript\nanchor:{ type:\"Continuous\", options:{ faces:[ \"top\", \"left\" ] } }\n\n```\n\nAllowed values are:\n\n* `top`\n* `left`\n* `right`\n* `bottom`\n\nIf you provide an empty array for the `faces` parameter, VisuallyJs will default to using all four faces.","url":"https://visuallyjs.com/react/docs/diagrams/edges/anchors","lib":"react","topic":"diagrams"},"docs/diagrams/edges/click-to-add-edges.md":{"title":"Click To Add Edges","body":"# Click to add edges\n\nThis is an input method for edges whereby your users click a shape to select it, and then click a target shape. With pointer devices the user can see the edge that is being created as the pointer moves to the target, but with touch devices this is not the case, so take that into account if you're considering using this.\n\n## Configuration[](#configuration)\n\nTo setup click to add edges, you specify a flag in your render options:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n edges: {\n inputMethod: \"click\"\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\nShapes are automatically configured as edge targets in a diagram.\n\n## Cancelling edge input[](#cancelling-edge-input)\n\nIf you've clicked a source vertex but you wish to abort, you have one of two choices:\n\n* Press the **ESCAPE** key\n* Right-click somewhere in the canvas whitespace\n\ncaution\n\nIf you have set `consumeRightClick:false` in your render options, right click will *not* work to cancel edge input.\n\n## Unattached edges[](#unattached-edges)\n\nThe click to add functionality cannot currently be used to establish an edge whose target is initially unattached.\n\n## Relocating edges[](#relocating-edges)\n\nEdges that were added via click-to-add can only be relocated by dragging.\n\n## CSS Classes[](#css-classes)\n\n| Class | Description |\n| ----------------------------- | -------------------------------------------------------------------------------------------------- |\n| `vjs-edge-click-entry-method` | Added to the document body when in click mode for edges, and the user has clicked/tapped a source. |","url":"https://visuallyjs.com/react/docs/diagrams/edges/click-to-add-edges","lib":"react","topic":"diagrams"},"docs/diagrams/edges/connectors.md":{"title":"Connectors","body":"# Connectors\n\nThis page contains definitions and examples for the various connectors that ship with VisuallyJs.\n\n## Bezier[](#bezier)\n\nProvides a cubic Bezier path (having two control points) between the two anchors.\n\n```javascript\n\n{\n \"connector\": \"Bezier\"\n}\n\n```\n\n**********\n\n### Scale[](#scale)\n\nThe key measurement in the Bezier connector is how far the control points are from the anchors. This is controlled by the `scale` option, which is a measure of the ratio of a control point's distance from its anchor compared to the distance between the two anchors in the edge. By default this is 0.45. Increasing this value will make the connector more curvy - in the canvas below we have set it to 0.85:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Bezier\",\n \"options\": {\n \"scale\": 0.85\n }\n }\n}\n\n```\n\n**********\n\nYou can set this to any number, even numbers greater than 1.\n\n### Stubs[](#stubs)\n\nYou can set a `stub` on the connector:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Bezier\",\n \"options\": {\n \"stub\": 25\n }\n }\n}\n\n```\n\n**********\n\n### Gap[](#gap)\n\nYou can set a `gap` on the connector to leave some space between the anchor point and the connector line:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Bezier\",\n \"options\": {\n \"gap\": 10\n }\n }\n}\n\n```\n\n**********\n\n### Options[](#options)\n\nBezierConnectorOptions\n\nOptions for CubicBezierConnector\n\n| Name | Type | Description |\n| ----------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| cssClass? | string | Optional class to set on the element used to render the connector. |\n| gap? | number | Defines a number of pixels between the end of the connector and its anchor point. Defaults to zero. |\n| hoverClass? | string | Optional class to set on the element used to render the connector when the mouse is hovering over the connector. |\n| loopbackDistance? | number | When the connector's source and target is the same vertex, this is a measure of how far the control point will<br />be placed from the element. Defaults to 62 pixels |\n| scale? | number | Where to put the control point relative to the source/target. The number provided here should be a decimal, whose value defines the proportional distance between the source and target that the control point should be located at. The default value is 0.45. Larger values will make the Bezier curvier. |\n| stub? | number | Stub defines a number of pixels that the connector travels away from its element before the connector's actual path begins. |\n\n***\n\n## Straight[](#straight)\n\nDraws a series of one or more straight line segments between the source and target, with options to smooth to a curve or to round the corners between segments. The default computation creates a single segment, but if you have vertex avoidance switched on, or if you edit the path, then the connector will have multiple segments.\n\n```javascript\n\n{\n \"connector\": \"Straight\"\n}\n\n```\n\n**********\n\n### Stubs[](#stubs-1)\n\nYou can set a `stub` on the connector:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Straight\",\n \"options\": {\n \"stub\": 25\n }\n }\n}\n\n```\n\n**********\n\n### Gap[](#gap-1)\n\nYou can set a `gap` on the connector to leave some space between the anchor point and the connector line:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Straight\",\n \"options\": {\n \"gap\": 10\n }\n }\n}\n\n```\n\n**********\n\n### Geometry[](#geometry)\n\nYou can supply a `geometry` object for the edge that the connector represents for when you want multiple segments:\n\n```javascript\nedges:[\n{ \n \"source\":\"1\", \n \"target\":\"3\",\n \"geometry\":{\n source:{ curX:170, curY:90, ox:1, oy:0, x:1, y:0.5 },\n target:{ curX:510, curY:230, ox:0, oy:1, x:0.5, y:1 },\n segments:[\n { x1: 170, y1: 90, x2:250, y2:90 },\n { x1: 250, y1: 90, x2:400, y2:310 },\n { x1: 400, y1:310, x2:510, y2:230 }\n ]\n }\n }\n]\n\n```\n\n```javascript\n\n{\n \"connector\": \"Straight\"\n}\n\n```\n\n**********\n\n### Smoothing[](#smoothing)\n\nYou can also specify that you want to smooth the connector via the `smooth` option:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Straight\",\n \"options\": {\n \"smooth\": true\n }\n }\n}\n\n```\n\n**********\n\nnote\n\nIf you set `smooth:true` on a `Straight` connector but don't provide a a value for `stub` then you won't see any curve when there's only one segment, as the smoothing is only applied when the connector has more than one segment. If you provide a small value for `stub` you will see quite a pronounced hook, as in the following example where we set `stub` to 10.\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Straight\",\n \"options\": {\n \"stub\": 10,\n \"smooth\": true\n }\n }\n}\n\n```\n\n**********\n\nCompare with the same dataset and a `stub` of 50:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Straight\",\n \"options\": {\n \"stub\": 50,\n \"smooth\": true\n }\n }\n}\n\n```\n\n**********\n\nSmoothing works better when there are multiple segments in the connector, or when it does not just consist of one straight segment and stubs.\n\n### Rounded corners[](#rounded-corners)\n\nAn alternative to smoothing is rounded corners:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Straight\",\n \"options\": {\n \"cornerRadius\": 15\n }\n }\n}\n\n```\n\n**********\n\n### Options[](#options-1)\n\nStraightConnectorOptions\n\nOptions for a straight connector.\n\n| Name | Type | Description |\n| ------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| alwaysRespectStubs? | boolean | Defaults to true, meaning always draw a stub of the desired length, even when the source and target elements are very close together. This only applies when constrain is set to PATH\\_CONSTRAIN\\_ORTHOGONAL. |\n| constrain? | [ConnectorPathConstrainment]() | Optional constraint on the direction path segments can travel in. Options are PATH\\_CONSTRAIN\\_NONE, PATH\\_CONSTRAIN\\_ORTHOGONAL (segments are vertical and/or horizontal lines) and PATH\\_CONSTRAIN\\_DIAGONAL (segments are vertical, horizontal, or 45 degree lines). You can also use PATH\\_CONSTRAIN\\_MANHATTAN as an alias for PATH\\_CONSTRAIN\\_ORTHOGONAL or PATH\\_CONSTRAIN\\_METRO as an alias for PATH\\_CONSTRAIN\\_DIAGONAL. |\n| cornerRadius? | number | Optional radius to apply to corners. If you have set `smooth:true` this will be ignored. |\n| cssClass? | string | Optional class to set on the element used to render the connector. |\n| gap? | number | Defines a number of pixels between the end of the connector and its anchor point. Defaults to zero. |\n| hoverClass? | string | Optional class to set on the element used to render the connector when the mouse is hovering over the connector. |\n| loopbackRadius? | number | For a loopback connection (when constrain is set to orthogonal), the size of the loop. |\n| midpoint? | number | The point to use as the halfway point between the source and target when constrain is set to orthogonal. Defaults to 0.5. |\n| slightlyWonky? | boolean | If true, and a cornerRadius is set, the lines are drawn in such a way that they look slightly hand drawn. |\n| smooth? | boolean | Whether or not to smooth the connector. Defaults to false. It is not recommended to use this in conjunction with `orthogonal` or `diagonal` constrain, as the line tends to take on a bit of a hand-drawn appearance. It's not without charm but it's also not for everyone. |\n| smoothing? | number | The amount of smoothing to apply. The default is 0.15. Values that deviate too much from the default will make your lines look weird. |\n| stub? | number | Stub defines a number of pixels that the connector travels away from its element before the connector's actual path begins. |\n\n***\n\n## Orthogonal[](#orthogonal)\n\nDraws a connection that consists of a series of vertical or horizontal segments - the classic flowchart look. Internally this connector is an alias for a `Straight` connector with `constrain:\"orthogonal\"`.\n\n```javascript\n\n{\n \"connector\": \"Orthogonal\"\n}\n\n```\n\n**********\n\n### Stubs[](#stubs-2)\n\nYou can set a `stub` on the connector.\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Orthogonal\",\n \"options\": {\n \"stub\": 25\n }\n }\n}\n\n```\n\n**********\n\n### Gap[](#gap-2)\n\nYou can set a `gap` on the connector to leave some space between the anchor point and the connector line:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Orthogonal\",\n \"options\": {\n \"gap\": 10\n }\n }\n}\n\n```\n\n**********\n\n### Rounded corners[](#rounded-corners-1)\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Orthogonal\",\n \"options\": {\n \"cornerRadius\": 5\n }\n }\n}\n\n```\n\n**********\n\n### Slightly wonky[](#slightly-wonky)\n\nWe stumbled across this effect in error while developing the orthogonal connector and we thought it had a certain charm, so we put it on a flag - it gives your connectors a slightly hand-drawn feel. You need to set a `cornerRadius` when you set this flag or you won't see any effect. Here we've used a corner radius of 5 pixels. Feel free to experiment, but in our experience numbers much larger than that tend to reduce the charm.\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"Orthogonal\",\n \"options\": {\n \"slightlyWonky\": true,\n \"cornerRadius\": 5\n }\n }\n}\n\n```\n\n**********\n\n### Options[](#options-2)\n\nOrthogonalConnectorOptions\n\nOptions for an orthogonal connector.\n\n| Name | Type | Description |\n| ------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------- |\n| alwaysRespectStubs? | boolean | Defaults to true, meaning always draw a stub of the desired length, even when the source and target elements are very close together. |\n| cornerRadius? | number | Optional curvature of the corners in the connector. Defaults to 0. |\n| cssClass? | string | Optional class to set on the element used to render the connector. |\n| gap? | number | Defines a number of pixels between the end of the connector and its anchor point. Defaults to zero. |\n| hoverClass? | string | Optional class to set on the element used to render the connector when the mouse is hovering over the connector. |\n| loopbackRadius? | number | For a loopback connection, the size of the loop. |\n| midpoint? | number | The point to use as the halfway point between the source and target. Defaults to 0.5. |\n| slightlyWonky? | boolean | If true, and a cornerRadius is set, the lines are drawn in such a way that they look slightly hand drawn. |\n| stub? | number | Stub defines a number of pixels that the connector travels away from its element before the connector's actual path begins. |\n\n***\n\n## QuadraticBezier[](#quadraticbezier)\n\nDraws slightly curved lines, similar to the connectors you may have seen in software like GraphViz.\n\n```javascript\n\n{\n \"connector\": \"QuadraticBezier\"\n}\n\n```\n\n**********\n\n### Curviness[](#curviness)\n\nYou can set the `curviness` of the connector to adjust how pronounced the curve is, by changing the position of the control with respect to the midpoint of the two anchors. The default value is 10. There is no limit to what you can set this value to be, although large values do tend to be less pleasing. You can also set this to be a negative number, which will result in the connector curving in the opposite way to the default.\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"QuadraticBezier\",\n \"options\": {\n \"curviness\": 30\n }\n }\n}\n\n```\n\n**********\n\n### Stubs[](#stubs-3)\n\nYou can set a `stub` on the connector:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"QuadraticBezier\",\n \"options\": {\n \"stub\": 25\n }\n }\n}\n\n```\n\n**********\n\n### Gap[](#gap-3)\n\nYou can set a `gap` on the connector to leave some space between the anchor point and the connector line:\n\n```javascript\n\n{\n \"connector\": {\n \"type\": \"QuadraticBezier\",\n \"options\": {\n \"gap\": 10\n }\n }\n}\n\n```\n\n**********\n\n### Options[](#options-3)\n\nQuadraticBezierConnectorOptions\n\nOptions for a QuadraticBezierConnector\n\n| Name | Type | Description |\n| ----------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| cssClass? | string | Optional class to set on the element used to render the connector. |\n| curviness? | number | A measure of how \"curvy\" the bezier is. In terms of maths what this translates to is how far from the midpoint of the curve the control points is positioned. |\n| gap? | number | Defines a number of pixels between the end of the connector and its anchor point. Defaults to zero. |\n| hoverClass? | string | Optional class to set on the element used to render the connector when the mouse is hovering over the connector. |\n| loopbackDistance? | number | When the connector's source and target is the same vertex, this is a measure of how far the control point will<br />be placed from the element. Defaults to 62 pixels |\n| stub? | number | Stub defines a number of pixels that the connector travels away from its element before the connector's actual path begins. |","url":"https://visuallyjs.com/react/docs/diagrams/edges/connectors","lib":"react","topic":"diagrams"},"docs/diagrams/edges/dragging-edges.md":{"title":"Dragging Edges","body":"# Dragging edges\n\nYou can drag edges between the shapes in your diagram by first clicking on some shape to select it (which we have done below programmatically via the `selectCell` method of the diagram), and then dragging an edge from the arrow icon in the lower right corner:\n\n**********\n\n## Visual cues[](#visual-cues)\n\n### While dragging[](#while-dragging)\n\nThere are two main CSS classes you can use to provide visual cues to your users about the state of an edge drag:\n\n* `vjs-drag-active` When an edge is being dragged, this class is assigned to all elements onto which the edge could be dropped\n\n* `vjs-drag-hover` When an edge is being dragged and the mouse is hovering over a possible target, this class is assigned to that element\n\nIn the canvas below we have these style rules:\n\n```css\n.vjs-node {\n outline:1px solid;\n}\n \n.vjs-drag-active {\n outline:2px solid forestgreen;\n}\n\n.vjs-drag-hover {\n outline:4px solid orangered;\n}\n\n```\n\nTry dragging an edge - you'll see the `.vjs-drag-active` class applied to each of the nodes initially. When you drag the edge over one of the nodes you'll see the `.vjs-drag-hover` class applied:\n\n**********\n\n### Connected elements[](#connected-elements)\n\nWhen some element has one or more edges attached to it, VisuallyJs adds the CSS class `vjs-connected` to the element in the DOM. In the canvas below we have this style rule declared:\n\n```css\n.vjs-connected g {\n fill:#0a58ca;\n}\n\n```\n\nNodes 1 and 2 are connected in our initial dataset and are, accordingly, painted with a blue background, via the CSS rule. If you drag a new edge (from one of the red circles) to node 3 you'll see it update to have a blue background, as the `vjs-connected` class will be assigned when the edge is established.\n\n**********\n\n***\n\n## Snapping to drag targets[](#snapping-to-drag-targets)\n\nYou can instruct VisuallyJs to snap to target shapes when dragging edges:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n edges: {\n snap: {\n enabled: true\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\nWhich you can see in operation here - try dragging an edge from one of the shapes. As it gets within proximity of one of the other nodes, the edge is snapped:\n\n**********\n\n### Adjusting sensitivity[](#adjusting-sensitivity)\n\nBy default the snapping mechanism will kick in at a distance of 50 pixels from the target. You can change this:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n edges: {\n snap: {\n enabled: true,\n threshold: 20\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\nWhich you can see in operation here - try dragging an edge from one of the shapes. As it gets within 20px of one of the other nodes, the edge is snapped:\n\n**********\n\n## Constraining connectivity[](#constraining-connectivity)\n\nYou can control whether or not a shape will display a link icon via the `canLink` mediator action:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n canLink: (vertex: Vertex, shape: Shape, el: HTMLElement) => {\n return vertex.type !== \\pool\\\" && vertex.type !== \\\"lane\\\"\n}\"\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\nMediators are discussed in detail [on this page](/react/docs/diagrams/controlling-diagram-actions.md#canlink)\n\n## CSS Classes[](#css-classes)\n\nThere are a number of CSS classes assigned to various parts of the UI during an edge drag. These can be used to easily add visual cues for your users, and also to manage z-index for the best user experience.\n\n| Class | Description |\n| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `vjs-connector-source-drag` | The class assigned to the SVG element with which a user can drag to reposition the source of some edge. |\n| `vjs-connector-target-drag` | The class assigned to the SVG element with which a user can drag to reposition the target of some edge. |\n| `vjs-connector-transient-drag` | Assigned to the temporary DOM element used when relocating an existing edge via the mouse/touch events. |\n| `vjs-edge-relocating` | Assigned by the Surface to the DOM element representing an edge that is being dragged to relocate its source or target. This class is only added when the edge input handler is in drag mode. It is assigned to the connector element once the mouse starts to move, and removed on mouseup. |\n| `vjs-edge-will-relocate` | Assigned by the Surface to the DOM element representing an edge that is about to be relocated. When the edge input mode is dragging, this class is assigned on mousedown on one of the drag handles, before the mouse moves, and removed when the mouse begins to move (or on mouseup if the user does not move the mouse). When the edge input mode is tap, this class is assigned when the user has tapped on one of the relocate handles, and is removed either when the user clicks on whitespace, cancelling the relocation, or clicks on an active target and effects the relocation. |\n| `vjs-surface-edge-dragging` | Assigned by the Surface to its root element when an edge is being dragged. This is not assigned to the edge element itself. |","url":"https://visuallyjs.com/react/docs/diagrams/edges/dragging-edges","lib":"react","topic":"diagrams"},"docs/diagrams/edges/edge-labels.md":{"title":"Edge Labels","body":"# Edge Labels\n\nYou can extract the value of each edge's `label` from the edge's backing data:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = {\n nodes:[\n {id:\"1\",x:50,y:50,type:\"diamond\"},\n {id:\"2\",x:250,y:50,type:\"rectangle\"}\n ],\n edges:[\n {source:\"1\",target:\"2\",data:{label:\"A Label\"}}\n ]\n}\n \n const options = {\n edges: {\n showLabels: true\n },\n shapes: [\n {\n id: \"basic\",\n name: \"Basic\",\n shapes: [\n {\n type: \"rectangle\",\n label: \"Rectangle\",\n template: \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"{{width}}\\\" height=\\\"{{height}}\\\"/>\"\n },\n {\n type: \"rounded-rectangle\",\n label: \"Rounded Rectangle\",\n template: \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"{{width}}\\\" height=\\\"{{height}}\\\" rx=\\\"{{width/10}}\\\"/>\"\n },\n {\n type: \"ellipse\",\n label: \"Ellipse\",\n template: \"<ellipse cx=\\\"{{width/2}}\\\" cy=\\\"{{height/2}}\\\" rx=\\\"{{width/2}}\\\" ry=\\\"{{height/2}}\\\"/>\"\n },\n {\n type: \"diamond\",\n label: \"Diamond\",\n square: true,\n template: \"<polygon points=\\\"{{width/2}} 0 {{width}} {{height/2}} {{width/2}} {{height}} 0 {{height /2}}\\\"/>\"\n },\n {\n type: \"isosceles-triangle\",\n label: \"Isosceles Triangle\",\n template: \"<polygon points=\\\"{{width/2}} 0 {{width}} {{height}} 0 {{height}}\\\"/>\"\n },\n {\n type: \"inverted-isosceles-triangle\",\n label: \"Inverted Isosceles Triangle\",\n template: \"<polygon points=\\\"{{width/2}} {{height}} {{width}} 0 0 0\\\"/>\"\n },\n {\n type: \"right-triangle\",\n label: \"Right Triangle\",\n template: \"<polygon points=\\\"0 0 0 {{height}} {{width}} {{height}}\\\"/>\"\n },\n {\n type: \"label\",\n label: \"Label\",\n icon: \"<svg:svg viewBox=\\\"0 0 100 100\\\"><svg:rect x=\\\"10\\\" y=\\\"10\\\" width=\\\"80\\\" height=\\\"80\\\" rx=\\\"5\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"8,4\\\" opacity=\\\"0.6\\\"/><svg:path d=\\\"M 35 75 L 48 30 L 52 30 L 65 75 M 40 62 L 60 62\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/></svg:svg>\",\n template: \"<g>\n<r-if test=\\\"!text\\\">\n<svg:rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"{{width}}\\\" height=\\\"{{height}}\\\" stroke=\\\"#888\\\" stroke-dasharray=\\\"2\\\" stroke-width=\\\"1\\\" fill=\\\"{{'transparent'}}\\\"/>\n</r-if>\n<svg:rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"{{width}}\\\" height=\\\"{{height}}\\\" stroke=\\\"none\\\" fill=\\\"{{fill || 'transparent'}}\\\"/>\n<!-- if scaled not set default to true -->\n<r-if test=\\\"!!scaled\\\">\n <svg:text dominant-baseline=\\\"hanging\\\" stroke=\\\"none\\\" fill=\\\"{{color}}\\\" textLength=\\\"{{width}}\\\" lengthAdjust=\\\"spacingAndGlyphs\\\" font-size=\\\"{{height}}\\\" font-style=\\\"{{fontStyle}}\\\">{{text}}</svg:text>\n</r-if>\n<!-- if scaled set explicitly to false do not scale -->\n<r-if test=\\\"scaled === false\\\">\n <svg:text dominant-baseline=\\\"hanging\\\" stroke=\\\"none\\\" fill=\\\"{{color}}\\\" font-size=\\\"{{fontSize}}\\\" font-style=\\\"{{fontStyle}}\\\">{{text}}</svg:text>\n</r-if>\n</g>\",\n payload: {\n text: \"Label\",\n scaled: true\n },\n properties: [\n {\n id: \"fill\",\n label: \"Background Color\",\n type: \"color\",\n defaultValue: \"transparent\"\n },\n {\n id: \"color\",\n label: \"Text Color\",\n type: \"color\",\n defaultValue: \"#000000\"\n },\n {\n id: \"text\",\n label: \"Text\",\n type: \"string\",\n defaultValue: \"Text\"\n },\n {\n id: \"scaled\",\n label: \"Scaled\",\n type: \"boolean\",\n defaultValue: true\n }\n ]\n },\n {\n type: \"inverted-right-triangle\",\n label: \"Right Triangle\",\n template: \"<polygon points=\\\"{{width}} {{height}} {{width}} 0 0 {{height}}\\\"/>\"\n },\n {\n type: \"hexagon\",\n label: \"Hexagon (pointy)\",\n square: true,\n template: \"<polygon points=\\\"{{width/2}} 0 {{width}} {{height*1732/6000}} {{width}} {{height-(height*1732/6000)}} {{width/2}} {{height}} 0 {{height-(height*1732/6000)}} 0 {{height*1732/6000}}\\\"/>\"\n },\n {\n type: \"hexagon-flat\",\n label: \"Hexagon (flat)\",\n square: true,\n template: \"<polygon points=\\\"0 {{height/2}} {{width*1732/6000}} {{height}} {{width-(width*1732/6000)}} {{height}} {{width}} {{height/2}} {{width-(width*1732/6000)}} 0 {{width*1732/6000}} 0\\\"/>\"\n },\n {\n type: \"octagon\",\n label: \"Octagon\",\n square: true,\n template: \"<polygon points=\\\"{{width * 293 / 1000}} 0 {{width * 707 / 1000}} 0 {{width}} {{height * 293 / 1000}} {{width}} {{height * 707 / 1000}} {{width * 707 / 1000}} {{height}} {{width * 293 / 1000}} {{height}} 0 {{height * 707 / 1000}} 0 {{height * 293 / 1000}}\\\"/>\"\n },\n {\n type: \"pentagon\",\n label: \"Pentagon\",\n square: true,\n template: \"<polygon points=\\\"{{width/2}} 0 {{width}} {{height*343/1000}} {{width*793/1000}} {{height*904/1000}} {{width*206/1000}} {{height*904/1000}} 0 {{height*343/1000}}\\\"/>\"\n },\n {\n type: \"parallelogram\",\n label: \"Parallelogram\",\n template: \"<polygon points=\\\"0 {{height}} {{width/8}} 0 {{width}} 0 {{width * 7 / 8}} {{height}}\\\"/>\"\n },\n {\n type: \"trapezoid\",\n label: \"Trapezoid\",\n template: \"<polygon points=\\\"0 {{height}} {{width/8}} 0 {{width * 7 / 8}} 0 {{width}} {{height}}\\\"/>\"\n },\n {\n type: \"cross\",\n label: \"Cross\",\n template: \"<path d=\\\"M 0 {{height*3/10}} L 0 {{height * 7/10}} L {{width *3/10}} {{ height * 7/10}} L {{width *3/10}} {{height}} L {{width *7/10}} {{height}} L {{width*7/10}} {{height*7/10}} L {{width}} {{height * 7/10}} L {{width}} {{height*3/10}} L {{width *7/10}} {{height*3/10}} L {{width*7/10}} 0 L {{width*3/10}} 0 L {{width*3/10}} {{height*3 /10}} Z\\\"/>\"\n },\n {\n type: \"l-shape-bl\",\n label: \"L Shape (Bottom left)\",\n template: \"<path d=\\\"M 0 0 L 0 {{height}} L {{width}} {{height}} L {{width}} {{height / 2}} L {{width/2}} {{height/2}} L {{width/2}} 0 Z\\\"/>\"\n },\n {\n type: \"l-shape-br\",\n label: \"L Shape (Bottom right)\",\n template: \"<path d=\\\"M {{width}} {{height}} L {{width}} 0 L {{width/2}} 0 L {{width/2}} {{height/2}} L 0 {{height/2}} L 0 {{height}} Z\\\"/>\"\n },\n {\n type: \"l-shape-tl\",\n label: \"L Shape (Top left)\",\n template: \"<path d=\\\"M 0 0 L 0 {{height}} L {{width/2}} {{height}} L {{width/2}} {{height / 2}} L {{width}} {{height/2}} L {{width}} 0 Z\\\"/>\"\n },\n {\n type: \"l-shape-tr\",\n label: \"L Shape (Top right)\",\n template: \"<path d=\\\"M {{width}} {{height}} L {{width}} 0 L 0 0 L 0 {{height/2}} L {{width/2}} {{height/2}} L {{width/2}} {{height}} Z\\\"/>\"\n },\n {\n type: \"u-shape\",\n label: \"U Shape\",\n template: \"<path d=\\\"M 0 0 L 0 {{height}} L {{width}} {{height}} L {{width}} 0 L {{width*2/3}} 0 L {{width*2/3}} {{height/2}} L {{width/3}} {{height/2}} L {{width/3}} 0 Z\\\"/>\"\n },\n {\n type: \"inverted-u-shape\",\n label: \"U Shape (Inverted)\",\n template: \"<path d=\\\"M 0 0 L {{width}} 0 L {{width}} {{height}} L {{width*2/3}} {{height}} L {{width*2/3}} {{height/2}} L {{width/3}} {{height/2}} L {{width/3}} {{height}} L 0 {{height}} Z\\\"/>\"\n }\n ]\n }\n ]\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********\n\n## Label location[](#label-location)\n\nBy default, an edge label will be assigned a location of `0.5` - meaning it will be halfway along the edge path. You can change this by providing a `labelLocation`:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = {\n nodes:[\n {id:\"1\",x:50,y:50,type:\"diamond\"},\n {id:\"2\",x:250,y:50,type:\"rectangle\"}\n ],\n edges:[\n {source:\"1\",target:\"2\",data:{label:\"A Label\"}}\n ]\n}\n \n const options = {\n edges: {\n showLabels: true,\n labelLocation: 0.25\n },\n shapes: [\n {\n id: \"basic\",\n name: \"Basic\",\n shapes: [\n {\n type: \"rectangle\",\n label: \"Rectangle\",\n template: \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"{{width}}\\\" height=\\\"{{height}}\\\"/>\"\n },\n {\n type: \"rounded-rectangle\",\n label: \"Rounded Rectangle\",\n template: \"<rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"{{width}}\\\" height=\\\"{{height}}\\\" rx=\\\"{{width/10}}\\\"/>\"\n },\n {\n type: \"ellipse\",\n label: \"Ellipse\",\n template: \"<ellipse cx=\\\"{{width/2}}\\\" cy=\\\"{{height/2}}\\\" rx=\\\"{{width/2}}\\\" ry=\\\"{{height/2}}\\\"/>\"\n },\n {\n type: \"diamond\",\n label: \"Diamond\",\n square: true,\n template: \"<polygon points=\\\"{{width/2}} 0 {{width}} {{height/2}} {{width/2}} {{height}} 0 {{height /2}}\\\"/>\"\n },\n {\n type: \"isosceles-triangle\",\n label: \"Isosceles Triangle\",\n template: \"<polygon points=\\\"{{width/2}} 0 {{width}} {{height}} 0 {{height}}\\\"/>\"\n },\n {\n type: \"inverted-isosceles-triangle\",\n label: \"Inverted Isosceles Triangle\",\n template: \"<polygon points=\\\"{{width/2}} {{height}} {{width}} 0 0 0\\\"/>\"\n },\n {\n type: \"right-triangle\",\n label: \"Right Triangle\",\n template: \"<polygon points=\\\"0 0 0 {{height}} {{width}} {{height}}\\\"/>\"\n },\n {\n type: \"label\",\n label: \"Label\",\n icon: \"<svg:svg viewBox=\\\"0 0 100 100\\\"><svg:rect x=\\\"10\\\" y=\\\"10\\\" width=\\\"80\\\" height=\\\"80\\\" rx=\\\"5\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-dasharray=\\\"8,4\\\" opacity=\\\"0.6\\\"/><svg:path d=\\\"M 35 75 L 48 30 L 52 30 L 65 75 M 40 62 L 60 62\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/></svg:svg>\",\n template: \"<g>\n<r-if test=\\\"!text\\\">\n<svg:rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"{{width}}\\\" height=\\\"{{height}}\\\" stroke=\\\"#888\\\" stroke-dasharray=\\\"2\\\" stroke-width=\\\"1\\\" fill=\\\"{{'transparent'}}\\\"/>\n</r-if>\n<svg:rect x=\\\"0\\\" y=\\\"0\\\" width=\\\"{{width}}\\\" height=\\\"{{height}}\\\" stroke=\\\"none\\\" fill=\\\"{{fill || 'transparent'}}\\\"/>\n<!-- if scaled not set default to true -->\n<r-if test=\\\"!!scaled\\\">\n <svg:text dominant-baseline=\\\"hanging\\\" stroke=\\\"none\\\" fill=\\\"{{color}}\\\" textLength=\\\"{{width}}\\\" lengthAdjust=\\\"spacingAndGlyphs\\\" font-size=\\\"{{height}}\\\" font-style=\\\"{{fontStyle}}\\\">{{text}}</svg:text>\n</r-if>\n<!-- if scaled set explicitly to false do not scale -->\n<r-if test=\\\"scaled === false\\\">\n <svg:text dominant-baseline=\\\"hanging\\\" stroke=\\\"none\\\" fill=\\\"{{color}}\\\" font-size=\\\"{{fontSize}}\\\" font-style=\\\"{{fontStyle}}\\\">{{text}}</svg:text>\n</r-if>\n</g>\",\n payload: {\n text: \"Label\",\n scaled: true\n },\n properties: [\n {\n id: \"fill\",\n label: \"Background Color\",\n type: \"color\",\n defaultValue: \"transparent\"\n },\n {\n id: \"color\",\n label: \"Text Color\",\n type: \"color\",\n defaultValue: \"#000000\"\n },\n {\n id: \"text\",\n label: \"Text\",\n type: \"string\",\n defaultValue: \"Text\"\n },\n {\n id: \"scaled\",\n label: \"Scaled\",\n type: \"boolean\",\n defaultValue: true\n }\n ]\n },\n {\n type: \"inverted-right-triangle\",\n label: \"Right Triangle\",\n template: \"<polygon points=\\\"{{width}} {{height}} {{width}} 0 0 {{height}}\\\"/>\"\n },\n {\n type: \"hexagon\",\n label: \"Hexagon (pointy)\",\n square: true,\n template: \"<polygon points=\\\"{{width/2}} 0 {{width}} {{height*1732/6000}} {{width}} {{height-(height*1732/6000)}} {{width/2}} {{height}} 0 {{height-(height*1732/6000)}} 0 {{height*1732/6000}}\\\"/>\"\n },\n {\n type: \"hexagon-flat\",\n label: \"Hexagon (flat)\",\n square: true,\n template: \"<polygon points=\\\"0 {{height/2}} {{width*1732/6000}} {{height}} {{width-(width*1732/6000)}} {{height}} {{width}} {{height/2}} {{width-(width*1732/6000)}} 0 {{width*1732/6000}} 0\\\"/>\"\n },\n {\n type: \"octagon\",\n label: \"Octagon\",\n square: true,\n template: \"<polygon points=\\\"{{width * 293 / 1000}} 0 {{width * 707 / 1000}} 0 {{width}} {{height * 293 / 1000}} {{width}} {{height * 707 / 1000}} {{width * 707 / 1000}} {{height}} {{width * 293 / 1000}} {{height}} 0 {{height * 707 / 1000}} 0 {{height * 293 / 1000}}\\\"/>\"\n },\n {\n type: \"pentagon\",\n label: \"Pentagon\",\n square: true,\n template: \"<polygon points=\\\"{{width/2}} 0 {{width}} {{height*343/1000}} {{width*793/1000}} {{height*904/1000}} {{width*206/1000}} {{height*904/1000}} 0 {{height*343/1000}}\\\"/>\"\n },\n {\n type: \"parallelogram\",\n label: \"Parallelogram\",\n template: \"<polygon points=\\\"0 {{height}} {{width/8}} 0 {{width}} 0 {{width * 7 / 8}} {{height}}\\\"/>\"\n },\n {\n type: \"trapezoid\",\n label: \"Trapezoid\",\n template: \"<polygon points=\\\"0 {{height}} {{width/8}} 0 {{width * 7 / 8}} 0 {{width}} {{height}}\\\"/>\"\n },\n {\n type: \"cross\",\n label: \"Cross\",\n template: \"<path d=\\\"M 0 {{height*3/10}} L 0 {{height * 7/10}} L {{width *3/10}} {{ height * 7/10}} L {{width *3/10}} {{height}} L {{width *7/10}} {{height}} L {{width*7/10}} {{height*7/10}} L {{width}} {{height * 7/10}} L {{width}} {{height*3/10}} L {{width *7/10}} {{height*3/10}} L {{width*7/10}} 0 L {{width*3/10}} 0 L {{width*3/10}} {{height*3 /10}} Z\\\"/>\"\n },\n {\n type: \"l-shape-bl\",\n label: \"L Shape (Bottom left)\",\n template: \"<path d=\\\"M 0 0 L 0 {{height}} L {{width}} {{height}} L {{width}} {{height / 2}} L {{width/2}} {{height/2}} L {{width/2}} 0 Z\\\"/>\"\n },\n {\n type: \"l-shape-br\",\n label: \"L Shape (Bottom right)\",\n template: \"<path d=\\\"M {{width}} {{height}} L {{width}} 0 L {{width/2}} 0 L {{width/2}} {{height/2}} L 0 {{height/2}} L 0 {{height}} Z\\\"/>\"\n },\n {\n type: \"l-shape-tl\",\n label: \"L Shape (Top left)\",\n template: \"<path d=\\\"M 0 0 L 0 {{height}} L {{width/2}} {{height}} L {{width/2}} {{height / 2}} L {{width}} {{height/2}} L {{width}} 0 Z\\\"/>\"\n },\n {\n type: \"l-shape-tr\",\n label: \"L Shape (Top right)\",\n template: \"<path d=\\\"M {{width}} {{height}} L {{width}} 0 L 0 0 L 0 {{height/2}} L {{width/2}} {{height/2}} L {{width/2}} {{height}} Z\\\"/>\"\n },\n {\n type: \"u-shape\",\n label: \"U Shape\",\n template: \"<path d=\\\"M 0 0 L 0 {{height}} L {{width}} {{height}} L {{width}} 0 L {{width*2/3}} 0 L {{width*2/3}} {{height/2}} L {{width/3}} {{height/2}} L {{width/3}} 0 Z\\\"/>\"\n },\n {\n type: \"inverted-u-shape\",\n label: \"U Shape (Inverted)\",\n template: \"<path d=\\\"M 0 0 L {{width}} 0 L {{width}} {{height}} L {{width*2/3}} {{height}} L {{width*2/3}} {{height/2}} L {{width/3}} {{height/2}} L {{width/3}} {{height}} L 0 {{height}} Z\\\"/>\"\n }\n ]\n }\n ]\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********\n\nYou can also control this via a `labelLocation` value in your edge's backing data. For example, this edge:\n\n```javascript\n{\n source:\"someNode\",\n target:\"someOtherNode\",\n data:{\n labelLocation:0.25\n }\n}\n\n```\n\nwould instruct VisuallyJs to put the label at 0.25, and you would not need to set `labelLocation` in the edge options.","url":"https://visuallyjs.com/react/docs/diagrams/edges/edge-labels","lib":"react","topic":"diagrams"},"docs/diagrams/edges/markers.md":{"title":"Markers","body":"# Markers\n\nMarkers are overlays that are being used in the specific context of marking the source or target of some edge. `Label` and `Custom` overlays are not supported for markers, but all of the simple shape overlays are.\n\nIn this example we show a `Dot` marker as the source and a `PlainArrow` as the target.\n\n```javascript\nedges:{\n sourceMarker:\"Dot\",\n targetMarker:\"PlainArrow\"\n}\n\n```\n\n**********\n\ninfo\n\n## Location[](#location)\n\nAlthough markers are just overlays, you do not supply a location when specifying a marker - or rather, you do, but implicitly, by the fact that you have identified a marker as a `sourceMarker` (location:0) or a `targetMarker` (location:1). VisuallyJs will automatically set this location and also set `direction:-1` for a target marker.\n\n## Differences to overlays[](#differences-to-overlays)\n\nMarkers are specified with the same syntax as overlays, so what is the difference? There are two:\n\n### Syntax[](#syntax)\n\nThe `sourceMarker` / `targetMarker` syntax is a useful shortcut to having to declare a set of `overlays` and configuring the properties required to set an overlay at the source/target of an edge. It is the difference, for instance, of typing this:\n\n```javascript\nmarkers:{\n sourceMarker:\"Dot\",\n targetMarker:\"PlainArrow\"\n}\n\n```\n\nversus typing this:\n\n```javascript\noverlays:[\n { type:\"Dot\", options:{location:0}},\n { type:\"PlainArrow\", options:{location:1}}\n]\n\n```\n\n### Edge overlap[](#edge-overlap)\n\nWhen an overlay is used as a marker, the path of the edge is adjusted so that it stops at the edge of the marker. An exaggerated example is given below - in this canvas, the edges have a stroke width of 8 pixels, and you can see in the top edge how the edge path intersects the overlays whereas in the bottom edge it does not.\n\n**********","url":"https://visuallyjs.com/react/docs/diagrams/edges/markers","lib":"react","topic":"diagrams"},"docs/diagrams/edges/overlays.md":{"title":"Overlays","body":"# Overlays\n\nOverlays are adornments to connections. There are two types - simple overlays, which are such things as arrows at the end of a line, or a label, etc, and component overlays, in which you can provide a component to use for the overlay.\n\n<!-- -->\n\nIn this canvas we have an edge with 6 [simple overlays](#simple-overlays) - a [Rectangle](#rectangle), a [PlainArrow](#plainarrow), a [Label](#label), a [Diamond](#diamond), a [Dot](#dot), and an [Arrow](#arrow):\n\n**********\n\ninfo\n\n## Location[](#location)\n\nA key concept with overlays is that of their **location**. It refers to some point along the path inscribed by the edge, and it can be specified in one of three ways:\n\n* as a decimal in the range \\[0..1], which indicates some proportional amount of travel along the path inscribed by the edge. The default value of 0.5 is in this form, and it means the default location of an overlay on an edge is a point halfway along the path.\n* as an integer greater than 1, which indicates some absolute number of pixels to travel along the edge from the start point\n* as an integer less than zero, which indicates some absolute number of pixels to travel backwards along the edge from the end point.\n\nThe default location for an overlay is halfway along the path traveled by the connector - `location` is `0.5`. If you specify `location:1`, then the overlay will be at the end of the path; `location:0` puts the overlay at the start.\n\n## Simple Overlays[](#simple-overlays)\n\nVisuallyJs ships with several types of simple overlays:\n\n* **Arrow** - a configurable arrow that is painted at some point along the connector. You can control the length and width of the Arrow, the 'foldback' point - a point the tail points fold back into, and the direction (allowed values are 1 and -1; 1 is the default and means point in the direction of the connection)\n* **Label** - a configurable label that is painted at some point along the connector, either as an SVG element or an HTML element\n* **PlainArrow** - an Arrow shaped as a triangle, with no foldback.\n* **Diamond** - A diamond shaped overlay.\n* **Dot** A circle overlay, with configurable radius\n* **Rectangle** A rectangle overlay, with configurable width and height\n* **Custom** - allows you to create the overlay yourself - your overlay may be any DOM element you like.\n\n`PlainArrow` and `Diamond` are actually just configured instances of the generic `Arrow` overlay (see examples).\n\n### Arrow[](#arrow)\n\nAn arrow with a configurable `foldback` point.\n\nArrowOverlayOptions\n\nOptions for an Arrow overlay.\n\n| Name | Type | Description |\n| ----------- | ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |\n| attributes? | Record\\<string,string> | Optional custom attributes to write to the overlay's element. |\n| cssClass? | string | Optional CSS class(es) to add to the overlay's element. |\n| direction? | number | 1 to point forwards (the default), -1 to point backwards. Only taken into consideration in some overlay types. |\n| events? | Record<[OverlayEvents](),(value:any, event:any) => any> | Optional event handlers to attach to the overlay. |\n| foldback? | number | How far, as a decimal, along the line from head to baseline to fold back into. Defaults to 0.623. |\n| hollow? | boolean | Defaults to false. When true, the arrow is stroked but not filled. |\n| id? | string | Optional ID for the overlay. Can be used to retrieve the overlay from a connection. |\n| length? | number | Length from the head to the baseline. Defaults to 20. |\n| location? | number | Defaults to 0.5. See docs. |\n| paintStyle? | [PaintStyle]() | Optional paint style to use. |\n| visibility? | [OverlayVisibility]() | Whether the overlay is always visible, or only on hover. Defaults to OVERLAY\\_VISIBILITY\\_ALWAYS. |\n| width? | number | Width of the arrow's baseline. Defaults to 20. |\n\n#### Arrow direction[](#arrow-direction)\n\nA point to note is that `location:0` for arrow overlays will not reverse the direction in which the arrow is pointing. To have the arrow point backwards along the path you have to provide a value for `direction`:\n\n```javascript\noverlays:[ \n {\n type:\"Arrow\",\n options:{\n width:10,\n length:15,\n location:0,\n direction:-1\n }\n } \n]\n\n```\n\nThe `direction:-1` here instructs VisuallyJs to draw the arrow painting backwards. There are only two valid values for `direction` - `1` and `-1`. If you provide any other value - or no value - then VisuallyJs will use a value of 1, meaning the arrow points forwards.\n\n### PlainArrow[](#plainarrow)\n\nThis overlay is an extension of `Arrow` with the `foldback` parameter's value fixed to `1`. This results in an arrow with a flat back.\n\n### Diamond[](#diamond)\n\nThis overlay is an extension of `Arrow` with the `foldback` parameter's value fixed to `2`. This results in an arrow shaped like a diamond.\n\n### Dot[](#dot)\n\nThis is a circle, with configurable radius.\n\nDotOverlayOptions\n\nOptions for a Dot overlay\n\n| Name | Type | Description |\n| ----------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| align? | \"center\" \\| \"flush\" | When the overlay is at position 1 or 0 (or is being used a source/target marker), this determines how the dot intersects the vertex. A value of 'flush', which is the default, means a point on the circumference of the dot touches the vertex boundary. A value of 'center' means the dot's center is on the vertex boundary. |\n| attributes? | Record\\<string,string> | Optional custom attributes to write to the overlay's element. |\n| cssClass? | string | Optional CSS class(es) to add to the overlay's element. |\n| direction? | number | 1 to point forwards (the default), -1 to point backwards. Only taken into consideration in some overlay types. |\n| events? | Record<[OverlayEvents](),(value:any, event:any) => any> | Optional event handlers to attach to the overlay. |\n| hollow? | boolean | Defaults to false. When true, the arrow is stroked but not filled. |\n| id? | string | Optional ID for the overlay. Can be used to retrieve the overlay from a connection. |\n| location? | number | Defaults to 0.5. See docs. |\n| paintStyle? | [PaintStyle]() | Optional paint style to use. |\n| radius? | number | Radius of the dot. Defaults to 5. |\n| visibility? | [OverlayVisibility]() | Whether the overlay is always visible, or only on hover. Defaults to OVERLAY\\_VISIBILITY\\_ALWAYS. |\n\n### Rectangle[](#rectangle)\n\nThis is a rectangle, with configurable width and height.\n\nRectangleOverlayOptions\n\nOptions for a Rectangle overlay\n\n| Name | Type | Description |\n| ----------- | ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| align? | \"center\" \\| \"flush\" | When the overlay is at position 1 or 0 (or is being used a source/target marker), this determines how the rectangle intersects the vertex. A value of 'flush', which is the default, means a point on the boundary of the rectangle touches the vertex boundary. A value of 'center' means the rectangle's center is on the vertex boundary. |\n| attributes? | Record\\<string,string> | Optional custom attributes to write to the overlay's element. |\n| cssClass? | string | Optional CSS class(es) to add to the overlay's element. |\n| direction? | number | 1 to point forwards (the default), -1 to point backwards. Only taken into consideration in some overlay types. |\n| events? | Record<[OverlayEvents](),(value:any, event:any) => any> | Optional event handlers to attach to the overlay. |\n| height? | number | Height of the rectangle. Defaults to 10. |\n| hollow? | boolean | Defaults to false. When true, the arrow is stroked but not filled. |\n| id? | string | Optional ID for the overlay. Can be used to retrieve the overlay from a connection. |\n| location? | number | Defaults to 0.5. See docs. |\n| paintStyle? | [PaintStyle]() | Optional paint style to use. |\n| rotate? | boolean | Whether or not to rotate the rectangle so that it is always perpendicular to the connector path. Defaults to false. |\n| visibility? | [OverlayVisibility]() | Whether the overlay is always visible, or only on hover. Defaults to OVERLAY\\_VISIBILITY\\_ALWAYS. |\n| width? | number | Width of the rectangle. Defaults to 10. |\n\n### Label[](#label)\n\nLabelOverlayOptions\n\nOptions for a label overlay\n\n| Name | Type | Description |\n| ----------------------- | ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |\n| attributes? | Record\\<string,string> | Optional custom attributes to write to the overlay's element. |\n| cssClass? | string | Optional CSS class(es) to add to the overlay's element. |\n| direction? | number | 1 to point forwards (the default), -1 to point backwards. Only taken into consideration in some overlay types. |\n| events? | Record<[OverlayEvents](),(value:any, event:any) => any> | Optional event handlers to attach to the overlay. |\n| font? | [FontSpec]() | Optional spec for the font to use on this label. |\n| id? | string | Optional ID for the overlay. Can be used to retrieve the overlay from a connection. |\n| label | string \\| Function | String, or a function returning a string, for the label. |\n| labelLocationAttribute? | string | Optional name of the attribute that identifies this overlay's location on the path. Defaults to `location`. |\n| location? | number | Defaults to 0.5. See docs. |\n| useHTMLElement? | boolean | Whether or not to use an HTML element. Defaults to false (uses an SVG element) |\n| visibility? | [OverlayVisibility]() | Whether the overlay is always visible, or only on hover. Defaults to OVERLAY\\_VISIBILITY\\_ALWAYS. |\n\nThe `label` for a label overlay can be a string or a function, but in practice with VisuallyJs you'll generally be defining labels as strings, as the values presented to the renderer are extracted from the JSON backing data for each edge.\n\n#### SVG vs HTML elements[](#svg-vs-html-elements)\n\nBy default, regardless of whether or not the container is an SVG element, a label overlay will be rendered as an SVG element. This is the most memory efficient and also allows a label to be printed by an SVG exporter. You can instruct VisuallyJs to use an HTML element via the `useHTMLElement` option for the label.\n\n### Custom[](#custom)\n\nThe custom overlay allows you to create your own overlays, which VisuallyJs will position for you. You need to implement one method - `create(component)` - which is passed the component on which the overlay is located as an argument, and which returns either a DOM element or a valid selector from the underlying library:\n\n```javascript\n\n overlays:[\n {\n type:\"Custom\"\n options:{\n create:(component) => {\n const d = document.createElement(\"select\")\n d.innerHTML = \"<option value='foo'>foo</option><option value='bar'>bar</option>\"\n return d\n },\n location:0.7,\n id:\"customOverlay\"\n }\n }\n ]\n\n```\n\nHere we have created a select box with a couple of values, assigned to it the id of 'customOverlay' and placed it at location 0.7. Note that the 'id' we assigned is distinct from the element's id. You can use the id you provided to later retrieve this overlay using the `getOverlay(id)` method on a connection.\n\nnote\n\nA custom overlay is a plain HTML element - you may wish to consider using a component overlay instead.\n\n## Showing/hiding on hover[](#showinghiding-on-hover)\n\nIt is possible to mark some overlay as being only visible when the mouse is hovering over the edge to which it belongs:\n\n<!-- -->\n\n```jsx\nimport { OVERLAY_VISIBILITY_HOVER } from \"@visuallyjs/browser-ui\"\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n edges: {\n overlays: [\n {\n type: \"Label\",\n options: {\n label: \"Hello!\",\n visibility: OVERLAY_VISIBILITY_HOVER\n }\n }\n ],\n paintOutline: true,\n outlineWidth: 30\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\nTry hovering the mouse over the edge path in this example:\n\n**********\n\n<!-- -->\n\ninfo\n\nIn this example we made it easy to hover over the edge by instructing VisuallyJs to paint a 30 pixel transparent connector outline, via the `outlineWidth:30` config.\n\n## React component overlays[](#react-component-overlays)\n\nVisuallyJs supports using React components as overlays.\n\n### Simple example[](#simple-example)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const viewOptions = {\n edges: {\n default: {\n overlays: [\n {\n jsx: (ctx) => <div onClick={() => alert('You clicked ' + ctx.data.label)}>\n I am {ctx.data.label}. Click me.\n </div>\n }\n ]\n }\n }\n}\n return <SurfaceComponent viewOptions={viewOptions}/>\n}\n\n```\n\n**********\n\n### Less Simple Example[](#less-simple-example)\n\nThe previous example demonstrates how the component overlay can display, reactively, the data object for the edge it represents. But we wanted to point out that the overlay has access not only to its edge, but also to the source and target vertices of the edge - again, reactively. So in this canvas below we show two nodes with an overlay on the edge that connects them. The overlay displays the background color of each node, and you can click the nodes to cycle their background color. When you do so, you'll see the overlay update itself too:\n\n**********\n\n#### Discussion[](#discussion)\n\nHow did we do this?\n\n##### Node data[](#node-data)\n\nFirst of all, we declared our nodes like this:\n\n```javascript\n{\n id:\"1\", \n left:50, \n top:50, \n bg:\"blue\" \n}\n\n```\n\n##### Helper functions[](#helper-functions)\n\nWe then wrote a quick helper function to get a random color, and another function which can invoke an update on the model:\n\n```javascript\nconst randomColor = () => `#${Array.from({length:3}, () => Math.floor(Math.random()*255).toString(16)).join(\"\")}`\n\nconst cycle = (ctx, node) => ctx.model.updateNode(node, {bg:randomColor()})\n\n```\n\nThe `cycle` method uses the `updateNode` method on the model to perform the update. `ctx` is passed in from either the node component or the overlay component, and is of type [JsxWrapperProps]().\n\n##### Node component[](#node-component)\n\nOur node component looks like this:\n\n```jsx\nconst NodeComponent = function({ctx}) {\n return <div style={{backgroundColor:ctx.data.bg}}\n onClick={() => cycle(ctx, ctx.obj)}>\n </div>\n}\n\n```\n\nIn this component, `ctx.obj` is the node being drawn. This component extracts `bg` from the node data and uses it for the background color, and binds a click listener, which calls `cycle`, which will result in the node's background colour being updated.\n\n##### Overlay component[](#overlay-component)\n\nOur overlay component looks like this:\n\n```jsx\nconst OverlayComponent = function({ctx}) {\n return <div className=\"advanced-demo-overlay\">\n \n <div style={{backgroundColor:ctx.obj.source.data.bg}} \n onClick={() => cycle(ctx, ctx.obj.source)}/>\n \n <div style={{backgroundColor:ctx.obj.target.data.bg}} \n onClick={() => cycle(ctx, ctx.obj.target)}/>\n \n </div>\n}\n\n```\n\nIn this component, `ctx.obj` is the edge the overlay represents. It has a `source` and `target` member which are the source and target nodes of the edge. This component extracts `bg` from the data of the source and target nodes and uses them for the background color of the two divs, and binds a click listener to each of those, which calls `cycle`, either with the source node or the target node.\n\n##### App component[](#app-component)\n\nOur app looks like this:\n\n```jsx\n<SurfaceComponent viewOptions={{\n nodes:{\n default:{\n jsx:(ctx) => <NodeComponent ctx={ctx}/>\n }\n }, \n edges:{\n default:{\n overlays:[\n {\n jsx:(ctx) => <OverlayComponent ctx={ctx}/>\n }\n ]\n }\n }\n}}/>\n\n```","url":"https://visuallyjs.com/react/docs/diagrams/edges/overlays","lib":"react","topic":"diagrams"},"docs/diagrams/edges/overview.md":{"title":"Overview","body":"# Connecting shapes\n\nEdges in a Diagram represent the relationships between nodes and groups. They are highly configurable, supporting various connector types, overlays (like arrows), and markers.\n\n## Configuration[](#configuration)\n\nYou configure the default behavior and appearance of edges in a Diagram using the `edges` section of the `DiagramOptions` interface.\n\n```javascript\nconst diagramOptions = {\n // ... other options\n edges: {\n anchor: \"AutoDefault\", // Default anchor for edges\n connector: { // Default connector type and options\n type: \"Orthogonal\",\n options: {\n cornerRadius: 3\n }\n },\n editable: true, // Whether edges can be edited via the UI\n avoidVertices: true, // Whether edges should avoid overlapping vertices\n allowUnattached: true, // Whether edges can exist without being connected to a target\n propertyMappings: [] // Mappings to drive edge appearance from data\n }\n}\n\n```\n\n### Options[](#options)\n\nThe `edges` section supports the following options:\n\n| Name | Type | Description |\n| ------------------ | ---------------------- | -------------------------------------------------------------------------------------- |\n| `anchor` | `AnchorSpec` | The default anchor(s) to use for edges. |\n| `connector` | `ConnectorSpec` | The default connector type (e.g., \"Orthogonal\", \"Bezier\", \"Straight\") and its options. |\n| `editable` | `boolean` | Whether edges are editable by the user. Defaults to `true`. |\n| `avoidVertices` | `boolean` | If `true`, the connector will attempt to route around vertices. |\n| `allowUnattached` | `boolean` | If `true`, users can drag an edge that isn't connected to a target vertex. |\n| `propertyMappings` | `EdgePropertyMappings` | A set of mappings that define how edge data affects its appearance. |\n| `color` | `string` | Default color for the edges. |\n| `outlineWidth` | `number` | Default width for the edge lines. |\n\n## Linking from Diagram tools[](#linking-from-diagram-tools)\n\nWhen a vertex (node or group) is selected in a Diagram, a set of tools appears around it. One of these tools is the **Link** tool (usually represented by a chain icon or a plus icon with an arrow).\n\nDragging from this tool allows users to create a new edge. You can control whether this tool is available for a specific vertex using the `canLink` method in the [Diagram Mediator](/react/docs/diagrams/controlling-diagram-actions.md).\n\n## Connectors[](#connectors)\n\nConnectors define the path that an edge takes between its source and target.\n\nConnectors are the lines that actually join elements of the UI. They are the visual representation of edges. VisuallyJs has four connector types:\n\n* **Bezier** - a Bezier curve with two control points\n* **Straight** - One or more straight line segments, optionally smoothed or with rounded corners\n* **Orthogonal** - Horizontal/vertical straight line segments, optionally with rounded corners\n* **QuadraticBezier** - a Bezier curve with a single control point\n\ninfo\n\nThe default, if you do not provide a value, is to use the `Straight` connector.\n\n## Overlays and Markers[](#overlays-and-markers)\n\nOverlays are UI elements attached to an edge, such as arrows, labels, or custom shapes. Markers are specific types of overlays that appear at the start or end of an edge.\n\nIn Diagrams, you typically use `propertyMappings` to define which overlays or markers should be visible based on the edge's data.\n\n## Unattached Edges[](#unattached-edges)\n\nBy default, edges in a Diagram must be connected to both a source and a target, but unattached edges are supported and can be enabled. You can toggle this behavior using the `allowUnattached` option.\n\nWhen `allowUnattached` is set to `true`, users can drag either end of an edge off a shape and leave it in whitespace. This is useful for creating diagrams where some connections might be incomplete or for visually indicating flow that doesn't yet have a target.\n\n**********\n\n## Edge Geometry and Editors[](#edge-geometry-and-editors)\n\nWhen `editable` is set to `true` in the `edges` configuration, users can modify the path of an edge. VisuallyJs automatically selects the appropriate editor based on the connector type.\n\nVisuallyJs supports editing the path of edges for each of the different [connector types](/react/docs/diagrams/edges/connectors.md) that VisuallyJs ships with. The selection of the appropriate editor tool is managed automatically by VisuallyJs.\n\n## Setup[](#setup)\n\nIn a diagram, edge path editing is enabled by default (as long as the diagram is not marked `editable:false`). If you want to disable path editing, without marking the diagram readonly, you need to set the `editable` flag in the `edges` section of your render options:\n\n<!-- -->\n\nPath editing begins when the user taps on an edge, and stays active until they click on whitespace, or perform some other operation such as editing a cell,\n\nEach editor offers a different interface for working with path edits.\n\n## Orthogonal editors[](#orthogonal-editors)\n\nThe orthogonal editor draws a handle on each segment of an edge, which can be dragged at 90 degrees to the direction of travel of the segment, ie. for a vertical segment, you can shift it horizontally, and for a horizontal segment you can shift it vertically.\n\nWhen you are shifting a segment, if you release the mouse at such a point that the segment you just dragged forms a straight line with a previous or subsequent segment, the segments are coalesced into one. If you drag some segment such that an existing segment ceases to be a straight line, the segment is split and new segment is inserted between them.\n\n#### Static anchors[](#static-anchors)\n\nIn this example we use an edge editor to edit the path of some edge whose anchors are at fixed points (in this case, `AnchorLocations.Bottom` and `AnchorLocations.Top`). We've also already called `startEditingPath(..)` on the surface for you:\n\n**********\n\n#### Dynamic anchors[](#dynamic-anchors)\n\nIf the edge you are editing has [dynamic anchors](/react/docs/diagrams/edges/anchors.md#dynamic), the edge editor will draw a placeholder at each end of the edge, which you can drag around to any supported position for the given anchor - here we use the `AutoDefault` dynamic anchor, which is an anchor that has one position on each of the four sides of the element on which it resides:\n\n**********\n\nWhen you start to drag an anchor placeholder, you'll see VisuallyJs adds an element indicating an allowed position to which that anchor can be moved.\n\n#### Continuous anchors[](#continuous-anchors)\n\nIf your edge is using anchor of type `AnchorLocations.Continuous` (which is the default), when you drag an anchor placeholder VisuallyJs will highlight the candidate face for the anchor relocation:\n\n**********\n\n### Avoiding vertices[](#avoiding-vertices)\n\nBy default, the orthogonal connector editor will avoid getting into a situation where either end of the connector intersects the source or target vertex. This is best illustrated with a picture:\n\n\n\ninfo\n\nThis functionality is only applied to the segments at either end of a connector. If you have some connector path that intersects the source or target vertex somewhere in the middle of the path, the path will not be re-routed to avoid the vertex.\n\nIf you want to switch this behaviour off, you can do so in the connector spec:\n\n```javascript\nconnector:{\n type:\"Orthogonal\",\n options:{\n vertexAvoidance:false\n }\n}\n\n```\n\nThis will be the resulting behaviour:\n\n\n\nYour users can still route the connector around in this setup but they'll have to move a lot more segments.\n\n***\n\n## Straight editors[](#straight-editors)\n\nThe straight editor draws a handle at the end of each segment of an edge, which can be dragged in any direction to alter its location. You can split a segment by clicking and holding the mouse at the location you wish to split the segment, and then dragging the new handle.\n\nTo delete a handle, click on it.\n\n#### Static anchors[](#static-anchors-1)\n\nIn this example we use an edge editor to edit the path of some edge whose anchors are at fixed points (in this case, `AnchorLocations.Right` and `AnchorLocations.Top`). We've also already called `startEditingPath(..)` for you:\n\n**********\n\n#### Dynamic anchors[](#dynamic-anchors-1)\n\nIf the edge you are editing has [dynamic anchors](/react/docs/diagrams/edges/anchors.md#dynamic), the edge editor will draw a placeholder at each end of the edge, which you can drag around to any supported position for the given anchor - here we use the `AutoDefault` dynamic anchor, which is an anchor that has one position on each of the four sides of the element on which it resides:\n\n**********\n\nWhen you start to drag an anchor placeholder, you'll see VisuallyJs adds an element indicating an allowed position to which that anchor can be moved.\n\n#### Continuous anchors[](#continuous-anchors-1)\n\nIf your edge is using anchor of type `AnchorLocations.Continuous`, when you drag an anchor placeholder VisuallyJs will highlight the candidate face for the anchor relocation:\n\n**********\n\n### Smoothed connectors[](#smoothed-connectors)\n\nWhen you have `smooth:true` set on your connector, the editor functions slightly differently - the drag handles now represent the location of the control points for the splines that make up the Bezier curve, and when you drag them, the control points are moved accordingly. Also when `smooth` is set, the editor draws a guideline for each segment.\n\n<!-- -->\n\n**********\n\n***\n\n## Bezier editors[](#bezier-editors)\n\nThe bezier editor draws two handles - one for each control point in the connector. They are placed where the control point is, and as you drag them around the control points are updated accordingly.\n\n#### Static anchors[](#static-anchors-2)\n\nIn this example we use an edge editor to edit the path of some edge whose anchors are at fixed points (in this case, `AnchorLocations.Bottom` and `AnchorLocations.Top`). We've also already called `startEditingPath(..)` on the surface for you:\n\n**********\n\n***\n\n## QuadraticBezier editors[](#quadraticbezier-editors)\n\nThe QuadraticBezier editor draws one handle, located at the connector's control point. As you drag the handle around, the connector's control point is updated.\n\n**********\n\n***\n\n## Overlays[](#overlays)\n\nYou can supply a set of overlays to render on an edge for the duration of the edit, for example:\n\n```javascript\n\ndiagram.startEditingPath(someEdge, {\n overlays:[\n {\n type:LabelOverlay.type,\n options:{\n label:\"editing...\",\n location:0.1\n }\n } \n ]\n})\n\n```\n\nWith this call we get a label overlay at location 0.1:\n\n**********\n\n## Delete button[](#delete-button)\n\nThe edge path editor offers a shortcut method to attach a delete button:\n\n```javascript\ndiagram.startEditingPath(someEdge, {\n deleteButton:true\n})\n\n```\n\nThis results in:\n\n**********\n\nThis will delete the edge without prompting the user. If you'd like to hook into the edge deletion, you can provide an `onMaybeDelete` function.\n\n```javascript\ndiagram.selectEdge(someEdge, {\n deleteButton:true,\n onMaybeDelete:(edge, connection, doDelete) => {\n if (confirm(`Delete edge ${edge.id}`)) {\n doDelete()\n }\n }\n})\n\n```\n\n**********\n\nNote that the operation is asynchronous - in the example above we use the windows `prompt` method, but you can invoke the `doDelete` callback at any stage.\n\n## Clearing path edits[](#clearing-path-edits)\n\nEdits made to a path can be cleared via `clearPathEdits` method on the `Diagram` object.\n\n```javascript\nclearPathEdits (edgeOrLink:Edge|DiagramLink):boolean\n\n\n```\n\n### Edge Geometry[](#edge-geometry)\n\nThe `geometry` of an edge is stored in its backing data when it has been edited or when vertex avoidance is active. This geometry consists of the anchor positions and any intermediate segments or control points.\n\n## Edge Mappings[](#edge-mappings)\n\nEdge mappings are a powerful way to drive the visual representation of an edge (its style, overlays, and markers) from the properties in its backing data.\n\nProperty mapping allows you to match specific values for a given property/properties to a set of config options - it's related to the concept of UI States, but it's a \"pull\" rather than \"push\": when you update the model, the UI figures out what config to apply for a given object, rather than you having to tell it.\n\nnote\n\nThis functionality is available only for edges. We are investigating options for how this could be usefully extended to nodes, groups and ports.\n\n### Example[](#example)\n\nThis example is drawn from the Flowchart starter app's source code:\n\n```javascript\n\nimport { ArrowOverlay } from \"@visuallyjs/browser-ui\"\n\nconst ARROW_WIDTH = 5\nconst ARROW_LENGTH = 10\nconst CLASS_DASHED_EDGE = \"some-css-class\"\n\nconst PROPERTY_LINE_STYLE = \"lineStyle\"\n\nconst EDGE_TYPE_SOURCE_ARROW = \"source\"\nconst EDGE_TYPE_TARGET_ARROW = \"target\"\nconst EDGE_TYPE_PLAIN = \"plain\"\nconst EDGE_TYPE_DASHED = \"dashed\"\n\nconst edgeMappings = [\n {\n property:PROPERTY_LINE_STYLE,\n mappings:{\n [EDGE_TYPE_SOURCE_ARROW]:{\n overlays:[\n {\n type:ArrowOverlay.type,\n options:{\n location:0,\n direction:-1,\n width:ARROW_WIDTH,\n Length:ARROW_LENGTH\n }\n } ]\n },\n [EDGE_TYPE_TARGET_ARROW]:{\n overlays:[\n {\n type:ArrowOverlay.type,\n options:{\n location:1,\n width:ARROW_WIDTH,\n length:ARROW_LENGTH\n }\n }\n ]\n },\n [EDGE_TYPE_PLAIN]:{},\n [EDGE_TYPE_DASHED]:{\n cssClass:CLASS_DASHED_EDGE\n }\n }\n }\n]\n\n\n```\n\nEach mapping consists of a property name (or list of names - see below) and a map of values to configs (the specific type of these configs is [EdgeMapping]()). Here we have declared a set of mappings for the property `lineStyle` in the backing data for an edge:\n\n```javascript\n{\n property:PROPERTY_LINE_STYLE,\n mappings: {\n [EDGE_TYPE_SOURCE_ARROW] : {\n ...\n }\n ...\n }\n}\n\n```\n\nSo if you had an edge with this definition:\n\n```javascript\n{\n source: \"1\",\n target: \"2\",\n data:{\n lineStyle:\"source\"\n }\n}\n\n```\n\nThen the corresponding connection would have an Arrow overlay at location 0.\n\n### Updating data[](#updating-data)\n\nWhen an edge is updated, the property mappings are inspected. Any that are no longer valid are removed, and any that are now valid are added:\n\n```javascript\nmodel.updateEdge(someEdge, {\n lineStyle:EDGE_TYPE_DASHED\n})\n\n```\n\nThis would result in the arrow overlay being removed, and `\"some-css-class\"` being added to the connection's class list, because there is a mapping for `EDGE_TYPE_DASHED`:\n\n```javascript\nmappings:{\n \n ... \n \n [EDGE_TYPE_DASHED]:{\n cssClass:CLASS_DASHED_EDGE\n }\n} \n\n```\n\n### Wildcard mappings[](#wildcard-mappings)\n\nYou can use \"\\*\" or `WILDCARD` from `@visuallyjs/browser-ui` as the value for some property, which will instruct the UI that the given config should be applied regardless of the value of the mapped property (as long as it is present, not null):\n\n```javascript\nimport { WILDCARD } from \"@visuallyjs/browser-ui\"\n\n{\n property:\"label\",\n mappings:{\n [WILDCARD]:{\n overlays:[\n {\n type:LabelOverlay.type,\n options:{\n label:\"{{label}}\",\n location:0.5,\n cssClass:\"some-label\"\n }\n }\n ]\n }\n }\n}\n\n```\n\nHere, we have instructed VisuallyJs to show a label whenever an edge's backing data has a `label` property. Incidentally, this specific requirement can actually be neatly handled by [Edge labels](/react/docs/diagrams/edges/edge-labels.md).\n\n### Multiple properties[](#multiple-properties)\n\nYou can map multiple properties instead of just a single property if you need the extra flexibility. For example, these are property mappings for an edge in a conceptual ERD, in which edges between entities and relationships show cardinality, but only at one end. We can model that with two properties:\n\n```javascript\npropertyMappings: [\n {\n property: [\"cardinality\", \"terminus\"],\n mappings:{\n \"one source\": {\n sourceMarker: OneOverlay.type\n },\n \"one target\": {\n targetMarker: OneOverlay.type\n }\n }\n }\n]\n\n```\n\nThen in our dataset we might have edges like this:\n\n```javascript\n[\n { source:\"1\", target:\"2\", data:{ cardinality:\"one\", terminus:\"source\" }},\n { source:\"2\", target:\"3\", data:{ cardinality:\"many\", terminus:\"target\" }}\n]\n\n```\n\nThe important point to note in the example mapping above is that the order of the keys must be reflected in the mapping keys: we declare `[\"cardiinality\", \"terminus\"]` as our properties, and our mapping keys are `\"one source\"` and `\"one target\"`, ie. the values to match are in the same order as the property keys.\n\n### Examples[](#examples)\n\n#### Flowchart Starter App[](#flowchart-starter-app)\n\nIn the Flowchart starter app, edge mappings are used to switch between different arrow configurations and line styles (plain or dashed).\n\n```typescript\nexport default function edgeMappings(): EdgePropertyMappings {\n return [\n {\n property: \"lineStyle\",\n mappings: {\n \"plain\": { },\n \"dashed\": {\n dashArray: \"2\"\n }\n }\n },\n {\n property: \"markers\",\n mappings: {\n \"source\": {\n overlays: [\n { type: ArrowOverlay.type, options: { location: 0, direction: -1 } }\n ]\n },\n \"target\": {\n overlays: [\n { type: ArrowOverlay.type, options: { location: 1 } }\n ]\n }\n }\n }\n ]\n}\n\n```\n\n#### BPMN Starter App[](#bpmn-starter-app)\n\nThe BPMN starter app uses edge mappings to distinguish between sequence flows and message flows, applying different markers and dash patterns.\n\n```javascript\nexport default function getFlowTypes() {\n return [\n {\n property: \"type\",\n mappings: {\n \"sequence\": {\n targetMarker: {\n type: \"PlainArrow\",\n options: { location: 1 }\n }\n },\n \"message\": {\n dashArray: \"3\",\n targetMarker: {\n type: \"PlainArrow\",\n options: { hollow: true }\n },\n sourceMarker: {\n type: \"Dot\",\n options: { radius: 6, hollow: true }\n }\n }\n }\n }\n ]\n}\n\n```","url":"https://visuallyjs.com/react/docs/diagrams/edges/overview","lib":"react","topic":"diagrams"},"docs/diagrams/edges/path-editing.md":{"title":"Path Editing","body":"# Editing edge paths\n\nVisuallyJs supports editing the path of edges for each of the different [connector types](/react/docs/diagrams/edges/connectors.md) that VisuallyJs ships with. The selection of the appropriate editor tool is managed automatically by VisuallyJs.\n\n## Setup[](#setup)\n\nIn a diagram, edge path editing is enabled by default (as long as the diagram is not marked `editable:false`). If you want to disable path editing, without marking the diagram readonly, you need to set the `editable` flag in the `edges` section of your render options:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n edges: {\n editable: false\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nPath editing begins when the user taps on an edge, and stays active until they click on whitespace, or perform some other operation such as editing a cell,\n\nEach editor offers a different interface for working with path edits.\n\n## Orthogonal editors[](#orthogonal-editors)\n\nThe orthogonal editor draws a handle on each segment of an edge, which can be dragged at 90 degrees to the direction of travel of the segment, ie. for a vertical segment, you can shift it horizontally, and for a horizontal segment you can shift it vertically.\n\nWhen you are shifting a segment, if you release the mouse at such a point that the segment you just dragged forms a straight line with a previous or subsequent segment, the segments are coalesced into one. If you drag some segment such that an existing segment ceases to be a straight line, the segment is split and new segment is inserted between them.\n\n#### Static anchors[](#static-anchors)\n\nIn this example we use an edge editor to edit the path of some edge whose anchors are at fixed points (in this case, `AnchorLocations.Bottom` and `AnchorLocations.Top`). We've also already called `startEditingPath(..)` on the surface for you:\n\n**********\n\n#### Dynamic anchors[](#dynamic-anchors)\n\nIf the edge you are editing has [dynamic anchors](/react/docs/diagrams/edges/anchors.md#dynamic), the edge editor will draw a placeholder at each end of the edge, which you can drag around to any supported position for the given anchor - here we use the `AutoDefault` dynamic anchor, which is an anchor that has one position on each of the four sides of the element on which it resides:\n\n**********\n\nWhen you start to drag an anchor placeholder, you'll see VisuallyJs adds an element indicating an allowed position to which that anchor can be moved.\n\n#### Continuous anchors[](#continuous-anchors)\n\nIf your edge is using anchor of type `AnchorLocations.Continuous` (which is the default), when you drag an anchor placeholder VisuallyJs will highlight the candidate face for the anchor relocation:\n\n**********\n\n### Avoiding vertices[](#avoiding-vertices)\n\nBy default, the orthogonal connector editor will avoid getting into a situation where either end of the connector intersects the source or target vertex. This is best illustrated with a picture:\n\n\n\ninfo\n\nThis functionality is only applied to the segments at either end of a connector. If you have some connector path that intersects the source or target vertex somewhere in the middle of the path, the path will not be re-routed to avoid the vertex.\n\nIf you want to switch this behaviour off, you can do so in the connector spec:\n\n```javascript\nconnector:{\n type:\"Orthogonal\",\n options:{\n vertexAvoidance:false\n }\n}\n\n```\n\nThis will be the resulting behaviour:\n\n\n\nYour users can still route the connector around in this setup but they'll have to move a lot more segments.\n\n***\n\n## Straight editors[](#straight-editors)\n\nThe straight editor draws a handle at the end of each segment of an edge, which can be dragged in any direction to alter its location. You can split a segment by clicking and holding the mouse at the location you wish to split the segment, and then dragging the new handle.\n\nTo delete a handle, click on it.\n\n#### Static anchors[](#static-anchors-1)\n\nIn this example we use an edge editor to edit the path of some edge whose anchors are at fixed points (in this case, `AnchorLocations.Right` and `AnchorLocations.Top`). We've also already called `startEditingPath(..)` for you:\n\n**********\n\n#### Dynamic anchors[](#dynamic-anchors-1)\n\nIf the edge you are editing has [dynamic anchors](/react/docs/diagrams/edges/anchors.md#dynamic), the edge editor will draw a placeholder at each end of the edge, which you can drag around to any supported position for the given anchor - here we use the `AutoDefault` dynamic anchor, which is an anchor that has one position on each of the four sides of the element on which it resides:\n\n**********\n\nWhen you start to drag an anchor placeholder, you'll see VisuallyJs adds an element indicating an allowed position to which that anchor can be moved.\n\n#### Continuous anchors[](#continuous-anchors-1)\n\nIf your edge is using anchor of type `AnchorLocations.Continuous`, when you drag an anchor placeholder VisuallyJs will highlight the candidate face for the anchor relocation:\n\n**********\n\n### Smoothed connectors[](#smoothed-connectors)\n\nWhen you have `smooth:true` set on your connector, the editor functions slightly differently - the drag handles now represent the location of the control points for the splines that make up the Bezier curve, and when you drag them, the control points are moved accordingly. Also when `smooth` is set, the editor draws a guideline for each segment.\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n edges: {\n editable: true,\n connector: {\n type: \"Straight\",\n options: {\n smooth: true\n }\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********\n\n***\n\n## Bezier editors[](#bezier-editors)\n\nThe bezier editor draws two handles - one for each control point in the connector. They are placed where the control point is, and as you drag them around the control points are updated accordingly.\n\n#### Static anchors[](#static-anchors-2)\n\nIn this example we use an edge editor to edit the path of some edge whose anchors are at fixed points (in this case, `AnchorLocations.Bottom` and `AnchorLocations.Top`). We've also already called `startEditingPath(..)` on the surface for you:\n\n**********\n\n***\n\n## QuadraticBezier editors[](#quadraticbezier-editors)\n\nThe QuadraticBezier editor draws one handle, located at the connector's control point. As you drag the handle around, the connector's control point is updated.\n\n**********\n\n***\n\n## Overlays[](#overlays)\n\nYou can supply a set of overlays to render on an edge for the duration of the edit, for example:\n\n```javascript\n\ndiagram.startEditingPath(someEdge, {\n overlays:[\n {\n type:LabelOverlay.type,\n options:{\n label:\"editing...\",\n location:0.1\n }\n } \n ]\n})\n\n```\n\nWith this call we get a label overlay at location 0.1:\n\n**********\n\n## Delete button[](#delete-button)\n\nThe edge path editor offers a shortcut method to attach a delete button:\n\n```javascript\ndiagram.startEditingPath(someEdge, {\n deleteButton:true\n})\n\n```\n\nThis results in:\n\n**********\n\nThis will delete the edge without prompting the user. If you'd like to hook into the edge deletion, you can provide an `onMaybeDelete` function.\n\n```javascript\ndiagram.selectEdge(someEdge, {\n deleteButton:true,\n onMaybeDelete:(edge, connection, doDelete) => {\n if (confirm(`Delete edge ${edge.id}`)) {\n doDelete()\n }\n }\n})\n\n```\n\n**********\n\nNote that the operation is asynchronous - in the example above we use the windows `prompt` method, but you can invoke the `doDelete` callback at any stage.\n\n## Clearing path edits[](#clearing-path-edits)\n\nEdits made to a path can be cleared via `clearPathEdits` method on the `Diagram` object.\n\n```javascript\nclearPathEdits (edgeOrLink:Edge|DiagramLink):boolean\n\n\n```","url":"https://visuallyjs.com/react/docs/diagrams/edges/path-editing","lib":"react","topic":"diagrams"},"docs/diagrams/edges/property-mapping.md":{"title":"Property Mapping","body":"# Property Mapping\n\nProperty mapping allows you to match specific values for a given property/properties to a set of config options - it's related to the concept of UI States, but it's a \"pull\" rather than \"push\": when you update the model, the UI figures out what config to apply for a given object, rather than you having to tell it.\n\nnote\n\nThis functionality is available only for edges. We are investigating options for how this could be usefully extended to nodes, groups and ports.\n\n### Example[](#example)\n\nThis example is drawn from the Flowchart starter app's source code:\n\n```javascript\n\nimport { ArrowOverlay } from \"@visuallyjs/browser-ui\"\n\nconst ARROW_WIDTH = 5\nconst ARROW_LENGTH = 10\nconst CLASS_DASHED_EDGE = \"some-css-class\"\n\nconst PROPERTY_LINE_STYLE = \"lineStyle\"\n\nconst EDGE_TYPE_SOURCE_ARROW = \"source\"\nconst EDGE_TYPE_TARGET_ARROW = \"target\"\nconst EDGE_TYPE_PLAIN = \"plain\"\nconst EDGE_TYPE_DASHED = \"dashed\"\n\nconst edgeMappings = [\n {\n property:PROPERTY_LINE_STYLE,\n mappings:{\n [EDGE_TYPE_SOURCE_ARROW]:{\n overlays:[\n {\n type:ArrowOverlay.type,\n options:{\n location:0,\n direction:-1,\n width:ARROW_WIDTH,\n Length:ARROW_LENGTH\n }\n } ]\n },\n [EDGE_TYPE_TARGET_ARROW]:{\n overlays:[\n {\n type:ArrowOverlay.type,\n options:{\n location:1,\n width:ARROW_WIDTH,\n length:ARROW_LENGTH\n }\n }\n ]\n },\n [EDGE_TYPE_PLAIN]:{},\n [EDGE_TYPE_DASHED]:{\n cssClass:CLASS_DASHED_EDGE\n }\n }\n }\n]\n\n\n```\n\nEach mapping consists of a property name (or list of names - see below) and a map of values to configs (the specific type of these configs is [EdgeMapping]()). Here we have declared a set of mappings for the property `lineStyle` in the backing data for an edge:\n\n```javascript\n{\n property:PROPERTY_LINE_STYLE,\n mappings: {\n [EDGE_TYPE_SOURCE_ARROW] : {\n ...\n }\n ...\n }\n}\n\n```\n\nSo if you had an edge with this definition:\n\n```javascript\n{\n source: \"1\",\n target: \"2\",\n data:{\n lineStyle:\"source\"\n }\n}\n\n```\n\nThen the corresponding connection would have an Arrow overlay at location 0.\n\n### Updating data[](#updating-data)\n\nWhen an edge is updated, the property mappings are inspected. Any that are no longer valid are removed, and any that are now valid are added:\n\n```javascript\nmodel.updateEdge(someEdge, {\n lineStyle:EDGE_TYPE_DASHED\n})\n\n```\n\nThis would result in the arrow overlay being removed, and `\"some-css-class\"` being added to the connection's class list, because there is a mapping for `EDGE_TYPE_DASHED`:\n\n```javascript\nmappings:{\n \n ... \n \n [EDGE_TYPE_DASHED]:{\n cssClass:CLASS_DASHED_EDGE\n }\n} \n\n```\n\n### Wildcard mappings[](#wildcard-mappings)\n\nYou can use \"\\*\" or `WILDCARD` from `@visuallyjs/browser-ui` as the value for some property, which will instruct the UI that the given config should be applied regardless of the value of the mapped property (as long as it is present, not null):\n\n```javascript\nimport { WILDCARD } from \"@visuallyjs/browser-ui\"\n\n{\n property:\"label\",\n mappings:{\n [WILDCARD]:{\n overlays:[\n {\n type:LabelOverlay.type,\n options:{\n label:\"{{label}}\",\n location:0.5,\n cssClass:\"some-label\"\n }\n }\n ]\n }\n }\n}\n\n```\n\nHere, we have instructed VisuallyJs to show a label whenever an edge's backing data has a `label` property. Incidentally, this specific requirement can actually be neatly handled by [Edge labels](/react/docs/diagrams/edges/edge-labels.md).\n\n### Multiple properties[](#multiple-properties)\n\nYou can map multiple properties instead of just a single property if you need the extra flexibility. For example, these are property mappings for an edge in a conceptual ERD, in which edges between entities and relationships show cardinality, but only at one end. We can model that with two properties:\n\n```javascript\npropertyMappings: [\n {\n property: [\"cardinality\", \"terminus\"],\n mappings:{\n \"one source\": {\n sourceMarker: OneOverlay.type\n },\n \"one target\": {\n targetMarker: OneOverlay.type\n }\n }\n }\n]\n\n```\n\nThen in our dataset we might have edges like this:\n\n```javascript\n[\n { source:\"1\", target:\"2\", data:{ cardinality:\"one\", terminus:\"source\" }},\n { source:\"2\", target:\"3\", data:{ cardinality:\"many\", terminus:\"target\" }}\n]\n\n```\n\nThe important point to note in the example mapping above is that the order of the keys must be reflected in the mapping keys: we declare `[\"cardiinality\", \"terminus\"]` as our properties, and our mapping keys are `\"one source\"` and `\"one target\"`, ie. the values to match are in the same order as the property keys.","url":"https://visuallyjs.com/react/docs/diagrams/edges/property-mapping","lib":"react","topic":"diagrams"},"docs/diagrams/edges/removing-edges.md":{"title":"Removing Edges","body":"# Removing edges\n\nThere are a few ways to remove edges in VisuallyJs. On this page we'll discuss edge deletion in the UI, but it's also possible to remove an edge programmatically from a diagram.\n\n## Removing via drag/drop[](#removing-via-dragdrop)\n\nYou can grab an edge near one of its anchors and then drag it off the vertex. In the canvas below we have applied a CSS class to make these zones visible on hover; by default this does not occur (the CSS classes we target are `.vjs-connector-source-drag` and `.vjs-connector-target-drag`).\n\nBy default, a diagram is configured to allow \"unattached\" edges, so the default behaviour when you drag an edge and drop it in whitespace is to just leave it there, unattached. You need to specify `allowUnattached` if you do not want this:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n edges: {\n allowUnattached: false\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********\n\n## Rettaching[](#rettaching)\n\nVisuallyJs's default behaviour is to discard any edges that a user has dropped in whitespace. You can override this via a setting:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n edges: {\n reattach: true\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\nIn this canvas if you drag one end of the edge and drop it in whitespace VisuallyJs will reattach it:\n\n**********\n\n## Disabling detach[](#disabling-detach)\n\nYou can disable detach via mouse/touch events with the `detachable` setting in the `edges` options:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n edges: {\n detachable: false\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\nIn this canvas VisuallyJs will not allow you to detach the edge using the mouse/touch events:\n\n**********\n\nHow, then, could your users delete an edge via the UI? One solution is to specify a **deleteButton**.\n\n## Showing a delete button[](#showing-a-delete-button)\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n edges: {\n deleteButton: true\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********\n\nThe delete button will be assigned a CSS class of `.vjs-edge-delete`.\n\n### Custom CSS class[](#custom-css-class)\n\nYou can provide one or more extra classes to set on the delete button via the `deleteButtonClass` property:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n edges: {\n deleteButton: true,\n deleteButtonClass: \"fooo bar etc\"\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n### Showing on hover only[](#showing-on-hover-only)\n\n`deleteButton` can be specified either as a boolean, or as a constant that specifies its `visibility`. To have a delete button that only appears on hover, for example:\n\n```jsx\nimport { OVERLAY_VISIBILITY_HOVER } from \"@visuallyjs/browser-ui\"\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n edges: {\n detachable: false,\n deleteButton: OVERLAY_VISIBILITY_HOVER\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********\n\n### Managing edge removal[](#managing-edge-removal)\n\nYou may want to manage the removal of some specific edge - perhaps some condition is met in your app that means the edge cannot be removed, or perhaps you want to hit the server to confirm edge deletion first, etc. For that you can use the `deleteConfirm` property:\n\n```jsx\nimport { OVERLAY_VISIBILITY_HOVER } from \"@visuallyjs/browser-ui\"\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n edges: {\n detachable: false,\n deleteButton: OVERLAY_VISIBILITY_HOVER,\n deleteConfirm: (p, proceed) => {\n if(confirm('Delete edge?')) {\n proceed() \n } \n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********\n\nThe argument for `deleteConfirm` should be a function of this type:\n\nEdgeDeleteConfirmationFunction\n\nDefinition of the function you can provide as `deleteConfirm` on an edge definition. VisuallyJs gives you the edge to be possibly deleted and the pointer event that instigated the deletion. If you wish to delete the edge you must invoke the `proceed()` function.\n\n`(params:{\n e:Event,\n edge:Edge\n}, proceed:() => any) => any`\n\nYou are given the edge that is a candidate for deletion, and the event that initiated the deletion. If you wish to confirm the edge removal, you must invoke the `proceed` method.","url":"https://visuallyjs.com/react/docs/diagrams/edges/removing-edges","lib":"react","topic":"diagrams"},"docs/diagrams/edges/styling-edges.md":{"title":"Styling Edges","body":"# Styling edges\n\nThere are a few approaches you can take when it comes to styling your edges - VisuallyJs provides an out of the box mapping from edge data to basic properties such as edge width, color etc, via the concept of [Simple edge styles](#simple-edge-styles). You can also [use CSS](#styling-with-css), or you can map a `PaintStyle` to your edges via a [view](#styling-with-paintstyles) or [in the UI defaults](#styling-with-ui-defaults). That's a lot of choice, so here we present a quick pros and cons for each option:\n\n| Method | Pros | Cons |\n| ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| [CSS](#styling-with-css) | Clean separation of presentation from code. Allows usage of various SVG CSS effects. Allows styling all edges of some type uniformly. | Does not support export to SVG. Does not support styling each edge individually. Does not support path outlines. |\n| [Paint styles](#styling-with-paintstyles) | Allows styling all edges of some type uniformly. Supports export to SVG. Supports path outlines. | Does not support styling each edge individually. |\n| [Simple edge styles](#simple-edge-styles) | Minimal setup. Allows each edge to be styled individually. Seamlessly integrated with update and undo/redo. Supports path outlines. Supports export to SVG. | Each edge needs its own styles declared in the backing data. Limited set of configurable properties. |\n| [UI Defaults](#styling-with-ui-defaults) | Allows configuration of default styles value which will apply, in the absence of some other value, to all edges. Supports export to SVG. Supports path outlines. | Does not support styling each edge individually. Applies to all types (but you can override on a per-type basis via [Paint styles](#styling-with-paintstyles)(. |\n\n### Styling with CSS[](#styling-with-css)\n\nSince VisuallyJs uses SVG to render edges, you can target the artifacts that VisuallyJs adds to the DOM via CSS. VisuallyJs uses a class of `vjs-connector` on the SVG element it uses for each edge, and the edge itself is written as one or more `path` elements inside of that, which each have a class according to their function:\n\n```html\n<svg class=\"vjs-connector\">\n <path d=\"...\" class=\"vjs-connector-outline\"></path>\n <path d=\"...\" class=\"vjs-connector-path\"></path>\n</svg>\n\n```\n\n#### Targeting the edge's SVG element[](#targeting-the-edges-svg-element)\n\nTo target the parent element for some path, for instance to assign `z-index`, you need a rule like this:\n\n```css\n.vjs-connector {\n z-index:50;\n}\n\n```\n\n#### Targeting the SVG path[](#targeting-the-svg-path)\n\nTo target the element used to render the path, you need a rule like this:\n\n```css\n.vjs-connector-path {\n stroke-width:2;\n stroke:cadetblue;\n stroke-dasharray: 2;\n}\n\n```\n\n#### Hover styles[](#hover-styles)\n\nTo change the appearance of an edge on hover, use the `:hover` css meta class:\n\n```css\n.vjs-connector-path:hover {\n stroke:orangered;\n}\n\n```\n\nNote that the above example targets the path element on hover, but you can also target the parent SVG element of course:\n\n```css\n.vjs-connector:hover {\n outline:1px solid orangered;\n}\n\n```\n\n#### Marching ants effect[](#marching-ants-effect)\n\nIt's simple to get this 'marching ants' effect via CSS with VisuallyJs:\n\n##### 1. Define the CSS animation[](#1-define-the-css-animation)\n\nDefine a CSS animation with a single keyframe that sets the dash offset:\n\n```css\n@keyframes dashdraw {\n 0% {\n stroke-dashoffset:10;\n }\n}\n\n```\n\n##### 2. Map the animation to a CSS rule[](#2-map-the-animation-to-a-css-rule)\n\n```css\n.animated-edge {\n stroke-dasharray:5;\n animation: dashdraw .5s linear infinite;\n}\n\n```\n\n##### 3. Use the cssClass property in an edge definition to map to this class (optional)[](#3-use-the-cssclass-property-in-an-edge-definition-to-map-to-this-class-optional)\n\n<!-- -->\n\nWe said that (3) is optional because if you just want to apply it to every edge in your dataset you can change the CSS rule shown in (2) to target every edge:\n\n```css\n.vjs-connector-path {\n stroke-dasharray:5;\n animation: dashdraw .5s linear infinite;\n}\n\n```\n\n#### Selected edges[](#selected-edges)\n\nWhen an edge is in the model's current selection, it has the CSS class `vjs-selected-connection` applied to it. You can target this class to change the appearance of either the connector's parent element:\n\n```css\n.vjs-selected-connection {\n outline:2px solid orangered;\n}\n\n```\n\nor the path element representing the edge:\n\n```css\n.vjs-selected-connection .vjs-connector-path {\n stroke:orangered;\n}\n\n```\n\n### Styling with PaintStyles[](#styling-with-paintstyles)\n\nA `PaintStyle` is an object containing various properties to apply to a given type of edge. The definition is:\n\nPaintStyle\n\nBasic style definition for an edge\n\n| Name | Type | Description |\n| -------------- | ------------------------ | ------------------------------------------------------------------------- |\n| dashArray? | string | Definition for stroke pattern |\n| fill? | string | Fill color for the edge. |\n| gradient? | Array<\\[number, string]> | Definition of a linear gradient to apply. Each entry is \\[offset, color]. |\n| outlineStroke? | string | Color for the outline path |\n| outlineWidth? | number | Width of the outline path |\n| stroke? | string | Stroke color for the edge |\n| strokeWidth? | number | Width of the stroke |\n\nAll properties are optional; VisuallyJs will use an default value where properties are not specified. To setup an outline path, you must provide both `outlineStroke` *and* `outlineWidth`.\n\n#### Mapping a PaintStyle in a view[](#mapping-a-paintstyle-in-a-view)\n\nYou can map a `PaintStyle` to some specific edge type inside a view:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const viewOptions = {\n edges: {\n redWithOutline: {\n paintStyle: {\n stroke: \"red\",\n strokeWidth: 3\n }\n }\n }\n}\n return <SurfaceComponent viewOptions={viewOptions}/>\n}\n\n```\n\n#### Mapping a PaintStyle in the UI defaults[](#mapping-a-paintstyle-in-the-ui-defaults)\n\nYou can also set a default paint style via the `defaults` for some surface:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n defaults: {\n paintStyle: {\n stroke: \"red\",\n strokeWidth: 3\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n#### Controlling the hit zone[](#controlling-the-hit-zone)\n\nBy default, VisuallyJs paints a single `path` element for each edge. If you want your users to be able to interact with your edges but your edges have a stroke width of only a couple of pixels, this can be difficult. To manage this with a `paintStyles` we recommend using the `outlineWidth` and `outlineStroke` paint style properties to setup a hit zone:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n defaults: {\n paintStyle: {\n stroke: \"red\",\n strokeWidth: 3,\n outlineStroke: \"transparent\",\n outlineWidth: 2\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nCalculating the outline width\n\nWhen you provide `outlineWidth` and `outlineStroke` properties in a `PaintStyle`, the visible width of the outline is computed as:\n\n`w = strokeWidth + (2 * outlineWidth)`\n\nwhich is to say that the `outlineWidth` value you provide is applied to each side of the connector's path.\n\nIn this example we've used `\"transparent\"` for the outline color, which gives us the expanded hit zone without altering the appearance of each edge. You can, of course, use any color you like.\n\n#### Hover styles[](#hover-styles-1)\n\nYou can also provide a `hoverPaintStyle` property in your view, which VisuallyJs will use to paint the edge when the mouse is hovering over it:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const viewOptions = {\n edges: {\n redWithOutline: {\n paintStyle: {\n stroke: \"red\",\n strokeWidth: 3,\n outlineStroke: \"orangered\",\n outlineWidth: 2\n },\n hoverPaintStyle: {\n stroke: \"green\",\n strokeWidth: 3,\n outlineStroke: \"yellowgreen\",\n outlineWidth: 4\n }\n }\n }\n}\n return <SurfaceComponent viewOptions={viewOptions}/>\n}\n\n```\n\n### Simple edge styles[](#simple-edge-styles)\n\nSimple edge styles allow you to map values from an edge's backing data to its appearance.\n\n#### Supported properties[](#supported-properties)\n\n* **color** A valid CSS color, which will be used to paint the connector\n* **lineWidth** An integer value denoting the width, in pixels, of the connector.\n* **outlineColor** A valid CSS color, which will be used to paint the connector's outline.\n* **outlineWidth** An integer value denoting the width of the connector's outline. Note that this is not added to the `lineWidth` value; this values describes the total width of the outline. For instance, a `lineWidth` of 3 and an `outlineWidth` of 5 would result in a 1 pixel outline on either side of the connector path.\n* **gradient** An array of \\[offset, color] values which will be used to apply a linear gradient to the path. When this is set, `color` is ignored.\n\nNone of these properties are mandatory. VisuallyJs will fall back to its defaults for these via the `paintStyle` mechanism if your edge data does not contain any of these properties.\n\n#### Example[](#example)\n\n<!-- -->\n\nIn this example the edge in our dataset will have a color of \"cadetblue\" and a stroke width of 3 pixels. It will also have an outline of 5 pixels each side, and the color of the outline will be pink. I think we can all agree it will look pretty fetching indeed.\n\nAnd..that's it, basically. There's not much else to it. If you call `updateEdge(...)` with some new values for these properties, the edge will be updated.\n\nLet's render that example from above. We'll render an edge with this backing data:\n\n```javascript\n{\n color:\"cadetblue\",\n lineWidth:3,\n outlineColor:\"pink\",\n outlineWidth:5,\n id:\"edge\" \n}\n\n```\n\n(we gave it an `id` because we want to access it when you press a button in a moment; id is not a mandatory property).\n\n**********\n\nIf you now click this button, we'll set these new values, and you'll see the edge update:\n\n```javascript\nmodel.updateEdge(\"edge\", {\n color:\"black\", \n outlineColor:\"yellow\",\n lineWidth:2,\n outlineWidth:3,\n label:\"New label\"\n})\n\n```\n\nnote\n\nSimple edge styles are switched on by default. If you do not want this behaviour in your app, you can save yourself some CPU cycles by setting `simpleEdgeStyles:false` in your render options.\n\n#### Gradient Example[](#gradient-example)\n\n<!-- -->\n\nIn this example the edge in our dataset will have a stroke width of 5 pixels, and will be painted with a linear gradient from \"lightblue\" to \"forestgreen\".\n\nLet's render that example from above. We'll render an edge with this backing data:\n\n```javascript\n{\n gradient:[[0,\"lightblue\"],[100, \"forestgreen\"]],\n lineWidth:5\n}\n\n```\n\n**********\n\n### Styling with UI Defaults[](#styling-with-ui-defaults)\n\nThe UI defaults support a few keys that allow you to configure default paint styles for your edges, and to setup a hit zone for edges that will apply to every edge in your app.\n\n#### Supported properties[](#supported-properties-1)\n\n| Key | Constant | Description |\n| ----------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `paintStyle` | `DEFAULT_KEY_PAINT_STYLE` | A `PaintStyle` object as discussed above, whose values will be used for all edges unless a more specific type mapping is found in the view. Defaults to a stroke width of 2 pixels and a stroke color of `#456`. |\n| `hoverPaintStyle` | `DEFAULT_KEY_HOVER_PAINT_STYLE` | A `PaintStyle` object as discussed above, whose values will be used for all edges when the mouse is hovering over it unless a more specific type mapping is found in the view. Defaults to null. |\n| `paintConnectorOutline` | `DEFAULT_KEY_PAINT_CONNECTOR_OUTLINE` | Defaults to false. When true, VisuallyJs will draw a second path underneath each edge, with, by default, a transparent stroke. This arrangement is a useful way to manage the hit zone for your edges, to make it easier for your users to click/tap on edges. The outline path is assigned a CSS class of `.vjs-connector-outline`, so you can override its transparent stroke via CSS if you wish. |\n| `connectorOutlineWidth` | `DEFAULT_KEY_CONNECTOR_OUTLINE_WIDTH` | Defaults to 10 pixels, but only takes effect if `paintConnectorOutline` is true. NOTE this value defines the total width of the outline path, not, as in the case of the `outlineWidth` property of a `PaintStyle`, the number of pixels to pad the main edge path with. |\n| `connectorOutlineColor` | `DEFAULT_KEY_CONNECTOR_OUTLINE_COLOR` | Defaults to \"transparent\". You can use any valid CSS3 color spec here. |\n\n#### Example[](#example)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n defaults: {\n paintStyle: {\n stroke: \"red\",\n strokeWidth: 3\n },\n hoverPaintStyle: {\n stroke: \"orangered\",\n strokeWidth: 5\n },\n paintConnectorOutline: true,\n connectorOutlineWidth: 15\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n#### Controlling the hit zone[](#controlling-the-hit-zone-1)\n\nAs discussed in the paint style section above, by default, VisuallyJs paints a single `path` element for each edge. If you want your users to be able to interact with your edges but your edges have a stroke width of only a couple of pixels, this can be difficult. To manage this via UI defaults you can use the `paintConnectorOutline` default:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n defaults: {\n paintConnectorOutline: true,\n connectorOutlineWidth: 30\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nIn this example we've instructed VisuallyJs to paint a connector outline on every edge, and we've also used the `connectorOutlineWidth` default to specify we want the outline to be 30 pixels. If you omit this flag VisuallyJs will use a default value of 10 pixels. By default this outline will be transparent, but you can also set `connectorOutlineColor` if you wish:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n defaults: {\n paintConnectorOutline: true,\n connectorOutlineWidth: 20,\n connectorOutlineColor: \"cadetblue\"\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n**********","url":"https://visuallyjs.com/react/docs/diagrams/edges/styling-edges","lib":"react","topic":"diagrams"},"docs/diagrams/edges/unattached-edges.md":{"title":"Unattached Edges","body":"# Unattached edges\n\nIn a diagram, by default, edges may have a `source` and/or `target` vertex, or their source/target may be located in whitespace. We refer to this as an `unattached edge`.\n\n## Configuration[](#configuration)\n\nUnattached edges are switched on by default. To turn them off, set `allowUnattached:false` in your render options:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n edges: {\n allowUnattached: false\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```","url":"https://visuallyjs.com/react/docs/diagrams/edges/unattached-edges","lib":"react","topic":"diagrams"},"docs/diagrams/edges/vertex-avoidance.md":{"title":"Vertex Avoidance","body":"# Vertex avoidance\n\nYou can instruct VisuallyJs to attempt to route edges around vertices, either for all edges in your app or just for some specific type(s) of edge.\n\n## Example[](#example)\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n edges: {\n connector: \"Orthogonal\",\n avoidVertices: true\n },\n grid: {\n size: {\n width: 20,\n height: 20\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********\n\nThe key option being `avoidVertices` in the `edges` config. Internally, vertex avoidance is computed using an A\\* algorithm, which is based upon a grid, and so we do recommend you use a `grid` in your app if you've got `avoidVertices` set. Without a grid set you can sometimes see an effect where a path segment's location changes as you drag an element, and then snaps back to some multiple of the A\\* grid. The A\\* grid has a cell size of 10 pixels and so the best results are obtained from setting your own grid to a multiple of that.\n\n## Path constrainment[](#path-constrainment)\n\nYou can constrain the travel of the path in a few different ways.\n\n### Orthogonal routing[](#orthogonal-routing)\n\nOrthogonal routing constrains path segments to travel either horizontally or vertically, as shown at the top of the page.\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n edges: {\n avoidVertices: true,\n targetMarker: \"Arrow\",\n connector: {\n type: \"Straight\",\n options: {\n constrain: \"orthogonal\"\n }\n }\n },\n zoomToFit: true,\n grid: {\n size: {\n width: 20,\n height: 20\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********\n\n### Any angle[](#any-angle)\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n edges: {\n avoidVertices: true,\n targetMarker: \"Arrow\",\n connector: {\n type: \"Straight\",\n options: {\n constrain: \"none\"\n }\n }\n },\n grid: {\n size: {\n width: 20,\n height: 20\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\nWith this setup path segments can travel at any angle:\n\n**********\n\n### Smooth connectors[](#smooth-connectors)\n\nFor some applications the above can look a little jerky, and so one thing you can do is set `smooth` on your connector, to get that Graphviz effect:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n edges: {\n avoidVertices: true,\n targetMarker: \"Arrow\",\n connector: {\n type: \"Straight\",\n options: {\n smooth: true\n }\n }\n },\n zoomToFit: true,\n grid: {\n size: {\n width: 20,\n height: 20\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********\n\ninfo\n\nStraight connectors with `smooth:true` set are aliased in VisuallyJs to the connector name `Smooth`:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n edges: {\n avoidVertices: true,\n connector: \"Smooth\"\n },\n grid: {\n size: {\n width: 20,\n height: 20\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n### Metro routing[](#metro-routing)\n\n\"Metro\" routing constrains path segments to travel either horizontally, vertically, or at 45 degrees.\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n edges: {\n avoidVertices: true,\n targetMarker: \"Arrow\",\n connector: {\n type: \"Straight\",\n options: {\n constrain: \"metro\"\n }\n }\n },\n zoomToFit: true,\n grid: {\n size: {\n width: 20,\n height: 20\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********","url":"https://visuallyjs.com/react/docs/diagrams/edges/vertex-avoidance","lib":"react","topic":"diagrams"},"docs/diagrams/inspectors.md":{"title":"Inspectors","body":"# Inspectors\n\nAn inspector is a form that can be used to edit the properties of some object, or set of objects, in the VisuallyJs dataset. Inspectors listen to selection events from the underlying model and then draw a suitable UI for editing the selected object(s) based upon the configuration you provide.\n\nIn the canvas below we've setup a simple inspector and selected a vertex to begin with. You can edit the various fields in the form on the left. Note that with the text input, changes are persisted on blur and when the enter key is pressed, but for the textarea changes are only persisted on blur.\n\n<!-- -->\n\n**********\n\n## Setup[](#setup)\n\nCreate a React component that renders an `InspectorComponent`, and pass a function to its body that renders content based on the current selected object.\n\n```jsx\n\nimport { useState } from \"react\"\nimport { InspectorComponent} from \"@visuallyjs/browser-ui-react\"\nimport { Node, Edge } from \"@visuallyjs/browser-ui\"\n\nexport default function MyInspectorComponent(props) {\n\n return <InspectorComponent>\n\n {(current) => {\n\n { current.objectType === Node.objectType &&\n <div className=\"node-inspector\">\n <div>Text</div>\n <input type=\"text\" vjs-att=\"text\" vjs-focus=\"true\"/>\n <div>Fill</div>\n <input type=\"color\" vjs-att=\"fill\"/>\n </div>\n }\n\n { current.objectType === Edge.objectType &&\n <div className=\"edge-inspector\">\n <div>Label</div>\n <input type=\"text\" vjs-att=\"label\"/>\n <div>Color</div>\n <input type=\"color\" vjs-att=\"color\"/>\n </div>\n }\n \n }}\n\n </InspectorComponent>\n}\n \n\n```\n\n## Empty inspector[](#empty-inspector)\n\nTo render something when the inspector has no current selection, pass a function to the `renderEmptyContent` prop:\n\n```jsx\n\nimport { useState } from \"react\"\nimport { InspectorComponent} from \"@visuallyjs/browser-ui-react\"\nimport { Node, Edge } from \"@visuallyjs/browser-ui\"\n\nexport default function MyInspectorComponent(props) {\n\n function nothingSelected() {\n return <h3>Select a node to inspect its properties</h3>\n }\n \n return <InspectorComponent renderEmptyContent={nothingSelected}>\n\n {(current) => {\n ...\n }}\n\n </InspectorComponent>\n}\n \n\n```\n\n<!-- -->\n\n<!-- -->\n\nNow you just need to declare that component in your JSX, ensuring that it's inside a `DiagramComponent` or `DiagramProvider`:\n\n```jsx\n\nimport { DiagramComponent, DiagramProvider} from \"@visuallyjs/browser-ui-react\"\nimport MyInspectorComponent from \"./MyInspector.jsx\"\n\nexport function MyApp() {\nreturn <DiagramProvider>\n<DiagramComponent .../>\n<MyInspectorComponent/>\n</DiagramProvider>\n}\n\n```\n\nThe InspectorComponent is discussed in detail in the reference docs [on this page](/react/docs/reference/InspectorComponent.md).\n\n## Binding data[](#binding-data)\n\nFields in your data objects are bound to HTML elements via an `vjs-att` attribute. For instance, here's the form we use in the example canvas above:\n\n```html\n<input type=\"text\" vjs-att=\"label\">\n<textarea vjs-att=\"description\" rows=\"10\" cols=\"10\"></textarea>\n<select vjs-att=\"someNumber\">\n <option value=\"1\">1</option>\n <option value=\"5\">5</option>\n <option value=\"10\">10</option>\n</select>\n\n```\n\nEach of the `vjs-att` attributes in the HTML above maps to a property in the backing data of the object(s) being inspected:\n\n```javascript\n{\n label:\"My Object\",\n description:\"This is my object, with a label and a description and some number\",\n someNumber:5\n}\n\n```\n\n## Supported input types[](#supported-input-types)\n\nThis is the list of supported input types. We show a simple example for each type, but keep in mind you can use all the available attributes on these in your markup - for instance, for a `number` field, perhaps you want to limit the allowed values. Or you could supply a regular expression to a `text` input, etc.\n\n### Text Input[](#text-input)\n\n```html\n<input type='text' vjs-att=\"someProperty\">\n\n```\n\n### Radio Button[](#radio-button)\n\n```html\n<input type='radio' vjs-att=\"someProperty\" value=\"radioValue\" name=\"someProperty\">\n\n```\n\n### Checkbox(es)[](#checkboxes)\n\n```html\n<input type='checkbox' vjs-att=\"someProperty\">\n\n```\n\nThe inspector supports rendering multiple checkboxes with the same `vjs-att`, for example:\n\n```html\n<div class=\"my-inspector\">\n <input type='checkbox' vjs-att=\"someProperty\" value=\"type1\">\n <input type='checkbox' vjs-att=\"someProperty\" value=\"type2\">\n</div>\n\n```\n\nYou need to be using an array in your data to support this:\n\n```javascript\n{\n id:\"my-vertex\",\n someProperty:[\"type1\", \"type2\"]\n}\n\n```\n\n### Number Input[](#number-input)\n\n```html\n<input type='number' vjs-att=\"someProperty\">\n\n```\n\n### Textarea[](#textarea)\n\n```html\n<textarea vjs-att=\"someProperty\" rows=\"10\" cols=\"5\">\n\n```\n\n### Select[](#select)\n\n```html\n<select vjs-att=\"someProperty\">\n <option value=\"someValue\">Some Value</option>\n <option value=\"someOtherValue\">Some Other Value</option>\n</select>\n\n```\n\n### Color Input[](#color-input)\n\n```html\n<input type='color' vjs-att=\"someProperty\">\n\n```\n\n### Hidden Input[](#hidden-input)\n\n```html\n<input type='hidden' vjs-att=\"someProperty\" value=\"someValue\">\n\n```\n\n## Non-string datatypes[](#non-string-datatypes)\n\nBy default, HTML element values are strings, which may not be ideal for your data model. You can instruct VisuallyJs to cast the value of certain elements to a number, by declaring a `vjs-datatype` attribute in your inspector template:\n\n```html\n<div>\n <select vjs-att=\"threshold\" vjs-datatype=\"integer\">\n <option value=\"5\">5</option>\n <option value=\"10\">10</option>\n <option value=\"15\">15</option>\n </select>\n</div>\n\n```\n\nIn this example, VisuallyJs will attempt to cast the value to an integer. Currently, supported values for `vjs-datatype` are:\n\n* **integer** Cast the value to an integer\n* **float** Cast the value to a float, eg 1.5, 2.0, etc.\n\nThe `vjs-datatype` attribute is supported on:\n\n* `<select.../>`\n* `<input type=\"radio\" .../>`\n* `<input type=\"text\" .../>`\n\nnote\n\nIf you're using an input of type `text` and you want a number, it's probably better to use an input of type `number` - see MDN's discussion [here](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/number).\n\n## Multiple selections[](#multiple-selections)\n\nBy default, an inspector supports selections containing multiple objects. When multiple objects are being edited, the inspector calculates a set of \"common data\", ie. the set of keys for which every object in the inspector has a value. For text inputs and text areas, if every value for some given key is the same across all the managed objects, that value is shown and can be edited, resulting in a change to all the managed objects. Otherwise, if not every value is the same, the text input or text area will display a blank value. If the user types in the input field then that change will be propagated to all the managed objects.\n\nTo switch off multiple selections you can do this:\n\n```jsx\n\nimport { useState } from \"react\"\nimport { InspectorComponent} from \"@visuallyjs/browser-ui-react\"\nimport { Node, Edge } from \"@visuallyjs/browser-ui\"\n\nexport default function MyInspectorComponent(props) {\n\n const [currentType, setCurrentType] = useState('')\n const renderEmptyContainer = () => setCurrentType('')\n \n // a Node, Edge, Group or Port\n const refresh= (obj, cb) => {\n setCurrentType(obj.objectType)\n }\n\n return <InspectorComponent refresh={refresh} \n multipleSelections={false}\n renderEmptyContainer={renderEmptyContainer}>\n ...\n\n </InspectorComponent>\n}\n\n```\n\n<!-- -->\n\nnote\n\nDiagrams are configured to use a selection mode of \\`isolated\\` - meaning that although multiple objects can be edited at once, they must all be of the same type. See the [documentation on selections](/react/docs/apps/model/selections.md) for a discussion of selections.","url":"https://visuallyjs.com/react/docs/diagrams/inspectors","lib":"react","topic":"diagrams"},"docs/diagrams/layouts/absolute.md":{"title":"Absolute","body":"# Absolute Layout\n\n<!-- -->\n\nThis layout, by default, retrieves positioning values from the \\`x\\` and \\`y\\` values in your vertex data and uses these to position the SVG element representing a vertex. However, you can provide your own function to extract appropriate values, should you need to.\n\nIn many diagrams, the positions of the shapes are determined by the users, and so VisuallyJs uses the `Absolute` layout as a default. If you need to render a dataset that a human being has never manipulated, you can use the [ForceDirected layout](./force-directed), which extends the `Absolute` layout and only calculates a position for vertices that do not have values set for their position.\n\nThere are also a number of other layouts you can use. One layout which you may find useful is the [Hierarchy layout](./hierarchy), which lays out shapes in a tree.\n\n## Parameters[](#parameters)\n\nAbsoluteLayoutParameters\n\nConstructor parameters for an AbsoluteLayout.\n\n| Name | Type | Description |\n| ----------------- | -------------------- | -------------------------------------------------------------------------------------------------------------- |\n| absoluteBacked? | boolean | Defaults to false. If true, then the layout will use any position values found in the data for a given vertex. |\n| height? | number | Optional fixed height for the layout. |\n| locationFunction? | [LocationFunction]() | Optional function that, given some vertex, can provide the x/y location of the vertex on the canvas |\n| padding? | [PointXY]() | Optional padding to put around the elements. |\n| width? | number | Optional fixed width for the layout. |\n\n## Calculation of location[](#calculation-of-location)\n\n#### Location Function[](#location-function)\n\nIf you provide a `locationFunction`, it will be passed each vertex and is expected to return a position for the given vertex in the form `{x:number, y:number}`\n\n```javascript\nlocationFunction:(v:Vertex):PointXY =>{\n return {x:node.data.xPosition, y:node.data.yPosition }\n}\n\n```\n\n### Location inside a group[](#location-inside-a-group)\n\nIf a node is a child of a group, when the group performs a layout of its child nodes, it will pass itself as the second argument to the location function:\n\n```javascript\nlocationFunction:(v:Vertex, parent:Group):PointXY =>{\n // perhaps here you want to do something unique to each group\n}\n\n```\n\n`group` is only ever assigned a value during the group layout phase. When processing the layout of nodes and groups, `group` will be null.\n\n## Positioning properties[](#positioning-properties)\n\nFor Surface/Paper UIs the default positioning properties are `left` and `top`, for instance:\n\n```json\n{\n \"id\": \"node1\",\n \"left\": 50,\n \"top\": 250\n}\n\n```\n\nFor Diagram UIs the default positioning properties are `x` and `y`:\n\n```json\n{\n \"id\": \"node1\",\n \"type\": \"process\",\n \"x\": 50,\n \"y\": 250\n}\n\n```","url":"https://visuallyjs.com/react/docs/diagrams/layouts/absolute","lib":"react","topic":"diagrams"},"docs/diagrams/layouts/balloon.md":{"title":"Balloon","body":"# Balloon Layout\n\nThis layout groups vertices into clusters.\n\nThis layout is useful for unstructured data - database schemas, mind maps, graphs, etc. For a given input graph the structure of the layout will always be the same, but this layout does not extend the [Absolute](/react/docs/diagrams/layouts/absolute.md) layout as the [ForceDirected](/react/docs/diagrams/layouts/force-directed.md) layout does, so all vertex placement is decided upon by the layout.\n\n## Parameters[](#parameters)\n\nBalloonLayoutParameters\n\nConstructor parameters for a Balloon layout.\n\n| Name | Type | Description |\n| ----------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| absoluteBacked? | boolean | Defaults to false. If true, then the layout will use any position values found in the data for a given vertex. |\n| getChildEdges | [ChildEdgesFunction]() | The function that retrieves child edges for a given vertex. This function defines how the<br />layout walks your data model to generate the output. |\n| getChildVertices? | [HierarchicalLayoutChildVerticesFunction<]()[Vertex]()> | Optional function used to determine the edges to traverse to find children from some node |\n| getRootNode? | (dataSource:[DataSource]()) => Array<[Vertex]()> | Optional. A function that is given the data source instance as argument and is expected to return either a<br />single node/group, or an array of nodes/groups, to use as the root(s) for the layout |\n| groupPadding? | number | Minimum distance between a group of vertices and its neighbours. Defaults to 100 pixels. |\n| height? | number | Optional fixed height for the layout. |\n| ignoreLoops? | boolean | Defaults to true. If a loop is found during the layout it is usually ignored, unless this is set to true. |\n| ignorePorts? | boolean | Defaults to false, meaning that ports are taken into account when figuring the list of edges from some vertex.<br />If you set this to `true`, ports will be ignored and the layout will only consider edges connected directly to<br />each vertex. |\n| locationFunction? | [LocationFunction]() | Optional function that, given some vertex, can provide the x/y location of the vertex on the canvas |\n| padding? | [PointXY]() | Optional padding to put around the elements. |\n| rootNode? | Array<[Vertex]()> | Optional. Defines the nodes/groups to use as the root of the tree. These may be provided as an array of either a<br />node/group id or a node/group object. If this parameter is not specified and multipleRoots is not false then the<br />layout uses the result(s) of the `getRootNode` function; otherwise it uses the first node/group found in the<br />dataset. |\n| width? | number | Optional fixed width for the layout. |\n\n## Example[](#example)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { BalloonLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: BalloonLayout.type\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n## Behaviour after relayout[](#behaviour-after-relayout)\n\nA relayout will generate the exact same arrangement of vertices, since this layout is deterministic. But any changes to node/group dimensions will be taken into account.\n\n## Behaviour after refresh[](#behaviour-after-refresh)\n\nA refresh will generate the exact same arrangement of nodes/groups, since this layout is deterministic. But any changes to node/group dimensions will be taken into account.","url":"https://visuallyjs.com/react/docs/diagrams/layouts/balloon","lib":"react","topic":"diagrams"},"docs/diagrams/layouts/circular.md":{"title":"Circular","body":"# Circular Layout\n\nArranges all the nodes/groups in the model into a circle, with a radius sufficiently large that no two nodes/groups overlap.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { CircularLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: CircularLayout.type\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n***\n\n### Parameters[](#parameters)\n\nCircularLayoutParameters\n\nParameters for the circular layout.\n\n| Name | Type | Description |\n| ----------------- | -------------------- | ------------------------------------------------------------------------------------------------------ |\n| centerRoot? | boolean | If true, the first node in the data set will be placed in the center of the circle. Defaults to false. |\n| height? | number | Optional fixed height for the layout. |\n| locationFunction? | [LocationFunction]() | Optional function that, given some vertex, can provide the x/y location of the vertex on the canvas |\n| padding? | [PointXY]() | Optional padding to put around the elements. |\n| width? | number | Optional fixed width for the layout. |\n\n***\n\n### Centering the root node[](#centering-the-root-node)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { CircularLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: CircularLayout.type,\n options: {\n centerRoot: true\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```","url":"https://visuallyjs.com/react/docs/diagrams/layouts/circular","lib":"react","topic":"diagrams"},"docs/diagrams/layouts/column.md":{"title":"Column","body":"# Column Layout\n\nThis is a specialized instance of `GridLayout` with the number of columns fixed to 1.\n\n### Example[](#example)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ColumnLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: ColumnLayout.type\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n### Sorting entries[](#sorting-entries)\n\nYou can provide a `sort` function to the column layout to specify an order in which entries are placed. The layout will then arrange them in the specified order from top to bottom.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ColumnLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: ColumnLayout.type,\n options: {\n sort: (a,b) => parseInt(b.id, 10) - parseInt(a.id, 10)\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nThe `sort` function receives two arguments, `a` and `b`, which are either `Node` or `Group` objects, and it should return a number indicating their relative order.","url":"https://visuallyjs.com/react/docs/diagrams/layouts/column","lib":"react","topic":"diagrams"},"docs/diagrams/layouts/force-directed.md":{"title":"Force Directed","body":"# ForceDirected Layout\n\nThis layout models edges as springs, placing connected elements nearby, and ensuring adequate space between all elements. [Wikipedia](http://en.wikipedia.org/wiki/Force-directed_graph_drawing) has a good introduction to these types of layouts. It is useful for unstructured data - database schemas, mind maps, graphs, etc. Force-directed algorithms initially position nodes with a degree of randomness and so do not ever produce exactly the same result twice (try reloading this page) - for this reason it is recommended that you read the note on \\[refresh vs re-layout]/lib/layouts#refreshvsrelayout)\n\n### Parameters[](#parameters)\n\nForceDirectedLayoutParameters\n\nParameters for the force directed layout\n\n| Name | Type | Description |\n| ----------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| absoluteBacked? | boolean | Defaults to false. If true, then the layout will use any position values found in the data for a given vertex. |\n| height? | number | Optional fixed height for the layout. |\n| iterations? | number | Maximum number of iterations to run. Defaults to 50. Increasing this number may result in a nicer output, at the expense of run time. |\n| locationFunction? | [LocationFunction]() | Optional function that, given some vertex, can provide the x/y location of the vertex on the canvas |\n| padding? | [PointXY]() | Optional padding to put around the elements. |\n| r? | number | The amount of travel to impose on each element every time a repulsion or attraction event occurs during the calculation of the layout. This is expressed as a fraction of the distance the two elements would travel in order to be `spacing` pixels apart. Defaults to 0.25. A value of 1 here may seem desirable but in general will not provide the best results: moving one pair of elements by their ideal amount can negatively affect many others. It is better to provide a fractional value here and allow the layout to compromise. |\n| spacing? | number | Ideal spacing to leave between elements. Defaults to 250px, but this does not mean that elements end up separated by exactly 250px. |\n| width? | number | Optional fixed width for the layout. |\n\n### Example[](#example)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ForceDirectedLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: ForceDirectedLayout.type\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n### Placement of vertices[](#placement-of-vertices)\n\n#### Absolute Backing[](#absolute-backing)\n\nThe `ForceDirected` layout extends [AbsoluteLayout](/react/docs/diagrams/layouts/absolute.md), which means that, by default, the layout will defer to positions that are stored in the backing data for each vertex. This is a very useful feature for the majority of applications: you do not typically want the layout to run if a human being has already taken a look at the data and perhaps moved things around to be more to their liking.\n\n##### Specifying Position[](#specifying-position)\n\nThe default parameters used by `AbsoluteLayout` are, for Surfaces and Papers, `left` and `top`. So for instance you might have these nodes in your data:\n\n```javascript\nnodes:[\n { id:\"1\", left:50, top:150, label:\"One\" },\n { id:\"2\", left:150, top:250, label:\"Two\" }\n]\n\n```\n\nFor Diagrams the default positioning parameters are `x` and `y`.\n\nBy default, the Force Directed layout will honour these values if they are present, rather than processing the nodes.\n\nIf you do not wish to use `left` and `top`, you can provide your own `locationFunction`. This is discussed in the [documentation for the Absolute layout](/react/docs/diagrams/layouts/absolute.md#location-function).\n\n##### Switching off Absolute backing[](#switching-off-absolute-backing)\n\nYou can switch off Absolute backing via the `absoluteBacked` parameter:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ForceDirectedLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: ForceDirectedLayout.type,\n options: {\n absoluteBacked: false\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n### Behaviour after relayout[](#behaviour-after-relayout)\n\nA relayout will generate a brand new arrangement of elements, due to the fact that elements are placed randomly initially.\n\n### Behaviour after refresh[](#behaviour-after-refresh)\n\nA refresh of the layout locks the positions of any vertices that were positioned in a previous run of the layout, and these vertices do not move: only vertices that have not yet been positioned by the layout algorithm will move.\n\n### Fine tuning positioning[](#fine-tuning-positioning)\n\nFor vertices without positioning information, the layout will optimise their placement relative to vertices to which they are connected, and ensure that vertices do not overlap.\n\nWhen placing vertices dynamically, an initial random position is computed for each vertex. The bounding box that limits possible values for this random position is taken to be the size of the viewport in which the layout is being displayed, not the bounds of the dataset. This is to ensure that the new vertex appears somewhere the user can see it. Whilst initial positions are computed to lie within the bounds of the viewport, when the algorithm runs there is no reason that vertices won't be pushed out of the viewport.\n\nThe layout works by alternately pushing apart vertices so they do not overlap, and then pulling together vertices that have one or more edges between them. This is controlled by three parameters:\n\n* **iterations** The maximum number of iterations to run through until accepting the state of the layout as it is. More iterations will typically result in a finer grained output, but will take longer. This defaults to 50.\n\n* **spacing** This is the measure of how much padding you want to see between the vertices. It defaults to 250px. Note that the layout will never result in exactly this much padding between every vertex (unless, perhaps you have a very small number of vertices in the dataset); rather this number is your \"ideal\" padding, and the layout will strive to establish this amount of padding but will be constrained by the number of iterations it is allowed to run for and the complexity of the dataset.\n\n* **r** This is a measure of how far each vertex will be moved when two vertices need to be repelled or attracted. Mathematically, this number is the ratio of the amount of travel applied to each vertex versus the amount of travel that would be applied for the two vertices to be spaced according to the value of `spacing`. It defaults to 0.25. Increasing this number will result in a shorter run time but the quality of the output will be degraded. Reducing this value can improve the quality of the output but you may find you also need to increase the number of iterations you allow the layout to run for.","url":"https://visuallyjs.com/react/docs/diagrams/layouts/force-directed","lib":"react","topic":"diagrams"},"docs/diagrams/layouts/grid.md":{"title":"Grid","body":"# Grid Layout\n\nThis layout arranges elements into a grid. If you do not provide hints, the number of rows and columns is calculated such that the two values are as close to equal as possible. For instance, this dataset has 11 nodes, and is rendered with 3 rows of 3 columns, with the last row having 2 columns.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { GridLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: GridLayout.type\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n### Fixed column/row count[](#fixed-columnrow-count)\n\nYou can fix the number of columns/rows via the `columns` or `rows` option - here we display the same dataset but with 2 columns.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { GridLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: GridLayout.type,\n options: {\n columns: 2\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nnote\n\nIf you supply a fixed value for `columns` and for `rows`, the layout will only honour the `columns` value.\n\n### Sorting entries[](#sorting-entries)\n\nBy default, the order in which entries are placed into the grid depends on the order they are returned from the data source. You can provide a `sort` function to the grid layout to specify an order:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { GridLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: GridLayout.type,\n options: {\n sort: (a,b) => parseInt(b.id, 10) - parseInt(a.id, 10)\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nIn this example we sort based on reverse order of the node ids, so we see node `11` placed first:\n\nThe `sort` function receives two arguments, `a` and `b`, which are either `Node` or `Group` objects, and it should return a number indicating their relative order, just like a standard JavaScript sort function.\n\n### Parameters[](#parameters)\n\nGridLayoutParameters\n\nOptions for the GridLayout.\n\n| Name | Type | Description |\n| -------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| columns? | number | Optional fixed number of columns. By default this is set to -1 - meaning not fixed - which will result in the layout making its best effort at drawing a grid of equal width and height |\n| height? | number | Optional fixed height for the layout. |\n| horizontalAlignment? | [GridLayoutHorizontalAlignment]() | Optional alignment for horizontal placement in cells. Defaults to center. |\n| locationFunction? | [LocationFunction]() | Optional function that, given some vertex, can provide the x/y location of the vertex on the canvas |\n| orientation? | [GridLayoutOrientation]() | Whether to lay out items row first or column first. Additionally, this setting will determine where any extra items are placed if the dataset does not conform to a grid of equal width and height |\n| padding? | [PointXY]() | Optional padding to put around the elements. |\n| rows? | number | Optional fixed number of rows. By default this is set to -1 - meaning not fixed - which will result in the layout making its best effort at drawing a grid of equal width and height. |\n| sort? | (a:[Node]() \\| [Group](), b:[Node]() \\| [Group]()) => number | Optional sort function to run before layout. |\n| verticalAlignment? | [GridLayoutVerticalAlignment]() | Optional alignment for vertical placement in cells. Defaults to center. |\n| width? | number | Optional fixed width for the layout. |","url":"https://visuallyjs.com/react/docs/diagrams/layouts/grid","lib":"react","topic":"diagrams"},"docs/diagrams/layouts/hierarchy.md":{"title":"Hierarchy","body":"# Hierarchy Layout\n\nThe Hierarchy layout positions vertices in a hierarchy, oriented either vertically or horizontally, following a slightly modified version of the 'Sugiyama' method.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { HierarchyLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: HierarchyLayout.type\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n***\n\n### Orientation[](#orientation)\n\nThe layout at the top of this page shows the `horizontal` orientation, which is the default. Here we show the same dataset in the `vertical` orientation:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { HierarchyLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: HierarchyLayout.type,\n options: {\n axis: \"vertical\"\n }\n },\n defaults: {\n anchors: [\n \"Right\",\n \"Left\"\n ]\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n***\n\n### Placement Strategy[](#placement-strategy)\n\nYou can use a few different \"placement strategies\" with the Hierarchy layout. By default, the child elements of some parent are positioned with respect to the center of their parent element (you can see this in the layouts above). This behaviour corresponds to a `placementStrategy` of `parent`.\n\nYou can, instead, instruct the layout to position elements with respect to the layout's main axis, should you wish to, using a `placementStrategy` of `center`, `start` or `end`.\n\nHere we see `placementStrategy:'center'` in operation - each layer is positioned such that its center point lies on the main axis of the layout:\n\n##### Hierarchy layout with placementStrategy<!-- -->:center[](#hierarchy-layout-with-placementstrategy)\n\nIn the next two examples we use `start` and `end`. Note how these roughly correlate to the way `flex-start` and `flex-end` function in a flex layout.\n\n##### Hierarchy layout with placementStrategy<!-- -->:start[](#hierarchy-layout-with-placementstrategy-1)\n\n##### Hierarchy layout with placementStrategy<!-- -->:end[](#hierarchy-layout-with-placementstrategy-2)\n\n### Alignment[](#alignment)\n\nA separate, but related, concept to the `placementStrategy` is that of `alignment`, which instructs the layout how to place child elements with respect to their parent element, and is only used when `placementStrategy` is set to `parent`. Here's the first layout from above, but with `alignment:'start'` set:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { HierarchyLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: HierarchyLayout.type,\n options: {\n alignment: \"start\"\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n### Determining the root node(s)[](#determining-the-root-nodes)\n\nIn the Hierarchy layout there are always one or more \"root\" vertices, which are vertices that are to be placed at the root of the hierarchy. The layout calculates these by looking for vertices that are not the target of any edges. If it finds none, an arbitrary vertex will be used as the initial root. From each root, edges are followed and connected vertices are placed, until there are no more edges to follow. There may be more than one root in a given dataset.\n\nYou can specify a root node by setting it as the `rootNode`:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { HierarchyLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: HierarchyLayout.type,\n options: {\n rootNode: rootNode,\n axis: \"horizontal\"\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nNote that we said \"a\" root node, and not \"the\" root node, as after placing every node connected to your nominated root, the layout will continue to place other root nodes that it has found.\n\n### Edge routing[](#edge-routing)\n\nThe Hierarchy layout can generate routing information for edges, via the `generateRouting` flag:\n\nTo setup edge routing you need 3 things:\n\n* You must be using a `Hierarchy` layout and you need to have `generateRouting:true` in the layout options:\n\n* You must be using the [Straight](/react/docs/diagrams/edges/connectors.md#straight) connector type. This is the default connector type so if you haven't specifically set a connector anywhere you'll be using this.\n\n* You need to enable the [edge routing plugin](/react/docs/diagrams/plugins/edge-routing)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { HierarchyLayout, EdgeRoutingPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: HierarchyLayout.type,\n options: {\n generateRouting: true\n }\n },\n plugins: [\n {\n type: EdgeRoutingPlugin.type\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nA deeper discussion of edge routing can be on the [edge routing plugin page](/react/docs/diagrams/plugins/edge-routing), but to whet your appetite, here's the Hierarchy layout configured to use [orthogonal routing](/react/docs/diagrams/plugins/edge-routing#orthogonal):\n\n***\n\n### Parameters[](#parameters)\n\nHierarchyLayoutParameters\n\nOptional parameters for a Hierarchy layout\n\n| Name | Type | Description |\n| -------------------------------- | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| absoluteBacked? | boolean | Defaults to false. If true, then the layout will use any position values found in the data for a given vertex. |\n| alignment? | [HierarchyLayoutAlignment]() | Optional, defaults to `HierarchyLayoutAlignmentValues.center`. Instructs the layout how to place child nodes with respect to their parent nodes. By default, a group of child nodes is centered on its parent. The layout also supports \"start\" and \"end\" for this value, which work in much the same way as \"flex-start\" and \"flex-end\" do in CSS: for a layout with the root at the top of the tree and the child nodes underneath, a value of \"start\" for align would cause the first child of the root to be placed immediately under the root, with its first child immediately underneath, etc. The remainder of the content would fan out to the right. This option also works in conjunction with invert and axis<!-- -->:HierarchyLayoutAxisValues<!-- -->.vertical. |\n| axis? | [HierarchyLayoutAxis]() | Either `horizontal` (the default, groups of child vertices are laid out in rows) or `vertical` (groups of child vertices are laid out in columns) |\n| gatherUnattachedRoots? | boolean | If true root nodes that do not have children will be positioned adjacent to the last root node that does have children. When false (which is the default), unattached roots are spaced apart so that they do not overlap any child trees. |\n| generateRouting? | boolean | Defaults to false. If true, the layout generates routing information for the channels between layers and edge nodes, and for edge routing. |\n| getRootNode? | () => [AbstractEdgeTerminus]() | Optional function you can provide that will dynamically be invoked to get the root node to use. |\n| height? | number | Optional fixed height for the layout. |\n| invert? | boolean | If true, the layout will be inverted in its perpendicular axis. For instance, if `axis` is \"horizontal\" and `invert` is true, the root nodes of the layout will be placed at the bottom of the layout, and their children will be placed above them. |\n| leavesAtBottom? | boolean | If true, all of the leaf nodes will be placed at the bottom of the layout (or at the right hand side if the axis is `vertical`) |\n| locationFunction? | [LocationFunction]() | Optional function that, given some vertex, can provide the x/y location of the vertex on the canvas |\n| maxIterations? | number | Maximum number of iterations to run. Defaults to 24. |\n| maxIterationsWithoutImprovement? | number | Number of iterations to try rearranging the graph without an improvement in legibility before accepting the current state. Defaults to 2. |\n| padding? | [PointXY]() | Optional padding to put around the elements. |\n| placementStrategy? | PlacementStageStrategy | The strategy to use when placing vertices. Default is 'center', meaning every row is centered around the axis orthogonal to the axis in which the vertices are laid out. |\n| rootNode? | any | Optional node to use as the root. If this is not provided the layout calculates the best candidate based upon incoming and outgoing edges for each vertex. |\n| width? | number | Optional fixed width for the layout. |","url":"https://visuallyjs.com/react/docs/diagrams/layouts/hierarchy","lib":"react","topic":"diagrams"},"docs/diagrams/layouts/overview.md":{"title":"Overview","body":"# Layouts\n\nA core piece of functionality offered by the VisuallyJs UI is support for layouts - a means to control the positioning of the vertices in your application.\n\nThe default layout used is the [Absolute layout](/react/docs/diagrams/layouts/absolute.md).\n\n## Applying a layout[](#applying-a-layout)\n\n<!-- -->\n\nTo apply a layout to an app, supply the spec for the layout in your render options:\n\n```jsx\nimport { ForceDirectedLayout } from \"@visuallyjs/browser-ui\"\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n layout: {\n type: ForceDirectedLayout.type,\n options: {\n spacing: 150\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\nThe contents of `options` depend on the specific layout you are configuring.\n\n## Available layouts[](#available-layouts)\n\nThe available layouts are:\n\n* [Absolute](/react/docs/diagrams/layouts/absolute.md) This layout positions vertices dependent on values in each vertex's backing data. For many applications in which the position of vertices is under the control of a user, this layout is a good choice. It can be combined with other layouts, such as the ForceDirected layout, to implement a scheme whereby vertices untouched by a user are placed automatically and vertices touched by a user are placed wherever the user chose.\n\n* [ForceDirected](/react/docs/diagrams/layouts/force-directed.md) Positions vertices in an optimum position relative to vertices to which they are connected. This layout is an extension of the Absolute layout, which can be instructed to honour user-supplied values for vertices if present.\n\n* [Balloon](/react/docs/diagrams/layouts/balloon.md) This layout groups vertices into clusters. This is a useful layout for certain types of unstructured data such as mind maps.\n\n* [Hierarchy](/react/docs/diagrams/layouts/hierarchy.md) Positions vertices in a hierarchy, oriented either vertically or horizontally. The classic use cases for this layout are such things as a family tree or an org chart.\n\n* [Circular](/react/docs/diagrams/layouts/circular.md) Arranges vertices instance into a circle, with a radius sufficiently large that no two vertices overlap.\n\n* [Grid](/react/docs/diagrams/layouts/grid.md) Arranges vertices into a grid, optionally with restrictions placed on the number of columns or rows.\n\n* [Column](/react/docs/diagrams/layouts/column.md) Arranges vertices into a column - a specialized instance of the Grid layout.\n\n* [Row](/react/docs/diagrams/layouts/row.md) Arranges vertices into a row - a specialized instance of the Grid layout.","url":"https://visuallyjs.com/react/docs/diagrams/layouts/overview","lib":"react","topic":"diagrams"},"docs/diagrams/layouts/row.md":{"title":"Row","body":"# Row Layout\n\nThis is a specialized instance of `GridLayout` with the number of rows fixed to 1.\n\n### Example[](#example)\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { RowLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: RowLayout.type\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\n### Sorting entries[](#sorting-entries)\n\nYou can provide a `sort` function to the row layout to specify an order in which entries are placed. The layout will then arrange them in the specified order from left to right.\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { RowLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: RowLayout.type,\n options: {\n sort: (a,b) => parseInt(b.id, 10) - parseInt(a.id, 10)\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nThe `sort` function receives two arguments, `a` and `b`, which are either `Node` or `Group` objects, and it should return a number indicating their relative order.","url":"https://visuallyjs.com/react/docs/diagrams/layouts/row","lib":"react","topic":"diagrams"},"docs/diagrams/load-save-export.md":{"title":"Load Save Export","body":"# Load, save and export\n\nGetting data into and out of a VisuallyJs diagram is easy. There are a few different approaches you can use:\n\n* You can [load/save JSON](#loading-json) directly on a Diagram, either as a JS object or via a URL;\n\n* You can supply an initial dataset or URL to load data into certain UI components - read more here]\\(component-load);\n\n* You can [export](#export) a diagram as SVG, PNG or JPEG.\n\nAppending Data\n\nData can be appended via the `load` method, since it does not cause the underlying model to be cleared.\n\n***\n\n## Diagram JSON Syntax[](#diagram-json-syntax)\n\nThe JSON representation of a diagram consists of a JSON object with arrays for `nodes`, `groups` and `edges`. All of these are optional, but of course if you declare an edge then the nodes/groups for that edge must be present in the dataset.\n\nEach node/group definition declares a `type`, which maps it to a shape, as well as, optionally, a `category`, which provides the name of the shape library the shape belongs to. If you diagram has only one shape library installed, `category` is not necessary. Shapes also include positioning information and, optionally, labels, as well as information about the shape's appearance, including such things as fill, outline width, outline color etc.\n\nHere's an example dataset for a flowchart, with 2 shapes and 1 edge:\n\n```javascript\n{\n \"nodes\": [\n { \n \"id\":\"1\", \n \"label\":\"foo\", \n \"type\":\"process\", \n \"category\":\"flowchart\", \n \"width\":80, \n \"height\":60, \n \"x\":50, \n \"y\":60 \n },\n { \n \"id\":\"3\", \n \"name\":\"foo\", \n \"type\":\"rectangle\", \n \"category\":\"basic\", \n \"width\":180, \n \"height\":20, \n \"x\":50, \n \"y\":260, \n \"fill\":\"#565623\" \n }\n ],\n \"edges\":[\n { \"source\":\"1\", \"target\":\"3\" }\n ]\n}\n\n```\n\nThe previous example shows nodes and edges - here's an example BPMN dataset, showing 2 groups, and how the `group` member is used to indicate which group a shape has as its parent:\n\n```javascript\n{\n \"groups\":[\n {\n \"id\":\"g1\",\n \"type\":\"pool\",\n \"category\":\"bpmn2\",\n \"label\":\"BPMN Pool\",\n \"x\":0,\n \"y\":0,\n \"width\":600,\n \"height\":250\n },\n {\n \"id\":\"l1\",\n \"type\":\"lane\",\n \"label\":\"BPMN Lane\",\n \"category\":\"bpmn2\",\n \"x\":0,\n \"y\":0,\n \"width\":600,\n \"height\":250\n }\n ],\n \"nodes\": [\n {\n \"id\":\"1\",\n \"type\":\"gateway\",\n \"category\":\"bpmn2\",\n \"width\":40,\n \"height\":40,\n \"x\":50,\n \"y\":60,\n \"group\":\"l1\"\n },\n {\n \"id\":\"3\",\n \"type\":\"start-event\",\n \"category\":\"bpmn2\",\n \"width\":40,\n \"height\":40,\n \"x\":50,\n \"y\":260,\n \"fill\":\"#565623\",\n \"group\":\"l1\"\n }\n ],\n \"edges\":[\n { \"source\":\"1\", \"target\":\"3\" }\n ]\n}\n\n```\n\n## Loading JSON[](#loading-json)\n\n```javascript\ndiagram.load({\n url:\"http://mydata.com?xyz\"\n});\n\n```","url":"https://visuallyjs.com/react/docs/diagrams/load-save-export","lib":"react","topic":"diagrams"},"docs/diagrams/loading-and-saving-data.md":{"title":"Loading And Saving Data","body":"# Loading and saving data\n\nloading-and-saving-data.mdx","url":"https://visuallyjs.com/react/docs/diagrams/loading-and-saving-data","lib":"react","topic":"diagrams"},"docs/diagrams/magnetizer.md":{"title":"Magnetizer","body":"# Magnetizer\n\nThe magnetizer is a useful piece of VisuallyJs's UI functionality, providing a means to nudge elements around in your UI so that things don't overlap. There are a few different ways to use the magnetizer - you can instruct your layout to apply the magnetizer after the layout is run, or you can use it to manage element dragging. You can also call it programmatically on an ad-hoc basis.\n\n## Layout magnetization[](#layout-magnetization)\n\nAll layouts support the option of switching on magnetization, which is invoked after the layout runs. For some layouts this ability is theoretically of no use, for instance the [Force directed layout](/react/docs/diagrams/layouts/force-directed.md), because in that layout the elements in your UI have already been moved apart by the layout itself. But if you're using, for instance, the [Absolute layout](/react/docs/diagrams/layouts/absolute.md), then there is a chance one or more elements are overlapping.\n\nYou can switch on magnetization in a layout by setting it as a layout option:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { AbsoluteLayout } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n layout: {\n type: AbsoluteLayout.type,\n options: {\n magnetizer: true\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nEach time the layout runs, the magnetizer will be run afterwards.\n\n## Magnetizing after dragging[](#magnetizing-after-dragging)\n\nYou can instruct the magnetizer to run after some vertex has been dragged:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n magnetizer: {\n afterDrag: true\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nTry dragging one element on top of another element in the canvas below. At the end of the drag the magnetizer will run. The element you just dragged will be the \"focus\", and will not move from where you placed it:\n\n**********\n\n#### Repositioning the dragged element[](#repositioning-the-dragged-element)\n\nAs mentioned above, the dragged element will remain stationary if the magnetize is run after a drag. You can change that behaviour, though:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n magnetizer: {\n afterDrag: true,\n repositionDraggedElement: true\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nTry dragging one element on top of another element in the canvas below. At the end of the drag the magnetizer will run, but this time the dragged element will be the one that is moved if there is any overlap:\n\n**********\n\n## Magnetizing while dragging[](#magnetizing-while-dragging)\n\nYou can run the magnetizer while dragging an element by using the `constant` flag:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n magnetizer: {\n constant: true\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nTry dragging node 1 through the gap between nodes 2 and 3 in this canvas - they'll move out of the way as node 1 moves through, and then spring back. Once you release the mouse button, the position of each node is fixed.\n\n**********\n\nThe vertices spring back to their original position in the canvas above because when you switch on `constant` mode, the UI automatically also switches on `trackback`. You can switch off trackback if you wish - see the section [below](#trackback).\n\ntip\n\nIf you have `trackback` switched on, your users can switch if off temporarily while dragging by holding down the `shift` key.\n\n## Trackback[](#trackback)\n\nTo switch off trackback:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n magnetizer: {\n constant: true,\n trackback: false\n }\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nTry dragging node 1 through the gap between nodes 2 and 3 in this canvas - they'll move out of the way as node 1 moves through, but this time they won't spring back:\n\n**********\n\ntip\n\nIf you have switched off `trackback` your users can still switch it on temporarily, by holding down the `shift` key while dragging.\n\n## Adhoc magnetization[](#adhoc-magnetization)\n\nYou can instruct the Surface widget to run the magnetizer over the entire contents of the UI at any time via the `magnetize` method:\n\n<!-- -->\n\nBy default, the magnetizer will use the computed center of all the elements as its origin, and all elements will be pushed away from that point, as in this call:\n\n```javascript\nsurface.magnetize()\n\n```\n\nAn alternative, though, is to supply a vertex that you wish to act as the origin, and which you do not wish to move:\n\n```javascript\nsurface.magnetize(\"nodeId\")\n\n```\n\nHere we passed the ID of some node, but we could also have passed the node itself. The signature of the `magnetize` method is:\n\n```text\nmagnetize(focus?:string|Vertex):void\n\n```\n\n## Setting a vertex position and magnetizing[](#setting-a-vertex-position-and-magnetizing)\n\nAnother feature the Surface offers is the ability to set the position of some element and to immediately magnetize the UI after setting the element's position, using that element as the focus:\n\n```javascript\nsetMagnetizedPosition(element:string|Vertex, x:number, y:number):void\n\n```\n\nThis is effectively the same as:\n\n```javascript\nsurface.setPosition(element, x, y)\nsurface.magnetize(element)\n\n```\n\nThis operation is wrapped in a transaction on the model so if undo is called then every element affected by the magnetize is relocated to its original position.\n\n## Gathering Elements[](#gathering-elements)\n\nThe magnetizer can also gather elements to bring them closer together around some origin. Internally this works by pulling each affected element in on its radial from the origin to the element's center, and then running the magnetizer to nudge everything back out so that nothing overlaps.\n\n```text\ngather(focus?:string|Vertex):void\n\n```\n\nTo gather all the elements in the UI around their computed center, don't supply a focus element:\n\n```text\nsurface.gather()\n\n```\n\nTo gather all the elements in the UI around some focus element:\n\n```text\nsurface.gather(idOrVertex)\n\n```\n\nThis code sets up a surface so that when you click on one of the nodes, the other nodes in the surface are gathered around it:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n zoomToFit: true\n}\n\n const viewOptions = {\n nodes: {\n default: {\n events: {\n tap: (p) => {\n p.ui.gather(p.obj)\n }\n }\n }\n }\n}\n return <SurfaceComponent renderOptions={renderOptions} viewOptions={viewOptions}/>\n}\n\n```\n\nTry clicking one of the nodes in the canvas below. You'll see the other two nodes are gathered in to it. Note that nodes are gathered along a path from the current location to the focus node, and so other nodes may still obstruct their travel. A good example of that is if you click node 1: node 2 is pulled in close to node 1, but node 3 can only travel until it is blocked by node 2.\n\n**********\n\n## All options[](#all-options)\n\nThe Surface offers many options for configuring the magnetizer. The full list is:\n\nMagnetizeOptions\n\nOptions for the magnetize functionality of the UI.\n\n| Name | Type | Description |\n| ------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| afterDrag? | boolean | If true, magnetizer will be run after a vertex is dragged. Defaults to false. |\n| afterGroupCollapse? | boolean | Defaults to false. Indicates the UI should gather nodes around a newly collapsed group |\n| afterGroupExpand? | boolean | Defaults to false. Indicates the UI should magnetize nodes around a newly expanded group |\n| afterGroupGrow? | boolean | Defaults to false. Indicates the UI should magnetize/gather nodes around a newly resized group if the group size was enlarged. |\n| afterGroupResize? | boolean | Defaults to false. Indicates the surface should magnetize/gather nodes around a newly resized group, regardless of whether the group size grew or if it shrunk. This flag is the same as setting `afterGroupShrink` and `afterGroupGrow` |\n| afterGroupShrink? | boolean | Defaults to false. Indicates the UI should magnetize/gather nodes around a newly resized group if the group size was reduced. |\n| afterLayout? | boolean | If true, magnetizer will be run after the layout is run. |\n| constant? | boolean | If true, magnetizer will be run constantly as a vertex is being dragged, pushing other vertices out of the way of the vertex that is being dragged. Defaults to false. By default, `constant` magnetize will also set `trackback:true`, but you can disable that behaviour by setting `trackback:false`. |\n| constrainToViewport? | boolean | If true, vertices moved by the magnetizer will be constrained to move within the visible viewport, which is a function of the current zoom/pan of the UI. Otherwise, vertices will be able to be pushed out of the visible viewport. |\n| padding? | [PointXY]() | How much padding to leave between elements. Defaults to 100 pixels in each axis. |\n| repositionDraggedElement? | boolean | If true, and `afterDrag` is true, when the magnetizer is run after a drag it will be the recently dragged element that moves in precedence to the other elements. By default, the recently dragged element is *not* moved by the magnetize operation - it stays where you dragged it. |\n| trackback? | boolean | Used in conjunction with `constant`: attempts to track any moved elements to their original positions (or as close as possible) once the path is clear, each time the magnetizer runs a sweep. Defaults to true (when `constant` is true). |\n| trackbackThreshold? | number | When in `constant` mode and `trackback` is set, this value specifies a threshold for elements that have been pushed from their original position. Beyond this threshold, the magnetizer will no longer attempt to track an element back. This can be useful in certain situations where the user does want to move an element by pushing it via the magnetizer |","url":"https://visuallyjs.com/react/docs/diagrams/magnetizer","lib":"react","topic":"diagrams"},"docs/diagrams/panning-and-zooming.md":{"title":"Panning And Zooming","body":"# Panning and zooming\n\nVisuallyJs has the smoothest pan/zoom for miles around, and exposes a number of hooks for you to inject your own behaviour.\n\nBy default, the UI is setup to support an infinite canvas. This means the canvas element is positioned `absolute`, we set `overflow:hidden` on the container element (which disables the browser's scrolling mechanism), and the transform origin for the canvas is set to wherever the user last used the mouse or performed a pinch to zoom.\n\n### Panning[](#panning)\n\nIn the default configuration, panning is performed by dragging the canvas with the mouse, or via touch. You can configure pan options via the `panOptions` property:\n\nPanOptions\n\nOptions to control how a user pans the canvas.\n\n| Name | Type | Description |\n| ----------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| axis? | [PanAxis]() | Optional axes in which to constrain pan - 'x', 'y' or 'both'. Defaults to 'both'. |\n| enabled? | boolean | Defaults to true, meaning panning is enabled. |\n| filter? | (el:Element) => boolean | Optional function which is called at the start of panning and can return false to reject pan starting. |\n| useMetaKey? | boolean | Optional, defaults to false. When true, the user must hold down the meta key (ctrl on windows) in order to pan. |\n| wheel? | boolean | Defaults to false, meaning panning works via canvas drag. If you set this to true, the mousewheel (or move events on a touchpad) will pan the canvas. This will also override any zoom wheel flag. |\n\n<!-- -->\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n panOptions: {\n axis: \"x\",\n metaKey: true\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\nAuto pan\n\nThe default behaviour of the UI is to automatically pan the canvas whenever a vertex is dragged out of the viewport. We're mentioning it here as it is related to pan, but this is controlled in the vertex drag options.\n\nFor more information see [this page](/react/docs/apps/shapes/dragging#auto-pan).\n\n### Zooming[](#zooming)\n\nThe canvas supports zooming both programmatically and via the mouse wheel (or pinch, on touch devices or a trackpad). A Surface has an associated `zoom range`, which is the minimum and maximum zoom that can be applied. When using the mouse wheel or pinch, these limits are applied automatically. If you attempt to set a zoom value outside of the zoom range programmatically (via `setZoom`), the zoom value will be clamped to the current range.\n\nZooming is configured via the `zoomOptions` property:\n\nZoomOptions\n\nOptions to control how a user manages zoom on the canvas.\n\n| Name | Type | Description |\n| --------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| fixedTransformOrigin? | [PointXY]() | Optional fixed transform origin for the canvas. Defaults to null.When this is supplied the zoom function does not change the transform origin You can still zoom and pan but the zoom/pan is applied relative to the top/left corner of the content. |\n| initialValue? | number | Initial zoom value. Defaults to 1. |\n| range? | [ZoomRange]() | Zoom range to support. The default is \\[0.05, 3] |\n| step? | number | When zooming by step, this defines the change in zoom for each step. Defaults to 0.25. |\n| wheel? | boolean | When true - which is the default - the wheel will be used for zoom. |\n\n<!-- -->\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n zoomOptions: {\n range: [\n 0.1,\n 5\n ],\n step: 0.1\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n### Mouse Wheel/Pinch[](#mouse-wheelpinch)\n\nThe `wheelOptions` property provides more granular control over how the mouse wheel (and pinch, on trackpads and touch screens) interacts with the UI for both zooming and panning. By default, the wheel controls zoom.\n\nWheelOptions\n\nOptions for how to respond to wheel events.\n\n| Name | Type | Description |\n| ------------ | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| cssFilter? | string | Optional CSS 3 selector to check if the wheel should be enabled for the current event target. |\n| filter? | (e:MouseEvent) => boolean | Optional function to call to check if wheel zooming should be enabled for the current event target. |\n| reverse? | boolean | Defaults to false. If true, the zoom direction is reversed: wheel up zooms out, and wheel down zooms in. |\n| sensitivity? | number | How sensitive the wheel should be. |\n| useMetaKey? | boolean | If true, the \"meta\" key (CMD on Mac, Ctrl on windows/linux) must be pressed in order for wheel zoom to operate. This can be useful if your UI fills the screen in one or more axes and your users would not be able to scroll past the Surface widget. |\n\n<!-- -->\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n wheelOptions: {\n useMetaKey: true,\n sensitivity: 0.5\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\nNote that if you set `wheel: true` in `panOptions`, the mouse wheel will pan the canvas, and this will take precedence over any zoom wheel configuration.","url":"https://visuallyjs.com/react/docs/diagrams/panning-and-zooming","lib":"react","topic":"diagrams"},"docs/diagrams/plugins/diagram-tools.md":{"title":"Diagram Tools","body":"# Diagram tools\n\nProvides a set of tools for working with shapes in a Diagram - resizing, rotating, cloning, deleting, and creating links.\n\n**********\n\nThe plugin automatically attaches tools to any shape that is added to VisuallyJs's current selection, and removes the tools when the shape is removed from the selection.\n\n## Setup[](#setup)\n\nThis plugin is installed on an editable Diagram by default, and configured indirectly via various diagram options.\n\nBy default, these tools are enabled:\n\n* [**Resize**](#resizing) Places a handle at each corner of a shape, with which the user can alter the shape's size\n* [**Rotate**](#rotation) Places a rotate handle above the shape, which the user can drag to rotate the shape.\n* [**Clone**](#cloning-a-shape) Places a clone button at the top right corner, which a user can click on to create a clone of the shape\n* [**Link**](#linking) Places a link handle at the bottom right, from which a user can drag a link to another shape\n\nThe default settings for the diagram tools plugin attach a handle at each corner that your users can drag to resize, but you can also instruct the plugin to allow users to resize by [dragging an element's borders](#resize-by-border)\n\n## Resizing[](#resizing)\n\nThe default resize mechanism is to place handles at each corner and halfway along each edge on a vertex's perimeter:\n\n**********\n\n### Handle shape[](#handle-shape)\n\nBy default, the plugin will use circular handles. You can change this to use rectangular handles by setting `handleShape:\"rectangle\"` in the cell options:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n cells: {\n resize: {\n handleShape: \"rectangle\"\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********\n\n<br />\n\n### Handle size[](#handle-size)\n\nThe default handle size is 10 pixels. You can change this to use rectangular handles by setting `handleSize`:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n cells: {\n resize: {\n handleShape: \"rectangle\",\n handleSize: 20\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********\n\n<br />\n\n## Resize by border[](#resize-by-border)\n\nInstead of attaching a handle at each corner to enable resize, you can setup the diagram tools to allow resize by dragging the borders of the element:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n cells: {\n resize: {\n method: \"borders\"\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********\n\n#### Border visibility[](#border-visibility)\n\nBy default, the borders for resizing will be visible to the user. You can set `bordersVisible:false` to hide the borders - the user will still see the cursor change when hovering over a border, but the border itself will not be shown:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n cells: {\n resize: {\n method: \"borders\",\n bordersVisible: false\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********\n\n## Rotation[](#rotation)\n\nBy default, the rotation tool is enabled.\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********\n\n### Disabling rotation[](#disabling-rotation)\n\nYou can switch off the rotate tool by setting `rotatable:false` in the `cells` diagram option:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n cells: {\n rotatable: false\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********\n\n### Rotation stops[](#rotation-stops)\n\nThe default behaviour is to support rotation to any angle, but you can specify the number of rotation stops VisuallyJs should use:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n cells: {\n rotationStops: 12\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********\n\n## Grids[](#grids)\n\nWhen the associated diagram has a grid, this plugin will constrain node/group resizing so that the dimensions of the vertex are a multiple of the grid in each axis.\n\n**********\n\n### Ignoring the grid[](#ignoring-the-grid)\n\nConstraining resize to the grid is controlled by the `ignoreGrid` option, which is set to false by default. You can change that:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n cells: {\n resize: {\n ignoreGrid: true\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********\n\n## Constraining resize axes[](#constraining-resize-axes)\n\nBy default, the diagram tools plugin will allow users to resize an element's width and height. This behaviour can be changed, by setting `resizeX` or `resizeY` to \"false\" in the plugin options.\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n cells: {\n resizeX: false\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\nThe above configuration would result in a setup where your users can only resize the height of elements:\n\n**********\n\n## Excluding elements[](#excluding-elements)\n\nYou can exclude specific elements from being resizable by writing a `data-vjs-resizable` attribute on them:\n\n```html\n<div data-vjs-resizable=\"false\">{{name}}</div>\n\n```\n\n## Custom payloads[](#custom-payloads)\n\nYou can provide a `payloadGenerator` to the diagram tools which will be invoked before the diagram tools commits a change to a model object. This method allows you to customize the changes that will be made to the model object (or it can be used as a hook to make other changes in your model of course):\n\n```typescript\npayloadGenerator?:(v:Node, p:ObjectData) => ObjectData\n\n```\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nimport { ResizingToolsPlugin } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n\n const renderOptions = {\n plugins: [\n {\n type: ResizingToolsPlugin.type,\n options: {\n payloadGenerator: (vertex, data) => {\n return {\n someDynamicValue:data.w * something etc\n } \n }\n }\n }\n ]\n}\n return <SurfaceComponent renderOptions={renderOptions}/>\n}\n\n```\n\nIn this example the model object's data will be updated with the `someDynamicValue` we calculated.\n\ncaution\n\nA payload generator function cannot override the value of any attributes the diagram tools needs to set, ie. the position or size of the object. the diagram tools will merge its attributes on top of any you return from a payload generator.\n\n## CSS[](#css)\n\n| Class | Description |\n| ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `vjs-resize-border` | Set on the border handles |\n| `vjs-resize-border-b` | Set on the bottom border handle |\n| `vjs-resize-border-l` | Set on the left border handle |\n| `vjs-resize-border-r` | Set on the right border handle |\n| `vjs-resize-border-t` | Set on the top border handle |\n| `vjs-resize-frame` | Set on the frame the resize tool draws around an object it is currently editing. |\n| `vjs-resize-handle` | Set on the resize handles by the resizing/diagram tools |\n| `vjs-resize-handle-active` | Set on a resize handle when it is being actively used |\n| `vjs-resize-handle-b` | Set on the bottom center resize handle |\n| `vjs-resize-handle-bl` | Set on the bottom left corner resize handle |\n| `vjs-resize-handle-br` | Set on the bottom right corner resize handle |\n| `vjs-resize-handle-l` | Set on the left center resize handle |\n| `vjs-resize-handle-r` | Set on the right center resize handle |\n| `vjs-resize-handle-t` | Set on the top center resize handle |\n| `vjs-resize-handle-tl` | Set on the top left corner resize handle |\n| `vjs-resize-handle-tr` | Set on the top right corner resize handle |\n| `vjs-resize-skeleton` | Set on the element that is the parent of drag handles when in `handles` resize mode. |\n| `vjs-resize-skeleton-borders` | Set on the element that is the parent of drag borders when in `borders` resize mode. |\n| `vjs-resize-skeleton-borders-visible` | Set on the resize tool's main group element for some vertex when `bordersVisible` is set to true and the resize mode is RESIZING\\_TOOLS\\_RESIZE\\_METHOD\\_BORDERS |\n| `vjs-rotate-handle` | Set on the rotation handle |\n| `vjs-rotate-leader` | Set on the leader to the rotation handle. |\n\n## Options[](#options)\n\nResizingToolsPluginOptions\n\nOptions for the resizing tool plugin.\n\n| Name | Type | Description |\n| ------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| borderHandleSize? | number | Size of handles when using \"border\" resize. Defaults to 6 pixels. |\n| bordersVisible? | boolean | When resizeMethod is \"borders\", set this to make the borders visible. Internally this just sets a CSS class on the draw skeleton's parent DOM element, and the appearance of the borders is then controlled via CSS. |\n| canResizeFilter? | (v:[Vertex](), el:[BrowserElement]()) => boolean | Optional function that can decide on whether or not the given vertex should be resizable |\n| canRotateFilter? | (v:[Vertex](), el:[BrowserElement]()) => boolean | Optional function that can decide on whether or not the given vertex should be rotatable |\n| constrainGroups? | boolean | Defaults to true, meaning groups will not be shrunk to the point that one or more of their child vertices is no longer visible. |\n| handleOffset? | number | How much to offset the resize frame and handles from the bounds of the shape. Defaults to 5 pixels. |\n| handlerFactory? | [ResizingToolsHandlerFactory]() | Optional factory that can return a resize handler for some given vertex. You can use this to override the default behaviour for any vertex you choose |\n| handleShape? | \"circle\" \\| \"rectangle\" | Shape of resize handles. Defaults to circle. |\n| handleSize? | number | Width/height to use for handles. Defaults to 20 pixels. |\n| heightAttribute? | string | Attribute to use for vertex height - defaults to 'height' |\n| ignoreGrid? | boolean | Defaults to false, meaning size changes conform to an underlying grid, if present |\n| leftAttribute? | string | Attribute to use for vertex left position - defaults to 'left' |\n| minimumHeight? | number | Minimum height the user can shrink a vertex to. Defaults to 30. |\n| minimumWidth? | number | Minimum width the user can shrink a vertex to. Defaults to 30. |\n| modelUpdater? | [ResizingToolsModelUpdater]() | Optional function that can inject extra model updates each time a vertex is resized. |\n| onDemand? | boolean | Defaults to false, meaning the resizing tool plugin switches on whenever a new vertex is selected. |\n| onEdit? | (o:[Node]() \\| [Group](), surface:[Surface](), toolkit:[VisuallyJsModel]()) => any | Optional callback invoked after an edit has occurred |\n| payloadGenerator? | (v:[Node](), p:[ObjectData]()) => [ObjectData]() | Optional function to invoke when a resize has occurred. The values the resizing plugin wants to write for the vertex are merged on top of the value returned from this function, and the combined payload is written as an update to the vertex in the data model. This exists for internal use mostly but there's no harm in it being exposed for your enjoyment. |\n| resizeMethod? | [ResizingToolsResizeMethod]() | Method to use for resize - handles on the corners, or borders. Defaults to handles. |\n| resizeX? | boolean | Whether or not to support resize in the X axis. Defaults to true. |\n| resizeY? | boolean | Whether or not to support resize in the Y axis. Defaults to true. |\n| rotatable? | boolean | Whether or not to support rotation on all elements.. Defaults to false. |\n| rotateHandleSize? | number | Size of the rotate handle. Defaults to 16 pixels. |\n| rotateLeaderLength? | number | Length of the leader line to the resize handle when using the resizing tools in an SVG container. Defaults to 30 pixels. |\n| rotationStops? | number | Optional number of stops to use when rotating. If not provided vertices can be rotated to any angle. If provided, the value is divided into 360 and the result is the angle between each stop. For example, a value of 12 means each stop is 30 degrees. |\n| topAttribute? | string | Attribute to use for vertex top position - defaults to 'top' |\n| widthAttribute? | string | Attribute to use for vertex width - defaults to 'width' |","url":"https://visuallyjs.com/react/docs/diagrams/plugins/diagram-tools","lib":"react","topic":"diagrams"},"docs/diagrams/plugins/lasso.md":{"title":"Lasso","body":"# Lasso\n\nThe lasso plugin allows users to select nodes, group and edges with the mouse. We've activated it on page load so you can try it out below. After you've tried it once the surface will revert to pan mode and you'll need to select the lasso from the controls.\n\nAny vertices snagged by your lasso are added to the model's current selection.\n\nThe lasso works like the lasso in AutoCAD: when you drag from left to right, any vertices that intersect with your lasso are added to the selection. When you drag from right to left, though, only vertices that your lasso fully encloses are added to the selection.\n\n**********\n\n## Setup[](#setup)\n\n<!-- -->\n\n```jsx\nimport { LassoPlugin } from \"@visuallyjs/browser-ui\"\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n plugins: [\n {\n type: LassoPlugin.type,\n options: {\n invert: true\n }\n }\n ]\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n## CSS Classes[](#css-classes)\n\n| Class | Description |\n| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `vjs-lasso` | Assigned to the DOM element representing a lasso |\n| `vjs-lasso-mask` | Assigned to each DOM element representing part of the lasso mask, when the lasso is inverted mode. The lasso mask consists of four parts, one to the left, right, top and bottom of the area that has been lassoed. |\n| `vjs-lasso-mask-bottom` | Assigned to the DOM element representing the bottom part of the lasso mask, when the lasso is inverted mode. |\n| `vjs-lasso-mask-left` | Assigned to the DOM element representing the left part of the lasso mask, when the lasso is inverted mode. |\n| `vjs-lasso-mask-right` | Assigned to the DOM element representing the right part of the lasso mask, when the lasso is inverted mode. |\n| `vjs-lasso-mask-top` | Assigned to the DOM element representing the top part of the lasso mask, when the lasso is inverted mode. |\n\n## Options[](#options)\n\nLassoPluginOptions\n\n| Name | Type | Description |\n| --------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| autoExit? | boolean | When true (which is the default) the lasso exits after a selection has been made. |\n| cssClass? | string | Extra class(es) to add to the lasso's DOM element |\n| filter? | string \\| (e:MouseEvent) => boolean | Optional CSS3 filter identifying elements you do not want to lasso |\n| generateLassoContent? | (origin:[PointXY](), e:MouseEvent) => [BrowserElement]() | Optional function that generates the DOM element for the lasso to use. This is<br />for advanced usage scenarios and most users will not need to supply this. |\n| includeEdges? | boolean | Defaults to false. If true, edges are included in the lasso selection. |\n| invert? | boolean | Defaults to false, meaning the lasso is drawn as a rectangle. If true, the lasso is drawn as a set of masks,<br />with the lasso area drawn as a \"hole\" in the masks. |\n| onEnd? | Function | Optional function to call when lasso selection ends. |\n| onSelect? | (vertices:Array<[Vertex]()>) => any | Optional function to call when one or more objects has been selected by the lasso. |\n| onStart? | Function | Optional function to call when lasso selection starts. |\n| selectionFilter? | (o:[Edge]() \\| [Vertex]()) => boolean | Optional filter that is passed every vertex/edge that the lasso would ordinarily select, and if this function returns false<br />then the vertex/edge is not added to the selection |","url":"https://visuallyjs.com/react/docs/diagrams/plugins/lasso","lib":"react","topic":"diagrams"},"docs/diagrams/plugins/overview.md":{"title":"Overview","body":"# Plugins\n\nPLUGINS OVERVIEW","url":"https://visuallyjs.com/react/docs/diagrams/plugins/overview","lib":"react","topic":"diagrams"},"docs/diagrams/plugins/selected-edge-highlight.md":{"title":"Selected Edge Highlight","body":"# Selected edge highlighter\n\nThis plugin provides a visual indicator for edges when they are selected in a Diagram. It draws a bounding box (highlight) around the selected edge, making it easier for users to identify which edge is currently being interacted with.\n\n<!-- -->\n\n**********\n\nThis plugin is **switched on by default** in any `Diagram` instance.\n\n## Features[](#features)\n\n* Automatically draws a highlight when an edge is selected.\n* Updates the highlight position and size in real-time if the edge's geometry changes (e.g., when moving connected vertices or editing the edge path).\n* Removes the highlight when the edge is deselected or removed from the diagram.\n\n## Configuration[](#configuration)\n\nWhile the plugin is active by default, you can configure its behavior or disable it entirely via the `edges` section of your `DiagramOptions`.\n\n## Disabling the Plugin[](#disabling-the-plugin)\n\nTo disable the edge highlight, set `highlightSelected` to `false`:\n\n```jsx\nimport { FLOWCHART_SHAPES } from \"@visuallyjs/browser-ui\"\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n shapes: FLOWCHART_SHAPES,\n edges: {\n highlightSelected: false\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n## Customizing the Highlight Style[](#customizing-the-highlight-style)\n\nYou can customize the appearance of the highlight box using the `highlightStyle` option. This option accepts a [PaintStyle]() object.\n\n**********\n\n```jsx\nimport { FLOWCHART_SHAPES } from \"@visuallyjs/browser-ui\"\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n shapes: FLOWCHART_SHAPES,\n edges: {\n highlightStyle: {\n stroke: \"blue\",\n strokeWidth: 3,\n fill: \"rgba(0, 0, 255, 0.1)\",\n dashArray: \"5 5\"\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\nThe `highlightStyle` supports the following properties:\n\nPaintStyle\n\nBasic style definition for an edge\n\n| Name | Type | Description |\n| -------------- | ------------------------ | ------------------------------------------------------------------------- |\n| dashArray? | string | Definition for stroke pattern |\n| fill? | string | Fill color for the edge. |\n| gradient? | Array<\\[number, string]> | Definition of a linear gradient to apply. Each entry is \\[offset, color]. |\n| outlineStroke? | string | Color for the outline path |\n| outlineWidth? | number | Width of the outline path |\n| stroke? | string | Stroke color for the edge |\n| strokeWidth? | number | Width of the stroke |\n\n## CSS Customization[](#css-customization)\n\nThe highlight element is an SVG `rect` and is assigned the CSS class `vjs-selected-edge-highlight`. You can also use this class to apply additional styles via CSS, though `highlightStyle` in options is the preferred method for basic styling.","url":"https://visuallyjs.com/react/docs/diagrams/plugins/selected-edge-highlight","lib":"react","topic":"diagrams"},"docs/diagrams/programmatic-api.md":{"title":"Programmatic Api","body":"# Programmatic API\n\nVisuallyJS supports both declarative and programmatic approaches to diagramming:\n\n* **Declarative**: You can define the entire state of the diagram at once using a data object - this is often the preferred way when loading a saved diagram or when the UI is driven by external state.\n* **Programmatic**: Once a diagram is created, you can interact with it at a granular level. You can add or remove individual cells and links, and you can manipulate existing cells by changing their properties (label, color, size, etc.) through the `DiagramCell` and `DiagramLink` classes.\n\nTo access the underlying Diagram in a React app, declare a ref and then use the `getDiagram()` method on it:\n\n```jsx\n\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\"\nimport {useRef} from \"react\"\n\nexport default function App() {\n\n const diagramRef = useRef(null)\n\n const data = { ... }\n\n const options = {...}\n\n function doSomething() {\n const diagram = diagramRef.current.getDiagram()\n // now you can invoke methods on \"diagram\"\n }\n\n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options} ref={diagramRef}/>\n </div> \n}\n\n```\n\n## Manipulating Diagram Cells[](#manipulating-diagram-cells)\n\nThe `addCell` method on a `Diagram` instance returns an instance of `DiagramCell`. You can also retrieve an existing cell using the `getCell(id)` method.\n\n### Getting a Cell[](#getting-a-cell)\n\n```javascript\nconst cell = diagram.getCell(\"1\");\n\n```\n\nThe return value is of type [DiagramCell]().\n\n### Setting Basic Properties[](#setting-basic-properties)\n\n`DiagramCell` provides several methods to update its visual appearance and data:\n\n* **`setLabel(label: string)`**: Updates the cell's label text.\n* **`setFill(fill: string)`**: Sets the cell's fill color (e.g., \"#ff0000\").\n* **`setOutline(outline: string)`**: Sets the color of the cell's outline.\n* **`setOutlineWidth(width: number)`**: Sets the thickness of the cell's outline.\n* **`setColor(color: string)`**: Sets the color of the cell's label text.\n\nExample:\n\n```javascript\ncell.setLabel(\"Process Completed\");\ncell.setFill(\"#d4edda\");\ncell.setOutline(\"#28a745\");\ncell.setOutlineWidth(2);\ncell.setColor(\"#155724\");\n\n```\n\n### Positioning and Sizing[](#positioning-and-sizing)\n\nYou can move and resize cells programmatically:\n\n* **`setPosition(p: PointXY)`**: Moves the cell to the specified coordinates `{x, y}`.\n* **`setSize(s: Size)`**: Sets the cell's width and height `{width, height}`.\n\n```javascript\ncell.setPosition({ x: 250, y: 150 });\ncell.setSize({ width: 150, height: 100 });\n\n```\n\n### Updating arbitrary data[](#updating-arbitrary-data)\n\nYou can update any data on a cell via the low-level **`update`** method. Each of the methods discussed previously on this page are in fact wrappers around a call to `update`, with the appropriate properties.\n\n```javascript\ncell.update({ foo:\"someValue\" });\n\n```\n\n### Z-Index and Visibility[](#z-index-and-visibility)\n\n* **`toFront()`**: Brings the cell to the front of all other cells.\n* **`toBack()`**: Sends the cell behind all other cells.\n\n### Removing a cell[](#removing-a-cell)\n\nTo delete a cell and its associated model object from the diagram, call **`remove()`**:\n\n```javascript\ncell.remove()\n\n```\n\ncaution\n\nOnce you have called `remove` on a cell, the cell is no longer attached to the diagram, and invoking any methods on it will give indefinite results.\n\n## Adding Cells and Links Programmatically[](#adding-cells-and-links-programmatically)\n\nYou can add new elements to the diagram at any time:\n\n#### Adding a Cell[](#adding-a-cell)\n\nThe `addCell` method requires at least a `type` property. If dimensions or positions are omitted, defaults will be used.\n\n```javascript\nconst newCell = diagram.addCell({\n type: \"terminus\",\n x: 400,\n y: 100,\n label: \"End\"\n});\n\n```\n\n## Manipulating Links[](#manipulating-links)\n\n#### Adding a Link[](#adding-a-link)\n\nThe `addLink` method connects two cells. You can pass the `DiagramCell` objects directly or use their IDs.\n\n```javascript\nconst link = diagram.addLink({\n source: cell,\n target: newCell\n});\n\n```\n\nThis method returns an instance of [DiagramLink]().\n\n#### Styling Links[](#styling-links)\n\n`DiagramLink` provides methods to update the visual appearance of a link, leveraging the \"simple edge styles\" functionality:\n\n* **`setLabel(label: string)`**: Updates the link's label text.\n* **`setColor(color: string)`**: Sets the link's stroke color.\n* **`setLineWidth(width: number)`**: Sets the thickness of the link.\n* **`setDashArray(dashArray: string)`**: Sets the dash pattern for the link (e.g., \"5,5\").\n* **`setOutlineColor(color: string)`**: Sets the color of the link's outline.\n* **`setOutlineWidth(width: number)`**: Sets the thickness of the link's outline.\n* **`setLabelLocation(location: number)`**: Sets the position of the label along the link (0 to 1).\n\nExample:\n\n```javascript\nlink.setLabel(\"Depends On\");\nlink.setColor(\"#007bff\");\nlink.setLineWidth(2);\nlink.setDashArray(\"2,2\");\n\n```\n\n#### Connectivity[](#connectivity)\n\nYou can change the source or target of an existing link:\n\n* **`setSource(source: string | DiagramCell | PointXY)`**: Reconnects the link's source.\n* **`setTarget(target: string | DiagramCell | PointXY)`**: Reconnects the link's target.\n\n#### Z-Index and Lifecycle[](#z-index-and-lifecycle)\n\n* **`toFront()`**: Brings the link to the front.\n* **`toBack()`**: Sends the link to the back.\n* **`remove()`**: Deletes the link from the diagram.","url":"https://visuallyjs.com/react/docs/diagrams/programmatic-api","lib":"react","topic":"diagrams"},"docs/diagrams/shapes/dragging.md":{"title":"Dragging","body":"# Dragging shapes\n\nBy default, all shapes in a Diagram will be made draggable, and the default behaviour of a draggable element is that it can be dragged to anywhere on the canvas. No special treatment is needed for touch devices - VisuallyJs abstracts that away.\n\n## Controlling drag[](#controlling-drag)\n\nThere are a few approaches to controlling which shapes may be dragged.\n\n### Readonly diagrams[](#readonly-diagrams)\n\nIf you mark a Diagram as `editable:false`, no shapes will be draggable:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n editable: false\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n### Switching off drag[](#switching-off-drag)\n\nYou can disable dragging for all shapes in an editable diagram like this:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n cells: {\n draggable: false\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n### Selective disable[](#selective-disable)\n\nif you want more fine-grained control over which shapes should be draggable, you can provide a [DiagramActionMediator]() to the Diagram, and implement the `canDrag` method:\n\nThe `canDrag` method is invoked when the user begins to drag a shape. It is passed the underlying vertex that is being dragged, the definition for the shape representing that vertex, and the SVG element from the DOM. Return `false` from this method if you wish to prevent drag.\n\n```typescript\ncanDrag:(vertex: Vertex, shape: Shape, el: HTMLElement) => {\n return vertex.type !== \"lane\"\n}\n\n```\n\n## Dragging on a grid[](#dragging-on-a-grid)\n\nWhen you declare a grid in your diagram options, the shapes in the diagram will be dragged on that grid:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n grid: {\n size: {\n width: 50,\n height: 50\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\nThe full list of options supported by grid are defined in the [GridOptions]() interface:\n\nGridOptions\n\nOptions for a grid in the UI\n\n| Name | Type | Description |\n| ---------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------- |\n| fitGroupsToGrid? | boolean | Whether or not to ensure calculated group sizes (from auto sized groups) are a multiple of the grid size in each axis. Defaults to false. |\n| size? | [Grid]() | Width/height of the grid cells |\n| snap? | boolean | Whether or not to snap elements to the grid when dragging. Defaults to false. |\n\n## Magnetizing[](#magnetizing)\n\nVisuallyJs has a built in \"magnetizer\", which provides a means to nudge elements around in your UI so that things don't overlap. There are a few different ways to use the magnetizer, and it is covered in full [on this page](/react/docs/diagrams/magnetizer.md). In the canvas below we're using the magnetizer in `constant` mode, so that as you drag a vertex the other vertices are moved aside. We've also switched on `trackback`, which causes vertices to try to move back to their original position wherever possible.\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = {\n nodes:[\n {id:\"1\",x:50,y:50},\n {id:\"2\",x:350,y:60},\n {id:\"3\",x:50,y:250}\n ]\n}\n \n const options = {\n shapes: [BASIC_SHAPES],\n cells: {\n magnetizer: {\n constant: true,\n trackback: true\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n**********\n\n## Z Index[](#z-index)\n\nSince a diagram is a pure SVG UI you cannot use CSS to manage z-index for your shapes. When a user drags a shape, VisuallyJs automatically moves that shape so that it is the last child in the SVG, which results in it being painted on top the other shapes.\n\n## Auto pan[](#auto-pan)\n\nVisuallyJs will auto pan a canvas when a shape is dragged outside of the visible bounds. This can be controlled with the `autoPan` flag in your diagram options:\n\n```jsx\n\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n autoPan: false\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n## Identifying drop targets[](#identifying-drop-targets)\n\nBy default, an element can be dragged to any position on the canvas, and into any group. You can use the `canDrop` option of a mediator to restrict where an element can be dropped:\n\n```javascript\ndragOptions:{\n canDrop:(candidate, target, onCanvas) => {\n // return true if the candidate can be dropped on the target\n }\n}\n\n```\n\nThe arguments passed to `canDrop` are:\n\n* **candidate** The node or group being dragged.\n* **target** The node, group, or canvas that is a potential drop target.\n* **onCanvas** A boolean indicating if the target is the canvas.\n\nVisuallyJs calls this function for every possible drop target when a drag starts. If you return `false` for a given target, VisuallyJs will not allow the candidate to be dropped there.\n\n## Drag groups[](#drag-groups)\n\nA `DragGroup` models a group of vertices that should be dragged together. You can have any number of drag groups in your canvas. When you assign a vertex to a drag group you indicate to VisuallyJs whether that vertex should be an `active` member - meaning that when it is dragged all of the other vertices in the drag group are also dragged - or that it should be a `passive` member - meaning that when it is dragged no other members should be dragged, but that it should be dragged whenever an `active` member is dragged.\n\n### Assigning drag groups[](#assigning-drag-groups)\n\nTo assign vertices to drag groups you need to configure `dragGroups` in your diagram options:\n\n```jsx\nimport { DragGroupsPlugin, BASIC_SHAPES } from \"@visuallyjs/browser-ui\"\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n shapes: [BASIC_SHAPES],\n dragGroups: {\n assignDragGroup: (v) => {\n return { id:'dragGroup', active:v.main === true }\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\nThe key piece to note is the `assignDragGroup` function that you provide. In the above example our `assignDragGroup` function instructs VisuallyJs to add every vertex to a group called `\"dragGroup\"`, but that the vertex should only be an `active` member if it has a `main` of attribute with value `true`.\n\nConsider this dataset:\n\n```javascript\n{\n nodes:[\n {\"id\":\"1\",\"x\":50,\"y\":50,\"width\":180,\"height\":100,\"type\":\"rectangle\",\"main\":true,\"fill\":\"forestgreen\"},\n {\"id\":\"2\",\"x\":250,\"y\":160,\"width\":50,\"height\":30,\"fill\":\"orangered\",\"type\":\"rectangle\"},\n {\"id\":\"3\",\"x\":350,\"y\":100,\"width\":50,\"height\":30,\"fill\":\"orangered\",\"type\":\"rectangle\"},\n]\n\n```\n\nWe have one `\"main\"` shape and two other shapes. In the canvas below, try dragging the large green box around. You'll see the two red boxes drag along with it. Now try dragging one of the red boxes - nothing else moves. This is because all of the nodes are inside a drag group, but the large green node is marked `active` and the red nodes are marked `passive`, due to the `assignDragGroup` function shown above:\n\n**********\n\nThe key is the `assignDragGroup` function that we provide. In the implementation above we do two things:\n\n* all vertices are assigned to a drag group called `\"dragGroup\"`\n* The vertex whose `main` is `true` is marked `active:true`; the others are marked `active:false`\n\n### Multiple drag groups[](#multiple-drag-groups)\n\nOur example above just used a single drag group, but we can have as many of these as we want. For instance, here's a canvas in which all the red elements are dragged in a single group, and all the green elements are dragged in a different group:\n\n**********\n\nThis was an even simpler setup - we just use each node's `fill` to specify its drag group:\n\n```jsx\nimport { DragGroupsPlugin, BASIC_SHAPES } from \"@visuallyjs/browser-ui\"\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n shapes: [BASIC_SHAPES],\n dragGroups: {\n assignDragGroup: (v) => {\n return v.data.fill\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\nEvery element in this example is marked `active` because that's the default if you do not specify it. All we had to do in this example is return the name of a drag group and VisuallyJs adds the vertex as an active participant to that group.\n\nOur dataset in this example is:\n\n```javascript\n{\n nodes:[\n {\"id\":\"1\",\"x\":50,\"y\":50,\"fill\":\"forestgreen\",\"type\":\"rectangle\"},\n {\"id\":\"2\",\"x\":150,\"y\":160,\"fill\":\"orangered\",\"type\":\"rectangle\"},\n {\"id\":\"3\",\"x\":200,\"y\":30,\"fill\":\"orangered\",\"type\":\"rectangle\"},\n {\"id\":\"4\",\"x\":280,\"y\":150,\"fill\":\"forestgreen\",\"type\":\"rectangle\"},\n]\n\n```\n\n### Example - annotating objects[](#example---annotating-objects)\n\nA good example of how this functionality is useful is the concept of annotating objects in a diagram - explanatory notes for some given vertex that you want to place near the vertex, but whose positioning you want to adjust in each case to suit the diagram. When you drag a vertex that has annotations you want the annotations to move with the vertex, but you want to be able to position the annotations without moving the vertex itself.\n\nConsider this dataset:\n\n```javascript\n{\n nodes:[\n {\"id\":\"1\",\"type\":\"rectangle\",\"x\":50,\"y\":50,\"fill\":\"forestgreen\"},\n {\"id\":\"2\",\"type\":\"rectangle\",\"x\":300,\"y\":50,\"fill\":\"forestgreen\"},\n {\"id\":\"3\",\"type\":\"rectangle\",\"label\":\"I belong to node 1\",\"ref\":\"1\",\"x\":70,\"y\":-40,\"width\":80,\"height\":40,\"fontSize\":11,\"annotation\":true},\n {\"id\":\"4\",\"type\":\"rectangle\",\"label\":\"I belong to node 1\",\"ref\":\"1\",\"x\":-90,\"y\":120,\"width\":80,\"height\":40,\"fontSize\":11,\"annotation\":true},\n {\"id\":\"5\",\"type\":\"rectangle\",\"label\":\"I belong to node 2\",\"ref\":\"2\",\"x\":380,\"y\":160,\"width\":80,\"height\":40,\"fontSize\":11,\"annotation\":true},\n]\n\n```\n\nWe've got five shapes, three of which are marked with `annotation:true`, each of which have a `ref` member, which points to another shape, by its id. We want to be able to drag our main nodes around and have the `annotation` nodes follow, but we also want to be able to position the `annotation` nodes around the `main` nodes where we please. This is easily achieved:\n\n```jsx\nimport { DragGroupsPlugin } from \"@visuallyjs/browser-ui\"\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n dragGroups: {\n assignDragGroup: (v) => {\n return v.annotation == null ? v.id : {id:v.data.ref, active:false}\n }\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n* For nodes of type `main`, we just return the node's id: `v.id`\n* For nodes of type `annotation`, we return the `ref` as the drag group id, and mark the vertex passive: `{id:v.data.ref, active:false}`.\n\nWhich gives us this arrangement:\n\n**********\n\nAnd there you have it! Annotated objects using just a few lines of configuration.\n\n#### Cleaning up annotations[](#cleaning-up-annotations)\n\nOne thing to keep in mind is that the annotations and the edges that connect them to their reference nodes will not automatically be removed by VisuallyJs if the reference node is removed from the dataset. To handle this we can use another of VisuallyJs's capabilities you won't find in other libraries in this space - [Transactions](/react/docs/diagrams/model/undo-redo#transactions) - to cleanup the annotations, but in an undo/redo friendly way.\n\nTry clicking one of the red circle buttons below. We'll remove the node the button belongs to, and we'll also remove any annotations that are attached to it (code follows below) :\n\n**********\n\nTo remove a node and its annotations in an undo-friendly way, we find everything we want to delete and then perform all the removals inside a transaction. An example function, into which you'd pass the model and the ID of the node to cleanup, is:\n\n```typescript\nfunction removeNode(model:VisuallyJsModel, nodeId:string) {\n \n // find all annotation nodes that reference this node\n const annotations = model.getNodes().filter(n => n.data.ref === nodeId)\n\n // in a transaction, remove all the annotation nodes and then the focus node. Edges will be cleaned up automatically, and if the user clicks undo, the entire transaction is rolled back as one.\n model.transaction(() => {\n annotations.forEach(a => model.removeNode(a))\n model.removeNode(nodeId)\n })\n}\n\n```\n\n<br />\n\nWe can integrate that snippet into our component as shown below. We have a click listener on a specific button, in which we get the model and the node ID from the context used to render the node:\n\n```jsx\nviewOptions={{\n nodes:{\n main:{\n jsx:(ctx) => <div>\n <div data-vjs-delete={true} onClick={() => {\n const annotations = ctx.model.getNodes().filter(n => n.data.ref === ctx.data.id) \n ctx.model.transaction(() => {\n annotations.forEach(a => ctx.model.removeNode(a))\n ctx.model.removeNode(ctx.data.id)\n }) \n }}/>\n </div>\n }\n }\n}}\n\n```\n\n## CSS Classes[](#css-classes)\n\nThere are a number of CSS classes assigned to various parts of the UI during a shape drag. These can be used to easily add visual cues for your users. Note, though, that since a diagram is a pure SVG UI, you cannot use CSS to control z-index during drag. See the discussion above for how VisuallyJs handles z-index in a diagram.\n\n| Class | Description |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `vjs-drag-active` | Assigned to any element that is a candidate drop target for an edge that is being dragged |\n| `vjs-drag-hover` | Assigned to any element that is the current drop target for an edge that is being dragged |\n| `vjs-drag-hover-cannot-drop` | Assigned to a vertex or the canvas when an element that is being dragged on the canvas is hovering over it but drop is not allowed. |\n| `vjs-drag-original-group` | Assigned to a group element when one of its children is being dragged. This can be useful to help manage z-index: we recommend using this class to set a z-index for the drag parent group above that of the other groups, which will ensure that the element you are dragging will appear on top of other groups. |\n| `vjs-element-dragging` | Assigned by the Surface to a vertex element that is being dragged |\n| `vjs-group-child-element-dragging` | Assigned by the Surface to the group parent of a vertex element that is being dragged, if applicable. You can use this class for a couple of things - to show that a child element is being dragged, of course, but also a good idea is to use this class to bump the z-index for any group that has it assigned, to put that group above other groups. This ensures that as you drag a child vertex over to some other group, it appears on top of that group in the UI. |\n| `vjs-most-recently-dragged` | Assigned by the Surface to the vertex element(s) that was/were the most recently dragged elements. |\n| `vjs-surface-element-dragging` | Assigned by the Surface to its container when a node or group is being dragged |","url":"https://visuallyjs.com/react/docs/diagrams/shapes/dragging","lib":"react","topic":"diagrams"},"docs/diagrams/shapes/overview.md":{"title":"Overview","body":"# Shapes\n\n<!-- -->\n\nShapes in a Diagram are provided by one or more **Shape Sets**. A shape set is a collection of named SVG shapes that the Diagram can use to render its nodes and groups.\n\n## Configuration[](#configuration)\n\nYou configure the shapes for a Diagram using the `shapes` option to a diagram. This option accepts either a single `ShapeSet` or an array of `ShapeSet` objects.\n\n```jsx\nimport { FLOWCHART_SHAPES, BASIC_SHAPES } from \"@visuallyjs/browser-ui\"\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n shapes: [ FLOWCHART_SHAPES, BASIC_SHAPES ]\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n## Available shape sets[](#available-shape-sets)\n\nVisuallyJs ships with two shape sets in the `browser-ui` package and a set of BPMN shapes:\n\n### Flowchart[](#flowchart)\n\n```javascript\nimport { FLOWCHART_SHAPES } from \"@visuallyjs/browser-ui\"\n\n```\n\n***\n\n### Basic[](#basic)\n\n```javascript\nimport { BASIC_SHAPES } from \"@visuallyjs/browser-ui\"\n\n```\n\n### BPMN[](#bpmn)\n\n```javascript\nimport { BPMN2_SHAPES } from \"@visuallyjs/bpmn\"\n\n```\n\ninfo\n\nThese shapes are shipped in the `@visuallyjs/bpmn` library - you'll need to import it.\n\n## Custom shape sets[](#custom-shape-sets)\n\nIt's straightforward to make your own shape set - they consist of an id and then a list of shapes, for each of which you provide SVG.\n\nHere we have made a set of faces:\n\n**********\n\n```javascript\nconst shapes = {\n id:\"faces\",\n shapes:[\n {\n type:\"impassive\",\n template:`<g>\n<circle cx=\"{{width/2}}\" cy=\"{{height/2}}\" r=\"{{(width/2)}}\"/>\n <path d=\"M {{width/4}} {{height*3/4}} L {{width*3/4}} {{height*3/4}}\"/>\n <circle cx=\"{{width/4}}\" cy=\"{{height/4}}\" r=\"10\"/>\n <circle cx=\"{{width*3/4}}\" cy=\"{{height/4}}\" r=\"10\"/>\n <circle cx=\"{{width/2}}\" cy=\"{{height/2}}\" r=\"10\"/>\n </g>`,\n label:\"Impassive\"\n },\n {\n type:\"pleased\",\n template:`<g>\n <circle cx=\"{{width/2}}\" cy=\"{{height/2}}\" r=\"{{(width/2)}}\"/> \n <circle cx=\"{{width/4}}\" cy=\"{{height/4}}\" r=\"10\"/>\n <circle cx=\"{{width*3/4}}\" cy=\"{{height/4}}\" r=\"10\"/>\n <circle cx=\"{{width/2}}\" cy=\"{{height/2}}\" r=\"10\"/>\n <path d=\"M {{width/4}} {{height*3/4}} C {{width/4}} {{height*7/8}}, {{width*3/4}} {{height*7/8}} {{width*3/4}} {{height*3/4}}\"/>\n </g>`,\n label:\"Pleased\"\n },\n {\n type:\"notpleased\",\n template:`<g>\n <circle cx=\"{{width/2}}\" cy=\"{{height/2}}\" r=\"{{(width/2)}}\"/> \n <circle cx=\"{{width/4}}\" cy=\"{{height/4}}\" r=\"10\"/>\n <circle cx=\"{{width*3/4}}\" cy=\"{{height/4}}\" r=\"10\"/>\n <circle cx=\"{{width/2}}\" cy=\"{{height/2}}\" r=\"10\"/>\n <path d=\"M {{width/4}} {{height*3/4}} C {{width/4}} {{height*5/8}}, {{width*3/4}} {{height*5/8}} {{width * 0.75}} {{height * 0.75}}\"/>\n </g>`,\n label:\"Not Pleased\"\n }\n ]\n}\n\n```","url":"https://visuallyjs.com/react/docs/diagrams/shapes/overview","lib":"react","topic":"diagrams"},"docs/diagrams/shapes/shape-libraries.md":{"title":"Shape Libraries","body":"# SVG Shapes\n\nDiagrams use SVG to render shapes. These shapes are stored inside `ShapeSets`, and when you create a diagram you instruct VisuallyJs which shape sets you want to use.\n\n## Registering shapes[](#registering-shapes)\n\n```jsx\nimport { FLOWCHART_SHAPES, BASIC_SHAPES } from \"@visuallyjs/browser-ui\"\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n shapes: [FLOWCHART_SHAPES, BASIC_SHAPES]\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n## Required data properties[](#required-data-properties)\n\nIn order for the diagram to be able to pick the appropriate shape for some vertex, the vertex data must contain:\n\n1. A `type` property that maps to the ID of one of the shapes in your library\n2. A `category` property that maps to some shape set ID\n3. A `width` and `height` value for each node. The SVG shapes use `path` elements internally, which require absolute coordinates, and so they need to know the current size of your vertices.\n4. An `x` and `y` value for each node\n\n## Optional data properties[](#optional-data-properties)\n\nThe full list of optional data properties depends on the shape libraries you are using, but all of the VisuallyJs libraries support these optional properties:\n\n* `fill` - Color to fill the shape with. Defaults to `#FFFFFF`.\n* `outline` - Color to outline the shape with. Defaults to `#000000`.\n* `outlineWidth` - Width of the shape's outline. Defaults to 2px.\n* `color` - Color to use for the shape's label (if shown). Defaults to `#000000`.\n\nAs an example, consider this list of two nodes:\n\n```javascript\n[\n{\n \"id\":\"1\",\n \"x\":50,\n \"y\":50,\n \"type\":\"process\",\n \"category\":\"flowchart\",\n \"width\":100,\n \"height\":100,\n \"fill\":\"white\",\n \"outline\":\"black\"\n},\n{\n \"id\":\"2\",\n \"x\":150,\n \"y\":250,\n \"type\":\"terminus\",\n \"category\":\"flowchart\",\n \"width\":100,\n \"height\":100,\n \"fill\":\"white\",\n \"outline\":\"black\"\n}\n]\n\n```\n\nThis is rendered as:\n\n**********\n\n## Displaying Labels[](#displaying-labels)\n\nBy default, a diagram will display a `label` value from each node - if we add `label` to the vertices from before we'll see them:\n\n```javascript\n[\n{\n \"id\":\"1\",\n ...,\n \"label\":\"Node 1\"\n},\n{\n \"id\":\"2\",\n ...,\n \"label\":\"Node 2\"\n}\n]\n\n```\n\n**********\n\n### Hiding labels[](#hiding-labels)\n\nYou can hide labels by setting `showLabels:false` in your diagram's `edges` options:\n\n```jsx\nimport { FLOWCHART_SHAPES, BASIC_SHAPES } from \"@visuallyjs/browser-ui\"\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = ...\n \n const options = {\n shapes: [FLOWCHART_SHAPES, BASIC_SHAPES],\n edges: {\n showLabels: false\n }\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\n## Available sets[](#available-sets)\n\nVisuallyJs ships with two shape sets in the `browser-ui` package and a set of BPMN shapes:\n\n### Flowchart[](#flowchart)\n\n```javascript\nimport { FLOWCHART_SHAPES } from \"@visuallyjs/browser-ui\"\n\n```\n\n***\n\n### Basic[](#basic)\n\n```javascript\nimport { BASIC_SHAPES } from \"@visuallyjs/browser-ui\"\n\n```\n\n### BPMN[](#bpmn)\n\n```javascript\nimport { BPMN2_SHAPES } from \"@visuallyjs/bpmn\"\n\n```\n\ninfo\n\nThese shapes are shipped in the `@visuallyjs/bpmn` library - you'll need to import it.\n\n***\n\n## Custom shape sets[](#custom-shape-sets)\n\nIt's straightforward to make your own shape set - they consist of an id and then a list of shapes, for each of which you provide SVG.\n\nHere we have made a set of faces:\n\n**********\n\n```javascript\nconst shapes = {\n id:\"faces\",\n shapes:[\n {\n type:\"impassive\",\n template:`<g>\n<circle cx=\"{{width/2}}\" cy=\"{{height/2}}\" r=\"{{(width/2)}}\"/>\n <path d=\"M {{width/4}} {{height*3/4}} L {{width*3/4}} {{height*3/4}}\"/>\n <circle cx=\"{{width/4}}\" cy=\"{{height/4}}\" r=\"10\"/>\n <circle cx=\"{{width*3/4}}\" cy=\"{{height/4}}\" r=\"10\"/>\n <circle cx=\"{{width/2}}\" cy=\"{{height/2}}\" r=\"10\"/>\n </g>`,\n label:\"Impassive\"\n },\n {\n type:\"pleased\",\n template:`<g>\n <circle cx=\"{{width/2}}\" cy=\"{{height/2}}\" r=\"{{(width/2)}}\"/> \n <circle cx=\"{{width/4}}\" cy=\"{{height/4}}\" r=\"10\"/>\n <circle cx=\"{{width*3/4}}\" cy=\"{{height/4}}\" r=\"10\"/>\n <circle cx=\"{{width/2}}\" cy=\"{{height/2}}\" r=\"10\"/>\n <path d=\"M {{width/4}} {{height*3/4}} C {{width/4}} {{height*7/8}}, {{width*3/4}} {{height*7/8}} {{width*3/4}} {{height*3/4}}\"/>\n </g>`,\n label:\"Pleased\"\n },\n {\n type:\"notpleased\",\n template:`<g>\n <circle cx=\"{{width/2}}\" cy=\"{{height/2}}\" r=\"{{(width/2)}}\"/> \n <circle cx=\"{{width/4}}\" cy=\"{{height/4}}\" r=\"10\"/>\n <circle cx=\"{{width*3/4}}\" cy=\"{{height/4}}\" r=\"10\"/>\n <circle cx=\"{{width/2}}\" cy=\"{{height/2}}\" r=\"10\"/>\n <path d=\"M {{width/4}} {{height*3/4}} C {{width/4}} {{height*5/8}}, {{width*3/4}} {{height*5/8}} {{width * 0.75}} {{height * 0.75}}\"/>\n </g>`,\n label:\"Not Pleased\"\n }\n ]\n}\n\n```\n\n***\n\n## Nested Shape sets[](#nested-shape-sets)\n\nIt is possible to nest shape sets, via the `children` property of a shape set. For instance, say we want to split our set of faces into two subsets:\n\n```javascript\nconst shapes = {\n id:\"faces\",\n children:[\n {\n id:\"expressionless\",\n name:\"Expressionless\",\n shapes:[\n {\n id:\"impassive\",\n template:`...`\n }\n ]\n }, \n {\n id:\"expressions\",\n name:\"Expressions\",\n shapes:[\n {\n id:\"pleased\",\n template:`...`\n },\n {\n id:\"notpleased\",\n template:`...`\n }\n ]\n }\n ]\n}\n\n```","url":"https://visuallyjs.com/react/docs/diagrams/shapes/shape-libraries","lib":"react","topic":"diagrams"},"docs/diagrams/svg-png-jpg-export.md":{"title":"Svg Png Jpg Export","body":"# SVG, PNG and JPG export\n\nTo export SVG, PNG or JPG from a diagram there are two approaches available to you - use VisuallyJs's export helper UI, or use the low level programmatic API.\n\n## Export helper UI[](#export-helper-ui)\n\nThe export helper UI provides a simple interface to allow your users to export the contents of a surface to an SVG file.\n\n**********\n\nExport SVGExport PNGExport JPG\n\n### SVG Export[](#svg-export)\n\nThe code to invoke the SVG exporter UI is:\n\n```jsx\n\nimport React, { useRef } from \"react\"\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\nimport { SVGExporterUI } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n const surfaceRef = useRef(null)\n \n const exportToSvg = () => {\n // create an exporter and invoke the export method on it\n new SVGExporterUI(surfaceRef.current.surface).export() \n }\n \n return <div>\n <SurfaceComponent ref={surfaceRef}/>\n <button onClick={() => exportToSvg()}>Export SVG</button>\n </div>\n}\n\n\n```\n\nThere are a number of options you can pass in to the export method - they are defined in the [SvgExportOptions]() interface.\n\n### PNG Export[](#png-export)\n\nYou can export to PNG with this code:\n\n```jsx\n\nimport React, { useRef } from \"react\"\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\nimport { ImageExporterUI } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n const surfaceRef = useRef(null)\n \n const exportToPng = () => {\n // create an exporter and invoke the export method on it\n new ImageExporterUI(surfaceRef.current.surface).export() \n }\n \n return <div>\n <SurfaceComponent ref={surfaceRef}/>\n <button onClick={() => exportToPng()}>Export PNG</button>\n </div>\n}\n\n\n```\n\nThere are a number of options you can pass in to the export method - they are defined in the [ImageExportOptions]() interface.\n\n### JPG Export[](#jpg-export)\n\nYou can export to JPG with this code:\n\n```jsx\n\nimport React, { useRef } from \"react\"\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\nimport { ImageExporterUI } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n const surfaceRef = useRef(null)\n \n const exportToJpg = () => {\n // create an exporter and invoke the export method on it\n new ImageExporterUI(surfaceRef.current.surface).export({type:\"image/jpeg\"}) \n }\n \n return <div>\n <SurfaceComponent ref={surfaceRef}/>\n <button onClick={() => exportToJpg()}>Export JPG</button>\n </div>\n}\n\n\n```\n\nThere are a number of options you can pass in to the export method - they are defined in the [ImageExportOptions]() interface.\n\n### CSS Classes[](#css-classes)\n\nThe export helper UI exposes a few CSS classes you can use to style it:\n\n| Class | Purpose |\n| --------------------------- | ------------------------------------------------------------------------------------ |\n| `vjs-export-underlay` | The modal backing element for SVG/PNG/JPG export dialog |\n| `vjs-export-overlay` | Content element for SVG/PNG/JPG export dialog |\n| `vjs-export-cancel` | Assigned to the cancel button on an export dialog |\n| `vjs-export-dimensions` | Assigned to the dimensions drop down in an export dialog |\n| `vjs-export-download-tools` | Assigned to the element containing buttons and dimensions picker on an export dialog |\n\n### Setting PNG/JPG export size[](#setting-pngjpg-export-size)\n\nWhen exporting a PNG or JPG you can provide a desired width or height for the exported image - just provide `width` or `height` as an option:\n\n```jsx\n\nimport React, { useRef } from \"react\"\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\nimport { ImageExporterUI } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n const surfaceRef = useRef(null)\n \n const exportToPng = () => {\n // create an exporter and invoke the export method on it\n new ImageExporterUI(surfaceRef.current.surface).export({width:3000}) \n }\n \n return <div>\n <SurfaceComponent ref={surfaceRef}/>\n <button onClick={() => exportToPng()}>Export PNG</button>\n </div>\n}\n\n\n```\n\n**********\n\nExport PNG\n\nIf you click the export button above you'll get an image with width 3000 pixels. You can also specify height instead of width if you prefer, but if you specify height and width we'll only use the width you provide - the exporter always maintains the aspect ratio of the original image.\n\n### Specifying a set of exportable dimensions[](#specifying-a-set-of-exportable-dimensions)\n\nIf you'd like your users to be able to pick the dimensions of their exported image you can also do that:\n\n```typescript\nimport { ImageExporterUI } from \"@visuallyjs/browser-ui\"\nnew ImageExporterUI(someSurface).export({\n dimensions:[\n { width:3000 },\n { width:1200 },\n { width:800 }\n ]\n})\n\n```\n\nThe entries in `dimensions` can have either width or height, but if you supply both we will, as discussed above, only honour the width. Try clicking the export button here - you'll see a dropdown from which you can pick the size of the export:\n\n**********\n\nExport PNG\n\n## Programmatic export[](#programmatic-export)\n\nThe various methods shown above are wrappers around a lower level API that you can use instead if you wish to.\n\n### SVG Export[](#svg-export-1)\n\n```jsx\n\nimport React, { useRef } from \"react\"\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\nimport { SVGExporter } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n const surfaceRef = useRef(null)\n \n const exportToSvg = () => {\n // create an exporter and invoke the export method on it\n new SVGExporter(surfaceRef.current.surface).export() \n }\n \n return <div>\n <SurfaceComponent ref={surfaceRef}/>\n <button onClick={() => exportToSvg()}>Export SVG</button>\n </div>\n}\n\n\n```\n\n### PNG Export[](#png-export-1)\n\n```jsx\n\nimport React, { useRef } from \"react\"\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\nimport { ImageExporter } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n const surfaceRef = useRef(null)\n \n const exportToPng = () => {\n // create an exporter and invoke the export method on it\n new ImageExporter(surfaceRef.current.surface).export() \n }\n \n return <div>\n <SurfaceComponent ref={surfaceRef}/>\n <button onClick={() => exportToPng()}>Export PNG</button>\n </div>\n}\n\n\n```\n\n### JPG Export[](#jpg-export-1)\n\n```jsx\n\nimport React, { useRef } from \"react\"\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\nimport { ImageExporter } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n const surfaceRef = useRef(null)\n \n const exportToJpg = () => {\n // create an exporter and invoke the export method on it\n new ImageExporter(surfaceRef.current.surface).export({type:\"image/jpeg\"}) \n }\n \n return <div>\n <SurfaceComponent ref={surfaceRef}/>\n <button onClick={() => exportToJpg()}>Export JPG</button>\n </div>\n}\n\n\n```\n\n## Exporting a Selection or Path[](#exporting-a-selection-or-path)\n\nYou can export a Selection or Path to SVG/PNG/JPG. For example here we create a Selection and add nodes \"1\", \"2\" and \"5\" to it, and then export that selection only:\n\n```javascript\nimport { SVGExporter } from \"@visuallyjs/browser-ui\"\n\nconst selection = new Selection(model)\nselection.append([\"1\", \"2\", \"5\"])\nconst exporter = new SVGExporter(surface)\nconst result = exporter.export({ selection })\n\n```\n\n<!-- -->\n\nYou can supply a `selection` to all of the UI exporter methods discussed above.\n\n## Exporting the current selection[](#exporting-the-current-selection)\n\nYou can export the [current selection](/react/docs/diagrams/model/selections#currentSelection) for some model instance to SVG/PNG/JPG. This can be very handy in conjunction with the lasso tool, for example - your users can snag a few nodes and print just those out.\n\n```javascript\nimport React, { useRef, useEffect } from \"react\"\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\nimport { SVGExporter } from \"@visuallyjs/browser-ui\"\n\nexport default function MyComponent() {\n const surfaceRef = useRef(null)\n \n const exportToSvg = () => {\n // create an exporter and invoke the `export` method on it\n const exporter = new SVGExporter(surfaceRef.current.surface)\n const result = exporter.exportCurrentSelection()\n }\n \n return <div>\n <SurfaceComponent ref={surfaceRef}/>\n <button onClick={() => exportToSvg()}>Export SVG</button>\n </div>\n}\n\n\n```","url":"https://visuallyjs.com/react/docs/diagrams/svg-png-jpg-export","lib":"react","topic":"diagrams"},"docs/diagrams.md":{"title":"Diagrams","body":"# Overview\n\nA VisuallyJs <!-- -->React<!-- --> diagram has the following basic structure:\n\n**********\n\n**Controls**\n\n**Miniview**\n\n**Grid**\n\n**Palette**\n\n## Shapes[](#shapes)\n\nIn a diagram, shapes are represented by SVG. Shapes are supplied by one or more `ShapeSets`, and when you create a diagram you tell VisuallyJs which shape set(s) you want to use. Each shape in your diagram has an associated `type`, which identifies it inside a `ShapeSet`, and it also optionally has a `category`, which identifies the shape set it belongs to.\n\nVisuallyJs ships with three shape sets - `Flowchart`, `Basic` and `BPMN2`, and you can easily make your own.\n\nRead more about shapes and shape sets [on this page](/react/docs/diagrams/shapes/overview.md)\n\n## Edges[](#edges)\n\nEdges join shapes, and they can be represented in several different ways - the representation of an edge is called a `Connector`. In the above example we use an `Orthogonal` connector, which consists of horizontal and vertical lines only; VisuallyJs ships with several connector types, including Straight (one or more straight line segments, optionally smoothed), Bezier (a cubic Bézier curve) and QuadraticBezier (a Bézier curve with a single control point), and you can also create your own.\n\nIn the diagram options, you can declare various aspect of how an edge appears, such as the connector used, where on the vertex the edge should be anchored, the appearance of the edge, its label, etc. You can also map event handlers to hook in to mouse/touch events with your edges.\n\n## Mediator[](#mediator)\n\nThe mediator is responsible for managing which operations are allowed in your diagram - such things as which tools should be available on shapes, what can be dropped where, etc. A mediator is optional, but it is a very powerful way to control your diagram in a declarative manner. Read more about the things you can do with a mediator [in the mediator docs](/react/docs/diagrams/controlling-diagram-actions.md).\n\n## Controls[](#controls)\n\nCommon controls such as zoom to extents, undo/redo, clear dataset - and many more - are available in a dedicated component. Read about configuring the controls component [on this page](/react/docs/diagrams/controls).\n\n## Miniview[](#miniview)\n\nProvides a summary view of your diagram and allows you to zoom (via pinch/mouse wheel), pan and center on specific elements. Read about configuring the controls component [on this page](/react/docs/diagrams/miniview).","url":"https://visuallyjs.com/react/docs/diagrams","lib":"react","topic":""},"docs/mcp.md":{"title":"Mcp","body":"# MCP Server\n\nThis guide explains how to configure various AI agents and IDEs to use the VisuallyJs MCP servers. These servers provide documentation and search capabilities for `@visuallyjs/browser-ui` and its library-specific integrations.\n\n## Available MCP Servers[](#available-mcp-servers)\n\nYou can choose to install the all-in-one server or a specific one for your library:\n\n| Package | Library | Command |\n| ------------------------------------ | ------------------------------------------ | ---------------------------------------- |\n| `@visuallyjs/browser-ui-angular-mcp` | Angular | `npx @visuallyjs/browser-ui-angular-mcp` |\n| `@visuallyjs/browser-ui-react-mcp` | React | `npx @visuallyjs/browser-ui-react-mcp` |\n| `@visuallyjs/browser-ui-svelte-mcp` | Svelte | `npx @visuallyjs/browser-ui-svelte-mcp` |\n| `@visuallyjs/browser-ui-vue-mcp` | Vue | `npx @visuallyjs/browser-ui-vue-mcp` |\n| `@visuallyjs/browser-ui-vanilla-mcp` | Vanilla JS | `npx @visuallyjs/browser-ui-vanilla-mcp` |\n| `@visuallyjs/browser-ui-mcp` | All (Angular, React, Svelte, Vue, Vanilla) | `npx @visuallyjs/browser-ui-mcp` |\n\n### Version Management[](#version-management)\n\nThe MCP package versions are kept in sync with their related `@visuallyjs/browser-ui` packages.\n\nWhile it's not required (omitting the version will always pull the latest), you may want to include a specific version number in your configuration to ensure compatibility with the version of VisuallyJs you are using in your project.\n\nTo use a specific version, append `@<version>` to the package name:\n\n* `npx -y @visuallyjs/browser-ui-mcp@1.1.0`\n\n***\n\n## Setup[](#setup)\n\n### Claude Desktop[](#claude-desktop)\n\nTo use VisuallyJs MCP with Claude Desktop, you need to edit your `claude_desktop_config.json` file.\n\n1. Open your Claude Desktop configuration file:\n\n * **macOS:** `~/Library/Application\\ Support/Claude/claude_desktop_config.json`\n * **Windows:** `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n2. Add the server to the `mcpServers` section. For example, to add the all-in-one server:\n\n```json\n{\n \"mcpServers\": {\n \"visuallyjs\": {\n \"command\": \"npx\",\n \"args\": [\n \"-y\",\n \"@visuallyjs/browser-ui-mcp\"\n ]\n }\n }\n}\n\n```\n\n3. Restart Claude Desktop.\n\n***\n\n### Cursor[](#cursor)\n\nCursor supports MCP servers natively.\n\n1. Open Cursor and go to **Settings** > **Cursor Settings** > **Features**.\n\n2. Scroll down to the **MCP** section.\n\n3. Click on **+ Add New MCP Server**.\n\n4. Fill in the details:\n\n <!-- -->\n\n * **Name:** `VisuallyJs`\n * **Type:** `command`\n * **Command:** `npx -y @visuallyjs/browser-ui-mcp` (or your framework-specific package)\n\n5. Click **Save**.\n\n***\n\n### IntelliJ IDEA[](#intellij-idea)\n\nIn IntelliJ IDEA, you can configure MCP servers for both the **AI Assistant** and **Junie**.\n\n#### AI Assistant[](#ai-assistant)\n\n1. Open **Settings** (or **Settings/Preferences** on macOS) and navigate to **Tools** > **AI Assistant**.\n\n2. Look for the **MCP Servers** section.\n\n3. Click **+ Add Server**.\n\n4. Configure the server:\n\n <!-- -->\n\n * **Name:** `VisuallyJs`\n * **Command:** `npx`\n * **Arguments:** `-y @visuallyjs/browser-ui-mcp` (or your specific framework package)\n\n5. Click **OK** to save.\n\n#### Junie[](#junie)\n\n1. Open **Settings** and navigate to **Tools** > **Junie**.\n\n2. Find the **MCP Servers** configuration area.\n\n3. Click **Add** or **+**.\n\n4. Fill in the details:\n\n <!-- -->\n\n * **Name:** `VisuallyJs`\n * **Command:** `npx`\n * **Arguments:** `-y @visuallyjs/browser-ui-mcp`\n\n5. Click **Save** or **Apply**.\n\n***\n\n### VS Code (via Continue or Roo Code)[](#vs-code-via-continue-or-roo-code)\n\n#### Continue[](#continue)\n\nFollow the same steps as for IntelliJ (edit `~/.continue/config.json`).\n\n#### Roo Code (formerly Roo Cline)[](#roo-code-formerly-roo-cline)\n\n1. Open the Roo Code side panel.\n\n2. Click on the **Settings** (cog) icon.\n\n3. Find the **MCP Servers** section.\n\n4. Add the server:\n\n <!-- -->\n\n * **Name:** `visuallyjs`\n * **Command:** `npx -y @visuallyjs/browser-ui-mcp`\n\n***\n\n### Goose[](#goose)\n\nGoose is a CLI-based agent that supports MCP.\n\nTo add the VisuallyJs MCP server to Goose:\n\n```bash\ngoose configure\n\n```\n\nFollow the prompts to add a new MCP server with the command `npx -y @visuallyjs/browser-ui-mcp`.\n\nAlternatively, you can manually edit the goose configuration file (usually in `~/.goose/config.yaml` or similar depending on your OS).\n\n***\n\n### Other Agents[](#other-agents)\n\nMost agents that support the Model Context Protocol (MCP) follow a similar pattern: they require a `command` (usually `npx`) and `arguments` (the package name).\n\nIf you are using a different agent, look for \"MCP\" or \"Model Context Protocol\" in its settings and provide the following:\n\n* **Command:** `npx`\n* **Arguments:** `-y @visuallyjs/browser-ui-mcp`\n\n***\n\n## Available Tools[](#available-tools)\n\nEach library-specific package provides tools with unique suffixes, allowing them to coexist in a flat namespace if multiple servers are connected simultaneously. Tools are named following the pattern `search_vjs_<suffix>` for general documentation and `search_vjs_<suffix>_api` for API-specific documentation.\n\n### Angular[](#angular)\n\n* `search_vjs_ng`: Search VisuallyJs Angular documentation.\n* `search_vjs_ng_api`: Search VisuallyJs Angular API documentation.\n\n### React[](#react)\n\n* `search_vjs_react`: Search VisuallyJs React documentation.\n* `search_vjs_react_api`: Search VisuallyJs React API documentation.\n\n### Vue[](#vue)\n\n* `search_vjs_vue`: Search VisuallyJs Vue documentation.\n* `search_vjs_vue_api`: Search VisuallyJs Vue API documentation.\n\n### Svelte[](#svelte)\n\n* `search_vjs_svelte`: Search VisuallyJs Svelte documentation.\n* `search_vjs_svelte_api`: Search VisuallyJs Svelte API documentation.\n\n### Vanilla[](#vanilla)\n\n* `search_vjs_vanilla`: Search VisuallyJs Vanilla documentation.\n* `search_vjs_vanilla_api`: Search VisuallyJs Vanilla API documentation.\n\n### All libraries[](#all-libraries)\n\nThe `@visuallyjs/browser-ui-mcp` package (the `all` package) offers all of the search commands from each of the library-specific packages listed above. This allows you to have a single MCP server that can search across all VisuallyJs integrations.","url":"https://visuallyjs.com/react/docs/mcp","lib":"react","topic":""},"docs/npm-repository.md":{"title":"Npm Repository","body":"# NPM Repository\n\nThe VisuallyJs packages are hosted in two places:\n\n* In the public NPM repository (<https://registry.npmjs.org>) there is a watermarked version of each package which can be used for evaluation and for users who satisfy the conditions of non-commercial usage.\n* For licensees, the packages are hosted in our private VisuallyJs NPM repository. This repository is available to all licensees who currently have access to download new releases.\n\n## VisuallyJs Repository details[](#visuallyjs-repository-details)\n\nNote the trailing slash on the repository location: this must be included.\n\n```javascript\nhttps://repository.visuallyjs.com/visuallyjs/\n\n```\n\n## Logon[](#logon)\n\nTo login to the VisuallyJs NPM repository you use your licensee ID:\n\n```bash\nnpm adduser --registry=https://repository.visuallyjs.com/visuallyjs/\n...\nUsername: <licensee id>\nPassword: <...>\n\n```\n\nYour password will have been supplied in an email from VisuallyJs.\n\n## .npmrc[](#npmrc)\n\nYou'll need to map the `@visuallyjs` scope to VisuallyJs's NPM repository. For that, ensure your `.npmrc` has these entries:\n\n```bash\n@visuallyjs:registry=https://repository.visuallyjs.com/visuallyjs/\n\n```\n\n## Tokens[](#tokens)\n\nRunning the `npm adduser` command to login to the NPM repository will result in an `authToken` being written to your local `.npmrc`. For licensees, the number of active tokens is determined relative to the number of developer seats purchased: for single seat licensees, one token is supported. For holders of a small team (1-5 developers) license, 6 concurrent tokens are supported. For holders of a team (1-10 developers) license, 12 concurrent tokens are supported. The extra token(s) are intended to help if you have a machine that runs automated builds or some such setup. For holders of an unlimited seats developer license, unlimited NPM tokens are supported.\n\n## Repository Availability[](#repository-availability)\n\nWhilst every effort is made to ensure the repository is available at all times, VisuallyJs enters into no Service Level Agreement with licensees as to the availability of the NPM repository. It is recommended that all licensees download the VisuallyJs packages from our [Downloads Page](https://visuallyjs.com/download).","url":"https://visuallyjs.com/react/docs/npm-repository","lib":"react","topic":""},"docs/quickstart.md":{"title":"Quickstart","body":"# Quick Start\n\n## Installation[](#installation)\n\nFirst create a new app (if you need to, otherwise skip this and move to the install command below). There are various tools for this, but we'd recommend [Vite](https://vitejs.dev/).\n\n* npm\n* pnpm\n* yarn\n* bun\n\n```bash\nnpm init vite visuallyjs-app -- --template react\n\n```\n\n```bash\npnpm create vite visuallyjs-app -- --template react\n\n```\n\n```bash\nyarn create vite visuallyjs-app -- --template react\n\n```\n\n```bash\nbunx create-vite visuallyjs-app -- --template react\n\n```\n\nThen `cd` into your project directory and install VisuallyJs:\n\n* npm\n* pnpm\n* yarn\n* bun\n\n```bash\nnpm install @visuallyjs/browser-ui-react\n\n```\n\n```bash\npnpm add @visuallyjs/browser-ui-react\n\n```\n\n```bash\nyarn add @visuallyjs/browser-ui-react\n\n```\n\n```bash\nbun add @visuallyjs/browser-ui-react\n\n```\n\n## MCP[](#mcp)\n\nTo speed up your development you can optionally setup our MCP server with your agent - we provide tools for searching the docs and the apidocs for each library integration. A full discussion of our MCP servers are available on [this page](/react/docs/mcp.md), but if you've done this before, this is the command you need:\n\n```bash\nnpx @visuallyjs/browser-ui-react-mcp\n\n```\n\n## Usage[](#usage)\n\nWhat do you want to build? VisuallyJs can be used to build a variety of different solutions. We split them up into four main categories:\n\n#### [Apps](#apps)[](#apps)\n\nApps use <!-- -->React<!-- --> components to render each node/group in the display. Functionality can be encapsulated in these components. Node/group sizes in an App are typically dependent on CSS and are managed automatically by VisuallyJs. Apps are great when you need rich content in your nodes/groups and you don't want to be limited to using SVG.\n\n#### [Diagrams](#diagrams)[](#diagrams)\n\nDiagrams are pure SVG applications, that draw SVG shapes into an SVG canvas, and provide an API to manipulate each cell/link individually. VisuallyJs offers a <!-- -->React<!-- --> component that you can use to seamlessly embed a Diagram into your application, as well as several other components such as a miniview, a palette (from which shapes can be dragged onto the canvas), and basic controls such as pan/zoom/undo/redo etc.\n\n#### [Charts](#charts)[](#charts)\n\nVisuallyJs includes a wide range of chart types—from standard Line and Bar charts to more specialized Pie, Donut, and Scatter charts, which can be rendered standalone, or integrated with the data model that is powering an App or Diagram on the same page.\n\n#### [Dashboards](#dashboards)[](#dashboards)\n\nA powerful feature of VisuallyJs is the ability to mix and match different types of components on a single page. You can create a dashboard that combines a rich node-based canvas or a diagram with real-time charts, all powered by the same underlying data model.\n\nFor example, you might have an app representing a manufacturing process where clicking on a machine (a node in the app) updates a set of charts showing that machine's performance metrics. Or a supply chain visualizer with an attached sankey diagram giving you insights into the flow of materials - there are endless possibilities.\n\n\n\n### Apps[](#apps)\n\nWe'll use the `SurfaceComponent` from `@visuallyjs/browser-ui-react` to render a zoomable and pannable canvas.\n\n1. Remove all the code from `src/App.jsx` and replace with this:\n\n```jsx\nimport { SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = {\n nodes:[\n { id:\"1\", label:\"Hello\", left:50, top:50 },\n { id:\"2\", label:\"World\", left:50, top:250 }\n ],\n edges:[\n { source:\"1\", target:\"2\" }\n ]\n }\n \n return <div className=\"my-container\">\n <SurfaceComponent data={data}/>\n </div>\n}\n\n\n```\n\n2. Remove all the code from `src/index.css` and `src/App.css` and put this into `src/index.css`:\n\n```css\n\n.my-container {\n width:600px;\n height:500px;\n position:relative;\n outline:1px solid;\n}\n\n.vjs-surface {\n width:100%;\n height:100%;\n}\n\n\n```\n\n<br />\n\nAnd that's it! It's very easy to quickly build apps with VisuallyJs. That example uses some default JSX to render the nodes, which is great to get you up and running, but you'll typically want to provide your own. In this next snippet we supply the JSX to render each node and we add a miniview and some controls.\n\nReplace the contents of `src/App.jsx` with this:\n\n```jsx\nimport { SurfaceComponent, SurfaceProvider, ControlsComponent, MiniviewComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function App() {\n \n const data = {\n nodes:[\n { id:\"1\", label:\"Hello\", left:50, top:50, bg:\"cadetblue\" },\n { id:\"2\", label:\"World\", left:50, top:200, bg:\"forestgreen\" }\n ],\n edges:[\n { source:\"1\", target:\"2\" }\n ]\n }\n \n const viewOptions = {\n nodes:{\n default:{\n jsx:(ctx) => <div style={{backgroundColor:ctx.obj.data.bg}} className=\"my-node\">\n <span onClick={() => alert(`You clicked on vertex ${ctx.obj.id}`)}>\n {ctx.obj.data.label}\n </span>\n </div>\n }\n }\n } \n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <SurfaceProvider>\n <SurfaceComponent data={data} viewOptions={viewOptions}/>\n <ControlsComponent/>\n <MiniviewComponent/>\n </SurfaceProvider>\n </div> \n}\n\n\n```\n\nRemove all the code from `src/index.css` and `src/App.css` and put this into `src/index.css`:\n\n```css\n\n@import \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\n.my-container {\n width:600px;\n height:500px;\n position:relative;\n outline:1px solid;\n}\n\n.vjs-surface {\n width:100%;\n height:100%;\n}\n\n.my-node {\n color:white;\n display:flex;\n align-items: center;\n justify-content: center;\n width:100px;\n height:60px;\n}\n\n\n```\n\n**********\n\nTry clicking on the label for each node - you'll get a popup with its ID. This is a simple example but hopefully gives you an idea of what is possible when you use React components to render the nodes in your UI.\n\nTo find out more about building React apps with VisuallyJs, we'd suggest [starting here](/react/docs/apps.md).\n\n### Diagrams[](#diagrams)\n\n***\n\nDiagrams use SVG shapes to render their nodes and groups. It's straightforward to create one - first replace the contents of `src/App.jsx` with this code:\n\n```jsx\nimport { FLOWCHART_SHAPES, ArrowOverlay } from \"@visuallyjs/browser-ui\"\nimport { DiagramComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = {\n nodes:[\n {id:\"1\",label:\"Begin\",x:50,y:50,width:100,height:40,type:\"terminus\"},\n {id:\"2\",label:\"Test\",x:70,y:200,width:60,height:60,type:\"decision\"}\n ],\n edges:[\n {source:\"1\",target:\"2\"}\n ]\n}\n \n const options = {\n shapes: FLOWCHART_SHAPES,\n edges: {\n overlays: [\n {\n type: ArrowOverlay.type,\n options: {\n location: 1\n }\n }\n ]\n },\n zoomToFit: true\n}\n \n return <div style={{width:\"100%\", height:\"500px\"}}>\n <DiagramComponent data={data} options={options}/>\n </div> \n}\n\n```\n\nThen, remove all the code from `src/index.css` and `src/App.css` and put this into `src/index.css`:\n\n```css\n\n@import \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\n.my-container {\n width:600px;\n height:500px;\n position:relative;\n outline:1px solid;\n}\n\n.vjs-surface {\n width:100%;\n height:100%;\n}\n\n\n```\n\n**********\n\n### Charts[](#charts)\n\n***\n\nVisuallyJs has support for many different types of charts. Here's a simple column chart:\n\nwhich we generated with this code:\n\n```jsx\nimport {ColumnChartComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyChart() {\n\n const data = [\n {id:\"USA\",corn:387749,wheat:45321},\n {id:\"China\",corn:280000,wheat:140000},\n {id:\"Brazil\",corn:129000,wheat:10000},\n {id:\"EU\",corn:64300,wheat:140500},\n {id:\"Argentina\",corn:54000,wheat:19500},\n {id:\"India\",corn:34300,wheat:113500}\n]\n \n const options = {\n title: {\n text: \"Corn vs wheat estimated production for 2023\"\n },\n valueAxis: [\n {\n title: {\n text: \"1000 metric tons (MT)\"\n }\n }\n ],\n series: [\n {\n valueField: \"corn\",\n label: \"Corn\"\n },\n {\n valueField: \"wheat\",\n label: \"Wheat\"\n }\n ]\n} \n \n return <ColumnChartComponent options={options} className=\"my-chart\" data={data}/>\n}\n\n```\n\nHere we pass the data in to the chart when the chart is created, but there are a number of ways to supply data to chart, including the powerful ability for a chart to source its data from the model backing an App or Diagram.\n\nSee the [charts docs](/react/docs/charts/concepts/overview.md) for a full discussion of how to use VisuallyJs to render charts.\n\n### Dashboards[](#dashboards)\n\n***\n\nIt's easy to build dashboards with VisuallyJs where multiple components all reference the same data model. Here we'll show you a quick example which is from our [dashboards documentation](/react/docs/dashboards.md) - a scatter chart that reflects the positions of the nodes in the canvas.\n\n1. Remove all the code from `src/App.jsx` and replace with this:\n\n```jsx\nimport { SurfaceComponent, SurfaceProvider, ScatterChartComponent } from \"@visuallyjs/browser-ui-react\"\nimport \"@visuallyjs/browser-ui/css/visuallyjs.css\";\n\nexport default function App() {\n \n const data = {\n nodes:[\n { id:\"1\", label:\"Hello\", left:50, top:50 },\n { id:\"2\", label:\"World\", left:50, top:250 },\n { id:\"3\", label:\"Hola\", left:250, top:150 }\n ],\n edges:[\n { source:\"1\", target:\"2\" }\n ]\n }\n \n return <div className=\"my-container\">\n <SurfaceProvider>\n <SurfaceComponent data={data}/>\n <ScatterChartComponent options={{\n series:[\n {\n xAxisField:\"left\",\n yAxisField:\"top\",\n color:\"#569934\"\n }\n ],\n yAxis:{\n inverted:true\n }\n }}/> \n </SurfaceProvider> \n </div>\n}\n\n\n```\n\n2. Remove all the code from `src/index.css` and `src/App.css` and put this into `src/index.css`:\n\n```css\n\n.my-container {\n width:600px;\n height:500px;\n position:relative;\n outline:1px solid;\n display:flex;\n}\n\n.vjs-surface {\n flex:0 0 50%;\n height:100%;\n}\n\n.vjs-scatter-chart {\n flex:0 0 50%;\n height:100%;\n}\n\n\n```\n\n**********\n\n## Next Steps[](#next-steps)\n\n***\n\nWhere to from here?\n\n[Apps](/react/docs/apps.md)\n\n[Read about building professional visual apps with React components](/react/docs/apps.md)\n\n[Diagrams](/react/docs/diagrams.md)\n\n[Read about how to build SVG diagrams with VisuallyJs](/react/docs/diagrams.md)\n\n[Charts](/react/docs/charts)\n\n[Read about VisuallyJs's powerful chart engine](/react/docs/charts)\n\n[Dashboards](/react/docs/dashboards.md)\n\n[Read more about how to build dashboards with VisuallyJs](/react/docs/dashboards.md)\n\n[Templates](/react/templates)\n\n[Clone an app, diagram or chart template project](/react/templates)\n\n[API Reference](/api-reference)\n\n[Browse the VisuallyJs API docs](/api-reference)","url":"https://visuallyjs.com/react/docs/quickstart","lib":"react","topic":""},"docs/reference/ColorPickerComponent.md":{"title":"ColorPickerComponent","body":"# \\<ColorPickerComponent/>\n\nA helper component that offers the ability to change color and keep a history of selected colors, for use with an [InspectorComponent](/react/docs/reference/InspectorComponent.md).\n\n## Usage[](#usage)\n\nIf you haven't yet read the docs for [InspectorComponent](/react/docs/reference/InspectorComponent.md) we'd recommend it.\n\nThis component is used in the template for an inspector. You need to pass in the name of the property to manage.\n\n```jsx\n\nimport { useState } from \"react\"\nimport { ColorPickerComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyInspectorComponent(props) {\n\n const [currentType, setCurrentType] = useState('')\n const renderEmptyContainer = () => setCurrentType('')\n \n // a Node, Edge, Group or Port\n const refresh= (obj, cb) => {\n setCurrentType(obj.objectType)\n }\n\n return <InspectorComponent refresh={refresh}\n renderEmptyContainer={renderEmptyContainer}>\n \n <ColorPickerComponent propertyName=\"bgColor\"/>\n\n </InspectorComponent>\n}\n \n\n```\n\n## Inputs[](#inputs)\n\nColorPickerComponentProps\n\nProps for the ColorPicker inspector component.\n\n| Name | Type | Description |\n| ------------ | ------ | ---------------------------------------------------------------- |\n| maxColors? | number | Maximum color swatches to show. Defaults to 10. |\n| propertyName | string | Property name in the data that this picker represents. Required. |","url":"https://visuallyjs.com/react/docs/reference/colorpickercomponent","lib":"react","topic":""},"docs/reference/ControlsComponent.md":{"title":"ControlsComponent","body":"# \\<ControlsComponent/>\n\nThis component provides a set of controls for a surface - such operations as zoom to extents, undo/redo, clear, etc. The operations that are available can be specified on the controls element, and you can also add your own buttons.\n\n## Usage[](#usage)\n\n### Apps[](#apps)\n\nThis component is context aware and will discover the Surface to attach itself to if it is a child of a `SurfaceComponent`:\n\n```jsx\n<SurfaceComponent renderOptions={...} data={...}>\n <ControlsComponent />\n</SurfaceComponent>\n\n```\n\nor if it is a descendant of a `SurfaceProvider`:\n\n```jsx\n<SurfaceProvider>\n <SurfaceComponent renderOptions={...} data={...}/>\n <div className=\"someContainer\">\n <ControlsComponent/>\n </div>\n</SurfaceProvider>\n\n```\n\n### Diagrams[](#diagrams)\n\nThis component is context aware and will discover the Diagram to attach itself to if it is a child of a `DiagramComponent`:\n\n```jsx\n<DiagramComponent options={...} data={...}>\n <ControlsComponent />\n</DiagramComponent>\n\n```\n\nor if it is a descendant of a `DiagramProvider`:\n\n```jsx\n<DiagramProvider>\n <DiagramComponent options={...} data={...}/>\n <div className=\"someContainer\">\n <ControlsComponent/>\n </div>\n</DiagramProvider>\n\n```\n\n## Props[](#props)\n\nControlsComponentProps\n\nProps for the controls component.\n\n| Name | Type | Description |\n| -------------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| buttons? | [ControlsComponentButtons]() | Optional extra buttons to add to the controls component. |\n| className? | string | Optional class name to append to the root element's class list. |\n| clear? | boolean | Whether or not to show the clear button, defaults to true. |\n| clearMessage? | string | Optional message for the alert that the clear button shows by default. Defaults to `Clear dataset?`. |\n| onMaybeClear? | (doClear:() => void) => void | Optional callback to invoke when the user presses the clear button. If you provide this, the component will not show an alert, and instead call this method, passing in a function you can invoke if you wish to continue with the clear operation. |\n| orientation? | \"row\" \\| \"column\" | Optional orientation for the controls. Defaults to 'row'. |\n| style? | Record\\<string,string> | Optional style object to apply to the container element. |\n| surfaceId? | string | The ID of surface to attach to. Optional. Will be inferred from context if not provided. |\n| undoRedo? | boolean | Whether or not to show undo/redo buttons, defaults to true |\n| zoomButtons? | boolean | Whether or not to show the zoom in/zoom out buttons, defaults to false |\n| zoomToExtents? | boolean | Whether or not to show the zoom to extents button, defaults to true |","url":"https://visuallyjs.com/react/docs/reference/controlscomponent","lib":"react","topic":""},"docs/reference/DecoratorComponent.md":{"title":"DecoratorComponent","body":"# \\<DecoratorComponent/>\n\nThis component allows you to position content relative to the canvas in your UI - either floating on top, or positioned with the canvas content.\n\nContent can be any valid JSX.\n\n## Usage[](#usage)\n\n### Floating content[](#floating-content)\n\nThe default behaviour is to float the content above the UI canvas, where `position` is relative to the canvas viewport:\n\n```jsx\n<SurfaceComponent .../>\n <DecoratorComponent position={{x:50, y:50}}>\n <h4>Hello World</h4>\n <button onClick={() => alert(\"You can include any JSX you like\")}>click me</button>\n </DecoratorComponent>\n</SurfaceComponent>\n\n```\n\n### Fixed content[](#fixed-content)\n\nYou can specify \"'fixed'\" positioning if you want to place the conent on the canvas. Here, `position` will be treated as a point relative to the canvas origin, and the content will be drawn on the UI canvas alongside the vertices and edges:\n\n```jsx\n<SurfaceComponent .../>\n <DecoratorComponent position={{x:50, y:50}} placement={\"fixed\"}>\n <h4>Hello World</h4>\n <button onClick={() => alert(\"You can include any JSX you like\")}>click me</button>\n </DecoratorComponent>\n</SurfaceComponent>\n\n```\n\n### Clamping to canvas[](#clamping-to-canvas)\n\nWhen using `fixed` content, you can instruct VisuallyJs to prevent the fixed element from being panned out of the viewport, by supplying constraints to the decorator - here we instruct VisuallyJs to clamp in both the left and top directions:\n\n```jsx\n<SurfaceComponent .../>\n <DecoratorComponent position={{x:50, y:50}} \n placement={\"fixed\"} \n constraints={{left:true, top:true}}>\n <h4>Hello World</h4>\n <button onClick={() => alert(\"You can include any JSX you like\")}>click me</button>\n </DecoratorComponent>\n</SurfaceComponent>\n\n```\n\n## Props[](#props)\n\nDecoratorComponentProps\n\nProps for the DecoratorComponent\n\n| Name | Type | Description |\n| ------------ | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| constraints? | [FixedElementConstraints]() | Optional constraints when using fixed placement: you can instruct the UI to restrict movement in one or both axes. |\n| placement? | \"fixed\" \\| \"floating\" | Whether to float the element over the UI, so that it does not move with the content (floating), or to place the element onto the canvas, so that it moves/zooms with the content (fixed). Floating is the default. |\n| position? | [PointXY]() | For floating placement, this is a point relative to the viewport origin. for fixed placement, this is a point relative to the canvas origin. Defaults to 0,0. |","url":"https://visuallyjs.com/react/docs/reference/decoratorcomponent","lib":"react","topic":""},"docs/reference/DiagramComponent.md":{"title":"DiagramComponent","body":"# \\<DiagramComponent/>\n\nProvides an SVG diagram component. This is a wrapper around a Surface or Paper, with a few flags set:\n\n* We use an SVG container element\n* Every cell is drawn as an SVG element from a ShapeLibrary\n* Cell sizes and positions are stored inside the model\n\nA Diagram is a pure SVG UI.\n\n## Usage[](#usage)\n\n```jsx\nimport {DiagramComponent} from \"@visuallyjs/browser-ui-react\";\nimport {FLOWCHART_SHAPES} from \"@visuallyjs/browser-ui\";\n\nexport default function MyApp() {\n const options = {\n shapes: [FLOWCHART_SHAPES]\n }\n \n const data = {\n nodes:[\n { id:\"1\", x:50, top:50, width:150, height:100, type:\"process\" },\n { id:\"2\", x:250, top:250, width:150, height:100, type:\"terminus\" }\n ]\n }\n\n return <DiagramComponent options={options} data={data}/>\n}\n\n\n```\n\n## Props[](#props)\n\nDiagramComponentProps\n\nProps for the DiagramComponent\n\n| Name | Type | Description |\n| ------------- | ---------------------- | -------------------------------------------------------- |\n| className? | string | Optional class name to set on the container |\n| data? | any | Optional initial data |\n| modelOptions? | [ModelOptions]() | Options for the underlying model |\n| options? | [DiagramOptions]() | Options for the Diagram |\n| style? | Record\\<string,string> | Optional style object to apply to the container element. |\n| url? | string | Optional URL to load initial data from. |\n\n## Ref Handle[](#ref-handle)\n\nIf you bind this component to a ref, you get an object of type `DiagramComponentRef`:\n\nDiagramComponentRef\n\nHandle for a DiagramComponent.\n\n| Name | Type | Description |\n| ---------- | ----------------- | ----------------------------------------- |\n| getDiagram | () => [Diagram]() | Gets the underlying Diagram from UI core. |","url":"https://visuallyjs.com/react/docs/reference/diagramcomponent","lib":"react","topic":""},"docs/reference/DiagramPaletteComponent.md":{"title":"DiagramPaletteComponent","body":"# \\<DiagramPaletteComponent/>\n\nA shape palette for linking with a [DiagramComponent](/react/docs/reference/DiagramComponent.md). This component will automatically display the shapes available to the Diagram it is attached to, allowing your users to drag them onto your Diagram, or to click to add.\n\n## Usage[](#usage)\n\nYou'll need to declare a `DiagramProvider` in your JSX, and have the `DiagramComponent` and `DiagramPaletteComponent` both be descendants of that element:\n\n```jsx\nimport {DiagramProvider, DiagramComponent, DiagramPaletteComponent } from \"@visuallyjs/browser-ui-react\";\n\nexport default function MyApp() {\n return <DiagramProvider>\n <DiagramComponent options={...}/>\n <DiagramPaletteComponent/>\n </DiagramProvider>\n}\n\n\n```\n\n## Props[](#props)\n\nSorry - we could not find this document.","url":"https://visuallyjs.com/react/docs/reference/diagrampalettecomponent","lib":"react","topic":""},"docs/reference/EdgeTypePickerComponent.md":{"title":"EdgeTypePickerComponent","body":"# \\<EdgeTypePickerComponent/>\n\nThis component provides the means for a user to pick an edge type from a visual rendering of the available options. It reads the current list of edge property mappings from the surface its inspector is attached to, and draws a sample of each one in a list for the user to select from. It is designed for use inside of an Inspector.\n\n## Usage[](#usage)\n\nIf you haven't yet read the docs for [InspectorComponent](/react/docs/reference/InspectorComponent.md) we'd recommend it.\n\nThis component is used in the template for an inspector. It uses the [useInspector() hook](/react/docs/reference/UseInspectorHook.md) to resolve an inspector to attach to - you just need to tell it the name of the property you want to manage.\n\n```jsx\n\nimport { useState } from \"react\"\nimport { EdgeTypePickerComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyInspectorComponent(props) {\n\n const [currentType, setCurrentType] = useState('')\n const renderEmptyContainer = () => setCurrentType('')\n \n // a Node, Edge, Group or Port\n const refresh= (obj, cb) => {\n setCurrentType(obj.objectType)\n }\n\n return <InspectorComponent refresh={refresh} \n renderEmptyContainer={renderEmptyContainer}>\n \n <EdgeTypePickerComponent propertyName=\"edgeType\"/>\n\n </InspectorComponent>\n}\n \n\n```\n\n## Props[](#props)\n\nEdgeTypePickerComponentProps\n\nProps for the EdgeTypePickerComponent\n\n| Name | Type | Description |\n| ------------ | ------ | ------------------------------------------------ |\n| propertyName | string | Name of the property to get/set in the edge data |\n\n## Edge Mappings[](#edge-mappings)\n\nThis component expects that you have some edge mappings declared on your surface - it is these that the component displays for the user to select from.\n\nEdge mappings allows you to match specific values for a given property to a set of config options for an edge.\n\nAn edge mapping declares a `property`, which is the name of some property an edge's backing data that VisuallyJs will attempt to match. In the code snippet below we're matching the property `lineStyle`. Then there is a `mappings` section, which is an object whose keys are the values we're matching.\n\nIn this example we see four possible matches - `\"source\"`, `\"target\"`, `\"plain\"` and `\"dashed\"`. Each match then declares a set of zero or more configuration options for the edge.\n\n```json\n{\n \"property\": \"lineStyle\",\n \"mappings\": {\n \"source\": {\n \"overlays\": [\n {\n \"type\": \"Arrow\",\n \"options\": {\n \"location\": 0,\n \"direction\": -1,\n \"width\": 5,\n \"length\": 10\n }\n }\n ]\n },\n \"target\": {\n \"overlays\": [\n {\n \"type\": \"Arrow\",\n \"options\": {\n \"location\": 1,\n \"width\": 5,\n \"length\": 10\n }\n }\n ]\n },\n \"plain\": {},\n \"dashed\": {\n \"cssClass\": \"some-css-class\"\n }\n }\n}\n\n```","url":"https://visuallyjs.com/react/docs/reference/edgetypepickercomponent","lib":"react","topic":""},"docs/reference/ExportControlsComponent.md":{"title":"ExportControlsComponent","body":"# \\<ExportControlsComponent/>\n\nProvides a set of buttons allowing your users to export a given canvas as SVG, PNG or JPG.\n\ninfo\n\nThis component only works when your surface is using a `ShapeLibrary` to render elements, or if you are using a `Diagram`.\n\n## Usage[](#usage)\n\nThis component is context aware and will discover the Surface to attach itself to if it is a child of a `SurfaceComponent`:\n\n```jsx\nimport { FLOWCHART_SHAPES } from \"@visuallyjs/browser-ui\"\nimport { SurfaceComponent, ExportControlsComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function() {\n const renderOptions = {\n shapes:{\n sets:[FLOWCHART_SHAPES]\n }\n }\n return <SurfaceComponent renderOptions={renderOptions} data={...}>\n <ExportControlsComponent />\n </SurfaceComponent> \n}\n\n```\n\nor if it is a descendant of a `SurfaceProvider`:\n\n```jsx\nimport { FLOWCHART_SHAPES } from \"@visuallyjs/browser-ui\"\nimport { SurfaceComponent, ExportControlsComponent, SurfaceProvider} from \"@visuallyjs/browser-ui-react\"\n\nexport default function() {\n const renderOptions = {\n shapes:{\n sets:[FLOWCHART_SHAPES]\n }\n }\n return <SurfaceProvider> \n <SurfaceComponent renderOptions={renderOptions} data={...}/>\n <ExportControlsComponent />\n </SurfaceProvider>\n}\n\n```\n\n## Props[](#props)\n\nExportControlsComponentProps\n\nOptions for the ExportControlsComponent\n\n| Name | Type | Description |\n| --------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| allowJpgExport? | boolean | Defaults to true. |\n| allowPngExport? | boolean | Defaults to true. |\n| allowSvgExport? | boolean | Defaults to true. |\n| imageOptions? | [ImageExportUIOptions]() | Options for image exports. |\n| label? | string | What to show in the label, if visible. Defaults to \"Export:\". |\n| margins? | [PointXY]() | Optional margins to apply to both SVG and image exports. Will not override any margins specified in svgOptions or imageOptions. |\n| showLabel? | boolean | Whether or not to show a label in front of the buttons. Defaults to true. |\n| surfaceId? | string | The ID of surface to attach to. Optional. The component is context aware and will try to resolve the Surface/Paper<br />to attach to from an ancestor SurfaceProvider SurfaceComponent or PaperComponent. |\n| svgOptions? | [SvgExportUIOptions]() | Options for SVG exports. |","url":"https://visuallyjs.com/react/docs/reference/exportcontrolscomponent","lib":"react","topic":""},"docs/reference/InspectorComponent.md":{"title":"InspectorComponent","body":"# \\<InspectorComponent/>\n\nProvides an object inspector for the nodes/groups/edges in your app. When model objects are added to the model's current selection, the inspector component is informed. You can use any HTML you like in an inspector. VisuallyJs will bind values into inputs on which you have declared a `vjs-att` attribute, for instance:\n\n```html\n<input vjs-att=\"label\" type=\"text\"></input>\n\n```\n\nHere, VisuallyJs will populate the given text input with the value of the `label` property in the backing data of whatever is currently selected.\n\nIf you have multiple objects selected, VisuallyJs will only populate fields of the inspector where every selected object has the same value for that field. Otherwise the field is initially left blank. Changes are, though, propagated to every selected object.\n\n## Usage[](#usage)\n\nCreate a React component that renders an `InspectorComponent`, and pass a function to its body that renders content based on the current selected object.\n\n```jsx\n\nimport { useState } from \"react\"\nimport { InspectorComponent} from \"@visuallyjs/browser-ui-react\"\nimport { Node, Edge } from \"@visuallyjs/browser-ui\"\n\nexport default function MyInspectorComponent(props) {\n\n return <InspectorComponent>\n\n {(current) => {\n\n { current.objectType === Node.objectType &&\n <div className=\"node-inspector\">\n <div>Text</div>\n <input type=\"text\" vjs-att=\"text\" vjs-focus=\"true\"/>\n <div>Fill</div>\n <input type=\"color\" vjs-att=\"fill\"/>\n </div>\n }\n\n { current.objectType === Edge.objectType &&\n <div className=\"edge-inspector\">\n <div>Label</div>\n <input type=\"text\" vjs-att=\"label\"/>\n <div>Color</div>\n <input type=\"color\" vjs-att=\"color\"/>\n </div>\n }\n \n }}\n\n </InspectorComponent>\n}\n \n\n```\n\n## Empty inspector[](#empty-inspector)\n\nTo render something when the inspector has no current selection, pass a function to the `renderEmptyContent` prop:\n\n```jsx\n\nimport { useState } from \"react\"\nimport { InspectorComponent} from \"@visuallyjs/browser-ui-react\"\nimport { Node, Edge } from \"@visuallyjs/browser-ui\"\n\nexport default function MyInspectorComponent(props) {\n\n function nothingSelected() {\n return <h3>Select a node to inspect its properties</h3>\n }\n \n return <InspectorComponent renderEmptyContent={nothingSelected}>\n\n {(current) => {\n ...\n }}\n\n </InspectorComponent>\n}\n \n\n```\n\n<!-- -->\n\n<!-- -->\n\n## Data Binding[](#data-binding)\n\n### Supported elements[](#supported-elements)\n\nElements on which the inspector will perform data binding are:\n\n* **select** Drop down boxes, including those with `multiple:true`\n* **textarea** For long pieces of text\n* **input** Various input types are supported.\n\n### Supported input types[](#supported-input-types)\n\n* **checkbox** Note: the inspector will peform a [\"truthy\" match](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) to determine whether or not a checkbox should be checked\n* **radio** Note: As radio buttons are represented with strings in HTML, you can provide a `vjs-datatype` attribute to instruct VisuallyJs that you wish to coerce its value to a number. [Read more here](#radio-button-datatypes)\n* **color** Note: your data model must be using rgb or hex to represent colors\n* **number**\n* **range**\n* **text**\n\n### Validation[](#validation)\n\nAs the inspector is represented using standard HTML, you can take advantage of all of the validation attributes that are available in HTML 5 elements.\n\n### Radio Button Datatypes[](#radio-button-datatypes)\n\nTo tell VisuallyJs to coerce the value a given radio button represents to a number, write out a `vjs-datatype` attribute on it:\n\n```html\n<input type=\"radio\" vjs-att=\"foo\" value=\"5\" vjs-datatype=\"integer\"/>\n\n```\n\nValid values are `\"integer\"` and `\"float\"`.\n\n## Setting focus[](#setting-focus)\n\nIf you wish to specify a field that should receive the focus whenever the UI is updated, use `vjs-focus`:\n\n```html\n<input type=\"text\" vjs-att=\"label\" vjs-focus=\"true\"/>\n\n```\n\n## Props[](#props)\n\nInspectorComponentProps\n\nProps for the InspectorComponent\n\n| Name | Type | Description |\n| ------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| afterUpdate? | (s:[Surface]()) => void | Optional function to invoke after an update. |\n| autoCommit? | boolean | Whether or not to auto commit on enter keypress/blur. Defaults to true. |\n| className? | string | Optional extra css classes to set on the root element |\n| filter? | (b:[Base]()) => boolean | Optional filter you can use to instruct the inspector to ignore certain items. |\n| multipleSelections? | boolean | Whether or not to support multiple selections. Defaults to true. |\n| refresh? | (obj:[Base]()) => void | Callback invoked when a new object has started to be edited. You need to provide this if the child content you provide to the Inspector is not a function. |\n| renderEmptyContent? | () => any | Optional function that returns JSX to use when nothing is selected |\n| showCloseButton? | boolean | Whether or not to show a close button. Defaults to false. |\n| surface? | [Surface]() | Surface to attach to. It is not mandatory that you supply this - the component is context aware and can try to resolve a surface from an ancestor SurfaceProvider SurfaceComponent or PaperComponent. |","url":"https://visuallyjs.com/react/docs/reference/inspectorcomponent","lib":"react","topic":""},"docs/reference/MiniviewComponent.md":{"title":"MiniviewComponent","body":"# \\<MiniviewComponent/>\n\nProvides a miniaturized view of a Surface, showing the nodes/groups in the Surface canvas. Users can pan/zoom the surface via pointer/touch events on the Miniview, and click on specific vertices to have the Surface center itself on the clicked vertex.\n\n## Usage[](#usage)\n\nThis component is context aware and will discover the Surface to attach itself to if it is a child of a [SurfaceComponent](/react/docs/reference/SurfaceComponent.md):\n\n```jsx\n<SurfaceComponent renderOptions={...} data={...}>\n <MiniviewComponent />\n</SurfaceComponent>\n\n```\n\nor if it is a descendant of a [SurfaceProvider](/react/docs/reference/SurfaceProvider.md):\n\n```jsx\n<SurfaceProvider>\n <SurfaceComponent renderOptions={...} data={...}/>\n <div className=\"someContainer\">\n <MiniviewComponent/>\n </div>\n</SurfaceProvider>\n\n```\n\n## Props[](#props)\n\nMiniviewComponentProps\n\nProps for the MiniviewComponent.\n\n| Name | Type | Description |\n| --------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |\n| activeTracking? | boolean | Whether or not to move miniview elements at the same time as their related surface element is being dragged. Defaults to true. |\n| className? | string | Optional class name to append to the root element's class list. |\n| clickToCenter? | boolean | Defaults to true, meaning a click on a node/group in the miniview will cause that node/group to be centered in the related surface. |\n| elementFilter? | (obj:[Group]() \\| [Node]()) => boolean | Optional filter to decide which elements to show in the miniview. |\n| typeFunction? | (obj:[Group]() \\| [Node]()) => string | Optional function to use to decorate miniview elements with a `vjs-miniview-type` attribute. Can be used for simple styling. |","url":"https://visuallyjs.com/react/docs/reference/miniviewcomponent","lib":"react","topic":""},"docs/reference/PaletteComponent.md":{"title":"PaletteComponent","body":"# \\<PaletteComponent/>\n\nProvides a palette from which your users can select nodes or groups to add to a canvas. Two modes are supported - the default is to allow users to drag nodes or groups from the palette element onto a canvas using touch/pointer events; it is also possible to run the palette in `tap` mode, in which a user first selects a node/group in the palette by clicking it, and then subsequently clicks on the canvas where they would like to place a new object of that type.\n\nTo locate the surface it should attach to, this component should be contained within a `SurfaceProvider`.\n\n## Usage[](#usage)\n\n```jsx\n<SurfaceProvider>\n <SurfaceComponent data={...}/>\n <PaletteComponent selector=\"div\">\n <div style=\"display:flex;flex-direction:column\">\n <h1>Item Type 1</h1>\n <div data-vjs-type=\"type11\">Type 1</div>\n <div data-vjs-type=\"groupType1\" data-vjs-is-group=\"true\">Group Type 1</div>\n <h1>Item Type 2</h1>\n <div data-vjs-type=\"type21\">Type 21</div>\n </div>\n </PaletteComponent>\n</SurfaceProvider>\n\n```\n\nThe PaletteComponent is context aware and will find the surface to attach to if you include it inside a [SurfaceProvider](/react/docs/reference/SurfaceProvider.md)\n\nThe `selector:\"div\"` option tells VisuallyJs what CSS3 selector it should use to determine which child elements of the palette represent draggable items. This selector is simple, but any valid selector will do, so you can use arbitrary markup.\n\n## Payloads[](#payloads)\n\nWhen a user adds a node/group to a canvas from a Palette, VisuallyJs will prepare an initial payload for the new object in one of two ways:\n\n### Default extractor[](#default-extractor)\n\nBy default, any `data-vjs-***` attribute on the element in the Palette will have its value read and inserted into the payload. For instance, the attribute `data-vjs-label=\"hello\"` will result in `{label:\"hello\"}`.\n\n### Custom extractor[](#custom-extractor)\n\nIf you provide a `dataGenerator`, you can control on a fine-grained level what the payload for new objects will be. This is a [DataGeneratorFunction]() whose type definition is:\n\n`(el:BrowserElement) => T`\n\n### Marking groups[](#marking-groups)\n\nTo inform VisuallyJs that a certain element represents a Group and not a Node, set `data-vjs-is-group=\"true\"` on it:\n\n```html\n<div>\n <div data-vjs-type=\"foo\">Foo NODE</div>\n <div data-vjs-type=\"bar\" data-vjs-is-group=\"true\">Bar GROUP</div>\n</div>\n\n```\n\n## Props[](#props)\n\nPaletteComponentProps\n\nProps for the `PaletteComponent`\n\n| Name | Type | Description |\n| ------------------ | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| allowClickToAdd? | boolean | When in draw mode, allow addition of new vertices simply by clicking, instead of requiring a shape be drawn. (When this is true, the drag to draw functionality also still works) |\n| allowDropOnCanvas? | boolean | Whether or not to allow drop on whitespace in the canvas. Defaults to true. |\n| allowDropOnEdge? | boolean | Whether or not to allow drop on edge. Defaults to false. |\n| allowDropOnGroup? | boolean | Whether or not to allow drop on existing vertices. Defaults to true. |\n| allowDropOnNode? | boolean | Defaults to false. Allows items to be dropped onto nodes in the canvas. If this is true and an element is dropped onto a node, the result is the same as if the element has been dropped onto whitespace. Note that when this is false and the user has dragged something over a node, the drag item is still not considered to be over the canvas, and releasing the mouse button at that time will not cause a new node to be added. Use `ignoreDropOnNode` if that's the behaviour you want. |\n| canvasDropFilter? | [CanvasDropFilter<]()[BrowserElement]()> | Optional filter to test if objects may be dropped on the canvas. |\n| className? | string | Optional extra css classes to set on the element |\n| clickToAddOnly? | boolean | This flag relates to \"draw\" mode, and defaults to false. When true, the palette only supports click to draw new vertices, not drag. This flag is forced to true if the associated UI does not have `useModelForSizes` set, since there is no point in allowing a user to drag a vertex to some size if its not going to be honoured. When you set this flag and associated UI does have `useModelForSizes` set, the palette will use default sizes for new nodes/groups. |\n| dataGenerator? | [DataGeneratorFunction<]()[BrowserElement]()> | Function to use to get a dataset for an item that is being dragged or has been tapped. If omitted, Visually JS will use a default data generator that extracts data values from any `data-vjs-***` attribute on the element being dragged. |\n| dragSize? | [Size]() | Optional size to use for elements dragged from the palette, when in \"drag\" mode |\n| groupIdentifier? | [GroupIdentifierFunction<]()[BrowserElement]()> | Function to use to determine whether an item that is being dragged or has been tapped represents a group. |\n| ignoreDropOnNode? | boolean | Defaults to false. When true, the palette treats nodes as if they are part of the canvas - a user can drag new items on top of existing nodes and the new item will be added to the canvas. If you want to force your users to drop on canvas whitespace, don't set this. Note that this flag will force `allowDropOnNode` to `false`. |\n| mode? | PaletteMode | Mode to operate in - 'drag', 'tap' or 'draw'. Defaults to 'drag'. |\n| onVertexAdded? | [OnVertexAddedCallback]() | Optional callback that will be invoked after a new vertex has been dropped and added to the dataset. |\n| selectAfterAdd? | boolean | Defaults to false. When true, a newly added vertex is set as the model's current selection. |\n| selector? | string | CSS 3 selector identifying what child elements of `container` are draggable/tappable. Optional. If omitted, a default of `[data-vjs-type]` will be used. |\n| surface? | [Surface]() | The surface to attach to. Optional: this component can derive a surface from a SurfaceProvider or SurfaceComponent. You'll only need this in certain advanced scenarios. |\n| typeGenerator? | [TypeGeneratorFunction<]()[BrowserElement]()> | Function to use to get the type of an item that is being dragged or has been tapped. |","url":"https://visuallyjs.com/react/docs/reference/palettecomponent","lib":"react","topic":""},"docs/reference/ShapeComponent.md":{"title":"ShapeComponent","body":"# \\<ShapeComponent/>\n\nA component that renders an SVG shape from a `ShapeLibrary`. This component can be used inside your own React components if you've got a `ShapeLibrary` setup on your Surface - see the documentation for a discussion of this.\n\nIf you're building an SVG diagram in which the shapes are the entire node contents, you may want to look at the [DiagramComponent](/react/docs/reference/DiagramComponent.md).\n\n## Usage[](#usage)\n\nThis component is used inside the JSX that represents some node (or group) in your app. For example, here we use one in the JSX in our view, which we pass in to a `SurfaceComponent`:\n\n```jsx\n\nexport default function MyApp() {\n\n const view = {\n nodes: {\n default: {\n jsx: (ctx) => <div>\n <strong>{ctx.obj.label}</strong>\n <ShapeComponent ctx={ctx}/>\n </div>\n }\n }\n }\n\n return <SurfaceComponent viewOptions={view}/>\n} \n\n```\n\n`ctx` contains information about the vertex being rendered, and the Surface that is rendering it, etc. The vertex's `type` (and optionally `category`) values will be extracted and used to resolve an appropriate shape to draw from the ShapeLibrary the Surface is using.\n\n## Supported Properties[](#supported-properties)\n\nAn svg shape supports these properties:\n\n* **type** Identifies the shape to be drawn. Required.\n* **category** Identifies the shape set that the shape belongs to. Not required if you have only one shape set, but recommended.\n* **fill** The color to use for the SVG's background - equivalent to the SVG attribute `fill`.\n* **outline** The color to use for the outline of the shape - equivalent to the SVG attribute `stroke`.\n* **outlineWidth** The `stroke-width` to use in the shape's outline.\n* **label** Label to display for the shape.\n\nAn example payload might be:\n\n```json\n{\n \"type\": \"process\",\n \"category\": \"flowchart\",\n \"fill\":\"#FFFFFF\",\n \"outline\":\"#000000\",\n \"outlineWidth\":2,\n \"label\":\"My Node\" \n}\n\n```\n\n## Props[](#props)\n\nShapeComponentProps\n\nProps for a ShapeComponent\n\n| Name | Type | Description |\n| ----------------- | ----------------------- | ------------------------------------------------------------------------------------------------- |\n| ctx | [JsxWrapperProps\\<T>]() | Context for the vertex, as passed in by the SurfaceComponent. |\n| font? | [FontSpec]() | Optional font size/style to use for this shape. |\n| labelColor? | string | Color for the label. Defaults to #000000. |\n| labelFillRatio? | number | For multiline labels, the proportion of the width of the shape that the longest line can take up. |\n| labelProperty? | string | The name of the property that identifies some vertex's label. Defaults to \"label\". |\n| labelStrokeWidth? | string | Optional stroke width to use for labels. Defaults to \"0.25px\". |\n| multilineLabels? | boolean | Defaults to true - word wrap shape labels so they fit into their shapes |\n| showLabels? | boolean | Defaults to false. If true, a label will be written on the shape (using an SVG text element). |","url":"https://visuallyjs.com/react/docs/reference/shapecomponent","lib":"react","topic":""},"docs/reference/ShapePaletteComponent.md":{"title":"ShapePaletteComponent","body":"# \\<ShapePaletteComponent/>\n\nThis is a palette that sources its draggable items from the SVG shapes that the surface it is attached to has available.\n\nTo locate the surface it should attach to, this component should be contained within a `SurfaceProvider`.\n\n## Usage[](#usage)\n\n```jsx\nimport {FLOWCHART_SHAPES, BASIC_SHAPES} from \"@visuallyjs/browser-ui\";\nimport {SurfaceProvider, SurfaceComponent, ShapePaletteComponent} from \"@visuallyjs/browser-ui-react\";\n\n<SurfaceProvider>\n <SurfaceComponent renderOptions={{\n shapes:{\n sets:[FLOWCHART_SHAPES, BASIC_SHAPES]\n }\n }}/>\n \n <ShapePaletteComponent/>\n</SurfaceProvider>\n\n```\n\n## Props[](#props)\n\nShapePaletteComponentProps\n\nProps for the ShapePaletteComponent\n\n| Name | Type | Description |\n| ------------------- | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| allowClickToAdd? | boolean | When in tap mode, allow addition of new vertices simply by clicking, instead of requiring a shape be drawn. (When this is true, the drawing method also still works) |\n| className? | string | Optional class name to append to the root element's class list. |\n| dataGenerator? | [DataGeneratorFunction<]()[ObjectData]()> | Optional data generator to allow you to specify initial data for some element to be dragged. Note that you cannot override the object's `type` with this function. The palette will set the new object's type to match the type of the element that the user is dragging from the palette. |\n| dragSize? | [Size]() | Optional size to use for dragged elements. |\n| fill? | string | Optional fill color to use for dragged elements. This should be in RGB or hex format, *not* a color like 'white' or 'cyan' etc. |\n| iconSize? | [Size]() | Optional size to use for icons. |\n| initialSet? | string | ID of the initial set to show, if any. When you have multiple shapes in a set you may want the palette to open up showing just one set. |\n| inspector? | boolean | Indicates two things: first, when one or more vertices are selected, clicking on an entry in the palette will change the type of the selected vertices to that type. Secondly, selecting an element in the canvas will cause its related shape to be selected in the palette. Defaults to true. |\n| mode? | PaletteMode | Mode to use for the palette. |\n| onVertexAdded? | [OnVertexAddedCallback]() | Optional callback to invoke when a vertex as been dragged onto the canvas |\n| outline? | string | Optional color to use for outline of dragged elements. Should be in RGB or hex format. |\n| paletteStrokeWidth? | number | Stroke width to use for shapes in palette. Defaults to 1. |\n| preparedShapes? | Array\\<PreparedShape> | Optional set of prepared shapes to show in the palette. When this is provided, the palette will only render these shapes, and not the contents of the shape library. |\n| selectAfterDrop? | boolean | When true (which is the default), a newly dropped vertex will be set as the underlying model's selection. |\n| showAllMessage? | string | Message to use for the 'show all' option in the shape set drop down when there is more than one set of shapes. Defaults to `Show all`. |\n| showLabels? | boolean | Optionally show each shape icon's label underneath it |\n| surface? | [Surface]() | Surface to attach the drag/drop to. Optional; this component can extract the Surface from a SurfaceProvider, or from being a child of a SurfaceComponent. You'd only need to set this in certain advanced scenarios. |","url":"https://visuallyjs.com/react/docs/reference/shapepalettecomponent","lib":"react","topic":""},"docs/reference/SurfaceComponent.md":{"title":"SurfaceComponent","body":"# \\<SurfaceComponent/>\n\nProvides a pannable and zoomable canvas on which nodes, edges and groups can be drawn, with support for layouts and various plugins.\n\n## Usage[](#usage)\n\nThis component is at the heart of VisuallyJs React, and is very customizable, but there are three main sections of props that you should be familiar with:\n\n* **renderOptions** This prop contains all of the settings that control the behaviour and appearance of the component itself - what layout to use, whether to zoom to fit a dataset when it has been loaded, whether or not to use a grid, plugins, etc...the list is long.\n\n* **viewOptions** This contains the mapping from node/edge/group types to their visual representation and behaviour. For nodes and groups this means mapping some JSX to use to render them; for edges this means specifying details of the connector to use to draw an edge, and how the edge should be anchored. You can also supply event mappings in your `viewOptions` to hook into user interaction with the various parts of the UI\n\n* **modelOptions** This is used less often than `viewOptions` and `renderOptions`, but this is how you can provide settings for the underlying model.\n\n```jsx\n<SurfaceComponent \n className=\"...\"\n data={ ... }\n url=\" ... \"\n renderOptions={ ... }\n viewOptions={ ... }\n modelOptions={ ... }\n/>\n\n```\n\n## Props[](#props)\n\nSurfaceComponentProps\n\nProps for the SurfaceComponent.\n\n| Name | Type | Description |\n| -------------- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |\n| childProps? | any | Any props to pass to children. |\n| className? | string | Optional class name to append to the root element's class list. |\n| data? | any | Optional initial data |\n| model? | [BrowserUIReactModel]() | Optional instance to render. You mostly wont need to do this; the SurfaceComponent or PaperComponent will create<br />an instance. |\n| modelOptions? | [ModelOptions]() | Options for the underlying instance. |\n| renderOptions? | [ReactSurfaceRenderOptions]() | Render options such as layout, drag options etc |\n| style? | Record\\<string,string> | Optional style object to apply to the container element. |\n| surfaceId? | string | Optional ID to assign to the surface that is created. |\n| url? | string | Optional URL to load initial data from. |\n| viewOptions? | [ReactSurfaceViewOptions]() | Mappings of vertex types to components/jsx and edge types. |\n\n## Ref Handle[](#ref-handle)\n\nIf you bind this component to a ref, you get an object of type `SurfaceComponentRef`:\n\nSurfaceComponentRef\n\nReference to a SurfaceComponent. Offers methods to get the underlying surface and VisuallyJs instance.\n\n| Name | Type | Description |\n| ---------- | ----------------------------- | ---------------------------------------------------------------------- |\n| getModel | () => [BrowserUIReactModel]() | Gets the underlying model instance, on which you can manage the model. |\n| getSurface | () => [Surface]() | Gets the Surface canvas component. |","url":"https://visuallyjs.com/react/docs/reference/surfacecomponent","lib":"react","topic":""},"docs/reference/SurfaceProvider.md":{"title":"SurfaceProvider","body":"# \\<SurfaceProvider/>\n\nThis is a context provider that enables you to use various other components alongside a [SurfaceComponent](/react/docs/reference/SurfaceComponent.md) without having to explicitly connect them up.\n\n## Usage[](#usage)\n\n```jsx\nimport { SurfaceProvider, \n SurfaceComponent, \n ControlsComponent, \n MiniviewComponent} from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyApp() {\n\n return <SurfaceProvider>\n <SurfaceComponent data={...}/>\n <ControlsComponent/>\n <MiniviewComponent/>\n </SurfaceProvider>\n \n}\n\n```\n\nIn this example, `ControlsComponent` and `MiniviewComponent` can both find the surface to attach to due to them all being contained within the `SurfaceProvider` element.\n\nThe list of components that are surface context aware is:\n\n* [Miniview](/react/docs/reference/MiniviewComponent.md)\n* [Controls](/react/docs/reference/ControlsComponent.md)\n* [ExportControls](/react/docs/reference/ExportControlsComponent.md)\n* [Palette](/react/docs/reference/PaletteComponent.md)\n* [ShapePalette](/react/docs/reference/ShapePaletteComponent.md)\n* [Inspector](/react/docs/reference/InspectorComponent.md)\n* [ShapeComponent](/react/docs/reference/ShapeComponent.md)","url":"https://visuallyjs.com/react/docs/reference/surfaceprovider","lib":"react","topic":""},"docs/reference/UseInspectorHook.md":{"title":"UseInspectorHook","body":"# useInspector()\n\nThis hook is for use by components that are children of an [InspectorComponent](/react/docs/reference/InspectorComponent.md). It provides access to the underlying `Inspector`. You won't need to use this hook unless you're writing your own custom components for an inspector.\n\n## Usage[](#usage)\n\n```jsx\nimport { useInspector } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyEditorComponent(props) {\n const inspector = useInspector()\n \n // you can call inspector.setValue(key, value) to set values\n \n}\n\n\n```","url":"https://visuallyjs.com/react/docs/reference/useinspectorhook","lib":"react","topic":""},"docs/reference/UseModelHook.md":{"title":"UseModelHook","body":"# useVisuallyJsModel()\n\nThis hook provides access to the underlying model. It's not something you'll necessarily need often, but if you're writing your own components that want to manipulate the model, this is the hook for you.\n\n## Usage[](#usage)\n\nThis is an asynchronous hook that returns a Promise, which resolves to the current model in use. Your component should use it as shown in the code below.\n\n```jsx\nimport { useRef } from \"react\"\nimport { useVisuallyJsModel } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n\n const [model, setModel] = useState<BrowserUIReactModel>(null)\n useVisuallyJsModel().then(m => setModel(m))\n \n return <div>\n {model && <>The model currently has {model.getNodes().length} nodes.</>}\n {!model && <>Loading...</>}\n </div>\n}\n\n\n```","url":"https://visuallyjs.com/react/docs/reference/usemodelhook","lib":"react","topic":""},"docs/reference/UseSurfaceHook.md":{"title":"UseSurfaceHook","body":"# useSurface()\n\nThis hook is not something you'll ordinarily need to use, but if you decide to write your own component that needs to access the underlying `Surface`, this hook will be of use.\n\nThis hook will only return a value if your component is a descendant in the JSX of a [SurfaceProvider](/react/docs/reference/SurfaceProvider.md) or [SurfaceComponent](/react/docs/reference/SurfaceComponent.md).\n\n## Usage[](#usage)\n\nThis is an asynchronous hook that returns a Promise, which resolves to the current Surface in use. Your component should use it as shown in the code below.\n\n```jsx\nimport { useState } from \"react\"\nimport { useSurface } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyComponent() {\n \n const [surface, setSurface] = useState(null)\n \n useSurface().then((s) => setSurface(s))\n \n return <div>\n {surface && <>The Surface currently has {surface.model.getNodes().length} nodes.</>}\n {!surface && <>Loading...</>}\n </div>\n}\n\n\n```\n\nThis component would then need to be loaded inside a context in which a surface is available, for instance:\n\n```jsx\nimport { useState } from \"react\"\n\nimport MyComponent from \"./my-component\"\nimport { SurfaceProvider, SurfaceComponent } from \"@visuallyjs/browser-ui-react\"\n\nexport default function MyApp() {\n \n return <SurfaceProvider>\n <SurfaceComponent data={{nodes:[{id:\"1\"}, {id:\"2\"}]}}/>\n <MyComponent/>\n </SurfaceProvider>\n}\n\n\n```","url":"https://visuallyjs.com/react/docs/reference/usesurfacehook","lib":"react","topic":""},"docs/reference/classes/BrowserUIReactModel.md":{"title":"BrowserUIReactModel","body":"### BrowserUIReactModel\n\nExtension of the VisuallyJsModel for use in React. This is the class you use to manipulate and query the contents of the data model. You will rarely need to create one of these manually, since the UI components will do that for you (unless you have an app in which you wish to share one model among several renderers), but if you wish to perform programmatic operations on the data model this is the class you will interact with.\n\n### Class Methods[](#class-methods)\n\n#### render[](#render)\n\nConfigures the given element as a Surface, registering it so that it reflects any changes to the underlying data. If there is any data in the model at the time of this call it is rendered; any data subsequently loaded is automatically rendered. You can supply layout arguments to this method (layout type + layout specific parameters), as well as rules for paint styles etc.\n\nSignature\n\nrender(container:Element, options:[SurfaceOptions]())\n\nParameters\n\n| | | |\n| --------- | ------------------ | -------------------------- |\n| container | Element | The Element to render into |\n| options | [SurfaceOptions]() | Render options |\n\nReturn value\n\n[Surface]()","url":"https://visuallyjs.com/react/docs/reference/classes/browseruireactmodel","lib":"react","topic":""},"docs/reference/props/AreaChartComponentProps.md":{"title":"AreaChartComponentProps","body":"AreaChartComponentProps\n\nAreaChartComponent props\n\n| Name | Type | Description |\n| ----------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------- |\n| className? | string | Optional class name to set on the chart's root element. |\n| data? | Array<[ObjectData]()> | Data to load |\n| dataSourceFilter? | [ChartModelFilter]() | Optional filter to apply to the chart's data source. |\n| interactive? | boolean | Whether the chart is interactive. |\n| options | Omit<[AreaChartOptions](),\"data\" \\| \"url\" \\| \"model\"> | Options for the area chart. |\n| reactive? | boolean | Whether or not to respond to changes in the `url` or `data` prop. Defaults to true. |\n| style? | Record\\<string,any> | Optional style object |\n| url? | string | URL to load data from |","url":"https://visuallyjs.com/react/docs/reference/props/areachartcomponentprops","lib":"react","topic":""},"docs/reference/props/BackgroundComponentProps.md":{"title":"BackgroundComponentProps","body":"BackgroundComponentProps\n\nProps for the background component. `type` defines the type of background to render, and each background type has its own set of options.\n\n| Name | Type | Description |\n| ------------------ | ----------------------------- | ------------------------------------------------------------------------------------- |\n| onBackgroundReady? | [OnBackgroundReadyCallback]() | Optional function to call when the image has loaded (or otherwise claims to be ready) |\n| type | string | Type of background to render. |\n| visible? | boolean | Whether or not the background should initially be visible. Defaults to true. |","url":"https://visuallyjs.com/react/docs/reference/props/backgroundcomponentprops","lib":"react","topic":""},"docs/reference/props/BarChartComponentProps.md":{"title":"BarChartComponentProps","body":"BarChartComponentProps\n\nBarChartComponent props\n\n| Name | Type | Description |\n| ----------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------- |\n| className? | string | Optional class name to set on the chart's root element. |\n| data? | Array<[ObjectData]()> | Data to load |\n| dataSourceFilter? | [ChartModelFilter]() | Optional filter to apply to the chart's data source. |\n| interactive? | boolean | Whether the chart is interactive. |\n| options | Omit<[BarChartOptions](),\"data\" \\| \"url\" \\| \"model\"> | Options for the bar chart |\n| reactive? | boolean | Whether or not to respond to changes in the `url` or `data` prop. Defaults to true. |\n| style? | Record\\<string,any> | Optional style object |\n| url? | string | URL to load data from |","url":"https://visuallyjs.com/react/docs/reference/props/barchartcomponentprops","lib":"react","topic":""},"docs/reference/props/BaseChartProps.md":{"title":"BaseChartProps","body":"BaseChartProps\n\nBase interface for chart props\n\n| Name | Type | Description |\n| ----------------- | --------------------- | ----------------------------------------------------------------------------------- |\n| className? | string | Optional class name to set on the chart's root element. |\n| data? | Array<[ObjectData]()> | Data to load |\n| dataSourceFilter? | [ChartModelFilter]() | Optional filter to apply to the chart's data source. |\n| interactive? | boolean | Whether the chart is interactive. |\n| reactive? | boolean | Whether or not to respond to changes in the `url` or `data` prop. Defaults to true. |\n| style? | Record\\<string,any> | Optional style object |\n| url? | string | URL to load data from |","url":"https://visuallyjs.com/react/docs/reference/props/basechartprops","lib":"react","topic":""},"docs/reference/props/BubbleChartComponentProps.md":{"title":"BubbleChartComponentProps","body":"BubbleChartComponentProps\n\nBubbleChartComponent props\n\n| Name | Type | Description |\n| ----------------- | ------------------------------------------------------- | ----------------------------------------------------------------------------------- |\n| className? | string | Optional class name to set on the chart's root element. |\n| data? | Array<[ObjectData]()> | Data to load |\n| dataSourceFilter? | [ChartModelFilter]() | Optional filter to apply to the chart's data source. |\n| interactive? | boolean | Whether the chart is interactive. |\n| options | Omit<[BubbleChartOptions](),\"data\" \\| \"url\" \\| \"model\"> | Options for the bubble chart. |\n| reactive? | boolean | Whether or not to respond to changes in the `url` or `data` prop. Defaults to true. |\n| style? | Record\\<string,any> | Optional style object |\n| url? | string | URL to load data from |","url":"https://visuallyjs.com/react/docs/reference/props/bubblechartcomponentprops","lib":"react","topic":""},"docs/reference/props/ColorPickerComponentProps.md":{"title":"ColorPickerComponentProps","body":"ColorPickerComponentProps\n\nProps for the ColorPicker inspector component.\n\n| Name | Type | Description |\n| ------------ | ------ | ---------------------------------------------------------------- |\n| maxColors? | number | Maximum color swatches to show. Defaults to 10. |\n| propertyName | string | Property name in the data that this picker represents. Required. |","url":"https://visuallyjs.com/react/docs/reference/props/colorpickercomponentprops","lib":"react","topic":""},"docs/reference/props/ColumnChartComponentProps.md":{"title":"ColumnChartComponentProps","body":"ColumnChartComponentProps\n\nColumnChartComponent props\n\n| Name | Type | Description |\n| ----------------- | ------------------------------------------------------- | ----------------------------------------------------------------------------------- |\n| className? | string | Optional class name to set on the chart's root element. |\n| data? | Array<[ObjectData]()> | Data to load |\n| dataSourceFilter? | [ChartModelFilter]() | Optional filter to apply to the chart's data source. |\n| interactive? | boolean | Whether the chart is interactive. |\n| options | Omit<[ColumnChartOptions](),\"data\" \\| \"url\" \\| \"model\"> | Options for the column chart. |\n| reactive? | boolean | Whether or not to respond to changes in the `url` or `data` prop. Defaults to true. |\n| style? | Record\\<string,any> | Optional style object |\n| url? | string | URL to load data from |","url":"https://visuallyjs.com/react/docs/reference/props/columnchartcomponentprops","lib":"react","topic":""},"docs/reference/props/ControlsComponentProps.md":{"title":"ControlsComponentProps","body":"ControlsComponentProps\n\nProps for the controls component.\n\n| Name | Type | Description |\n| -------------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| buttons? | [ControlsComponentButtons]() | Optional extra buttons to add to the controls component. |\n| className? | string | Optional class name to append to the root element's class list. |\n| clear? | boolean | Whether or not to show the clear button, defaults to true. |\n| clearMessage? | string | Optional message for the alert that the clear button shows by default. Defaults to `Clear dataset?`. |\n| onMaybeClear? | (doClear:() => void) => void | Optional callback to invoke when the user presses the clear button. If you provide this, the component will not show an alert, and instead call this method, passing in a function you can invoke if you wish to continue with the clear operation. |\n| orientation? | \"row\" \\| \"column\" | Optional orientation for the controls. Defaults to 'row'. |\n| style? | Record\\<string,string> | Optional style object to apply to the container element. |\n| surfaceId? | string | The ID of surface to attach to. Optional. Will be inferred from context if not provided. |\n| undoRedo? | boolean | Whether or not to show undo/redo buttons, defaults to true |\n| zoomButtons? | boolean | Whether or not to show the zoom in/zoom out buttons, defaults to false |\n| zoomToExtents? | boolean | Whether or not to show the zoom to extents button, defaults to true |","url":"https://visuallyjs.com/react/docs/reference/props/controlscomponentprops","lib":"react","topic":""},"docs/reference/props/DiagramComponentProps.md":{"title":"DiagramComponentProps","body":"DiagramComponentProps\n\nProps for the DiagramComponent\n\n| Name | Type | Description |\n| ------------- | ---------------------- | -------------------------------------------------------- |\n| className? | string | Optional class name to set on the container |\n| data? | any | Optional initial data |\n| modelOptions? | [ModelOptions]() | Options for the underlying model |\n| options? | [DiagramOptions]() | Options for the Diagram |\n| style? | Record\\<string,string> | Optional style object to apply to the container element. |\n| url? | string | Optional URL to load initial data from. |","url":"https://visuallyjs.com/react/docs/reference/props/diagramcomponentprops","lib":"react","topic":""},"docs/reference/props/DiagramPaletteComponentProps.md":{"title":"DiagramPaletteComponentProps","body":"DiagramPaletteComponentProps\n\nOptions for a palette for a diagram.\n\n| Name | Type | Description |\n| ------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| allowClickToAdd? | boolean | When in tap mode, allow addition of new vertices simply by clicking, instead of requiring a shape be drawn. (When this is true, the drawing method also still works) |\n| autoExitDrawMode? | boolean | Defaults to true: when in 'tap' mode and a new group/node has been drawn on the canvas, the UI is set back to pan mode. |\n| className? | string | Optional class name to set on the diagram palette root element. |\n| diagram? | [Diagram]() | Optional diagram to attach to. In most cases it is better to use a DiagramProvider to provision the diagram to this component. |\n| dragSize? | [Size]() | Optional size to use for dragged elements. |\n| fill? | string | Optional fill color to use for dragged elements. This should be in RGB format, *not* a color like 'white' or 'cyan' etc. |\n| iconSize? | [Size]() | Optional size to use for icons. Defaults to 150x100 pixels. If you provide this but not `dragSize` this size will also be used for an icon that is being dragged. |\n| inspector? | boolean | Indicates that when one or more vertices are selected, clicking on an entry in the palette will change the type of the selected vertices to that type. Defaults to true. |\n| mode? | PaletteMode | Mode to operate in - 'drag' or 'tap'. Defaults to 'drag' (PALETTE\\_MODE\\_DRAG). |\n| onCellAdded? | (dc:[DiagramCell]()) => any | Callback to invoke when a new diagram cell has been added. |\n| onVertexAdded? | [OnVertexAddedCallback]() | Optional callback that will be invoked after a new vertex has been dropped and added to the dataset. |\n| outline? | string | Optional color to use for outline of dragged elements. Should be in RGB format. |\n| paletteStrokeWidth? | number | Stroke width to use for shapes in palette. Defaults to 1. |\n| preparedShapes? | Array\\<PreparedShape> | Optional set of prepared shapes to show in the palette. When this is provided, the palette will only render these shapes, and not the contents of the shape library. |\n| selectAfterAdd? | boolean | When true (which is the default), a newly dropped shape will be set as the underlying model's selection. |\n| showAllMessage? | string | Message to use for the 'show all' option in the shape set drop down when there is more than one set of shapes. Defaults to `Show all`. |\n| showLabels? | boolean | Optionally show each shape icon's label underneath it |\n| style? | Record\\<string,string> | Optional style object to apply to the container element. |","url":"https://visuallyjs.com/react/docs/reference/props/diagrampalettecomponentprops","lib":"react","topic":""},"docs/reference/props/EdgeTypePickerComponentProps.md":{"title":"EdgeTypePickerComponentProps","body":"EdgeTypePickerComponentProps\n\nProps for the EdgeTypePickerComponent\n\n| Name | Type | Description |\n| ------------ | ------ | ------------------------------------------------ |\n| propertyName | string | Name of the property to get/set in the edge data |","url":"https://visuallyjs.com/react/docs/reference/props/edgetypepickercomponentprops","lib":"react","topic":""},"docs/reference/props/ExportControlsComponentProps.md":{"title":"ExportControlsComponentProps","body":"ExportControlsComponentProps\n\nOptions for the ExportControlsComponent\n\n| Name | Type | Description |\n| --------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| allowJpgExport? | boolean | Defaults to true. |\n| allowPngExport? | boolean | Defaults to true. |\n| allowSvgExport? | boolean | Defaults to true. |\n| imageOptions? | [ImageExportUIOptions]() | Options for image exports. |\n| label? | string | What to show in the label, if visible. Defaults to \"Export:\". |\n| margins? | [PointXY]() | Optional margins to apply to both SVG and image exports. Will not override any margins specified in svgOptions or imageOptions. |\n| showLabel? | boolean | Whether or not to show a label in front of the buttons. Defaults to true. |\n| surfaceId? | string | The ID of surface to attach to. Optional. The component is context aware and will try to resolve the Surface/Paper<br />to attach to from an ancestor SurfaceProvider SurfaceComponent or PaperComponent. |\n| svgOptions? | [SvgExportUIOptions]() | Options for SVG exports. |","url":"https://visuallyjs.com/react/docs/reference/props/exportcontrolscomponentprops","lib":"react","topic":""},"docs/reference/props/GaugeChartComponentProps.md":{"title":"GaugeChartComponentProps","body":"GaugeChartComponentProps\n\nGaugeChartComponent props\n\n| Name | Type | Description |\n| ----------------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------- |\n| className? | string | Optional class name to set on the chart's root element. |\n| data? | Array<[ObjectData]()> | Data to load |\n| dataSourceFilter? | [ChartModelFilter]() | Optional filter to apply to the chart's data source. |\n| interactive? | boolean | Whether the chart is interactive. |\n| options | Omit<[GaugeChartOptions](),\"data\" \\| \"url\" \\| \"model\"> | Options for the gauge chart |\n| reactive? | boolean | Whether or not to respond to changes in the `url` or `data` prop. Defaults to true. |\n| style? | Record\\<string,any> | Optional style object |\n| url? | string | URL to load data from |","url":"https://visuallyjs.com/react/docs/reference/props/gaugechartcomponentprops","lib":"react","topic":""},"docs/reference/props/GridBackgroundComponentProps.md":{"title":"GridBackgroundComponentProps","body":"GridBackgroundComponentProps\n\nProps for the grid background component.\n\n| Name | Type | Description |\n| ------------------ | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| autoShrink? | boolean | Defaults to true, and instructs the grid that if the grid has grown beyond any minimum value set in either axis, if the content bounds subsequently shrink in that axis below the minimum, the grid should shrink back to the minimum. If you set this to false the grid will never shrink back to its minimum values once they have been exceeded. |\n| dotRadius? | number | The radius for dots representing grid positions (when gridType id GridTypes.dotted). Defaults to 2. |\n| grid? | [Grid]() | The grid to use. This is optional; if you do not supply one the background will attempt to read the grid definition from the Surface. If that is also not set then a default grid of 50x50 pixels will be used. |\n| gridType? | [GridType]() | Type of grid - lines or dots. Defaults to lines. |\n| maxHeight? | number | The maximum height for the grid. The value you provided is divided by 2 and then the grid is guaranteed to never exceed the range of (-maxHeight / 2) - (maxHeight / 2). maxHeight takes precedence over minHeight. |\n| maxWidth? | number | The maximum width for the grid. The value you provided is divided by 2 and then the grid is guaranteed to never exceed the range of (-maxWidth / 2) - (maxWidth / 2). maxWidth takes precedence over minWidth. |\n| minHeight? | number | The minimum height for the grid. The value you provided is divided by 2 and then the grid is guaranteed to always at least span the range of (-minHeight / 2) - (minHeight / 2). Defaults to 20 000. |\n| minWidth? | number | The minimum width for the grid. The value you provided is divided by 2 and then the grid is guaranteed to always at least span the range of (-minWidth / 2) - (minWidth / 2). Defaults to 20 000. |\n| onBackgroundReady? | [OnBackgroundReadyCallback]() | Optional function to call when the image has loaded (or otherwise claims to be ready) |\n| showBorder? | boolean | Whether or not to show a thick border around the entire background. Defaults to false. |\n| showTickMarks? | boolean | Defaults to false. If true, the grid will also draw tick marks between the grid lines. |\n| tickDotRadius? | number | The radius for dots representing grid tick marks (when gridType id GridTypes.dotted). Defaults to 1. |\n| tickMarksPerCell? | number | Number of tick marks to draw per cell. Defaults to 2. |\n| visible? | boolean | Whether or not the background is initially visible. Defaults to true. |","url":"https://visuallyjs.com/react/docs/reference/props/gridbackgroundcomponentprops","lib":"react","topic":""},"docs/reference/props/ImageBackgroundComponentProps.md":{"title":"ImageBackgroundComponentProps","body":"ImageBackgroundComponentProps\n\nProps for the image background component.\n\nThis interface has no members","url":"https://visuallyjs.com/react/docs/reference/props/imagebackgroundcomponentprops","lib":"react","topic":""},"docs/reference/props/InspectorComponentProps.md":{"title":"InspectorComponentProps","body":"InspectorComponentProps\n\nProps for the InspectorComponent\n\n| Name | Type | Description |\n| ------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| afterUpdate? | (s:[Surface]()) => void | Optional function to invoke after an update. |\n| autoCommit? | boolean | Whether or not to auto commit on enter keypress/blur. Defaults to true. |\n| className? | string | Optional extra css classes to set on the root element |\n| filter? | (b:[Base]()) => boolean | Optional filter you can use to instruct the inspector to ignore certain items. |\n| multipleSelections? | boolean | Whether or not to support multiple selections. Defaults to true. |\n| refresh? | (obj:[Base]()) => void | Callback invoked when a new object has started to be edited. You need to provide this if the child content you provide to the Inspector is not a function. |\n| renderEmptyContent? | () => any | Optional function that returns JSX to use when nothing is selected |\n| showCloseButton? | boolean | Whether or not to show a close button. Defaults to false. |\n| surface? | [Surface]() | Surface to attach to. It is not mandatory that you supply this - the component is context aware and can try to resolve a surface from an ancestor SurfaceProvider SurfaceComponent or PaperComponent. |","url":"https://visuallyjs.com/react/docs/reference/props/inspectorcomponentprops","lib":"react","topic":""},"docs/reference/props/JsxWrapperProps.md":{"title":"JsxWrapperProps","body":"JsxWrapperProps\n\nThese are the props that are passed to the `jsx` you provide to map a node, group or overlay component in the `viewOptions` of a SurfaceComponent or PaperComponent. VisuallyJs passes in the UI, the model (which you can get from the UI anyway), the object being rendered, the object's data, and any `childProps` that have been configured.\n\n| Name | Type | Description |\n| ----- | ------------------ | -------------------------------------------------------------- |\n| data | [ObjectData]() | The object's backing data |\n| model | [BrowserUIModel]() | Underlying model. Can also be accessed via `ui.model`. |\n| obj | T | The object to be rendered - a Node, Group or Edge. |\n| props | any | Any extra props configured by the view to present to this JSX. |\n| ui | BrowserUI | The UI that is rendering this object. |","url":"https://visuallyjs.com/react/docs/reference/props/jsxwrapperprops","lib":"react","topic":""},"docs/reference/props/LineChartComponentProps.md":{"title":"LineChartComponentProps","body":"LineChartComponentProps\n\nLineChartComponent props\n\n| Name | Type | Description |\n| ----------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------- |\n| className? | string | Optional class name to set on the chart's root element. |\n| data? | Array<[ObjectData]()> | Data to load |\n| dataSourceFilter? | [ChartModelFilter]() | Optional filter to apply to the chart's data source. |\n| interactive? | boolean | Whether the chart is interactive. |\n| options | Omit<[LineChartOptions](),\"data\" \\| \"url\" \\| \"model\"> | Options for the line chart. |\n| reactive? | boolean | Whether or not to respond to changes in the `url` or `data` prop. Defaults to true. |\n| style? | Record\\<string,any> | Optional style object |\n| url? | string | URL to load data from |","url":"https://visuallyjs.com/react/docs/reference/props/linechartcomponentprops","lib":"react","topic":""},"docs/reference/props/MiniviewComponentProps.md":{"title":"MiniviewComponentProps","body":"MiniviewComponentProps\n\nProps for the MiniviewComponent.\n\n| Name | Type | Description |\n| --------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |\n| activeTracking? | boolean | Whether or not to move miniview elements at the same time as their related surface element is being dragged. Defaults to true. |\n| className? | string | Optional class name to append to the root element's class list. |\n| clickToCenter? | boolean | Defaults to true, meaning a click on a node/group in the miniview will cause that node/group to be centered in the related surface. |\n| elementFilter? | (obj:[Group]() \\| [Node]()) => boolean | Optional filter to decide which elements to show in the miniview. |\n| typeFunction? | (obj:[Group]() \\| [Node]()) => string | Optional function to use to decorate miniview elements with a `vjs-miniview-type` attribute. Can be used for simple styling. |","url":"https://visuallyjs.com/react/docs/reference/props/miniviewcomponentprops","lib":"react","topic":""},"docs/reference/props/PaletteComponentProps.md":{"title":"PaletteComponentProps","body":"PaletteComponentProps\n\nProps for the `PaletteComponent`\n\n| Name | Type | Description |\n| ------------------ | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| allowClickToAdd? | boolean | When in draw mode, allow addition of new vertices simply by clicking, instead of requiring a shape be drawn. (When this is true, the drag to draw functionality also still works) |\n| allowDropOnCanvas? | boolean | Whether or not to allow drop on whitespace in the canvas. Defaults to true. |\n| allowDropOnEdge? | boolean | Whether or not to allow drop on edge. Defaults to false. |\n| allowDropOnGroup? | boolean | Whether or not to allow drop on existing vertices. Defaults to true. |\n| allowDropOnNode? | boolean | Defaults to false. Allows items to be dropped onto nodes in the canvas. If this is true and an element is dropped onto a node, the result is the same as if the element has been dropped onto whitespace. Note that when this is false and the user has dragged something over a node, the drag item is still not considered to be over the canvas, and releasing the mouse button at that time will not cause a new node to be added. Use `ignoreDropOnNode` if that's the behaviour you want. |\n| canvasDropFilter? | [CanvasDropFilter<]()[BrowserElement]()> | Optional filter to test if objects may be dropped on the canvas. |\n| className? | string | Optional extra css classes to set on the element |\n| clickToAddOnly? | boolean | This flag relates to \"draw\" mode, and defaults to false. When true, the palette only supports click to draw new vertices, not drag. This flag is forced to true if the associated UI does not have `useModelForSizes` set, since there is no point in allowing a user to drag a vertex to some size if its not going to be honoured. When you set this flag and associated UI does have `useModelForSizes` set, the palette will use default sizes for new nodes/groups. |\n| dataGenerator? | [DataGeneratorFunction<]()[BrowserElement]()> | Function to use to get a dataset for an item that is being dragged or has been tapped. If omitted, Visually JS will use a default data generator that extracts data values from any `data-vjs-***` attribute on the element being dragged. |\n| dragSize? | [Size]() | Optional size to use for elements dragged from the palette, when in \"drag\" mode |\n| groupIdentifier? | [GroupIdentifierFunction<]()[BrowserElement]()> | Function to use to determine whether an item that is being dragged or has been tapped represents a group. |\n| ignoreDropOnNode? | boolean | Defaults to false. When true, the palette treats nodes as if they are part of the canvas - a user can drag new items on top of existing nodes and the new item will be added to the canvas. If you want to force your users to drop on canvas whitespace, don't set this. Note that this flag will force `allowDropOnNode` to `false`. |\n| mode? | PaletteMode | Mode to operate in - 'drag', 'tap' or 'draw'. Defaults to 'drag'. |\n| onVertexAdded? | [OnVertexAddedCallback]() | Optional callback that will be invoked after a new vertex has been dropped and added to the dataset. |\n| selectAfterAdd? | boolean | Defaults to false. When true, a newly added vertex is set as the model's current selection. |\n| selector? | string | CSS 3 selector identifying what child elements of `container` are draggable/tappable. Optional. If omitted, a default of `[data-vjs-type]` will be used. |\n| surface? | [Surface]() | The surface to attach to. Optional: this component can derive a surface from a SurfaceProvider or SurfaceComponent. You'll only need this in certain advanced scenarios. |\n| typeGenerator? | [TypeGeneratorFunction<]()[BrowserElement]()> | Function to use to get the type of an item that is being dragged or has been tapped. |","url":"https://visuallyjs.com/react/docs/reference/props/palettecomponentprops","lib":"react","topic":""},"docs/reference/props/PieChartComponentProps.md":{"title":"PieChartComponentProps","body":"PieChartComponentProps\n\nPieChartComponent props\n\n| Name | Type | Description |\n| ----------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------- |\n| className? | string | Optional class name to set on the chart's root element. |\n| data? | Array<[ObjectData]()> | Data to load |\n| dataSourceFilter? | [ChartModelFilter]() | Optional filter to apply to the chart's data source. |\n| interactive? | boolean | Whether the chart is interactive. |\n| options | Omit<[PieChartOptions](),\"data\" \\| \"url\" \\| \"model\"> | Options for the pie chart. |\n| reactive? | boolean | Whether or not to respond to changes in the `url` or `data` prop. Defaults to true. |\n| style? | Record\\<string,any> | Optional style object |\n| url? | string | URL to load data from |","url":"https://visuallyjs.com/react/docs/reference/props/piechartcomponentprops","lib":"react","topic":""},"docs/reference/props/SankeyChartComponentProps.md":{"title":"SankeyChartComponentProps","body":"SankeyChartComponentProps\n\nSankeyChartComponent props\n\n| Name | Type | Description |\n| ----------------- | -------------------------------------------------- | ----------------------------------------------------------------------------------- |\n| className? | string | Optional class name to set on the chart's root element. |\n| csvData? | string | Optional data to load into the chart (in CSV format) |\n| dataSourceFilter? | [ChartModelFilter]() | Optional filter to apply to the chart's data source. |\n| interactive? | boolean | Whether the chart is interactive. |\n| jsonData? | [VisuallyJsDefaultJSON]() | Optional data to load into the chart (in VisuallyJs default json format) |\n| options | Omit<[SankeyOptions](),\"data\" \\| \"url\" \\| \"model\"> | Options for the sankey chart |\n| pivot? | string | Optional property to pivot the sankey chart on. |\n| reactive? | boolean | Whether or not to respond to changes in the `url` or `data` prop. Defaults to true. |\n| style? | Record\\<string,any> | Optional style object |\n| url? | string | URL to load data from |","url":"https://visuallyjs.com/react/docs/reference/props/sankeychartcomponentprops","lib":"react","topic":""},"docs/reference/props/ScatterChartComponentProps.md":{"title":"ScatterChartComponentProps","body":"ScatterChartComponentProps\n\nScatterChartComponent props\n\n| Name | Type | Description |\n| ----------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------- |\n| className? | string | Optional class name to set on the chart's root element. |\n| data? | Array<[ObjectData]()> | Data to load |\n| dataSourceFilter? | [ChartModelFilter]() | Optional filter to apply to the chart's data source. |\n| interactive? | boolean | Whether the chart is interactive. |\n| options | Omit<[ScatterChartOptions](),\"data\" \\| \"url\" \\| \"model\"> | Options for the scatter chart. |\n| reactive? | boolean | Whether or not to respond to changes in the `url` or `data` prop. Defaults to true. |\n| style? | Record\\<string,any> | Optional style object |\n| url? | string | URL to load data from |","url":"https://visuallyjs.com/react/docs/reference/props/scatterchartcomponentprops","lib":"react","topic":""},"docs/reference/props/ShapeComponentProps.md":{"title":"ShapeComponentProps","body":"ShapeComponentProps\n\nProps for a ShapeComponent\n\n| Name | Type | Description |\n| ----------------- | ----------------------- | ------------------------------------------------------------------------------------------------- |\n| ctx | [JsxWrapperProps\\<T>]() | Context for the vertex, as passed in by the SurfaceComponent. |\n| font? | [FontSpec]() | Optional font size/style to use for this shape. |\n| labelColor? | string | Color for the label. Defaults to #000000. |\n| labelFillRatio? | number | For multiline labels, the proportion of the width of the shape that the longest line can take up. |\n| labelProperty? | string | The name of the property that identifies some vertex's label. Defaults to \"label\". |\n| labelStrokeWidth? | string | Optional stroke width to use for labels. Defaults to \"0.25px\". |\n| multilineLabels? | boolean | Defaults to true - word wrap shape labels so they fit into their shapes |\n| showLabels? | boolean | Defaults to false. If true, a label will be written on the shape (using an SVG text element). |","url":"https://visuallyjs.com/react/docs/reference/props/shapecomponentprops","lib":"react","topic":""},"docs/reference/props/ShapePaletteComponentProps.md":{"title":"ShapePaletteComponentProps","body":"ShapePaletteComponentProps\n\nProps for the ShapePaletteComponent\n\n| Name | Type | Description |\n| ------------------- | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| allowClickToAdd? | boolean | When in tap mode, allow addition of new vertices simply by clicking, instead of requiring a shape be drawn. (When this is true, the drawing method also still works) |\n| className? | string | Optional class name to append to the root element's class list. |\n| dataGenerator? | [DataGeneratorFunction<]()[ObjectData]()> | Optional data generator to allow you to specify initial data for some element to be dragged. Note that you cannot override the object's `type` with this function. The palette will set the new object's type to match the type of the element that the user is dragging from the palette. |\n| dragSize? | [Size]() | Optional size to use for dragged elements. |\n| fill? | string | Optional fill color to use for dragged elements. This should be in RGB or hex format, *not* a color like 'white' or 'cyan' etc. |\n| iconSize? | [Size]() | Optional size to use for icons. |\n| initialSet? | string | ID of the initial set to show, if any. When you have multiple shapes in a set you may want the palette to open up showing just one set. |\n| inspector? | boolean | Indicates two things: first, when one or more vertices are selected, clicking on an entry in the palette will change the type of the selected vertices to that type. Secondly, selecting an element in the canvas will cause its related shape to be selected in the palette. Defaults to true. |\n| mode? | PaletteMode | Mode to use for the palette. |\n| onVertexAdded? | [OnVertexAddedCallback]() | Optional callback to invoke when a vertex as been dragged onto the canvas |\n| outline? | string | Optional color to use for outline of dragged elements. Should be in RGB or hex format. |\n| paletteStrokeWidth? | number | Stroke width to use for shapes in palette. Defaults to 1. |\n| preparedShapes? | Array\\<PreparedShape> | Optional set of prepared shapes to show in the palette. When this is provided, the palette will only render these shapes, and not the contents of the shape library. |\n| selectAfterDrop? | boolean | When true (which is the default), a newly dropped vertex will be set as the underlying model's selection. |\n| showAllMessage? | string | Message to use for the 'show all' option in the shape set drop down when there is more than one set of shapes. Defaults to `Show all`. |\n| showLabels? | boolean | Optionally show each shape icon's label underneath it |\n| surface? | [Surface]() | Surface to attach the drag/drop to. Optional; this component can extract the Surface from a SurfaceProvider, or from being a child of a SurfaceComponent. You'd only need to set this in certain advanced scenarios. |","url":"https://visuallyjs.com/react/docs/reference/props/shapepalettecomponentprops","lib":"react","topic":""},"docs/reference/props/SurfaceComponentProps.md":{"title":"SurfaceComponentProps","body":"SurfaceComponentProps\n\nProps for the SurfaceComponent.\n\n| Name | Type | Description |\n| -------------- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |\n| childProps? | any | Any props to pass to children. |\n| className? | string | Optional class name to append to the root element's class list. |\n| data? | any | Optional initial data |\n| model? | [BrowserUIReactModel]() | Optional instance to render. You mostly wont need to do this; the SurfaceComponent or PaperComponent will create<br />an instance. |\n| modelOptions? | [ModelOptions]() | Options for the underlying instance. |\n| renderOptions? | [ReactSurfaceRenderOptions]() | Render options such as layout, drag options etc |\n| style? | Record\\<string,string> | Optional style object to apply to the container element. |\n| surfaceId? | string | Optional ID to assign to the surface that is created. |\n| url? | string | Optional URL to load initial data from. |\n| viewOptions? | [ReactSurfaceViewOptions]() | Mappings of vertex types to components/jsx and edge types. |","url":"https://visuallyjs.com/react/docs/reference/props/surfacecomponentprops","lib":"react","topic":""},"docs/reference/props/TiledImageBackgroundComponentProps.md":{"title":"TiledImageBackgroundComponentProps","body":"TiledImageBackgroundComponentProps\n\nProps for the tiled image background component\n\nThis interface has no members","url":"https://visuallyjs.com/react/docs/reference/props/tiledimagebackgroundcomponentprops","lib":"react","topic":""},"docs/reference/props/XYChartComponentProps.md":{"title":"XYChartComponentProps","body":"XYChartComponentProps\n\nXYChartComponent props\n\n| Name | Type | Description |\n| ----------------- | ----------------------------------------------------------- | ----------------------------------------------------------------------------------- |\n| className? | string | Optional class name to set on the chart's root element. |\n| data? | Array<[ObjectData]()> | Data to load |\n| dataSourceFilter? | [ChartModelFilter]() | Optional filter to apply to the chart's data source. |\n| interactive? | boolean | Whether the chart is interactive. |\n| options | Omit\\<CategoryValueChartOptions,\"data\" \\| \"url\" \\| \"model\"> | Options for the XY chart |\n| reactive? | boolean | Whether or not to respond to changes in the `url` or `data` prop. Defaults to true. |\n| style? | Record\\<string,any> | Optional style object |\n| url? | string | URL to load data from |","url":"https://visuallyjs.com/react/docs/reference/props/xychartcomponentprops","lib":"react","topic":""},"docs/reference.md":{"title":"Reference","body":"# Overview\n\nThese pages provide an exhaustive reference to the various components, providers, hooks, types, interfaces and classes that together make up VisuallyJs React. If you're looking for examples of how to use VisuallyJs you may wish to look through the [Learn](/react/docs.md) area of the documentation.\n\nnote\n\nVisuallyJs React has a dependency on VisuallyJs, and you will find references to various types/interfaces from the core UI throughout these reference docs. You can browse through these inline, but if you wish to take a look at the full list, head over to the [Vanilla Reference](/vanilla/docs/reference.md).\n\nIn this section of the documentation you will find:\n\n## Components[](#components)\n\nThis section lists out each of the React components in VisuallyJs, with an example usage, and, where relevant, a list of props for the component.\n\n## Providers[](#providers)\n\nLists the providers available in VisuallyJs React.\n\n## Hooks[](#hooks)\n\nLists the hooks available in VisuallyJs React.\n\n## Props[](#props)\n\nAll of the Props interface declared by VisuallyJs React\n\n## Classes[](#classes)\n\nAll of the classes declared by VisuallyJs React.","url":"https://visuallyjs.com/react/docs/reference","lib":"react","topic":""},"docs.md":{"title":"Docs","body":"# Introduction\n\nVisuallyJs is a flexible, standards-based library for building interactive node-based applications, diagrams and charts. Whether you need to build a complex node-based editor, a data-driven diagram, or an insightful dashboard with various chart types, VisuallyJs provides the tools you need to create a seamless user experience.\n\n<!-- -->\n\n## What can you build with VisuallyJs?[](#what-can-you-build-with-visuallyjs)\n\n### Node-based applications[](#node-based-applications)\n\nApps use <!-- -->React<!-- --> components to render each node/group in the display. Functionality can be encapsulated in these components. Node/group sizes in an App are typically dependent on CSS and are managed automatically by VisuallyJs. Apps are great when you need rich content in your nodes/groups and you don't want to be limited to using SVG.\n\n\n\nSchema Builder starter app\n\n### Diagrams[](#diagrams)\n\nDiagrams are pure SVG applications, that draw SVG shapes into an SVG canvas, and provide an API to manipulate each cell/link individually. VisuallyJs offers a <!-- -->React<!-- --> component that you can use to seamlessly embed a Diagram into your application, as well as several other components such as a miniview, a palette (from which shapes can be dragged onto the canvas), and basic controls such as pan/zoom/undo/redo etc.\n\nVisuallyJs comes with built-in shape sets like Flowchart and BPMN, and you can easily create your own.\n\n\n\nFlowchart Builder starter app\n\n### Charts[](#charts)\n\nVisuallyJs includes a wide range of chart types—from standard Line and Bar charts to more specialized Pie, Donut, and Scatter charts, which can be rendered standalone, or integrated with the data model that is powering an App or Diagram on the same page.\n\n\n\nBar & Column chart starter app\n\n### Dashboards[](#dashboards)\n\nA powerful feature of VisuallyJs is the ability to mix and match different types of components on a single page. You can create a dashboard that combines a rich node-based canvas or a diagram with real-time charts, all powered by the same underlying data model.\n\nFor example, you might have an app representing a manufacturing process where clicking on a machine (a node in the app) updates a set of charts showing that machine's performance metrics. Or a supply chain visualizer with an attached sankey diagram giving you insights into the flow of materials - there are endless possibilities.\n\n\n\n## Flexible and Standards-Based[](#flexible-and-standards-based)\n\nVisuallyJs is built on modern web standards. It uses SVG for diagrams and charts, and HTML/SVG for Apps, and exposes a wide range of CSS classes for you to hook into. This ensures that your visualizations are accessible, performant, and easy to style. The library's architecture is highly extensible, allowing you to create custom connectors, shapes, layouts and new charts to suit your specific needs.","url":"https://visuallyjs.com/react/docs","lib":"react","topic":""}}
|