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