orcasvn-react-diagrams 0.1.80 → 0.1.82

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.
package/dist/cjs/index.js CHANGED
@@ -869,8 +869,18 @@ var EVENT_MANUALLY_TRIGGER_DRAGGING_ELEMENT = 'manuallyTriggerDraggingElement';
869
869
  var EVENT_LINK_SELECTED = 'linkSelected';
870
870
  var EVENT_TEXT_SELECTED = 'textSelected';
871
871
  var EVENT_MANUALLY_TRIGGER_STARTED_LINKING = 'manuallyTriggerStartedLinking';
872
+ var INITIAL_EDITOR_CONFIGURATION = {
873
+ paperBounds: {
874
+ minX: -1500,
875
+ minY: -1500,
876
+ maxX: 1500,
877
+ maxY: 1500
878
+ },
879
+ paperOrigin: { x: 0, y: 0 }
880
+ };
872
881
  var EditorContext = /** @class */ (function () {
873
882
  function EditorContext(elements, links, texts, configuration) {
883
+ if (configuration === void 0) { configuration = INITIAL_EDITOR_CONFIGURATION; }
874
884
  var _this = this;
875
885
  /** @internal */
876
886
  this.onEditorContextUpdated = function (callback) {
@@ -883,7 +893,7 @@ var EditorContext = /** @class */ (function () {
883
893
  this._elements = elements;
884
894
  this._links = links;
885
895
  this._texts = texts;
886
- this._configuration = configuration || {};
896
+ this._configuration = Object.assign({}, INITIAL_EDITOR_CONFIGURATION, configuration);
887
897
  this._eventEmitter = new EventEmitter();
888
898
  }
889
899
  EditorContext.prototype.addEventListener = function (event, callback) {
@@ -7636,14 +7646,14 @@ var correctPortPositionInElement = function (elementRelativePosition, elementWid
7636
7646
  }
7637
7647
  return newPosition || elementRelativePosition;
7638
7648
  };
7639
- var windowsPositionToPaperPosition = function (clientPosition, paperElement, zoom) {
7649
+ var windowsPositionToPaperPosition = function (clientPosition, paperElement, zoom, paperBounds) {
7640
7650
  var paperRect = paperElement.getBoundingClientRect();
7641
7651
  // Calculate the position relative to the paper element
7642
- var xPosOnPaper = (clientPosition.x - paperRect.left) / zoom;
7643
- var yPosOnPaper = (clientPosition.y - paperRect.top) / zoom;
7652
+ var xPosOnPaper = Math.round((clientPosition.x - paperRect.left) / zoom) + paperBounds.minX;
7653
+ var yPosOnPaper = Math.round((clientPosition.y - paperRect.top) / zoom) + paperBounds.minY;
7644
7654
  return {
7645
- x: Math.round(xPosOnPaper),
7646
- y: Math.round(yPosOnPaper),
7655
+ x: xPosOnPaper,
7656
+ y: yPosOnPaper,
7647
7657
  };
7648
7658
  };
7649
7659
 
@@ -7763,11 +7773,22 @@ var automationAddPointsToLink = function (eleLink, elements, limitPoint) {
7763
7773
  return eleLink;
7764
7774
  };
7765
7775
 
7776
+ var editorConfigurationContext = React.createContext(null);
7777
+ var useEditorConfiguration = function () {
7778
+ var context = React.useContext(editorConfigurationContext);
7779
+ if (!context) {
7780
+ throw new Error("useEditorConfiguration must be used within an EditorConfigurationProvider");
7781
+ }
7782
+ return context;
7783
+ };
7784
+ var EditorConfigurationContextProvider = editorConfigurationContext.Provider;
7785
+
7766
7786
  // import { paperEventEmitterContext } from '../../contexts/paperEventEmitterContext';
7767
7787
  var SelectionFrame = function (props) {
7768
7788
  var propTargetSVGElement = props.targetSVGElement, propWidth = props.width, propHeight = props.height, propFramePadding = props.framePadding, objectX = props.objectX, objectY = props.objectY,
7769
7789
  // movingOffsetThreshold: propMovingOffsetThreshold,
7770
7790
  propMovingRate = props.movingRate, propOnMouseDown = props.onMouseDown, propOnMouseUp = props.onMouseUp, propOnMove = props.onMove, propContainer = props.container, propResizability = props.resizability, propOnResize = props.onResize, draggingByDefault = props.draggingByDefault, PropDragDropHandlerElement = props.dragDropHandlerElement, propStrokeWidth = props.strokeWidth, propAnchor = props.anchor, zoom = props.zoom;
7791
+ var paperBounds = useEditorConfiguration().paperBounds;
7771
7792
  var bbox = propTargetSVGElement === null || propTargetSVGElement === void 0 ? void 0 : propTargetSVGElement.getBBox();
7772
7793
  var _a = React.useState(propWidth || (bbox === null || bbox === void 0 ? void 0 : bbox.width) || MIN_ELEMENT_SIZE), width = _a[0], setWidth = _a[1];
7773
7794
  var _b = React.useState(propHeight || (bbox === null || bbox === void 0 ? void 0 : bbox.height) || MIN_ELEMENT_SIZE), height = _b[0], setHeight = _b[1];
@@ -7815,7 +7836,7 @@ var SelectionFrame = function (props) {
7815
7836
  var position = windowsPositionToPaperPosition({
7816
7837
  x: event.clientX,
7817
7838
  y: event.clientY
7818
- }, propContainer, zoom);
7839
+ }, propContainer, zoom, paperBounds);
7819
7840
  return position;
7820
7841
  }, [propContainer, zoom]);
7821
7842
  var addRectHandleMouseDown = function (event) {
@@ -8226,39 +8247,136 @@ var paperEventEmitterContext = React.createContext({
8226
8247
  onCommandRenderPort: onCommandRenderPort,
8227
8248
  });
8228
8249
 
8229
- var editorConfigurationContext = React.createContext(null);
8230
- var useEditorConfiguration = function () {
8231
- var context = React.useContext(editorConfigurationContext);
8232
- if (!context) {
8233
- throw new Error("useEditorConfiguration must be used within an EditorConfigurationProvider");
8234
- }
8235
- return context;
8236
- };
8237
- var EditorConfigurationContextProvider = editorConfigurationContext.Provider;
8238
-
8239
8250
  /**
8240
8251
  * Zoom context to manage zoom level and related state.
8241
8252
  * This context can be used to provide zoom functionality across the application.
8242
8253
  */
8243
- var zoomContext = React.createContext(null);
8244
- var ZoomContextProvider = function (_a) {
8245
- var children = _a.children;
8254
+ var zoomPanContext = React.createContext(null);
8255
+ var ZoomPanContextProvider = function (_a) {
8256
+ var paperOrigin = _a.paperOrigin, children = _a.children, bounds = _a.bounds, onExpandBounds = _a.onExpandBounds;
8246
8257
  var _b = React.useState(1), zoom = _b[0], setZoom = _b[1];
8247
8258
  var _c = React.useState(0), scrollLeft = _c[0], setScrollLeft = _c[1];
8248
8259
  var _d = React.useState(0), scrollTop = _d[0], setScrollTop = _d[1];
8260
+ var _e = React.useState(false), isPanning = _e[0], setIsPanning = _e[1];
8249
8261
  var wrapperRef = React.useRef(null);
8250
8262
  var contentRef = React.useRef(null);
8251
- var handleWheel = function (e) {
8252
- // Chỉ zoom khi giữ Ctrl
8253
- if (!e.ctrlKey)
8263
+ var originalWidth = bounds.maxX - bounds.minX;
8264
+ var originalHeight = bounds.maxY - bounds.minY;
8265
+ // Width and height of the content area based on zoom and bounds
8266
+ var contentWidth = Math.min(originalWidth, originalWidth * zoom);
8267
+ var contentHeight = Math.min(originalHeight, originalHeight * zoom);
8268
+ React.useLayoutEffect(function () {
8269
+ var _a;
8270
+ (_a = wrapperRef.current) === null || _a === void 0 ? void 0 : _a.scrollTo({
8271
+ left: scrollLeft,
8272
+ top: scrollTop,
8273
+ });
8274
+ }, [scrollLeft, scrollTop]);
8275
+ // Pan to paper origin on initial load
8276
+ React.useLayoutEffect(function () {
8277
+ var initialScrollLeft = Math.abs(bounds.minX) + (paperOrigin ? paperOrigin.x : 0);
8278
+ var initialScrollTop = Math.abs(bounds.minY) + (paperOrigin ? paperOrigin.y : 0);
8279
+ setScrollLeft(initialScrollLeft);
8280
+ setScrollTop(initialScrollTop);
8281
+ }, [paperOrigin === null || paperOrigin === void 0 ? void 0 : paperOrigin.x, paperOrigin === null || paperOrigin === void 0 ? void 0 : paperOrigin.y]);
8282
+ var resetZoom = function () {
8283
+ setZoom(1);
8284
+ };
8285
+ React.useEffect(function () {
8286
+ var preventBrowserZoom = function (e) {
8287
+ if (e.ctrlKey || e.metaKey) {
8288
+ e.preventDefault();
8289
+ }
8290
+ };
8291
+ window.addEventListener("wheel", preventBrowserZoom, { passive: false });
8292
+ return function () {
8293
+ window.removeEventListener("wheel", preventBrowserZoom);
8294
+ };
8295
+ }, []);
8296
+ var handleMouseDown = function (e) {
8297
+ if (e.button === 0) { // Left mouse button
8298
+ setIsPanning(true);
8299
+ }
8300
+ };
8301
+ var handleMouseUp = function (e) {
8302
+ setIsPanning(false);
8303
+ };
8304
+ // Throttle function to limit the frequency of handleMouseMove calls
8305
+ var throttle = React.useCallback(function (func, delay) {
8306
+ var timeoutId = null;
8307
+ var lastExecTime = 0;
8308
+ return function () {
8309
+ var args = [];
8310
+ for (var _i = 0; _i < arguments.length; _i++) {
8311
+ args[_i] = arguments[_i];
8312
+ }
8313
+ var currentTime = Date.now();
8314
+ if (currentTime - lastExecTime > delay) {
8315
+ func.apply(void 0, args);
8316
+ lastExecTime = currentTime;
8317
+ }
8318
+ else {
8319
+ if (timeoutId)
8320
+ clearTimeout(timeoutId);
8321
+ timeoutId = setTimeout(function () {
8322
+ func.apply(void 0, args);
8323
+ lastExecTime = Date.now();
8324
+ }, delay - (currentTime - lastExecTime));
8325
+ }
8326
+ };
8327
+ }, []);
8328
+ var handleMouseMoveCore = React.useCallback(function (e) {
8329
+ if (!isPanning || !wrapperRef.current)
8254
8330
  return;
8331
+ if (e.movementX === 0 && e.movementY === 0)
8332
+ return; // Ignore if there's no movement
8333
+ var newScrollLeft = wrapperRef.current.scrollLeft - e.movementX;
8334
+ var newScrollTop = wrapperRef.current.scrollTop - e.movementY;
8335
+ setScrollLeft(newScrollLeft);
8336
+ setScrollTop(newScrollTop);
8337
+ var increment = 100;
8338
+ var newBounds = __assign({}, bounds);
8339
+ var isChangedBounds = false;
8340
+ // If pan reaches the right edge and mouse is moving right
8341
+ if (newScrollLeft + wrapperRef.current.clientWidth > wrapperRef.current.scrollWidth &&
8342
+ e.movementX < 0) {
8343
+ newBounds.maxX += increment;
8344
+ isChangedBounds = true;
8345
+ }
8346
+ // If pan reaches the left edge and mouse is moving left
8347
+ if (newScrollLeft < 0 && e.movementX > 0) {
8348
+ newBounds.minX -= increment;
8349
+ isChangedBounds = true;
8350
+ }
8351
+ // If pan reaches the bottom edge and mouse is moving down
8352
+ if (newScrollTop + wrapperRef.current.clientHeight > wrapperRef.current.scrollHeight &&
8353
+ e.movementY < 0) {
8354
+ newBounds.maxY += increment;
8355
+ isChangedBounds = true;
8356
+ }
8357
+ // If pan reaches the top edge and mouse is moving up
8358
+ if (newScrollTop < 0 && e.movementY > 0) {
8359
+ newBounds.minY -= increment;
8360
+ isChangedBounds = true;
8361
+ }
8362
+ if (isChangedBounds && onExpandBounds) {
8363
+ onExpandBounds(newBounds);
8364
+ }
8365
+ }, [isPanning, bounds, onExpandBounds]);
8366
+ // Throttled version of handleMouseMove (16ms = ~60fps)
8367
+ var handleMouseMove = React.useCallback(throttle(handleMouseMoveCore, 16), [throttle, handleMouseMoveCore, bounds]);
8368
+ var handleWheelCore = React.useCallback(function (e) {
8255
8369
  e.preventDefault();
8256
- var delta = -e.deltaY;
8257
- var zoomFactor = 0.05;
8258
- var newZoom = zoom + (delta > 0 ? zoomFactor : -zoomFactor);
8259
- newZoom = Math.max(0.1, Math.min(newZoom, 4));
8370
+ // Only zoom when Ctrl key is pressed
8371
+ if (!e.ctrlKey)
8372
+ return;
8260
8373
  if (!wrapperRef.current || !contentRef.current)
8261
8374
  return;
8375
+ var delta = -e.deltaY;
8376
+ // Adjust zoom factor as needed
8377
+ var zoomFactor = 0.02;
8378
+ var newZoom = zoom + (delta > 0 ? zoomFactor : -zoomFactor);
8379
+ newZoom = Math.max(0.1, Math.min(newZoom, 4)); // Clamp zoom between 0.1 and 4
8262
8380
  var wrapper = wrapperRef.current;
8263
8381
  var content = contentRef.current;
8264
8382
  // Get bounding rectangle of the content
@@ -8267,55 +8385,49 @@ var ZoomContextProvider = function (_a) {
8267
8385
  var offsetY = e.clientY - rect.top;
8268
8386
  var percentX = offsetX / (content.offsetWidth);
8269
8387
  var percentY = offsetY / (content.offsetHeight);
8270
- console.log(offsetX, offsetY, content.offsetWidth, content.offsetHeight, percentX, percentY);
8271
8388
  // Old width and height of content
8272
8389
  var prevWidth = content.offsetWidth * zoom;
8273
8390
  var prevHeight = content.offsetHeight * zoom;
8274
8391
  var newWidth = content.offsetWidth * newZoom;
8275
8392
  var newHeight = content.offsetHeight * newZoom;
8393
+ // Calculate new scroll positions to keep the point under the cursor stationary
8276
8394
  var scrollLeft = wrapper.scrollLeft + (percentX * (newWidth - prevWidth));
8277
8395
  var scrollTop = wrapper.scrollTop + (percentY * (newHeight - prevHeight));
8278
8396
  setZoom(newZoom);
8279
8397
  setScrollLeft(scrollLeft);
8280
8398
  setScrollTop(scrollTop);
8281
- };
8282
- React.useLayoutEffect(function () {
8283
- var _a;
8284
- (_a = wrapperRef.current) === null || _a === void 0 ? void 0 : _a.scrollTo({
8285
- left: scrollLeft,
8286
- top: scrollTop,
8287
- });
8288
- }, [zoom, scrollLeft, scrollTop]);
8289
- var resetZoom = function () {
8290
- setZoom(1);
8291
- };
8292
- React.useEffect(function () {
8293
- var preventBrowserZoom = function (e) {
8294
- if (e.ctrlKey || e.metaKey) {
8399
+ }, [zoom]);
8400
+ // Throttled version of handleWheel (16ms = ~60fps)
8401
+ var handleWheel = React.useCallback(throttle(handleWheelCore, 16), [throttle, handleWheelCore]);
8402
+ var value = {
8403
+ zoom: zoom,
8404
+ isPanning: isPanning,
8405
+ wrapperContainer: wrapperRef.current,
8406
+ setZoom: setZoom,
8407
+ resetZoom: resetZoom
8408
+ };
8409
+ return (React.createElement(zoomPanContext.Provider, { value: value },
8410
+ React.createElement("div", { ref: wrapperRef, onWheel: handleWheel, onMouseDown: handleMouseDown, onMouseUp: handleMouseUp, onMouseMove: handleMouseMove,
8411
+ // onScroll={handleScroll}
8412
+ onContextMenu: function (e) {
8295
8413
  e.preventDefault();
8296
- }
8297
- };
8298
- window.addEventListener("wheel", preventBrowserZoom, { passive: false });
8299
- return function () {
8300
- window.removeEventListener("wheel", preventBrowserZoom);
8301
- };
8302
- }, []);
8303
- return (React.createElement(zoomContext.Provider, { value: { zoom: zoom, setZoom: setZoom, resetZoom: resetZoom } },
8304
- React.createElement("div", { ref: wrapperRef, onWheel: handleWheel, style: {
8414
+ }, style: {
8305
8415
  width: "100vw",
8306
8416
  height: "92vh",
8307
8417
  overflow: "auto",
8418
+ cursor: isPanning ? "grabbing" : "default",
8308
8419
  } },
8309
8420
  React.createElement("div", { ref: contentRef, style: {
8310
8421
  transform: "scale(".concat(zoom, ")"),
8311
8422
  transformOrigin: "top left",
8312
- // transition: "transform 0.1s linear",
8423
+ width: contentWidth,
8424
+ height: contentHeight,
8313
8425
  } }, children))));
8314
8426
  };
8315
- var useZoomContext = function () {
8316
- var context = React.useContext(zoomContext);
8427
+ var useZoomPanContext = function () {
8428
+ var context = React.useContext(zoomPanContext);
8317
8429
  if (!context) {
8318
- throw new Error("useZoomContext must be used within a ZoomContextProvider");
8430
+ throw new Error("useZoomPanContext must be used within a ZoomPanContextProvider");
8319
8431
  }
8320
8432
  return context;
8321
8433
  };
@@ -8325,7 +8437,7 @@ var Text = React.forwardRef(function (_a, ref) {
8325
8437
  var _d = React.useState(false), isSelected = _d[0], setIsSelected = _d[1];
8326
8438
  var _e = React.useState(false), isEditing = _e[0], setIsEditing = _e[1];
8327
8439
  var textFontSize = useEditorConfiguration().textFontSize;
8328
- var zoom = useZoomContext().zoom;
8440
+ var zoom = useZoomPanContext().zoom;
8329
8441
  var absolutePosition = React.useMemo(function () {
8330
8442
  var _a, _b;
8331
8443
  return {
@@ -8533,7 +8645,8 @@ var IElementLink = function (_a) {
8533
8645
  }), selectedLabelRef = _k[0], setSelectedLabelRef = _k[1];
8534
8646
  var _l = React.useState(false), isSelectedLink = _l[0], setIsSelectedLink = _l[1];
8535
8647
  var _m = React.useContext(paperEventEmitterContext), onPaperClicked = _m.onPaperClicked, onElementSelected = _m.onElementSelected;
8536
- var zoom = useZoomContext().zoom;
8648
+ var zoom = useZoomPanContext().zoom;
8649
+ var paperBounds = useEditorConfiguration().paperBounds;
8537
8650
  var pathRef = React.useRef(null);
8538
8651
  var labelRef = React.useRef(null);
8539
8652
  var sourceLabelRef = React.useRef(null);
@@ -8658,7 +8771,7 @@ var IElementLink = function (_a) {
8658
8771
  var paperPosition_1 = windowsPositionToPaperPosition({
8659
8772
  x: mouseEvent.clientX,
8660
8773
  y: mouseEvent.clientY
8661
- }, container, zoom);
8774
+ }, container, zoom, paperBounds);
8662
8775
  if (draggingPointIndexRef.current !== undefined) { // If dragging a point
8663
8776
  setPoints(function (prev) {
8664
8777
  var temp = __spreadArray([], prev, true);
@@ -8688,7 +8801,7 @@ var IElementLink = function (_a) {
8688
8801
  container === null || container === void 0 ? void 0 : container.removeEventListener('mousemove', handleMouseMove);
8689
8802
  container === null || container === void 0 ? void 0 : container.removeEventListener('mouseup', mouseUp);
8690
8803
  };
8691
- }, [container, isDragging, zoom, points, id, addMovingPoint]);
8804
+ }, [container, isDragging, zoom, points, id, addMovingPoint, paperBounds]);
8692
8805
  React.useEffect(function () {
8693
8806
  console.info("Container changed in link", id);
8694
8807
  }, [addMovingPoint]);
@@ -8824,24 +8937,35 @@ function configureLogger(_a) {
8824
8937
  }
8825
8938
 
8826
8939
  var Ruler = function (_a) {
8827
- var squareSize = _a.squareSize, border = _a.border;
8828
- var numColumns = Math.ceil(3000 / squareSize);
8829
- var numRows = Math.ceil(3000 / squareSize);
8830
- var tableWidth = numColumns * squareSize;
8831
- return (React.createElement("table", { style: { position: 'absolute', zIndex: -1, top: 0, left: 0, borderCollapse: 'collapse', width: tableWidth } },
8832
- React.createElement("tbody", null, Array.from({ length: numRows }).map(function (_, rowIndex) { return (React.createElement("tr", { key: rowIndex, style: { margin: 0, padding: 0 } }, Array.from({ length: numColumns }).map(function (_, colIndex) { return (React.createElement("td", { key: colIndex, style: {
8833
- width: squareSize,
8834
- height: squareSize,
8835
- border: border,
8836
- margin: 0,
8837
- padding: 0,
8838
- boxSizing: 'border-box',
8839
- verticalAlign: 'top',
8840
- position: 'relative',
8841
- fontSize: 12,
8842
- } },
8843
- rowIndex === 0 ? React.createElement("span", { style: { marginLeft: "-12px" } }, colIndex * squareSize) : "",
8844
- colIndex === 0 ? React.createElement("span", { style: { top: "-9px", position: "absolute" } }, rowIndex * squareSize) : "")); }))); }))));
8940
+ // const [offsetX, setOffsetX] = React.useState(0);
8941
+ // const [offsetY, setOffsetY] = React.useState(0);
8942
+ var squareSize = _a.squareSize, _b = _a.gridStroke, gridStroke = _b === void 0 ? 'grey' : _b, bounds = _a.bounds;
8943
+ var minX = bounds.minX, minY = bounds.minY, maxX = bounds.maxX, maxY = bounds.maxY;
8944
+ // const numColumnsInNegative = Math.ceil(Math.abs(minX) / squareSize);
8945
+ // const numRowsInNegative = Math.ceil(Math.abs(minY) / squareSize);
8946
+ var width = maxX - minX;
8947
+ var height = maxY - minY;
8948
+ var cellSize = squareSize;
8949
+ var gridStrokeWidth = 1;
8950
+ var borderStroke = '#000000';
8951
+ var borderStrokeWidth = 2;
8952
+ var patternId = "svg-grid-".concat(cellSize, "-").concat(gridStroke.replace(/[#(), ]/g, ""));
8953
+ // When scrolling/panning/wheeling/zooming, we need to update the offsets of the grid so that it appears fixed relative to the content
8954
+ // Update offsets when bounds change
8955
+ // useLayoutEffect(() => {
8956
+ // console.count("Updating ruler offsets due to bounds/zoom/scrollOffset change");
8957
+ // const newOffsetX = scrollOffset.x / zoom;
8958
+ // const newOffsetY = scrollOffset.y / zoom;
8959
+ // setOffsetX(newOffsetX);
8960
+ // setOffsetY(newOffsetY);
8961
+ // }, [minX, minY, maxX, maxY, zoom, scrollOffset.x, scrollOffset.y]);
8962
+ return (React.createElement("div", { style: { width: width, height: height, position: 'absolute', top: 0, left: 0, zIndex: -1 } },
8963
+ React.createElement("svg", { viewBox: "0 0 ".concat(width, " ").concat(height), width: "100%", height: "100%", preserveAspectRatio: "xMinYMin meet", role: "img", "aria-label": "Grid ".concat(width, " by ").concat(height, " with cell ").concat(cellSize) },
8964
+ React.createElement("defs", null,
8965
+ React.createElement("pattern", { id: patternId, width: cellSize, height: cellSize, patternUnits: "userSpaceOnUse" },
8966
+ React.createElement("path", { d: "M ".concat(cellSize, " 0 L 0 0 0 ").concat(cellSize), fill: "none", stroke: gridStroke, strokeWidth: gridStrokeWidth }))),
8967
+ React.createElement("rect", { x: 0, y: 0, width: width, height: height, fill: "url(#".concat(patternId, ")") }),
8968
+ React.createElement("rect", { x: 0, y: 0, width: width, height: height, fill: "none", stroke: borderStroke, strokeWidth: borderStrokeWidth }))));
8845
8969
  };
8846
8970
 
8847
8971
  var ElementWrapper = React.forwardRef(function (_a, ref) {
@@ -8863,14 +8987,23 @@ var ElementWrapper = React.forwardRef(function (_a, ref) {
8863
8987
  return (React.createElement("svg", { className: cssClass, x: x, y: y, onClick: handleClick, onContextMenu: handleClick, onMouseDown: onMouseDown, ref: ref, style: { overflow: "visible" }, onMouseMove: onMouseMove, onMouseLeave: onMouseLeave, onMouseUp: onMouseUp }, children));
8864
8988
  });
8865
8989
 
8990
+ var transformPositionToAnchoredPosition = function (position, elementSize, anchor) {
8991
+ var anchoredPosition = { x: position.x, y: position.y };
8992
+ if (anchor === exports.PositioningAnchor.Center) {
8993
+ anchoredPosition.x = position.x - elementSize.width / 2;
8994
+ anchoredPosition.y = position.y - elementSize.height / 2;
8995
+ }
8996
+ return anchoredPosition;
8997
+ };
8866
8998
  var Element = React.forwardRef(function (props, forwardedRef) {
8867
8999
  var _paperEventEmitterContext = React.useContext(paperEventEmitterContext);
9000
+ var paperBounds = useEditorConfiguration().paperBounds;
8868
9001
  // const elementObj = props.element;
8869
9002
  var beingSelected = props.beingSelected, portPlaceholderShape = props.portPlaceholderShape, children = props.children, container = props.container, onMouseUp = props.onMouseUp, onMouseDown = props.onMouseDown, onMouseLeave = props.onMouseLeave, onMouseMove = props.onMouseMove, onMoving = props.onMoving, onMoved = props.onMoved, onResized = props.onResized, onPortMoved = props.onPortMoved, onPortMouseDown = props.onPortMouseDown, onPortMouseUp = props.onPortMouseUp, onClick = props.onClick, onContextMenu = props.onContextMenu, onPortContextMenu = props.onPortContextMenu, onMouseUpAtLinkedPortPlaceholder = props.onMouseUpAtLinkedPortPlaceholder, onManuallyTriggerRenderPort = props.onManuallyTriggerRenderPort, draggingByDefault = props.draggingByDefault, parentDOM = props.parentDOM;
8870
9003
  var _a = props.element, id = _a.id, cssClass = _a.cssClass; _a.textsPlaceHolderClassName; var portSlideRailSVGClassName = _a.portSlideRailSVGClassName, portMoveableAreas = _a.portMoveableAreas, portDirection = _a.portDirection, defaultPortSize = _a.defaultPortSize; _a.textsPlaceHolderFlexStyle; _a.textsPlaceHolderFlexboxPosition; var resizability = _a.resizability, renderShape = _a.renderShape;
8871
9004
  var propPorts = props.element.ports;
8872
9005
  //state for position
8873
- var _b = React.useState(__assign({}, props.element.position)), position = _b[0], setPosition = _b[1];
9006
+ var _b = React.useState(__assign({}, transformPositionToAnchoredPosition(props.element.position, props.element.size, props.element.positionAnchor || exports.PositioningAnchor.TopLeft))), position = _b[0], setPosition = _b[1];
8874
9007
  //state for size
8875
9008
  var _c = React.useState(__assign({}, props.element.size)), size = _c[0], setSize = _c[1];
8876
9009
  var _d = React.useState(), selectedPort = _d[0], setSelectedPort = _d[1];
@@ -8880,8 +9013,8 @@ var Element = React.forwardRef(function (props, forwardedRef) {
8880
9013
  var _h = React.useState(false), someElementLinkStarted = _h[0], setSomeElementLinkStarted = _h[1];
8881
9014
  var _j = React.useState(), potentialPortPosition = _j[0], setPotentialPortPosition = _j[1];
8882
9015
  //Zoom
8883
- var zoom = useZoomContext().zoom;
8884
- var zoomRef = React.useRef(zoom);
9016
+ var zoom = useZoomPanContext().zoom;
9017
+ React.useRef(zoom);
8885
9018
  var elementRef = React.useRef(null);
8886
9019
  React.useImperativeHandle(forwardedRef, function () { return elementRef.current; });
8887
9020
  var elementLinkStarted = React.useRef();
@@ -8924,7 +9057,7 @@ var Element = React.forwardRef(function (props, forwardedRef) {
8924
9057
  portsRef.current = newState;
8925
9058
  return newState;
8926
9059
  });
8927
- }, [normalizePortPosition]);
9060
+ }, [normalizePortPosition, onPortMoved, id, _paperEventEmitterContext]);
8928
9061
  // useLayoutEffect(() => {
8929
9062
  // if (!hasNormalizedPortPositions.current && elementRef.current) {
8930
9063
  // handlePortsState(portsRef.current);
@@ -8949,9 +9082,10 @@ var Element = React.forwardRef(function (props, forwardedRef) {
8949
9082
  var elementAbsPosition = React.useMemo(function () { return getElementAbsPosition(); }, [getElementAbsPosition]);
8950
9083
  //update element position
8951
9084
  var updateElementPosition = React.useCallback(function (newPosition) {
8952
- setPosition({ x: newPosition.x, y: newPosition.y });
9085
+ var newPositionAdjusted = transformPositionToAnchoredPosition(newPosition, { width: size.width, height: size.height }, props.element.positionAnchor || exports.PositioningAnchor.TopLeft);
9086
+ setPosition(newPositionAdjusted);
8953
9087
  props.element.position = { x: newPosition.x, y: newPosition.y };
8954
- }, [props.element]);
9088
+ }, [props.element, size.width, size.height]);
8955
9089
  //update element size
8956
9090
  var updateElementSize = React.useCallback(function (newSize) {
8957
9091
  setSize({ width: newSize.width, height: newSize.height });
@@ -9208,7 +9342,7 @@ var Element = React.forwardRef(function (props, forwardedRef) {
9208
9342
  var paper = windowsPositionToPaperPosition({
9209
9343
  x: ev.clientX,
9210
9344
  y: ev.clientY
9211
- }, container, zoom);
9345
+ }, container, zoom, paperBounds);
9212
9346
  var elementAbsPosition_1 = getElementAbsPosition();
9213
9347
  var mousePositionOnElement = {
9214
9348
  x: paper.x - elementAbsPosition_1.x,
@@ -9380,16 +9514,24 @@ var Element = React.forwardRef(function (props, forwardedRef) {
9380
9514
  }, objectX: elementAbsPosition === null || elementAbsPosition === void 0 ? void 0 : elementAbsPosition.x, objectY: elementAbsPosition === null || elementAbsPosition === void 0 ? void 0 : elementAbsPosition.y, width: size.width, height: size.height, zoom: zoom, draggingByDefault: draggingByDefault,
9381
9515
  //movingOffsetThreshold: ELEMENT_MOVING_OFFSET_THRESHOLD,
9382
9516
  onMouseDown: function (ev) {
9383
- windowsPositionToPaperPosition({
9384
- x: ev.clientX,
9385
- y: ev.clientY
9386
- }, container, zoomRef.current);
9517
+ // const paperPosition = windowsPositionToPaperPosition(
9518
+ // {
9519
+ // x: ev.clientX,
9520
+ // y: ev.clientY
9521
+ // },
9522
+ // container as Element,
9523
+ // zoomRef.current
9524
+ // )
9387
9525
  onMouseDown === null || onMouseDown === void 0 ? void 0 : onMouseDown(ev, id);
9388
9526
  }, onMouseUp: function (ev) {
9389
- windowsPositionToPaperPosition({
9390
- x: ev.clientX,
9391
- y: ev.clientY
9392
- }, container, zoomRef.current);
9527
+ // const paperPosition = windowsPositionToPaperPosition(
9528
+ // {
9529
+ // x: ev.clientX,
9530
+ // y: ev.clientY
9531
+ // },
9532
+ // container as Element,
9533
+ // zoomRef.current
9534
+ // )
9393
9535
  onMouseUp === null || onMouseUp === void 0 ? void 0 : onMouseUp(ev, id);
9394
9536
  }, onMove: function (newX, newY) {
9395
9537
  var _a;
@@ -9701,14 +9843,16 @@ var Paper = function (props) {
9701
9843
  var _j = React.useState(null), selectedElementSVG = _j[0], setSelectedElementSVG = _j[1];
9702
9844
  var _k = React.useState(false), mouseDownedOnPaper = _k[0], setMouseDownedOnPaper = _k[1];
9703
9845
  var paperEventEmitter = React.useContext(paperEventEmitterContext);
9704
- var zoom = useZoomContext().zoom;
9846
+ var zoom = useZoomPanContext().zoom;
9847
+ var paperBounds = useEditorConfiguration().paperBounds;
9848
+ var paperWidth = paperBounds.maxX - paperBounds.minX;
9849
+ var paperHeight = paperBounds.maxY - paperBounds.minY;
9705
9850
  var zoomRef = React.useRef(zoom);
9706
9851
  var paperContainerRef = React.useRef(null);
9707
9852
  var tempLinkRef = React.useRef(tempLink); //Cache tempLink to avoid re-render when tempLink changed
9708
9853
  //const elementsRef = useRef<IElementState[]>([]); //Cache elements to avoid re-render when elements changed
9709
9854
  var linksRef = React.useRef(links); //Cache links to avoid re-render when links changed
9710
9855
  var textsRef = React.useRef(texts); //Cache texts to avoid re-render when texts changed
9711
- var size = props.size;
9712
9856
  var onPortMoved = props.onPortMoved, onPortSelected = props.onPortSelected, onPortMouseDown = props.onPortMouseDown, onPortMouseUp = props.onPortMouseUp,
9713
9857
  //onPortsChanged,
9714
9858
  onPortContextMenu = props.onPortContextMenu, onElementSelected = props.onElementSelected, onElementsChanged = props.onElementsChanged, onElementResized = props.onElementResized, onElementContextMenu = props.onElementContextMenu, onElementMouseUp = props.onElementMouseUp, onElementMouseDown = props.onElementMouseDown, onElementMouseMove = props.onElementMouseMove, onElementMoved = props.onElementMoved, onElementMouseLeave = props.onElementMouseLeave, onElementDeleted = props.onElementDeleted, onLinksChanged = props.onLinksChanged, onLinkSelected = props.onLinkSelected, onTextSelected = props.onTextSelected, onTextsChanged = props.onTextsChanged, manuallyTriggerRenderElementsHandler = props.manuallyTriggerRenderElementsHandler, manuallyTriggerRenderElementHandler = props.manuallyTriggerRenderElementHandler, manuallyTriggerRenderPortHandler = props.manuallyTriggerRenderPortHandler, onCreatingPortByLinking = props.onCreatingPortByLinking, onCreatingLink = props.onCreatingLink, onElementMoving = props.onElementMoving, manuallySelectElementHandler = props.manuallySelectElementHandler, manuallyTriggerDraggingElementHandler = props.manuallyTriggerDraggingElementHandler, manuallyTriggerStartedLinkingHandler = props.manuallyTriggerStartedLinkingHandler;
@@ -9993,7 +10137,7 @@ var Paper = function (props) {
9993
10137
  var _b = windowsPositionToPaperPosition({
9994
10138
  x: ev.clientX,
9995
10139
  y: ev.clientY
9996
- }, paperContainerRef.current, zoom), xPosOnPaper = _b.x, yPosOnPaper = _b.y;
10140
+ }, paperContainerRef.current, zoom, paperBounds), xPosOnPaper = _b.x, yPosOnPaper = _b.y;
9997
10141
  //if there is a temp link, update the temp target point
9998
10142
  if (tempLink) {
9999
10143
  var sourceElementAbsPosition = getAbsolutePosition(tempLink.sourceElement);
@@ -10019,7 +10163,7 @@ var Paper = function (props) {
10019
10163
  var _c = windowsPositionToPaperPosition({
10020
10164
  x: ev.clientX,
10021
10165
  y: ev.clientY
10022
- }, paperContainerRef.current, zoom), xPosOnPaper = _c.x, yPosOnPaper = _c.y;
10166
+ }, paperContainerRef.current, zoom, paperBounds), xPosOnPaper = _c.x, yPosOnPaper = _c.y;
10023
10167
  setMouseDownedOnPaper(true);
10024
10168
  (_a = props.onPaperClicked) === null || _a === void 0 ? void 0 : _a.call(props, {
10025
10169
  x: xPosOnPaper,
@@ -10038,7 +10182,7 @@ var Paper = function (props) {
10038
10182
  var _b = windowsPositionToPaperPosition({
10039
10183
  x: ev.clientX,
10040
10184
  y: ev.clientY
10041
- }, paperContainerRef.current, zoom), xPosOnPaper = _b.x, yPosOnPaper = _b.y;
10185
+ }, paperContainerRef.current, zoom, paperBounds), xPosOnPaper = _b.x, yPosOnPaper = _b.y;
10042
10186
  if (mouseDownedOnPaper) {
10043
10187
  setSelectedElement(undefined);
10044
10188
  setSelectedElementSVG(null);
@@ -10187,7 +10331,7 @@ var Paper = function (props) {
10187
10331
  var paperPosition = windowsPositionToPaperPosition({
10188
10332
  x: ev.clientX,
10189
10333
  y: ev.clientY
10190
- }, paperContainerRef.current, zoomRef.current);
10334
+ }, paperContainerRef.current, zoomRef.current, paperBounds);
10191
10335
  //broadcast port mouse down to parent component
10192
10336
  if (element) {
10193
10337
  onPortMouseDown === null || onPortMouseDown === void 0 ? void 0 : onPortMouseDown(port, element, paperPosition);
@@ -10203,7 +10347,7 @@ var Paper = function (props) {
10203
10347
  setTempLink(newLink);
10204
10348
  paperEventEmitter.emitElementLinkStarted(newLink);
10205
10349
  }
10206
- }, [paperEventEmitter, elementsState, onPortMouseDown]);
10350
+ }, [paperEventEmitter, elementsState, paperBounds, onPortMouseDown]);
10207
10351
  var createElementLink = React.useCallback(function (sourcePort, sourceElement, targetPort, targetElement) {
10208
10352
  //if no onCreatingLink prop, no link will be created
10209
10353
  if (!onCreatingLink) {
@@ -10225,7 +10369,7 @@ var Paper = function (props) {
10225
10369
  var paperPosition = windowsPositionToPaperPosition({
10226
10370
  x: ev.clientX,
10227
10371
  y: ev.clientY
10228
- }, paperContainerRef.current, zoomRef.current);
10372
+ }, paperContainerRef.current, zoomRef.current, paperBounds);
10229
10373
  //broadcast port mouse down to parent component
10230
10374
  if (element) {
10231
10375
  onPortMouseUp === null || onPortMouseUp === void 0 ? void 0 : onPortMouseUp(port, element, paperPosition);
@@ -10254,7 +10398,7 @@ var Paper = function (props) {
10254
10398
  }
10255
10399
  setTempLink(null);
10256
10400
  }
10257
- }, [paperEventEmitter, elementsState, createElementLink, onPortMouseUp, onLinksChanged]);
10401
+ }, [paperEventEmitter, elementsState, paperBounds, createElementLink, onPortMouseUp, onLinksChanged]);
10258
10402
  // const handlePortsChanged = useCallback((ports: IPort[], elementId: string) => {
10259
10403
  // const element = elementsRef.current.find(e => e.id === elementId);
10260
10404
  // if (element) {
@@ -10475,41 +10619,41 @@ var Paper = function (props) {
10475
10619
  var paperPosition = windowsPositionToPaperPosition({
10476
10620
  x: ev.clientX,
10477
10621
  y: ev.clientY
10478
- }, paperContainerRef.current, zoomRef.current);
10622
+ }, paperContainerRef.current, zoomRef.current, paperBounds);
10479
10623
  if (element) {
10480
10624
  onElementMouseUp === null || onElementMouseUp === void 0 ? void 0 : onElementMouseUp(ev, element, paperPosition);
10481
10625
  }
10482
- }, [onElementMouseUp, elementsState]);
10626
+ }, [onElementMouseUp, elementsState, paperBounds]);
10483
10627
  var handleMouseDown = React.useCallback(function (ev, elementId) {
10484
10628
  var element = elementsState.elements.find(function (ele) { return ele.id === elementId; });
10485
10629
  var paperPosition = windowsPositionToPaperPosition({
10486
10630
  x: ev.clientX,
10487
10631
  y: ev.clientY
10488
- }, paperContainerRef.current, zoomRef.current);
10632
+ }, paperContainerRef.current, zoomRef.current, paperBounds);
10489
10633
  if (element) {
10490
10634
  onElementMouseDown === null || onElementMouseDown === void 0 ? void 0 : onElementMouseDown(ev, element, paperPosition);
10491
10635
  }
10492
- }, [onElementMouseDown, elementsState]);
10636
+ }, [onElementMouseDown, elementsState, paperBounds]);
10493
10637
  var handleMouseMove = React.useCallback(function (ev, elementId) {
10494
10638
  var element = elementsState.elements.find(function (ele) { return ele.id === elementId; });
10495
10639
  var paperPosition = windowsPositionToPaperPosition({
10496
10640
  x: ev.clientX,
10497
10641
  y: ev.clientY
10498
- }, paperContainerRef.current, zoomRef.current);
10642
+ }, paperContainerRef.current, zoomRef.current, paperBounds);
10499
10643
  if (element) {
10500
10644
  onElementMouseMove === null || onElementMouseMove === void 0 ? void 0 : onElementMouseMove(ev, element, paperPosition);
10501
10645
  }
10502
- }, [onElementMouseMove, elementsState]);
10646
+ }, [onElementMouseMove, elementsState, paperBounds]);
10503
10647
  var handleMouseLeave = React.useCallback(function (ev, elementId) {
10504
10648
  var element = elementsState.elements.find(function (ele) { return ele.id === elementId; });
10505
10649
  var paperPosition = windowsPositionToPaperPosition({
10506
10650
  x: ev.clientX,
10507
10651
  y: ev.clientY
10508
- }, paperContainerRef.current, zoomRef.current);
10652
+ }, paperContainerRef.current, zoomRef.current, paperBounds);
10509
10653
  if (element) {
10510
10654
  onElementMouseLeave === null || onElementMouseLeave === void 0 ? void 0 : onElementMouseLeave(ev, element, paperPosition);
10511
10655
  }
10512
- }, [onElementMouseLeave, elementsState]);
10656
+ }, [onElementMouseLeave, elementsState, paperBounds]);
10513
10657
  var renderElementInTree = React.useCallback(function (element) {
10514
10658
  var _a;
10515
10659
  logger.info("Rendering element tree for element ".concat(element.id));
@@ -10518,7 +10662,7 @@ var Paper = function (props) {
10518
10662
  return (React.createElement("g", { id: "group-of-element-".concat(element.id), key: element.id },
10519
10663
  React.createElement(ReactElement, { key: "element-".concat(element.id, "-").concat(element.version), element: element,
10520
10664
  //id={element.id}
10521
- //ref={(refDOM) => element.DOM = refDOM}
10665
+ ref: function (refDOM) { return element.DOM = refDOM; },
10522
10666
  //height={element.size.height}
10523
10667
  //width={element.size.width}
10524
10668
  //x={element.positionAnchor === PositioningAnchor.Center ? element.position.x - element.size.width / 2 : element.position.x}
@@ -10547,8 +10691,8 @@ var Paper = function (props) {
10547
10691
  });
10548
10692
  }, [elementsState.elementsInTree, renderElementInTree]);
10549
10693
  return (React.createElement("div", { style: { position: "relative" } },
10550
- React.createElement(Ruler, { squareSize: 100, border: '1px dashed grey' }),
10551
- React.createElement("svg", { tabIndex: 0, width: size.width, height: size.height, ref: paperContainerRef, id: "paper-container", onMouseMove: handlePaperMouseMove, onMouseDown: handleMouseDownOnPaper, onMouseUp: handleMouseUpOnPaper },
10694
+ React.createElement(Ruler, { bounds: paperBounds, squareSize: 100 }),
10695
+ React.createElement("svg", { tabIndex: 0, width: paperWidth, height: paperHeight, viewBox: "".concat(paperBounds.minX, " ").concat(paperBounds.minY, " ").concat(paperWidth, " ").concat(paperHeight), ref: paperContainerRef, id: "paper-container", onMouseMove: handlePaperMouseMove, onMouseDown: handleMouseDownOnPaper, onMouseUp: handleMouseUpOnPaper },
10552
10696
  paperContainerRef.current ? ElementsInTree : "",
10553
10697
  links && links.map(function (link, index) {
10554
10698
  if (!link.targetElement || !link.targetPort)
@@ -10567,16 +10711,11 @@ var Paper = function (props) {
10567
10711
  var Paper$1 = React.memo(Paper);
10568
10712
 
10569
10713
  var Editor = function (_a) {
10570
- var editorContext = _a.editorContext, width = _a.width, height = _a.height;
10714
+ var editorContext = _a.editorContext; _a.width; _a.height;
10571
10715
  var _b = React.useState([]), elements = _b[0], setElements = _b[1];
10572
10716
  var _c = React.useState([]), links = _c[0], setLinks = _c[1];
10573
10717
  var _d = React.useState([]), texts = _d[0], setTexts = _d[1];
10574
- if (!width) {
10575
- width = 3000;
10576
- }
10577
- if (!height) {
10578
- height = 3000;
10579
- }
10718
+ var _e = React.useState(editorContext.configuration.paperBounds), bounds = _e[0], setBounds = _e[1];
10580
10719
  var setEditorStates = React.useCallback(function (ctx) {
10581
10720
  setElements(__spreadArray([], ctx.elements, true));
10582
10721
  setLinks(__spreadArray([], ctx.links, true));
@@ -10687,8 +10826,11 @@ var Editor = function (_a) {
10687
10826
  editorContext.onElementRemovedHandler(element.id, parentElementId);
10688
10827
  }, [editorContext]);
10689
10828
  return (React.createElement(EditorConfigurationContextProvider, { value: editorContext.configuration },
10690
- React.createElement(ZoomContextProvider, null,
10691
- React.createElement(Paper$1, { key: "paper", size: { width: width, height: height }, elements: elements, links: links, texts: texts, onPaperClicked: handlePaperClicked, onPortMouseDown: handlePortMouseDown, onPortMouseUp: handlePortMouseUp, onPortMoved: handlePortMoved, onPortSelected: handlePortSelected,
10829
+ React.createElement(ZoomPanContextProvider, { bounds: bounds, paperOrigin: editorContext.configuration.paperOrigin, onExpandBounds: function (bounds) {
10830
+ editorContext.configuration.paperBounds = bounds;
10831
+ setBounds(bounds);
10832
+ } },
10833
+ React.createElement(Paper$1, { key: "paper", elements: elements, links: links, texts: texts, onPaperClicked: handlePaperClicked, onPortMouseDown: handlePortMouseDown, onPortMouseUp: handlePortMouseUp, onPortMoved: handlePortMoved, onPortSelected: handlePortSelected,
10692
10834
  //onPortsChanged={handlePortsChanged}
10693
10835
  onPortContextMenu: handlePortContextMenu, onElementContextMenu: handleElementContextMenu, onElementMoved: handleElementMoved, onElementResized: handleElementResized, onElementSelected: handleElementSelected, onElementMouseLeave: handleElementMouseLeave, onElementMouseMove: handleElementMouseMove, onElementMouseDown: handleElementMouseDown, onElementMouseUp: handleElementMouseUp, onElementDeleted: handleElementRemoved, onElementsChanged: handleElementsChanged, onCreatingLink: handleOnCreatingLink, onElementMoving: handleOnElementMoving, onCreatingPortByLinking: handleOnCreatingPortByLinking, onLinkSelected: handleLinkSelected, onLinksChanged: handleLinksChanged, onTextSelected: handleTextSelected, onTextsChanged: handleTextsChanged, onPaperMouseMoved: handlePaperMouseMoved, onPaperMouseUp: handlePaperMouseUp, onPaperMouseDown: handlePaperMouseDown, manuallyTriggerRenderElementsHandler: editorContext.manuallyTriggerRenderElementsHandler.bind(editorContext), manuallyTriggerRenderElementHandler: editorContext.manuallyTriggerRenderElementHandler.bind(editorContext), manuallyTriggerRenderPortHandler: editorContext.manuallyTriggerRenderPortHandler.bind(editorContext), manuallySelectElementHandler: editorContext.manuallySelectElementHandler.bind(editorContext), manuallyTriggerDraggingElementHandler: editorContext.manuallyTriggerDraggingElementHandler.bind(editorContext), manuallyTriggerStartedLinkingHandler: editorContext.manuallyTriggerStartedLinkingHandler.bind(editorContext) }))));
10694
10836
  };