@inditextech/weave-sdk 5.0.0-SNAPSHOT.377.1 → 5.0.0-SNAPSHOT.397.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 +1985 -141
- package/dist/sdk.node.js +1985 -141
- package/dist/sdk.node.stats.html +1 -1
- package/dist/sdk.stats.html +1 -1
- package/dist/types.d.ts +297 -29
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1985 -141
- package/dist/types.js.map +1 -1
- package/dist/types.stats.html +1 -1
- package/package.json +2 -2
package/dist/sdk.js
CHANGED
|
@@ -4356,6 +4356,7 @@ var TransformerController = class {
|
|
|
4356
4356
|
listening: true,
|
|
4357
4357
|
shouldOverdrawWholeArea: true
|
|
4358
4358
|
});
|
|
4359
|
+
this.tr.boundBoxFunc(this.getBoundBoxFunc());
|
|
4359
4360
|
layer.add(this.tr);
|
|
4360
4361
|
this.trHover = new Konva.Transformer({
|
|
4361
4362
|
id: "hoverTransformer",
|
|
@@ -4371,6 +4372,20 @@ var TransformerController = class {
|
|
|
4371
4372
|
this.registerTransformerEvents();
|
|
4372
4373
|
this.registerInstanceEvents();
|
|
4373
4374
|
}
|
|
4375
|
+
getBoundBoxFunc() {
|
|
4376
|
+
return (oldBox, newBox) => {
|
|
4377
|
+
const sx = newBox.width / oldBox.width;
|
|
4378
|
+
const sy = newBox.height / oldBox.height;
|
|
4379
|
+
const violatesConstraint = this.tr.nodes().some((node) => {
|
|
4380
|
+
const rect = node.getClientRect({ skipStroke: true });
|
|
4381
|
+
const { width: minWidth, height: minHeight } = node.getNodeMinSize();
|
|
4382
|
+
if (["middle-right", "middle-left"].includes(this.tr.getActiveAnchor() ?? "")) return rect.width * sx < minWidth;
|
|
4383
|
+
if (["top-center", "bottom-center"].includes(this.tr.getActiveAnchor() ?? "")) return rect.height * sy < minHeight;
|
|
4384
|
+
return rect.width * sx < minWidth || rect.height * sy < minHeight;
|
|
4385
|
+
});
|
|
4386
|
+
return violatesConstraint ? oldBox : newBox;
|
|
4387
|
+
};
|
|
4388
|
+
}
|
|
4374
4389
|
getTransformer() {
|
|
4375
4390
|
return this.tr;
|
|
4376
4391
|
}
|
|
@@ -4835,9 +4850,10 @@ function handleClickOrTap(ctx, e) {
|
|
|
4835
4850
|
const isMainLayer = parent === mainLayer;
|
|
4836
4851
|
const isContainerEmptyArea = e.target.getAttrs().isContainerPrincipal !== void 0 && !e.target.getAttrs().isContainerPrincipal;
|
|
4837
4852
|
if (isStage || isMainLayer || isContainerEmptyArea) ctx.setSelectedNodes([]);
|
|
4853
|
+
ctx.triggerSelectedNodesEvent();
|
|
4838
4854
|
return;
|
|
4839
4855
|
}
|
|
4840
|
-
if (nodeTargeted.getAttrs().nodeId) {
|
|
4856
|
+
if (!nodeTargeted.getAttrs().name?.includes("node") && nodeTargeted.getAttrs().nodeId) {
|
|
4841
4857
|
const realNode = stage.findOne(`#${nodeTargeted.getAttrs().nodeId}`);
|
|
4842
4858
|
if (realNode) nodeTargeted = realNode;
|
|
4843
4859
|
}
|
|
@@ -4950,6 +4966,7 @@ function handlePointerDown(ctx, e) {
|
|
|
4950
4966
|
for (const node of nodesSelected) node.fire("onSelectionCleared", { bubbles: true });
|
|
4951
4967
|
}
|
|
4952
4968
|
ctx.selectNone();
|
|
4969
|
+
ctx.triggerSelectedNodesEvent();
|
|
4953
4970
|
ctx.getWeaveInstance().emitEvent("onSelectionState", true);
|
|
4954
4971
|
ctx.getEdgePanning().start();
|
|
4955
4972
|
}
|
|
@@ -5432,6 +5449,9 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
|
|
|
5432
5449
|
isDragging() {
|
|
5433
5450
|
return this.transformerCtrl.isDragging();
|
|
5434
5451
|
}
|
|
5452
|
+
getBoundBoxFunc() {
|
|
5453
|
+
return this.transformerCtrl.getBoundBoxFunc();
|
|
5454
|
+
}
|
|
5435
5455
|
getSelectorConfig() {
|
|
5436
5456
|
return this.config.selection;
|
|
5437
5457
|
}
|
|
@@ -6006,6 +6026,12 @@ const augmentKonvaNodeClass = (config) => {
|
|
|
6006
6026
|
};
|
|
6007
6027
|
Konva.Node.prototype.lockMutex = function() {};
|
|
6008
6028
|
Konva.Node.prototype.releaseMutex = function() {};
|
|
6029
|
+
Konva.Node.prototype.getNodeMinSize = function() {
|
|
6030
|
+
return {
|
|
6031
|
+
width: 0,
|
|
6032
|
+
height: 0
|
|
6033
|
+
};
|
|
6034
|
+
};
|
|
6009
6035
|
};
|
|
6010
6036
|
var WeaveNode = class {
|
|
6011
6037
|
async register(instance) {
|
|
@@ -6169,8 +6195,8 @@ var WeaveNode = class {
|
|
|
6169
6195
|
if (selectionPlugin?.getSelectedNodes().map((node) => node.getAttrs().id).includes(ele.getAttrs().id)) return true;
|
|
6170
6196
|
return false;
|
|
6171
6197
|
}
|
|
6172
|
-
scaleReset(node) {
|
|
6173
|
-
const scale = node.scale();
|
|
6198
|
+
scaleReset(node, scaleCustom) {
|
|
6199
|
+
const scale = scaleCustom ?? node.scale();
|
|
6174
6200
|
node.width(Math.max(5, node.width() * scale.x));
|
|
6175
6201
|
node.height(Math.max(5, node.height() * scale.y));
|
|
6176
6202
|
node.scale({
|
|
@@ -6260,8 +6286,6 @@ var WeaveNode = class {
|
|
|
6260
6286
|
if (e.target.getAttrs()._revertStrokeScaleEnabled === true) e.target.setAttr("strokeScaleEnabled", true);
|
|
6261
6287
|
e.target.setAttr("_revertStrokeScaleEnabled", void 0);
|
|
6262
6288
|
this.instance.emitEvent("onTransform", null);
|
|
6263
|
-
const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
6264
|
-
if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
|
|
6265
6289
|
if (performScaleReset) this.scaleReset(node$1);
|
|
6266
6290
|
if (this.getSelectionPlugin()?.getSelectedNodes().length === 1) {
|
|
6267
6291
|
this.getNodesSelectionFeedbackPlugin()?.showSelectionHalo(node$1);
|
|
@@ -6270,8 +6294,13 @@ var WeaveNode = class {
|
|
|
6270
6294
|
const nodeHandler = this.instance.getNodeHandler(node$1.getAttrs().nodeType);
|
|
6271
6295
|
if (nodeHandler) {
|
|
6272
6296
|
const shouldUpdateOnTransform = node$1.getAttrs().shouldUpdateOnTransform ?? true;
|
|
6273
|
-
if (shouldUpdateOnTransform)
|
|
6297
|
+
if (shouldUpdateOnTransform) {
|
|
6298
|
+
const serializedNode = nodeHandler.serialize(node$1);
|
|
6299
|
+
this.instance.updateNode(serializedNode);
|
|
6300
|
+
}
|
|
6274
6301
|
}
|
|
6302
|
+
const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
6303
|
+
if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
|
|
6275
6304
|
this.getNodesSelectionPlugin()?.getHoverTransformer().forceUpdate();
|
|
6276
6305
|
});
|
|
6277
6306
|
const stage = this.instance.getStage();
|
|
@@ -8416,7 +8445,11 @@ var WeaveGroupsManager = class {
|
|
|
8416
8445
|
this.instance.removeNodes(sortedNodesByZIndex);
|
|
8417
8446
|
groupInstance.destroy();
|
|
8418
8447
|
const groupNode = stage.findOne(`#${groupId}`);
|
|
8419
|
-
if (groupHandler && groupNode)
|
|
8448
|
+
if (groupHandler && groupNode) {
|
|
8449
|
+
groupNode.x(0);
|
|
8450
|
+
groupNode.y(0);
|
|
8451
|
+
this.instance.updateNodeNT(groupHandler.serialize(groupNode));
|
|
8452
|
+
}
|
|
8420
8453
|
setTimeout(() => {
|
|
8421
8454
|
this.getNodesMultiSelectionFeedbackPlugin()?.cleanupSelectedHalos();
|
|
8422
8455
|
const groupNode$1 = stage.findOne(`#${groupId}`);
|
|
@@ -8478,6 +8511,8 @@ var WeaveGroupsManager = class {
|
|
|
8478
8511
|
y: absScale.y / stage.scaleY()
|
|
8479
8512
|
});
|
|
8480
8513
|
child.rotation(absRotation);
|
|
8514
|
+
const nodeHandler = this.instance.getNodeHandler(child.getAttrs().nodeType);
|
|
8515
|
+
if (nodeHandler) nodeHandler.scaleReset(child);
|
|
8481
8516
|
child.zIndex(newLayerChildrenAmount - 1 + child.zIndex());
|
|
8482
8517
|
child.setAttr("draggable", true);
|
|
8483
8518
|
newChildId = child.getAttrs().id;
|
|
@@ -9288,6 +9323,7 @@ var WeaveStateManager = class {
|
|
|
9288
9323
|
}
|
|
9289
9324
|
const yjsProps = yjsNode.get("props");
|
|
9290
9325
|
this.updateYjsMapFromObject(yjsProps, node.props);
|
|
9326
|
+
if (Array.isArray(node.props.children) && node.props.children.length > 0) for (const child of node.props.children) this.updateNode(child);
|
|
9291
9327
|
this.instance.emitEvent("onNodeUpdated", node);
|
|
9292
9328
|
}
|
|
9293
9329
|
updateNodes(nodes) {
|
|
@@ -9482,7 +9518,7 @@ var WeaveRegisterManager = class {
|
|
|
9482
9518
|
|
|
9483
9519
|
//#endregion
|
|
9484
9520
|
//#region package.json
|
|
9485
|
-
var version = "5.0.0-SNAPSHOT.
|
|
9521
|
+
var version = "5.0.0-SNAPSHOT.397.1";
|
|
9486
9522
|
|
|
9487
9523
|
//#endregion
|
|
9488
9524
|
//#region src/managers/setup.ts
|
|
@@ -11871,10 +11907,36 @@ var WeaveGroupNode = class extends WeaveNode {
|
|
|
11871
11907
|
return intersectArrays(anchorsArrays);
|
|
11872
11908
|
};
|
|
11873
11909
|
this.setupDefaultNodeEvents(group);
|
|
11910
|
+
group.on("transform", () => {
|
|
11911
|
+
const sx = group.scaleX();
|
|
11912
|
+
const sy = group.scaleY();
|
|
11913
|
+
group.getChildren().forEach((child) => {
|
|
11914
|
+
child.scaleX(child.scaleX() * sx);
|
|
11915
|
+
child.scaleY(child.scaleY() * sy);
|
|
11916
|
+
child.x(child.x() * sx);
|
|
11917
|
+
child.y(child.y() * sy);
|
|
11918
|
+
const nodeHandler = this.instance.getNodeHandler(child.getAttrs().nodeType);
|
|
11919
|
+
if (nodeHandler) {
|
|
11920
|
+
nodeHandler.scaleReset(child);
|
|
11921
|
+
nodeHandler.onUpdate(child, child.getAttrs());
|
|
11922
|
+
}
|
|
11923
|
+
});
|
|
11924
|
+
group.scale({
|
|
11925
|
+
x: 1,
|
|
11926
|
+
y: 1
|
|
11927
|
+
});
|
|
11928
|
+
});
|
|
11874
11929
|
return group;
|
|
11875
11930
|
}
|
|
11876
11931
|
onUpdate(nodeInstance, nextProps) {
|
|
11877
|
-
nodeInstance.setAttrs({
|
|
11932
|
+
nodeInstance.setAttrs({
|
|
11933
|
+
...nextProps,
|
|
11934
|
+
x: nextProps.x ?? 0,
|
|
11935
|
+
y: nextProps.y ?? 0,
|
|
11936
|
+
scaleX: nextProps.scaleX ?? 1,
|
|
11937
|
+
scaleY: nextProps.scaleY ?? 1,
|
|
11938
|
+
rotation: nextProps.rotation ?? 0
|
|
11939
|
+
});
|
|
11878
11940
|
const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
11879
11941
|
if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
|
|
11880
11942
|
}
|
|
@@ -11911,18 +11973,571 @@ var WeaveGroupNode = class extends WeaveNode {
|
|
|
11911
11973
|
}
|
|
11912
11974
|
};
|
|
11913
11975
|
}
|
|
11914
|
-
scaleReset() {
|
|
11976
|
+
scaleReset(node) {
|
|
11977
|
+
const sx = node.scaleX();
|
|
11978
|
+
const sy = node.scaleY();
|
|
11979
|
+
node.getChildren().forEach((child) => {
|
|
11980
|
+
child.scaleX(child.scaleX() * sx);
|
|
11981
|
+
child.scaleY(child.scaleY() * sy);
|
|
11982
|
+
child.x(child.x() * sx);
|
|
11983
|
+
child.y(child.y() * sy);
|
|
11984
|
+
const nodeHandler = this.instance.getNodeHandler(child.getAttrs().nodeType);
|
|
11985
|
+
if (nodeHandler) {
|
|
11986
|
+
nodeHandler.scaleReset(child);
|
|
11987
|
+
nodeHandler.onUpdate(child, child.getAttrs());
|
|
11988
|
+
}
|
|
11989
|
+
});
|
|
11990
|
+
node.scale({
|
|
11991
|
+
x: 1,
|
|
11992
|
+
y: 1
|
|
11993
|
+
});
|
|
11994
|
+
}
|
|
11915
11995
|
};
|
|
11916
11996
|
|
|
11917
11997
|
//#endregion
|
|
11918
11998
|
//#region src/nodes/rectangle/constants.ts
|
|
11919
11999
|
const WEAVE_RECTANGLE_NODE_TYPE = "rectangle";
|
|
11920
12000
|
|
|
12001
|
+
//#endregion
|
|
12002
|
+
//#region src/nodes/shared/shape-label.constants.ts
|
|
12003
|
+
const WEAVE_STAGE_SHAPE_LABEL_EDITION_MODE = "shape-label-edition";
|
|
12004
|
+
const WEAVE_SHAPE_LABEL_DEFAULTS = {
|
|
12005
|
+
labelText: "",
|
|
12006
|
+
labelFontFamily: "Arial, sans-serif",
|
|
12007
|
+
labelFontSize: 14,
|
|
12008
|
+
labelFontStyle: "normal",
|
|
12009
|
+
labelFontVariant: "normal",
|
|
12010
|
+
labelTextDecoration: "",
|
|
12011
|
+
labelFill: "#000000",
|
|
12012
|
+
labelAlign: "center",
|
|
12013
|
+
labelVerticalAlign: "middle",
|
|
12014
|
+
labelLetterSpacing: 0,
|
|
12015
|
+
labelLineHeight: 1,
|
|
12016
|
+
labelPaddingX: 8,
|
|
12017
|
+
labelPaddingY: 8
|
|
12018
|
+
};
|
|
12019
|
+
const labelId = (id) => `${id}-label`;
|
|
12020
|
+
|
|
12021
|
+
//#endregion
|
|
12022
|
+
//#region src/nodes/shared/shape-label-editor.ts
|
|
12023
|
+
var WeaveShapeLabelEditor = class {
|
|
12024
|
+
editing = false;
|
|
12025
|
+
editingGroup = null;
|
|
12026
|
+
editingTextBounds = null;
|
|
12027
|
+
textArea = null;
|
|
12028
|
+
onLiveResize = null;
|
|
12029
|
+
constructor(instance) {
|
|
12030
|
+
this.instance = instance;
|
|
12031
|
+
}
|
|
12032
|
+
isEditing() {
|
|
12033
|
+
return this.editing;
|
|
12034
|
+
}
|
|
12035
|
+
renderLabel(group, props, textBounds) {
|
|
12036
|
+
const labelText = props.labelText ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelText;
|
|
12037
|
+
const labelNode = new Konva.Text({
|
|
12038
|
+
id: labelId(props.id),
|
|
12039
|
+
x: textBounds.x,
|
|
12040
|
+
y: textBounds.y,
|
|
12041
|
+
width: textBounds.width,
|
|
12042
|
+
height: textBounds.height,
|
|
12043
|
+
text: labelText,
|
|
12044
|
+
fontFamily: props.labelFontFamily ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontFamily,
|
|
12045
|
+
fontSize: props.labelFontSize ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontSize,
|
|
12046
|
+
fontStyle: props.labelFontStyle ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontStyle,
|
|
12047
|
+
fontVariant: props.labelFontVariant ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontVariant,
|
|
12048
|
+
textDecoration: props.labelTextDecoration ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelTextDecoration,
|
|
12049
|
+
fill: props.labelFill ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFill,
|
|
12050
|
+
align: props.labelAlign ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelAlign,
|
|
12051
|
+
verticalAlign: props.labelVerticalAlign ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelVerticalAlign,
|
|
12052
|
+
letterSpacing: props.labelLetterSpacing ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelLetterSpacing,
|
|
12053
|
+
lineHeight: props.labelLineHeight ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelLineHeight,
|
|
12054
|
+
wrap: "word",
|
|
12055
|
+
listening: false,
|
|
12056
|
+
visible: labelText !== ""
|
|
12057
|
+
});
|
|
12058
|
+
group.add(labelNode);
|
|
12059
|
+
return labelNode;
|
|
12060
|
+
}
|
|
12061
|
+
updateLabel(group, nextProps, textBounds, growCallback) {
|
|
12062
|
+
const labelNode = group.findOne(`#${labelId(nextProps.id)}`);
|
|
12063
|
+
if (!labelNode) return;
|
|
12064
|
+
const labelText = nextProps.labelText ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelText;
|
|
12065
|
+
labelNode.setAttrs({
|
|
12066
|
+
x: textBounds.x,
|
|
12067
|
+
y: textBounds.y,
|
|
12068
|
+
width: textBounds.width,
|
|
12069
|
+
height: textBounds.height,
|
|
12070
|
+
text: labelText,
|
|
12071
|
+
fontFamily: nextProps.labelFontFamily ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontFamily,
|
|
12072
|
+
fontSize: nextProps.labelFontSize ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontSize,
|
|
12073
|
+
fontStyle: nextProps.labelFontStyle ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontStyle,
|
|
12074
|
+
fontVariant: nextProps.labelFontVariant ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontVariant,
|
|
12075
|
+
textDecoration: nextProps.labelTextDecoration ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelTextDecoration,
|
|
12076
|
+
fill: nextProps.labelFill ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFill,
|
|
12077
|
+
align: nextProps.labelAlign ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelAlign,
|
|
12078
|
+
verticalAlign: nextProps.labelVerticalAlign ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelVerticalAlign,
|
|
12079
|
+
letterSpacing: nextProps.labelLetterSpacing ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelLetterSpacing,
|
|
12080
|
+
lineHeight: nextProps.labelLineHeight ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelLineHeight,
|
|
12081
|
+
wrap: "word",
|
|
12082
|
+
visible: !this.editing && labelText !== ""
|
|
12083
|
+
});
|
|
12084
|
+
if (labelText !== "") {
|
|
12085
|
+
labelNode.setAttr("height", void 0);
|
|
12086
|
+
const measuredHeight = labelNode.height();
|
|
12087
|
+
labelNode.height(Math.max(textBounds.height, measuredHeight));
|
|
12088
|
+
if (growCallback && measuredHeight > textBounds.height) {
|
|
12089
|
+
const paddingY = nextProps.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
12090
|
+
growCallback(measuredHeight + paddingY * 2);
|
|
12091
|
+
}
|
|
12092
|
+
}
|
|
12093
|
+
}
|
|
12094
|
+
computeVerticalOffset(verticalAlign, boundsHeightPx, contentHeightPx) {
|
|
12095
|
+
if (verticalAlign === "top") return 0;
|
|
12096
|
+
if (verticalAlign === "bottom") return Math.max(0, boundsHeightPx - contentHeightPx);
|
|
12097
|
+
return Math.max(0, (boundsHeightPx - contentHeightPx) / 2);
|
|
12098
|
+
}
|
|
12099
|
+
triggerEditMode(group, textBounds, onCommit, onLiveResize) {
|
|
12100
|
+
if (this.editing) return;
|
|
12101
|
+
const lockAcquired = this.instance.setMutexLock({
|
|
12102
|
+
nodeIds: [group.id()],
|
|
12103
|
+
operation: "label-edit"
|
|
12104
|
+
});
|
|
12105
|
+
if (!lockAcquired) return;
|
|
12106
|
+
this.editing = true;
|
|
12107
|
+
this.editingGroup = group;
|
|
12108
|
+
this.editingTextBounds = textBounds;
|
|
12109
|
+
this.onLiveResize = onLiveResize ?? null;
|
|
12110
|
+
const labelNode = group.findOne(`#${labelId(group.id())}`);
|
|
12111
|
+
if (labelNode) labelNode.visible(false);
|
|
12112
|
+
const selectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
12113
|
+
if (selectionPlugin) {
|
|
12114
|
+
const tr = selectionPlugin.getTransformer();
|
|
12115
|
+
this.instance.disablePlugin("nodesSelection");
|
|
12116
|
+
tr.hide();
|
|
12117
|
+
}
|
|
12118
|
+
const stage = this.instance.getStage();
|
|
12119
|
+
const upscaleScale = stage.getAttr("upscaleScale") ?? 1;
|
|
12120
|
+
const absoluteTransform = group.getAbsoluteTransform();
|
|
12121
|
+
const topLeft = absoluteTransform.point({
|
|
12122
|
+
x: textBounds.x,
|
|
12123
|
+
y: textBounds.y
|
|
12124
|
+
});
|
|
12125
|
+
this.createTextAreaDOM(group, textBounds, topLeft, upscaleScale, onCommit, onLiveResize);
|
|
12126
|
+
this.instance.getStage().mode(WEAVE_STAGE_SHAPE_LABEL_EDITION_MODE);
|
|
12127
|
+
}
|
|
12128
|
+
exitEditMode() {
|
|
12129
|
+
if (!this.editing) return;
|
|
12130
|
+
this.instance.releaseMutexLock();
|
|
12131
|
+
this.instance.getStage().mode(WEAVE_STAGE_DEFAULT_MODE);
|
|
12132
|
+
this.editing = false;
|
|
12133
|
+
if (this.editingGroup) {
|
|
12134
|
+
const liveGroup = this.instance.getStage().findOne(`#${this.editingGroup.id()}`);
|
|
12135
|
+
const labelNode = liveGroup?.findOne(`#${labelId(this.editingGroup.id())}`);
|
|
12136
|
+
if (labelNode) {
|
|
12137
|
+
labelNode.visible(true);
|
|
12138
|
+
labelNode.getLayer()?.batchDraw();
|
|
12139
|
+
}
|
|
12140
|
+
this.editingGroup = null;
|
|
12141
|
+
}
|
|
12142
|
+
if (this.textArea) this.textArea.remove();
|
|
12143
|
+
this.textArea = null;
|
|
12144
|
+
this.onLiveResize = null;
|
|
12145
|
+
this.editingTextBounds = null;
|
|
12146
|
+
this.instance.getStage().off(".weaveLabelEdit");
|
|
12147
|
+
const selectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
12148
|
+
if (selectionPlugin) this.instance.enablePlugin("nodesSelection");
|
|
12149
|
+
}
|
|
12150
|
+
updateTextAreaPosition(group, textBounds) {
|
|
12151
|
+
if (!this.editing || !this.textArea) return;
|
|
12152
|
+
const stage = this.instance.getStage();
|
|
12153
|
+
const upscaleScale = stage.getAttr("upscaleScale") ?? 1;
|
|
12154
|
+
const absoluteTransform = group.getAbsoluteTransform();
|
|
12155
|
+
const topLeft = absoluteTransform.point({
|
|
12156
|
+
x: textBounds.x,
|
|
12157
|
+
y: textBounds.y
|
|
12158
|
+
});
|
|
12159
|
+
this.textArea.style.left = `${topLeft.x * upscaleScale}px`;
|
|
12160
|
+
const absScale = group.getAbsoluteScale();
|
|
12161
|
+
const props = group.getAttrs();
|
|
12162
|
+
const fontSize = (props.labelFontSize ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontSize) * absScale.x;
|
|
12163
|
+
this.textArea.style.fontSize = `${fontSize * upscaleScale}px`;
|
|
12164
|
+
const textWidth = textBounds.width * absScale.x;
|
|
12165
|
+
this.textArea.style.width = `${textWidth * upscaleScale}px`;
|
|
12166
|
+
const originalBoundsHeightPx = textBounds.height * absScale.y * upscaleScale;
|
|
12167
|
+
const paddingY = props.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
12168
|
+
const verticalAlign = props.labelVerticalAlign ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelVerticalAlign;
|
|
12169
|
+
this.textArea.style.height = "auto";
|
|
12170
|
+
const contentHeightPx = this.textArea.scrollHeight;
|
|
12171
|
+
if (contentHeightPx <= originalBoundsHeightPx) {
|
|
12172
|
+
this.textArea.style.height = `${contentHeightPx}px`;
|
|
12173
|
+
const offsetY = this.computeVerticalOffset(verticalAlign, originalBoundsHeightPx, contentHeightPx);
|
|
12174
|
+
this.textArea.style.top = `${topLeft.y * upscaleScale + offsetY}px`;
|
|
12175
|
+
} else {
|
|
12176
|
+
this.textArea.style.height = `${contentHeightPx}px`;
|
|
12177
|
+
this.textArea.style.top = `${topLeft.y * upscaleScale}px`;
|
|
12178
|
+
}
|
|
12179
|
+
if (this.onLiveResize) {
|
|
12180
|
+
const contentHeightInCanvas = contentHeightPx / (absScale.y * upscaleScale);
|
|
12181
|
+
this.onLiveResize(contentHeightInCanvas + paddingY * 2);
|
|
12182
|
+
}
|
|
12183
|
+
}
|
|
12184
|
+
/**
|
|
12185
|
+
* Updates the textarea `left`, `width`, and `top` to match new text bounds.
|
|
12186
|
+
* Call this from an `onLiveResize` callback when the shape grows symmetrically
|
|
12187
|
+
* (e.g. regular polygon) so the textarea tracks the new position on all axes.
|
|
12188
|
+
* Does NOT call `onLiveResize` — there is no re-entrancy risk, but also no need.
|
|
12189
|
+
*/
|
|
12190
|
+
repositionTextArea(group, textBounds) {
|
|
12191
|
+
if (!this.editing || !this.textArea) return;
|
|
12192
|
+
this.editingTextBounds = textBounds;
|
|
12193
|
+
const stage = this.instance.getStage();
|
|
12194
|
+
const upscaleScale = stage.getAttr("upscaleScale") ?? 1;
|
|
12195
|
+
const absoluteTransform = group.getAbsoluteTransform();
|
|
12196
|
+
const topLeft = absoluteTransform.point({
|
|
12197
|
+
x: textBounds.x,
|
|
12198
|
+
y: textBounds.y
|
|
12199
|
+
});
|
|
12200
|
+
const absScale = group.getAbsoluteScale();
|
|
12201
|
+
const textWidth = textBounds.width * absScale.x;
|
|
12202
|
+
this.textArea.style.left = `${topLeft.x * upscaleScale}px`;
|
|
12203
|
+
this.textArea.style.width = `${textWidth * upscaleScale}px`;
|
|
12204
|
+
const newBoundsHeightPx = textBounds.height * absScale.y * upscaleScale;
|
|
12205
|
+
const savedHeight = this.textArea.style.height;
|
|
12206
|
+
this.textArea.style.height = "auto";
|
|
12207
|
+
const actualContentHeightPx = this.textArea.scrollHeight;
|
|
12208
|
+
this.textArea.style.height = savedHeight;
|
|
12209
|
+
const groupProps = group.getAttrs();
|
|
12210
|
+
const verticalAlign = groupProps.labelVerticalAlign ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelVerticalAlign;
|
|
12211
|
+
const offsetY = this.computeVerticalOffset(verticalAlign, newBoundsHeightPx, actualContentHeightPx);
|
|
12212
|
+
this.textArea.style.top = `${topLeft.y * upscaleScale + offsetY}px`;
|
|
12213
|
+
}
|
|
12214
|
+
/**
|
|
12215
|
+
* Convergence loop: onLiveResize may change the textarea width (e.g. a
|
|
12216
|
+
* growing polygon becomes wider), which changes line-wrapping, which may
|
|
12217
|
+
* require a different shape height. Iterates until scrollHeight is stable
|
|
12218
|
+
* or a safety limit is reached (5 passes cover any practical input).
|
|
12219
|
+
*
|
|
12220
|
+
* Oscillation prevention: if the sequence alternates (narrow→grow→wide→
|
|
12221
|
+
* restore→narrow→…) the loop exits with the polygon under-sized.
|
|
12222
|
+
* We track `lastUsedPx` — the height last passed to onLiveResize — and
|
|
12223
|
+
* fire a final corrective grow whenever `prevHeightPx > lastUsedPx`
|
|
12224
|
+
* (content at the current width still overflows what was last asked for).
|
|
12225
|
+
*/
|
|
12226
|
+
runLiveResizeLoop(onLiveResize, contentHeightPx, effectiveScale, upscaleScale, paddingY) {
|
|
12227
|
+
const MAX_PASSES = 5;
|
|
12228
|
+
let maxNeededPx = contentHeightPx;
|
|
12229
|
+
let prevHeightPx = contentHeightPx;
|
|
12230
|
+
let lastUsedPx = 0;
|
|
12231
|
+
for (let pass = 0; pass < MAX_PASSES; pass++) {
|
|
12232
|
+
lastUsedPx = prevHeightPx;
|
|
12233
|
+
const neededInCanvas = prevHeightPx / (effectiveScale * upscaleScale);
|
|
12234
|
+
onLiveResize(neededInCanvas + paddingY * 2);
|
|
12235
|
+
if (!this.textArea) break;
|
|
12236
|
+
this.textArea.style.height = "auto";
|
|
12237
|
+
const measuredPx = this.textArea.scrollHeight;
|
|
12238
|
+
this.textArea.style.height = `${measuredPx}px`;
|
|
12239
|
+
if (measuredPx > maxNeededPx) maxNeededPx = measuredPx;
|
|
12240
|
+
if (measuredPx === prevHeightPx) break;
|
|
12241
|
+
prevHeightPx = measuredPx;
|
|
12242
|
+
}
|
|
12243
|
+
if (this.textArea && prevHeightPx > lastUsedPx) {
|
|
12244
|
+
const finalInCanvas = maxNeededPx / (effectiveScale * upscaleScale);
|
|
12245
|
+
onLiveResize(finalInCanvas + paddingY * 2);
|
|
12246
|
+
this.textArea.style.height = "auto";
|
|
12247
|
+
const finalPx = this.textArea.scrollHeight;
|
|
12248
|
+
this.textArea.style.height = `${finalPx}px`;
|
|
12249
|
+
}
|
|
12250
|
+
}
|
|
12251
|
+
createTextAreaDOM(group, textBounds, position, upscaleScale, onCommit, onLiveResize) {
|
|
12252
|
+
const stage = this.instance.getStage();
|
|
12253
|
+
const props = group.getAttrs();
|
|
12254
|
+
const absScale = group.getAbsoluteScale();
|
|
12255
|
+
const effectiveScale = absScale.x;
|
|
12256
|
+
this.textArea = document.createElement("textarea");
|
|
12257
|
+
this.textArea.id = `${group.id()}_label_textarea`;
|
|
12258
|
+
this.textArea.rows = 1;
|
|
12259
|
+
stage.container().appendChild(this.textArea);
|
|
12260
|
+
stage.on("dragmove.weaveLabelEdit xChange.weaveLabelEdit yChange.weaveLabelEdit", () => {
|
|
12261
|
+
if (this.editingGroup && this.editingTextBounds) this.repositionTextArea(this.editingGroup, this.editingTextBounds);
|
|
12262
|
+
});
|
|
12263
|
+
const textWidth = textBounds.width * effectiveScale;
|
|
12264
|
+
const fontSize = (props.labelFontSize ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontSize) * effectiveScale;
|
|
12265
|
+
const originalBoundsHeightPx = textBounds.height * effectiveScale * upscaleScale;
|
|
12266
|
+
const paddingY = props.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
12267
|
+
this.textArea.style.position = "absolute";
|
|
12268
|
+
this.textArea.style.visibility = "hidden";
|
|
12269
|
+
this.textArea.style.left = `${position.x * upscaleScale}px`;
|
|
12270
|
+
this.textArea.style.width = `${textWidth * upscaleScale}px`;
|
|
12271
|
+
this.textArea.style.border = "solid 0px #1e40af";
|
|
12272
|
+
this.textArea.style.background = "transparent";
|
|
12273
|
+
this.textArea.style.backgroundColor = "transparent";
|
|
12274
|
+
this.textArea.style.boxSizing = "border-box";
|
|
12275
|
+
this.textArea.style.overflow = "hidden";
|
|
12276
|
+
const rotation = group.getAbsoluteRotation();
|
|
12277
|
+
if (rotation) {
|
|
12278
|
+
this.textArea.style.transformOrigin = "left top";
|
|
12279
|
+
this.textArea.style.transform = `rotate(${rotation}deg)`;
|
|
12280
|
+
}
|
|
12281
|
+
this.textArea.value = props.labelText ?? "";
|
|
12282
|
+
this.textArea.style.fontSize = `${fontSize * upscaleScale}px`;
|
|
12283
|
+
this.textArea.style.fontFamily = props.labelFontFamily ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontFamily;
|
|
12284
|
+
this.textArea.style.letterSpacing = `${props.labelLetterSpacing ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelLetterSpacing}px`;
|
|
12285
|
+
this.textArea.style.lineHeight = `${props.labelLineHeight ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelLineHeight}em`;
|
|
12286
|
+
const fontStyle = props.labelFontStyle ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontStyle;
|
|
12287
|
+
this.textArea.style.fontStyle = fontStyle.includes("italic") ? "italic" : "normal";
|
|
12288
|
+
this.textArea.style.textDecoration = props.labelTextDecoration ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelTextDecoration;
|
|
12289
|
+
let fontWeight = "normal";
|
|
12290
|
+
const matchNumber = fontStyle.match(/\d+/);
|
|
12291
|
+
if (fontStyle.includes("bold")) fontWeight = "bold";
|
|
12292
|
+
if (matchNumber) fontWeight = matchNumber[0];
|
|
12293
|
+
this.textArea.style.fontWeight = fontWeight;
|
|
12294
|
+
this.textArea.style.fontVariant = props.labelFontVariant ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontVariant;
|
|
12295
|
+
this.textArea.style.color = props.labelFill ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFill;
|
|
12296
|
+
this.textArea.style.textAlign = props.labelAlign ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelAlign;
|
|
12297
|
+
this.textArea.style.outline = "none";
|
|
12298
|
+
this.textArea.style.resize = "none";
|
|
12299
|
+
this.textArea.style.margin = "0";
|
|
12300
|
+
this.textArea.style.padding = "0";
|
|
12301
|
+
this.textArea.style.caretColor = "black";
|
|
12302
|
+
this.textArea.style.overscrollBehavior = "contains";
|
|
12303
|
+
const resizeTextarea = () => {
|
|
12304
|
+
if (!this.textArea) return;
|
|
12305
|
+
this.textArea.style.height = "auto";
|
|
12306
|
+
const contentHeightPx = this.textArea.scrollHeight;
|
|
12307
|
+
const fonts = this.instance.getFonts();
|
|
12308
|
+
const font = fonts.find((f) => f.name === (props.labelFontFamily ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontFamily));
|
|
12309
|
+
const currentBounds = this.editingTextBounds ?? textBounds;
|
|
12310
|
+
const liveTL = group.getAbsoluteTransform().point({
|
|
12311
|
+
x: currentBounds.x,
|
|
12312
|
+
y: currentBounds.y + (font?.offsetY ?? 0)
|
|
12313
|
+
});
|
|
12314
|
+
this.textArea.style.left = `${liveTL.x * upscaleScale}px`;
|
|
12315
|
+
if (contentHeightPx <= originalBoundsHeightPx) {
|
|
12316
|
+
this.textArea.style.height = `${contentHeightPx}px`;
|
|
12317
|
+
const verticalAlign = props.labelVerticalAlign ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelVerticalAlign;
|
|
12318
|
+
const offsetY = this.computeVerticalOffset(verticalAlign, originalBoundsHeightPx, contentHeightPx);
|
|
12319
|
+
this.textArea.style.top = `${liveTL.y * upscaleScale + offsetY}px`;
|
|
12320
|
+
} else {
|
|
12321
|
+
this.textArea.style.height = `${contentHeightPx}px`;
|
|
12322
|
+
this.textArea.style.top = `${liveTL.y * upscaleScale}px`;
|
|
12323
|
+
}
|
|
12324
|
+
if (onLiveResize) this.runLiveResizeLoop(onLiveResize, contentHeightPx, effectiveScale, upscaleScale, paddingY);
|
|
12325
|
+
if (this.textArea.style.visibility === "hidden") this.textArea.style.visibility = "";
|
|
12326
|
+
};
|
|
12327
|
+
const commit = (text) => {
|
|
12328
|
+
window.removeEventListener("pointerup", handleOutsideClick);
|
|
12329
|
+
this.exitEditMode();
|
|
12330
|
+
const liveGroup = this.instance.getStage().findOne(`#${group.id()}`);
|
|
12331
|
+
const labelNode = liveGroup?.findOne(`#${labelId(group.id())}`);
|
|
12332
|
+
if (labelNode) labelNode.visible(text !== "");
|
|
12333
|
+
onCommit(text);
|
|
12334
|
+
};
|
|
12335
|
+
this.textArea.addEventListener("keydown", (e) => {
|
|
12336
|
+
e.stopPropagation();
|
|
12337
|
+
if (e.code === "Escape") {
|
|
12338
|
+
e.preventDefault();
|
|
12339
|
+
commit(this.textArea?.value ?? "");
|
|
12340
|
+
return;
|
|
12341
|
+
}
|
|
12342
|
+
resizeTextarea();
|
|
12343
|
+
}, { signal: this.instance.getEventsController().signal });
|
|
12344
|
+
this.textArea.addEventListener("keyup", () => resizeTextarea(), { signal: this.instance.getEventsController().signal });
|
|
12345
|
+
this.textArea.addEventListener("input", () => resizeTextarea(), { signal: this.instance.getEventsController().signal });
|
|
12346
|
+
this.textArea.addEventListener("scroll", () => {
|
|
12347
|
+
if (this.textArea) {
|
|
12348
|
+
this.textArea.scrollTop = 0;
|
|
12349
|
+
this.textArea.scrollLeft = 0;
|
|
12350
|
+
}
|
|
12351
|
+
}, { signal: this.instance.getEventsController().signal });
|
|
12352
|
+
const handleOutsideClick = (e) => {
|
|
12353
|
+
e.stopPropagation();
|
|
12354
|
+
if (!this.textArea) return;
|
|
12355
|
+
const mouseX = e.clientX;
|
|
12356
|
+
const mouseY = e.clientY;
|
|
12357
|
+
let elementUnderMouse = document.elementFromPoint(mouseX, mouseY);
|
|
12358
|
+
if (isInShadowDOM(stage.container())) {
|
|
12359
|
+
const shadowHost = getTopmostShadowHost(stage.container());
|
|
12360
|
+
if (shadowHost) elementUnderMouse = shadowHost.elementFromPoint(mouseX, mouseY);
|
|
12361
|
+
}
|
|
12362
|
+
const clickedOutside = elementUnderMouse?.id !== `${group.id()}_label_textarea`;
|
|
12363
|
+
if (clickedOutside) commit(this.textArea.value);
|
|
12364
|
+
};
|
|
12365
|
+
setTimeout(() => {
|
|
12366
|
+
window.addEventListener("pointerup", handleOutsideClick, { signal: this.instance.getEventsController().signal });
|
|
12367
|
+
}, 0);
|
|
12368
|
+
this.textArea.tabIndex = 1;
|
|
12369
|
+
requestAnimationFrame(() => {
|
|
12370
|
+
resizeTextarea();
|
|
12371
|
+
this.textArea?.focus({ preventScroll: true });
|
|
12372
|
+
if (this.textArea?.value) this.textArea.select();
|
|
12373
|
+
});
|
|
12374
|
+
}
|
|
12375
|
+
};
|
|
12376
|
+
|
|
12377
|
+
//#endregion
|
|
12378
|
+
//#region src/nodes/shared/shape-label.utils.ts
|
|
12379
|
+
/**
|
|
12380
|
+
* Returns a partial props object containing only the label-related fields that
|
|
12381
|
+
* are explicitly set on `props`. Spread this into the `props` section of
|
|
12382
|
+
* `addNodeState` / `updateNodeState` to avoid duplicating the 12-field pattern
|
|
12383
|
+
* across every shape node that supports inline text labels.
|
|
12384
|
+
*/
|
|
12385
|
+
function spreadLabelProps(props) {
|
|
12386
|
+
return {
|
|
12387
|
+
...props.labelText !== void 0 && { labelText: props.labelText },
|
|
12388
|
+
...props.labelFontFamily !== void 0 && { labelFontFamily: props.labelFontFamily },
|
|
12389
|
+
...props.labelFontSize !== void 0 && { labelFontSize: props.labelFontSize },
|
|
12390
|
+
...props.labelFontStyle !== void 0 && { labelFontStyle: props.labelFontStyle },
|
|
12391
|
+
...props.labelFontVariant !== void 0 && { labelFontVariant: props.labelFontVariant },
|
|
12392
|
+
...props.labelFill !== void 0 && { labelFill: props.labelFill },
|
|
12393
|
+
...props.labelAlign !== void 0 && { labelAlign: props.labelAlign },
|
|
12394
|
+
...props.labelVerticalAlign !== void 0 && { labelVerticalAlign: props.labelVerticalAlign },
|
|
12395
|
+
...props.labelLetterSpacing !== void 0 && { labelLetterSpacing: props.labelLetterSpacing },
|
|
12396
|
+
...props.labelLineHeight !== void 0 && { labelLineHeight: props.labelLineHeight },
|
|
12397
|
+
...props.labelPaddingX !== void 0 && { labelPaddingX: props.labelPaddingX },
|
|
12398
|
+
...props.labelPaddingY !== void 0 && { labelPaddingY: props.labelPaddingY }
|
|
12399
|
+
};
|
|
12400
|
+
}
|
|
12401
|
+
/**
|
|
12402
|
+
* Returns the shared Zod schema fields for inline text label properties.
|
|
12403
|
+
* Spread the result of this function into a shape node's `props` schema
|
|
12404
|
+
* extension to avoid duplicating the 10-field label schema across rectangle,
|
|
12405
|
+
* ellipse, and any future shape that supports text labels.
|
|
12406
|
+
*/
|
|
12407
|
+
function getShapeLabelSchemaFields() {
|
|
12408
|
+
return {
|
|
12409
|
+
labelText: z.string().optional().describe("Text label displayed inside the shape"),
|
|
12410
|
+
labelFontFamily: z.string().optional().describe("Font family for the label text"),
|
|
12411
|
+
labelFontSize: z.number().optional().describe("Font size for the label text in pixels"),
|
|
12412
|
+
labelFontStyle: z.string().optional().describe("Font style for the label text (e.g. \"normal\", \"bold\", \"italic\", \"bold italic\")"),
|
|
12413
|
+
labelFontVariant: z.string().optional().describe("Font variant for the label text (e.g. \"normal\", \"small-caps\")"),
|
|
12414
|
+
labelFill: z.string().optional().describe("Color of the label text in hex format (e.g. #RRGGBBAA)"),
|
|
12415
|
+
labelAlign: z.string().optional().describe("Horizontal alignment of the label text (\"left\", \"center\", \"right\")"),
|
|
12416
|
+
labelVerticalAlign: z.string().optional().describe("Vertical alignment of the label text (\"top\", \"middle\", \"bottom\")"),
|
|
12417
|
+
labelLetterSpacing: z.number().optional().describe("Letter spacing for the label text in pixels"),
|
|
12418
|
+
labelLineHeight: z.number().optional().describe("Line height multiplier for the label text"),
|
|
12419
|
+
labelPaddingX: z.number().optional().describe("Horizontal inset (padding) in pixels applied on each side of the label"),
|
|
12420
|
+
labelPaddingY: z.number().optional().describe("Vertical inset (padding) in pixels applied on top and bottom of the label")
|
|
12421
|
+
};
|
|
12422
|
+
}
|
|
12423
|
+
/**
|
|
12424
|
+
* Extracts the label node and typography settings from a Konva group.
|
|
12425
|
+
* Returns `null` when the group has no label text or no label Konva.Text child.
|
|
12426
|
+
* Used internally by `computeRectangleLabelMinSize`, `computeEllipseLabelMinSize`,
|
|
12427
|
+
* and `computePolygonLabelMinSize` to avoid duplicating the setup logic.
|
|
12428
|
+
*/
|
|
12429
|
+
function extractLabelNodeContext(group, skipTransformInClientRect = true) {
|
|
12430
|
+
const attrs = group.getAttrs();
|
|
12431
|
+
const labelText = attrs.labelText ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelText;
|
|
12432
|
+
if (!labelText) return null;
|
|
12433
|
+
const labelNode = group.findOne(`#${labelId(group.id())}`);
|
|
12434
|
+
if (!labelNode) return null;
|
|
12435
|
+
const paddingX = attrs.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
12436
|
+
const paddingY = attrs.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
12437
|
+
const fontSize = attrs.labelFontSize ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelFontSize;
|
|
12438
|
+
const cloneLabel = labelNode.clone({ visible: false });
|
|
12439
|
+
cloneLabel.height(void 0);
|
|
12440
|
+
const naturalSize = cloneLabel.getClientRect({
|
|
12441
|
+
skipTransform: skipTransformInClientRect,
|
|
12442
|
+
skipShadow: true
|
|
12443
|
+
});
|
|
12444
|
+
return {
|
|
12445
|
+
paddingX,
|
|
12446
|
+
paddingY,
|
|
12447
|
+
fontSize,
|
|
12448
|
+
labelNode,
|
|
12449
|
+
naturalSize
|
|
12450
|
+
};
|
|
12451
|
+
}
|
|
12452
|
+
/**
|
|
12453
|
+
* Returns the minimum bounding size `{ width, height }` (in Konva canvas
|
|
12454
|
+
* units) that the rectangle must have so its label text is fully visible —
|
|
12455
|
+
* no vertical truncation and no horizontal clipping of the widest word.
|
|
12456
|
+
*
|
|
12457
|
+
* Returns `{ width: 0, height: 0 }` when the label is empty.
|
|
12458
|
+
*
|
|
12459
|
+
* @param group - The rectangle `Konva.Group` returned by `onRender`.
|
|
12460
|
+
*/
|
|
12461
|
+
function computeRectangleLabelMinSize(stage, group) {
|
|
12462
|
+
const ctx = extractLabelNodeContext(group);
|
|
12463
|
+
if (!ctx) return {
|
|
12464
|
+
width: 0,
|
|
12465
|
+
height: 0
|
|
12466
|
+
};
|
|
12467
|
+
const { paddingX, paddingY, fontSize, naturalSize } = ctx;
|
|
12468
|
+
return {
|
|
12469
|
+
width: (paddingX * 2 + fontSize) * stage.scaleX(),
|
|
12470
|
+
height: (naturalSize.height + paddingY * 2) * stage.scaleX()
|
|
12471
|
+
};
|
|
12472
|
+
}
|
|
12473
|
+
/**
|
|
12474
|
+
* Returns the minimum bounding box size `{ minWidth, minHeight }` (in Konva
|
|
12475
|
+
* canvas units, i.e. `radiusX * 2` × `radiusY * 2`) that the ellipse must have
|
|
12476
|
+
* so its inscribed label text is fully visible.
|
|
12477
|
+
*
|
|
12478
|
+
* The ellipse label sits inside the largest axis-aligned rectangle inscribed in
|
|
12479
|
+
* the ellipse: `inscribedW = radiusX * √2`, `inscribedH = radiusY * √2`. The
|
|
12480
|
+
* minimum radiusY is back-computed from the text's natural height:
|
|
12481
|
+
* `minRadiusY = ceil(naturalTextH / √2)`
|
|
12482
|
+
*
|
|
12483
|
+
* Returns `{ minWidth: 0, minHeight: 0 }` when the label is empty.
|
|
12484
|
+
*
|
|
12485
|
+
* @param group - The ellipse `Konva.Group` returned by `onRender`.
|
|
12486
|
+
*/
|
|
12487
|
+
function computeEllipseLabelMinSize(stage, group) {
|
|
12488
|
+
const ctx = extractLabelNodeContext(group);
|
|
12489
|
+
if (!ctx) return {
|
|
12490
|
+
width: 0,
|
|
12491
|
+
height: 0
|
|
12492
|
+
};
|
|
12493
|
+
const { paddingX, paddingY, fontSize, naturalSize } = ctx;
|
|
12494
|
+
const minRadiusY = Math.ceil((naturalSize.height + paddingY * 2) / Math.SQRT2);
|
|
12495
|
+
const minRadiusX = Math.ceil((fontSize + paddingX * 2) / Math.SQRT2);
|
|
12496
|
+
return {
|
|
12497
|
+
width: minRadiusX * 2 * stage.scaleX(),
|
|
12498
|
+
height: minRadiusY * 2 * stage.scaleY()
|
|
12499
|
+
};
|
|
12500
|
+
}
|
|
12501
|
+
/**
|
|
12502
|
+
* Returns the minimum bounding-box size `{ width, height }` (in Konva canvas
|
|
12503
|
+
* units) that the polygon node must have so its label text is fully visible.
|
|
12504
|
+
*
|
|
12505
|
+
* The polygon label sits inside the stored `innerRect` attribute. The minimum
|
|
12506
|
+
* size is back-computed from the label text's natural wrapped height and the
|
|
12507
|
+
* current ratio of `innerRect` to the overall bounding box.
|
|
12508
|
+
*
|
|
12509
|
+
* Returns `{ width: 0, height: 0 }` when the label is empty.
|
|
12510
|
+
*
|
|
12511
|
+
* @param group - The polygon `Konva.Group` returned by `onRender`.
|
|
12512
|
+
*/
|
|
12513
|
+
function computePolygonLabelMinSize(stage, group) {
|
|
12514
|
+
const ctx = extractLabelNodeContext(group);
|
|
12515
|
+
if (!ctx) return {
|
|
12516
|
+
width: 0,
|
|
12517
|
+
height: 0
|
|
12518
|
+
};
|
|
12519
|
+
const { paddingX, paddingY, fontSize, naturalSize } = ctx;
|
|
12520
|
+
const attrs = group.getAttrs();
|
|
12521
|
+
const innerRect = attrs.innerRect;
|
|
12522
|
+
if (!innerRect) return {
|
|
12523
|
+
width: 0,
|
|
12524
|
+
height: 0
|
|
12525
|
+
};
|
|
12526
|
+
return {
|
|
12527
|
+
width: (paddingX * 2 + fontSize) * stage.scaleX(),
|
|
12528
|
+
height: (naturalSize.height + paddingY * 2) * stage.scaleX()
|
|
12529
|
+
};
|
|
12530
|
+
}
|
|
12531
|
+
|
|
11921
12532
|
//#endregion
|
|
11922
12533
|
//#region src/nodes/rectangle/rectangle.ts
|
|
11923
12534
|
var WeaveRectangleNode = class extends WeaveNode {
|
|
11924
12535
|
nodeType = WEAVE_RECTANGLE_NODE_TYPE;
|
|
11925
12536
|
initialize = void 0;
|
|
12537
|
+
_transforming = false;
|
|
12538
|
+
get shapeLabelEditor() {
|
|
12539
|
+
return this._shapeLabelEditor ??= new WeaveShapeLabelEditor(this.instance);
|
|
12540
|
+
}
|
|
11926
12541
|
constructor(params) {
|
|
11927
12542
|
super();
|
|
11928
12543
|
const { config } = params ?? {};
|
|
@@ -11931,13 +12546,15 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
11931
12546
|
onRender(props) {
|
|
11932
12547
|
const rectangle = new Konva.Group({
|
|
11933
12548
|
...props,
|
|
12549
|
+
id: `${props.id}`,
|
|
11934
12550
|
name: "node"
|
|
11935
12551
|
});
|
|
11936
12552
|
const internalRectBg = new Konva.Rect({
|
|
11937
12553
|
...props,
|
|
11938
12554
|
name: void 0,
|
|
11939
|
-
|
|
12555
|
+
nodeType: void 0,
|
|
11940
12556
|
nodeId: props.id,
|
|
12557
|
+
id: `${props.id}-bg`,
|
|
11941
12558
|
x: 0,
|
|
11942
12559
|
y: 0,
|
|
11943
12560
|
width: props.width,
|
|
@@ -11952,6 +12569,7 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
11952
12569
|
const internalRectBorder = new Konva.Rect({
|
|
11953
12570
|
...props,
|
|
11954
12571
|
name: void 0,
|
|
12572
|
+
nodeType: void 0,
|
|
11955
12573
|
id: `${props.id}-border`,
|
|
11956
12574
|
x: props.strokeWidth / 2,
|
|
11957
12575
|
y: props.strokeWidth / 2,
|
|
@@ -11961,9 +12579,19 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
11961
12579
|
strokeWidth: props.strokeWidth || 0,
|
|
11962
12580
|
strokeScaleEnabled: true,
|
|
11963
12581
|
rotation: 0,
|
|
11964
|
-
listening: false
|
|
12582
|
+
listening: false,
|
|
12583
|
+
draggable: false
|
|
11965
12584
|
});
|
|
11966
12585
|
rectangle.add(internalRectBorder);
|
|
12586
|
+
const paddingX = props.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
12587
|
+
const paddingY = props.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
12588
|
+
const labelTextBounds = {
|
|
12589
|
+
x: paddingX,
|
|
12590
|
+
y: paddingY,
|
|
12591
|
+
width: Math.max(1, props.width - paddingX * 2),
|
|
12592
|
+
height: Math.max(1, props.height - paddingY * 2)
|
|
12593
|
+
};
|
|
12594
|
+
this.shapeLabelEditor.renderLabel(rectangle, props, labelTextBounds);
|
|
11967
12595
|
internalRectBorder.moveToTop();
|
|
11968
12596
|
internalRectBg.moveToBottom();
|
|
11969
12597
|
this.setupDefaultNodeAugmentation(rectangle);
|
|
@@ -11972,6 +12600,51 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
11972
12600
|
return defaultTransformerProperties;
|
|
11973
12601
|
};
|
|
11974
12602
|
this.setupDefaultNodeEvents(rectangle);
|
|
12603
|
+
rectangle.on("transformstart", () => {
|
|
12604
|
+
this._transforming = true;
|
|
12605
|
+
});
|
|
12606
|
+
rectangle.on("transform", () => {
|
|
12607
|
+
this.scaleReset(rectangle);
|
|
12608
|
+
this.onUpdate(rectangle, rectangle.getAttrs());
|
|
12609
|
+
});
|
|
12610
|
+
rectangle.on("transformend", () => {
|
|
12611
|
+
this._transforming = false;
|
|
12612
|
+
});
|
|
12613
|
+
rectangle.dblClick = () => {
|
|
12614
|
+
if (this.shapeLabelEditor.isEditing()) return;
|
|
12615
|
+
if (!(this.isSelecting() && this.isNodeSelected(rectangle))) return;
|
|
12616
|
+
const onCommit = (labelText) => {
|
|
12617
|
+
const updatedGroup = this.instance.getStage().findOne(`#${props.id}`);
|
|
12618
|
+
if (!updatedGroup) return;
|
|
12619
|
+
const serialized = this.serialize(updatedGroup);
|
|
12620
|
+
serialized.props.labelText = labelText;
|
|
12621
|
+
this.instance.updateNode(serialized);
|
|
12622
|
+
};
|
|
12623
|
+
const currentAttrs = rectangle.getAttrs();
|
|
12624
|
+
const curPaddingX = currentAttrs.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
12625
|
+
const curPaddingY = currentAttrs.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
12626
|
+
const currentLabelTextBounds = {
|
|
12627
|
+
x: curPaddingX,
|
|
12628
|
+
y: curPaddingY,
|
|
12629
|
+
width: Math.max(1, (currentAttrs.width ?? 0) - curPaddingX * 2),
|
|
12630
|
+
height: Math.max(1, (currentAttrs.height ?? 0) - curPaddingY * 2)
|
|
12631
|
+
};
|
|
12632
|
+
const originalHeight = currentAttrs.height ?? 0;
|
|
12633
|
+
this.shapeLabelEditor.triggerEditMode(rectangle, currentLabelTextBounds, onCommit, (neededShapeHeight) => {
|
|
12634
|
+
const finalHeight = Math.max(neededShapeHeight, originalHeight);
|
|
12635
|
+
const liveAttrs = rectangle.getAttrs();
|
|
12636
|
+
const strokeW = liveAttrs.strokeWidth || 0;
|
|
12637
|
+
const bg = rectangle.findOne(`#${liveAttrs.id}-bg`);
|
|
12638
|
+
const border = rectangle.findOne(`#${liveAttrs.id}-border`);
|
|
12639
|
+
rectangle.setAttrs({ height: finalHeight });
|
|
12640
|
+
bg?.setAttrs({ height: finalHeight });
|
|
12641
|
+
border?.setAttrs({ height: Math.max(0, finalHeight - strokeW) });
|
|
12642
|
+
rectangle.getLayer()?.batchDraw();
|
|
12643
|
+
});
|
|
12644
|
+
};
|
|
12645
|
+
rectangle.getNodeMinSize = () => {
|
|
12646
|
+
return computeRectangleLabelMinSize(this.instance.getStage(), rectangle);
|
|
12647
|
+
};
|
|
11975
12648
|
return rectangle;
|
|
11976
12649
|
}
|
|
11977
12650
|
onUpdate(nodeInstance, nextProps) {
|
|
@@ -12001,6 +12674,7 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
12001
12674
|
internalRectBorder.setAttrs({
|
|
12002
12675
|
...nextProps,
|
|
12003
12676
|
name: void 0,
|
|
12677
|
+
fill: "transparent",
|
|
12004
12678
|
id: `${nextProps.id}-border`,
|
|
12005
12679
|
x: nextProps.strokeWidth / 2,
|
|
12006
12680
|
y: nextProps.strokeWidth / 2,
|
|
@@ -12014,6 +12688,26 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
12014
12688
|
});
|
|
12015
12689
|
internalRectBorder.moveToTop();
|
|
12016
12690
|
}
|
|
12691
|
+
const paddingX = nextProps.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
12692
|
+
const paddingY = nextProps.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
12693
|
+
const labelTextBounds = {
|
|
12694
|
+
x: paddingX,
|
|
12695
|
+
y: paddingY,
|
|
12696
|
+
width: Math.max(1, nextProps.width - paddingX * 2),
|
|
12697
|
+
height: Math.max(1, nextProps.height - paddingY * 2)
|
|
12698
|
+
};
|
|
12699
|
+
this.shapeLabelEditor.updateLabel(rectangle, nextProps, labelTextBounds, (neededShapeHeight) => {
|
|
12700
|
+
nodeInstance.setAttrs({ height: neededShapeHeight });
|
|
12701
|
+
internalRectBg?.setAttrs({ height: neededShapeHeight });
|
|
12702
|
+
internalRectBorder?.setAttrs({ height: neededShapeHeight - nextProps.strokeWidth });
|
|
12703
|
+
if (!this._transforming) this.instance.updateNode(this.serialize(nodeInstance));
|
|
12704
|
+
});
|
|
12705
|
+
const labelNode = rectangle.findOne(`#${labelId(nextProps.id ?? "")}`);
|
|
12706
|
+
if (labelNode) {
|
|
12707
|
+
labelNode.moveToTop();
|
|
12708
|
+
internalRectBg?.moveToBottom();
|
|
12709
|
+
internalRectBorder?.moveToTop();
|
|
12710
|
+
}
|
|
12017
12711
|
const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
12018
12712
|
if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
|
|
12019
12713
|
}
|
|
@@ -12034,7 +12728,8 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
12034
12728
|
strokeScaleEnabled: true,
|
|
12035
12729
|
rotation: 0,
|
|
12036
12730
|
zIndex: 1,
|
|
12037
|
-
children: []
|
|
12731
|
+
children: [],
|
|
12732
|
+
...WEAVE_SHAPE_LABEL_DEFAULTS
|
|
12038
12733
|
}
|
|
12039
12734
|
};
|
|
12040
12735
|
}
|
|
@@ -12047,7 +12742,8 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
12047
12742
|
rotation: props.rotation,
|
|
12048
12743
|
fill: props.fill,
|
|
12049
12744
|
...props.stroke && { stroke: props.stroke },
|
|
12050
|
-
...props.strokeWidth && { strokeWidth: props.strokeWidth }
|
|
12745
|
+
...props.strokeWidth && { strokeWidth: props.strokeWidth },
|
|
12746
|
+
...spreadLabelProps(props)
|
|
12051
12747
|
} });
|
|
12052
12748
|
}
|
|
12053
12749
|
static updateNodeState(prevNodeState, nextProps) {
|
|
@@ -12059,7 +12755,8 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
12059
12755
|
rotation: nextProps.rotation,
|
|
12060
12756
|
fill: nextProps.fill,
|
|
12061
12757
|
...nextProps.stroke && { stroke: nextProps.stroke },
|
|
12062
|
-
...nextProps.strokeWidth && { strokeWidth: nextProps.strokeWidth }
|
|
12758
|
+
...nextProps.strokeWidth && { strokeWidth: nextProps.strokeWidth },
|
|
12759
|
+
...spreadLabelProps(nextProps)
|
|
12063
12760
|
} });
|
|
12064
12761
|
}
|
|
12065
12762
|
static getSchema() {
|
|
@@ -12073,7 +12770,8 @@ var WeaveRectangleNode = class extends WeaveNode {
|
|
|
12073
12770
|
fill: z.string().describe("Fill color of the rectangle in hex format with alpha channel (e.g. #RRGGBBAA)"),
|
|
12074
12771
|
stroke: z.string().describe("Stroke color of the rectangle in hex format with alpha channel (e.g. #RRGGBBAA)"),
|
|
12075
12772
|
strokeWidth: z.number().describe("Stroke width of the rectangle in pixels"),
|
|
12076
|
-
strokeScaleEnabled: z.boolean().describe("Whether the rectangle stroke width should scale when the node is scaled. Defaults to true.")
|
|
12773
|
+
strokeScaleEnabled: z.boolean().describe("Whether the rectangle stroke width should scale when the node is scaled. Defaults to true."),
|
|
12774
|
+
...getShapeLabelSchemaFields()
|
|
12077
12775
|
})
|
|
12078
12776
|
});
|
|
12079
12777
|
return nodeSchema;
|
|
@@ -12089,11 +12787,25 @@ const WEAVE_ELLIPSE_NODE_TYPE = "ellipse";
|
|
|
12089
12787
|
var WeaveEllipseNode = class extends WeaveNode {
|
|
12090
12788
|
nodeType = WEAVE_ELLIPSE_NODE_TYPE;
|
|
12091
12789
|
initialize = void 0;
|
|
12790
|
+
_transforming = false;
|
|
12791
|
+
get shapeLabelEditor() {
|
|
12792
|
+
return this._shapeLabelEditor ??= new WeaveShapeLabelEditor(this.instance);
|
|
12793
|
+
}
|
|
12092
12794
|
constructor(params) {
|
|
12093
12795
|
super();
|
|
12094
12796
|
const { config } = params ?? {};
|
|
12095
12797
|
this.config = { transform: { ...config?.transform } };
|
|
12096
12798
|
}
|
|
12799
|
+
getLabelTextBounds(radiusX, radiusY, paddingX, paddingY) {
|
|
12800
|
+
const inscribedW = radiusX * Math.SQRT2;
|
|
12801
|
+
const inscribedH = radiusY * Math.SQRT2;
|
|
12802
|
+
return {
|
|
12803
|
+
x: radiusX - inscribedW / 2 + paddingX,
|
|
12804
|
+
y: radiusY - inscribedH / 2 + paddingY,
|
|
12805
|
+
width: Math.max(1, inscribedW - paddingX * 2),
|
|
12806
|
+
height: Math.max(1, inscribedH - paddingY * 2)
|
|
12807
|
+
};
|
|
12808
|
+
}
|
|
12097
12809
|
onRender(props) {
|
|
12098
12810
|
const ellipse = new Konva.Group({
|
|
12099
12811
|
...props,
|
|
@@ -12131,6 +12843,10 @@ var WeaveEllipseNode = class extends WeaveNode {
|
|
|
12131
12843
|
listening: false
|
|
12132
12844
|
});
|
|
12133
12845
|
ellipse.add(internalEllipseBorder);
|
|
12846
|
+
const paddingX = props.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
12847
|
+
const paddingY = props.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
12848
|
+
const labelTextBounds = this.getLabelTextBounds(Math.max(1, baseRadiusX), Math.max(1, baseRadiusY), paddingX, paddingY);
|
|
12849
|
+
this.shapeLabelEditor.renderLabel(ellipse, props, labelTextBounds);
|
|
12134
12850
|
internalEllipseBorder.moveToTop();
|
|
12135
12851
|
internalEllipseBg.moveToBottom();
|
|
12136
12852
|
this.setupDefaultNodeAugmentation(ellipse);
|
|
@@ -12169,6 +12885,56 @@ var WeaveEllipseNode = class extends WeaveNode {
|
|
|
12169
12885
|
];
|
|
12170
12886
|
};
|
|
12171
12887
|
this.setupDefaultNodeEvents(ellipse);
|
|
12888
|
+
ellipse.on("transformstart", () => {
|
|
12889
|
+
this._transforming = true;
|
|
12890
|
+
});
|
|
12891
|
+
ellipse.on("transform", () => {
|
|
12892
|
+
this.scaleReset(ellipse);
|
|
12893
|
+
this.onUpdate(ellipse, ellipse.getAttrs());
|
|
12894
|
+
});
|
|
12895
|
+
ellipse.on("transformend", () => {
|
|
12896
|
+
this._transforming = false;
|
|
12897
|
+
});
|
|
12898
|
+
ellipse.dblClick = () => {
|
|
12899
|
+
if (this.shapeLabelEditor.isEditing()) return;
|
|
12900
|
+
if (!(this.isSelecting() && this.isNodeSelected(ellipse))) return;
|
|
12901
|
+
const onCommit = (labelText) => {
|
|
12902
|
+
const updatedGroup = this.instance.getStage().findOne(`#${props.id}`);
|
|
12903
|
+
if (!updatedGroup) return;
|
|
12904
|
+
const serialized = this.serialize(updatedGroup);
|
|
12905
|
+
serialized.props.labelText = labelText;
|
|
12906
|
+
this.instance.updateNode(serialized);
|
|
12907
|
+
};
|
|
12908
|
+
const currentAttrs = ellipse.getAttrs();
|
|
12909
|
+
const curPaddingX = currentAttrs.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
12910
|
+
const curPaddingY = currentAttrs.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
12911
|
+
const currentRadiusX = Math.max(1, currentAttrs.radiusX);
|
|
12912
|
+
const currentRadiusY = Math.max(1, currentAttrs.radiusY);
|
|
12913
|
+
const currentLabelTextBounds = this.getLabelTextBounds(currentRadiusX, currentRadiusY, curPaddingX, curPaddingY);
|
|
12914
|
+
const originalRadiusY = currentRadiusY;
|
|
12915
|
+
const originalNeededHeight = currentLabelTextBounds.height + curPaddingY * 2;
|
|
12916
|
+
this.shapeLabelEditor.triggerEditMode(ellipse, currentLabelTextBounds, onCommit, (neededShapeHeight) => {
|
|
12917
|
+
const newRadiusY = neededShapeHeight <= originalNeededHeight ? originalRadiusY : Math.ceil(neededShapeHeight / Math.SQRT2);
|
|
12918
|
+
const liveAttrs = ellipse.getAttrs();
|
|
12919
|
+
const strokeW = liveAttrs.strokeWidth || 0;
|
|
12920
|
+
const bg = ellipse.findOne(`#${liveAttrs.id}-bg`);
|
|
12921
|
+
const border = ellipse.findOne(`#${liveAttrs.id}-border`);
|
|
12922
|
+
ellipse.setAttrs({ radiusY: newRadiusY });
|
|
12923
|
+
bg?.setAttrs({
|
|
12924
|
+
radiusY: Math.max(1, newRadiusY),
|
|
12925
|
+
y: Math.max(1, newRadiusY)
|
|
12926
|
+
});
|
|
12927
|
+
border?.setAttrs({
|
|
12928
|
+
radiusY: Math.max(1, newRadiusY) - strokeW / 2,
|
|
12929
|
+
y: Math.max(1, newRadiusY)
|
|
12930
|
+
});
|
|
12931
|
+
const newLabelTextBounds = this.getLabelTextBounds(currentRadiusX, newRadiusY, curPaddingX, curPaddingY);
|
|
12932
|
+
this.shapeLabelEditor.repositionTextArea(ellipse, newLabelTextBounds);
|
|
12933
|
+
});
|
|
12934
|
+
};
|
|
12935
|
+
ellipse.getNodeMinSize = () => {
|
|
12936
|
+
return computeEllipseLabelMinSize(this.instance.getStage(), ellipse);
|
|
12937
|
+
};
|
|
12172
12938
|
return ellipse;
|
|
12173
12939
|
}
|
|
12174
12940
|
onUpdate(nodeInstance, nextProps) {
|
|
@@ -12206,12 +12972,34 @@ var WeaveEllipseNode = class extends WeaveNode {
|
|
|
12206
12972
|
radiusY: Math.max(1, baseRadiusY) - (nextProps.strokeWidth || 0) / 2,
|
|
12207
12973
|
stroke: nextProps.stroke || "transparent",
|
|
12208
12974
|
strokeWidth: nextProps.strokeWidth || 0,
|
|
12975
|
+
fill: "transparent",
|
|
12209
12976
|
strokeScaleEnabled: true,
|
|
12210
12977
|
listening: false,
|
|
12211
12978
|
rotation: 0
|
|
12212
12979
|
});
|
|
12213
12980
|
internalEllipseBorder.moveToTop();
|
|
12214
12981
|
}
|
|
12982
|
+
const paddingX = nextProps.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
12983
|
+
const paddingY = nextProps.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
12984
|
+
const labelTextBounds = this.getLabelTextBounds(Math.max(1, baseRadiusX), Math.max(1, baseRadiusY), paddingX, paddingY);
|
|
12985
|
+
this.shapeLabelEditor.updateLabel(ellipse, nextProps, labelTextBounds, (neededHeight) => {
|
|
12986
|
+
const newRadiusY = Math.ceil(neededHeight / Math.SQRT2);
|
|
12987
|
+
nodeInstance.setAttrs({ radiusY: newRadiusY });
|
|
12988
|
+
internalEllipseBg?.setAttrs({
|
|
12989
|
+
radiusY: Math.max(1, newRadiusY),
|
|
12990
|
+
y: Math.max(1, newRadiusY)
|
|
12991
|
+
});
|
|
12992
|
+
internalEllipseBorder?.setAttrs({
|
|
12993
|
+
radiusY: Math.max(1, newRadiusY) - (nextProps.strokeWidth || 0) / 2,
|
|
12994
|
+
y: Math.max(1, newRadiusY)
|
|
12995
|
+
});
|
|
12996
|
+
if (!this._transforming) this.instance.updateNode(this.serialize(nodeInstance));
|
|
12997
|
+
});
|
|
12998
|
+
const labelNode = ellipse.findOne(`#${labelId(nextProps.id)}`);
|
|
12999
|
+
if (labelNode) {
|
|
13000
|
+
labelNode.moveToTop();
|
|
13001
|
+
internalEllipseBorder?.moveToTop();
|
|
13002
|
+
}
|
|
12215
13003
|
const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
12216
13004
|
if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
|
|
12217
13005
|
}
|
|
@@ -12254,7 +13042,8 @@ var WeaveEllipseNode = class extends WeaveNode {
|
|
|
12254
13042
|
strokeScaleEnabled: true,
|
|
12255
13043
|
rotation: 0,
|
|
12256
13044
|
zIndex: 1,
|
|
12257
|
-
children: []
|
|
13045
|
+
children: [],
|
|
13046
|
+
...WEAVE_SHAPE_LABEL_DEFAULTS
|
|
12258
13047
|
}
|
|
12259
13048
|
};
|
|
12260
13049
|
}
|
|
@@ -12267,7 +13056,8 @@ var WeaveEllipseNode = class extends WeaveNode {
|
|
|
12267
13056
|
rotation: props.rotation,
|
|
12268
13057
|
fill: props.fill,
|
|
12269
13058
|
...props.stroke && { stroke: props.stroke },
|
|
12270
|
-
...props.strokeWidth && { strokeWidth: props.strokeWidth }
|
|
13059
|
+
...props.strokeWidth && { strokeWidth: props.strokeWidth },
|
|
13060
|
+
...spreadLabelProps(props)
|
|
12271
13061
|
} });
|
|
12272
13062
|
}
|
|
12273
13063
|
static updateNodeState(prevNodeState, nextProps) {
|
|
@@ -12279,7 +13069,8 @@ var WeaveEllipseNode = class extends WeaveNode {
|
|
|
12279
13069
|
rotation: nextProps.rotation,
|
|
12280
13070
|
fill: nextProps.fill,
|
|
12281
13071
|
...nextProps.stroke && { stroke: nextProps.stroke },
|
|
12282
|
-
...nextProps.strokeWidth && { strokeWidth: nextProps.strokeWidth }
|
|
13072
|
+
...nextProps.strokeWidth && { strokeWidth: nextProps.strokeWidth },
|
|
13073
|
+
...spreadLabelProps(nextProps)
|
|
12283
13074
|
} });
|
|
12284
13075
|
}
|
|
12285
13076
|
static getSchema() {
|
|
@@ -12293,7 +13084,8 @@ var WeaveEllipseNode = class extends WeaveNode {
|
|
|
12293
13084
|
fill: z.string().describe("Fill color of the ellipse in hex format with alpha channel (e.g. #RRGGBBAA)"),
|
|
12294
13085
|
stroke: z.string().describe("Stroke color of the ellipse in hex format with alpha channel (e.g. #RRGGBBAA)"),
|
|
12295
13086
|
strokeWidth: z.number().describe("Stroke width of the ellipse in pixels"),
|
|
12296
|
-
strokeScaleEnabled: z.boolean().describe("Whether the ellipse stroke width should scale when the node is scaled. Defaults to true.")
|
|
13087
|
+
strokeScaleEnabled: z.boolean().describe("Whether the ellipse stroke width should scale when the node is scaled. Defaults to true."),
|
|
13088
|
+
...getShapeLabelSchemaFields()
|
|
12297
13089
|
})
|
|
12298
13090
|
});
|
|
12299
13091
|
return nodeSchema;
|
|
@@ -15060,6 +15852,7 @@ var WeaveImageNode = class extends WeaveNode {
|
|
|
15060
15852
|
x: 1,
|
|
15061
15853
|
y: 1
|
|
15062
15854
|
});
|
|
15855
|
+
this.updateImageCrop(node);
|
|
15063
15856
|
}
|
|
15064
15857
|
getIsAsync() {
|
|
15065
15858
|
return true;
|
|
@@ -15537,161 +16330,1009 @@ var WeaveRegularPolygonNode = class extends WeaveNode {
|
|
|
15537
16330
|
...props,
|
|
15538
16331
|
name: "node"
|
|
15539
16332
|
});
|
|
15540
|
-
const sides = regularPolygon.getAttr("sides");
|
|
15541
|
-
const radius = regularPolygon.getAttr("radius");
|
|
15542
|
-
const internalRPBg = new Konva.RegularPolygon({
|
|
15543
|
-
...props,
|
|
15544
|
-
name: void 0,
|
|
16333
|
+
const sides = regularPolygon.getAttr("sides");
|
|
16334
|
+
const radius = regularPolygon.getAttr("radius");
|
|
16335
|
+
const internalRPBg = new Konva.RegularPolygon({
|
|
16336
|
+
...props,
|
|
16337
|
+
name: void 0,
|
|
16338
|
+
id: `${props.id}-bg`,
|
|
16339
|
+
nodeId: props.id,
|
|
16340
|
+
x: radius,
|
|
16341
|
+
y: radius,
|
|
16342
|
+
sides,
|
|
16343
|
+
radius,
|
|
16344
|
+
fill: props.fill || "transparent",
|
|
16345
|
+
strokeWidth: 0,
|
|
16346
|
+
strokeScaleEnabled: true,
|
|
16347
|
+
rotation: 0
|
|
16348
|
+
});
|
|
16349
|
+
const internalRPBgBox = internalRPBg.getClientRect({ relativeTo: regularPolygon });
|
|
16350
|
+
internalRPBg.x(internalRPBg.x() - internalRPBgBox.x);
|
|
16351
|
+
internalRPBg.y(internalRPBg.y() - internalRPBgBox.y);
|
|
16352
|
+
regularPolygon.add(internalRPBg);
|
|
16353
|
+
const internalRPBorder = new Konva.RegularPolygon({
|
|
16354
|
+
...props,
|
|
16355
|
+
name: void 0,
|
|
16356
|
+
id: `${props.id}-border`,
|
|
16357
|
+
x: radius,
|
|
16358
|
+
y: radius,
|
|
16359
|
+
sides,
|
|
16360
|
+
radius: radius - (props.strokeWidth || 0) / 2,
|
|
16361
|
+
fill: "transparent",
|
|
16362
|
+
strokeWidth: props.strokeWidth || 0,
|
|
16363
|
+
strokeScaleEnabled: true,
|
|
16364
|
+
rotation: 0,
|
|
16365
|
+
listening: false
|
|
16366
|
+
});
|
|
16367
|
+
const internalRPBorderBox = internalRPBorder.getClientRect({ relativeTo: regularPolygon });
|
|
16368
|
+
internalRPBorder.x(internalRPBorder.x() - internalRPBorderBox.x);
|
|
16369
|
+
internalRPBorder.y(internalRPBorder.y() - internalRPBorderBox.y);
|
|
16370
|
+
regularPolygon.add(internalRPBorder);
|
|
16371
|
+
internalRPBorder.moveToTop();
|
|
16372
|
+
internalRPBg.moveToBottom();
|
|
16373
|
+
this.setupDefaultNodeAugmentation(regularPolygon);
|
|
16374
|
+
const defaultTransformerProperties = this.defaultGetTransformerProperties(this.config.transform);
|
|
16375
|
+
regularPolygon.getTransformerProperties = function() {
|
|
16376
|
+
return {
|
|
16377
|
+
...defaultTransformerProperties,
|
|
16378
|
+
enabledAnchors: [
|
|
16379
|
+
"top-left",
|
|
16380
|
+
"top-right",
|
|
16381
|
+
"bottom-left",
|
|
16382
|
+
"bottom-right"
|
|
16383
|
+
],
|
|
16384
|
+
keepRatio: true
|
|
16385
|
+
};
|
|
16386
|
+
};
|
|
16387
|
+
regularPolygon.allowedAnchors = function() {
|
|
16388
|
+
return [
|
|
16389
|
+
"top-left",
|
|
16390
|
+
"top-right",
|
|
16391
|
+
"bottom-left",
|
|
16392
|
+
"bottom-right"
|
|
16393
|
+
];
|
|
16394
|
+
};
|
|
16395
|
+
this.setupDefaultNodeEvents(regularPolygon);
|
|
16396
|
+
return regularPolygon;
|
|
16397
|
+
}
|
|
16398
|
+
onUpdate(nodeInstance, nextProps) {
|
|
16399
|
+
nodeInstance.setAttrs({ ...nextProps });
|
|
16400
|
+
const sides = nodeInstance.getAttr("sides");
|
|
16401
|
+
const radius = nodeInstance.getAttr("radius");
|
|
16402
|
+
const regularPolygon = nodeInstance;
|
|
16403
|
+
const internalRPBg = regularPolygon.findOne(`#${nextProps.id}-bg`);
|
|
16404
|
+
const internalRPBorder = regularPolygon.findOne(`#${nextProps.id}-border`);
|
|
16405
|
+
if (internalRPBg) {
|
|
16406
|
+
internalRPBg.setAttrs({
|
|
16407
|
+
...nextProps,
|
|
16408
|
+
name: void 0,
|
|
16409
|
+
id: `${nextProps.id}-bg`,
|
|
16410
|
+
nodeId: nextProps.id,
|
|
16411
|
+
x: radius,
|
|
16412
|
+
y: radius,
|
|
16413
|
+
sides,
|
|
16414
|
+
radius,
|
|
16415
|
+
fill: nextProps.fill || "transparent",
|
|
16416
|
+
strokeWidth: 0,
|
|
16417
|
+
strokeScaleEnabled: true,
|
|
16418
|
+
rotation: 0
|
|
16419
|
+
});
|
|
16420
|
+
const internalRPBgBox = internalRPBg.getClientRect({ relativeTo: regularPolygon });
|
|
16421
|
+
internalRPBg.x(internalRPBg.x() - internalRPBgBox.x);
|
|
16422
|
+
internalRPBg.y(internalRPBg.y() - internalRPBgBox.y);
|
|
16423
|
+
internalRPBg.moveToBottom();
|
|
16424
|
+
}
|
|
16425
|
+
if (internalRPBorder) {
|
|
16426
|
+
internalRPBorder.setAttrs({
|
|
16427
|
+
...nextProps,
|
|
16428
|
+
name: void 0,
|
|
16429
|
+
id: `${nextProps.id}-border`,
|
|
16430
|
+
x: radius,
|
|
16431
|
+
y: radius,
|
|
16432
|
+
sides,
|
|
16433
|
+
radius: radius - (nextProps.strokeWidth || 0) / 2,
|
|
16434
|
+
stroke: nextProps.stroke || "transparent",
|
|
16435
|
+
strokeWidth: nextProps.strokeWidth || 0,
|
|
16436
|
+
strokeScaleEnabled: true,
|
|
16437
|
+
fill: "transparent",
|
|
16438
|
+
listening: false,
|
|
16439
|
+
rotation: 0
|
|
16440
|
+
});
|
|
16441
|
+
const internalRPBorderBox = internalRPBorder.getClientRect({ relativeTo: regularPolygon });
|
|
16442
|
+
internalRPBorder.x(internalRPBorder.x() - internalRPBorderBox.x);
|
|
16443
|
+
internalRPBorder.y(internalRPBorder.y() - internalRPBorderBox.y);
|
|
16444
|
+
internalRPBorder.moveToTop();
|
|
16445
|
+
}
|
|
16446
|
+
const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
16447
|
+
if (nodesSelectionPlugin) {
|
|
16448
|
+
const actualSelectedNodes = nodesSelectionPlugin.getSelectedNodes();
|
|
16449
|
+
nodesSelectionPlugin.setSelectedNodes(actualSelectedNodes);
|
|
16450
|
+
nodesSelectionPlugin.getTransformer().forceUpdate();
|
|
16451
|
+
}
|
|
16452
|
+
}
|
|
16453
|
+
scaleReset(node) {
|
|
16454
|
+
const absTransform = node.getAbsoluteTransform().copy();
|
|
16455
|
+
const radius = node.getAttr("radius");
|
|
16456
|
+
node.setAttrs({ radius: radius * node.scaleX() });
|
|
16457
|
+
node.scaleX(1);
|
|
16458
|
+
node.scaleY(1);
|
|
16459
|
+
const newTransform = node.getAbsoluteTransform();
|
|
16460
|
+
const dx = absTransform.m[4] - newTransform.m[4];
|
|
16461
|
+
const dy = absTransform.m[5] - newTransform.m[5];
|
|
16462
|
+
node.x(node.x() + dx);
|
|
16463
|
+
node.y(node.y() + dy);
|
|
16464
|
+
}
|
|
16465
|
+
realOffset(element) {
|
|
16466
|
+
return {
|
|
16467
|
+
x: element.props.radius,
|
|
16468
|
+
y: element.props.radius
|
|
16469
|
+
};
|
|
16470
|
+
}
|
|
16471
|
+
static defaultState(nodeId) {
|
|
16472
|
+
return {
|
|
16473
|
+
...super.defaultState(nodeId),
|
|
16474
|
+
type: WEAVE_REGULAR_POLYGON_NODE_TYPE,
|
|
16475
|
+
props: {
|
|
16476
|
+
...super.defaultState(nodeId).props,
|
|
16477
|
+
nodeType: WEAVE_REGULAR_POLYGON_NODE_TYPE,
|
|
16478
|
+
x: 0,
|
|
16479
|
+
y: 0,
|
|
16480
|
+
sides: 5,
|
|
16481
|
+
radius: 100,
|
|
16482
|
+
stroke: "#000000",
|
|
16483
|
+
fill: "#FFFFFF",
|
|
16484
|
+
strokeWidth: 1,
|
|
16485
|
+
strokeScaleEnabled: true,
|
|
16486
|
+
rotation: 0,
|
|
16487
|
+
zIndex: 1,
|
|
16488
|
+
children: []
|
|
16489
|
+
}
|
|
16490
|
+
};
|
|
16491
|
+
}
|
|
16492
|
+
static addNodeState(defaultNodeState, props) {
|
|
16493
|
+
return mergeExceptArrays(defaultNodeState, { props: {
|
|
16494
|
+
x: props.x,
|
|
16495
|
+
y: props.y,
|
|
16496
|
+
sides: props.sides,
|
|
16497
|
+
radius: props.radius,
|
|
16498
|
+
rotation: props.rotation,
|
|
16499
|
+
fill: props.fill,
|
|
16500
|
+
...props.stroke && { stroke: props.stroke },
|
|
16501
|
+
...props.strokeWidth && { strokeWidth: props.strokeWidth }
|
|
16502
|
+
} });
|
|
16503
|
+
}
|
|
16504
|
+
static updateNodeState(prevNodeState, nextProps) {
|
|
16505
|
+
return mergeExceptArrays(prevNodeState, { props: {
|
|
16506
|
+
x: nextProps.x,
|
|
16507
|
+
y: nextProps.y,
|
|
16508
|
+
sides: nextProps.sides,
|
|
16509
|
+
radius: nextProps.radius,
|
|
16510
|
+
rotation: nextProps.rotation,
|
|
16511
|
+
fill: nextProps.fill,
|
|
16512
|
+
...nextProps.stroke && { stroke: nextProps.stroke },
|
|
16513
|
+
...nextProps.strokeWidth && { strokeWidth: nextProps.strokeWidth }
|
|
16514
|
+
} });
|
|
16515
|
+
}
|
|
16516
|
+
static getSchema() {
|
|
16517
|
+
const baseSchema = super.getSchema();
|
|
16518
|
+
const nodeSchema = baseSchema.extend({
|
|
16519
|
+
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}"`),
|
|
16520
|
+
props: baseSchema.shape.props.extend({
|
|
16521
|
+
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}"`),
|
|
16522
|
+
sides: z.number().describe("Number of sides of the regular polygon, must be 3 or more"),
|
|
16523
|
+
radius: z.number().describe("Radius of the regular polygon in pixels, distance from the center to any vertex"),
|
|
16524
|
+
fill: z.string().describe("Fill color of the regular polygon in hex format with alpha channel (e.g. #RRGGBBAA)"),
|
|
16525
|
+
stroke: z.string().describe("Stroke color of the regular polygon in hex format with alpha channel (e.g. #RRGGBBAA)"),
|
|
16526
|
+
strokeWidth: z.number().describe("Stroke width of the regular polygon in pixels"),
|
|
16527
|
+
strokeScaleEnabled: z.boolean().describe("Whether the regular polygon stroke width should scale when the node is scaled. Defaults to true.")
|
|
16528
|
+
})
|
|
16529
|
+
});
|
|
16530
|
+
return nodeSchema;
|
|
16531
|
+
}
|
|
16532
|
+
};
|
|
16533
|
+
|
|
16534
|
+
//#endregion
|
|
16535
|
+
//#region src/nodes/polygon/constants.ts
|
|
16536
|
+
const WEAVE_POLYGON_NODE_TYPE = "polygon";
|
|
16537
|
+
|
|
16538
|
+
//#endregion
|
|
16539
|
+
//#region src/nodes/polygon/presets.ts
|
|
16540
|
+
const WEAVE_POLYGON_PRESETS = {
|
|
16541
|
+
triangle: {
|
|
16542
|
+
label: "Triangle",
|
|
16543
|
+
sides: 3,
|
|
16544
|
+
defaultWidth: 100,
|
|
16545
|
+
defaultHeight: 100,
|
|
16546
|
+
normalizedPoints: [
|
|
16547
|
+
{
|
|
16548
|
+
x: .5,
|
|
16549
|
+
y: 0
|
|
16550
|
+
},
|
|
16551
|
+
{
|
|
16552
|
+
x: .933013,
|
|
16553
|
+
y: .75
|
|
16554
|
+
},
|
|
16555
|
+
{
|
|
16556
|
+
x: .066987,
|
|
16557
|
+
y: .75
|
|
16558
|
+
}
|
|
16559
|
+
],
|
|
16560
|
+
normalizedInnerRect: {
|
|
16561
|
+
tl: {
|
|
16562
|
+
x: .283494,
|
|
16563
|
+
y: .375
|
|
16564
|
+
},
|
|
16565
|
+
tr: {
|
|
16566
|
+
x: .716506,
|
|
16567
|
+
y: .375
|
|
16568
|
+
},
|
|
16569
|
+
bl: {
|
|
16570
|
+
x: .283494,
|
|
16571
|
+
y: .75
|
|
16572
|
+
},
|
|
16573
|
+
br: {
|
|
16574
|
+
x: .716506,
|
|
16575
|
+
y: .75
|
|
16576
|
+
}
|
|
16577
|
+
}
|
|
16578
|
+
},
|
|
16579
|
+
diamond: {
|
|
16580
|
+
label: "Diamond",
|
|
16581
|
+
sides: 4,
|
|
16582
|
+
defaultWidth: 100,
|
|
16583
|
+
defaultHeight: 100,
|
|
16584
|
+
normalizedPoints: [
|
|
16585
|
+
{
|
|
16586
|
+
x: .5,
|
|
16587
|
+
y: 0
|
|
16588
|
+
},
|
|
16589
|
+
{
|
|
16590
|
+
x: 1,
|
|
16591
|
+
y: .5
|
|
16592
|
+
},
|
|
16593
|
+
{
|
|
16594
|
+
x: .5,
|
|
16595
|
+
y: 1
|
|
16596
|
+
},
|
|
16597
|
+
{
|
|
16598
|
+
x: 0,
|
|
16599
|
+
y: .5
|
|
16600
|
+
}
|
|
16601
|
+
],
|
|
16602
|
+
normalizedInnerRect: {
|
|
16603
|
+
tl: {
|
|
16604
|
+
x: .25,
|
|
16605
|
+
y: .25
|
|
16606
|
+
},
|
|
16607
|
+
tr: {
|
|
16608
|
+
x: .75,
|
|
16609
|
+
y: .25
|
|
16610
|
+
},
|
|
16611
|
+
bl: {
|
|
16612
|
+
x: .25,
|
|
16613
|
+
y: .75
|
|
16614
|
+
},
|
|
16615
|
+
br: {
|
|
16616
|
+
x: .75,
|
|
16617
|
+
y: .75
|
|
16618
|
+
}
|
|
16619
|
+
}
|
|
16620
|
+
},
|
|
16621
|
+
pentagon: {
|
|
16622
|
+
label: "Pentagon",
|
|
16623
|
+
sides: 5,
|
|
16624
|
+
defaultWidth: 100,
|
|
16625
|
+
defaultHeight: 100,
|
|
16626
|
+
normalizedPoints: [
|
|
16627
|
+
{
|
|
16628
|
+
x: .5,
|
|
16629
|
+
y: 0
|
|
16630
|
+
},
|
|
16631
|
+
{
|
|
16632
|
+
x: .975528,
|
|
16633
|
+
y: .345492
|
|
16634
|
+
},
|
|
16635
|
+
{
|
|
16636
|
+
x: .793893,
|
|
16637
|
+
y: .904508
|
|
16638
|
+
},
|
|
16639
|
+
{
|
|
16640
|
+
x: .206107,
|
|
16641
|
+
y: .904508
|
|
16642
|
+
},
|
|
16643
|
+
{
|
|
16644
|
+
x: .024472,
|
|
16645
|
+
y: .345492
|
|
16646
|
+
}
|
|
16647
|
+
],
|
|
16648
|
+
normalizedInnerRect: {
|
|
16649
|
+
tl: {
|
|
16650
|
+
x: .132634,
|
|
16651
|
+
y: .316578
|
|
16652
|
+
},
|
|
16653
|
+
tr: {
|
|
16654
|
+
x: .867366,
|
|
16655
|
+
y: .316578
|
|
16656
|
+
},
|
|
16657
|
+
bl: {
|
|
16658
|
+
x: .132634,
|
|
16659
|
+
y: .678381
|
|
16660
|
+
},
|
|
16661
|
+
br: {
|
|
16662
|
+
x: .867366,
|
|
16663
|
+
y: .678381
|
|
16664
|
+
}
|
|
16665
|
+
}
|
|
16666
|
+
},
|
|
16667
|
+
hexagon: {
|
|
16668
|
+
label: "Hexagon",
|
|
16669
|
+
sides: 6,
|
|
16670
|
+
defaultWidth: 100,
|
|
16671
|
+
defaultHeight: 100,
|
|
16672
|
+
normalizedPoints: [
|
|
16673
|
+
{
|
|
16674
|
+
x: .5,
|
|
16675
|
+
y: 0
|
|
16676
|
+
},
|
|
16677
|
+
{
|
|
16678
|
+
x: .933013,
|
|
16679
|
+
y: .25
|
|
16680
|
+
},
|
|
16681
|
+
{
|
|
16682
|
+
x: .933013,
|
|
16683
|
+
y: .75
|
|
16684
|
+
},
|
|
16685
|
+
{
|
|
16686
|
+
x: .5,
|
|
16687
|
+
y: 1
|
|
16688
|
+
},
|
|
16689
|
+
{
|
|
16690
|
+
x: .066987,
|
|
16691
|
+
y: .75
|
|
16692
|
+
},
|
|
16693
|
+
{
|
|
16694
|
+
x: .066987,
|
|
16695
|
+
y: .25
|
|
16696
|
+
}
|
|
16697
|
+
],
|
|
16698
|
+
normalizedInnerRect: {
|
|
16699
|
+
tl: {
|
|
16700
|
+
x: .066987,
|
|
16701
|
+
y: .25
|
|
16702
|
+
},
|
|
16703
|
+
tr: {
|
|
16704
|
+
x: .933013,
|
|
16705
|
+
y: .25
|
|
16706
|
+
},
|
|
16707
|
+
bl: {
|
|
16708
|
+
x: .066987,
|
|
16709
|
+
y: .75
|
|
16710
|
+
},
|
|
16711
|
+
br: {
|
|
16712
|
+
x: .933013,
|
|
16713
|
+
y: .75
|
|
16714
|
+
}
|
|
16715
|
+
}
|
|
16716
|
+
},
|
|
16717
|
+
octagon: {
|
|
16718
|
+
label: "Octagon",
|
|
16719
|
+
sides: 8,
|
|
16720
|
+
defaultWidth: 100,
|
|
16721
|
+
defaultHeight: 100,
|
|
16722
|
+
normalizedPoints: [
|
|
16723
|
+
{
|
|
16724
|
+
x: .5,
|
|
16725
|
+
y: 0
|
|
16726
|
+
},
|
|
16727
|
+
{
|
|
16728
|
+
x: .853553,
|
|
16729
|
+
y: .146447
|
|
16730
|
+
},
|
|
16731
|
+
{
|
|
16732
|
+
x: 1,
|
|
16733
|
+
y: .5
|
|
16734
|
+
},
|
|
16735
|
+
{
|
|
16736
|
+
x: .853553,
|
|
16737
|
+
y: .853553
|
|
16738
|
+
},
|
|
16739
|
+
{
|
|
16740
|
+
x: .5,
|
|
16741
|
+
y: 1
|
|
16742
|
+
},
|
|
16743
|
+
{
|
|
16744
|
+
x: .146447,
|
|
16745
|
+
y: .853553
|
|
16746
|
+
},
|
|
16747
|
+
{
|
|
16748
|
+
x: 0,
|
|
16749
|
+
y: .5
|
|
16750
|
+
},
|
|
16751
|
+
{
|
|
16752
|
+
x: .146447,
|
|
16753
|
+
y: .146447
|
|
16754
|
+
}
|
|
16755
|
+
],
|
|
16756
|
+
normalizedInnerRect: {
|
|
16757
|
+
tl: {
|
|
16758
|
+
x: .25,
|
|
16759
|
+
y: .25
|
|
16760
|
+
},
|
|
16761
|
+
tr: {
|
|
16762
|
+
x: .75,
|
|
16763
|
+
y: .25
|
|
16764
|
+
},
|
|
16765
|
+
bl: {
|
|
16766
|
+
x: .25,
|
|
16767
|
+
y: .75
|
|
16768
|
+
},
|
|
16769
|
+
br: {
|
|
16770
|
+
x: .75,
|
|
16771
|
+
y: .75
|
|
16772
|
+
}
|
|
16773
|
+
}
|
|
16774
|
+
},
|
|
16775
|
+
decagon: {
|
|
16776
|
+
label: "Decagon",
|
|
16777
|
+
sides: 10,
|
|
16778
|
+
defaultWidth: 100,
|
|
16779
|
+
defaultHeight: 100,
|
|
16780
|
+
normalizedPoints: [
|
|
16781
|
+
{
|
|
16782
|
+
x: .5,
|
|
16783
|
+
y: 0
|
|
16784
|
+
},
|
|
16785
|
+
{
|
|
16786
|
+
x: .793893,
|
|
16787
|
+
y: .095492
|
|
16788
|
+
},
|
|
16789
|
+
{
|
|
16790
|
+
x: .975528,
|
|
16791
|
+
y: .345492
|
|
16792
|
+
},
|
|
16793
|
+
{
|
|
16794
|
+
x: .975528,
|
|
16795
|
+
y: .654508
|
|
16796
|
+
},
|
|
16797
|
+
{
|
|
16798
|
+
x: .793893,
|
|
16799
|
+
y: .904508
|
|
16800
|
+
},
|
|
16801
|
+
{
|
|
16802
|
+
x: .5,
|
|
16803
|
+
y: 1
|
|
16804
|
+
},
|
|
16805
|
+
{
|
|
16806
|
+
x: .206107,
|
|
16807
|
+
y: .904508
|
|
16808
|
+
},
|
|
16809
|
+
{
|
|
16810
|
+
x: .024472,
|
|
16811
|
+
y: .654508
|
|
16812
|
+
},
|
|
16813
|
+
{
|
|
16814
|
+
x: .024472,
|
|
16815
|
+
y: .345492
|
|
16816
|
+
},
|
|
16817
|
+
{
|
|
16818
|
+
x: .206107,
|
|
16819
|
+
y: .095492
|
|
16820
|
+
}
|
|
16821
|
+
],
|
|
16822
|
+
normalizedInnerRect: {
|
|
16823
|
+
tl: {
|
|
16824
|
+
x: .093851,
|
|
16825
|
+
y: .35
|
|
16826
|
+
},
|
|
16827
|
+
tr: {
|
|
16828
|
+
x: .906149,
|
|
16829
|
+
y: .35
|
|
16830
|
+
},
|
|
16831
|
+
bl: {
|
|
16832
|
+
x: .093851,
|
|
16833
|
+
y: .75
|
|
16834
|
+
},
|
|
16835
|
+
br: {
|
|
16836
|
+
x: .906149,
|
|
16837
|
+
y: .75
|
|
16838
|
+
}
|
|
16839
|
+
}
|
|
16840
|
+
}
|
|
16841
|
+
};
|
|
16842
|
+
/**
|
|
16843
|
+
* Scales a preset's normalized points and inner rect to actual pixel dimensions.
|
|
16844
|
+
*
|
|
16845
|
+
* Points are normalized so that minX = 0 and minY = 0 in the resulting pixel
|
|
16846
|
+
* space. This ensures the polygon group's position corresponds exactly to the
|
|
16847
|
+
* visual top-left of the polygon, which is required for the snapping system to
|
|
16848
|
+
* work correctly (it assumes nodeBox.x === node.x()).
|
|
16849
|
+
*/
|
|
16850
|
+
function instantiatePreset(def, width, height) {
|
|
16851
|
+
const rawPoints = def.normalizedPoints.map((p) => ({
|
|
16852
|
+
x: p.x * width,
|
|
16853
|
+
y: p.y * height
|
|
16854
|
+
}));
|
|
16855
|
+
const minX = Math.min(...rawPoints.map((p) => p.x));
|
|
16856
|
+
const minY = Math.min(...rawPoints.map((p) => p.y));
|
|
16857
|
+
const points = rawPoints.map((p) => ({
|
|
16858
|
+
x: p.x - minX,
|
|
16859
|
+
y: p.y - minY
|
|
16860
|
+
}));
|
|
16861
|
+
const ir = def.normalizedInnerRect;
|
|
16862
|
+
const innerRect = {
|
|
16863
|
+
tl: {
|
|
16864
|
+
x: ir.tl.x * width - minX,
|
|
16865
|
+
y: ir.tl.y * height - minY
|
|
16866
|
+
},
|
|
16867
|
+
tr: {
|
|
16868
|
+
x: ir.tr.x * width - minX,
|
|
16869
|
+
y: ir.tr.y * height - minY
|
|
16870
|
+
},
|
|
16871
|
+
bl: {
|
|
16872
|
+
x: ir.bl.x * width - minX,
|
|
16873
|
+
y: ir.bl.y * height - minY
|
|
16874
|
+
},
|
|
16875
|
+
br: {
|
|
16876
|
+
x: ir.br.x * width - minX,
|
|
16877
|
+
y: ir.br.y * height - minY
|
|
16878
|
+
}
|
|
16879
|
+
};
|
|
16880
|
+
const visualWidth = Math.max(...points.map((p) => p.x));
|
|
16881
|
+
const visualHeight = Math.max(...points.map((p) => p.y));
|
|
16882
|
+
return {
|
|
16883
|
+
points,
|
|
16884
|
+
innerRect,
|
|
16885
|
+
width: visualWidth,
|
|
16886
|
+
height: visualHeight
|
|
16887
|
+
};
|
|
16888
|
+
}
|
|
16889
|
+
|
|
16890
|
+
//#endregion
|
|
16891
|
+
//#region src/nodes/polygon/polygon.ts
|
|
16892
|
+
function computePolygonBounds(points) {
|
|
16893
|
+
if (!points.length) return {
|
|
16894
|
+
width: 0,
|
|
16895
|
+
height: 0
|
|
16896
|
+
};
|
|
16897
|
+
const maxX = Math.max(...points.map((p) => p.x));
|
|
16898
|
+
const maxY = Math.max(...points.map((p) => p.y));
|
|
16899
|
+
return {
|
|
16900
|
+
width: Math.max(1, maxX),
|
|
16901
|
+
height: Math.max(1, maxY)
|
|
16902
|
+
};
|
|
16903
|
+
}
|
|
16904
|
+
function polygonSelfRect() {
|
|
16905
|
+
const pts = this.getAttr("points");
|
|
16906
|
+
if (!pts?.length) return {
|
|
16907
|
+
x: 0,
|
|
16908
|
+
y: 0,
|
|
16909
|
+
width: 0,
|
|
16910
|
+
height: 0
|
|
16911
|
+
};
|
|
16912
|
+
const minX = Math.min(...pts.map((p) => p.x));
|
|
16913
|
+
const minY = Math.min(...pts.map((p) => p.y));
|
|
16914
|
+
const maxX = Math.max(...pts.map((p) => p.x));
|
|
16915
|
+
const maxY = Math.max(...pts.map((p) => p.y));
|
|
16916
|
+
return {
|
|
16917
|
+
x: minX,
|
|
16918
|
+
y: minY,
|
|
16919
|
+
width: maxX - minX,
|
|
16920
|
+
height: maxY - minY
|
|
16921
|
+
};
|
|
16922
|
+
}
|
|
16923
|
+
function getPolygonLabelTextBounds(innerRect, paddingX, paddingY) {
|
|
16924
|
+
return {
|
|
16925
|
+
x: innerRect.tl.x + paddingX,
|
|
16926
|
+
y: innerRect.tl.y + paddingY,
|
|
16927
|
+
width: Math.max(1, innerRect.tr.x - innerRect.tl.x - paddingX * 2),
|
|
16928
|
+
height: Math.max(1, innerRect.bl.y - innerRect.tl.y - paddingY * 2)
|
|
16929
|
+
};
|
|
16930
|
+
}
|
|
16931
|
+
function sceneFunc(context, shape) {
|
|
16932
|
+
const pts = shape.getAttr("points");
|
|
16933
|
+
if (!pts || pts.length < 3) return;
|
|
16934
|
+
context.beginPath();
|
|
16935
|
+
context.moveTo(pts[0].x, pts[0].y);
|
|
16936
|
+
for (let i = 1; i < pts.length; i++) context.lineTo(pts[i].x, pts[i].y);
|
|
16937
|
+
context.closePath();
|
|
16938
|
+
context.fillStrokeShape(shape);
|
|
16939
|
+
}
|
|
16940
|
+
/**
|
|
16941
|
+
* Draws an "inside" stroke for the border shape.
|
|
16942
|
+
* Clips to the polygon interior then draws 2× the stroke width so the outer
|
|
16943
|
+
* half is clipped away — resulting in a stroke of correct visual width that
|
|
16944
|
+
* stays entirely inside the polygon boundary.
|
|
16945
|
+
* strokeWidth is intentionally 0 on the shape (so getClientRect doesn't
|
|
16946
|
+
* expand the bounding box); the real width is stored in `innerStrokeWidth`.
|
|
16947
|
+
*/
|
|
16948
|
+
function borderSceneFunc(context, shape) {
|
|
16949
|
+
const pts = shape.getAttr("points");
|
|
16950
|
+
if (!pts || pts.length < 3) return;
|
|
16951
|
+
const sw = shape.getAttr("innerStrokeWidth");
|
|
16952
|
+
if (!sw) return;
|
|
16953
|
+
const stroke = shape.stroke();
|
|
16954
|
+
if (!stroke || stroke === "transparent") return;
|
|
16955
|
+
const ctx = context._context;
|
|
16956
|
+
const drawPath = () => {
|
|
16957
|
+
ctx.beginPath();
|
|
16958
|
+
ctx.moveTo(pts[0].x, pts[0].y);
|
|
16959
|
+
for (let i = 1; i < pts.length; i++) ctx.lineTo(pts[i].x, pts[i].y);
|
|
16960
|
+
ctx.closePath();
|
|
16961
|
+
};
|
|
16962
|
+
ctx.save();
|
|
16963
|
+
drawPath();
|
|
16964
|
+
ctx.clip();
|
|
16965
|
+
drawPath();
|
|
16966
|
+
ctx.lineWidth = sw * 2;
|
|
16967
|
+
ctx.strokeStyle = stroke;
|
|
16968
|
+
ctx.stroke();
|
|
16969
|
+
ctx.restore();
|
|
16970
|
+
}
|
|
16971
|
+
var WeavePolygonNode = class extends WeaveNode {
|
|
16972
|
+
nodeType = WEAVE_POLYGON_NODE_TYPE;
|
|
16973
|
+
initialize = void 0;
|
|
16974
|
+
_transforming = false;
|
|
16975
|
+
get shapeLabelEditor() {
|
|
16976
|
+
this._shapeLabelEditor ??= new WeaveShapeLabelEditor(this.instance);
|
|
16977
|
+
return this._shapeLabelEditor;
|
|
16978
|
+
}
|
|
16979
|
+
constructor(params) {
|
|
16980
|
+
super();
|
|
16981
|
+
const { config } = params ?? {};
|
|
16982
|
+
this.config = { transform: { ...config?.transform } };
|
|
16983
|
+
}
|
|
16984
|
+
getLabelTextBounds(group) {
|
|
16985
|
+
const attrs = group.getAttrs();
|
|
16986
|
+
const innerRect = attrs.innerRect;
|
|
16987
|
+
const paddingX = attrs.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
16988
|
+
const paddingY = attrs.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
16989
|
+
if (!innerRect) return {
|
|
16990
|
+
x: 0,
|
|
16991
|
+
y: 0,
|
|
16992
|
+
width: 1,
|
|
16993
|
+
height: 1
|
|
16994
|
+
};
|
|
16995
|
+
return getPolygonLabelTextBounds(innerRect, paddingX, paddingY);
|
|
16996
|
+
}
|
|
16997
|
+
scalePolygonByDimensions(polygon, nextProps, nodeInstance) {
|
|
16998
|
+
let points = polygon.getAttr("points");
|
|
16999
|
+
const propsMaxX = points.length ? Math.max(...points.map((p) => p.x)) : 0;
|
|
17000
|
+
const propsMaxY = points.length ? Math.max(...points.map((p) => p.y)) : 0;
|
|
17001
|
+
const wantWidth = nextProps.width;
|
|
17002
|
+
const wantHeight = nextProps.height;
|
|
17003
|
+
if (wantWidth === void 0 || wantHeight === void 0) return points;
|
|
17004
|
+
const sX = propsMaxX > 0 ? wantWidth / propsMaxX : 1;
|
|
17005
|
+
const sY = propsMaxY > 0 ? wantHeight / propsMaxY : 1;
|
|
17006
|
+
if (Math.abs(sX - 1) <= .001 && Math.abs(sY - 1) <= .001) return points;
|
|
17007
|
+
const scaledPoints = points.map((p) => ({
|
|
17008
|
+
x: p.x * sX,
|
|
17009
|
+
y: p.y * sY
|
|
17010
|
+
}));
|
|
17011
|
+
const prevInnerRect = polygon.getAttr("innerRect");
|
|
17012
|
+
if (prevInnerRect) {
|
|
17013
|
+
const scaledInnerRect = {
|
|
17014
|
+
tl: {
|
|
17015
|
+
x: prevInnerRect.tl.x * sX,
|
|
17016
|
+
y: prevInnerRect.tl.y * sY
|
|
17017
|
+
},
|
|
17018
|
+
tr: {
|
|
17019
|
+
x: prevInnerRect.tr.x * sX,
|
|
17020
|
+
y: prevInnerRect.tr.y * sY
|
|
17021
|
+
},
|
|
17022
|
+
bl: {
|
|
17023
|
+
x: prevInnerRect.bl.x * sX,
|
|
17024
|
+
y: prevInnerRect.bl.y * sY
|
|
17025
|
+
},
|
|
17026
|
+
br: {
|
|
17027
|
+
x: prevInnerRect.br.x * sX,
|
|
17028
|
+
y: prevInnerRect.br.y * sY
|
|
17029
|
+
}
|
|
17030
|
+
};
|
|
17031
|
+
polygon.setAttr("innerRect", scaledInnerRect);
|
|
17032
|
+
}
|
|
17033
|
+
polygon.setAttr("points", scaledPoints);
|
|
17034
|
+
points = scaledPoints;
|
|
17035
|
+
if (!this._transforming) this.instance.updateNode(this.serialize(nodeInstance));
|
|
17036
|
+
return points;
|
|
17037
|
+
}
|
|
17038
|
+
onLabelGrow(polygon, bgShape, borderShape, nodeInstance, neededHeight) {
|
|
17039
|
+
const livePoints = polygon.getAttr("points");
|
|
17040
|
+
const liveInnerRect = polygon.getAttr("innerRect");
|
|
17041
|
+
if (!liveInnerRect) return;
|
|
17042
|
+
const currentBoundsHeight = liveInnerRect.bl.y - liveInnerRect.tl.y;
|
|
17043
|
+
if (neededHeight <= currentBoundsHeight) return;
|
|
17044
|
+
const oldHeight = Math.max(...livePoints.map((p) => p.y));
|
|
17045
|
+
const scale = currentBoundsHeight > 0 ? neededHeight / currentBoundsHeight : 1;
|
|
17046
|
+
const newHeight = oldHeight * scale;
|
|
17047
|
+
const newPoints = livePoints.map((p) => ({
|
|
17048
|
+
...p,
|
|
17049
|
+
y: p.y * scale
|
|
17050
|
+
}));
|
|
17051
|
+
const newInnerRect = {
|
|
17052
|
+
tl: {
|
|
17053
|
+
...liveInnerRect.tl,
|
|
17054
|
+
y: liveInnerRect.tl.y * scale
|
|
17055
|
+
},
|
|
17056
|
+
tr: {
|
|
17057
|
+
...liveInnerRect.tr,
|
|
17058
|
+
y: liveInnerRect.tr.y * scale
|
|
17059
|
+
},
|
|
17060
|
+
bl: {
|
|
17061
|
+
...liveInnerRect.bl,
|
|
17062
|
+
y: liveInnerRect.bl.y * scale
|
|
17063
|
+
},
|
|
17064
|
+
br: {
|
|
17065
|
+
...liveInnerRect.br,
|
|
17066
|
+
y: liveInnerRect.br.y * scale
|
|
17067
|
+
}
|
|
17068
|
+
};
|
|
17069
|
+
polygon.setAttr("points", newPoints);
|
|
17070
|
+
polygon.setAttr("innerRect", newInnerRect);
|
|
17071
|
+
polygon.setAttr("height", newHeight);
|
|
17072
|
+
bgShape?.setAttr("points", newPoints);
|
|
17073
|
+
borderShape?.setAttr("points", newPoints);
|
|
17074
|
+
if (!this._transforming) this.instance.updateNode(this.serialize(nodeInstance));
|
|
17075
|
+
}
|
|
17076
|
+
triggerPolygonLabelEdit(polygon, props) {
|
|
17077
|
+
const onCommit = (labelText) => {
|
|
17078
|
+
const updatedGroup = this.instance.getStage().findOne(`#${props.id}`);
|
|
17079
|
+
if (!updatedGroup) return;
|
|
17080
|
+
const serialized = this.serialize(updatedGroup);
|
|
17081
|
+
serialized.props.labelText = labelText;
|
|
17082
|
+
this.instance.updateNode(serialized);
|
|
17083
|
+
};
|
|
17084
|
+
const currentLabelTextBounds = this.getLabelTextBounds(polygon);
|
|
17085
|
+
this.shapeLabelEditor.triggerEditMode(polygon, currentLabelTextBounds, onCommit, (neededShapeHeight) => {
|
|
17086
|
+
const liveAttrs = polygon.getAttrs();
|
|
17087
|
+
const livePoints = liveAttrs.points;
|
|
17088
|
+
const liveInnerRect = liveAttrs.innerRect;
|
|
17089
|
+
const liveInnerRectHeight = liveInnerRect.bl.y - liveInnerRect.tl.y;
|
|
17090
|
+
if (neededShapeHeight <= liveInnerRectHeight) return;
|
|
17091
|
+
const oldHeight = Math.max(...livePoints.map((p) => p.y));
|
|
17092
|
+
const scale = liveInnerRectHeight > 0 ? neededShapeHeight / liveInnerRectHeight : 1;
|
|
17093
|
+
const newHeight = oldHeight * scale;
|
|
17094
|
+
const newPoints = livePoints.map((p) => ({
|
|
17095
|
+
...p,
|
|
17096
|
+
y: p.y * scale
|
|
17097
|
+
}));
|
|
17098
|
+
const newInnerRect = {
|
|
17099
|
+
tl: {
|
|
17100
|
+
...liveInnerRect.tl,
|
|
17101
|
+
y: liveInnerRect.tl.y * scale
|
|
17102
|
+
},
|
|
17103
|
+
tr: {
|
|
17104
|
+
...liveInnerRect.tr,
|
|
17105
|
+
y: liveInnerRect.tr.y * scale
|
|
17106
|
+
},
|
|
17107
|
+
bl: {
|
|
17108
|
+
...liveInnerRect.bl,
|
|
17109
|
+
y: liveInnerRect.bl.y * scale
|
|
17110
|
+
},
|
|
17111
|
+
br: {
|
|
17112
|
+
...liveInnerRect.br,
|
|
17113
|
+
y: liveInnerRect.br.y * scale
|
|
17114
|
+
}
|
|
17115
|
+
};
|
|
17116
|
+
polygon.setAttrs({
|
|
17117
|
+
points: newPoints,
|
|
17118
|
+
innerRect: newInnerRect,
|
|
17119
|
+
height: newHeight
|
|
17120
|
+
});
|
|
17121
|
+
this.onUpdate(polygon, polygon.getAttrs());
|
|
17122
|
+
const newLabelTextBounds = this.getLabelTextBounds(polygon);
|
|
17123
|
+
this.shapeLabelEditor.repositionTextArea(polygon, newLabelTextBounds);
|
|
17124
|
+
});
|
|
17125
|
+
}
|
|
17126
|
+
scaleReset(group) {
|
|
17127
|
+
const scaleX = group.scaleX();
|
|
17128
|
+
const scaleY = group.scaleY();
|
|
17129
|
+
if (scaleX === 1 && scaleY === 1) return;
|
|
17130
|
+
const points = group.getAttr("points");
|
|
17131
|
+
const innerRect = group.getAttr("innerRect");
|
|
17132
|
+
const newPoints = points.map((p) => ({
|
|
17133
|
+
x: p.x * scaleX,
|
|
17134
|
+
y: p.y * scaleY
|
|
17135
|
+
}));
|
|
17136
|
+
const newInnerRect = innerRect ? {
|
|
17137
|
+
tl: {
|
|
17138
|
+
x: innerRect.tl.x * scaleX,
|
|
17139
|
+
y: innerRect.tl.y * scaleY
|
|
17140
|
+
},
|
|
17141
|
+
tr: {
|
|
17142
|
+
x: innerRect.tr.x * scaleX,
|
|
17143
|
+
y: innerRect.tr.y * scaleY
|
|
17144
|
+
},
|
|
17145
|
+
bl: {
|
|
17146
|
+
x: innerRect.bl.x * scaleX,
|
|
17147
|
+
y: innerRect.bl.y * scaleY
|
|
17148
|
+
},
|
|
17149
|
+
br: {
|
|
17150
|
+
x: innerRect.br.x * scaleX,
|
|
17151
|
+
y: innerRect.br.y * scaleY
|
|
17152
|
+
}
|
|
17153
|
+
} : void 0;
|
|
17154
|
+
const absTransform = group.getAbsoluteTransform().copy();
|
|
17155
|
+
group.setAttr("points", newPoints);
|
|
17156
|
+
if (newInnerRect) group.setAttr("innerRect", newInnerRect);
|
|
17157
|
+
group.scaleX(1);
|
|
17158
|
+
group.scaleY(1);
|
|
17159
|
+
group.setAttr("width", Math.max(...newPoints.map((p) => p.x)));
|
|
17160
|
+
group.setAttr("height", Math.max(...newPoints.map((p) => p.y)));
|
|
17161
|
+
const newTransform = group.getAbsoluteTransform();
|
|
17162
|
+
const dx = absTransform.m[4] - newTransform.m[4];
|
|
17163
|
+
const dy = absTransform.m[5] - newTransform.m[5];
|
|
17164
|
+
group.x(group.x() + dx);
|
|
17165
|
+
group.y(group.y() + dy);
|
|
17166
|
+
}
|
|
17167
|
+
onRender(props) {
|
|
17168
|
+
const polygon = new Konva.Group({
|
|
17169
|
+
...props,
|
|
17170
|
+
name: "node"
|
|
17171
|
+
});
|
|
17172
|
+
const points = polygon.getAttr("points");
|
|
17173
|
+
const strokeWidth = props.strokeWidth || 0;
|
|
17174
|
+
const bgShape = new Konva.Shape({
|
|
15545
17175
|
id: `${props.id}-bg`,
|
|
15546
17176
|
nodeId: props.id,
|
|
15547
|
-
|
|
15548
|
-
|
|
15549
|
-
sides,
|
|
15550
|
-
radius,
|
|
17177
|
+
points,
|
|
17178
|
+
...computePolygonBounds(points),
|
|
15551
17179
|
fill: props.fill || "transparent",
|
|
15552
17180
|
strokeWidth: 0,
|
|
15553
|
-
strokeScaleEnabled:
|
|
15554
|
-
|
|
17181
|
+
strokeScaleEnabled: false,
|
|
17182
|
+
sceneFunc
|
|
15555
17183
|
});
|
|
15556
|
-
|
|
15557
|
-
|
|
15558
|
-
|
|
15559
|
-
regularPolygon.add(internalRPBg);
|
|
15560
|
-
const internalRPBorder = new Konva.RegularPolygon({
|
|
15561
|
-
...props,
|
|
15562
|
-
name: void 0,
|
|
17184
|
+
bgShape.getSelfRect = polygonSelfRect.bind(bgShape);
|
|
17185
|
+
polygon.add(bgShape);
|
|
17186
|
+
const borderShape = new Konva.Shape({
|
|
15563
17187
|
id: `${props.id}-border`,
|
|
15564
|
-
|
|
15565
|
-
y: radius,
|
|
15566
|
-
sides,
|
|
15567
|
-
radius: radius - (props.strokeWidth || 0) / 2,
|
|
17188
|
+
points,
|
|
15568
17189
|
fill: "transparent",
|
|
15569
|
-
|
|
15570
|
-
|
|
15571
|
-
|
|
15572
|
-
|
|
15573
|
-
|
|
15574
|
-
|
|
15575
|
-
|
|
15576
|
-
|
|
15577
|
-
|
|
15578
|
-
|
|
15579
|
-
|
|
15580
|
-
|
|
17190
|
+
stroke: props.stroke || "transparent",
|
|
17191
|
+
strokeWidth: 0,
|
|
17192
|
+
innerStrokeWidth: strokeWidth,
|
|
17193
|
+
strokeScaleEnabled: false,
|
|
17194
|
+
listening: false,
|
|
17195
|
+
sceneFunc: borderSceneFunc
|
|
17196
|
+
});
|
|
17197
|
+
borderShape.getSelfRect = polygonSelfRect.bind(borderShape);
|
|
17198
|
+
polygon.add(borderShape);
|
|
17199
|
+
const innerRect = polygon.getAttr("innerRect");
|
|
17200
|
+
const paddingX = props.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
17201
|
+
const paddingY = props.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
17202
|
+
const labelTextBounds = innerRect ? getPolygonLabelTextBounds(innerRect, paddingX, paddingY) : {
|
|
17203
|
+
x: 0,
|
|
17204
|
+
y: 0,
|
|
17205
|
+
width: 1,
|
|
17206
|
+
height: 1
|
|
17207
|
+
};
|
|
17208
|
+
this.shapeLabelEditor.renderLabel(polygon, props, labelTextBounds);
|
|
17209
|
+
borderShape.moveToTop();
|
|
17210
|
+
bgShape.moveToBottom();
|
|
17211
|
+
this.setupDefaultNodeAugmentation(polygon);
|
|
15581
17212
|
const defaultTransformerProperties = this.defaultGetTransformerProperties(this.config.transform);
|
|
15582
|
-
|
|
17213
|
+
polygon.getTransformerProperties = function() {
|
|
15583
17214
|
return {
|
|
15584
17215
|
...defaultTransformerProperties,
|
|
15585
17216
|
enabledAnchors: [
|
|
15586
17217
|
"top-left",
|
|
17218
|
+
"top-center",
|
|
15587
17219
|
"top-right",
|
|
17220
|
+
"middle-right",
|
|
17221
|
+
"middle-left",
|
|
15588
17222
|
"bottom-left",
|
|
17223
|
+
"bottom-center",
|
|
15589
17224
|
"bottom-right"
|
|
15590
17225
|
],
|
|
15591
|
-
keepRatio:
|
|
17226
|
+
keepRatio: false
|
|
15592
17227
|
};
|
|
15593
17228
|
};
|
|
15594
|
-
|
|
17229
|
+
polygon.allowedAnchors = function() {
|
|
15595
17230
|
return [
|
|
15596
17231
|
"top-left",
|
|
17232
|
+
"top-center",
|
|
15597
17233
|
"top-right",
|
|
17234
|
+
"middle-right",
|
|
17235
|
+
"middle-left",
|
|
15598
17236
|
"bottom-left",
|
|
17237
|
+
"bottom-center",
|
|
15599
17238
|
"bottom-right"
|
|
15600
17239
|
];
|
|
15601
17240
|
};
|
|
15602
|
-
this.setupDefaultNodeEvents(
|
|
15603
|
-
|
|
17241
|
+
this.setupDefaultNodeEvents(polygon);
|
|
17242
|
+
polygon.on("transformstart", () => {
|
|
17243
|
+
this._transforming = true;
|
|
17244
|
+
});
|
|
17245
|
+
polygon.on("transform", () => {
|
|
17246
|
+
this.scaleReset(polygon);
|
|
17247
|
+
this.onUpdate(polygon, polygon.getAttrs());
|
|
17248
|
+
});
|
|
17249
|
+
polygon.on("transformend", () => {
|
|
17250
|
+
this._transforming = false;
|
|
17251
|
+
});
|
|
17252
|
+
polygon.dblClick = () => {
|
|
17253
|
+
if (this.shapeLabelEditor.isEditing()) return;
|
|
17254
|
+
if (!(this.isSelecting() && this.isNodeSelected(polygon))) return;
|
|
17255
|
+
this.triggerPolygonLabelEdit(polygon, props);
|
|
17256
|
+
};
|
|
17257
|
+
polygon.getNodeMinSize = () => {
|
|
17258
|
+
return computePolygonLabelMinSize(this.instance.getStage(), polygon);
|
|
17259
|
+
};
|
|
17260
|
+
return polygon;
|
|
15604
17261
|
}
|
|
15605
17262
|
onUpdate(nodeInstance, nextProps) {
|
|
15606
17263
|
nodeInstance.setAttrs({ ...nextProps });
|
|
15607
|
-
const
|
|
15608
|
-
const
|
|
15609
|
-
const
|
|
15610
|
-
const
|
|
15611
|
-
|
|
15612
|
-
|
|
15613
|
-
|
|
15614
|
-
...
|
|
15615
|
-
name: void 0,
|
|
15616
|
-
id: `${nextProps.id}-bg`,
|
|
15617
|
-
nodeId: nextProps.id,
|
|
15618
|
-
x: radius,
|
|
15619
|
-
y: radius,
|
|
15620
|
-
sides,
|
|
15621
|
-
radius,
|
|
17264
|
+
const polygon = nodeInstance;
|
|
17265
|
+
const strokeWidth = nextProps.strokeWidth || 0;
|
|
17266
|
+
const points = this.scalePolygonByDimensions(polygon, nextProps, nodeInstance);
|
|
17267
|
+
const bgShape = polygon.findOne(`#${nextProps.id}-bg`);
|
|
17268
|
+
if (bgShape) {
|
|
17269
|
+
bgShape.setAttrs({
|
|
17270
|
+
points,
|
|
17271
|
+
...computePolygonBounds(points),
|
|
15622
17272
|
fill: nextProps.fill || "transparent",
|
|
15623
17273
|
strokeWidth: 0,
|
|
15624
|
-
strokeScaleEnabled:
|
|
15625
|
-
rotation: 0
|
|
17274
|
+
strokeScaleEnabled: false
|
|
15626
17275
|
});
|
|
15627
|
-
|
|
15628
|
-
internalRPBg.x(internalRPBg.x() - internalRPBgBox.x);
|
|
15629
|
-
internalRPBg.y(internalRPBg.y() - internalRPBgBox.y);
|
|
15630
|
-
internalRPBg.moveToBottom();
|
|
17276
|
+
bgShape.moveToBottom();
|
|
15631
17277
|
}
|
|
15632
|
-
|
|
15633
|
-
|
|
15634
|
-
|
|
15635
|
-
|
|
15636
|
-
|
|
15637
|
-
|
|
15638
|
-
|
|
15639
|
-
|
|
15640
|
-
|
|
15641
|
-
|
|
15642
|
-
|
|
15643
|
-
|
|
15644
|
-
|
|
15645
|
-
|
|
15646
|
-
|
|
15647
|
-
|
|
15648
|
-
|
|
15649
|
-
|
|
15650
|
-
|
|
17278
|
+
const borderShape = polygon.findOne(`#${nextProps.id}-border`);
|
|
17279
|
+
if (borderShape) borderShape.setAttrs({
|
|
17280
|
+
points,
|
|
17281
|
+
fill: "transparent",
|
|
17282
|
+
stroke: nextProps.stroke || "transparent",
|
|
17283
|
+
strokeWidth: 0,
|
|
17284
|
+
innerStrokeWidth: strokeWidth,
|
|
17285
|
+
strokeScaleEnabled: false,
|
|
17286
|
+
listening: false
|
|
17287
|
+
});
|
|
17288
|
+
const paddingX = nextProps.labelPaddingX ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingX;
|
|
17289
|
+
const paddingY = nextProps.labelPaddingY ?? WEAVE_SHAPE_LABEL_DEFAULTS.labelPaddingY;
|
|
17290
|
+
const innerRect = polygon.getAttr("innerRect");
|
|
17291
|
+
const labelTextBounds = innerRect ? getPolygonLabelTextBounds(innerRect, paddingX, paddingY) : {
|
|
17292
|
+
x: 0,
|
|
17293
|
+
y: 0,
|
|
17294
|
+
width: 1,
|
|
17295
|
+
height: 1
|
|
17296
|
+
};
|
|
17297
|
+
this.shapeLabelEditor.updateLabel(polygon, nextProps, labelTextBounds, (neededHeight) => this.onLabelGrow(polygon, bgShape, borderShape, nodeInstance, neededHeight));
|
|
17298
|
+
const labelNode = polygon.findOne(`#${labelId(nextProps.id)}`);
|
|
17299
|
+
if (labelNode) {
|
|
17300
|
+
labelNode.moveToTop();
|
|
17301
|
+
borderShape?.moveToTop();
|
|
15651
17302
|
}
|
|
15652
17303
|
const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
15653
|
-
if (nodesSelectionPlugin)
|
|
15654
|
-
const actualSelectedNodes = nodesSelectionPlugin.getSelectedNodes();
|
|
15655
|
-
nodesSelectionPlugin.setSelectedNodes(actualSelectedNodes);
|
|
15656
|
-
nodesSelectionPlugin.getTransformer().forceUpdate();
|
|
15657
|
-
}
|
|
15658
|
-
}
|
|
15659
|
-
scaleReset(node) {
|
|
15660
|
-
const absTransform = node.getAbsoluteTransform().copy();
|
|
15661
|
-
const radius = node.getAttr("radius");
|
|
15662
|
-
node.setAttrs({ radius: radius * node.scaleX() });
|
|
15663
|
-
node.scaleX(1);
|
|
15664
|
-
node.scaleY(1);
|
|
15665
|
-
const newTransform = node.getAbsoluteTransform();
|
|
15666
|
-
const dx = absTransform.m[4] - newTransform.m[4];
|
|
15667
|
-
const dy = absTransform.m[5] - newTransform.m[5];
|
|
15668
|
-
node.x(node.x() + dx);
|
|
15669
|
-
node.y(node.y() + dy);
|
|
17304
|
+
if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
|
|
15670
17305
|
}
|
|
15671
|
-
realOffset(
|
|
17306
|
+
realOffset(_element) {
|
|
15672
17307
|
return {
|
|
15673
|
-
x:
|
|
15674
|
-
y:
|
|
17308
|
+
x: 0,
|
|
17309
|
+
y: 0
|
|
15675
17310
|
};
|
|
15676
17311
|
}
|
|
15677
17312
|
static defaultState(nodeId) {
|
|
17313
|
+
const preset = WEAVE_POLYGON_PRESETS.pentagon;
|
|
17314
|
+
const { points, innerRect, width, height } = instantiatePreset(preset, preset.defaultWidth, preset.defaultHeight);
|
|
15678
17315
|
return {
|
|
15679
17316
|
...super.defaultState(nodeId),
|
|
15680
|
-
type:
|
|
17317
|
+
type: WEAVE_POLYGON_NODE_TYPE,
|
|
15681
17318
|
props: {
|
|
15682
17319
|
...super.defaultState(nodeId).props,
|
|
15683
|
-
nodeType:
|
|
17320
|
+
nodeType: WEAVE_POLYGON_NODE_TYPE,
|
|
15684
17321
|
x: 0,
|
|
15685
17322
|
y: 0,
|
|
15686
|
-
|
|
15687
|
-
|
|
17323
|
+
width,
|
|
17324
|
+
height,
|
|
17325
|
+
sides: preset.sides,
|
|
17326
|
+
points,
|
|
17327
|
+
innerRect,
|
|
15688
17328
|
stroke: "#000000",
|
|
15689
17329
|
fill: "#FFFFFF",
|
|
15690
17330
|
strokeWidth: 1,
|
|
15691
|
-
strokeScaleEnabled:
|
|
17331
|
+
strokeScaleEnabled: false,
|
|
15692
17332
|
rotation: 0,
|
|
15693
17333
|
zIndex: 1,
|
|
15694
|
-
children: []
|
|
17334
|
+
children: [],
|
|
17335
|
+
...WEAVE_SHAPE_LABEL_DEFAULTS
|
|
15695
17336
|
}
|
|
15696
17337
|
};
|
|
15697
17338
|
}
|
|
@@ -15699,38 +17340,103 @@ var WeaveRegularPolygonNode = class extends WeaveNode {
|
|
|
15699
17340
|
return mergeExceptArrays(defaultNodeState, { props: {
|
|
15700
17341
|
x: props.x,
|
|
15701
17342
|
y: props.y,
|
|
17343
|
+
width: props.width,
|
|
17344
|
+
height: props.height,
|
|
15702
17345
|
sides: props.sides,
|
|
15703
|
-
|
|
17346
|
+
points: props.points,
|
|
17347
|
+
innerRect: props.innerRect,
|
|
15704
17348
|
rotation: props.rotation,
|
|
15705
17349
|
fill: props.fill,
|
|
15706
17350
|
...props.stroke && { stroke: props.stroke },
|
|
15707
|
-
...props.strokeWidth && { strokeWidth: props.strokeWidth }
|
|
17351
|
+
...props.strokeWidth !== void 0 && { strokeWidth: props.strokeWidth },
|
|
17352
|
+
...props.labelText !== void 0 && { labelText: props.labelText },
|
|
17353
|
+
...props.labelFontFamily !== void 0 && { labelFontFamily: props.labelFontFamily },
|
|
17354
|
+
...props.labelFontSize !== void 0 && { labelFontSize: props.labelFontSize },
|
|
17355
|
+
...props.labelFontStyle !== void 0 && { labelFontStyle: props.labelFontStyle },
|
|
17356
|
+
...props.labelFontVariant !== void 0 && { labelFontVariant: props.labelFontVariant },
|
|
17357
|
+
...props.labelFill !== void 0 && { labelFill: props.labelFill },
|
|
17358
|
+
...props.labelAlign !== void 0 && { labelAlign: props.labelAlign },
|
|
17359
|
+
...props.labelVerticalAlign !== void 0 && { labelVerticalAlign: props.labelVerticalAlign },
|
|
17360
|
+
...props.labelLetterSpacing !== void 0 && { labelLetterSpacing: props.labelLetterSpacing },
|
|
17361
|
+
...props.labelLineHeight !== void 0 && { labelLineHeight: props.labelLineHeight },
|
|
17362
|
+
...props.labelPaddingX !== void 0 && { labelPaddingX: props.labelPaddingX },
|
|
17363
|
+
...props.labelPaddingY !== void 0 && { labelPaddingY: props.labelPaddingY }
|
|
15708
17364
|
} });
|
|
15709
17365
|
}
|
|
15710
17366
|
static updateNodeState(prevNodeState, nextProps) {
|
|
15711
17367
|
return mergeExceptArrays(prevNodeState, { props: {
|
|
15712
17368
|
x: nextProps.x,
|
|
15713
17369
|
y: nextProps.y,
|
|
17370
|
+
...nextProps.width !== void 0 && { width: nextProps.width },
|
|
17371
|
+
...nextProps.height !== void 0 && { height: nextProps.height },
|
|
15714
17372
|
sides: nextProps.sides,
|
|
15715
|
-
|
|
17373
|
+
points: nextProps.points,
|
|
17374
|
+
innerRect: nextProps.innerRect,
|
|
15716
17375
|
rotation: nextProps.rotation,
|
|
15717
17376
|
fill: nextProps.fill,
|
|
15718
17377
|
...nextProps.stroke && { stroke: nextProps.stroke },
|
|
15719
|
-
...nextProps.strokeWidth && { strokeWidth: nextProps.strokeWidth }
|
|
17378
|
+
...nextProps.strokeWidth !== void 0 && { strokeWidth: nextProps.strokeWidth },
|
|
17379
|
+
...nextProps.labelText !== void 0 && { labelText: nextProps.labelText },
|
|
17380
|
+
...nextProps.labelFontFamily !== void 0 && { labelFontFamily: nextProps.labelFontFamily },
|
|
17381
|
+
...nextProps.labelFontSize !== void 0 && { labelFontSize: nextProps.labelFontSize },
|
|
17382
|
+
...nextProps.labelFontStyle !== void 0 && { labelFontStyle: nextProps.labelFontStyle },
|
|
17383
|
+
...nextProps.labelFontVariant !== void 0 && { labelFontVariant: nextProps.labelFontVariant },
|
|
17384
|
+
...nextProps.labelFill !== void 0 && { labelFill: nextProps.labelFill },
|
|
17385
|
+
...nextProps.labelAlign !== void 0 && { labelAlign: nextProps.labelAlign },
|
|
17386
|
+
...nextProps.labelVerticalAlign !== void 0 && { labelVerticalAlign: nextProps.labelVerticalAlign },
|
|
17387
|
+
...nextProps.labelLetterSpacing !== void 0 && { labelLetterSpacing: nextProps.labelLetterSpacing },
|
|
17388
|
+
...nextProps.labelLineHeight !== void 0 && { labelLineHeight: nextProps.labelLineHeight },
|
|
17389
|
+
...nextProps.labelPaddingX !== void 0 && { labelPaddingX: nextProps.labelPaddingX },
|
|
17390
|
+
...nextProps.labelPaddingY !== void 0 && { labelPaddingY: nextProps.labelPaddingY }
|
|
15720
17391
|
} });
|
|
15721
17392
|
}
|
|
15722
17393
|
static getSchema() {
|
|
15723
17394
|
const baseSchema = super.getSchema();
|
|
15724
17395
|
const nodeSchema = baseSchema.extend({
|
|
15725
|
-
type: z.literal(
|
|
17396
|
+
type: z.literal(WEAVE_POLYGON_NODE_TYPE).describe(`Type of the node, for a polygon node it will always be "${WEAVE_POLYGON_NODE_TYPE}"`),
|
|
15726
17397
|
props: baseSchema.shape.props.extend({
|
|
15727
|
-
nodeType: z.literal(
|
|
15728
|
-
sides: z.number().describe("Number of sides of the
|
|
15729
|
-
|
|
15730
|
-
|
|
15731
|
-
|
|
15732
|
-
|
|
15733
|
-
|
|
17398
|
+
nodeType: z.literal(WEAVE_POLYGON_NODE_TYPE).describe(`Type of the node, for a polygon node it will always be "${WEAVE_POLYGON_NODE_TYPE}"`),
|
|
17399
|
+
sides: z.number().describe("Number of sides of the polygon (3 or more)"),
|
|
17400
|
+
width: z.number().optional().describe("Visual width of the polygon in pixels (= maxX of vertices). Setting this rescales vertices proportionally."),
|
|
17401
|
+
height: z.number().optional().describe("Visual height of the polygon in pixels (= maxY of vertices). Setting this rescales vertices proportionally."),
|
|
17402
|
+
points: z.array(z.object({
|
|
17403
|
+
x: z.number(),
|
|
17404
|
+
y: z.number()
|
|
17405
|
+
})).describe("Vertex positions of the polygon in group-local pixel space"),
|
|
17406
|
+
innerRect: z.object({
|
|
17407
|
+
tl: z.object({
|
|
17408
|
+
x: z.number(),
|
|
17409
|
+
y: z.number()
|
|
17410
|
+
}),
|
|
17411
|
+
tr: z.object({
|
|
17412
|
+
x: z.number(),
|
|
17413
|
+
y: z.number()
|
|
17414
|
+
}),
|
|
17415
|
+
bl: z.object({
|
|
17416
|
+
x: z.number(),
|
|
17417
|
+
y: z.number()
|
|
17418
|
+
}),
|
|
17419
|
+
br: z.object({
|
|
17420
|
+
x: z.number(),
|
|
17421
|
+
y: z.number()
|
|
17422
|
+
})
|
|
17423
|
+
}).describe("Largest inscribed axis-aligned rectangle inside the polygon (used for label bounds)"),
|
|
17424
|
+
fill: z.string().describe("Fill color of the polygon in hex format with alpha channel (e.g. #RRGGBBAA)"),
|
|
17425
|
+
stroke: z.string().describe("Stroke color of the polygon in hex format with alpha channel (e.g. #RRGGBBAA)"),
|
|
17426
|
+
strokeWidth: z.number().describe("Stroke width of the polygon in pixels"),
|
|
17427
|
+
strokeScaleEnabled: z.boolean().describe("Whether the polygon stroke width should scale when the node is scaled. Defaults to false."),
|
|
17428
|
+
labelText: z.string().optional().describe("Text label displayed inside the polygon"),
|
|
17429
|
+
labelFontFamily: z.string().optional().describe("Font family for the label text"),
|
|
17430
|
+
labelFontSize: z.number().optional().describe("Font size for the label text in pixels"),
|
|
17431
|
+
labelFontStyle: z.string().optional().describe("Font style for the label text (e.g. \"normal\", \"bold\", \"italic\", \"bold italic\")"),
|
|
17432
|
+
labelFontVariant: z.string().optional().describe("Font variant for the label text (e.g. \"normal\", \"small-caps\")"),
|
|
17433
|
+
labelFill: z.string().optional().describe("Color of the label text in hex format (e.g. #RRGGBBAA)"),
|
|
17434
|
+
labelAlign: z.string().optional().describe("Horizontal alignment of the label text (\"left\", \"center\", \"right\")"),
|
|
17435
|
+
labelVerticalAlign: z.string().optional().describe("Vertical alignment of the label text (\"top\", \"middle\", \"bottom\")"),
|
|
17436
|
+
labelLetterSpacing: z.number().optional().describe("Letter spacing for the label text in pixels"),
|
|
17437
|
+
labelLineHeight: z.number().optional().describe("Line height multiplier for the label text"),
|
|
17438
|
+
labelPaddingX: z.number().optional().describe("Horizontal inset (padding) in pixels applied on each side of the label"),
|
|
17439
|
+
labelPaddingY: z.number().optional().describe("Vertical inset (padding) in pixels applied on top and bottom of the label")
|
|
15734
17440
|
})
|
|
15735
17441
|
});
|
|
15736
17442
|
return nodeSchema;
|
|
@@ -21629,6 +23335,7 @@ var WeaveRectangleToolAction = class extends WeaveAction {
|
|
|
21629
23335
|
if (node) selectionPlugin.setSelectedNodes([node]);
|
|
21630
23336
|
this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
|
|
21631
23337
|
}
|
|
23338
|
+
if (this.tempRectNode) this.tempRectNode.destroy();
|
|
21632
23339
|
this.rectId = null;
|
|
21633
23340
|
this.tempRectNode = null;
|
|
21634
23341
|
this.moved = false;
|
|
@@ -24739,6 +26446,137 @@ var WeaveRegularPolygonToolAction = class extends WeaveAction {
|
|
|
24739
26446
|
}
|
|
24740
26447
|
};
|
|
24741
26448
|
|
|
26449
|
+
//#endregion
|
|
26450
|
+
//#region src/actions/polygon-tool/constants.ts
|
|
26451
|
+
const POLYGON_TOOL_ACTION_NAME = "polygonTool";
|
|
26452
|
+
const POLYGON_TOOL_STATE = {
|
|
26453
|
+
["IDLE"]: "idle",
|
|
26454
|
+
["ADDING"]: "adding",
|
|
26455
|
+
["ADDED"]: "added"
|
|
26456
|
+
};
|
|
26457
|
+
|
|
26458
|
+
//#endregion
|
|
26459
|
+
//#region src/actions/polygon-tool/polygon-tool.ts
|
|
26460
|
+
var WeavePolygonToolAction = class extends WeaveAction {
|
|
26461
|
+
initialized = false;
|
|
26462
|
+
onPropsChange = void 0;
|
|
26463
|
+
onInit = void 0;
|
|
26464
|
+
constructor(preset) {
|
|
26465
|
+
super();
|
|
26466
|
+
this.preset = preset ?? "pentagon";
|
|
26467
|
+
this.initialize();
|
|
26468
|
+
}
|
|
26469
|
+
initialize() {
|
|
26470
|
+
this.initialized = false;
|
|
26471
|
+
this.state = POLYGON_TOOL_STATE.IDLE;
|
|
26472
|
+
this.polygonId = null;
|
|
26473
|
+
this.props = this.initProps();
|
|
26474
|
+
}
|
|
26475
|
+
getName() {
|
|
26476
|
+
return POLYGON_TOOL_ACTION_NAME;
|
|
26477
|
+
}
|
|
26478
|
+
initProps() {
|
|
26479
|
+
return {
|
|
26480
|
+
opacity: 1,
|
|
26481
|
+
fill: "#ffffffff",
|
|
26482
|
+
stroke: "#000000ff",
|
|
26483
|
+
strokeWidth: 1
|
|
26484
|
+
};
|
|
26485
|
+
}
|
|
26486
|
+
getPolygonsPresets() {
|
|
26487
|
+
return WEAVE_POLYGON_PRESETS;
|
|
26488
|
+
}
|
|
26489
|
+
getPolygonPreset() {
|
|
26490
|
+
return this.preset;
|
|
26491
|
+
}
|
|
26492
|
+
setPolygonPreset(preset) {
|
|
26493
|
+
this.preset = preset;
|
|
26494
|
+
}
|
|
26495
|
+
setupEvents() {
|
|
26496
|
+
const stage = this.instance.getStage();
|
|
26497
|
+
window.addEventListener("keydown", (e) => {
|
|
26498
|
+
if ((e.code === "Enter" || e.code === "Escape") && this.instance.getActiveAction() === POLYGON_TOOL_ACTION_NAME) this.cancelAction();
|
|
26499
|
+
}, { signal: this.instance.getEventsController().signal });
|
|
26500
|
+
stage.on("pointermove", () => {
|
|
26501
|
+
if (this.state === POLYGON_TOOL_STATE.IDLE) return;
|
|
26502
|
+
this.setCursor();
|
|
26503
|
+
});
|
|
26504
|
+
stage.on("pointerdown", (e) => {
|
|
26505
|
+
this.setTapStart(e);
|
|
26506
|
+
if (this.state !== POLYGON_TOOL_STATE.ADDING) return;
|
|
26507
|
+
this.handleAdding();
|
|
26508
|
+
});
|
|
26509
|
+
this.initialized = true;
|
|
26510
|
+
}
|
|
26511
|
+
setState(state) {
|
|
26512
|
+
this.state = state;
|
|
26513
|
+
}
|
|
26514
|
+
addPolygon() {
|
|
26515
|
+
this.setCursor();
|
|
26516
|
+
this.setFocusStage();
|
|
26517
|
+
this.instance.emitEvent("onAddingPolygon");
|
|
26518
|
+
this.setState(POLYGON_TOOL_STATE.ADDING);
|
|
26519
|
+
}
|
|
26520
|
+
handleAdding() {
|
|
26521
|
+
const { mousePoint, container } = this.instance.getMousePointer();
|
|
26522
|
+
this.polygonId = v4_default();
|
|
26523
|
+
const presetDef = WEAVE_POLYGON_PRESETS[this.preset];
|
|
26524
|
+
const scaleFactor = this.props.scaleFactor ?? 1;
|
|
26525
|
+
const { points, innerRect, width, height } = instantiatePreset(presetDef, presetDef.defaultWidth * scaleFactor, presetDef.defaultHeight * scaleFactor);
|
|
26526
|
+
const nodeHandler = this.instance.getNodeHandler(WEAVE_POLYGON_NODE_TYPE);
|
|
26527
|
+
if (nodeHandler) {
|
|
26528
|
+
const node = nodeHandler.create(this.polygonId, {
|
|
26529
|
+
...this.props,
|
|
26530
|
+
x: mousePoint?.x ?? 0,
|
|
26531
|
+
y: mousePoint?.y ?? 0,
|
|
26532
|
+
width,
|
|
26533
|
+
height,
|
|
26534
|
+
sides: presetDef.sides,
|
|
26535
|
+
points,
|
|
26536
|
+
innerRect
|
|
26537
|
+
});
|
|
26538
|
+
this.instance.addNode(node, container?.getAttrs().id);
|
|
26539
|
+
}
|
|
26540
|
+
this.instance.emitEvent("onAddedPolygon");
|
|
26541
|
+
this.cancelAction();
|
|
26542
|
+
}
|
|
26543
|
+
trigger(cancelAction, params) {
|
|
26544
|
+
if (!this.instance) throw new Error("Instance not defined");
|
|
26545
|
+
if (!this.initialized) this.setupEvents();
|
|
26546
|
+
this.preset = params?.presetId ?? "pentagon";
|
|
26547
|
+
const stage = this.instance.getStage();
|
|
26548
|
+
stage.container().tabIndex = 1;
|
|
26549
|
+
stage.container().focus();
|
|
26550
|
+
this.cancelAction = cancelAction;
|
|
26551
|
+
const selectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
26552
|
+
if (selectionPlugin) selectionPlugin.setSelectedNodes([]);
|
|
26553
|
+
this.props = this.initProps();
|
|
26554
|
+
this.addPolygon();
|
|
26555
|
+
}
|
|
26556
|
+
cleanup() {
|
|
26557
|
+
const stage = this.instance.getStage();
|
|
26558
|
+
stage.container().style.cursor = "default";
|
|
26559
|
+
const selectionPlugin = this.instance.getPlugin("nodesSelection");
|
|
26560
|
+
if (selectionPlugin) {
|
|
26561
|
+
const node = stage.findOne(`#${this.polygonId}`);
|
|
26562
|
+
if (node) selectionPlugin.setSelectedNodes([node]);
|
|
26563
|
+
this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
|
|
26564
|
+
}
|
|
26565
|
+
this.polygonId = null;
|
|
26566
|
+
this.setState(POLYGON_TOOL_STATE.IDLE);
|
|
26567
|
+
}
|
|
26568
|
+
setCursor() {
|
|
26569
|
+
const stage = this.instance.getStage();
|
|
26570
|
+
stage.container().style.cursor = "crosshair";
|
|
26571
|
+
}
|
|
26572
|
+
setFocusStage() {
|
|
26573
|
+
const stage = this.instance.getStage();
|
|
26574
|
+
stage.container().tabIndex = 1;
|
|
26575
|
+
stage.container().blur();
|
|
26576
|
+
stage.container().focus();
|
|
26577
|
+
}
|
|
26578
|
+
};
|
|
26579
|
+
|
|
24742
26580
|
//#endregion
|
|
24743
26581
|
//#region src/actions/frame-tool/constants.ts
|
|
24744
26582
|
const FRAME_TOOL_ACTION_NAME = "frameTool";
|
|
@@ -30835,14 +32673,20 @@ var WeaveNodesSnappingPlugin = class extends WeavePlugin {
|
|
|
30835
32673
|
}
|
|
30836
32674
|
return updatedBox;
|
|
30837
32675
|
};
|
|
30838
|
-
const
|
|
30839
|
-
|
|
32676
|
+
const snapBoundingBoxFunc = boundingBoxFunc.bind(this);
|
|
32677
|
+
const newBoundFunc = (oldBox, newBox) => {
|
|
32678
|
+
const mainBoundBoxFunc = nodesSelectionPlugin.getBoundBoxFunc();
|
|
32679
|
+
const actualBox = mainBoundBoxFunc(oldBox, newBox);
|
|
32680
|
+
if (actualBox === oldBox) return actualBox;
|
|
32681
|
+
return snapBoundingBoxFunc(oldBox, newBox);
|
|
32682
|
+
};
|
|
32683
|
+
tr.boundBoxFunc(newBoundFunc);
|
|
30840
32684
|
}
|
|
30841
32685
|
transformEndHandler() {
|
|
30842
32686
|
const nodesSelectionPlugin = this.getNodesSelectionPlugin();
|
|
30843
32687
|
if (nodesSelectionPlugin) {
|
|
30844
32688
|
const tr = nodesSelectionPlugin.getTransformer();
|
|
30845
|
-
tr.boundBoxFunc(
|
|
32689
|
+
tr.boundBoxFunc(nodesSelectionPlugin.getBoundBoxFunc());
|
|
30846
32690
|
}
|
|
30847
32691
|
this.snappingGuides = [];
|
|
30848
32692
|
}
|
|
@@ -31086,4 +32930,4 @@ function getJSONFromYjsBinary(actualState) {
|
|
|
31086
32930
|
}
|
|
31087
32931
|
|
|
31088
32932
|
//#endregion
|
|
31089
|
-
export { ALIGN_NODES_ALIGN_TO, ALIGN_NODES_TOOL_ACTION_NAME, ALIGN_NODES_TOOL_STATE, BRUSH_TOOL_ACTION_NAME, BRUSH_TOOL_DEFAULT_CONFIG, BRUSH_TOOL_STATE, CONNECTOR_TOOL_ACTION_NAME, CONNECTOR_TOOL_DEFAULT_CONFIG, CONNECTOR_TOOL_STATE, COPY_PASTE_NODES_PLUGIN_STATE, DEFAULT_GUIDE_TOOL_ACTION_CONFIG, DEFAULT_SNAPPING_MANAGER_CONFIG, ELLIPSE_TOOL_ACTION_NAME, ELLIPSE_TOOL_STATE, ERASER_TOOL_ACTION_NAME, ERASER_TOOL_STATE, FRAME_TOOL_ACTION_NAME, FRAME_TOOL_STATE, GUIDE_DISTANCE_NAME, GUIDE_DISTANCE_ORIGIN, GUIDE_KIND, GUIDE_NAME, GUIDE_ORIENTATION, GUIDE_STATE, GUIDE_TOOL_ACTION_NAME, GUIDE_TOOL_STATE, LINE_TOOL_ACTION_NAME, LINE_TOOL_DEFAULT_CONFIG, LINE_TOOL_STATE, MEASURE_TOOL_ACTION_NAME, MEASURE_TOOL_STATE, MOVE_ORIENTATION, MOVE_TOOL_ACTION_NAME, MOVE_TOOL_STATE, PEN_TOOL_ACTION_NAME, PEN_TOOL_STATE, RECTANGLE_TOOL_ACTION_NAME, RECTANGLE_TOOL_STATE, REGULAR_POLYGON_TOOL_ACTION_NAME, REGULAR_POLYGON_TOOL_STATE, SELECTION_TOOL_ACTION_NAME, SELECTION_TOOL_STATE, STAGE_MINIMAP_DEFAULT_CONFIG, STAR_TOOL_ACTION_NAME, STAR_TOOL_STATE, TEXT_LAYOUT, TEXT_TOOL_ACTION_NAME, TEXT_TOOL_STATE, VIDEO_TOOL_ACTION_NAME, VIDEO_TOOL_STATE, WEAVE_ARROW_NODE_TYPE, WEAVE_ARROW_TOOL_ACTION_NAME, WEAVE_ARROW_TOOL_STATE, WEAVE_COMMENTS_RENDERER_KEY, WEAVE_COMMENTS_TOOL_LAYER_ID, WEAVE_COMMENT_CREATE_ACTION, WEAVE_COMMENT_NODE_ACTION, WEAVE_COMMENT_NODE_DEFAULTS, WEAVE_COMMENT_NODE_TYPE, WEAVE_COMMENT_STATUS, WEAVE_COMMENT_TOOL_ACTION_NAME, WEAVE_COMMENT_TOOL_DEFAULT_CONFIG, WEAVE_COMMENT_TOOL_STATE, WEAVE_COMMENT_VIEW_ACTION, WEAVE_CONNECTOR_NODE_ANCHOR_ORIGIN, WEAVE_CONNECTOR_NODE_DECORATOR_TYPE, WEAVE_CONNECTOR_NODE_DEFAULT_CONFIG, WEAVE_CONNECTOR_NODE_LINE_ORIGIN, WEAVE_CONNECTOR_NODE_LINE_TYPE, WEAVE_CONNECTOR_NODE_TYPE, WEAVE_COPY_PASTE_CONFIG_DEFAULT, WEAVE_COPY_PASTE_NODES_KEY, WEAVE_COPY_PASTE_PASTE_CATCHER_ID, WEAVE_COPY_PASTE_PASTE_MODES, WEAVE_DEFAULT_USER_INFO_FUNCTION, WEAVE_ELLIPSE_NODE_TYPE, WEAVE_FRAME_DEFAULT_BACKGROUND_COLOR, WEAVE_FRAME_NODE_DEFAULT_CONFIG, WEAVE_FRAME_NODE_DEFAULT_PROPS, WEAVE_FRAME_NODE_TYPE, WEAVE_GRID_DEFAULT_CONFIG, WEAVE_GRID_DOT_TYPES, WEAVE_GRID_LAYER_ID, WEAVE_GRID_TYPES, WEAVE_GROUP_NODE_TYPE, WEAVE_IMAGES_TOOL_ACTION_NAME, WEAVE_IMAGES_TOOL_DEFAULT_CONFIG, WEAVE_IMAGES_TOOL_STATE, WEAVE_IMAGES_TOOL_UPLOAD_TYPE, WEAVE_IMAGE_CROP_ANCHOR_POSITION, WEAVE_IMAGE_CROP_END_TYPE, WEAVE_IMAGE_DEFAULT_CONFIG, WEAVE_IMAGE_NODE_TYPE, WEAVE_IMAGE_TOOL_ACTION_NAME, WEAVE_IMAGE_TOOL_CONFIG_DEFAULT, WEAVE_IMAGE_TOOL_STATE, WEAVE_IMAGE_TOOL_UPLOAD_TYPE, WEAVE_LAYER_NODE_TYPE, WEAVE_LINE_NODE_DEFAULT_CONFIG, WEAVE_LINE_NODE_TYPE, WEAVE_MEASURE_NODE_DEFAULT_CONFIG, WEAVE_MEASURE_NODE_TYPE, WEAVE_MEASURE_TOOL_DEFAULT_CONFIG, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_DEFAULT_CONFIG, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_KEY, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_LAYER_ID, WEAVE_NODES_SELECTION_DEFAULT_CONFIG, WEAVE_NODES_SELECTION_KEY, WEAVE_NODES_SELECTION_LAYER_ID, WEAVE_NODES_SNAPPING_PLUGIN_KEY, WEAVE_RECTANGLE_NODE_TYPE, WEAVE_REGULAR_POLYGON_NODE_TYPE, WEAVE_STAGE_DEFAULT_MODE, WEAVE_STAGE_DROP_AREA_KEY, WEAVE_STAGE_GRID_PLUGIN_KEY, WEAVE_STAGE_IMAGE_CROPPING_MODE, WEAVE_STAGE_KEYBOARD_MOVE_DEFAULT_CONFIG, WEAVE_STAGE_KEYBOARD_MOVE_KEY, WEAVE_STAGE_KEYBOARD_MOVE_ORIENTATION, WEAVE_STAGE_MINIMAP_KEY, WEAVE_STAGE_NODE_TYPE, WEAVE_STAGE_PANNING_DEFAULT_CONFIG, WEAVE_STAGE_PANNING_KEY, WEAVE_STAGE_PANNING_THROTTLE_MS, WEAVE_STAGE_TEXT_EDITION_MODE, WEAVE_STAGE_ZOOM_DEFAULT_CONFIG, WEAVE_STAGE_ZOOM_KEY, WEAVE_STAGE_ZOOM_TYPE, WEAVE_STAR_NODE_TYPE, WEAVE_STROKE_NODE_DEFAULT_CONFIG, WEAVE_STROKE_NODE_TYPE, WEAVE_STROKE_SINGLE_NODE_DEFAULT_CONFIG, WEAVE_STROKE_SINGLE_NODE_TIP_SIDE, WEAVE_STROKE_SINGLE_NODE_TIP_TYPE, WEAVE_STROKE_SINGLE_NODE_TYPE, WEAVE_STROKE_TOOL_ACTION_NAME, WEAVE_STROKE_TOOL_ACTION_NAME_ALIASES, WEAVE_STROKE_TOOL_DEFAULT_CONFIG, WEAVE_STROKE_TOOL_STATE, WEAVE_TEXT_NODE_DEFAULT_CONFIG, WEAVE_TEXT_NODE_TYPE, WEAVE_USERS_POINTERS_CONFIG_DEFAULT_PROPS, WEAVE_USERS_POINTERS_KEY, WEAVE_USERS_PRESENCE_CONFIG_DEFAULT_PROPS, WEAVE_USERS_PRESENCE_PLUGIN_KEY, WEAVE_USERS_SELECTION_KEY, WEAVE_USER_POINTER_KEY, WEAVE_USER_PRESENCE_KEY, WEAVE_USER_SELECTION_KEY, WEAVE_VIDEO_DEFAULT_CONFIG, WEAVE_VIDEO_NODE_TYPE, Weave, WeaveAction, WeaveAlignNodesToolAction, WeaveArrowNode, WeaveArrowToolAction, WeaveBrushToolAction, WeaveCommentNode, WeaveCommentToolAction, WeaveCommentsRendererPlugin, WeaveConnectedUsersPlugin, WeaveConnectorNode, WeaveConnectorToolAction, WeaveContextMenuPlugin, WeaveCopyPasteNodesPlugin, WeaveEllipseNode, WeaveEllipseToolAction, WeaveEraserToolAction, WeaveExportNodesToolAction, WeaveExportStageToolAction, WeaveFitToScreenToolAction, WeaveFitToSelectionToolAction, WeaveFrameNode, WeaveFrameToolAction, WeaveGroupNode, WeaveGuideToolAction, WeaveImageNode, WeaveImageToolAction, WeaveImagesToolAction, WeaveLayerNode, WeaveLineNode, WeaveLineToolAction, WeaveMeasureNode, WeaveMeasureToolAction, WeaveMoveToolAction, WeaveNode, WeaveNodesMultiSelectionFeedbackPlugin, WeaveNodesSelectionPlugin, WeaveNodesSnappingPlugin, WeavePenToolAction, WeavePlugin, WeaveRectangleNode, WeaveRectangleToolAction, WeaveRegularPolygonNode, WeaveRegularPolygonToolAction, WeaveRenderer, WeaveSelectionToolAction, WeaveStageDropAreaPlugin, WeaveStageGridPlugin, WeaveStageKeyboardMovePlugin, WeaveStageMinimapPlugin, WeaveStageNode, WeaveStagePanningPlugin, WeaveStageResizePlugin, WeaveStageZoomPlugin, WeaveStarNode, WeaveStarToolAction, WeaveStateManipulation, WeaveStore, WeaveStrokeNode, WeaveStrokeSingleNode, WeaveStrokeToolAction, WeaveTextNode, WeaveTextToolAction, WeaveUsersPointersPlugin, WeaveUsersPresencePlugin, WeaveUsersSelectionPlugin, WeaveVideoNode, WeaveVideoToolAction, WeaveZoomInToolAction, WeaveZoomOutToolAction, canComposite, clearContainerTargets, containerOverCursor, containsNodeDeep, defaultInitialState, downscaleImageFile, downscaleImageFromURL, getBoundingBox, getDownscaleRatio, getExportBoundingBox, getImageSizeFromFile, getJSONFromYjsBinary, getSelectedNodesMetadata, getStageClickPoint, getTargetAndSkipNodes, getTargetedNode, getTopmostShadowHost, getVisibleNodes, getVisibleNodesInViewport, hasFrames, hasImages, intersectArrays, isArray, isIOS, isInShadowDOM, isNodeInSelection, isNumber, isObject, isServer, loadImageSource, mapJsonToYjsArray, mapJsonToYjsElements, mapJsonToYjsMap, memoize, mergeExceptArrays, moveNodeToContainer, moveNodeToContainerNT, resetScale, weavejsToYjsBinary };
|
|
32933
|
+
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, canComposite, clearContainerTargets, computeEllipseLabelMinSize, computePolygonLabelMinSize, computeRectangleLabelMinSize, containerOverCursor, containsNodeDeep, defaultInitialState, downscaleImageFile, downscaleImageFromURL, getBoundingBox, getDownscaleRatio, getExportBoundingBox, getImageSizeFromFile, getJSONFromYjsBinary, getSelectedNodesMetadata, getShapeLabelSchemaFields, getStageClickPoint, getTargetAndSkipNodes, getTargetedNode, getTopmostShadowHost, getVisibleNodes, getVisibleNodesInViewport, hasFrames, hasImages, instantiatePreset, intersectArrays, isArray, isIOS, isInShadowDOM, isNodeInSelection, isNumber, isObject, isServer, labelId, loadImageSource, mapJsonToYjsArray, mapJsonToYjsElements, mapJsonToYjsMap, memoize, mergeExceptArrays, moveNodeToContainer, moveNodeToContainerNT, resetScale, spreadLabelProps, weavejsToYjsBinary };
|