@inditextech/weave-sdk 5.0.0-SNAPSHOT.377.1 → 5.0.0-SNAPSHOT.403.1
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/sdk.js +2190 -140
- package/dist/sdk.node.js +2190 -140
- package/dist/sdk.node.stats.html +1 -1
- package/dist/sdk.stats.html +1 -1
- package/dist/types.d.ts +335 -51
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2190 -140
- package/dist/types.js.map +1 -1
- package/dist/types.stats.html +1 -1
- package/package.json +2 -2
package/dist/sdk.js
CHANGED
|
@@ -3501,13 +3501,34 @@ function getBoundingBox(nodes, config) {
|
|
|
3501
3501
|
height: maxY - minY
|
|
3502
3502
|
};
|
|
3503
3503
|
}
|
|
3504
|
+
/**
|
|
3505
|
+
* Builds an array of Weave node IDs from `groupId` up to the root,
|
|
3506
|
+
* including only nodes that have a `nodeType` attribute (actual Weave nodes,
|
|
3507
|
+
* not Konva stage/layer). Used as the multi-stop set for `getInstanceRecursive`
|
|
3508
|
+
* and group-context ancestor checks.
|
|
3509
|
+
*/
|
|
3510
|
+
function buildAncestorGroupIds(groupId, stage) {
|
|
3511
|
+
const ids = [];
|
|
3512
|
+
let cur = stage.findOne(`#${groupId}`) ?? null;
|
|
3513
|
+
while (cur) {
|
|
3514
|
+
const id = cur.getAttrs().id;
|
|
3515
|
+
if (id && cur.getAttrs().nodeType) ids.push(id);
|
|
3516
|
+
cur = cur.getParent();
|
|
3517
|
+
}
|
|
3518
|
+
return ids;
|
|
3519
|
+
}
|
|
3504
3520
|
function getTargetedNode(instance) {
|
|
3505
3521
|
const stage = instance.getStage();
|
|
3506
3522
|
let selectedGroup = void 0;
|
|
3507
3523
|
const mousePos = stage.getPointerPosition();
|
|
3508
3524
|
if (mousePos) {
|
|
3509
3525
|
const inter = stage.getIntersection(mousePos);
|
|
3510
|
-
if (inter)
|
|
3526
|
+
if (inter) {
|
|
3527
|
+
const selectionPlugin = instance.getPlugin("nodesSelection");
|
|
3528
|
+
const activeGroupContext = selectionPlugin?.getActiveGroupContext() ?? void 0;
|
|
3529
|
+
const stopIds = activeGroupContext ? buildAncestorGroupIds(activeGroupContext, stage) : void 0;
|
|
3530
|
+
selectedGroup = instance.getInstanceRecursive(inter, [], stopIds);
|
|
3531
|
+
}
|
|
3511
3532
|
}
|
|
3512
3533
|
return selectedGroup;
|
|
3513
3534
|
}
|
|
@@ -3648,7 +3669,7 @@ function getVisibleNodes({ instance, skipNodes, referenceLayer }) {
|
|
|
3648
3669
|
nodes.forEach((node) => {
|
|
3649
3670
|
const actualNodeParent = instance.getNodeContainer(node);
|
|
3650
3671
|
if (actualNodeParent?.getAttrs().id !== referenceLayer?.getAttrs().id) return;
|
|
3651
|
-
if (node.getParent()?.getAttrs().nodeType === "group") return;
|
|
3672
|
+
if (node.getParent()?.getAttrs().nodeType === "group" && node.getParent()?.getAttrs().id !== referenceLayer?.getAttrs().id) return;
|
|
3652
3673
|
if (skipNodes.includes(node.getParent()?.getAttrs().nodeId)) return;
|
|
3653
3674
|
if (skipNodes.includes(node.getAttrs().id ?? "")) return;
|
|
3654
3675
|
if (node.getAttrs().nodeType === "connector") return;
|
|
@@ -4356,6 +4377,7 @@ var TransformerController = class {
|
|
|
4356
4377
|
listening: true,
|
|
4357
4378
|
shouldOverdrawWholeArea: true
|
|
4358
4379
|
});
|
|
4380
|
+
this.tr.boundBoxFunc(this.getBoundBoxFunc());
|
|
4359
4381
|
layer.add(this.tr);
|
|
4360
4382
|
this.trHover = new Konva.Transformer({
|
|
4361
4383
|
id: "hoverTransformer",
|
|
@@ -4371,6 +4393,20 @@ var TransformerController = class {
|
|
|
4371
4393
|
this.registerTransformerEvents();
|
|
4372
4394
|
this.registerInstanceEvents();
|
|
4373
4395
|
}
|
|
4396
|
+
getBoundBoxFunc() {
|
|
4397
|
+
return (oldBox, newBox) => {
|
|
4398
|
+
const sx = newBox.width / oldBox.width;
|
|
4399
|
+
const sy = newBox.height / oldBox.height;
|
|
4400
|
+
const violatesConstraint = this.tr.nodes().some((node) => {
|
|
4401
|
+
const rect = node.getClientRect({ skipStroke: true });
|
|
4402
|
+
const { width: minWidth, height: minHeight } = node.getNodeMinSize();
|
|
4403
|
+
if (["middle-right", "middle-left"].includes(this.tr.getActiveAnchor() ?? "")) return rect.width * sx < minWidth;
|
|
4404
|
+
if (["top-center", "bottom-center"].includes(this.tr.getActiveAnchor() ?? "")) return rect.height * sy < minHeight;
|
|
4405
|
+
return rect.width * sx < minWidth || rect.height * sy < minHeight;
|
|
4406
|
+
});
|
|
4407
|
+
return violatesConstraint ? oldBox : newBox;
|
|
4408
|
+
};
|
|
4409
|
+
}
|
|
4374
4410
|
getTransformer() {
|
|
4375
4411
|
return this.tr;
|
|
4376
4412
|
}
|
|
@@ -4811,6 +4847,7 @@ function handleClickOrTap(ctx, e) {
|
|
|
4811
4847
|
let areNodesSelected = false;
|
|
4812
4848
|
let nodeTargeted = selectedGroup && !(selectedGroup.getAttrs().active ?? false) ? selectedGroup : e.target;
|
|
4813
4849
|
if (e.target === weave.getStage()) {
|
|
4850
|
+
if (ctx.getActiveGroupContext() !== null) ctx.exitGroupContext();
|
|
4814
4851
|
ctx.getGesture().resetDoubleTap();
|
|
4815
4852
|
ctx.getNodesSelectionFeedbackPlugin()?.cleanupSelectedHalos();
|
|
4816
4853
|
return;
|
|
@@ -4820,6 +4857,18 @@ function handleClickOrTap(ctx, e) {
|
|
|
4820
4857
|
ctx.getGesture().resetDoubleTap();
|
|
4821
4858
|
return;
|
|
4822
4859
|
}
|
|
4860
|
+
const activeGroupContext = ctx.getActiveGroupContext();
|
|
4861
|
+
if (activeGroupContext !== null) {
|
|
4862
|
+
const isInsideActiveGroup = isNodeInsideGroup(nodeTargeted, activeGroupContext, stage);
|
|
4863
|
+
if (isInsideActiveGroup) {
|
|
4864
|
+
const parentId = nodeTargeted.getParent()?.getAttrs().id ?? "";
|
|
4865
|
+
if (parentId !== activeGroupContext) ctx.enterGroupContext(parentId);
|
|
4866
|
+
}
|
|
4867
|
+
if (!isInsideActiveGroup) {
|
|
4868
|
+
ctx.exitGroupContext();
|
|
4869
|
+
nodeTargeted = weave.getInstanceRecursive(nodeTargeted);
|
|
4870
|
+
}
|
|
4871
|
+
}
|
|
4823
4872
|
const metaPressed = e.evt.shiftKey || e.evt.ctrlKey || e.evt.metaKey;
|
|
4824
4873
|
const nodeSelectedIndex = tr.nodes().findIndex((node) => {
|
|
4825
4874
|
return node.getAttrs().id === nodeTargeted.getAttrs().id;
|
|
@@ -4835,13 +4884,21 @@ function handleClickOrTap(ctx, e) {
|
|
|
4835
4884
|
const isMainLayer = parent === mainLayer;
|
|
4836
4885
|
const isContainerEmptyArea = e.target.getAttrs().isContainerPrincipal !== void 0 && !e.target.getAttrs().isContainerPrincipal;
|
|
4837
4886
|
if (isStage || isMainLayer || isContainerEmptyArea) ctx.setSelectedNodes([]);
|
|
4887
|
+
ctx.triggerSelectedNodesEvent();
|
|
4838
4888
|
return;
|
|
4839
4889
|
}
|
|
4840
|
-
if (nodeTargeted.getAttrs().nodeId) {
|
|
4890
|
+
if (!nodeTargeted.getAttrs().name?.includes("node") && nodeTargeted.getAttrs().nodeId) {
|
|
4841
4891
|
const realNode = stage.findOne(`#${nodeTargeted.getAttrs().nodeId}`);
|
|
4842
4892
|
if (realNode) nodeTargeted = realNode;
|
|
4843
4893
|
}
|
|
4844
4894
|
if (typeof nodeTargeted.getAttrs().isContainerPrincipal !== "undefined" && !nodeTargeted.getAttrs().isContainerPrincipal) return;
|
|
4895
|
+
let cur = nodeTargeted;
|
|
4896
|
+
let p = cur.getParent();
|
|
4897
|
+
while (p?.getAttrs().nodeType === "group" && activeGroupContext !== p.getAttrs().id && !isAncestorOfActiveGroup(p, activeGroupContext, stage)) {
|
|
4898
|
+
cur = p;
|
|
4899
|
+
p = cur.getParent();
|
|
4900
|
+
}
|
|
4901
|
+
nodeTargeted = cur;
|
|
4845
4902
|
if (ctx.getGesture().isDoubleTap && !metaPressed) {
|
|
4846
4903
|
ctx.getGesture().resetDoubleTap();
|
|
4847
4904
|
nodeTargeted.dblClick();
|
|
@@ -4873,6 +4930,40 @@ function handleClickOrTap(ctx, e) {
|
|
|
4873
4930
|
}
|
|
4874
4931
|
ctx.triggerSelectedNodesEvent();
|
|
4875
4932
|
}
|
|
4933
|
+
/**
|
|
4934
|
+
* Returns true if `node` is anywhere within the group hierarchy rooted at
|
|
4935
|
+
* `groupId`: either a descendant of the active group itself, or a descendant
|
|
4936
|
+
* of any ancestor group in the path from `groupId` to the root.
|
|
4937
|
+
* Used to decide whether a click should keep the current group context active.
|
|
4938
|
+
*/
|
|
4939
|
+
function isNodeInsideGroup(node, groupId, stage) {
|
|
4940
|
+
const groupNode = stage.findOne(`#${groupId}`);
|
|
4941
|
+
if (!groupNode) return false;
|
|
4942
|
+
const containerIds = new Set(buildAncestorGroupIds(groupId, stage));
|
|
4943
|
+
let current = node;
|
|
4944
|
+
while (current) {
|
|
4945
|
+
if (containerIds.has(current.getAttrs().id ?? "")) return true;
|
|
4946
|
+
current = current.getParent();
|
|
4947
|
+
}
|
|
4948
|
+
return false;
|
|
4949
|
+
}
|
|
4950
|
+
/**
|
|
4951
|
+
* Returns true if `node` is a (strict) ancestor of the active group — i.e.
|
|
4952
|
+
* it appears in the parent chain above `activeGroupId`, not at the group
|
|
4953
|
+
* itself and not below it.
|
|
4954
|
+
*/
|
|
4955
|
+
function isAncestorOfActiveGroup(node, activeGroupId, stage) {
|
|
4956
|
+
if (!node || !activeGroupId) return false;
|
|
4957
|
+
const nodeId = node.getAttrs().id ?? "";
|
|
4958
|
+
const activeGroupNode = stage.findOne(`#${activeGroupId}`);
|
|
4959
|
+
if (!activeGroupNode) return false;
|
|
4960
|
+
let cur = activeGroupNode.getParent();
|
|
4961
|
+
while (cur) {
|
|
4962
|
+
if ((cur.getAttrs().id ?? "") === nodeId) return true;
|
|
4963
|
+
cur = cur.getParent();
|
|
4964
|
+
}
|
|
4965
|
+
return false;
|
|
4966
|
+
}
|
|
4876
4967
|
|
|
4877
4968
|
//#endregion
|
|
4878
4969
|
//#region src/plugins/nodes-selection/events/keyboard.ts
|
|
@@ -4886,6 +4977,13 @@ function registerKeyboardHandlers(ctx) {
|
|
|
4886
4977
|
const signal = ctx.getWeaveInstance().getEventsController().signal;
|
|
4887
4978
|
stage.container().addEventListener("keydown", (e) => {
|
|
4888
4979
|
if (e.code === "Space") ctx.setSpaceKeyPressed(true);
|
|
4980
|
+
if (e.code === "Escape") {
|
|
4981
|
+
if (ctx.getActiveGroupContext() !== null) {
|
|
4982
|
+
ctx.exitGroupContext();
|
|
4983
|
+
e.stopPropagation();
|
|
4984
|
+
return;
|
|
4985
|
+
}
|
|
4986
|
+
}
|
|
4889
4987
|
if (e.code === "Backspace" || e.code === "Delete") {
|
|
4890
4988
|
Promise.resolve().then(() => {
|
|
4891
4989
|
ctx.removeSelectedNodes();
|
|
@@ -4949,7 +5047,10 @@ function handlePointerDown(ctx, e) {
|
|
|
4949
5047
|
const nodesSelected = tr.nodes();
|
|
4950
5048
|
for (const node of nodesSelected) node.fire("onSelectionCleared", { bubbles: true });
|
|
4951
5049
|
}
|
|
5050
|
+
const activeGroupContext = ctx.getActiveGroupContext();
|
|
5051
|
+
if (activeGroupContext !== null) ctx.exitGroupContext();
|
|
4952
5052
|
ctx.selectNone();
|
|
5053
|
+
ctx.triggerSelectedNodesEvent();
|
|
4953
5054
|
ctx.getWeaveInstance().emitEvent("onSelectionState", true);
|
|
4954
5055
|
ctx.getEdgePanning().start();
|
|
4955
5056
|
}
|
|
@@ -5095,6 +5196,8 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
|
|
|
5095
5196
|
gesture = new GestureDetector();
|
|
5096
5197
|
_handledClickOrTap = false;
|
|
5097
5198
|
dragSelectedNodes = [];
|
|
5199
|
+
_activeGroupContext = null;
|
|
5200
|
+
onRender = void 0;
|
|
5098
5201
|
constructor(params) {
|
|
5099
5202
|
super();
|
|
5100
5203
|
this.config = mergeExceptArrays(WEAVE_NODES_SELECTION_DEFAULT_CONFIG, params?.config ?? {});
|
|
@@ -5119,6 +5222,8 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
|
|
|
5119
5222
|
this.enabled = false;
|
|
5120
5223
|
this.pointers = {};
|
|
5121
5224
|
this.dragSelectedNodes = [];
|
|
5225
|
+
this._handledClickOrTap = false;
|
|
5226
|
+
this._activeGroupContext = null;
|
|
5122
5227
|
}
|
|
5123
5228
|
getName() {
|
|
5124
5229
|
return WEAVE_NODES_SELECTION_KEY;
|
|
@@ -5240,6 +5345,7 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
|
|
|
5240
5345
|
this.active = true;
|
|
5241
5346
|
});
|
|
5242
5347
|
this.instance.addEventListener("onNodeRemoved", (node) => {
|
|
5348
|
+
if (this._activeGroupContext === node.id) this.exitGroupContext();
|
|
5243
5349
|
const selectedNodes = this.getSelectedNodes();
|
|
5244
5350
|
const newSelectedNodes = selectedNodes.filter((actNode) => actNode.getAttrs().id !== node.id);
|
|
5245
5351
|
this.setSelectedNodes(newSelectedNodes);
|
|
@@ -5248,6 +5354,31 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
|
|
|
5248
5354
|
stage.container().style.cursor = "default";
|
|
5249
5355
|
});
|
|
5250
5356
|
}
|
|
5357
|
+
getActiveGroupContext() {
|
|
5358
|
+
return this._activeGroupContext;
|
|
5359
|
+
}
|
|
5360
|
+
enterGroupContext(groupId) {
|
|
5361
|
+
const stage = this.instance.getStage();
|
|
5362
|
+
const groupNode = stage.findOne(`#${groupId}`);
|
|
5363
|
+
if (!groupNode) return;
|
|
5364
|
+
this._activeGroupContext = groupId;
|
|
5365
|
+
groupNode.getChildren().forEach((child) => {
|
|
5366
|
+
child.setAttr("draggable", true);
|
|
5367
|
+
});
|
|
5368
|
+
this.selectNone();
|
|
5369
|
+
this.instance.emitEvent("onGroupContextChange", groupId);
|
|
5370
|
+
}
|
|
5371
|
+
exitGroupContext() {
|
|
5372
|
+
if (this._activeGroupContext === null) return;
|
|
5373
|
+
const stage = this.instance.getStage();
|
|
5374
|
+
const groupNode = stage.findOne(`#${this._activeGroupContext}`);
|
|
5375
|
+
if (groupNode) groupNode.getChildren().forEach((child) => {
|
|
5376
|
+
child.setAttr("draggable", false);
|
|
5377
|
+
});
|
|
5378
|
+
this._activeGroupContext = null;
|
|
5379
|
+
this.selectNone();
|
|
5380
|
+
this.instance.emitEvent("onGroupContextChange", null);
|
|
5381
|
+
}
|
|
5251
5382
|
getLayer() {
|
|
5252
5383
|
const stage = this.instance.getStage();
|
|
5253
5384
|
return stage.findOne(`#${this.getLayerName()}`);
|
|
@@ -5432,6 +5563,9 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
|
|
|
5432
5563
|
isDragging() {
|
|
5433
5564
|
return this.transformerCtrl.isDragging();
|
|
5434
5565
|
}
|
|
5566
|
+
getBoundBoxFunc() {
|
|
5567
|
+
return this.transformerCtrl.getBoundBoxFunc();
|
|
5568
|
+
}
|
|
5435
5569
|
getSelectorConfig() {
|
|
5436
5570
|
return this.config.selection;
|
|
5437
5571
|
}
|
|
@@ -6006,6 +6140,12 @@ const augmentKonvaNodeClass = (config) => {
|
|
|
6006
6140
|
};
|
|
6007
6141
|
Konva.Node.prototype.lockMutex = function() {};
|
|
6008
6142
|
Konva.Node.prototype.releaseMutex = function() {};
|
|
6143
|
+
Konva.Node.prototype.getNodeMinSize = function() {
|
|
6144
|
+
return {
|
|
6145
|
+
width: 0,
|
|
6146
|
+
height: 0
|
|
6147
|
+
};
|
|
6148
|
+
};
|
|
6009
6149
|
};
|
|
6010
6150
|
var WeaveNode = class {
|
|
6011
6151
|
async register(instance) {
|
|
@@ -6169,8 +6309,8 @@ var WeaveNode = class {
|
|
|
6169
6309
|
if (selectionPlugin?.getSelectedNodes().map((node) => node.getAttrs().id).includes(ele.getAttrs().id)) return true;
|
|
6170
6310
|
return false;
|
|
6171
6311
|
}
|
|
6172
|
-
scaleReset(node) {
|
|
6173
|
-
const scale = node.scale();
|
|
6312
|
+
scaleReset(node, scaleCustom) {
|
|
6313
|
+
const scale = scaleCustom ?? node.scale();
|
|
6174
6314
|
node.width(Math.max(5, node.width() * scale.x));
|
|
6175
6315
|
node.height(Math.max(5, node.height() * scale.y));
|
|
6176
6316
|
node.scale({
|
|
@@ -6189,10 +6329,27 @@ var WeaveNode = class {
|
|
|
6189
6329
|
this.hideHoverState();
|
|
6190
6330
|
return;
|
|
6191
6331
|
}
|
|
6332
|
+
if (this.isHoverSuppressedByGroupContext(node, selectionPlugin)) {
|
|
6333
|
+
this.hideHoverState();
|
|
6334
|
+
return;
|
|
6335
|
+
}
|
|
6192
6336
|
if (node?.canBeHovered?.()) selectionPlugin.getHoverTransformer().nodes([node]);
|
|
6193
6337
|
else selectionPlugin.getHoverTransformer().nodes([]);
|
|
6194
6338
|
selectionPlugin.getHoverTransformer().moveToTop();
|
|
6195
6339
|
}
|
|
6340
|
+
isHoverSuppressedByGroupContext(node, selectionPlugin) {
|
|
6341
|
+
const activeGroupId = selectionPlugin.getActiveGroupContext();
|
|
6342
|
+
if (activeGroupId === null) return false;
|
|
6343
|
+
const activeGroupNode = this.instance.getStage().findOne(`#${activeGroupId}`);
|
|
6344
|
+
if (!activeGroupNode) return false;
|
|
6345
|
+
const hoveredId = node.getAttrs().id ?? "";
|
|
6346
|
+
let current = activeGroupNode;
|
|
6347
|
+
while (current) {
|
|
6348
|
+
if ((current.getAttrs().id ?? "") === hoveredId) return true;
|
|
6349
|
+
current = current.getParent();
|
|
6350
|
+
}
|
|
6351
|
+
return false;
|
|
6352
|
+
}
|
|
6196
6353
|
hideHoverState() {
|
|
6197
6354
|
const selectionPlugin = this.getSelectionPlugin();
|
|
6198
6355
|
if (!selectionPlugin) return;
|
|
@@ -6260,8 +6417,6 @@ var WeaveNode = class {
|
|
|
6260
6417
|
if (e.target.getAttrs()._revertStrokeScaleEnabled === true) e.target.setAttr("strokeScaleEnabled", true);
|
|
6261
6418
|
e.target.setAttr("_revertStrokeScaleEnabled", void 0);
|
|
6262
6419
|
this.instance.emitEvent("onTransform", null);
|
|
6263
|
-
const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
6264
|
-
if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
|
|
6265
6420
|
if (performScaleReset) this.scaleReset(node$1);
|
|
6266
6421
|
if (this.getSelectionPlugin()?.getSelectedNodes().length === 1) {
|
|
6267
6422
|
this.getNodesSelectionFeedbackPlugin()?.showSelectionHalo(node$1);
|
|
@@ -6270,8 +6425,13 @@ var WeaveNode = class {
|
|
|
6270
6425
|
const nodeHandler = this.instance.getNodeHandler(node$1.getAttrs().nodeType);
|
|
6271
6426
|
if (nodeHandler) {
|
|
6272
6427
|
const shouldUpdateOnTransform = node$1.getAttrs().shouldUpdateOnTransform ?? true;
|
|
6273
|
-
if (shouldUpdateOnTransform)
|
|
6428
|
+
if (shouldUpdateOnTransform) {
|
|
6429
|
+
const serializedNode = nodeHandler.serialize(node$1);
|
|
6430
|
+
this.instance.updateNode(serializedNode);
|
|
6431
|
+
}
|
|
6274
6432
|
}
|
|
6433
|
+
const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
6434
|
+
if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
|
|
6275
6435
|
this.getNodesSelectionPlugin()?.getHoverTransformer().forceUpdate();
|
|
6276
6436
|
});
|
|
6277
6437
|
const stage = this.instance.getStage();
|
|
@@ -6447,7 +6607,8 @@ var WeaveNode = class {
|
|
|
6447
6607
|
}
|
|
6448
6608
|
this.instance.emitEvent("onDrag", null);
|
|
6449
6609
|
const realNodeTarget = this.getRealSelectedNode(nodeTarget);
|
|
6450
|
-
|
|
6610
|
+
const isInGroupContext = (this.getSelectionPlugin()?.getActiveGroupContext() ?? null) !== null;
|
|
6611
|
+
if (!isInGroupContext && this.isSelecting() && this.getSelectionPlugin()?.getSelectedNodes().length === 1 && (realNodeTarget.getAttrs().lockToContainer === void 0 || !realNodeTarget.getAttrs().lockToContainer)) this.instance.stateTransactional(() => {
|
|
6451
6612
|
clearContainerTargets(this.instance);
|
|
6452
6613
|
const layerToMove = containerOverCursor(this.instance, [realNodeTarget]);
|
|
6453
6614
|
let containerToMove = this.instance.getMainLayer();
|
|
@@ -6535,7 +6696,19 @@ var WeaveNode = class {
|
|
|
6535
6696
|
const user = this.instance.getStore().getUser();
|
|
6536
6697
|
const activeAction = this.instance.getActiveAction();
|
|
6537
6698
|
const isNodeSelectionEnabled = this.getSelectionPlugin()?.isEnabled();
|
|
6538
|
-
const
|
|
6699
|
+
const activeGroupCtx = this.getSelectionPlugin()?.getActiveGroupContext() ?? void 0;
|
|
6700
|
+
let realNode;
|
|
6701
|
+
if (activeGroupCtx) {
|
|
6702
|
+
const stage$1 = this.instance.getStage();
|
|
6703
|
+
const stopIds = [];
|
|
6704
|
+
let cur = stage$1.findOne(`#${activeGroupCtx}`) ?? null;
|
|
6705
|
+
while (cur) {
|
|
6706
|
+
const id = cur.getAttrs().id;
|
|
6707
|
+
if (id) stopIds.push(id);
|
|
6708
|
+
cur = cur.getParent();
|
|
6709
|
+
}
|
|
6710
|
+
realNode = this.instance.getInstanceRecursive(node, [], stopIds);
|
|
6711
|
+
} else realNode = this.instance.getInstanceRecursive(node);
|
|
6539
6712
|
const canBeTargeted = realNode.getAttrs().canBeTargeted !== false;
|
|
6540
6713
|
const isLocked = realNode.getAttrs().locked ?? false;
|
|
6541
6714
|
const isMutexLocked = realNode.getAttrs().mutexLocked && realNode.getAttrs().mutexUserId !== user.id;
|
|
@@ -8416,7 +8589,11 @@ var WeaveGroupsManager = class {
|
|
|
8416
8589
|
this.instance.removeNodes(sortedNodesByZIndex);
|
|
8417
8590
|
groupInstance.destroy();
|
|
8418
8591
|
const groupNode = stage.findOne(`#${groupId}`);
|
|
8419
|
-
if (groupHandler && groupNode)
|
|
8592
|
+
if (groupHandler && groupNode) {
|
|
8593
|
+
groupNode.x(0);
|
|
8594
|
+
groupNode.y(0);
|
|
8595
|
+
this.instance.updateNodeNT(groupHandler.serialize(groupNode));
|
|
8596
|
+
}
|
|
8420
8597
|
setTimeout(() => {
|
|
8421
8598
|
this.getNodesMultiSelectionFeedbackPlugin()?.cleanupSelectedHalos();
|
|
8422
8599
|
const groupNode$1 = stage.findOne(`#${groupId}`);
|
|
@@ -8478,6 +8655,8 @@ var WeaveGroupsManager = class {
|
|
|
8478
8655
|
y: absScale.y / stage.scaleY()
|
|
8479
8656
|
});
|
|
8480
8657
|
child.rotation(absRotation);
|
|
8658
|
+
const nodeHandler = this.instance.getNodeHandler(child.getAttrs().nodeType);
|
|
8659
|
+
if (nodeHandler) nodeHandler.scaleReset(child);
|
|
8481
8660
|
child.zIndex(newLayerChildrenAmount - 1 + child.zIndex());
|
|
8482
8661
|
child.setAttr("draggable", true);
|
|
8483
8662
|
newChildId = child.getAttrs().id;
|
|
@@ -9288,6 +9467,7 @@ var WeaveStateManager = class {
|
|
|
9288
9467
|
}
|
|
9289
9468
|
const yjsProps = yjsNode.get("props");
|
|
9290
9469
|
this.updateYjsMapFromObject(yjsProps, node.props);
|
|
9470
|
+
if (Array.isArray(node.props.children) && node.props.children.length > 0) for (const child of node.props.children) this.updateNode(child);
|
|
9291
9471
|
this.instance.emitEvent("onNodeUpdated", node);
|
|
9292
9472
|
}
|
|
9293
9473
|
updateNodes(nodes) {
|
|
@@ -9482,7 +9662,7 @@ var WeaveRegisterManager = class {
|
|
|
9482
9662
|
|
|
9483
9663
|
//#endregion
|
|
9484
9664
|
//#region package.json
|
|
9485
|
-
var version = "5.0.0-SNAPSHOT.
|
|
9665
|
+
var version = "5.0.0-SNAPSHOT.403.1";
|
|
9486
9666
|
|
|
9487
9667
|
//#endregion
|
|
9488
9668
|
//#region src/managers/setup.ts
|
|
@@ -9576,13 +9756,18 @@ var WeaveStageManager = class {
|
|
|
9576
9756
|
const stage = this.getStage();
|
|
9577
9757
|
return stage.findOne(`#${WEAVE_UTILITY_LAYER_ID}`);
|
|
9578
9758
|
}
|
|
9579
|
-
getInstanceRecursive(instance, filterInstanceType = []) {
|
|
9759
|
+
getInstanceRecursive(instance, filterInstanceType = [], stopAtGroupId) {
|
|
9580
9760
|
const attributes = instance.getAttrs();
|
|
9761
|
+
if (stopAtGroupId) {
|
|
9762
|
+
const parentId = instance.getParent()?.getAttrs().id ?? "";
|
|
9763
|
+
const matches = Array.isArray(stopAtGroupId) ? stopAtGroupId.includes(parentId) : parentId === stopAtGroupId;
|
|
9764
|
+
if (matches) return instance;
|
|
9765
|
+
}
|
|
9581
9766
|
if (instance.getParent() && instance.getParent()?.getAttrs().nodeType && ![
|
|
9582
9767
|
"stage",
|
|
9583
9768
|
"layer",
|
|
9584
9769
|
...filterInstanceType
|
|
9585
|
-
].includes(instance.getParent()?.getAttrs().nodeType)) return this.getInstanceRecursive(instance.getParent());
|
|
9770
|
+
].includes(instance.getParent()?.getAttrs().nodeType)) return this.getInstanceRecursive(instance.getParent(), filterInstanceType, stopAtGroupId);
|
|
9586
9771
|
if (attributes.id === "mainLayer") return this.instance.getMainLayer();
|
|
9587
9772
|
if (attributes.id === "stage") return this.instance.getMainLayer();
|
|
9588
9773
|
return instance;
|
|
@@ -10921,8 +11106,8 @@ var Weave = class {
|
|
|
10921
11106
|
getStageConfiguration() {
|
|
10922
11107
|
return this.stageManager.getConfiguration();
|
|
10923
11108
|
}
|
|
10924
|
-
getInstanceRecursive(instance, filterInstanceType = []) {
|
|
10925
|
-
return this.stageManager.getInstanceRecursive(instance, filterInstanceType);
|
|
11109
|
+
getInstanceRecursive(instance, filterInstanceType = [], stopAtGroupId) {
|
|
11110
|
+
return this.stageManager.getInstanceRecursive(instance, filterInstanceType, stopAtGroupId);
|
|
10926
11111
|
}
|
|
10927
11112
|
getContainerNodes() {
|
|
10928
11113
|
return this.stageManager.getContainerNodes();
|
|
@@ -11871,10 +12056,55 @@ var WeaveGroupNode = class extends WeaveNode {
|
|
|
11871
12056
|
return intersectArrays(anchorsArrays);
|
|
11872
12057
|
};
|
|
11873
12058
|
this.setupDefaultNodeEvents(group);
|
|
12059
|
+
group.on("transform", () => {
|
|
12060
|
+
const sx = group.scaleX();
|
|
12061
|
+
const sy = group.scaleY();
|
|
12062
|
+
group.getChildren().forEach((child) => {
|
|
12063
|
+
child.scaleX(child.scaleX() * sx);
|
|
12064
|
+
child.scaleY(child.scaleY() * sy);
|
|
12065
|
+
child.x(child.x() * sx);
|
|
12066
|
+
child.y(child.y() * sy);
|
|
12067
|
+
const nodeHandler = this.instance.getNodeHandler(child.getAttrs().nodeType);
|
|
12068
|
+
if (nodeHandler) {
|
|
12069
|
+
nodeHandler.scaleReset(child);
|
|
12070
|
+
nodeHandler.onUpdate(child, child.getAttrs());
|
|
12071
|
+
}
|
|
12072
|
+
});
|
|
12073
|
+
group.scale({
|
|
12074
|
+
x: 1,
|
|
12075
|
+
y: 1
|
|
12076
|
+
});
|
|
12077
|
+
});
|
|
12078
|
+
group.dblClick = () => {
|
|
12079
|
+
const selectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
12080
|
+
if (!selectionPlugin) return;
|
|
12081
|
+
const groupId = group.getAttrs().id ?? "";
|
|
12082
|
+
selectionPlugin.enterGroupContext(groupId);
|
|
12083
|
+
const stage = this.instance.getStage();
|
|
12084
|
+
const mousePos = stage.getPointerPosition();
|
|
12085
|
+
if (!mousePos) return;
|
|
12086
|
+
const selectionLayer = stage.findOne("#" + selectionPlugin.getLayerName());
|
|
12087
|
+
selectionLayer?.listening(false);
|
|
12088
|
+
const intersected = stage.getIntersection(mousePos);
|
|
12089
|
+
selectionLayer?.listening(true);
|
|
12090
|
+
if (!intersected) return;
|
|
12091
|
+
const directChild = this.instance.getInstanceRecursive(intersected, [], groupId);
|
|
12092
|
+
if (directChild.getParent()?.getAttrs().id === groupId) {
|
|
12093
|
+
selectionPlugin.setSelectedNodes([directChild]);
|
|
12094
|
+
selectionPlugin.triggerSelectedNodesEvent();
|
|
12095
|
+
}
|
|
12096
|
+
};
|
|
11874
12097
|
return group;
|
|
11875
12098
|
}
|
|
11876
12099
|
onUpdate(nodeInstance, nextProps) {
|
|
11877
|
-
nodeInstance.setAttrs({
|
|
12100
|
+
nodeInstance.setAttrs({
|
|
12101
|
+
...nextProps,
|
|
12102
|
+
x: nextProps.x ?? 0,
|
|
12103
|
+
y: nextProps.y ?? 0,
|
|
12104
|
+
scaleX: nextProps.scaleX ?? 1,
|
|
12105
|
+
scaleY: nextProps.scaleY ?? 1,
|
|
12106
|
+
rotation: nextProps.rotation ?? 0
|
|
12107
|
+
});
|
|
11878
12108
|
const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
11879
12109
|
if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
|
|
11880
12110
|
}
|
|
@@ -11911,18 +12141,578 @@ var WeaveGroupNode = class extends WeaveNode {
|
|
|
11911
12141
|
}
|
|
11912
12142
|
};
|
|
11913
12143
|
}
|
|
11914
|
-
scaleReset() {
|
|
12144
|
+
scaleReset(node) {
|
|
12145
|
+
const sx = node.scaleX();
|
|
12146
|
+
const sy = node.scaleY();
|
|
12147
|
+
node.getChildren().forEach((child) => {
|
|
12148
|
+
child.scaleX(child.scaleX() * sx);
|
|
12149
|
+
child.scaleY(child.scaleY() * sy);
|
|
12150
|
+
child.x(child.x() * sx);
|
|
12151
|
+
child.y(child.y() * sy);
|
|
12152
|
+
const nodeHandler = this.instance.getNodeHandler(child.getAttrs().nodeType);
|
|
12153
|
+
if (nodeHandler) {
|
|
12154
|
+
nodeHandler.scaleReset(child);
|
|
12155
|
+
nodeHandler.onUpdate(child, child.getAttrs());
|
|
12156
|
+
}
|
|
12157
|
+
});
|
|
12158
|
+
node.scale({
|
|
12159
|
+
x: 1,
|
|
12160
|
+
y: 1
|
|
12161
|
+
});
|
|
12162
|
+
}
|
|
11915
12163
|
};
|
|
11916
12164
|
|
|
11917
12165
|
//#endregion
|
|
11918
12166
|
//#region src/nodes/rectangle/constants.ts
|
|
11919
12167
|
const WEAVE_RECTANGLE_NODE_TYPE = "rectangle";
|
|
11920
12168
|
|
|
12169
|
+
//#endregion
|
|
12170
|
+
//#region src/nodes/shared/shape-label.constants.ts
|
|
12171
|
+
const WEAVE_STAGE_SHAPE_LABEL_EDITION_MODE = "shape-label-edition";
|
|
12172
|
+
const WEAVE_SHAPE_LABEL_DEFAULTS = {
|
|
12173
|
+
labelText: "",
|
|
12174
|
+
labelFontFamily: "Arial, sans-serif",
|
|
12175
|
+
labelFontSize: 14,
|
|
12176
|
+
labelFontStyle: "normal",
|
|
12177
|
+
labelFontVariant: "normal",
|
|
12178
|
+
labelTextDecoration: "",
|
|
12179
|
+
labelFill: "#000000",
|
|
12180
|
+
labelAlign: "center",
|
|
12181
|
+
labelVerticalAlign: "middle",
|
|
12182
|
+
labelLetterSpacing: 0,
|
|
12183
|
+
labelLineHeight: 1,
|
|
12184
|
+
labelPaddingX: 8,
|
|
12185
|
+
labelPaddingY: 8
|
|
12186
|
+
};
|
|
12187
|
+
const labelId = (id) => `${id}-label`;
|
|
12188
|
+
|
|
12189
|
+
//#endregion
|
|
12190
|
+
//#region src/nodes/shared/shape-label-editor.ts
|
|
12191
|
+
var WeaveShapeLabelEditor = class {
|
|
12192
|
+
editing = false;
|
|
12193
|
+
editingGroup = null;
|
|
12194
|
+
editingTextBounds = null;
|
|
12195
|
+
textArea = null;
|
|
12196
|
+
onLiveResize = null;
|
|
12197
|
+
constructor(instance) {
|
|
12198
|
+
this.instance = instance;
|
|
12199
|
+
}
|
|
12200
|
+
isEditing() {
|
|
12201
|
+
return this.editing;
|
|
12202
|
+
}
|
|
12203
|
+
renderLabel(group, props, textBounds) {
|
|
12204
|
+
const labelText = props.labelText ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelText;
|
|
12205
|
+
const labelNode = new Konva.Text({
|
|
12206
|
+
id: labelId(props.id),
|
|
12207
|
+
x: textBounds.x,
|
|
12208
|
+
y: textBounds.y,
|
|
12209
|
+
width: textBounds.width,
|
|
12210
|
+
height: textBounds.height,
|
|
12211
|
+
text: labelText,
|
|
12212
|
+
fontFamily: props.labelFontFamily ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontFamily,
|
|
12213
|
+
fontSize: props.labelFontSize ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontSize,
|
|
12214
|
+
fontStyle: props.labelFontStyle ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontStyle,
|
|
12215
|
+
fontVariant: props.labelFontVariant ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontVariant,
|
|
12216
|
+
textDecoration: props.labelTextDecoration ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelTextDecoration,
|
|
12217
|
+
fill: props.labelFill ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFill,
|
|
12218
|
+
align: props.labelAlign ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelAlign,
|
|
12219
|
+
verticalAlign: props.labelVerticalAlign ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelVerticalAlign,
|
|
12220
|
+
letterSpacing: props.labelLetterSpacing ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelLetterSpacing,
|
|
12221
|
+
lineHeight: props.labelLineHeight ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelLineHeight,
|
|
12222
|
+
wrap: "word",
|
|
12223
|
+
listening: false,
|
|
12224
|
+
visible: labelText !== ""
|
|
12225
|
+
});
|
|
12226
|
+
group.add(labelNode);
|
|
12227
|
+
return labelNode;
|
|
12228
|
+
}
|
|
12229
|
+
updateLabel(group, nextProps, textBounds, growCallback) {
|
|
12230
|
+
const labelNode = group.findOne(`#${labelId(nextProps.id)}`);
|
|
12231
|
+
if (!labelNode) return;
|
|
12232
|
+
const labelText = nextProps.labelText ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelText;
|
|
12233
|
+
labelNode.setAttrs({
|
|
12234
|
+
x: textBounds.x,
|
|
12235
|
+
y: textBounds.y,
|
|
12236
|
+
width: textBounds.width,
|
|
12237
|
+
height: textBounds.height,
|
|
12238
|
+
text: labelText,
|
|
12239
|
+
fontFamily: nextProps.labelFontFamily ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontFamily,
|
|
12240
|
+
fontSize: nextProps.labelFontSize ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontSize,
|
|
12241
|
+
fontStyle: nextProps.labelFontStyle ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontStyle,
|
|
12242
|
+
fontVariant: nextProps.labelFontVariant ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontVariant,
|
|
12243
|
+
textDecoration: nextProps.labelTextDecoration ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelTextDecoration,
|
|
12244
|
+
fill: nextProps.labelFill ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFill,
|
|
12245
|
+
align: nextProps.labelAlign ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelAlign,
|
|
12246
|
+
verticalAlign: nextProps.labelVerticalAlign ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelVerticalAlign,
|
|
12247
|
+
letterSpacing: nextProps.labelLetterSpacing ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelLetterSpacing,
|
|
12248
|
+
lineHeight: nextProps.labelLineHeight ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelLineHeight,
|
|
12249
|
+
wrap: "word",
|
|
12250
|
+
visible: !this.editing && labelText !== ""
|
|
12251
|
+
});
|
|
12252
|
+
if (labelText !== "") {
|
|
12253
|
+
labelNode.setAttr("height", void 0);
|
|
12254
|
+
const measuredHeight = labelNode.height();
|
|
12255
|
+
labelNode.height(Math.max(textBounds.height, measuredHeight));
|
|
12256
|
+
if (growCallback && measuredHeight > textBounds.height) {
|
|
12257
|
+
const paddingY = nextProps.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
12258
|
+
growCallback(measuredHeight + paddingY * 2);
|
|
12259
|
+
}
|
|
12260
|
+
}
|
|
12261
|
+
}
|
|
12262
|
+
computeVerticalOffset(verticalAlign, boundsHeightPx, contentHeightPx) {
|
|
12263
|
+
if (verticalAlign === "top") return 0;
|
|
12264
|
+
if (verticalAlign === "bottom") return Math.max(0, boundsHeightPx - contentHeightPx);
|
|
12265
|
+
return Math.max(0, (boundsHeightPx - contentHeightPx) / 2);
|
|
12266
|
+
}
|
|
12267
|
+
triggerEditMode(group, textBounds, onCommit, onLiveResize) {
|
|
12268
|
+
if (this.editing) return;
|
|
12269
|
+
const lockAcquired = this.instance.setMutexLock({
|
|
12270
|
+
nodeIds: [group.id()],
|
|
12271
|
+
operation: "label-edit"
|
|
12272
|
+
});
|
|
12273
|
+
if (!lockAcquired) return;
|
|
12274
|
+
this.editing = true;
|
|
12275
|
+
this.editingGroup = group;
|
|
12276
|
+
this.editingTextBounds = textBounds;
|
|
12277
|
+
this.onLiveResize = onLiveResize ?? null;
|
|
12278
|
+
const labelNode = group.findOne(`#${labelId(group.id())}`);
|
|
12279
|
+
if (labelNode) labelNode.visible(false);
|
|
12280
|
+
const selectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
12281
|
+
if (selectionPlugin) {
|
|
12282
|
+
const tr = selectionPlugin.getTransformer();
|
|
12283
|
+
this.instance.disablePlugin("nodesSelection");
|
|
12284
|
+
tr.hide();
|
|
12285
|
+
}
|
|
12286
|
+
const stage = this.instance.getStage();
|
|
12287
|
+
const upscaleScale = stage.getAttr("upscaleScale") ?? 1;
|
|
12288
|
+
const absoluteTransform = group.getAbsoluteTransform();
|
|
12289
|
+
const topLeft = absoluteTransform.point({
|
|
12290
|
+
x: textBounds.x,
|
|
12291
|
+
y: textBounds.y
|
|
12292
|
+
});
|
|
12293
|
+
this.createTextAreaDOM(group, textBounds, topLeft, upscaleScale, onCommit, onLiveResize);
|
|
12294
|
+
this.instance.getStage().mode(WEAVE_STAGE_SHAPE_LABEL_EDITION_MODE);
|
|
12295
|
+
}
|
|
12296
|
+
exitEditMode() {
|
|
12297
|
+
if (!this.editing) return;
|
|
12298
|
+
this.instance.releaseMutexLock();
|
|
12299
|
+
this.instance.getStage().mode(WEAVE_STAGE_DEFAULT_MODE);
|
|
12300
|
+
this.editing = false;
|
|
12301
|
+
const editedGroupId = this.editingGroup?.id() ?? null;
|
|
12302
|
+
if (this.editingGroup) {
|
|
12303
|
+
const liveGroup = this.instance.getStage().findOne(`#${this.editingGroup.id()}`);
|
|
12304
|
+
const labelNode = liveGroup?.findOne(`#${labelId(this.editingGroup.id())}`);
|
|
12305
|
+
if (labelNode) {
|
|
12306
|
+
labelNode.visible(true);
|
|
12307
|
+
labelNode.getLayer()?.batchDraw();
|
|
12308
|
+
}
|
|
12309
|
+
this.editingGroup = null;
|
|
12310
|
+
}
|
|
12311
|
+
if (this.textArea) this.textArea.remove();
|
|
12312
|
+
this.textArea = null;
|
|
12313
|
+
this.onLiveResize = null;
|
|
12314
|
+
this.editingTextBounds = null;
|
|
12315
|
+
this.instance.getStage().off(".weaveLabelEdit");
|
|
12316
|
+
const selectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
12317
|
+
if (selectionPlugin) {
|
|
12318
|
+
this.instance.enablePlugin("nodesSelection");
|
|
12319
|
+
if (editedGroupId) requestAnimationFrame(() => {
|
|
12320
|
+
const liveGroup = this.instance.getStage().findOne(`#${editedGroupId}`);
|
|
12321
|
+
if (liveGroup) selectionPlugin.setSelectedNodes([liveGroup]);
|
|
12322
|
+
});
|
|
12323
|
+
}
|
|
12324
|
+
}
|
|
12325
|
+
updateTextAreaPosition(group, textBounds) {
|
|
12326
|
+
if (!this.editing || !this.textArea) return;
|
|
12327
|
+
const stage = this.instance.getStage();
|
|
12328
|
+
const upscaleScale = stage.getAttr("upscaleScale") ?? 1;
|
|
12329
|
+
const absoluteTransform = group.getAbsoluteTransform();
|
|
12330
|
+
const topLeft = absoluteTransform.point({
|
|
12331
|
+
x: textBounds.x,
|
|
12332
|
+
y: textBounds.y
|
|
12333
|
+
});
|
|
12334
|
+
this.textArea.style.left = `${topLeft.x * upscaleScale}px`;
|
|
12335
|
+
const absScale = group.getAbsoluteScale();
|
|
12336
|
+
const props = group.getAttrs();
|
|
12337
|
+
const fontSize = (props.labelFontSize ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontSize) * absScale.x;
|
|
12338
|
+
this.textArea.style.fontSize = `${fontSize * upscaleScale}px`;
|
|
12339
|
+
const textWidth = textBounds.width * absScale.x;
|
|
12340
|
+
this.textArea.style.width = `${textWidth * upscaleScale}px`;
|
|
12341
|
+
const originalBoundsHeightPx = textBounds.height * absScale.y * upscaleScale;
|
|
12342
|
+
const paddingY = props.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
12343
|
+
const verticalAlign = props.labelVerticalAlign ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelVerticalAlign;
|
|
12344
|
+
this.textArea.style.height = "auto";
|
|
12345
|
+
const contentHeightPx = this.textArea.scrollHeight;
|
|
12346
|
+
if (contentHeightPx <= originalBoundsHeightPx) {
|
|
12347
|
+
this.textArea.style.height = `${contentHeightPx}px`;
|
|
12348
|
+
const offsetY = this.computeVerticalOffset(verticalAlign, originalBoundsHeightPx, contentHeightPx);
|
|
12349
|
+
this.textArea.style.top = `${topLeft.y * upscaleScale + offsetY}px`;
|
|
12350
|
+
} else {
|
|
12351
|
+
this.textArea.style.height = `${contentHeightPx}px`;
|
|
12352
|
+
this.textArea.style.top = `${topLeft.y * upscaleScale}px`;
|
|
12353
|
+
}
|
|
12354
|
+
if (this.onLiveResize) {
|
|
12355
|
+
const contentHeightInCanvas = contentHeightPx / (absScale.y * upscaleScale);
|
|
12356
|
+
this.onLiveResize(contentHeightInCanvas + paddingY * 2);
|
|
12357
|
+
}
|
|
12358
|
+
}
|
|
12359
|
+
/**
|
|
12360
|
+
* Updates the textarea `left`, `width`, and `top` to match new text bounds.
|
|
12361
|
+
* Call this from an `onLiveResize` callback when the shape grows symmetrically
|
|
12362
|
+
* (e.g. regular polygon) so the textarea tracks the new position on all axes.
|
|
12363
|
+
* Does NOT call `onLiveResize` — there is no re-entrancy risk, but also no need.
|
|
12364
|
+
*/
|
|
12365
|
+
repositionTextArea(group, textBounds) {
|
|
12366
|
+
if (!this.editing || !this.textArea) return;
|
|
12367
|
+
this.editingTextBounds = textBounds;
|
|
12368
|
+
const stage = this.instance.getStage();
|
|
12369
|
+
const upscaleScale = stage.getAttr("upscaleScale") ?? 1;
|
|
12370
|
+
const absoluteTransform = group.getAbsoluteTransform();
|
|
12371
|
+
const topLeft = absoluteTransform.point({
|
|
12372
|
+
x: textBounds.x,
|
|
12373
|
+
y: textBounds.y
|
|
12374
|
+
});
|
|
12375
|
+
const absScale = group.getAbsoluteScale();
|
|
12376
|
+
const textWidth = textBounds.width * absScale.x;
|
|
12377
|
+
this.textArea.style.left = `${topLeft.x * upscaleScale}px`;
|
|
12378
|
+
this.textArea.style.width = `${textWidth * upscaleScale}px`;
|
|
12379
|
+
const newBoundsHeightPx = textBounds.height * absScale.y * upscaleScale;
|
|
12380
|
+
const savedHeight = this.textArea.style.height;
|
|
12381
|
+
this.textArea.style.height = "auto";
|
|
12382
|
+
const actualContentHeightPx = this.textArea.scrollHeight;
|
|
12383
|
+
this.textArea.style.height = savedHeight;
|
|
12384
|
+
const groupProps = group.getAttrs();
|
|
12385
|
+
const verticalAlign = groupProps.labelVerticalAlign ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelVerticalAlign;
|
|
12386
|
+
const offsetY = this.computeVerticalOffset(verticalAlign, newBoundsHeightPx, actualContentHeightPx);
|
|
12387
|
+
this.textArea.style.top = `${topLeft.y * upscaleScale + offsetY}px`;
|
|
12388
|
+
}
|
|
12389
|
+
/**
|
|
12390
|
+
* Convergence loop: onLiveResize may change the textarea width (e.g. a
|
|
12391
|
+
* growing polygon becomes wider), which changes line-wrapping, which may
|
|
12392
|
+
* require a different shape height. Iterates until scrollHeight is stable
|
|
12393
|
+
* or a safety limit is reached (5 passes cover any practical input).
|
|
12394
|
+
*
|
|
12395
|
+
* Oscillation prevention: if the sequence alternates (narrow→grow→wide→
|
|
12396
|
+
* restore→narrow→…) the loop exits with the polygon under-sized.
|
|
12397
|
+
* We track `lastUsedPx` — the height last passed to onLiveResize — and
|
|
12398
|
+
* fire a final corrective grow whenever `prevHeightPx > lastUsedPx`
|
|
12399
|
+
* (content at the current width still overflows what was last asked for).
|
|
12400
|
+
*/
|
|
12401
|
+
runLiveResizeLoop(onLiveResize, contentHeightPx, effectiveScale, upscaleScale, paddingY) {
|
|
12402
|
+
const MAX_PASSES = 5;
|
|
12403
|
+
let maxNeededPx = contentHeightPx;
|
|
12404
|
+
let prevHeightPx = contentHeightPx;
|
|
12405
|
+
let lastUsedPx = 0;
|
|
12406
|
+
for (let pass = 0; pass < MAX_PASSES; pass++) {
|
|
12407
|
+
lastUsedPx = prevHeightPx;
|
|
12408
|
+
const neededInCanvas = prevHeightPx / (effectiveScale * upscaleScale);
|
|
12409
|
+
onLiveResize(neededInCanvas + paddingY * 2);
|
|
12410
|
+
if (!this.textArea) break;
|
|
12411
|
+
this.textArea.style.height = "auto";
|
|
12412
|
+
const measuredPx = this.textArea.scrollHeight;
|
|
12413
|
+
this.textArea.style.height = `${measuredPx}px`;
|
|
12414
|
+
if (measuredPx > maxNeededPx) maxNeededPx = measuredPx;
|
|
12415
|
+
if (measuredPx === prevHeightPx) break;
|
|
12416
|
+
prevHeightPx = measuredPx;
|
|
12417
|
+
}
|
|
12418
|
+
if (this.textArea && prevHeightPx > lastUsedPx) {
|
|
12419
|
+
const finalInCanvas = maxNeededPx / (effectiveScale * upscaleScale);
|
|
12420
|
+
onLiveResize(finalInCanvas + paddingY * 2);
|
|
12421
|
+
this.textArea.style.height = "auto";
|
|
12422
|
+
const finalPx = this.textArea.scrollHeight;
|
|
12423
|
+
this.textArea.style.height = `${finalPx}px`;
|
|
12424
|
+
}
|
|
12425
|
+
}
|
|
12426
|
+
createTextAreaDOM(group, textBounds, position, upscaleScale, onCommit, onLiveResize) {
|
|
12427
|
+
const stage = this.instance.getStage();
|
|
12428
|
+
const props = group.getAttrs();
|
|
12429
|
+
const absScale = group.getAbsoluteScale();
|
|
12430
|
+
const effectiveScale = absScale.x;
|
|
12431
|
+
this.textArea = document.createElement("textarea");
|
|
12432
|
+
this.textArea.id = `${group.id()}_label_textarea`;
|
|
12433
|
+
this.textArea.rows = 1;
|
|
12434
|
+
stage.container().appendChild(this.textArea);
|
|
12435
|
+
stage.on("dragmove.weaveLabelEdit xChange.weaveLabelEdit yChange.weaveLabelEdit", () => {
|
|
12436
|
+
if (this.editingGroup && this.editingTextBounds) this.repositionTextArea(this.editingGroup, this.editingTextBounds);
|
|
12437
|
+
});
|
|
12438
|
+
const textWidth = textBounds.width * effectiveScale;
|
|
12439
|
+
const fontSize = (props.labelFontSize ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontSize) * effectiveScale;
|
|
12440
|
+
const originalBoundsHeightPx = textBounds.height * effectiveScale * upscaleScale;
|
|
12441
|
+
const paddingY = props.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
12442
|
+
this.textArea.style.position = "absolute";
|
|
12443
|
+
this.textArea.style.visibility = "hidden";
|
|
12444
|
+
this.textArea.style.left = `${position.x * upscaleScale}px`;
|
|
12445
|
+
this.textArea.style.width = `${textWidth * upscaleScale}px`;
|
|
12446
|
+
this.textArea.style.border = "solid 0px #1e40af";
|
|
12447
|
+
this.textArea.style.background = "transparent";
|
|
12448
|
+
this.textArea.style.backgroundColor = "transparent";
|
|
12449
|
+
this.textArea.style.boxSizing = "border-box";
|
|
12450
|
+
this.textArea.style.overflow = "hidden";
|
|
12451
|
+
const rotation = group.getAbsoluteRotation();
|
|
12452
|
+
if (rotation) {
|
|
12453
|
+
this.textArea.style.transformOrigin = "left top";
|
|
12454
|
+
this.textArea.style.transform = `rotate(${rotation}deg)`;
|
|
12455
|
+
}
|
|
12456
|
+
this.textArea.value = props.labelText ?? "";
|
|
12457
|
+
this.textArea.style.fontSize = `${fontSize * upscaleScale}px`;
|
|
12458
|
+
this.textArea.style.fontFamily = props.labelFontFamily ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontFamily;
|
|
12459
|
+
this.textArea.style.letterSpacing = `${props.labelLetterSpacing ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelLetterSpacing}px`;
|
|
12460
|
+
this.textArea.style.lineHeight = `${props.labelLineHeight ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelLineHeight}em`;
|
|
12461
|
+
const fontStyle = props.labelFontStyle ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontStyle;
|
|
12462
|
+
this.textArea.style.fontStyle = fontStyle.includes("italic") ? "italic" : "normal";
|
|
12463
|
+
this.textArea.style.textDecoration = props.labelTextDecoration ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelTextDecoration;
|
|
12464
|
+
let fontWeight = "normal";
|
|
12465
|
+
const matchNumber = fontStyle.match(/\d+/);
|
|
12466
|
+
if (fontStyle.includes("bold")) fontWeight = "bold";
|
|
12467
|
+
if (matchNumber) fontWeight = matchNumber[0];
|
|
12468
|
+
this.textArea.style.fontWeight = fontWeight;
|
|
12469
|
+
this.textArea.style.fontVariant = props.labelFontVariant ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontVariant;
|
|
12470
|
+
this.textArea.style.color = props.labelFill ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFill;
|
|
12471
|
+
this.textArea.style.textAlign = props.labelAlign ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelAlign;
|
|
12472
|
+
this.textArea.style.outline = "none";
|
|
12473
|
+
this.textArea.style.resize = "none";
|
|
12474
|
+
this.textArea.style.margin = "0";
|
|
12475
|
+
this.textArea.style.padding = "0";
|
|
12476
|
+
this.textArea.style.caretColor = "black";
|
|
12477
|
+
this.textArea.style.overscrollBehavior = "contains";
|
|
12478
|
+
const resizeTextarea = () => {
|
|
12479
|
+
if (!this.textArea) return;
|
|
12480
|
+
this.textArea.style.height = "auto";
|
|
12481
|
+
const contentHeightPx = this.textArea.scrollHeight;
|
|
12482
|
+
const fonts = this.instance.getFonts();
|
|
12483
|
+
const font = fonts.find((f) => f.name === (props.labelFontFamily ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontFamily));
|
|
12484
|
+
const currentBounds = this.editingTextBounds ?? textBounds;
|
|
12485
|
+
const liveTL = group.getAbsoluteTransform().point({
|
|
12486
|
+
x: currentBounds.x,
|
|
12487
|
+
y: currentBounds.y + (font?.offsetY ?? 0)
|
|
12488
|
+
});
|
|
12489
|
+
this.textArea.style.left = `${liveTL.x * upscaleScale}px`;
|
|
12490
|
+
if (contentHeightPx <= originalBoundsHeightPx) {
|
|
12491
|
+
this.textArea.style.height = `${contentHeightPx}px`;
|
|
12492
|
+
const verticalAlign = props.labelVerticalAlign ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelVerticalAlign;
|
|
12493
|
+
const offsetY = this.computeVerticalOffset(verticalAlign, originalBoundsHeightPx, contentHeightPx);
|
|
12494
|
+
this.textArea.style.top = `${liveTL.y * upscaleScale + offsetY}px`;
|
|
12495
|
+
} else {
|
|
12496
|
+
this.textArea.style.height = `${contentHeightPx}px`;
|
|
12497
|
+
this.textArea.style.top = `${liveTL.y * upscaleScale}px`;
|
|
12498
|
+
}
|
|
12499
|
+
if (onLiveResize) this.runLiveResizeLoop(onLiveResize, contentHeightPx, effectiveScale, upscaleScale, paddingY);
|
|
12500
|
+
if (this.textArea.style.visibility === "hidden") this.textArea.style.visibility = "";
|
|
12501
|
+
};
|
|
12502
|
+
const commit = (text) => {
|
|
12503
|
+
window.removeEventListener("pointerup", handleOutsideClick);
|
|
12504
|
+
this.exitEditMode();
|
|
12505
|
+
const liveGroup = this.instance.getStage().findOne(`#${group.id()}`);
|
|
12506
|
+
const labelNode = liveGroup?.findOne(`#${labelId(group.id())}`);
|
|
12507
|
+
if (labelNode) labelNode.visible(text !== "");
|
|
12508
|
+
onCommit(text);
|
|
12509
|
+
};
|
|
12510
|
+
this.textArea.addEventListener("keydown", (e) => {
|
|
12511
|
+
e.stopPropagation();
|
|
12512
|
+
if (e.code === "Escape") {
|
|
12513
|
+
e.preventDefault();
|
|
12514
|
+
commit(this.textArea?.value ?? "");
|
|
12515
|
+
return;
|
|
12516
|
+
}
|
|
12517
|
+
resizeTextarea();
|
|
12518
|
+
}, { signal: this.instance.getEventsController().signal });
|
|
12519
|
+
this.textArea.addEventListener("keyup", () => resizeTextarea(), { signal: this.instance.getEventsController().signal });
|
|
12520
|
+
this.textArea.addEventListener("input", () => resizeTextarea(), { signal: this.instance.getEventsController().signal });
|
|
12521
|
+
this.textArea.addEventListener("scroll", () => {
|
|
12522
|
+
if (this.textArea) {
|
|
12523
|
+
this.textArea.scrollTop = 0;
|
|
12524
|
+
this.textArea.scrollLeft = 0;
|
|
12525
|
+
}
|
|
12526
|
+
}, { signal: this.instance.getEventsController().signal });
|
|
12527
|
+
const handleOutsideClick = (e) => {
|
|
12528
|
+
e.stopPropagation();
|
|
12529
|
+
if (!this.textArea) return;
|
|
12530
|
+
const mouseX = e.clientX;
|
|
12531
|
+
const mouseY = e.clientY;
|
|
12532
|
+
let elementUnderMouse = document.elementFromPoint(mouseX, mouseY);
|
|
12533
|
+
if (isInShadowDOM(stage.container())) {
|
|
12534
|
+
const shadowHost = getTopmostShadowHost(stage.container());
|
|
12535
|
+
if (shadowHost) elementUnderMouse = shadowHost.elementFromPoint(mouseX, mouseY);
|
|
12536
|
+
}
|
|
12537
|
+
const clickedOutside = elementUnderMouse?.id !== `${group.id()}_label_textarea`;
|
|
12538
|
+
if (clickedOutside) commit(this.textArea.value);
|
|
12539
|
+
};
|
|
12540
|
+
setTimeout(() => {
|
|
12541
|
+
window.addEventListener("pointerup", handleOutsideClick, { signal: this.instance.getEventsController().signal });
|
|
12542
|
+
}, 0);
|
|
12543
|
+
this.textArea.tabIndex = 1;
|
|
12544
|
+
requestAnimationFrame(() => {
|
|
12545
|
+
resizeTextarea();
|
|
12546
|
+
this.textArea?.focus({ preventScroll: true });
|
|
12547
|
+
if (this.textArea?.value) this.textArea.select();
|
|
12548
|
+
});
|
|
12549
|
+
}
|
|
12550
|
+
};
|
|
12551
|
+
|
|
12552
|
+
//#endregion
|
|
12553
|
+
//#region src/nodes/shared/shape-label.utils.ts
|
|
12554
|
+
/**
|
|
12555
|
+
* Returns a partial props object containing only the label-related fields that
|
|
12556
|
+
* are explicitly set on `props`. Spread this into the `props` section of
|
|
12557
|
+
* `addNodeState` / `updateNodeState` to avoid duplicating the 12-field pattern
|
|
12558
|
+
* across every shape node that supports inline text labels.
|
|
12559
|
+
*/
|
|
12560
|
+
function spreadLabelProps(props) {
|
|
12561
|
+
return {
|
|
12562
|
+
...props.labelText !== void 0 && { labelText: props.labelText },
|
|
12563
|
+
...props.labelFontFamily !== void 0 && { labelFontFamily: props.labelFontFamily },
|
|
12564
|
+
...props.labelFontSize !== void 0 && { labelFontSize: props.labelFontSize },
|
|
12565
|
+
...props.labelFontStyle !== void 0 && { labelFontStyle: props.labelFontStyle },
|
|
12566
|
+
...props.labelFontVariant !== void 0 && { labelFontVariant: props.labelFontVariant },
|
|
12567
|
+
...props.labelFill !== void 0 && { labelFill: props.labelFill },
|
|
12568
|
+
...props.labelAlign !== void 0 && { labelAlign: props.labelAlign },
|
|
12569
|
+
...props.labelVerticalAlign !== void 0 && { labelVerticalAlign: props.labelVerticalAlign },
|
|
12570
|
+
...props.labelLetterSpacing !== void 0 && { labelLetterSpacing: props.labelLetterSpacing },
|
|
12571
|
+
...props.labelLineHeight !== void 0 && { labelLineHeight: props.labelLineHeight },
|
|
12572
|
+
...props.labelPaddingX !== void 0 && { labelPaddingX: props.labelPaddingX },
|
|
12573
|
+
...props.labelPaddingY !== void 0 && { labelPaddingY: props.labelPaddingY }
|
|
12574
|
+
};
|
|
12575
|
+
}
|
|
12576
|
+
/**
|
|
12577
|
+
* Returns the shared Zod schema fields for inline text label properties.
|
|
12578
|
+
* Spread the result of this function into a shape node's `props` schema
|
|
12579
|
+
* extension to avoid duplicating the 10-field label schema across rectangle,
|
|
12580
|
+
* ellipse, and any future shape that supports text labels.
|
|
12581
|
+
*/
|
|
12582
|
+
function getShapeLabelSchemaFields() {
|
|
12583
|
+
return {
|
|
12584
|
+
labelText: z.string().optional().describe("Text label displayed inside the shape"),
|
|
12585
|
+
labelFontFamily: z.string().optional().describe("Font family for the label text"),
|
|
12586
|
+
labelFontSize: z.number().optional().describe("Font size for the label text in pixels"),
|
|
12587
|
+
labelFontStyle: z.string().optional().describe("Font style for the label text (e.g. \"normal\", \"bold\", \"italic\", \"bold italic\")"),
|
|
12588
|
+
labelFontVariant: z.string().optional().describe("Font variant for the label text (e.g. \"normal\", \"small-caps\")"),
|
|
12589
|
+
labelFill: z.string().optional().describe("Color of the label text in hex format (e.g. #RRGGBBAA)"),
|
|
12590
|
+
labelAlign: z.string().optional().describe("Horizontal alignment of the label text (\"left\", \"center\", \"right\")"),
|
|
12591
|
+
labelVerticalAlign: z.string().optional().describe("Vertical alignment of the label text (\"top\", \"middle\", \"bottom\")"),
|
|
12592
|
+
labelLetterSpacing: z.number().optional().describe("Letter spacing for the label text in pixels"),
|
|
12593
|
+
labelLineHeight: z.number().optional().describe("Line height multiplier for the label text"),
|
|
12594
|
+
labelPaddingX: z.number().optional().describe("Horizontal inset (padding) in pixels applied on each side of the label"),
|
|
12595
|
+
labelPaddingY: z.number().optional().describe("Vertical inset (padding) in pixels applied on top and bottom of the label")
|
|
12596
|
+
};
|
|
12597
|
+
}
|
|
12598
|
+
/**
|
|
12599
|
+
* Extracts the label node and typography settings from a Konva group.
|
|
12600
|
+
* Returns `null` when the group has no label text or no label Konva.Text child.
|
|
12601
|
+
* Used internally by `computeRectangleLabelMinSize`, `computeEllipseLabelMinSize`,
|
|
12602
|
+
* and `computePolygonLabelMinSize` to avoid duplicating the setup logic.
|
|
12603
|
+
*/
|
|
12604
|
+
function extractLabelNodeContext(group, skipTransformInClientRect = true) {
|
|
12605
|
+
const attrs = group.getAttrs();
|
|
12606
|
+
const labelText = attrs.labelText ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelText;
|
|
12607
|
+
if (!labelText) return null;
|
|
12608
|
+
const labelNode = group.findOne(`#${labelId(group.id())}`);
|
|
12609
|
+
if (!labelNode) return null;
|
|
12610
|
+
const paddingX = attrs.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
12611
|
+
const paddingY = attrs.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
12612
|
+
const fontSize = attrs.labelFontSize ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontSize;
|
|
12613
|
+
const cloneLabel = labelNode.clone({ visible: false });
|
|
12614
|
+
cloneLabel.height(void 0);
|
|
12615
|
+
const naturalSize = cloneLabel.getClientRect({
|
|
12616
|
+
skipTransform: skipTransformInClientRect,
|
|
12617
|
+
skipShadow: true
|
|
12618
|
+
});
|
|
12619
|
+
return {
|
|
12620
|
+
paddingX,
|
|
12621
|
+
paddingY,
|
|
12622
|
+
fontSize,
|
|
12623
|
+
labelNode,
|
|
12624
|
+
naturalSize
|
|
12625
|
+
};
|
|
12626
|
+
}
|
|
12627
|
+
/**
|
|
12628
|
+
* Returns the minimum bounding size `{ width, height }` (in Konva canvas
|
|
12629
|
+
* units) that the rectangle must have so its label text is fully visible —
|
|
12630
|
+
* no vertical truncation and no horizontal clipping of the widest word.
|
|
12631
|
+
*
|
|
12632
|
+
* Returns `{ width: 0, height: 0 }` when the label is empty.
|
|
12633
|
+
*
|
|
12634
|
+
* @param group - The rectangle `Konva.Group` returned by `onRender`.
|
|
12635
|
+
*/
|
|
12636
|
+
function computeRectangleLabelMinSize(stage, group) {
|
|
12637
|
+
const ctx = extractLabelNodeContext(group);
|
|
12638
|
+
if (!ctx) return {
|
|
12639
|
+
width: 0,
|
|
12640
|
+
height: 0
|
|
12641
|
+
};
|
|
12642
|
+
const { paddingX, paddingY, fontSize, naturalSize } = ctx;
|
|
12643
|
+
return {
|
|
12644
|
+
width: (paddingX * 2 + fontSize) * stage.scaleX(),
|
|
12645
|
+
height: (naturalSize.height + paddingY * 2) * stage.scaleX()
|
|
12646
|
+
};
|
|
12647
|
+
}
|
|
12648
|
+
/**
|
|
12649
|
+
* Returns the minimum bounding box size `{ minWidth, minHeight }` (in Konva
|
|
12650
|
+
* canvas units, i.e. `radiusX * 2` × `radiusY * 2`) that the ellipse must have
|
|
12651
|
+
* so its inscribed label text is fully visible.
|
|
12652
|
+
*
|
|
12653
|
+
* The ellipse label sits inside the largest axis-aligned rectangle inscribed in
|
|
12654
|
+
* the ellipse: `inscribedW = radiusX * √2`, `inscribedH = radiusY * √2`. The
|
|
12655
|
+
* minimum radiusY is back-computed from the text's natural height:
|
|
12656
|
+
* `minRadiusY = ceil(naturalTextH / √2)`
|
|
12657
|
+
*
|
|
12658
|
+
* Returns `{ minWidth: 0, minHeight: 0 }` when the label is empty.
|
|
12659
|
+
*
|
|
12660
|
+
* @param group - The ellipse `Konva.Group` returned by `onRender`.
|
|
12661
|
+
*/
|
|
12662
|
+
function computeEllipseLabelMinSize(stage, group) {
|
|
12663
|
+
const ctx = extractLabelNodeContext(group);
|
|
12664
|
+
if (!ctx) return {
|
|
12665
|
+
width: 0,
|
|
12666
|
+
height: 0
|
|
12667
|
+
};
|
|
12668
|
+
const { paddingX, paddingY, fontSize, naturalSize } = ctx;
|
|
12669
|
+
const minRadiusY = Math.ceil((naturalSize.height + paddingY * 2) / Math.SQRT2);
|
|
12670
|
+
const minRadiusX = Math.ceil((fontSize + paddingX * 2) / Math.SQRT2);
|
|
12671
|
+
return {
|
|
12672
|
+
width: minRadiusX * 2 * stage.scaleX(),
|
|
12673
|
+
height: minRadiusY * 2 * stage.scaleY()
|
|
12674
|
+
};
|
|
12675
|
+
}
|
|
12676
|
+
/**
|
|
12677
|
+
* Returns the minimum bounding-box size `{ width, height }` (in Konva canvas
|
|
12678
|
+
* units) that the polygon node must have so its label text is fully visible.
|
|
12679
|
+
*
|
|
12680
|
+
* The polygon label sits inside the stored `innerRect` attribute. The minimum
|
|
12681
|
+
* size is back-computed from the label text's natural wrapped height and the
|
|
12682
|
+
* current ratio of `innerRect` to the overall bounding box.
|
|
12683
|
+
*
|
|
12684
|
+
* Returns `{ width: 0, height: 0 }` when the label is empty.
|
|
12685
|
+
*
|
|
12686
|
+
* @param group - The polygon `Konva.Group` returned by `onRender`.
|
|
12687
|
+
*/
|
|
12688
|
+
function computePolygonLabelMinSize(stage, group) {
|
|
12689
|
+
const ctx = extractLabelNodeContext(group);
|
|
12690
|
+
if (!ctx) return {
|
|
12691
|
+
width: 0,
|
|
12692
|
+
height: 0
|
|
12693
|
+
};
|
|
12694
|
+
const { paddingX, paddingY, fontSize, naturalSize } = ctx;
|
|
12695
|
+
const attrs = group.getAttrs();
|
|
12696
|
+
const innerRect = attrs.innerRect;
|
|
12697
|
+
if (!innerRect) return {
|
|
12698
|
+
width: 0,
|
|
12699
|
+
height: 0
|
|
12700
|
+
};
|
|
12701
|
+
return {
|
|
12702
|
+
width: (paddingX * 2 + fontSize) * stage.scaleX(),
|
|
12703
|
+
height: (naturalSize.height + paddingY * 2) * stage.scaleX()
|
|
12704
|
+
};
|
|
12705
|
+
}
|
|
12706
|
+
|
|
11921
12707
|
//#endregion
|
|
11922
12708
|
//#region src/nodes/rectangle/rectangle.ts
|
|
11923
12709
|
var WeaveRectangleNode = class extends WeaveNode {
|
|
11924
12710
|
nodeType = WEAVE_RECTANGLE_NODE_TYPE;
|
|
11925
12711
|
initialize = void 0;
|
|
12712
|
+
_transforming = false;
|
|
12713
|
+
get shapeLabelEditor() {
|
|
12714
|
+
return this._shapeLabelEditor ??= new WeaveShapeLabelEditor(this.instance);
|
|
12715
|
+
}
|
|
11926
12716
|
constructor(params) {
|
|
11927
12717
|
super();
|
|
11928
12718
|
const { config } = params ?? {};
|
|
@@ -11931,13 +12721,15 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
11931
12721
|
onRender(props) {
|
|
11932
12722
|
const rectangle = new Konva.Group({
|
|
11933
12723
|
...props,
|
|
12724
|
+
id: `${props.id}`,
|
|
11934
12725
|
name: "node"
|
|
11935
12726
|
});
|
|
11936
12727
|
const internalRectBg = new Konva.Rect({
|
|
11937
12728
|
...props,
|
|
11938
12729
|
name: void 0,
|
|
11939
|
-
|
|
12730
|
+
nodeType: void 0,
|
|
11940
12731
|
nodeId: props.id,
|
|
12732
|
+
id: `${props.id}-bg`,
|
|
11941
12733
|
x: 0,
|
|
11942
12734
|
y: 0,
|
|
11943
12735
|
width: props.width,
|
|
@@ -11952,6 +12744,7 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
11952
12744
|
const internalRectBorder = new Konva.Rect({
|
|
11953
12745
|
...props,
|
|
11954
12746
|
name: void 0,
|
|
12747
|
+
nodeType: void 0,
|
|
11955
12748
|
id: `${props.id}-border`,
|
|
11956
12749
|
x: props.strokeWidth / 2,
|
|
11957
12750
|
y: props.strokeWidth / 2,
|
|
@@ -11961,9 +12754,19 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
11961
12754
|
strokeWidth: props.strokeWidth || 0,
|
|
11962
12755
|
strokeScaleEnabled: true,
|
|
11963
12756
|
rotation: 0,
|
|
11964
|
-
listening: false
|
|
12757
|
+
listening: false,
|
|
12758
|
+
draggable: false
|
|
11965
12759
|
});
|
|
11966
12760
|
rectangle.add(internalRectBorder);
|
|
12761
|
+
const paddingX = props.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
12762
|
+
const paddingY = props.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
12763
|
+
const labelTextBounds = {
|
|
12764
|
+
x: paddingX,
|
|
12765
|
+
y: paddingY,
|
|
12766
|
+
width: Math.max(1, props.width - paddingX * 2),
|
|
12767
|
+
height: Math.max(1, props.height - paddingY * 2)
|
|
12768
|
+
};
|
|
12769
|
+
this.shapeLabelEditor.renderLabel(rectangle, props, labelTextBounds);
|
|
11967
12770
|
internalRectBorder.moveToTop();
|
|
11968
12771
|
internalRectBg.moveToBottom();
|
|
11969
12772
|
this.setupDefaultNodeAugmentation(rectangle);
|
|
@@ -11972,6 +12775,51 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
11972
12775
|
return defaultTransformerProperties;
|
|
11973
12776
|
};
|
|
11974
12777
|
this.setupDefaultNodeEvents(rectangle);
|
|
12778
|
+
rectangle.on("transformstart", () => {
|
|
12779
|
+
this._transforming = true;
|
|
12780
|
+
});
|
|
12781
|
+
rectangle.on("transform", () => {
|
|
12782
|
+
this.scaleReset(rectangle);
|
|
12783
|
+
this.onUpdate(rectangle, rectangle.getAttrs());
|
|
12784
|
+
});
|
|
12785
|
+
rectangle.on("transformend", () => {
|
|
12786
|
+
this._transforming = false;
|
|
12787
|
+
});
|
|
12788
|
+
rectangle.dblClick = () => {
|
|
12789
|
+
if (this.shapeLabelEditor.isEditing()) return;
|
|
12790
|
+
if (!(this.isSelecting() && this.isNodeSelected(rectangle))) return;
|
|
12791
|
+
const onCommit = (labelText) => {
|
|
12792
|
+
const updatedGroup = this.instance.getStage().findOne(`#${props.id}`);
|
|
12793
|
+
if (!updatedGroup) return;
|
|
12794
|
+
const serialized = this.serialize(updatedGroup);
|
|
12795
|
+
serialized.props.labelText = labelText;
|
|
12796
|
+
this.instance.updateNode(serialized);
|
|
12797
|
+
};
|
|
12798
|
+
const currentAttrs = rectangle.getAttrs();
|
|
12799
|
+
const curPaddingX = currentAttrs.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
12800
|
+
const curPaddingY = currentAttrs.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
12801
|
+
const currentLabelTextBounds = {
|
|
12802
|
+
x: curPaddingX,
|
|
12803
|
+
y: curPaddingY,
|
|
12804
|
+
width: Math.max(1, (currentAttrs.width ?? 0) - curPaddingX * 2),
|
|
12805
|
+
height: Math.max(1, (currentAttrs.height ?? 0) - curPaddingY * 2)
|
|
12806
|
+
};
|
|
12807
|
+
const originalHeight = currentAttrs.height ?? 0;
|
|
12808
|
+
this.shapeLabelEditor.triggerEditMode(rectangle, currentLabelTextBounds, onCommit, (neededShapeHeight) => {
|
|
12809
|
+
const finalHeight = Math.max(neededShapeHeight, originalHeight);
|
|
12810
|
+
const liveAttrs = rectangle.getAttrs();
|
|
12811
|
+
const strokeW = liveAttrs.strokeWidth || 0;
|
|
12812
|
+
const bg = rectangle.findOne(`#${liveAttrs.id}-bg`);
|
|
12813
|
+
const border = rectangle.findOne(`#${liveAttrs.id}-border`);
|
|
12814
|
+
rectangle.setAttrs({ height: finalHeight });
|
|
12815
|
+
bg?.setAttrs({ height: finalHeight });
|
|
12816
|
+
border?.setAttrs({ height: Math.max(0, finalHeight - strokeW) });
|
|
12817
|
+
rectangle.getLayer()?.batchDraw();
|
|
12818
|
+
});
|
|
12819
|
+
};
|
|
12820
|
+
rectangle.getNodeMinSize = () => {
|
|
12821
|
+
return computeRectangleLabelMinSize(this.instance.getStage(), rectangle);
|
|
12822
|
+
};
|
|
11975
12823
|
return rectangle;
|
|
11976
12824
|
}
|
|
11977
12825
|
onUpdate(nodeInstance, nextProps) {
|
|
@@ -12001,6 +12849,7 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
12001
12849
|
internalRectBorder.setAttrs({
|
|
12002
12850
|
...nextProps,
|
|
12003
12851
|
name: void 0,
|
|
12852
|
+
fill: "transparent",
|
|
12004
12853
|
id: `${nextProps.id}-border`,
|
|
12005
12854
|
x: nextProps.strokeWidth / 2,
|
|
12006
12855
|
y: nextProps.strokeWidth / 2,
|
|
@@ -12014,6 +12863,26 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
12014
12863
|
});
|
|
12015
12864
|
internalRectBorder.moveToTop();
|
|
12016
12865
|
}
|
|
12866
|
+
const paddingX = nextProps.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
12867
|
+
const paddingY = nextProps.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
12868
|
+
const labelTextBounds = {
|
|
12869
|
+
x: paddingX,
|
|
12870
|
+
y: paddingY,
|
|
12871
|
+
width: Math.max(1, nextProps.width - paddingX * 2),
|
|
12872
|
+
height: Math.max(1, nextProps.height - paddingY * 2)
|
|
12873
|
+
};
|
|
12874
|
+
this.shapeLabelEditor.updateLabel(rectangle, nextProps, labelTextBounds, (neededShapeHeight) => {
|
|
12875
|
+
nodeInstance.setAttrs({ height: neededShapeHeight });
|
|
12876
|
+
internalRectBg?.setAttrs({ height: neededShapeHeight });
|
|
12877
|
+
internalRectBorder?.setAttrs({ height: neededShapeHeight - nextProps.strokeWidth });
|
|
12878
|
+
if (!this._transforming) this.instance.updateNode(this.serialize(nodeInstance));
|
|
12879
|
+
});
|
|
12880
|
+
const labelNode = rectangle.findOne(`#${labelId(nextProps.id ?? "")}`);
|
|
12881
|
+
if (labelNode) {
|
|
12882
|
+
labelNode.moveToTop();
|
|
12883
|
+
internalRectBg?.moveToBottom();
|
|
12884
|
+
internalRectBorder?.moveToTop();
|
|
12885
|
+
}
|
|
12017
12886
|
const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
12018
12887
|
if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
|
|
12019
12888
|
}
|
|
@@ -12034,7 +12903,8 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
12034
12903
|
strokeScaleEnabled: true,
|
|
12035
12904
|
rotation: 0,
|
|
12036
12905
|
zIndex: 1,
|
|
12037
|
-
children: []
|
|
12906
|
+
children: [],
|
|
12907
|
+
...WEAVE_SHAPE_LABEL_DEFAULTS
|
|
12038
12908
|
}
|
|
12039
12909
|
};
|
|
12040
12910
|
}
|
|
@@ -12047,7 +12917,8 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
12047
12917
|
rotation: props.rotation,
|
|
12048
12918
|
fill: props.fill,
|
|
12049
12919
|
...props.stroke && { stroke: props.stroke },
|
|
12050
|
-
...props.strokeWidth && { strokeWidth: props.strokeWidth }
|
|
12920
|
+
...props.strokeWidth && { strokeWidth: props.strokeWidth },
|
|
12921
|
+
...spreadLabelProps(props)
|
|
12051
12922
|
} });
|
|
12052
12923
|
}
|
|
12053
12924
|
static updateNodeState(prevNodeState, nextProps) {
|
|
@@ -12059,7 +12930,8 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
12059
12930
|
rotation: nextProps.rotation,
|
|
12060
12931
|
fill: nextProps.fill,
|
|
12061
12932
|
...nextProps.stroke && { stroke: nextProps.stroke },
|
|
12062
|
-
...nextProps.strokeWidth && { strokeWidth: nextProps.strokeWidth }
|
|
12933
|
+
...nextProps.strokeWidth && { strokeWidth: nextProps.strokeWidth },
|
|
12934
|
+
...spreadLabelProps(nextProps)
|
|
12063
12935
|
} });
|
|
12064
12936
|
}
|
|
12065
12937
|
static getSchema() {
|
|
@@ -12073,7 +12945,8 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
12073
12945
|
fill: z.string().describe("Fill color of the rectangle in hex format with alpha channel (e.g. #RRGGBBAA)"),
|
|
12074
12946
|
stroke: z.string().describe("Stroke color of the rectangle in hex format with alpha channel (e.g. #RRGGBBAA)"),
|
|
12075
12947
|
strokeWidth: z.number().describe("Stroke width of the rectangle in pixels"),
|
|
12076
|
-
strokeScaleEnabled: z.boolean().describe("Whether the rectangle stroke width should scale when the node is scaled. Defaults to true.")
|
|
12948
|
+
strokeScaleEnabled: z.boolean().describe("Whether the rectangle stroke width should scale when the node is scaled. Defaults to true."),
|
|
12949
|
+
...getShapeLabelSchemaFields()
|
|
12077
12950
|
})
|
|
12078
12951
|
});
|
|
12079
12952
|
return nodeSchema;
|
|
@@ -12089,11 +12962,25 @@ const WEAVE_ELLIPSE_NODE_TYPE = "ellipse";
|
|
|
12089
12962
|
var WeaveEllipseNode = class extends WeaveNode {
|
|
12090
12963
|
nodeType = WEAVE_ELLIPSE_NODE_TYPE;
|
|
12091
12964
|
initialize = void 0;
|
|
12965
|
+
_transforming = false;
|
|
12966
|
+
get shapeLabelEditor() {
|
|
12967
|
+
return this._shapeLabelEditor ??= new WeaveShapeLabelEditor(this.instance);
|
|
12968
|
+
}
|
|
12092
12969
|
constructor(params) {
|
|
12093
12970
|
super();
|
|
12094
12971
|
const { config } = params ?? {};
|
|
12095
12972
|
this.config = { transform: { ...config?.transform } };
|
|
12096
12973
|
}
|
|
12974
|
+
getLabelTextBounds(radiusX, radiusY, paddingX, paddingY) {
|
|
12975
|
+
const inscribedW = radiusX * Math.SQRT2;
|
|
12976
|
+
const inscribedH = radiusY * Math.SQRT2;
|
|
12977
|
+
return {
|
|
12978
|
+
x: radiusX - inscribedW / 2 + paddingX,
|
|
12979
|
+
y: radiusY - inscribedH / 2 + paddingY,
|
|
12980
|
+
width: Math.max(1, inscribedW - paddingX * 2),
|
|
12981
|
+
height: Math.max(1, inscribedH - paddingY * 2)
|
|
12982
|
+
};
|
|
12983
|
+
}
|
|
12097
12984
|
onRender(props) {
|
|
12098
12985
|
const ellipse = new Konva.Group({
|
|
12099
12986
|
...props,
|
|
@@ -12131,6 +13018,10 @@ var WeaveEllipseNode = class extends WeaveNode {
|
|
|
12131
13018
|
listening: false
|
|
12132
13019
|
});
|
|
12133
13020
|
ellipse.add(internalEllipseBorder);
|
|
13021
|
+
const paddingX = props.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
13022
|
+
const paddingY = props.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
13023
|
+
const labelTextBounds = this.getLabelTextBounds(Math.max(1, baseRadiusX), Math.max(1, baseRadiusY), paddingX, paddingY);
|
|
13024
|
+
this.shapeLabelEditor.renderLabel(ellipse, props, labelTextBounds);
|
|
12134
13025
|
internalEllipseBorder.moveToTop();
|
|
12135
13026
|
internalEllipseBg.moveToBottom();
|
|
12136
13027
|
this.setupDefaultNodeAugmentation(ellipse);
|
|
@@ -12169,6 +13060,56 @@ var WeaveEllipseNode = class extends WeaveNode {
|
|
|
12169
13060
|
];
|
|
12170
13061
|
};
|
|
12171
13062
|
this.setupDefaultNodeEvents(ellipse);
|
|
13063
|
+
ellipse.on("transformstart", () => {
|
|
13064
|
+
this._transforming = true;
|
|
13065
|
+
});
|
|
13066
|
+
ellipse.on("transform", () => {
|
|
13067
|
+
this.scaleReset(ellipse);
|
|
13068
|
+
this.onUpdate(ellipse, ellipse.getAttrs());
|
|
13069
|
+
});
|
|
13070
|
+
ellipse.on("transformend", () => {
|
|
13071
|
+
this._transforming = false;
|
|
13072
|
+
});
|
|
13073
|
+
ellipse.dblClick = () => {
|
|
13074
|
+
if (this.shapeLabelEditor.isEditing()) return;
|
|
13075
|
+
if (!(this.isSelecting() && this.isNodeSelected(ellipse))) return;
|
|
13076
|
+
const onCommit = (labelText) => {
|
|
13077
|
+
const updatedGroup = this.instance.getStage().findOne(`#${props.id}`);
|
|
13078
|
+
if (!updatedGroup) return;
|
|
13079
|
+
const serialized = this.serialize(updatedGroup);
|
|
13080
|
+
serialized.props.labelText = labelText;
|
|
13081
|
+
this.instance.updateNode(serialized);
|
|
13082
|
+
};
|
|
13083
|
+
const currentAttrs = ellipse.getAttrs();
|
|
13084
|
+
const curPaddingX = currentAttrs.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
13085
|
+
const curPaddingY = currentAttrs.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
13086
|
+
const currentRadiusX = Math.max(1, currentAttrs.radiusX);
|
|
13087
|
+
const currentRadiusY = Math.max(1, currentAttrs.radiusY);
|
|
13088
|
+
const currentLabelTextBounds = this.getLabelTextBounds(currentRadiusX, currentRadiusY, curPaddingX, curPaddingY);
|
|
13089
|
+
const originalRadiusY = currentRadiusY;
|
|
13090
|
+
const originalNeededHeight = currentLabelTextBounds.height + curPaddingY * 2;
|
|
13091
|
+
this.shapeLabelEditor.triggerEditMode(ellipse, currentLabelTextBounds, onCommit, (neededShapeHeight) => {
|
|
13092
|
+
const newRadiusY = neededShapeHeight <= originalNeededHeight ? originalRadiusY : Math.ceil(neededShapeHeight / Math.SQRT2);
|
|
13093
|
+
const liveAttrs = ellipse.getAttrs();
|
|
13094
|
+
const strokeW = liveAttrs.strokeWidth || 0;
|
|
13095
|
+
const bg = ellipse.findOne(`#${liveAttrs.id}-bg`);
|
|
13096
|
+
const border = ellipse.findOne(`#${liveAttrs.id}-border`);
|
|
13097
|
+
ellipse.setAttrs({ radiusY: newRadiusY });
|
|
13098
|
+
bg?.setAttrs({
|
|
13099
|
+
radiusY: Math.max(1, newRadiusY),
|
|
13100
|
+
y: Math.max(1, newRadiusY)
|
|
13101
|
+
});
|
|
13102
|
+
border?.setAttrs({
|
|
13103
|
+
radiusY: Math.max(1, newRadiusY) - strokeW / 2,
|
|
13104
|
+
y: Math.max(1, newRadiusY)
|
|
13105
|
+
});
|
|
13106
|
+
const newLabelTextBounds = this.getLabelTextBounds(currentRadiusX, newRadiusY, curPaddingX, curPaddingY);
|
|
13107
|
+
this.shapeLabelEditor.repositionTextArea(ellipse, newLabelTextBounds);
|
|
13108
|
+
});
|
|
13109
|
+
};
|
|
13110
|
+
ellipse.getNodeMinSize = () => {
|
|
13111
|
+
return computeEllipseLabelMinSize(this.instance.getStage(), ellipse);
|
|
13112
|
+
};
|
|
12172
13113
|
return ellipse;
|
|
12173
13114
|
}
|
|
12174
13115
|
onUpdate(nodeInstance, nextProps) {
|
|
@@ -12206,12 +13147,34 @@ var WeaveEllipseNode = class extends WeaveNode {
|
|
|
12206
13147
|
radiusY: Math.max(1, baseRadiusY) - (nextProps.strokeWidth || 0) / 2,
|
|
12207
13148
|
stroke: nextProps.stroke || "transparent",
|
|
12208
13149
|
strokeWidth: nextProps.strokeWidth || 0,
|
|
13150
|
+
fill: "transparent",
|
|
12209
13151
|
strokeScaleEnabled: true,
|
|
12210
13152
|
listening: false,
|
|
12211
13153
|
rotation: 0
|
|
12212
13154
|
});
|
|
12213
13155
|
internalEllipseBorder.moveToTop();
|
|
12214
13156
|
}
|
|
13157
|
+
const paddingX = nextProps.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
13158
|
+
const paddingY = nextProps.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
13159
|
+
const labelTextBounds = this.getLabelTextBounds(Math.max(1, baseRadiusX), Math.max(1, baseRadiusY), paddingX, paddingY);
|
|
13160
|
+
this.shapeLabelEditor.updateLabel(ellipse, nextProps, labelTextBounds, (neededHeight) => {
|
|
13161
|
+
const newRadiusY = Math.ceil(neededHeight / Math.SQRT2);
|
|
13162
|
+
nodeInstance.setAttrs({ radiusY: newRadiusY });
|
|
13163
|
+
internalEllipseBg?.setAttrs({
|
|
13164
|
+
radiusY: Math.max(1, newRadiusY),
|
|
13165
|
+
y: Math.max(1, newRadiusY)
|
|
13166
|
+
});
|
|
13167
|
+
internalEllipseBorder?.setAttrs({
|
|
13168
|
+
radiusY: Math.max(1, newRadiusY) - (nextProps.strokeWidth || 0) / 2,
|
|
13169
|
+
y: Math.max(1, newRadiusY)
|
|
13170
|
+
});
|
|
13171
|
+
if (!this._transforming) this.instance.updateNode(this.serialize(nodeInstance));
|
|
13172
|
+
});
|
|
13173
|
+
const labelNode = ellipse.findOne(`#${labelId(nextProps.id)}`);
|
|
13174
|
+
if (labelNode) {
|
|
13175
|
+
labelNode.moveToTop();
|
|
13176
|
+
internalEllipseBorder?.moveToTop();
|
|
13177
|
+
}
|
|
12215
13178
|
const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
12216
13179
|
if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
|
|
12217
13180
|
}
|
|
@@ -12254,7 +13217,8 @@ var WeaveEllipseNode = class extends WeaveNode {
|
|
|
12254
13217
|
strokeScaleEnabled: true,
|
|
12255
13218
|
rotation: 0,
|
|
12256
13219
|
zIndex: 1,
|
|
12257
|
-
children: []
|
|
13220
|
+
children: [],
|
|
13221
|
+
...WEAVE_SHAPE_LABEL_DEFAULTS
|
|
12258
13222
|
}
|
|
12259
13223
|
};
|
|
12260
13224
|
}
|
|
@@ -12267,7 +13231,8 @@ var WeaveEllipseNode = class extends WeaveNode {
|
|
|
12267
13231
|
rotation: props.rotation,
|
|
12268
13232
|
fill: props.fill,
|
|
12269
13233
|
...props.stroke && { stroke: props.stroke },
|
|
12270
|
-
...props.strokeWidth && { strokeWidth: props.strokeWidth }
|
|
13234
|
+
...props.strokeWidth && { strokeWidth: props.strokeWidth },
|
|
13235
|
+
...spreadLabelProps(props)
|
|
12271
13236
|
} });
|
|
12272
13237
|
}
|
|
12273
13238
|
static updateNodeState(prevNodeState, nextProps) {
|
|
@@ -12279,7 +13244,8 @@ var WeaveEllipseNode = class extends WeaveNode {
|
|
|
12279
13244
|
rotation: nextProps.rotation,
|
|
12280
13245
|
fill: nextProps.fill,
|
|
12281
13246
|
...nextProps.stroke && { stroke: nextProps.stroke },
|
|
12282
|
-
...nextProps.strokeWidth && { strokeWidth: nextProps.strokeWidth }
|
|
13247
|
+
...nextProps.strokeWidth && { strokeWidth: nextProps.strokeWidth },
|
|
13248
|
+
...spreadLabelProps(nextProps)
|
|
12283
13249
|
} });
|
|
12284
13250
|
}
|
|
12285
13251
|
static getSchema() {
|
|
@@ -12293,7 +13259,8 @@ var WeaveEllipseNode = class extends WeaveNode {
|
|
|
12293
13259
|
fill: z.string().describe("Fill color of the ellipse in hex format with alpha channel (e.g. #RRGGBBAA)"),
|
|
12294
13260
|
stroke: z.string().describe("Stroke color of the ellipse in hex format with alpha channel (e.g. #RRGGBBAA)"),
|
|
12295
13261
|
strokeWidth: z.number().describe("Stroke width of the ellipse in pixels"),
|
|
12296
|
-
strokeScaleEnabled: z.boolean().describe("Whether the ellipse stroke width should scale when the node is scaled. Defaults to true.")
|
|
13262
|
+
strokeScaleEnabled: z.boolean().describe("Whether the ellipse stroke width should scale when the node is scaled. Defaults to true."),
|
|
13263
|
+
...getShapeLabelSchemaFields()
|
|
12297
13264
|
})
|
|
12298
13265
|
});
|
|
12299
13266
|
return nodeSchema;
|
|
@@ -15060,6 +16027,7 @@ var WeaveImageNode = class extends WeaveNode {
|
|
|
15060
16027
|
x: 1,
|
|
15061
16028
|
y: 1
|
|
15062
16029
|
});
|
|
16030
|
+
this.updateImageCrop(node);
|
|
15063
16031
|
}
|
|
15064
16032
|
getIsAsync() {
|
|
15065
16033
|
return true;
|
|
@@ -15571,127 +16539,975 @@ var WeaveRegularPolygonNode = class extends WeaveNode {
|
|
|
15571
16539
|
rotation: 0,
|
|
15572
16540
|
listening: false
|
|
15573
16541
|
});
|
|
15574
|
-
const internalRPBorderBox = internalRPBorder.getClientRect({ relativeTo: regularPolygon });
|
|
15575
|
-
internalRPBorder.x(internalRPBorder.x() - internalRPBorderBox.x);
|
|
15576
|
-
internalRPBorder.y(internalRPBorder.y() - internalRPBorderBox.y);
|
|
15577
|
-
regularPolygon.add(internalRPBorder);
|
|
15578
|
-
internalRPBorder.moveToTop();
|
|
15579
|
-
internalRPBg.moveToBottom();
|
|
15580
|
-
this.setupDefaultNodeAugmentation(regularPolygon);
|
|
16542
|
+
const internalRPBorderBox = internalRPBorder.getClientRect({ relativeTo: regularPolygon });
|
|
16543
|
+
internalRPBorder.x(internalRPBorder.x() - internalRPBorderBox.x);
|
|
16544
|
+
internalRPBorder.y(internalRPBorder.y() - internalRPBorderBox.y);
|
|
16545
|
+
regularPolygon.add(internalRPBorder);
|
|
16546
|
+
internalRPBorder.moveToTop();
|
|
16547
|
+
internalRPBg.moveToBottom();
|
|
16548
|
+
this.setupDefaultNodeAugmentation(regularPolygon);
|
|
16549
|
+
const defaultTransformerProperties = this.defaultGetTransformerProperties(this.config.transform);
|
|
16550
|
+
regularPolygon.getTransformerProperties = function() {
|
|
16551
|
+
return {
|
|
16552
|
+
...defaultTransformerProperties,
|
|
16553
|
+
enabledAnchors: [
|
|
16554
|
+
"top-left",
|
|
16555
|
+
"top-right",
|
|
16556
|
+
"bottom-left",
|
|
16557
|
+
"bottom-right"
|
|
16558
|
+
],
|
|
16559
|
+
keepRatio: true
|
|
16560
|
+
};
|
|
16561
|
+
};
|
|
16562
|
+
regularPolygon.allowedAnchors = function() {
|
|
16563
|
+
return [
|
|
16564
|
+
"top-left",
|
|
16565
|
+
"top-right",
|
|
16566
|
+
"bottom-left",
|
|
16567
|
+
"bottom-right"
|
|
16568
|
+
];
|
|
16569
|
+
};
|
|
16570
|
+
this.setupDefaultNodeEvents(regularPolygon);
|
|
16571
|
+
return regularPolygon;
|
|
16572
|
+
}
|
|
16573
|
+
onUpdate(nodeInstance, nextProps) {
|
|
16574
|
+
nodeInstance.setAttrs({ ...nextProps });
|
|
16575
|
+
const sides = nodeInstance.getAttr("sides");
|
|
16576
|
+
const radius = nodeInstance.getAttr("radius");
|
|
16577
|
+
const regularPolygon = nodeInstance;
|
|
16578
|
+
const internalRPBg = regularPolygon.findOne(`#${nextProps.id}-bg`);
|
|
16579
|
+
const internalRPBorder = regularPolygon.findOne(`#${nextProps.id}-border`);
|
|
16580
|
+
if (internalRPBg) {
|
|
16581
|
+
internalRPBg.setAttrs({
|
|
16582
|
+
...nextProps,
|
|
16583
|
+
name: void 0,
|
|
16584
|
+
id: `${nextProps.id}-bg`,
|
|
16585
|
+
nodeId: nextProps.id,
|
|
16586
|
+
x: radius,
|
|
16587
|
+
y: radius,
|
|
16588
|
+
sides,
|
|
16589
|
+
radius,
|
|
16590
|
+
fill: nextProps.fill || "transparent",
|
|
16591
|
+
strokeWidth: 0,
|
|
16592
|
+
strokeScaleEnabled: true,
|
|
16593
|
+
rotation: 0
|
|
16594
|
+
});
|
|
16595
|
+
const internalRPBgBox = internalRPBg.getClientRect({ relativeTo: regularPolygon });
|
|
16596
|
+
internalRPBg.x(internalRPBg.x() - internalRPBgBox.x);
|
|
16597
|
+
internalRPBg.y(internalRPBg.y() - internalRPBgBox.y);
|
|
16598
|
+
internalRPBg.moveToBottom();
|
|
16599
|
+
}
|
|
16600
|
+
if (internalRPBorder) {
|
|
16601
|
+
internalRPBorder.setAttrs({
|
|
16602
|
+
...nextProps,
|
|
16603
|
+
name: void 0,
|
|
16604
|
+
id: `${nextProps.id}-border`,
|
|
16605
|
+
x: radius,
|
|
16606
|
+
y: radius,
|
|
16607
|
+
sides,
|
|
16608
|
+
radius: radius - (nextProps.strokeWidth || 0) / 2,
|
|
16609
|
+
stroke: nextProps.stroke || "transparent",
|
|
16610
|
+
strokeWidth: nextProps.strokeWidth || 0,
|
|
16611
|
+
strokeScaleEnabled: true,
|
|
16612
|
+
fill: "transparent",
|
|
16613
|
+
listening: false,
|
|
16614
|
+
rotation: 0
|
|
16615
|
+
});
|
|
16616
|
+
const internalRPBorderBox = internalRPBorder.getClientRect({ relativeTo: regularPolygon });
|
|
16617
|
+
internalRPBorder.x(internalRPBorder.x() - internalRPBorderBox.x);
|
|
16618
|
+
internalRPBorder.y(internalRPBorder.y() - internalRPBorderBox.y);
|
|
16619
|
+
internalRPBorder.moveToTop();
|
|
16620
|
+
}
|
|
16621
|
+
const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
16622
|
+
if (nodesSelectionPlugin) {
|
|
16623
|
+
const actualSelectedNodes = nodesSelectionPlugin.getSelectedNodes();
|
|
16624
|
+
nodesSelectionPlugin.setSelectedNodes(actualSelectedNodes);
|
|
16625
|
+
nodesSelectionPlugin.getTransformer().forceUpdate();
|
|
16626
|
+
}
|
|
16627
|
+
}
|
|
16628
|
+
scaleReset(node) {
|
|
16629
|
+
const absTransform = node.getAbsoluteTransform().copy();
|
|
16630
|
+
const radius = node.getAttr("radius");
|
|
16631
|
+
node.setAttrs({ radius: radius * node.scaleX() });
|
|
16632
|
+
node.scaleX(1);
|
|
16633
|
+
node.scaleY(1);
|
|
16634
|
+
const newTransform = node.getAbsoluteTransform();
|
|
16635
|
+
const dx = absTransform.m[4] - newTransform.m[4];
|
|
16636
|
+
const dy = absTransform.m[5] - newTransform.m[5];
|
|
16637
|
+
node.x(node.x() + dx);
|
|
16638
|
+
node.y(node.y() + dy);
|
|
16639
|
+
}
|
|
16640
|
+
realOffset(element) {
|
|
16641
|
+
return {
|
|
16642
|
+
x: element.props.radius,
|
|
16643
|
+
y: element.props.radius
|
|
16644
|
+
};
|
|
16645
|
+
}
|
|
16646
|
+
static defaultState(nodeId) {
|
|
16647
|
+
return {
|
|
16648
|
+
...super.defaultState(nodeId),
|
|
16649
|
+
type: WEAVE_REGULAR_POLYGON_NODE_TYPE,
|
|
16650
|
+
props: {
|
|
16651
|
+
...super.defaultState(nodeId).props,
|
|
16652
|
+
nodeType: WEAVE_REGULAR_POLYGON_NODE_TYPE,
|
|
16653
|
+
x: 0,
|
|
16654
|
+
y: 0,
|
|
16655
|
+
sides: 5,
|
|
16656
|
+
radius: 100,
|
|
16657
|
+
stroke: "#000000",
|
|
16658
|
+
fill: "#FFFFFF",
|
|
16659
|
+
strokeWidth: 1,
|
|
16660
|
+
strokeScaleEnabled: true,
|
|
16661
|
+
rotation: 0,
|
|
16662
|
+
zIndex: 1,
|
|
16663
|
+
children: []
|
|
16664
|
+
}
|
|
16665
|
+
};
|
|
16666
|
+
}
|
|
16667
|
+
static addNodeState(defaultNodeState, props) {
|
|
16668
|
+
return mergeExceptArrays(defaultNodeState, { props: {
|
|
16669
|
+
x: props.x,
|
|
16670
|
+
y: props.y,
|
|
16671
|
+
sides: props.sides,
|
|
16672
|
+
radius: props.radius,
|
|
16673
|
+
rotation: props.rotation,
|
|
16674
|
+
fill: props.fill,
|
|
16675
|
+
...props.stroke && { stroke: props.stroke },
|
|
16676
|
+
...props.strokeWidth && { strokeWidth: props.strokeWidth }
|
|
16677
|
+
} });
|
|
16678
|
+
}
|
|
16679
|
+
static updateNodeState(prevNodeState, nextProps) {
|
|
16680
|
+
return mergeExceptArrays(prevNodeState, { props: {
|
|
16681
|
+
x: nextProps.x,
|
|
16682
|
+
y: nextProps.y,
|
|
16683
|
+
sides: nextProps.sides,
|
|
16684
|
+
radius: nextProps.radius,
|
|
16685
|
+
rotation: nextProps.rotation,
|
|
16686
|
+
fill: nextProps.fill,
|
|
16687
|
+
...nextProps.stroke && { stroke: nextProps.stroke },
|
|
16688
|
+
...nextProps.strokeWidth && { strokeWidth: nextProps.strokeWidth }
|
|
16689
|
+
} });
|
|
16690
|
+
}
|
|
16691
|
+
static getSchema() {
|
|
16692
|
+
const baseSchema = super.getSchema();
|
|
16693
|
+
const nodeSchema = baseSchema.extend({
|
|
16694
|
+
type: z.literal(WEAVE_REGULAR_POLYGON_NODE_TYPE).describe(`Type of the node, for a regular polygon node it will always be "${WEAVE_REGULAR_POLYGON_NODE_TYPE}"`),
|
|
16695
|
+
props: baseSchema.shape.props.extend({
|
|
16696
|
+
nodeType: z.literal(WEAVE_REGULAR_POLYGON_NODE_TYPE).describe(`Type of the node, for a regular polygon node it will always be "${WEAVE_REGULAR_POLYGON_NODE_TYPE}"`),
|
|
16697
|
+
sides: z.number().describe("Number of sides of the regular polygon, must be 3 or more"),
|
|
16698
|
+
radius: z.number().describe("Radius of the regular polygon in pixels, distance from the center to any vertex"),
|
|
16699
|
+
fill: z.string().describe("Fill color of the regular polygon in hex format with alpha channel (e.g. #RRGGBBAA)"),
|
|
16700
|
+
stroke: z.string().describe("Stroke color of the regular polygon in hex format with alpha channel (e.g. #RRGGBBAA)"),
|
|
16701
|
+
strokeWidth: z.number().describe("Stroke width of the regular polygon in pixels"),
|
|
16702
|
+
strokeScaleEnabled: z.boolean().describe("Whether the regular polygon stroke width should scale when the node is scaled. Defaults to true.")
|
|
16703
|
+
})
|
|
16704
|
+
});
|
|
16705
|
+
return nodeSchema;
|
|
16706
|
+
}
|
|
16707
|
+
};
|
|
16708
|
+
|
|
16709
|
+
//#endregion
|
|
16710
|
+
//#region src/nodes/polygon/constants.ts
|
|
16711
|
+
const WEAVE_POLYGON_NODE_TYPE = "polygon";
|
|
16712
|
+
|
|
16713
|
+
//#endregion
|
|
16714
|
+
//#region src/nodes/polygon/presets.ts
|
|
16715
|
+
const WEAVE_POLYGON_PRESETS = {
|
|
16716
|
+
triangle: {
|
|
16717
|
+
label: "Triangle",
|
|
16718
|
+
sides: 3,
|
|
16719
|
+
defaultWidth: 100,
|
|
16720
|
+
defaultHeight: 100,
|
|
16721
|
+
normalizedPoints: [
|
|
16722
|
+
{
|
|
16723
|
+
x: .5,
|
|
16724
|
+
y: 0
|
|
16725
|
+
},
|
|
16726
|
+
{
|
|
16727
|
+
x: .933013,
|
|
16728
|
+
y: .75
|
|
16729
|
+
},
|
|
16730
|
+
{
|
|
16731
|
+
x: .066987,
|
|
16732
|
+
y: .75
|
|
16733
|
+
}
|
|
16734
|
+
],
|
|
16735
|
+
normalizedInnerRect: {
|
|
16736
|
+
tl: {
|
|
16737
|
+
x: .283494,
|
|
16738
|
+
y: .375
|
|
16739
|
+
},
|
|
16740
|
+
tr: {
|
|
16741
|
+
x: .716506,
|
|
16742
|
+
y: .375
|
|
16743
|
+
},
|
|
16744
|
+
bl: {
|
|
16745
|
+
x: .283494,
|
|
16746
|
+
y: .75
|
|
16747
|
+
},
|
|
16748
|
+
br: {
|
|
16749
|
+
x: .716506,
|
|
16750
|
+
y: .75
|
|
16751
|
+
}
|
|
16752
|
+
}
|
|
16753
|
+
},
|
|
16754
|
+
diamond: {
|
|
16755
|
+
label: "Diamond",
|
|
16756
|
+
sides: 4,
|
|
16757
|
+
defaultWidth: 100,
|
|
16758
|
+
defaultHeight: 100,
|
|
16759
|
+
normalizedPoints: [
|
|
16760
|
+
{
|
|
16761
|
+
x: .5,
|
|
16762
|
+
y: 0
|
|
16763
|
+
},
|
|
16764
|
+
{
|
|
16765
|
+
x: 1,
|
|
16766
|
+
y: .5
|
|
16767
|
+
},
|
|
16768
|
+
{
|
|
16769
|
+
x: .5,
|
|
16770
|
+
y: 1
|
|
16771
|
+
},
|
|
16772
|
+
{
|
|
16773
|
+
x: 0,
|
|
16774
|
+
y: .5
|
|
16775
|
+
}
|
|
16776
|
+
],
|
|
16777
|
+
normalizedInnerRect: {
|
|
16778
|
+
tl: {
|
|
16779
|
+
x: .25,
|
|
16780
|
+
y: .25
|
|
16781
|
+
},
|
|
16782
|
+
tr: {
|
|
16783
|
+
x: .75,
|
|
16784
|
+
y: .25
|
|
16785
|
+
},
|
|
16786
|
+
bl: {
|
|
16787
|
+
x: .25,
|
|
16788
|
+
y: .75
|
|
16789
|
+
},
|
|
16790
|
+
br: {
|
|
16791
|
+
x: .75,
|
|
16792
|
+
y: .75
|
|
16793
|
+
}
|
|
16794
|
+
}
|
|
16795
|
+
},
|
|
16796
|
+
pentagon: {
|
|
16797
|
+
label: "Pentagon",
|
|
16798
|
+
sides: 5,
|
|
16799
|
+
defaultWidth: 100,
|
|
16800
|
+
defaultHeight: 100,
|
|
16801
|
+
normalizedPoints: [
|
|
16802
|
+
{
|
|
16803
|
+
x: .5,
|
|
16804
|
+
y: 0
|
|
16805
|
+
},
|
|
16806
|
+
{
|
|
16807
|
+
x: .975528,
|
|
16808
|
+
y: .345492
|
|
16809
|
+
},
|
|
16810
|
+
{
|
|
16811
|
+
x: .793893,
|
|
16812
|
+
y: .904508
|
|
16813
|
+
},
|
|
16814
|
+
{
|
|
16815
|
+
x: .206107,
|
|
16816
|
+
y: .904508
|
|
16817
|
+
},
|
|
16818
|
+
{
|
|
16819
|
+
x: .024472,
|
|
16820
|
+
y: .345492
|
|
16821
|
+
}
|
|
16822
|
+
],
|
|
16823
|
+
normalizedInnerRect: {
|
|
16824
|
+
tl: {
|
|
16825
|
+
x: .132634,
|
|
16826
|
+
y: .316578
|
|
16827
|
+
},
|
|
16828
|
+
tr: {
|
|
16829
|
+
x: .867366,
|
|
16830
|
+
y: .316578
|
|
16831
|
+
},
|
|
16832
|
+
bl: {
|
|
16833
|
+
x: .132634,
|
|
16834
|
+
y: .678381
|
|
16835
|
+
},
|
|
16836
|
+
br: {
|
|
16837
|
+
x: .867366,
|
|
16838
|
+
y: .678381
|
|
16839
|
+
}
|
|
16840
|
+
}
|
|
16841
|
+
},
|
|
16842
|
+
hexagon: {
|
|
16843
|
+
label: "Hexagon",
|
|
16844
|
+
sides: 6,
|
|
16845
|
+
defaultWidth: 100,
|
|
16846
|
+
defaultHeight: 100,
|
|
16847
|
+
normalizedPoints: [
|
|
16848
|
+
{
|
|
16849
|
+
x: .5,
|
|
16850
|
+
y: 0
|
|
16851
|
+
},
|
|
16852
|
+
{
|
|
16853
|
+
x: .933013,
|
|
16854
|
+
y: .25
|
|
16855
|
+
},
|
|
16856
|
+
{
|
|
16857
|
+
x: .933013,
|
|
16858
|
+
y: .75
|
|
16859
|
+
},
|
|
16860
|
+
{
|
|
16861
|
+
x: .5,
|
|
16862
|
+
y: 1
|
|
16863
|
+
},
|
|
16864
|
+
{
|
|
16865
|
+
x: .066987,
|
|
16866
|
+
y: .75
|
|
16867
|
+
},
|
|
16868
|
+
{
|
|
16869
|
+
x: .066987,
|
|
16870
|
+
y: .25
|
|
16871
|
+
}
|
|
16872
|
+
],
|
|
16873
|
+
normalizedInnerRect: {
|
|
16874
|
+
tl: {
|
|
16875
|
+
x: .066987,
|
|
16876
|
+
y: .25
|
|
16877
|
+
},
|
|
16878
|
+
tr: {
|
|
16879
|
+
x: .933013,
|
|
16880
|
+
y: .25
|
|
16881
|
+
},
|
|
16882
|
+
bl: {
|
|
16883
|
+
x: .066987,
|
|
16884
|
+
y: .75
|
|
16885
|
+
},
|
|
16886
|
+
br: {
|
|
16887
|
+
x: .933013,
|
|
16888
|
+
y: .75
|
|
16889
|
+
}
|
|
16890
|
+
}
|
|
16891
|
+
},
|
|
16892
|
+
octagon: {
|
|
16893
|
+
label: "Octagon",
|
|
16894
|
+
sides: 8,
|
|
16895
|
+
defaultWidth: 100,
|
|
16896
|
+
defaultHeight: 100,
|
|
16897
|
+
normalizedPoints: [
|
|
16898
|
+
{
|
|
16899
|
+
x: .5,
|
|
16900
|
+
y: 0
|
|
16901
|
+
},
|
|
16902
|
+
{
|
|
16903
|
+
x: .853553,
|
|
16904
|
+
y: .146447
|
|
16905
|
+
},
|
|
16906
|
+
{
|
|
16907
|
+
x: 1,
|
|
16908
|
+
y: .5
|
|
16909
|
+
},
|
|
16910
|
+
{
|
|
16911
|
+
x: .853553,
|
|
16912
|
+
y: .853553
|
|
16913
|
+
},
|
|
16914
|
+
{
|
|
16915
|
+
x: .5,
|
|
16916
|
+
y: 1
|
|
16917
|
+
},
|
|
16918
|
+
{
|
|
16919
|
+
x: .146447,
|
|
16920
|
+
y: .853553
|
|
16921
|
+
},
|
|
16922
|
+
{
|
|
16923
|
+
x: 0,
|
|
16924
|
+
y: .5
|
|
16925
|
+
},
|
|
16926
|
+
{
|
|
16927
|
+
x: .146447,
|
|
16928
|
+
y: .146447
|
|
16929
|
+
}
|
|
16930
|
+
],
|
|
16931
|
+
normalizedInnerRect: {
|
|
16932
|
+
tl: {
|
|
16933
|
+
x: .25,
|
|
16934
|
+
y: .25
|
|
16935
|
+
},
|
|
16936
|
+
tr: {
|
|
16937
|
+
x: .75,
|
|
16938
|
+
y: .25
|
|
16939
|
+
},
|
|
16940
|
+
bl: {
|
|
16941
|
+
x: .25,
|
|
16942
|
+
y: .75
|
|
16943
|
+
},
|
|
16944
|
+
br: {
|
|
16945
|
+
x: .75,
|
|
16946
|
+
y: .75
|
|
16947
|
+
}
|
|
16948
|
+
}
|
|
16949
|
+
},
|
|
16950
|
+
decagon: {
|
|
16951
|
+
label: "Decagon",
|
|
16952
|
+
sides: 10,
|
|
16953
|
+
defaultWidth: 100,
|
|
16954
|
+
defaultHeight: 100,
|
|
16955
|
+
normalizedPoints: [
|
|
16956
|
+
{
|
|
16957
|
+
x: .5,
|
|
16958
|
+
y: 0
|
|
16959
|
+
},
|
|
16960
|
+
{
|
|
16961
|
+
x: .793893,
|
|
16962
|
+
y: .095492
|
|
16963
|
+
},
|
|
16964
|
+
{
|
|
16965
|
+
x: .975528,
|
|
16966
|
+
y: .345492
|
|
16967
|
+
},
|
|
16968
|
+
{
|
|
16969
|
+
x: .975528,
|
|
16970
|
+
y: .654508
|
|
16971
|
+
},
|
|
16972
|
+
{
|
|
16973
|
+
x: .793893,
|
|
16974
|
+
y: .904508
|
|
16975
|
+
},
|
|
16976
|
+
{
|
|
16977
|
+
x: .5,
|
|
16978
|
+
y: 1
|
|
16979
|
+
},
|
|
16980
|
+
{
|
|
16981
|
+
x: .206107,
|
|
16982
|
+
y: .904508
|
|
16983
|
+
},
|
|
16984
|
+
{
|
|
16985
|
+
x: .024472,
|
|
16986
|
+
y: .654508
|
|
16987
|
+
},
|
|
16988
|
+
{
|
|
16989
|
+
x: .024472,
|
|
16990
|
+
y: .345492
|
|
16991
|
+
},
|
|
16992
|
+
{
|
|
16993
|
+
x: .206107,
|
|
16994
|
+
y: .095492
|
|
16995
|
+
}
|
|
16996
|
+
],
|
|
16997
|
+
normalizedInnerRect: {
|
|
16998
|
+
tl: {
|
|
16999
|
+
x: .093851,
|
|
17000
|
+
y: .35
|
|
17001
|
+
},
|
|
17002
|
+
tr: {
|
|
17003
|
+
x: .906149,
|
|
17004
|
+
y: .35
|
|
17005
|
+
},
|
|
17006
|
+
bl: {
|
|
17007
|
+
x: .093851,
|
|
17008
|
+
y: .75
|
|
17009
|
+
},
|
|
17010
|
+
br: {
|
|
17011
|
+
x: .906149,
|
|
17012
|
+
y: .75
|
|
17013
|
+
}
|
|
17014
|
+
}
|
|
17015
|
+
}
|
|
17016
|
+
};
|
|
17017
|
+
/**
|
|
17018
|
+
* Scales a preset's normalized points and inner rect to actual pixel dimensions.
|
|
17019
|
+
*
|
|
17020
|
+
* Points are normalized so that minX = 0 and minY = 0 in the resulting pixel
|
|
17021
|
+
* space. This ensures the polygon group's position corresponds exactly to the
|
|
17022
|
+
* visual top-left of the polygon, which is required for the snapping system to
|
|
17023
|
+
* work correctly (it assumes nodeBox.x === node.x()).
|
|
17024
|
+
*/
|
|
17025
|
+
function instantiatePreset(def, width, height) {
|
|
17026
|
+
const rawPoints = def.normalizedPoints.map((p) => ({
|
|
17027
|
+
x: p.x * width,
|
|
17028
|
+
y: p.y * height
|
|
17029
|
+
}));
|
|
17030
|
+
const minX = Math.min(...rawPoints.map((p) => p.x));
|
|
17031
|
+
const minY = Math.min(...rawPoints.map((p) => p.y));
|
|
17032
|
+
const points = rawPoints.map((p) => ({
|
|
17033
|
+
x: p.x - minX,
|
|
17034
|
+
y: p.y - minY
|
|
17035
|
+
}));
|
|
17036
|
+
const ir = def.normalizedInnerRect;
|
|
17037
|
+
const innerRect = {
|
|
17038
|
+
tl: {
|
|
17039
|
+
x: ir.tl.x * width - minX,
|
|
17040
|
+
y: ir.tl.y * height - minY
|
|
17041
|
+
},
|
|
17042
|
+
tr: {
|
|
17043
|
+
x: ir.tr.x * width - minX,
|
|
17044
|
+
y: ir.tr.y * height - minY
|
|
17045
|
+
},
|
|
17046
|
+
bl: {
|
|
17047
|
+
x: ir.bl.x * width - minX,
|
|
17048
|
+
y: ir.bl.y * height - minY
|
|
17049
|
+
},
|
|
17050
|
+
br: {
|
|
17051
|
+
x: ir.br.x * width - minX,
|
|
17052
|
+
y: ir.br.y * height - minY
|
|
17053
|
+
}
|
|
17054
|
+
};
|
|
17055
|
+
const visualWidth = Math.max(...points.map((p) => p.x));
|
|
17056
|
+
const visualHeight = Math.max(...points.map((p) => p.y));
|
|
17057
|
+
return {
|
|
17058
|
+
points,
|
|
17059
|
+
innerRect,
|
|
17060
|
+
width: visualWidth,
|
|
17061
|
+
height: visualHeight
|
|
17062
|
+
};
|
|
17063
|
+
}
|
|
17064
|
+
|
|
17065
|
+
//#endregion
|
|
17066
|
+
//#region src/nodes/polygon/polygon.ts
|
|
17067
|
+
function computePolygonBounds(points) {
|
|
17068
|
+
if (!points.length) return {
|
|
17069
|
+
width: 0,
|
|
17070
|
+
height: 0
|
|
17071
|
+
};
|
|
17072
|
+
const maxX = Math.max(...points.map((p) => p.x));
|
|
17073
|
+
const maxY = Math.max(...points.map((p) => p.y));
|
|
17074
|
+
return {
|
|
17075
|
+
width: Math.max(1, maxX),
|
|
17076
|
+
height: Math.max(1, maxY)
|
|
17077
|
+
};
|
|
17078
|
+
}
|
|
17079
|
+
function polygonSelfRect() {
|
|
17080
|
+
const pts = this.getAttr("points");
|
|
17081
|
+
if (!pts?.length) return {
|
|
17082
|
+
x: 0,
|
|
17083
|
+
y: 0,
|
|
17084
|
+
width: 0,
|
|
17085
|
+
height: 0
|
|
17086
|
+
};
|
|
17087
|
+
const minX = Math.min(...pts.map((p) => p.x));
|
|
17088
|
+
const minY = Math.min(...pts.map((p) => p.y));
|
|
17089
|
+
const maxX = Math.max(...pts.map((p) => p.x));
|
|
17090
|
+
const maxY = Math.max(...pts.map((p) => p.y));
|
|
17091
|
+
return {
|
|
17092
|
+
x: minX,
|
|
17093
|
+
y: minY,
|
|
17094
|
+
width: maxX - minX,
|
|
17095
|
+
height: maxY - minY
|
|
17096
|
+
};
|
|
17097
|
+
}
|
|
17098
|
+
function getPolygonLabelTextBounds(innerRect, paddingX, paddingY) {
|
|
17099
|
+
return {
|
|
17100
|
+
x: innerRect.tl.x + paddingX,
|
|
17101
|
+
y: innerRect.tl.y + paddingY,
|
|
17102
|
+
width: Math.max(1, innerRect.tr.x - innerRect.tl.x - paddingX * 2),
|
|
17103
|
+
height: Math.max(1, innerRect.bl.y - innerRect.tl.y - paddingY * 2)
|
|
17104
|
+
};
|
|
17105
|
+
}
|
|
17106
|
+
function sceneFunc(context, shape) {
|
|
17107
|
+
const pts = shape.getAttr("points");
|
|
17108
|
+
if (!pts || pts.length < 3) return;
|
|
17109
|
+
context.beginPath();
|
|
17110
|
+
context.moveTo(pts[0].x, pts[0].y);
|
|
17111
|
+
for (let i = 1; i < pts.length; i++) context.lineTo(pts[i].x, pts[i].y);
|
|
17112
|
+
context.closePath();
|
|
17113
|
+
context.fillStrokeShape(shape);
|
|
17114
|
+
}
|
|
17115
|
+
/**
|
|
17116
|
+
* Draws an "inside" stroke for the border shape.
|
|
17117
|
+
* Clips to the polygon interior then draws 2× the stroke width so the outer
|
|
17118
|
+
* half is clipped away — resulting in a stroke of correct visual width that
|
|
17119
|
+
* stays entirely inside the polygon boundary.
|
|
17120
|
+
* strokeWidth is intentionally 0 on the shape (so getClientRect doesn't
|
|
17121
|
+
* expand the bounding box); the real width is stored in `innerStrokeWidth`.
|
|
17122
|
+
*/
|
|
17123
|
+
function borderSceneFunc(context, shape) {
|
|
17124
|
+
const pts = shape.getAttr("points");
|
|
17125
|
+
if (!pts || pts.length < 3) return;
|
|
17126
|
+
const sw = shape.getAttr("innerStrokeWidth");
|
|
17127
|
+
if (!sw) return;
|
|
17128
|
+
const stroke = shape.stroke();
|
|
17129
|
+
if (!stroke || stroke === "transparent") return;
|
|
17130
|
+
const ctx = context._context;
|
|
17131
|
+
const drawPath = () => {
|
|
17132
|
+
ctx.beginPath();
|
|
17133
|
+
ctx.moveTo(pts[0].x, pts[0].y);
|
|
17134
|
+
for (let i = 1; i < pts.length; i++) ctx.lineTo(pts[i].x, pts[i].y);
|
|
17135
|
+
ctx.closePath();
|
|
17136
|
+
};
|
|
17137
|
+
ctx.save();
|
|
17138
|
+
drawPath();
|
|
17139
|
+
ctx.clip();
|
|
17140
|
+
drawPath();
|
|
17141
|
+
ctx.lineWidth = sw * 2;
|
|
17142
|
+
ctx.strokeStyle = stroke;
|
|
17143
|
+
ctx.stroke();
|
|
17144
|
+
ctx.restore();
|
|
17145
|
+
}
|
|
17146
|
+
var WeavePolygonNode = class extends WeaveNode {
|
|
17147
|
+
nodeType = WEAVE_POLYGON_NODE_TYPE;
|
|
17148
|
+
initialize = void 0;
|
|
17149
|
+
_transforming = false;
|
|
17150
|
+
get shapeLabelEditor() {
|
|
17151
|
+
this._shapeLabelEditor ??= new WeaveShapeLabelEditor(this.instance);
|
|
17152
|
+
return this._shapeLabelEditor;
|
|
17153
|
+
}
|
|
17154
|
+
constructor(params) {
|
|
17155
|
+
super();
|
|
17156
|
+
const { config } = params ?? {};
|
|
17157
|
+
this.config = { transform: { ...config?.transform } };
|
|
17158
|
+
}
|
|
17159
|
+
getLabelTextBounds(group) {
|
|
17160
|
+
const attrs = group.getAttrs();
|
|
17161
|
+
const innerRect = attrs.innerRect;
|
|
17162
|
+
const paddingX = attrs.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
17163
|
+
const paddingY = attrs.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
17164
|
+
if (!innerRect) return {
|
|
17165
|
+
x: 0,
|
|
17166
|
+
y: 0,
|
|
17167
|
+
width: 1,
|
|
17168
|
+
height: 1
|
|
17169
|
+
};
|
|
17170
|
+
return getPolygonLabelTextBounds(innerRect, paddingX, paddingY);
|
|
17171
|
+
}
|
|
17172
|
+
scalePolygonByDimensions(polygon, nextProps, nodeInstance) {
|
|
17173
|
+
let points = polygon.getAttr("points");
|
|
17174
|
+
const propsMaxX = points.length ? Math.max(...points.map((p) => p.x)) : 0;
|
|
17175
|
+
const propsMaxY = points.length ? Math.max(...points.map((p) => p.y)) : 0;
|
|
17176
|
+
const wantWidth = nextProps.width;
|
|
17177
|
+
const wantHeight = nextProps.height;
|
|
17178
|
+
if (wantWidth === void 0 || wantHeight === void 0) return points;
|
|
17179
|
+
const sX = propsMaxX > 0 ? wantWidth / propsMaxX : 1;
|
|
17180
|
+
const sY = propsMaxY > 0 ? wantHeight / propsMaxY : 1;
|
|
17181
|
+
if (Math.abs(sX - 1) <= .001 && Math.abs(sY - 1) <= .001) return points;
|
|
17182
|
+
const scaledPoints = points.map((p) => ({
|
|
17183
|
+
x: p.x * sX,
|
|
17184
|
+
y: p.y * sY
|
|
17185
|
+
}));
|
|
17186
|
+
const prevInnerRect = polygon.getAttr("innerRect");
|
|
17187
|
+
if (prevInnerRect) {
|
|
17188
|
+
const scaledInnerRect = {
|
|
17189
|
+
tl: {
|
|
17190
|
+
x: prevInnerRect.tl.x * sX,
|
|
17191
|
+
y: prevInnerRect.tl.y * sY
|
|
17192
|
+
},
|
|
17193
|
+
tr: {
|
|
17194
|
+
x: prevInnerRect.tr.x * sX,
|
|
17195
|
+
y: prevInnerRect.tr.y * sY
|
|
17196
|
+
},
|
|
17197
|
+
bl: {
|
|
17198
|
+
x: prevInnerRect.bl.x * sX,
|
|
17199
|
+
y: prevInnerRect.bl.y * sY
|
|
17200
|
+
},
|
|
17201
|
+
br: {
|
|
17202
|
+
x: prevInnerRect.br.x * sX,
|
|
17203
|
+
y: prevInnerRect.br.y * sY
|
|
17204
|
+
}
|
|
17205
|
+
};
|
|
17206
|
+
polygon.setAttr("innerRect", scaledInnerRect);
|
|
17207
|
+
}
|
|
17208
|
+
polygon.setAttr("points", scaledPoints);
|
|
17209
|
+
points = scaledPoints;
|
|
17210
|
+
if (!this._transforming) this.instance.updateNode(this.serialize(nodeInstance));
|
|
17211
|
+
return points;
|
|
17212
|
+
}
|
|
17213
|
+
onLabelGrow(polygon, bgShape, borderShape, nodeInstance, neededHeight) {
|
|
17214
|
+
const livePoints = polygon.getAttr("points");
|
|
17215
|
+
const liveInnerRect = polygon.getAttr("innerRect");
|
|
17216
|
+
if (!liveInnerRect) return;
|
|
17217
|
+
const currentBoundsHeight = liveInnerRect.bl.y - liveInnerRect.tl.y;
|
|
17218
|
+
if (neededHeight <= currentBoundsHeight) return;
|
|
17219
|
+
const oldHeight = Math.max(...livePoints.map((p) => p.y));
|
|
17220
|
+
const scale = currentBoundsHeight > 0 ? neededHeight / currentBoundsHeight : 1;
|
|
17221
|
+
const newHeight = oldHeight * scale;
|
|
17222
|
+
const newPoints = livePoints.map((p) => ({
|
|
17223
|
+
...p,
|
|
17224
|
+
y: p.y * scale
|
|
17225
|
+
}));
|
|
17226
|
+
const newInnerRect = {
|
|
17227
|
+
tl: {
|
|
17228
|
+
...liveInnerRect.tl,
|
|
17229
|
+
y: liveInnerRect.tl.y * scale
|
|
17230
|
+
},
|
|
17231
|
+
tr: {
|
|
17232
|
+
...liveInnerRect.tr,
|
|
17233
|
+
y: liveInnerRect.tr.y * scale
|
|
17234
|
+
},
|
|
17235
|
+
bl: {
|
|
17236
|
+
...liveInnerRect.bl,
|
|
17237
|
+
y: liveInnerRect.bl.y * scale
|
|
17238
|
+
},
|
|
17239
|
+
br: {
|
|
17240
|
+
...liveInnerRect.br,
|
|
17241
|
+
y: liveInnerRect.br.y * scale
|
|
17242
|
+
}
|
|
17243
|
+
};
|
|
17244
|
+
polygon.setAttr("points", newPoints);
|
|
17245
|
+
polygon.setAttr("innerRect", newInnerRect);
|
|
17246
|
+
polygon.setAttr("height", newHeight);
|
|
17247
|
+
bgShape?.setAttr("points", newPoints);
|
|
17248
|
+
borderShape?.setAttr("points", newPoints);
|
|
17249
|
+
if (!this._transforming) this.instance.updateNode(this.serialize(nodeInstance));
|
|
17250
|
+
}
|
|
17251
|
+
triggerPolygonLabelEdit(polygon, props) {
|
|
17252
|
+
const onCommit = (labelText) => {
|
|
17253
|
+
const updatedGroup = this.instance.getStage().findOne(`#${props.id}`);
|
|
17254
|
+
if (!updatedGroup) return;
|
|
17255
|
+
const serialized = this.serialize(updatedGroup);
|
|
17256
|
+
serialized.props.labelText = labelText;
|
|
17257
|
+
this.instance.updateNode(serialized);
|
|
17258
|
+
};
|
|
17259
|
+
const currentLabelTextBounds = this.getLabelTextBounds(polygon);
|
|
17260
|
+
this.shapeLabelEditor.triggerEditMode(polygon, currentLabelTextBounds, onCommit, (neededShapeHeight) => {
|
|
17261
|
+
const liveAttrs = polygon.getAttrs();
|
|
17262
|
+
const livePoints = liveAttrs.points;
|
|
17263
|
+
const liveInnerRect = liveAttrs.innerRect;
|
|
17264
|
+
const liveInnerRectHeight = liveInnerRect.bl.y - liveInnerRect.tl.y;
|
|
17265
|
+
if (neededShapeHeight <= liveInnerRectHeight) return;
|
|
17266
|
+
const oldHeight = Math.max(...livePoints.map((p) => p.y));
|
|
17267
|
+
const scale = liveInnerRectHeight > 0 ? neededShapeHeight / liveInnerRectHeight : 1;
|
|
17268
|
+
const newHeight = oldHeight * scale;
|
|
17269
|
+
const newPoints = livePoints.map((p) => ({
|
|
17270
|
+
...p,
|
|
17271
|
+
y: p.y * scale
|
|
17272
|
+
}));
|
|
17273
|
+
const newInnerRect = {
|
|
17274
|
+
tl: {
|
|
17275
|
+
...liveInnerRect.tl,
|
|
17276
|
+
y: liveInnerRect.tl.y * scale
|
|
17277
|
+
},
|
|
17278
|
+
tr: {
|
|
17279
|
+
...liveInnerRect.tr,
|
|
17280
|
+
y: liveInnerRect.tr.y * scale
|
|
17281
|
+
},
|
|
17282
|
+
bl: {
|
|
17283
|
+
...liveInnerRect.bl,
|
|
17284
|
+
y: liveInnerRect.bl.y * scale
|
|
17285
|
+
},
|
|
17286
|
+
br: {
|
|
17287
|
+
...liveInnerRect.br,
|
|
17288
|
+
y: liveInnerRect.br.y * scale
|
|
17289
|
+
}
|
|
17290
|
+
};
|
|
17291
|
+
polygon.setAttrs({
|
|
17292
|
+
points: newPoints,
|
|
17293
|
+
innerRect: newInnerRect,
|
|
17294
|
+
height: newHeight
|
|
17295
|
+
});
|
|
17296
|
+
this.onUpdate(polygon, polygon.getAttrs());
|
|
17297
|
+
const newLabelTextBounds = this.getLabelTextBounds(polygon);
|
|
17298
|
+
this.shapeLabelEditor.repositionTextArea(polygon, newLabelTextBounds);
|
|
17299
|
+
});
|
|
17300
|
+
}
|
|
17301
|
+
scaleReset(group) {
|
|
17302
|
+
const scaleX = group.scaleX();
|
|
17303
|
+
const scaleY = group.scaleY();
|
|
17304
|
+
if (scaleX === 1 && scaleY === 1) return;
|
|
17305
|
+
const points = group.getAttr("points");
|
|
17306
|
+
const innerRect = group.getAttr("innerRect");
|
|
17307
|
+
const newPoints = points.map((p) => ({
|
|
17308
|
+
x: p.x * scaleX,
|
|
17309
|
+
y: p.y * scaleY
|
|
17310
|
+
}));
|
|
17311
|
+
const newInnerRect = innerRect ? {
|
|
17312
|
+
tl: {
|
|
17313
|
+
x: innerRect.tl.x * scaleX,
|
|
17314
|
+
y: innerRect.tl.y * scaleY
|
|
17315
|
+
},
|
|
17316
|
+
tr: {
|
|
17317
|
+
x: innerRect.tr.x * scaleX,
|
|
17318
|
+
y: innerRect.tr.y * scaleY
|
|
17319
|
+
},
|
|
17320
|
+
bl: {
|
|
17321
|
+
x: innerRect.bl.x * scaleX,
|
|
17322
|
+
y: innerRect.bl.y * scaleY
|
|
17323
|
+
},
|
|
17324
|
+
br: {
|
|
17325
|
+
x: innerRect.br.x * scaleX,
|
|
17326
|
+
y: innerRect.br.y * scaleY
|
|
17327
|
+
}
|
|
17328
|
+
} : void 0;
|
|
17329
|
+
const absTransform = group.getAbsoluteTransform().copy();
|
|
17330
|
+
group.setAttr("points", newPoints);
|
|
17331
|
+
if (newInnerRect) group.setAttr("innerRect", newInnerRect);
|
|
17332
|
+
group.scaleX(1);
|
|
17333
|
+
group.scaleY(1);
|
|
17334
|
+
group.setAttr("width", Math.max(...newPoints.map((p) => p.x)));
|
|
17335
|
+
group.setAttr("height", Math.max(...newPoints.map((p) => p.y)));
|
|
17336
|
+
const newTransform = group.getAbsoluteTransform();
|
|
17337
|
+
const dx = absTransform.m[4] - newTransform.m[4];
|
|
17338
|
+
const dy = absTransform.m[5] - newTransform.m[5];
|
|
17339
|
+
group.x(group.x() + dx);
|
|
17340
|
+
group.y(group.y() + dy);
|
|
17341
|
+
}
|
|
17342
|
+
onRender(props) {
|
|
17343
|
+
const polygon = new Konva.Group({
|
|
17344
|
+
...props,
|
|
17345
|
+
name: "node"
|
|
17346
|
+
});
|
|
17347
|
+
const points = polygon.getAttr("points");
|
|
17348
|
+
const strokeWidth = props.strokeWidth || 0;
|
|
17349
|
+
const bgShape = new Konva.Shape({
|
|
17350
|
+
id: `${props.id}-bg`,
|
|
17351
|
+
nodeId: props.id,
|
|
17352
|
+
points,
|
|
17353
|
+
...computePolygonBounds(points),
|
|
17354
|
+
fill: props.fill || "transparent",
|
|
17355
|
+
strokeWidth: 0,
|
|
17356
|
+
strokeScaleEnabled: false,
|
|
17357
|
+
sceneFunc
|
|
17358
|
+
});
|
|
17359
|
+
bgShape.getSelfRect = polygonSelfRect.bind(bgShape);
|
|
17360
|
+
polygon.add(bgShape);
|
|
17361
|
+
const borderShape = new Konva.Shape({
|
|
17362
|
+
id: `${props.id}-border`,
|
|
17363
|
+
points,
|
|
17364
|
+
fill: "transparent",
|
|
17365
|
+
stroke: props.stroke || "transparent",
|
|
17366
|
+
strokeWidth: 0,
|
|
17367
|
+
innerStrokeWidth: strokeWidth,
|
|
17368
|
+
strokeScaleEnabled: false,
|
|
17369
|
+
listening: false,
|
|
17370
|
+
sceneFunc: borderSceneFunc
|
|
17371
|
+
});
|
|
17372
|
+
borderShape.getSelfRect = polygonSelfRect.bind(borderShape);
|
|
17373
|
+
polygon.add(borderShape);
|
|
17374
|
+
const innerRect = polygon.getAttr("innerRect");
|
|
17375
|
+
const paddingX = props.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
17376
|
+
const paddingY = props.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
17377
|
+
const labelTextBounds = innerRect ? getPolygonLabelTextBounds(innerRect, paddingX, paddingY) : {
|
|
17378
|
+
x: 0,
|
|
17379
|
+
y: 0,
|
|
17380
|
+
width: 1,
|
|
17381
|
+
height: 1
|
|
17382
|
+
};
|
|
17383
|
+
this.shapeLabelEditor.renderLabel(polygon, props, labelTextBounds);
|
|
17384
|
+
borderShape.moveToTop();
|
|
17385
|
+
bgShape.moveToBottom();
|
|
17386
|
+
this.setupDefaultNodeAugmentation(polygon);
|
|
15581
17387
|
const defaultTransformerProperties = this.defaultGetTransformerProperties(this.config.transform);
|
|
15582
|
-
|
|
17388
|
+
polygon.getTransformerProperties = function() {
|
|
15583
17389
|
return {
|
|
15584
17390
|
...defaultTransformerProperties,
|
|
15585
17391
|
enabledAnchors: [
|
|
15586
17392
|
"top-left",
|
|
17393
|
+
"top-center",
|
|
15587
17394
|
"top-right",
|
|
17395
|
+
"middle-right",
|
|
17396
|
+
"middle-left",
|
|
15588
17397
|
"bottom-left",
|
|
17398
|
+
"bottom-center",
|
|
15589
17399
|
"bottom-right"
|
|
15590
17400
|
],
|
|
15591
|
-
keepRatio:
|
|
17401
|
+
keepRatio: false
|
|
15592
17402
|
};
|
|
15593
17403
|
};
|
|
15594
|
-
|
|
17404
|
+
polygon.allowedAnchors = function() {
|
|
15595
17405
|
return [
|
|
15596
17406
|
"top-left",
|
|
17407
|
+
"top-center",
|
|
15597
17408
|
"top-right",
|
|
17409
|
+
"middle-right",
|
|
17410
|
+
"middle-left",
|
|
15598
17411
|
"bottom-left",
|
|
17412
|
+
"bottom-center",
|
|
15599
17413
|
"bottom-right"
|
|
15600
17414
|
];
|
|
15601
17415
|
};
|
|
15602
|
-
this.setupDefaultNodeEvents(
|
|
15603
|
-
|
|
17416
|
+
this.setupDefaultNodeEvents(polygon);
|
|
17417
|
+
polygon.on("transformstart", () => {
|
|
17418
|
+
this._transforming = true;
|
|
17419
|
+
});
|
|
17420
|
+
polygon.on("transform", () => {
|
|
17421
|
+
this.scaleReset(polygon);
|
|
17422
|
+
this.onUpdate(polygon, polygon.getAttrs());
|
|
17423
|
+
});
|
|
17424
|
+
polygon.on("transformend", () => {
|
|
17425
|
+
this._transforming = false;
|
|
17426
|
+
});
|
|
17427
|
+
polygon.dblClick = () => {
|
|
17428
|
+
if (this.shapeLabelEditor.isEditing()) return;
|
|
17429
|
+
if (!(this.isSelecting() && this.isNodeSelected(polygon))) return;
|
|
17430
|
+
this.triggerPolygonLabelEdit(polygon, props);
|
|
17431
|
+
};
|
|
17432
|
+
polygon.getNodeMinSize = () => {
|
|
17433
|
+
return computePolygonLabelMinSize(this.instance.getStage(), polygon);
|
|
17434
|
+
};
|
|
17435
|
+
return polygon;
|
|
15604
17436
|
}
|
|
15605
17437
|
onUpdate(nodeInstance, nextProps) {
|
|
15606
17438
|
nodeInstance.setAttrs({ ...nextProps });
|
|
15607
|
-
const
|
|
15608
|
-
const
|
|
15609
|
-
const
|
|
15610
|
-
const
|
|
15611
|
-
|
|
15612
|
-
|
|
15613
|
-
|
|
15614
|
-
...
|
|
15615
|
-
name: void 0,
|
|
15616
|
-
id: `${nextProps.id}-bg`,
|
|
15617
|
-
nodeId: nextProps.id,
|
|
15618
|
-
x: radius,
|
|
15619
|
-
y: radius,
|
|
15620
|
-
sides,
|
|
15621
|
-
radius,
|
|
17439
|
+
const polygon = nodeInstance;
|
|
17440
|
+
const strokeWidth = nextProps.strokeWidth || 0;
|
|
17441
|
+
const points = this.scalePolygonByDimensions(polygon, nextProps, nodeInstance);
|
|
17442
|
+
const bgShape = polygon.findOne(`#${nextProps.id}-bg`);
|
|
17443
|
+
if (bgShape) {
|
|
17444
|
+
bgShape.setAttrs({
|
|
17445
|
+
points,
|
|
17446
|
+
...computePolygonBounds(points),
|
|
15622
17447
|
fill: nextProps.fill || "transparent",
|
|
15623
17448
|
strokeWidth: 0,
|
|
15624
|
-
strokeScaleEnabled:
|
|
15625
|
-
rotation: 0
|
|
17449
|
+
strokeScaleEnabled: false
|
|
15626
17450
|
});
|
|
15627
|
-
|
|
15628
|
-
internalRPBg.x(internalRPBg.x() - internalRPBgBox.x);
|
|
15629
|
-
internalRPBg.y(internalRPBg.y() - internalRPBgBox.y);
|
|
15630
|
-
internalRPBg.moveToBottom();
|
|
17451
|
+
bgShape.moveToBottom();
|
|
15631
17452
|
}
|
|
15632
|
-
|
|
15633
|
-
|
|
15634
|
-
|
|
15635
|
-
|
|
15636
|
-
|
|
15637
|
-
|
|
15638
|
-
|
|
15639
|
-
|
|
15640
|
-
|
|
15641
|
-
|
|
15642
|
-
|
|
15643
|
-
|
|
15644
|
-
|
|
15645
|
-
|
|
15646
|
-
|
|
15647
|
-
|
|
15648
|
-
|
|
15649
|
-
|
|
15650
|
-
|
|
17453
|
+
const borderShape = polygon.findOne(`#${nextProps.id}-border`);
|
|
17454
|
+
if (borderShape) borderShape.setAttrs({
|
|
17455
|
+
points,
|
|
17456
|
+
fill: "transparent",
|
|
17457
|
+
stroke: nextProps.stroke || "transparent",
|
|
17458
|
+
strokeWidth: 0,
|
|
17459
|
+
innerStrokeWidth: strokeWidth,
|
|
17460
|
+
strokeScaleEnabled: false,
|
|
17461
|
+
listening: false
|
|
17462
|
+
});
|
|
17463
|
+
const paddingX = nextProps.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
17464
|
+
const paddingY = nextProps.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
17465
|
+
const innerRect = polygon.getAttr("innerRect");
|
|
17466
|
+
const labelTextBounds = innerRect ? getPolygonLabelTextBounds(innerRect, paddingX, paddingY) : {
|
|
17467
|
+
x: 0,
|
|
17468
|
+
y: 0,
|
|
17469
|
+
width: 1,
|
|
17470
|
+
height: 1
|
|
17471
|
+
};
|
|
17472
|
+
this.shapeLabelEditor.updateLabel(polygon, nextProps, labelTextBounds, (neededHeight) => this.onLabelGrow(polygon, bgShape, borderShape, nodeInstance, neededHeight));
|
|
17473
|
+
const labelNode = polygon.findOne(`#${labelId(nextProps.id)}`);
|
|
17474
|
+
if (labelNode) {
|
|
17475
|
+
labelNode.moveToTop();
|
|
17476
|
+
borderShape?.moveToTop();
|
|
15651
17477
|
}
|
|
15652
17478
|
const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
15653
|
-
if (nodesSelectionPlugin)
|
|
15654
|
-
const actualSelectedNodes = nodesSelectionPlugin.getSelectedNodes();
|
|
15655
|
-
nodesSelectionPlugin.setSelectedNodes(actualSelectedNodes);
|
|
15656
|
-
nodesSelectionPlugin.getTransformer().forceUpdate();
|
|
15657
|
-
}
|
|
15658
|
-
}
|
|
15659
|
-
scaleReset(node) {
|
|
15660
|
-
const absTransform = node.getAbsoluteTransform().copy();
|
|
15661
|
-
const radius = node.getAttr("radius");
|
|
15662
|
-
node.setAttrs({ radius: radius * node.scaleX() });
|
|
15663
|
-
node.scaleX(1);
|
|
15664
|
-
node.scaleY(1);
|
|
15665
|
-
const newTransform = node.getAbsoluteTransform();
|
|
15666
|
-
const dx = absTransform.m[4] - newTransform.m[4];
|
|
15667
|
-
const dy = absTransform.m[5] - newTransform.m[5];
|
|
15668
|
-
node.x(node.x() + dx);
|
|
15669
|
-
node.y(node.y() + dy);
|
|
17479
|
+
if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
|
|
15670
17480
|
}
|
|
15671
|
-
realOffset(
|
|
17481
|
+
realOffset(_element) {
|
|
15672
17482
|
return {
|
|
15673
|
-
x:
|
|
15674
|
-
y:
|
|
17483
|
+
x: 0,
|
|
17484
|
+
y: 0
|
|
15675
17485
|
};
|
|
15676
17486
|
}
|
|
15677
17487
|
static defaultState(nodeId) {
|
|
17488
|
+
const preset = WEAVE_POLYGON_PRESETS.pentagon;
|
|
17489
|
+
const { points, innerRect, width, height } = instantiatePreset(preset, preset.defaultWidth, preset.defaultHeight);
|
|
15678
17490
|
return {
|
|
15679
17491
|
...super.defaultState(nodeId),
|
|
15680
|
-
type:
|
|
17492
|
+
type: WEAVE_POLYGON_NODE_TYPE,
|
|
15681
17493
|
props: {
|
|
15682
17494
|
...super.defaultState(nodeId).props,
|
|
15683
|
-
nodeType:
|
|
17495
|
+
nodeType: WEAVE_POLYGON_NODE_TYPE,
|
|
15684
17496
|
x: 0,
|
|
15685
17497
|
y: 0,
|
|
15686
|
-
|
|
15687
|
-
|
|
17498
|
+
width,
|
|
17499
|
+
height,
|
|
17500
|
+
sides: preset.sides,
|
|
17501
|
+
points,
|
|
17502
|
+
innerRect,
|
|
15688
17503
|
stroke: "#000000",
|
|
15689
17504
|
fill: "#FFFFFF",
|
|
15690
17505
|
strokeWidth: 1,
|
|
15691
|
-
strokeScaleEnabled:
|
|
17506
|
+
strokeScaleEnabled: false,
|
|
15692
17507
|
rotation: 0,
|
|
15693
17508
|
zIndex: 1,
|
|
15694
|
-
children: []
|
|
17509
|
+
children: [],
|
|
17510
|
+
...WEAVE_SHAPE_LABEL_DEFAULTS
|
|
15695
17511
|
}
|
|
15696
17512
|
};
|
|
15697
17513
|
}
|
|
@@ -15699,38 +17515,103 @@ var WeaveRegularPolygonNode = class extends WeaveNode {
|
|
|
15699
17515
|
return mergeExceptArrays(defaultNodeState, { props: {
|
|
15700
17516
|
x: props.x,
|
|
15701
17517
|
y: props.y,
|
|
17518
|
+
width: props.width,
|
|
17519
|
+
height: props.height,
|
|
15702
17520
|
sides: props.sides,
|
|
15703
|
-
|
|
17521
|
+
points: props.points,
|
|
17522
|
+
innerRect: props.innerRect,
|
|
15704
17523
|
rotation: props.rotation,
|
|
15705
17524
|
fill: props.fill,
|
|
15706
17525
|
...props.stroke && { stroke: props.stroke },
|
|
15707
|
-
...props.strokeWidth && { strokeWidth: props.strokeWidth }
|
|
17526
|
+
...props.strokeWidth !== void 0 && { strokeWidth: props.strokeWidth },
|
|
17527
|
+
...props.labelText !== void 0 && { labelText: props.labelText },
|
|
17528
|
+
...props.labelFontFamily !== void 0 && { labelFontFamily: props.labelFontFamily },
|
|
17529
|
+
...props.labelFontSize !== void 0 && { labelFontSize: props.labelFontSize },
|
|
17530
|
+
...props.labelFontStyle !== void 0 && { labelFontStyle: props.labelFontStyle },
|
|
17531
|
+
...props.labelFontVariant !== void 0 && { labelFontVariant: props.labelFontVariant },
|
|
17532
|
+
...props.labelFill !== void 0 && { labelFill: props.labelFill },
|
|
17533
|
+
...props.labelAlign !== void 0 && { labelAlign: props.labelAlign },
|
|
17534
|
+
...props.labelVerticalAlign !== void 0 && { labelVerticalAlign: props.labelVerticalAlign },
|
|
17535
|
+
...props.labelLetterSpacing !== void 0 && { labelLetterSpacing: props.labelLetterSpacing },
|
|
17536
|
+
...props.labelLineHeight !== void 0 && { labelLineHeight: props.labelLineHeight },
|
|
17537
|
+
...props.labelPaddingX !== void 0 && { labelPaddingX: props.labelPaddingX },
|
|
17538
|
+
...props.labelPaddingY !== void 0 && { labelPaddingY: props.labelPaddingY }
|
|
15708
17539
|
} });
|
|
15709
17540
|
}
|
|
15710
17541
|
static updateNodeState(prevNodeState, nextProps) {
|
|
15711
17542
|
return mergeExceptArrays(prevNodeState, { props: {
|
|
15712
17543
|
x: nextProps.x,
|
|
15713
17544
|
y: nextProps.y,
|
|
17545
|
+
...nextProps.width !== void 0 && { width: nextProps.width },
|
|
17546
|
+
...nextProps.height !== void 0 && { height: nextProps.height },
|
|
15714
17547
|
sides: nextProps.sides,
|
|
15715
|
-
|
|
17548
|
+
points: nextProps.points,
|
|
17549
|
+
innerRect: nextProps.innerRect,
|
|
15716
17550
|
rotation: nextProps.rotation,
|
|
15717
17551
|
fill: nextProps.fill,
|
|
15718
17552
|
...nextProps.stroke && { stroke: nextProps.stroke },
|
|
15719
|
-
...nextProps.strokeWidth && { strokeWidth: nextProps.strokeWidth }
|
|
17553
|
+
...nextProps.strokeWidth !== void 0 && { strokeWidth: nextProps.strokeWidth },
|
|
17554
|
+
...nextProps.labelText !== void 0 && { labelText: nextProps.labelText },
|
|
17555
|
+
...nextProps.labelFontFamily !== void 0 && { labelFontFamily: nextProps.labelFontFamily },
|
|
17556
|
+
...nextProps.labelFontSize !== void 0 && { labelFontSize: nextProps.labelFontSize },
|
|
17557
|
+
...nextProps.labelFontStyle !== void 0 && { labelFontStyle: nextProps.labelFontStyle },
|
|
17558
|
+
...nextProps.labelFontVariant !== void 0 && { labelFontVariant: nextProps.labelFontVariant },
|
|
17559
|
+
...nextProps.labelFill !== void 0 && { labelFill: nextProps.labelFill },
|
|
17560
|
+
...nextProps.labelAlign !== void 0 && { labelAlign: nextProps.labelAlign },
|
|
17561
|
+
...nextProps.labelVerticalAlign !== void 0 && { labelVerticalAlign: nextProps.labelVerticalAlign },
|
|
17562
|
+
...nextProps.labelLetterSpacing !== void 0 && { labelLetterSpacing: nextProps.labelLetterSpacing },
|
|
17563
|
+
...nextProps.labelLineHeight !== void 0 && { labelLineHeight: nextProps.labelLineHeight },
|
|
17564
|
+
...nextProps.labelPaddingX !== void 0 && { labelPaddingX: nextProps.labelPaddingX },
|
|
17565
|
+
...nextProps.labelPaddingY !== void 0 && { labelPaddingY: nextProps.labelPaddingY }
|
|
15720
17566
|
} });
|
|
15721
17567
|
}
|
|
15722
17568
|
static getSchema() {
|
|
15723
17569
|
const baseSchema = super.getSchema();
|
|
15724
17570
|
const nodeSchema = baseSchema.extend({
|
|
15725
|
-
type: z.literal(
|
|
17571
|
+
type: z.literal(WEAVE_POLYGON_NODE_TYPE).describe(`Type of the node, for a polygon node it will always be "${WEAVE_POLYGON_NODE_TYPE}"`),
|
|
15726
17572
|
props: baseSchema.shape.props.extend({
|
|
15727
|
-
nodeType: z.literal(
|
|
15728
|
-
sides: z.number().describe("Number of sides of the
|
|
15729
|
-
|
|
15730
|
-
|
|
15731
|
-
|
|
15732
|
-
|
|
15733
|
-
|
|
17573
|
+
nodeType: z.literal(WEAVE_POLYGON_NODE_TYPE).describe(`Type of the node, for a polygon node it will always be "${WEAVE_POLYGON_NODE_TYPE}"`),
|
|
17574
|
+
sides: z.number().describe("Number of sides of the polygon (3 or more)"),
|
|
17575
|
+
width: z.number().optional().describe("Visual width of the polygon in pixels (= maxX of vertices). Setting this rescales vertices proportionally."),
|
|
17576
|
+
height: z.number().optional().describe("Visual height of the polygon in pixels (= maxY of vertices). Setting this rescales vertices proportionally."),
|
|
17577
|
+
points: z.array(z.object({
|
|
17578
|
+
x: z.number(),
|
|
17579
|
+
y: z.number()
|
|
17580
|
+
})).describe("Vertex positions of the polygon in group-local pixel space"),
|
|
17581
|
+
innerRect: z.object({
|
|
17582
|
+
tl: z.object({
|
|
17583
|
+
x: z.number(),
|
|
17584
|
+
y: z.number()
|
|
17585
|
+
}),
|
|
17586
|
+
tr: z.object({
|
|
17587
|
+
x: z.number(),
|
|
17588
|
+
y: z.number()
|
|
17589
|
+
}),
|
|
17590
|
+
bl: z.object({
|
|
17591
|
+
x: z.number(),
|
|
17592
|
+
y: z.number()
|
|
17593
|
+
}),
|
|
17594
|
+
br: z.object({
|
|
17595
|
+
x: z.number(),
|
|
17596
|
+
y: z.number()
|
|
17597
|
+
})
|
|
17598
|
+
}).describe("Largest inscribed axis-aligned rectangle inside the polygon (used for label bounds)"),
|
|
17599
|
+
fill: z.string().describe("Fill color of the polygon in hex format with alpha channel (e.g. #RRGGBBAA)"),
|
|
17600
|
+
stroke: z.string().describe("Stroke color of the polygon in hex format with alpha channel (e.g. #RRGGBBAA)"),
|
|
17601
|
+
strokeWidth: z.number().describe("Stroke width of the polygon in pixels"),
|
|
17602
|
+
strokeScaleEnabled: z.boolean().describe("Whether the polygon stroke width should scale when the node is scaled. Defaults to false."),
|
|
17603
|
+
labelText: z.string().optional().describe("Text label displayed inside the polygon"),
|
|
17604
|
+
labelFontFamily: z.string().optional().describe("Font family for the label text"),
|
|
17605
|
+
labelFontSize: z.number().optional().describe("Font size for the label text in pixels"),
|
|
17606
|
+
labelFontStyle: z.string().optional().describe("Font style for the label text (e.g. \"normal\", \"bold\", \"italic\", \"bold italic\")"),
|
|
17607
|
+
labelFontVariant: z.string().optional().describe("Font variant for the label text (e.g. \"normal\", \"small-caps\")"),
|
|
17608
|
+
labelFill: z.string().optional().describe("Color of the label text in hex format (e.g. #RRGGBBAA)"),
|
|
17609
|
+
labelAlign: z.string().optional().describe("Horizontal alignment of the label text (\"left\", \"center\", \"right\")"),
|
|
17610
|
+
labelVerticalAlign: z.string().optional().describe("Vertical alignment of the label text (\"top\", \"middle\", \"bottom\")"),
|
|
17611
|
+
labelLetterSpacing: z.number().optional().describe("Letter spacing for the label text in pixels"),
|
|
17612
|
+
labelLineHeight: z.number().optional().describe("Line height multiplier for the label text"),
|
|
17613
|
+
labelPaddingX: z.number().optional().describe("Horizontal inset (padding) in pixels applied on each side of the label"),
|
|
17614
|
+
labelPaddingY: z.number().optional().describe("Vertical inset (padding) in pixels applied on top and bottom of the label")
|
|
15734
17615
|
})
|
|
15735
17616
|
});
|
|
15736
17617
|
return nodeSchema;
|
|
@@ -21629,6 +23510,7 @@ var WeaveRectangleToolAction = class extends WeaveAction {
|
|
|
21629
23510
|
if (node) selectionPlugin.setSelectedNodes([node]);
|
|
21630
23511
|
this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
|
|
21631
23512
|
}
|
|
23513
|
+
if (this.tempRectNode) this.tempRectNode.destroy();
|
|
21632
23514
|
this.rectId = null;
|
|
21633
23515
|
this.tempRectNode = null;
|
|
21634
23516
|
this.moved = false;
|
|
@@ -24739,6 +26621,137 @@ var WeaveRegularPolygonToolAction = class extends WeaveAction {
|
|
|
24739
26621
|
}
|
|
24740
26622
|
};
|
|
24741
26623
|
|
|
26624
|
+
//#endregion
|
|
26625
|
+
//#region src/actions/polygon-tool/constants.ts
|
|
26626
|
+
const POLYGON_TOOL_ACTION_NAME = "polygonTool";
|
|
26627
|
+
const POLYGON_TOOL_STATE = {
|
|
26628
|
+
["IDLE"]: "idle",
|
|
26629
|
+
["ADDING"]: "adding",
|
|
26630
|
+
["ADDED"]: "added"
|
|
26631
|
+
};
|
|
26632
|
+
|
|
26633
|
+
//#endregion
|
|
26634
|
+
//#region src/actions/polygon-tool/polygon-tool.ts
|
|
26635
|
+
var WeavePolygonToolAction = class extends WeaveAction {
|
|
26636
|
+
initialized = false;
|
|
26637
|
+
onPropsChange = void 0;
|
|
26638
|
+
onInit = void 0;
|
|
26639
|
+
constructor(preset) {
|
|
26640
|
+
super();
|
|
26641
|
+
this.preset = preset ?? "pentagon";
|
|
26642
|
+
this.initialize();
|
|
26643
|
+
}
|
|
26644
|
+
initialize() {
|
|
26645
|
+
this.initialized = false;
|
|
26646
|
+
this.state = POLYGON_TOOL_STATE.IDLE;
|
|
26647
|
+
this.polygonId = null;
|
|
26648
|
+
this.props = this.initProps();
|
|
26649
|
+
}
|
|
26650
|
+
getName() {
|
|
26651
|
+
return POLYGON_TOOL_ACTION_NAME;
|
|
26652
|
+
}
|
|
26653
|
+
initProps() {
|
|
26654
|
+
return {
|
|
26655
|
+
opacity: 1,
|
|
26656
|
+
fill: "#ffffffff",
|
|
26657
|
+
stroke: "#000000ff",
|
|
26658
|
+
strokeWidth: 1
|
|
26659
|
+
};
|
|
26660
|
+
}
|
|
26661
|
+
getPolygonsPresets() {
|
|
26662
|
+
return WEAVE_POLYGON_PRESETS;
|
|
26663
|
+
}
|
|
26664
|
+
getPolygonPreset() {
|
|
26665
|
+
return this.preset;
|
|
26666
|
+
}
|
|
26667
|
+
setPolygonPreset(preset) {
|
|
26668
|
+
this.preset = preset;
|
|
26669
|
+
}
|
|
26670
|
+
setupEvents() {
|
|
26671
|
+
const stage = this.instance.getStage();
|
|
26672
|
+
window.addEventListener("keydown", (e) => {
|
|
26673
|
+
if ((e.code === "Enter" || e.code === "Escape") && this.instance.getActiveAction() === POLYGON_TOOL_ACTION_NAME) this.cancelAction();
|
|
26674
|
+
}, { signal: this.instance.getEventsController().signal });
|
|
26675
|
+
stage.on("pointermove", () => {
|
|
26676
|
+
if (this.state === POLYGON_TOOL_STATE.IDLE) return;
|
|
26677
|
+
this.setCursor();
|
|
26678
|
+
});
|
|
26679
|
+
stage.on("pointerdown", (e) => {
|
|
26680
|
+
this.setTapStart(e);
|
|
26681
|
+
if (this.state !== POLYGON_TOOL_STATE.ADDING) return;
|
|
26682
|
+
this.handleAdding();
|
|
26683
|
+
});
|
|
26684
|
+
this.initialized = true;
|
|
26685
|
+
}
|
|
26686
|
+
setState(state) {
|
|
26687
|
+
this.state = state;
|
|
26688
|
+
}
|
|
26689
|
+
addPolygon() {
|
|
26690
|
+
this.setCursor();
|
|
26691
|
+
this.setFocusStage();
|
|
26692
|
+
this.instance.emitEvent("onAddingPolygon");
|
|
26693
|
+
this.setState(POLYGON_TOOL_STATE.ADDING);
|
|
26694
|
+
}
|
|
26695
|
+
handleAdding() {
|
|
26696
|
+
const { mousePoint, container } = this.instance.getMousePointer();
|
|
26697
|
+
this.polygonId = v4_default();
|
|
26698
|
+
const presetDef = WEAVE_POLYGON_PRESETS[this.preset];
|
|
26699
|
+
const scaleFactor = this.props.scaleFactor ?? 1;
|
|
26700
|
+
const { points, innerRect, width, height } = instantiatePreset(presetDef, presetDef.defaultWidth * scaleFactor, presetDef.defaultHeight * scaleFactor);
|
|
26701
|
+
const nodeHandler = this.instance.getNodeHandler(WEAVE_POLYGON_NODE_TYPE);
|
|
26702
|
+
if (nodeHandler) {
|
|
26703
|
+
const node = nodeHandler.create(this.polygonId, {
|
|
26704
|
+
...this.props,
|
|
26705
|
+
x: mousePoint?.x ?? 0,
|
|
26706
|
+
y: mousePoint?.y ?? 0,
|
|
26707
|
+
width,
|
|
26708
|
+
height,
|
|
26709
|
+
sides: presetDef.sides,
|
|
26710
|
+
points,
|
|
26711
|
+
innerRect
|
|
26712
|
+
});
|
|
26713
|
+
this.instance.addNode(node, container?.getAttrs().id);
|
|
26714
|
+
}
|
|
26715
|
+
this.instance.emitEvent("onAddedPolygon");
|
|
26716
|
+
this.cancelAction();
|
|
26717
|
+
}
|
|
26718
|
+
trigger(cancelAction, params) {
|
|
26719
|
+
if (!this.instance) throw new Error("Instance not defined");
|
|
26720
|
+
if (!this.initialized) this.setupEvents();
|
|
26721
|
+
this.preset = params?.presetId ?? "pentagon";
|
|
26722
|
+
const stage = this.instance.getStage();
|
|
26723
|
+
stage.container().tabIndex = 1;
|
|
26724
|
+
stage.container().focus();
|
|
26725
|
+
this.cancelAction = cancelAction;
|
|
26726
|
+
const selectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
26727
|
+
if (selectionPlugin) selectionPlugin.setSelectedNodes([]);
|
|
26728
|
+
this.props = this.initProps();
|
|
26729
|
+
this.addPolygon();
|
|
26730
|
+
}
|
|
26731
|
+
cleanup() {
|
|
26732
|
+
const stage = this.instance.getStage();
|
|
26733
|
+
stage.container().style.cursor = "default";
|
|
26734
|
+
const selectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
26735
|
+
if (selectionPlugin) {
|
|
26736
|
+
const node = stage.findOne(`#${this.polygonId}`);
|
|
26737
|
+
if (node) selectionPlugin.setSelectedNodes([node]);
|
|
26738
|
+
this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
|
|
26739
|
+
}
|
|
26740
|
+
this.polygonId = null;
|
|
26741
|
+
this.setState(POLYGON_TOOL_STATE.IDLE);
|
|
26742
|
+
}
|
|
26743
|
+
setCursor() {
|
|
26744
|
+
const stage = this.instance.getStage();
|
|
26745
|
+
stage.container().style.cursor = "crosshair";
|
|
26746
|
+
}
|
|
26747
|
+
setFocusStage() {
|
|
26748
|
+
const stage = this.instance.getStage();
|
|
26749
|
+
stage.container().tabIndex = 1;
|
|
26750
|
+
stage.container().blur();
|
|
26751
|
+
stage.container().focus();
|
|
26752
|
+
}
|
|
26753
|
+
};
|
|
26754
|
+
|
|
24742
26755
|
//#endregion
|
|
24743
26756
|
//#region src/actions/frame-tool/constants.ts
|
|
24744
26757
|
const FRAME_TOOL_ACTION_NAME = "frameTool";
|
|
@@ -30352,19 +32365,40 @@ var WeaveNodesSnappingGuides = class {
|
|
|
30352
32365
|
const stage = this.instance.getStage();
|
|
30353
32366
|
const scaleX = stage.scaleX();
|
|
30354
32367
|
const scaleY = stage.scaleY();
|
|
30355
|
-
|
|
30356
|
-
if (container
|
|
30357
|
-
|
|
30358
|
-
|
|
30359
|
-
|
|
30360
|
-
|
|
30361
|
-
|
|
30362
|
-
|
|
32368
|
+
const mainLayer = this.instance.getMainLayer();
|
|
32369
|
+
if (container === stage || container === mainLayer) {
|
|
32370
|
+
const pos$1 = stage.position();
|
|
32371
|
+
return {
|
|
32372
|
+
x: -pos$1.x / scaleX,
|
|
32373
|
+
y: -pos$1.y / scaleY,
|
|
32374
|
+
width: stage.width() / scaleX,
|
|
32375
|
+
height: stage.height() / scaleY
|
|
32376
|
+
};
|
|
32377
|
+
}
|
|
32378
|
+
let frameNode = null;
|
|
32379
|
+
let cur = container;
|
|
32380
|
+
while (cur && cur !== mainLayer && cur !== stage) {
|
|
32381
|
+
if (cur.getAttrs().nodeType === "frame") {
|
|
32382
|
+
frameNode = cur;
|
|
32383
|
+
break;
|
|
32384
|
+
}
|
|
32385
|
+
cur = cur.getParent();
|
|
32386
|
+
}
|
|
32387
|
+
if (frameNode) {
|
|
32388
|
+
const rect = frameNode.getClientRect({ relativeTo: stage });
|
|
32389
|
+
return {
|
|
32390
|
+
x: rect.x,
|
|
32391
|
+
y: rect.y,
|
|
32392
|
+
width: rect.width,
|
|
32393
|
+
height: rect.height
|
|
32394
|
+
};
|
|
32395
|
+
}
|
|
32396
|
+
const pos = stage.position();
|
|
30363
32397
|
return {
|
|
30364
|
-
x,
|
|
30365
|
-
y,
|
|
30366
|
-
width,
|
|
30367
|
-
height
|
|
32398
|
+
x: -pos.x / scaleX,
|
|
32399
|
+
y: -pos.y / scaleY,
|
|
32400
|
+
width: stage.width() / scaleX,
|
|
32401
|
+
height: stage.height() / scaleY
|
|
30368
32402
|
};
|
|
30369
32403
|
}
|
|
30370
32404
|
renderSnapGuides(container, snap) {
|
|
@@ -30376,8 +32410,11 @@ var WeaveNodesSnappingGuides = class {
|
|
|
30376
32410
|
if (snap.containerId !== "mainLayer") {
|
|
30377
32411
|
const containerNode = stage.findOne(`#${snap.containerId}`);
|
|
30378
32412
|
if (containerNode) {
|
|
30379
|
-
const
|
|
30380
|
-
|
|
32413
|
+
const canvasPt = containerNode.getAbsoluteTransform().point({
|
|
32414
|
+
x: snap.guide,
|
|
32415
|
+
y: 0
|
|
32416
|
+
});
|
|
32417
|
+
value = stage.getAbsoluteTransform().copy().invert().point(canvasPt).x;
|
|
30381
32418
|
}
|
|
30382
32419
|
}
|
|
30383
32420
|
this.layer.add(new Konva.Line({
|
|
@@ -30400,8 +32437,11 @@ var WeaveNodesSnappingGuides = class {
|
|
|
30400
32437
|
if (snap.containerId !== "mainLayer") {
|
|
30401
32438
|
const containerNode = stage.findOne(`#${snap.containerId}`);
|
|
30402
32439
|
if (containerNode) {
|
|
30403
|
-
const
|
|
30404
|
-
|
|
32440
|
+
const canvasPt = containerNode.getAbsoluteTransform().point({
|
|
32441
|
+
x: 0,
|
|
32442
|
+
y: snap.guide
|
|
32443
|
+
});
|
|
32444
|
+
value = stage.getAbsoluteTransform().copy().invert().point(canvasPt).y;
|
|
30405
32445
|
}
|
|
30406
32446
|
}
|
|
30407
32447
|
this.layer.add(new Konva.Line({
|
|
@@ -30835,14 +32875,20 @@ var WeaveNodesSnappingPlugin = class extends WeavePlugin {
|
|
|
30835
32875
|
}
|
|
30836
32876
|
return updatedBox;
|
|
30837
32877
|
};
|
|
30838
|
-
const
|
|
30839
|
-
|
|
32878
|
+
const snapBoundingBoxFunc = boundingBoxFunc.bind(this);
|
|
32879
|
+
const newBoundFunc = (oldBox, newBox) => {
|
|
32880
|
+
const mainBoundBoxFunc = nodesSelectionPlugin.getBoundBoxFunc();
|
|
32881
|
+
const actualBox = mainBoundBoxFunc(oldBox, newBox);
|
|
32882
|
+
if (actualBox === oldBox) return actualBox;
|
|
32883
|
+
return snapBoundingBoxFunc(oldBox, newBox);
|
|
32884
|
+
};
|
|
32885
|
+
tr.boundBoxFunc(newBoundFunc);
|
|
30840
32886
|
}
|
|
30841
32887
|
transformEndHandler() {
|
|
30842
32888
|
const nodesSelectionPlugin = this.getNodesSelectionPlugin();
|
|
30843
32889
|
if (nodesSelectionPlugin) {
|
|
30844
32890
|
const tr = nodesSelectionPlugin.getTransformer();
|
|
30845
|
-
tr.boundBoxFunc(
|
|
32891
|
+
tr.boundBoxFunc(nodesSelectionPlugin.getBoundBoxFunc());
|
|
30846
32892
|
}
|
|
30847
32893
|
this.snappingGuides = [];
|
|
30848
32894
|
}
|
|
@@ -30861,6 +32907,10 @@ var WeaveNodesSnappingPlugin = class extends WeavePlugin {
|
|
|
30861
32907
|
this.relativeToId = containerNode.id();
|
|
30862
32908
|
}
|
|
30863
32909
|
}
|
|
32910
|
+
if (container !== this.instance.getMainLayer() && !container.getAttrs().nodeId && container.getAttrs().nodeType === "group") {
|
|
32911
|
+
this.relativeTo = container;
|
|
32912
|
+
this.relativeToId = container.id();
|
|
32913
|
+
}
|
|
30864
32914
|
if (!this.relativeTo) return;
|
|
30865
32915
|
this.visibleNodes = getVisibleNodes({
|
|
30866
32916
|
instance: this.instance,
|
|
@@ -30891,8 +32941,8 @@ var WeaveNodesSnappingPlugin = class extends WeavePlugin {
|
|
|
30891
32941
|
y: -1 * (relativeTo.getAttrs().containerCompensationY ?? 0)
|
|
30892
32942
|
};
|
|
30893
32943
|
const diff = {
|
|
30894
|
-
x:
|
|
30895
|
-
y:
|
|
32944
|
+
x: node.x() - nodeBox.x,
|
|
32945
|
+
y: node.y() - nodeBox.y
|
|
30896
32946
|
};
|
|
30897
32947
|
this.selectionOffsets.push({
|
|
30898
32948
|
x: nodeBox.x - nodesBox.x + diff.x + containerCompensation.x,
|
|
@@ -31086,4 +33136,4 @@ function getJSONFromYjsBinary(actualState) {
|
|
|
31086
33136
|
}
|
|
31087
33137
|
|
|
31088
33138
|
//#endregion
|
|
31089
|
-
export { ALIGN_NODES_ALIGN_TO, ALIGN_NODES_TOOL_ACTION_NAME, ALIGN_NODES_TOOL_STATE, BRUSH_TOOL_ACTION_NAME, BRUSH_TOOL_DEFAULT_CONFIG, BRUSH_TOOL_STATE, CONNECTOR_TOOL_ACTION_NAME, CONNECTOR_TOOL_DEFAULT_CONFIG, CONNECTOR_TOOL_STATE, COPY_PASTE_NODES_PLUGIN_STATE, DEFAULT_GUIDE_TOOL_ACTION_CONFIG, DEFAULT_SNAPPING_MANAGER_CONFIG, ELLIPSE_TOOL_ACTION_NAME, ELLIPSE_TOOL_STATE, ERASER_TOOL_ACTION_NAME, ERASER_TOOL_STATE, FRAME_TOOL_ACTION_NAME, FRAME_TOOL_STATE, GUIDE_DISTANCE_NAME, GUIDE_DISTANCE_ORIGIN, GUIDE_KIND, GUIDE_NAME, GUIDE_ORIENTATION, GUIDE_STATE, GUIDE_TOOL_ACTION_NAME, GUIDE_TOOL_STATE, LINE_TOOL_ACTION_NAME, LINE_TOOL_DEFAULT_CONFIG, LINE_TOOL_STATE, MEASURE_TOOL_ACTION_NAME, MEASURE_TOOL_STATE, MOVE_ORIENTATION, MOVE_TOOL_ACTION_NAME, MOVE_TOOL_STATE, PEN_TOOL_ACTION_NAME, PEN_TOOL_STATE, RECTANGLE_TOOL_ACTION_NAME, RECTANGLE_TOOL_STATE, REGULAR_POLYGON_TOOL_ACTION_NAME, REGULAR_POLYGON_TOOL_STATE, SELECTION_TOOL_ACTION_NAME, SELECTION_TOOL_STATE, STAGE_MINIMAP_DEFAULT_CONFIG, STAR_TOOL_ACTION_NAME, STAR_TOOL_STATE, TEXT_LAYOUT, TEXT_TOOL_ACTION_NAME, TEXT_TOOL_STATE, VIDEO_TOOL_ACTION_NAME, VIDEO_TOOL_STATE, WEAVE_ARROW_NODE_TYPE, WEAVE_ARROW_TOOL_ACTION_NAME, WEAVE_ARROW_TOOL_STATE, WEAVE_COMMENTS_RENDERER_KEY, WEAVE_COMMENTS_TOOL_LAYER_ID, WEAVE_COMMENT_CREATE_ACTION, WEAVE_COMMENT_NODE_ACTION, WEAVE_COMMENT_NODE_DEFAULTS, WEAVE_COMMENT_NODE_TYPE, WEAVE_COMMENT_STATUS, WEAVE_COMMENT_TOOL_ACTION_NAME, WEAVE_COMMENT_TOOL_DEFAULT_CONFIG, WEAVE_COMMENT_TOOL_STATE, WEAVE_COMMENT_VIEW_ACTION, WEAVE_CONNECTOR_NODE_ANCHOR_ORIGIN, WEAVE_CONNECTOR_NODE_DECORATOR_TYPE, WEAVE_CONNECTOR_NODE_DEFAULT_CONFIG, WEAVE_CONNECTOR_NODE_LINE_ORIGIN, WEAVE_CONNECTOR_NODE_LINE_TYPE, WEAVE_CONNECTOR_NODE_TYPE, WEAVE_COPY_PASTE_CONFIG_DEFAULT, WEAVE_COPY_PASTE_NODES_KEY, WEAVE_COPY_PASTE_PASTE_CATCHER_ID, WEAVE_COPY_PASTE_PASTE_MODES, WEAVE_DEFAULT_USER_INFO_FUNCTION, WEAVE_ELLIPSE_NODE_TYPE, WEAVE_FRAME_DEFAULT_BACKGROUND_COLOR, WEAVE_FRAME_NODE_DEFAULT_CONFIG, WEAVE_FRAME_NODE_DEFAULT_PROPS, WEAVE_FRAME_NODE_TYPE, WEAVE_GRID_DEFAULT_CONFIG, WEAVE_GRID_DOT_TYPES, WEAVE_GRID_LAYER_ID, WEAVE_GRID_TYPES, WEAVE_GROUP_NODE_TYPE, WEAVE_IMAGES_TOOL_ACTION_NAME, WEAVE_IMAGES_TOOL_DEFAULT_CONFIG, WEAVE_IMAGES_TOOL_STATE, WEAVE_IMAGES_TOOL_UPLOAD_TYPE, WEAVE_IMAGE_CROP_ANCHOR_POSITION, WEAVE_IMAGE_CROP_END_TYPE, WEAVE_IMAGE_DEFAULT_CONFIG, WEAVE_IMAGE_NODE_TYPE, WEAVE_IMAGE_TOOL_ACTION_NAME, WEAVE_IMAGE_TOOL_CONFIG_DEFAULT, WEAVE_IMAGE_TOOL_STATE, WEAVE_IMAGE_TOOL_UPLOAD_TYPE, WEAVE_LAYER_NODE_TYPE, WEAVE_LINE_NODE_DEFAULT_CONFIG, WEAVE_LINE_NODE_TYPE, WEAVE_MEASURE_NODE_DEFAULT_CONFIG, WEAVE_MEASURE_NODE_TYPE, WEAVE_MEASURE_TOOL_DEFAULT_CONFIG, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_DEFAULT_CONFIG, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_KEY, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_LAYER_ID, WEAVE_NODES_SELECTION_DEFAULT_CONFIG, WEAVE_NODES_SELECTION_KEY, WEAVE_NODES_SELECTION_LAYER_ID, WEAVE_NODES_SNAPPING_PLUGIN_KEY, WEAVE_RECTANGLE_NODE_TYPE, WEAVE_REGULAR_POLYGON_NODE_TYPE, WEAVE_STAGE_DEFAULT_MODE, WEAVE_STAGE_DROP_AREA_KEY, WEAVE_STAGE_GRID_PLUGIN_KEY, WEAVE_STAGE_IMAGE_CROPPING_MODE, WEAVE_STAGE_KEYBOARD_MOVE_DEFAULT_CONFIG, WEAVE_STAGE_KEYBOARD_MOVE_KEY, WEAVE_STAGE_KEYBOARD_MOVE_ORIENTATION, WEAVE_STAGE_MINIMAP_KEY, WEAVE_STAGE_NODE_TYPE, WEAVE_STAGE_PANNING_DEFAULT_CONFIG, WEAVE_STAGE_PANNING_KEY, WEAVE_STAGE_PANNING_THROTTLE_MS, WEAVE_STAGE_TEXT_EDITION_MODE, WEAVE_STAGE_ZOOM_DEFAULT_CONFIG, WEAVE_STAGE_ZOOM_KEY, WEAVE_STAGE_ZOOM_TYPE, WEAVE_STAR_NODE_TYPE, WEAVE_STROKE_NODE_DEFAULT_CONFIG, WEAVE_STROKE_NODE_TYPE, WEAVE_STROKE_SINGLE_NODE_DEFAULT_CONFIG, WEAVE_STROKE_SINGLE_NODE_TIP_SIDE, WEAVE_STROKE_SINGLE_NODE_TIP_TYPE, WEAVE_STROKE_SINGLE_NODE_TYPE, WEAVE_STROKE_TOOL_ACTION_NAME, WEAVE_STROKE_TOOL_ACTION_NAME_ALIASES, WEAVE_STROKE_TOOL_DEFAULT_CONFIG, WEAVE_STROKE_TOOL_STATE, WEAVE_TEXT_NODE_DEFAULT_CONFIG, WEAVE_TEXT_NODE_TYPE, WEAVE_USERS_POINTERS_CONFIG_DEFAULT_PROPS, WEAVE_USERS_POINTERS_KEY, WEAVE_USERS_PRESENCE_CONFIG_DEFAULT_PROPS, WEAVE_USERS_PRESENCE_PLUGIN_KEY, WEAVE_USERS_SELECTION_KEY, WEAVE_USER_POINTER_KEY, WEAVE_USER_PRESENCE_KEY, WEAVE_USER_SELECTION_KEY, WEAVE_VIDEO_DEFAULT_CONFIG, WEAVE_VIDEO_NODE_TYPE, Weave, WeaveAction, WeaveAlignNodesToolAction, WeaveArrowNode, WeaveArrowToolAction, WeaveBrushToolAction, WeaveCommentNode, WeaveCommentToolAction, WeaveCommentsRendererPlugin, WeaveConnectedUsersPlugin, WeaveConnectorNode, WeaveConnectorToolAction, WeaveContextMenuPlugin, WeaveCopyPasteNodesPlugin, WeaveEllipseNode, WeaveEllipseToolAction, WeaveEraserToolAction, WeaveExportNodesToolAction, WeaveExportStageToolAction, WeaveFitToScreenToolAction, WeaveFitToSelectionToolAction, WeaveFrameNode, WeaveFrameToolAction, WeaveGroupNode, WeaveGuideToolAction, WeaveImageNode, WeaveImageToolAction, WeaveImagesToolAction, WeaveLayerNode, WeaveLineNode, WeaveLineToolAction, WeaveMeasureNode, WeaveMeasureToolAction, WeaveMoveToolAction, WeaveNode, WeaveNodesMultiSelectionFeedbackPlugin, WeaveNodesSelectionPlugin, WeaveNodesSnappingPlugin, WeavePenToolAction, WeavePlugin, WeaveRectangleNode, WeaveRectangleToolAction, WeaveRegularPolygonNode, WeaveRegularPolygonToolAction, WeaveRenderer, WeaveSelectionToolAction, WeaveStageDropAreaPlugin, WeaveStageGridPlugin, WeaveStageKeyboardMovePlugin, WeaveStageMinimapPlugin, WeaveStageNode, WeaveStagePanningPlugin, WeaveStageResizePlugin, WeaveStageZoomPlugin, WeaveStarNode, WeaveStarToolAction, WeaveStateManipulation, WeaveStore, WeaveStrokeNode, WeaveStrokeSingleNode, WeaveStrokeToolAction, WeaveTextNode, WeaveTextToolAction, WeaveUsersPointersPlugin, WeaveUsersPresencePlugin, WeaveUsersSelectionPlugin, WeaveVideoNode, WeaveVideoToolAction, WeaveZoomInToolAction, WeaveZoomOutToolAction, canComposite, clearContainerTargets, containerOverCursor, containsNodeDeep, defaultInitialState, downscaleImageFile, downscaleImageFromURL, getBoundingBox, getDownscaleRatio, getExportBoundingBox, getImageSizeFromFile, getJSONFromYjsBinary, getSelectedNodesMetadata, getStageClickPoint, getTargetAndSkipNodes, getTargetedNode, getTopmostShadowHost, getVisibleNodes, getVisibleNodesInViewport, hasFrames, hasImages, intersectArrays, isArray, isIOS, isInShadowDOM, isNodeInSelection, isNumber, isObject, isServer, loadImageSource, mapJsonToYjsArray, mapJsonToYjsElements, mapJsonToYjsMap, memoize, mergeExceptArrays, moveNodeToContainer, moveNodeToContainerNT, resetScale, weavejsToYjsBinary };
|
|
33139
|
+
export { ALIGN_NODES_ALIGN_TO, ALIGN_NODES_TOOL_ACTION_NAME, ALIGN_NODES_TOOL_STATE, BRUSH_TOOL_ACTION_NAME, BRUSH_TOOL_DEFAULT_CONFIG, BRUSH_TOOL_STATE, CONNECTOR_TOOL_ACTION_NAME, CONNECTOR_TOOL_DEFAULT_CONFIG, CONNECTOR_TOOL_STATE, COPY_PASTE_NODES_PLUGIN_STATE, DEFAULT_GUIDE_TOOL_ACTION_CONFIG, DEFAULT_SNAPPING_MANAGER_CONFIG, ELLIPSE_TOOL_ACTION_NAME, ELLIPSE_TOOL_STATE, ERASER_TOOL_ACTION_NAME, ERASER_TOOL_STATE, FRAME_TOOL_ACTION_NAME, FRAME_TOOL_STATE, GUIDE_DISTANCE_NAME, GUIDE_DISTANCE_ORIGIN, GUIDE_KIND, GUIDE_NAME, GUIDE_ORIENTATION, GUIDE_STATE, GUIDE_TOOL_ACTION_NAME, GUIDE_TOOL_STATE, LINE_TOOL_ACTION_NAME, LINE_TOOL_DEFAULT_CONFIG, LINE_TOOL_STATE, MEASURE_TOOL_ACTION_NAME, MEASURE_TOOL_STATE, MOVE_ORIENTATION, MOVE_TOOL_ACTION_NAME, MOVE_TOOL_STATE, PEN_TOOL_ACTION_NAME, PEN_TOOL_STATE, POLYGON_TOOL_ACTION_NAME, POLYGON_TOOL_STATE, RECTANGLE_TOOL_ACTION_NAME, RECTANGLE_TOOL_STATE, REGULAR_POLYGON_TOOL_ACTION_NAME, REGULAR_POLYGON_TOOL_STATE, SELECTION_TOOL_ACTION_NAME, SELECTION_TOOL_STATE, STAGE_MINIMAP_DEFAULT_CONFIG, STAR_TOOL_ACTION_NAME, STAR_TOOL_STATE, TEXT_LAYOUT, TEXT_TOOL_ACTION_NAME, TEXT_TOOL_STATE, VIDEO_TOOL_ACTION_NAME, VIDEO_TOOL_STATE, WEAVE_ARROW_NODE_TYPE, WEAVE_ARROW_TOOL_ACTION_NAME, WEAVE_ARROW_TOOL_STATE, WEAVE_COMMENTS_RENDERER_KEY, WEAVE_COMMENTS_TOOL_LAYER_ID, WEAVE_COMMENT_CREATE_ACTION, WEAVE_COMMENT_NODE_ACTION, WEAVE_COMMENT_NODE_DEFAULTS, WEAVE_COMMENT_NODE_TYPE, WEAVE_COMMENT_STATUS, WEAVE_COMMENT_TOOL_ACTION_NAME, WEAVE_COMMENT_TOOL_DEFAULT_CONFIG, WEAVE_COMMENT_TOOL_STATE, WEAVE_COMMENT_VIEW_ACTION, WEAVE_CONNECTOR_NODE_ANCHOR_ORIGIN, WEAVE_CONNECTOR_NODE_DECORATOR_TYPE, WEAVE_CONNECTOR_NODE_DEFAULT_CONFIG, WEAVE_CONNECTOR_NODE_LINE_ORIGIN, WEAVE_CONNECTOR_NODE_LINE_TYPE, WEAVE_CONNECTOR_NODE_TYPE, WEAVE_COPY_PASTE_CONFIG_DEFAULT, WEAVE_COPY_PASTE_NODES_KEY, WEAVE_COPY_PASTE_PASTE_CATCHER_ID, WEAVE_COPY_PASTE_PASTE_MODES, WEAVE_DEFAULT_USER_INFO_FUNCTION, WEAVE_ELLIPSE_NODE_TYPE, WEAVE_FRAME_DEFAULT_BACKGROUND_COLOR, WEAVE_FRAME_NODE_DEFAULT_CONFIG, WEAVE_FRAME_NODE_DEFAULT_PROPS, WEAVE_FRAME_NODE_TYPE, WEAVE_GRID_DEFAULT_CONFIG, WEAVE_GRID_DOT_TYPES, WEAVE_GRID_LAYER_ID, WEAVE_GRID_TYPES, WEAVE_GROUP_NODE_TYPE, WEAVE_IMAGES_TOOL_ACTION_NAME, WEAVE_IMAGES_TOOL_DEFAULT_CONFIG, WEAVE_IMAGES_TOOL_STATE, WEAVE_IMAGES_TOOL_UPLOAD_TYPE, WEAVE_IMAGE_CROP_ANCHOR_POSITION, WEAVE_IMAGE_CROP_END_TYPE, WEAVE_IMAGE_DEFAULT_CONFIG, WEAVE_IMAGE_NODE_TYPE, WEAVE_IMAGE_TOOL_ACTION_NAME, WEAVE_IMAGE_TOOL_CONFIG_DEFAULT, WEAVE_IMAGE_TOOL_STATE, WEAVE_IMAGE_TOOL_UPLOAD_TYPE, WEAVE_LAYER_NODE_TYPE, WEAVE_LINE_NODE_DEFAULT_CONFIG, WEAVE_LINE_NODE_TYPE, WEAVE_MEASURE_NODE_DEFAULT_CONFIG, WEAVE_MEASURE_NODE_TYPE, WEAVE_MEASURE_TOOL_DEFAULT_CONFIG, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_DEFAULT_CONFIG, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_KEY, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_LAYER_ID, WEAVE_NODES_SELECTION_DEFAULT_CONFIG, WEAVE_NODES_SELECTION_KEY, WEAVE_NODES_SELECTION_LAYER_ID, WEAVE_NODES_SNAPPING_PLUGIN_KEY, WEAVE_POLYGON_NODE_TYPE, WEAVE_POLYGON_PRESETS, WEAVE_RECTANGLE_NODE_TYPE, WEAVE_REGULAR_POLYGON_NODE_TYPE, WEAVE_SHAPE_LABEL_DEFAULTS, WEAVE_STAGE_DEFAULT_MODE, WEAVE_STAGE_DROP_AREA_KEY, WEAVE_STAGE_GRID_PLUGIN_KEY, WEAVE_STAGE_IMAGE_CROPPING_MODE, WEAVE_STAGE_KEYBOARD_MOVE_DEFAULT_CONFIG, WEAVE_STAGE_KEYBOARD_MOVE_KEY, WEAVE_STAGE_KEYBOARD_MOVE_ORIENTATION, WEAVE_STAGE_MINIMAP_KEY, WEAVE_STAGE_NODE_TYPE, WEAVE_STAGE_PANNING_DEFAULT_CONFIG, WEAVE_STAGE_PANNING_KEY, WEAVE_STAGE_PANNING_THROTTLE_MS, WEAVE_STAGE_SHAPE_LABEL_EDITION_MODE, WEAVE_STAGE_TEXT_EDITION_MODE, WEAVE_STAGE_ZOOM_DEFAULT_CONFIG, WEAVE_STAGE_ZOOM_KEY, WEAVE_STAGE_ZOOM_TYPE, WEAVE_STAR_NODE_TYPE, WEAVE_STROKE_NODE_DEFAULT_CONFIG, WEAVE_STROKE_NODE_TYPE, WEAVE_STROKE_SINGLE_NODE_DEFAULT_CONFIG, WEAVE_STROKE_SINGLE_NODE_TIP_SIDE, WEAVE_STROKE_SINGLE_NODE_TIP_TYPE, WEAVE_STROKE_SINGLE_NODE_TYPE, WEAVE_STROKE_TOOL_ACTION_NAME, WEAVE_STROKE_TOOL_ACTION_NAME_ALIASES, WEAVE_STROKE_TOOL_DEFAULT_CONFIG, WEAVE_STROKE_TOOL_STATE, WEAVE_TEXT_NODE_DEFAULT_CONFIG, WEAVE_TEXT_NODE_TYPE, WEAVE_USERS_POINTERS_CONFIG_DEFAULT_PROPS, WEAVE_USERS_POINTERS_KEY, WEAVE_USERS_PRESENCE_CONFIG_DEFAULT_PROPS, WEAVE_USERS_PRESENCE_PLUGIN_KEY, WEAVE_USERS_SELECTION_KEY, WEAVE_USER_POINTER_KEY, WEAVE_USER_PRESENCE_KEY, WEAVE_USER_SELECTION_KEY, WEAVE_VIDEO_DEFAULT_CONFIG, WEAVE_VIDEO_NODE_TYPE, Weave, WeaveAction, WeaveAlignNodesToolAction, WeaveArrowNode, WeaveArrowToolAction, WeaveBrushToolAction, WeaveCommentNode, WeaveCommentToolAction, WeaveCommentsRendererPlugin, WeaveConnectedUsersPlugin, WeaveConnectorNode, WeaveConnectorToolAction, WeaveContextMenuPlugin, WeaveCopyPasteNodesPlugin, WeaveEllipseNode, WeaveEllipseToolAction, WeaveEraserToolAction, WeaveExportNodesToolAction, WeaveExportStageToolAction, WeaveFitToScreenToolAction, WeaveFitToSelectionToolAction, WeaveFrameNode, WeaveFrameToolAction, WeaveGroupNode, WeaveGuideToolAction, WeaveImageNode, WeaveImageToolAction, WeaveImagesToolAction, WeaveLayerNode, WeaveLineNode, WeaveLineToolAction, WeaveMeasureNode, WeaveMeasureToolAction, WeaveMoveToolAction, WeaveNode, WeaveNodesMultiSelectionFeedbackPlugin, WeaveNodesSelectionPlugin, WeaveNodesSnappingPlugin, WeavePenToolAction, WeavePlugin, WeavePolygonNode, WeavePolygonToolAction, WeaveRectangleNode, WeaveRectangleToolAction, WeaveRegularPolygonNode, WeaveRegularPolygonToolAction, WeaveRenderer, WeaveSelectionToolAction, WeaveStageDropAreaPlugin, WeaveStageGridPlugin, WeaveStageKeyboardMovePlugin, WeaveStageMinimapPlugin, WeaveStageNode, WeaveStagePanningPlugin, WeaveStageResizePlugin, WeaveStageZoomPlugin, WeaveStarNode, WeaveStarToolAction, WeaveStateManipulation, WeaveStore, WeaveStrokeNode, WeaveStrokeSingleNode, WeaveStrokeToolAction, WeaveTextNode, WeaveTextToolAction, WeaveUsersPointersPlugin, WeaveUsersPresencePlugin, WeaveUsersSelectionPlugin, WeaveVideoNode, WeaveVideoToolAction, WeaveZoomInToolAction, WeaveZoomOutToolAction, buildAncestorGroupIds, canComposite, clearContainerTargets, computeEllipseLabelMinSize, computePolygonLabelMinSize, computeRectangleLabelMinSize, containerOverCursor, containsNodeDeep, defaultInitialState, downscaleImageFile, downscaleImageFromURL, getBoundingBox, getDownscaleRatio, getExportBoundingBox, getImageSizeFromFile, getJSONFromYjsBinary, getSelectedNodesMetadata, getShapeLabelSchemaFields, getStageClickPoint, getTargetAndSkipNodes, getTargetedNode, getTopmostShadowHost, getVisibleNodes, getVisibleNodesInViewport, hasFrames, hasImages, instantiatePreset, intersectArrays, isArray, isIOS, isInShadowDOM, isNodeInSelection, isNumber, isObject, isServer, labelId, loadImageSource, mapJsonToYjsArray, mapJsonToYjsElements, mapJsonToYjsMap, memoize, mergeExceptArrays, moveNodeToContainer, moveNodeToContainerNT, resetScale, spreadLabelProps, weavejsToYjsBinary };
|