- Add css support in storybook.
- Add icons to mxgraph. - Convert some examples to storybook.development
|
@ -4245,6 +4245,38 @@
|
|||
"escape-string-regexp": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"file-loader": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz",
|
||||
"integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loader-utils": "^2.0.0",
|
||||
"schema-utils": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"json5": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
|
||||
"integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
|
||||
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
"json5": "^2.1.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
|
@ -5368,12 +5400,6 @@
|
|||
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
|
||||
"dev": true
|
||||
},
|
||||
"klona": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz",
|
||||
"integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==",
|
||||
"dev": true
|
||||
},
|
||||
"lerna": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lerna/-/lerna-4.0.0.tgz",
|
||||
|
@ -7270,16 +7296,6 @@
|
|||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"dev": true
|
||||
},
|
||||
"sass-loader": {
|
||||
"version": "11.0.1",
|
||||
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-11.0.1.tgz",
|
||||
"integrity": "sha512-Vp1LcP4slTsTNLEiDkTcm8zGN/XYYrZz2BZybQbliWA8eXveqA/AxsEjllQTpJbg2MzCsx/qNO48sHdZtOaxTw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"klona": "^2.0.4",
|
||||
"neo-async": "^2.6.2"
|
||||
}
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz",
|
||||
|
@ -8044,6 +8060,39 @@
|
|||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"url-loader": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz",
|
||||
"integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loader-utils": "^2.0.0",
|
||||
"mime-types": "^2.1.27",
|
||||
"schema-utils": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"json5": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
|
||||
"integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
|
||||
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
"json5": "^2.1.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
|
|
|
@ -32,8 +32,9 @@
|
|||
"lerna": "^4.0.0",
|
||||
"@lerna/filter-options": "4.0.0",
|
||||
"prettier": "^2.2.1",
|
||||
"sass-loader": "^11.0.1",
|
||||
"style-loader": "^2.0.0",
|
||||
"url-loader": "^4.1.1",
|
||||
"file-loader": "^6.2.0",
|
||||
"webpack": "^5.32.0",
|
||||
"webpack-cli": "^4.6.0",
|
||||
"webpack-merge": "^5.7.3",
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
div.mxRubberband {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: #0000FF;
|
||||
background: #0077FF;
|
||||
}
|
||||
.mxCellEditor {
|
||||
background: url(data:image/gif;base64,R0lGODlhMAAwAIAAAP///wAAACH5BAEAAAAALAAAAAAwADAAAAIxhI+py+0Po5y02ouz3rz7D4biSJbmiabqyrbuC8fyTNf2jef6zvf+DwwKh8Si8egpAAA7);
|
||||
_background: url('../images/transparent.gif');
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
overflow: visible;
|
||||
word-wrap: normal;
|
||||
border-width: 0;
|
||||
min-width: 1px;
|
||||
resize: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
.mxPlainTextEditor * {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
div.mxWindow {
|
||||
-webkit-box-shadow: 3px 3px 12px #C0C0C0;
|
||||
-moz-box-shadow: 3px 3px 12px #C0C0C0;
|
||||
box-shadow: 3px 3px 12px #C0C0C0;
|
||||
background: url(data:image/gif;base64,R0lGODlhGgAUAIAAAOzs7PDw8CH5BAAAAAAALAAAAAAaABQAAAIijI+py70Ao5y02lud3lzhD4ZUR5aPiKajyZbqq7YyB9dhAQA7);
|
||||
_background: url('../images/window.gif');
|
||||
border:1px solid #c3c3c3;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
}
|
||||
table.mxWindow {
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
font-family: Arial;
|
||||
font-size: 8pt;
|
||||
}
|
||||
td.mxWindowTitle {
|
||||
background: url(data:image/gif;base64,R0lGODlhFwAXAMQAANfX18rKyuHh4c7OzsDAwMHBwc/Pz+Li4uTk5NHR0dvb2+jo6O/v79/f3/n5+dnZ2dbW1uPj44yMjNPT0+Dg4N3d3ebm5szMzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAXABcAAAWQICESxWiW5Ck6bOu+MMvMdG3f86LvfO/rlqBwSCwaj8ikUohoOp/QaDNCrVqvWKpgezhsv+AwmEIum89ocmPNbrvf64p8Tq/b5Yq8fs/v5x+AgYKDhIAAh4iJiouHEI6PkJGSjhOVlpeYmZUJnJ2en6CcBqMDpaanqKgXq6ytrq+rAbKztLW2shK5uru8vbkhADs=) repeat-x;
|
||||
_background: url('../images/window-title.gif') repeat-x;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
overflow: hidden;
|
||||
height: 13px;
|
||||
padding: 2px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 6px;
|
||||
color: black;
|
||||
}
|
||||
td.mxWindowPane {
|
||||
vertical-align: top;
|
||||
padding: 0px;
|
||||
}
|
||||
div.mxWindowPane {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
td.mxWindowPane td {
|
||||
font-family: Arial;
|
||||
font-size: 8pt;
|
||||
}
|
||||
td.mxWindowPane input, td.mxWindowPane select, td.mxWindowPane textarea, td.mxWindowPane radio {
|
||||
border-color: #8C8C8C;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
font-family: Arial;
|
||||
font-size: 8pt;
|
||||
padding: 1px;
|
||||
}
|
||||
td.mxWindowPane button {
|
||||
background: url(data:image/gif;base64,R0lGODlhCgATALMAAP7+/t7e3vj4+Ojo6OXl5e/v7/n5+fb29vPz8/39/e3t7fHx8e7u7v///wAAAAAAACH5BAAAAAAALAAAAAAKABMAAAQ2MMlJhb0Y6c2X/2AhjiRjnqiirizqMkEsz0Rt30Ou7y8K/ouDcEg0GI9IgHLJbDif0Kh06owAADs=) repeat-x;
|
||||
_background: url('../images/button.gif') repeat-x;
|
||||
font-family: Arial;
|
||||
font-size: 8pt;
|
||||
padding: 2px;
|
||||
float: left;
|
||||
}
|
||||
img.mxToolbarItem {
|
||||
margin-right: 6px;
|
||||
margin-bottom: 6px;
|
||||
border-width: 1px;
|
||||
}
|
||||
select.mxToolbarCombo {
|
||||
vertical-align: top;
|
||||
border-style: inset;
|
||||
border-width: 2px;
|
||||
}
|
||||
div.mxToolbarComboContainer {
|
||||
padding: 2px;
|
||||
}
|
||||
img.mxToolbarMode {
|
||||
margin: 2px;
|
||||
margin-right: 4px;
|
||||
margin-bottom: 4px;
|
||||
border-width: 0px;
|
||||
}
|
||||
img.mxToolbarModeSelected {
|
||||
margin: 0px;
|
||||
margin-right: 2px;
|
||||
margin-bottom: 2px;
|
||||
border-width: 2px;
|
||||
border-style: inset;
|
||||
}
|
||||
div.mxTooltip {
|
||||
-webkit-box-shadow: 3px 3px 12px #C0C0C0;
|
||||
-moz-box-shadow: 3px 3px 12px #C0C0C0;
|
||||
box-shadow: 3px 3px 12px #C0C0C0;
|
||||
background: #FFFFCC;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: black;
|
||||
font-family: Arial;
|
||||
font-size: 8pt;
|
||||
position: absolute;
|
||||
cursor: default;
|
||||
padding: 4px;
|
||||
color: black;
|
||||
}
|
||||
div.mxPopupMenu {
|
||||
-webkit-box-shadow: 3px 3px 12px #C0C0C0;
|
||||
-moz-box-shadow: 3px 3px 12px #C0C0C0;
|
||||
box-shadow: 3px 3px 12px #C0C0C0;
|
||||
background: url(data:image/gif;base64,R0lGODlhGgAUAIAAAOzs7PDw8CH5BAAAAAAALAAAAAAaABQAAAIijI+py70Ao5y02lud3lzhD4ZUR5aPiKajyZbqq7YyB9dhAQA7);
|
||||
_background: url('../images/window.gif');
|
||||
position: absolute;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: black;
|
||||
}
|
||||
table.mxPopupMenu {
|
||||
border-collapse: collapse;
|
||||
margin-top: 1px;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
tr.mxPopupMenuItem {
|
||||
color: black;
|
||||
cursor: pointer;
|
||||
}
|
||||
tr.mxPopupMenuItemHover {
|
||||
background-color: #000066;
|
||||
color: #FFFFFF;
|
||||
cursor: pointer;
|
||||
}
|
||||
td.mxPopupMenuItem {
|
||||
padding: 2px 30px 2px 10px;
|
||||
white-space: nowrap;
|
||||
font-family: Arial;
|
||||
font-size: 8pt;
|
||||
}
|
||||
td.mxPopupMenuIcon {
|
||||
background-color: #D0D0D0;
|
||||
padding: 2px 4px 2px 4px;
|
||||
}
|
||||
.mxDisabled {
|
||||
opacity: 0.2 !important;
|
||||
cursor:default !important;
|
||||
}
|
After Width: | Height: | Size: 137 B |
After Width: | Height: | Size: 70 B |
After Width: | Height: | Size: 877 B |
After Width: | Height: | Size: 907 B |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 843 B |
After Width: | Height: | Size: 64 B |
After Width: | Height: | Size: 845 B |
After Width: | Height: | Size: 55 B |
After Width: | Height: | Size: 74 B |
After Width: | Height: | Size: 146 B |
After Width: | Height: | Size: 56 B |
After Width: | Height: | Size: 90 B |
After Width: | Height: | Size: 276 B |
After Width: | Height: | Size: 425 B |
After Width: | Height: | Size: 275 B |
After Width: | Height: | Size: 75 B |
|
@ -173,6 +173,8 @@ import mxOutline from './view/graph/mxOutline';
|
|||
import mxPrintPreview from './view/graph/mxPrintPreview';
|
||||
import mxSwimlaneManager from './view/graph/mxSwimlaneManager';
|
||||
|
||||
import '../css/common.css';
|
||||
|
||||
export default {
|
||||
mxClient,
|
||||
mxLog,
|
||||
|
|
|
@ -601,6 +601,7 @@ class mxEdgeStyle {
|
|||
}
|
||||
|
||||
const lastInx = pts.length - 1;
|
||||
let pe = null;
|
||||
|
||||
// Adds the waypoints
|
||||
if (controlHints != null && controlHints.length > 0) {
|
||||
|
@ -634,7 +635,7 @@ class mxEdgeStyle {
|
|||
}
|
||||
}
|
||||
|
||||
const pe = pts[lastInx];
|
||||
pe = pts[lastInx];
|
||||
|
||||
if (pe != null && hints[hints.length - 1] != null) {
|
||||
if (Math.abs(hints[hints.length - 1].x - pe.x) < tol) {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import mxConstants from '../../mxConstants';
|
||||
import mxPerimeter from './mxPerimeter';
|
||||
import mxUtils from '../../mxUtils';
|
||||
import { clone } from '../../mxCloneUtils';
|
||||
|
||||
/**
|
||||
* @class mxStylesheet
|
||||
|
@ -190,7 +191,7 @@ class mxStylesheet {
|
|||
const pairs = name.split(';');
|
||||
|
||||
if (style != null && name.charAt(0) !== ';') {
|
||||
style = mxUtils.clone(style);
|
||||
style = clone(style);
|
||||
} else {
|
||||
style = {};
|
||||
}
|
||||
|
|
|
@ -17,6 +17,22 @@ module.exports = merge(base, {
|
|||
library: 'mxgraph',
|
||||
libraryTarget: 'umd'
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(sa|sc|c)ss$/,
|
||||
use: ['style-loader', 'css-loader']
|
||||
},
|
||||
{
|
||||
test: /\.(ico|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$/,
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
name: 'images/[hash].[ext]',
|
||||
limit: 10000,
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new webpack.optimize.LimitChunkCountPlugin({
|
||||
maxChunks: 1,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "start-storybook -p 8901"
|
||||
"dev": "start-storybook -p 8901 -s ./public"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
|
|
After Width: | Height: | Size: 58 B |
|
@ -0,0 +1,131 @@
|
|||
import mxgraph from '@mxgraph/core';
|
||||
import HelloWorld from './HelloWorld.stories';
|
||||
|
||||
export default {
|
||||
title: 'Connections/Anchors',
|
||||
argTypes: {
|
||||
...HelloWorld.argTypes
|
||||
}
|
||||
};
|
||||
|
||||
const Template = ({ label, ...args }) => {
|
||||
const {
|
||||
mxGraph,
|
||||
mxEvent,
|
||||
mxRubberband,
|
||||
mxConnectionHandler,
|
||||
mxConnectionConstraint,
|
||||
mxGeometry,
|
||||
mxPolyline,
|
||||
mxPoint,
|
||||
mxCellState
|
||||
} = mxgraph;
|
||||
|
||||
const container = document.createElement('div');
|
||||
container.style.position = 'relative';
|
||||
container.style.overflow = 'hidden';
|
||||
container.style.width = `${args.width}px`;
|
||||
container.style.height = `${args.height}px`;
|
||||
container.style.background = 'url(/images/grid.gif)';
|
||||
container.style.cursor = 'default';
|
||||
|
||||
if (!args.contextMenu)
|
||||
mxEvent.disableContextMenu(container);
|
||||
|
||||
class MyCustomConnectionHandler extends mxConnectionHandler {
|
||||
// Enables connect preview for the default edge style
|
||||
createEdgeState(me) {
|
||||
const edge = graph.createEdge(null, null, null, null, null);
|
||||
return new mxCellState(
|
||||
this.graph.view,
|
||||
edge,
|
||||
this.graph.getCellStyle(edge)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyCustomGraph extends mxGraph {
|
||||
getAllConnectionConstraints(terminal, source) {
|
||||
// Overridden to define per-shape connection points
|
||||
if (terminal != null && terminal.shape != null) {
|
||||
if (terminal.shape.stencil != null) {
|
||||
if (terminal.shape.stencil.constraints != null) {
|
||||
return terminal.shape.stencil.constraints;
|
||||
}
|
||||
} else if (terminal.shape.constraints != null) {
|
||||
return terminal.shape.constraints;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
createConnectionHandler() {
|
||||
return new MyCustomConnectionHandler(this);
|
||||
}
|
||||
}
|
||||
|
||||
class MyCustomGeometryClass extends mxGeometry {
|
||||
// Defines the default constraints for the vertices
|
||||
constraints = [
|
||||
new mxConnectionConstraint(new mxPoint(0.25, 0), true),
|
||||
new mxConnectionConstraint(new mxPoint(0.5, 0), true),
|
||||
new mxConnectionConstraint(new mxPoint(0.75, 0), true),
|
||||
new mxConnectionConstraint(new mxPoint(0, 0.25), true),
|
||||
new mxConnectionConstraint(new mxPoint(0, 0.5), true),
|
||||
new mxConnectionConstraint(new mxPoint(0, 0.75), true),
|
||||
new mxConnectionConstraint(new mxPoint(1, 0.25), true),
|
||||
new mxConnectionConstraint(new mxPoint(1, 0.5), true),
|
||||
new mxConnectionConstraint(new mxPoint(1, 0.75), true),
|
||||
new mxConnectionConstraint(new mxPoint(0.25, 1), true),
|
||||
new mxConnectionConstraint(new mxPoint(0.5, 1), true),
|
||||
new mxConnectionConstraint(new mxPoint(0.75, 1), true),
|
||||
];
|
||||
}
|
||||
|
||||
// Edges have no connection points
|
||||
mxPolyline.prototype.constraints = null;
|
||||
|
||||
// Creates the graph inside the given container
|
||||
const graph = new MyCustomGraph(container);
|
||||
graph.setConnectable(true);
|
||||
|
||||
// Specifies the default edge style
|
||||
graph.getStylesheet().getDefaultEdgeStyle().edgeStyle =
|
||||
'orthogonalEdgeStyle';
|
||||
|
||||
// Enables rubberband selection
|
||||
if (args.rubberBand)
|
||||
new mxRubberband(graph);
|
||||
|
||||
// Gets the default parent for inserting new cells. This
|
||||
// is normally the first child of the root (ie. layer 0).
|
||||
const parent = graph.getDefaultParent();
|
||||
|
||||
// Adds cells to the model in a single step
|
||||
graph.batchUpdate(() => {
|
||||
const v1 = graph.insertVertex({
|
||||
parent,
|
||||
value: 'Hello,',
|
||||
position: [20, 20],
|
||||
size: [80, 30],
|
||||
geometryClass: MyCustomGeometryClass,
|
||||
});
|
||||
const v2 = graph.insertVertex({
|
||||
parent,
|
||||
value: 'World!',
|
||||
position: [200, 150],
|
||||
size: [80, 30],
|
||||
geometryClass: MyCustomGeometryClass,
|
||||
});
|
||||
const e1 = graph.insertEdge({
|
||||
parent,
|
||||
value: '',
|
||||
position: v1,
|
||||
size: v2,
|
||||
});
|
||||
});
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
export const Default = Template.bind({});
|
|
@ -0,0 +1,120 @@
|
|||
import mxgraph from '@mxgraph/core';
|
||||
|
||||
export default {
|
||||
title: 'Connections/EdgeTolerance',
|
||||
argTypes: {
|
||||
width: {
|
||||
type: 'number',
|
||||
defaultValue: 800
|
||||
},
|
||||
height: {
|
||||
type: 'number',
|
||||
defaultValue: 600
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const Template = ({ label, ...args }) => {
|
||||
const {
|
||||
mxGraph,
|
||||
mxEvent,
|
||||
mxUtils
|
||||
} = mxgraph;
|
||||
|
||||
const container = document.createElement('div');
|
||||
container.style.position = 'relative';
|
||||
container.style.overflow = 'hidden';
|
||||
container.style.width = `${args.width}px`;
|
||||
container.style.height = `${args.height}px`;
|
||||
container.style.background = 'url(/images/grid.gif)';
|
||||
container.style.cursor = 'default';
|
||||
|
||||
class MyCustomGraph extends mxGraph {
|
||||
fireMouseEvent(evtName, me, sender) {
|
||||
// Overrides the mouse event dispatching mechanism to update the
|
||||
// cell which is associated with the event in case the native hit
|
||||
// detection did not return anything.
|
||||
|
||||
// Checks if native hit detection did not return anything
|
||||
if (me.getState() == null) {
|
||||
// Updates the graph coordinates in the event since we need
|
||||
// them here. Storing them in the event means the overridden
|
||||
// method doesn't have to do this again.
|
||||
if (me.graphX == null || me.graphY == null) {
|
||||
const pt = mxUtils.convertPoint(container, me.getX(), me.getY());
|
||||
|
||||
me.graphX = pt.x;
|
||||
me.graphY = pt.y;
|
||||
}
|
||||
|
||||
const cell = this.getCellAt(me.graphX, me.graphY);
|
||||
if (this.getModel().isEdge(cell)) {
|
||||
me.state = this.view.getState(cell);
|
||||
|
||||
if (me.state != null && me.state.shape != null) {
|
||||
this.container.style.cursor = me.state.shape.node.style.cursor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (me.state == null) {
|
||||
this.container.style.cursor = 'default';
|
||||
}
|
||||
|
||||
super.fireMouseEvent(evtName, me, sender);
|
||||
}
|
||||
|
||||
dblClick(evt, cell) {
|
||||
// Overrides double click handling to use the tolerance
|
||||
if (cell == null) {
|
||||
const pt = mxUtils.convertPoint(
|
||||
el,
|
||||
mxEvent.getClientX(evt),
|
||||
mxEvent.getClientY(evt)
|
||||
);
|
||||
cell = this.getCellAt(pt.x, pt.y);
|
||||
}
|
||||
super.dblClick(evt, cell);
|
||||
}
|
||||
}
|
||||
|
||||
// Creates the graph inside the given container
|
||||
const graph = new MyCustomGraph(container);
|
||||
graph.setTolerance(20);
|
||||
|
||||
// Gets the default parent for inserting new cells. This
|
||||
// is normally the first child of the root (ie. layer 0).
|
||||
const parent = graph.getDefaultParent();
|
||||
|
||||
// Adds cells to the model in a single step
|
||||
graph.batchUpdate(() => {
|
||||
const v1 = graph.insertVertex({
|
||||
parent,
|
||||
value: 'Hello,',
|
||||
position: [120, 120],
|
||||
size: [80, 30],
|
||||
});
|
||||
const v2 = graph.insertVertex({
|
||||
parent,
|
||||
value: 'World!',
|
||||
position: [400, 250],
|
||||
size: [80, 30],
|
||||
});
|
||||
const e1 = graph.insertEdge({
|
||||
parent,
|
||||
source: v1,
|
||||
target: v2,
|
||||
style: 'edgeStyle=orthogonalEdgeStyle;',
|
||||
});
|
||||
const e2 = graph.insertEdge({
|
||||
parent,
|
||||
source: v2,
|
||||
target: v1,
|
||||
style: 'edgeStyle=orthogonalEdgeStyle;',
|
||||
});
|
||||
});
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
export const Default = Template.bind({});
|
|
@ -0,0 +1,261 @@
|
|||
import mxgraph from '@mxgraph/core';
|
||||
|
||||
import HelloWorld from './HelloWorld.stories';
|
||||
|
||||
export default {
|
||||
title: 'Backgrounds/ExtendCanvas',
|
||||
argTypes: {
|
||||
...HelloWorld.argTypes
|
||||
}
|
||||
};
|
||||
|
||||
const Template = ({ label, ...args }) => {
|
||||
const {
|
||||
mxGraph,
|
||||
mxEvent,
|
||||
mxRubberband,
|
||||
mxRectangle,
|
||||
mxGraphView,
|
||||
mxPoint,
|
||||
mxDomHelpers,
|
||||
mxUtils
|
||||
} = mxgraph;
|
||||
|
||||
const container = document.createElement('div');
|
||||
container.style.position = 'relative';
|
||||
container.style.overflow = 'auto';
|
||||
container.style.width = `${args.width}px`;
|
||||
container.style.height = `${args.height}px`;
|
||||
container.style.cursor = 'default';
|
||||
container.style.background = 'url(/images/grid.gif)';
|
||||
|
||||
if (!args.contextMenu)
|
||||
mxEvent.disableContextMenu(container);
|
||||
|
||||
/**
|
||||
* Specifies the size of the size for "tiles" to be used for a graph with
|
||||
* scrollbars but no visible background page. A good value is large
|
||||
* enough to reduce the number of repaints that is caused for auto-
|
||||
* translation, which depends on this value, and small enough to give
|
||||
* a small empty buffer around the graph. Default is 400x400.
|
||||
*/
|
||||
const scrollTileSize = new mxRectangle(0, 0, 400, 400);
|
||||
|
||||
class MyCustomGraph extends mxGraph {
|
||||
/**
|
||||
* Returns the padding for pages in page view with scrollbars.
|
||||
*/
|
||||
getPagePadding() {
|
||||
return new mxPoint(
|
||||
Math.max(0, Math.round(this.container.offsetWidth - 34)),
|
||||
Math.max(0, Math.round(this.container.offsetHeight - 34))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the page format scaled with the page size.
|
||||
*/
|
||||
getPageSize() {
|
||||
return this.pageVisible
|
||||
? new mxRectangle(
|
||||
0,
|
||||
0,
|
||||
this.pageFormat.width * this.pageScale,
|
||||
this.pageFormat.height * this.pageScale
|
||||
)
|
||||
: scrollTileSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rectangle describing the position and count of the
|
||||
* background pages, where x and y are the position of the top,
|
||||
* left page and width and height are the vertical and horizontal
|
||||
* page count.
|
||||
*/
|
||||
getPageLayout() {
|
||||
const size = this.pageVisible ? this.getPageSize() : scrollTileSize;
|
||||
const bounds = this.getGraphBounds();
|
||||
|
||||
if (bounds.width === 0 || bounds.height === 0) {
|
||||
return new mxRectangle(0, 0, 1, 1);
|
||||
}
|
||||
|
||||
// Computes untransformed graph bounds
|
||||
const x = Math.ceil(bounds.x / this.view.scale - this.view.translate.x);
|
||||
const y = Math.ceil(bounds.y / this.view.scale - this.view.translate.y);
|
||||
const w = Math.floor(bounds.width / this.view.scale);
|
||||
const h = Math.floor(bounds.height / this.view.scale);
|
||||
|
||||
const x0 = Math.floor(x / size.width);
|
||||
const y0 = Math.floor(y / size.height);
|
||||
const w0 = Math.ceil((x + w) / size.width) - x0;
|
||||
const h0 = Math.ceil((y + h) / size.height) - y0;
|
||||
|
||||
return new mxRectangle(x0, y0, w0, h0);
|
||||
}
|
||||
|
||||
getPreferredPageSize(bounds, width, height) {
|
||||
const pages = this.getPageLayout();
|
||||
const size = this.getPageSize();
|
||||
|
||||
return new mxRectangle(
|
||||
0,
|
||||
0,
|
||||
pages.width * size.width,
|
||||
pages.height * size.height
|
||||
);
|
||||
}
|
||||
|
||||
sizeDidChange() {
|
||||
if (this.container != null && mxUtils.hasScrollbars(this.container)) {
|
||||
const pages = this.getPageLayout();
|
||||
const pad = this.getPagePadding();
|
||||
const size = this.getPageSize();
|
||||
|
||||
// Updates the minimum graph size
|
||||
const minw = Math.ceil(
|
||||
(2 * pad.x) / this.view.scale + pages.width * size.width
|
||||
);
|
||||
const minh = Math.ceil(
|
||||
(2 * pad.y) / this.view.scale + pages.height * size.height
|
||||
);
|
||||
|
||||
const min = this.minimumGraphSize;
|
||||
|
||||
// LATER: Fix flicker of scrollbar size in IE quirks mode
|
||||
// after delayed call in window.resize event handler
|
||||
if (min == null || min.width !== minw || min.height !== minh) {
|
||||
this.minimumGraphSize = new mxRectangle(0, 0, minw, minh);
|
||||
}
|
||||
|
||||
// Updates auto-translate to include padding and graph size
|
||||
const dx = pad.x / this.view.scale - pages.x * size.width;
|
||||
const dy = pad.y / this.view.scale - pages.y * size.height;
|
||||
|
||||
if (
|
||||
!this.autoTranslate &&
|
||||
(this.view.translate.x !== dx || this.view.translate.y !== dy)
|
||||
) {
|
||||
this.autoTranslate = true;
|
||||
this.view.x0 = pages.x;
|
||||
this.view.y0 = pages.y;
|
||||
|
||||
// NOTE: THIS INVOKES THIS METHOD AGAIN. UNFORTUNATELY THERE IS NO WAY AROUND THIS SINCE THE
|
||||
// BOUNDS ARE KNOWN AFTER THE VALIDATION AND SETTING THE TRANSLATE TRIGGERS A REVALIDATION.
|
||||
// SHOULD MOVE TRANSLATE/SCALE TO VIEW.
|
||||
const tx = this.view.translate.x;
|
||||
const ty = this.view.translate.y;
|
||||
|
||||
this.view.setTranslate(dx, dy);
|
||||
this.container.scrollLeft += (dx - tx) * this.view.scale;
|
||||
this.container.scrollTop += (dy - ty) * this.view.scale;
|
||||
|
||||
this.autoTranslate = false;
|
||||
return;
|
||||
}
|
||||
super.sizeDidChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Creates the graph inside the given container
|
||||
const graph = new MyCustomGraph(container);
|
||||
graph.panningHandler.ignoreCell = true;
|
||||
graph.setPanning(true);
|
||||
|
||||
// Fits the number of background pages to the graph
|
||||
graph.view.getBackgroundPageBounds = function() {
|
||||
const layout = this.graph.getPageLayout();
|
||||
const page = this.graph.getPageSize();
|
||||
|
||||
return new mxRectangle(
|
||||
this.scale * (this.translate.x + layout.x * page.width),
|
||||
this.scale * (this.translate.y + layout.y * page.height),
|
||||
this.scale * layout.width * page.width,
|
||||
this.scale * layout.height * page.height
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Guesses autoTranslate to avoid another repaint (see below).
|
||||
* Works if only the scale of the graph changes or if pages
|
||||
* are visible and the visible pages do not change.
|
||||
*/
|
||||
const graphViewValidate = graph.view.validate;
|
||||
graph.view.validate = function() {
|
||||
if (
|
||||
this.graph.container != null &&
|
||||
mxUtils.hasScrollbars(this.graph.container)
|
||||
) {
|
||||
const pad = this.graph.getPagePadding();
|
||||
const size = this.graph.getPageSize();
|
||||
|
||||
// Updating scrollbars here causes flickering in quirks and is not needed
|
||||
// if zoom method is always used to set the current scale on the graph.
|
||||
const tx = this.translate.x;
|
||||
const ty = this.translate.y;
|
||||
this.translate.x = pad.x / this.scale - (this.x0 || 0) * size.width;
|
||||
this.translate.y = pad.y / this.scale - (this.y0 || 0) * size.height;
|
||||
}
|
||||
|
||||
graphViewValidate.apply(this, arguments);
|
||||
};
|
||||
|
||||
// Enables rubberband selection
|
||||
if (args.rubberBand)
|
||||
new mxRubberband(graph);
|
||||
|
||||
// Gets the default parent for inserting new cells. This
|
||||
// is normally the first child of the root (ie. layer 0).
|
||||
const parent = graph.getDefaultParent();
|
||||
|
||||
// Adds cells to the model in a single step
|
||||
graph.batchUpdate(() => {
|
||||
const v1 = graph.insertVertex({
|
||||
parent,
|
||||
value: 'Hello,',
|
||||
position: [20, 20],
|
||||
size: [80, 30],
|
||||
});
|
||||
const v2 = graph.insertVertex({
|
||||
parent,
|
||||
value: 'World!',
|
||||
position: [200, 150],
|
||||
size: [80, 30],
|
||||
});
|
||||
const e1 = graph.insertEdge({
|
||||
parent,
|
||||
source: v1,
|
||||
target: v2,
|
||||
});
|
||||
});
|
||||
|
||||
// Sets initial scrollbar positions
|
||||
window.setTimeout(() => {
|
||||
const bounds = graph.getGraphBounds();
|
||||
const width = Math.max(
|
||||
bounds.width,
|
||||
scrollTileSize.width * graph.view.scale
|
||||
);
|
||||
const height = Math.max(
|
||||
bounds.height,
|
||||
scrollTileSize.height * graph.view.scale
|
||||
);
|
||||
graph.container.scrollTop = Math.floor(
|
||||
Math.max(
|
||||
0,
|
||||
bounds.y - Math.max(20, (graph.container.clientHeight - height) / 4)
|
||||
)
|
||||
);
|
||||
graph.container.scrollLeft = Math.floor(
|
||||
Math.max(
|
||||
0,
|
||||
bounds.x - Math.max(0, (graph.container.clientWidth - width) / 2)
|
||||
)
|
||||
);
|
||||
}, 0);
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
export const Default = Template.bind({});
|
|
@ -1,7 +1,12 @@
|
|||
import mxgraph from '@mxgraph/core';
|
||||
|
||||
import HelloWorld from './HelloWorld.stories';
|
||||
|
||||
export default {
|
||||
title: 'Backgrounds/Grid'
|
||||
title: 'Backgrounds/Grid',
|
||||
argTypes: {
|
||||
...HelloWorld.argTypes
|
||||
}
|
||||
};
|
||||
|
||||
const Template = ({ label, ...args }) => {
|
||||
|
@ -21,11 +26,13 @@ const Template = ({ label, ...args }) => {
|
|||
const container = document.createElement('div');
|
||||
container.style.position = 'relative';
|
||||
container.style.overflow = 'hidden';
|
||||
container.style.height = '481px';
|
||||
container.style.width = `${args.width}px`;
|
||||
container.style.height = `${args.height}px`;
|
||||
container.style.cursor = 'default';
|
||||
div.appendChild(container);
|
||||
|
||||
mxEvent.disableContextMenu(container);
|
||||
if (!args.contextMenu)
|
||||
mxEvent.disableContextMenu(container);
|
||||
|
||||
// Creates the graph inside the given container
|
||||
var graph = new mxGraph(container);
|
||||
|
@ -33,7 +40,8 @@ const Template = ({ label, ...args }) => {
|
|||
graph.setPanning(true);
|
||||
|
||||
// Enables rubberband selection
|
||||
new mxRubberband(graph);
|
||||
if (args.rubberBand)
|
||||
new mxRubberband(graph);
|
||||
|
||||
let repaintGrid;
|
||||
|
||||
|
|
|
@ -1,7 +1,25 @@
|
|||
import mxgraph from '@mxgraph/core';
|
||||
|
||||
export default {
|
||||
title: 'Basic/HelloWorld'
|
||||
title: 'Basic/HelloWorld',
|
||||
argTypes: {
|
||||
width: {
|
||||
type: 'number',
|
||||
defaultValue: 800
|
||||
},
|
||||
height: {
|
||||
type: 'number',
|
||||
defaultValue: 600
|
||||
},
|
||||
contextMenu: {
|
||||
type: 'boolean',
|
||||
defaultValue: false
|
||||
},
|
||||
rubberBand: {
|
||||
type: 'boolean',
|
||||
defaultValue: true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const Template = ({ label, ...args }) => {
|
||||
|
@ -10,14 +28,17 @@ const Template = ({ label, ...args }) => {
|
|||
const container = document.createElement('div');
|
||||
container.style.position = 'relative';
|
||||
container.style.overflow = 'hidden';
|
||||
container.style.height = '241px';
|
||||
container.style.width = `${args.width}px`;
|
||||
container.style.height = `${args.height}px`;
|
||||
container.style.cursor = 'default';
|
||||
|
||||
mxEvent.disableContextMenu(container);
|
||||
if (!args.contextMenu)
|
||||
mxEvent.disableContextMenu(container);
|
||||
|
||||
const graph = new mxGraph(container);
|
||||
|
||||
new mxRubberband(graph);
|
||||
if (args.rubberBand)
|
||||
new mxRubberband(graph);
|
||||
|
||||
const parent = graph.getDefaultParent();
|
||||
|
||||
|
@ -30,6 +51,7 @@ const Template = ({ label, ...args }) => {
|
|||
size: [80, 30],
|
||||
relative: false,
|
||||
});
|
||||
|
||||
const vertex2 = graph.insertVertex({
|
||||
parent,
|
||||
value: 'World!',
|
||||
|
@ -37,9 +59,9 @@ const Template = ({ label, ...args }) => {
|
|||
size: [80, 30],
|
||||
relative: false,
|
||||
});
|
||||
|
||||
const edge = graph.insertEdge({
|
||||
parent,
|
||||
// value: 'to the',
|
||||
source: vertex1,
|
||||
target: vertex2,
|
||||
});
|
||||
|
|
|
@ -11,14 +11,10 @@ module.exports = {
|
|||
}
|
||||
},
|
||||
exclude: /node_modules/
|
||||
},
|
||||
{
|
||||
test: /\.(sa|sc|c)ss$/,
|
||||
use: ['style-loader', 'css-loader', 'sass-loader']
|
||||
}
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js', '.scss']
|
||||
extensions: ['.ts', '.js', '.css']
|
||||
}
|
||||
}
|