@inditextech/weave-sdk 5.3.0 → 5.4.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 +441 -82
- package/dist/sdk.node.js +442 -83
- package/dist/sdk.node.stats.html +1 -1
- package/dist/sdk.stats.html +1 -1
- package/dist/types.d.ts +159 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +441 -82
- package/dist/types.js.map +1 -1
- package/dist/types.stats.html +1 -1
- package/package.json +2 -2
package/dist/sdk.js
CHANGED
|
@@ -4676,7 +4676,15 @@ function handleClickOrTap(ctx, e) {
|
|
|
4676
4676
|
nodeTargeted.dblClick();
|
|
4677
4677
|
return;
|
|
4678
4678
|
}
|
|
4679
|
-
|
|
4679
|
+
const isCtrlOrCmdPressed = e.evt.ctrlKey || e.evt.metaKey;
|
|
4680
|
+
if (!e.evt.shiftKey) {
|
|
4681
|
+
const wasSelectedBeforeThisClick = tr.nodes().findIndex((node) => node.getAttrs().id === nodeTargeted.getAttrs().id) !== -1;
|
|
4682
|
+
nodeTargeted.click({
|
|
4683
|
+
wasSelected: wasSelectedBeforeThisClick,
|
|
4684
|
+
ctrlOrMetaPressed: isCtrlOrCmdPressed
|
|
4685
|
+
});
|
|
4686
|
+
}
|
|
4687
|
+
if (isCtrlOrCmdPressed) return;
|
|
4680
4688
|
if (!metaPressed) {
|
|
4681
4689
|
tr.nodes([nodeTargeted]);
|
|
4682
4690
|
tr.show();
|
|
@@ -5945,6 +5953,7 @@ const augmentKonvaNodeClass = (config) => {
|
|
|
5945
5953
|
Konva.Node.prototype.closeCrop = function() {};
|
|
5946
5954
|
Konva.Node.prototype.resetCrop = function() {};
|
|
5947
5955
|
Konva.Node.prototype.dblClick = function() {};
|
|
5956
|
+
Konva.Node.prototype.click = function() {};
|
|
5948
5957
|
Konva.Node.prototype.allowedAnchors = function() {
|
|
5949
5958
|
return [];
|
|
5950
5959
|
};
|
|
@@ -9457,7 +9466,7 @@ var WeaveRegisterManager = class {
|
|
|
9457
9466
|
};
|
|
9458
9467
|
//#endregion
|
|
9459
9468
|
//#region package.json
|
|
9460
|
-
var version = "5.
|
|
9469
|
+
var version = "5.4.1";
|
|
9461
9470
|
//#endregion
|
|
9462
9471
|
//#region src/managers/setup.ts
|
|
9463
9472
|
var WeaveSetupManager = class {
|
|
@@ -13387,8 +13396,13 @@ const WEAVE_TEXT_NODE_DEFAULT_CONFIG = {
|
|
|
13387
13396
|
transform: { ...WEAVE_NODES_SELECTION_DEFAULT_CONFIG.selection },
|
|
13388
13397
|
outline: { enabled: false },
|
|
13389
13398
|
cursor: { color: "#000000" },
|
|
13390
|
-
edition: { borderSize: 2 }
|
|
13399
|
+
edition: { borderSize: 2 },
|
|
13400
|
+
link: {
|
|
13401
|
+
defaultColor: "#1155ccff",
|
|
13402
|
+
hoverColor: "#3d7be0ff"
|
|
13403
|
+
}
|
|
13391
13404
|
};
|
|
13405
|
+
const WEAVE_TEXT_LINK_ALLOWED_PROTOCOLS = ["http:", "https:"];
|
|
13392
13406
|
const TEXT_LAYOUT = {
|
|
13393
13407
|
["SMART"]: "smart",
|
|
13394
13408
|
["AUTO_ALL"]: "auto-all",
|
|
@@ -13397,6 +13411,21 @@ const TEXT_LAYOUT = {
|
|
|
13397
13411
|
};
|
|
13398
13412
|
//#endregion
|
|
13399
13413
|
//#region src/nodes/text/text.ts
|
|
13414
|
+
/**
|
|
13415
|
+
* Validates that a link is an absolute http(s) URL. Used both by the zod
|
|
13416
|
+
* schema (getSchema()) and defensively again at click-time (setLink() and
|
|
13417
|
+
* the pointerclick handler), since the value is user-authored content
|
|
13418
|
+
* rendered and clicked on by other collaborators — schemes like
|
|
13419
|
+
* `javascript:` or `data:` must never reach `window.open`.
|
|
13420
|
+
*/
|
|
13421
|
+
function isValidTextLink(value) {
|
|
13422
|
+
try {
|
|
13423
|
+
const url = new URL(value);
|
|
13424
|
+
return WEAVE_TEXT_LINK_ALLOWED_PROTOCOLS.includes(url.protocol);
|
|
13425
|
+
} catch {
|
|
13426
|
+
return false;
|
|
13427
|
+
}
|
|
13428
|
+
}
|
|
13400
13429
|
var WeaveTextNode = class extends WeaveNode {
|
|
13401
13430
|
config;
|
|
13402
13431
|
nodeType = WEAVE_TEXT_NODE_TYPE;
|
|
@@ -13460,6 +13489,8 @@ var WeaveTextNode = class extends WeaveNode {
|
|
|
13460
13489
|
}
|
|
13461
13490
|
}
|
|
13462
13491
|
onRender(props) {
|
|
13492
|
+
const linkPreviousFill = props.link ? props.linkPreviousFill ?? props.fill : props.linkPreviousFill;
|
|
13493
|
+
const linkPreviousTextDecoration = props.link ? props.linkPreviousTextDecoration ?? props.textDecoration : props.linkPreviousTextDecoration;
|
|
13463
13494
|
const text = new Konva.Text({
|
|
13464
13495
|
...props,
|
|
13465
13496
|
name: "node",
|
|
@@ -13469,6 +13500,12 @@ var WeaveTextNode = class extends WeaveNode {
|
|
|
13469
13500
|
stroke: this.config.outline.color,
|
|
13470
13501
|
strokeWidth: this.config.outline.width,
|
|
13471
13502
|
fillAfterStrokeEnabled: true
|
|
13503
|
+
},
|
|
13504
|
+
...props.link && {
|
|
13505
|
+
textDecoration: "underline",
|
|
13506
|
+
fill: this.config.link.defaultColor,
|
|
13507
|
+
linkPreviousFill,
|
|
13508
|
+
linkPreviousTextDecoration
|
|
13472
13509
|
}
|
|
13473
13510
|
});
|
|
13474
13511
|
this.setupDefaultNodeAugmentation(text);
|
|
@@ -13527,6 +13564,7 @@ var WeaveTextNode = class extends WeaveNode {
|
|
|
13527
13564
|
this.triggerEditMode(text);
|
|
13528
13565
|
};
|
|
13529
13566
|
text.setAttr("triggerEditMode", this.triggerEditMode.bind(this));
|
|
13567
|
+
this.setupLinkBehavior(text);
|
|
13530
13568
|
let actualAnchor = void 0;
|
|
13531
13569
|
text.on("transformstart", (e) => {
|
|
13532
13570
|
const isCtrlOrMetaPressed = e.evt.ctrlKey || e.evt.metaKey;
|
|
@@ -13623,6 +13661,9 @@ var WeaveTextNode = class extends WeaveNode {
|
|
|
13623
13661
|
return text;
|
|
13624
13662
|
}
|
|
13625
13663
|
onUpdate(nodeInstance, nextProps) {
|
|
13664
|
+
const isLinked = Boolean(nextProps.link);
|
|
13665
|
+
const linkPreviousFill = nextProps.link ? nextProps.linkPreviousFill ?? nextProps.fill : nextProps.linkPreviousFill;
|
|
13666
|
+
const linkPreviousTextDecoration = nextProps.link ? nextProps.linkPreviousTextDecoration ?? nextProps.textDecoration : nextProps.linkPreviousTextDecoration;
|
|
13626
13667
|
nodeInstance.setAttrs({
|
|
13627
13668
|
...nextProps,
|
|
13628
13669
|
...!this.config.outline.enabled && { strokeEnabled: false },
|
|
@@ -13631,6 +13672,13 @@ var WeaveTextNode = class extends WeaveNode {
|
|
|
13631
13672
|
stroke: this.config.outline.color,
|
|
13632
13673
|
strokeWidth: this.config.outline.width,
|
|
13633
13674
|
fillAfterStrokeEnabled: true
|
|
13675
|
+
},
|
|
13676
|
+
link: nextProps.link,
|
|
13677
|
+
linkPreviousFill: isLinked ? linkPreviousFill : void 0,
|
|
13678
|
+
linkPreviousTextDecoration: isLinked ? linkPreviousTextDecoration : void 0,
|
|
13679
|
+
...isLinked && {
|
|
13680
|
+
textDecoration: "underline",
|
|
13681
|
+
fill: this.config.link.defaultColor
|
|
13634
13682
|
}
|
|
13635
13683
|
});
|
|
13636
13684
|
let width = nextProps.width;
|
|
@@ -13672,6 +13720,10 @@ var WeaveTextNode = class extends WeaveNode {
|
|
|
13672
13720
|
delete cleanedAttrs.overridesMouseControl;
|
|
13673
13721
|
delete cleanedAttrs.shouldUpdateOnTransform;
|
|
13674
13722
|
delete cleanedAttrs.dragBoundFunc;
|
|
13723
|
+
if (cleanedAttrs.link) {
|
|
13724
|
+
if (typeof cleanedAttrs.linkPreviousFill === "string") cleanedAttrs.fill = cleanedAttrs.linkPreviousFill;
|
|
13725
|
+
if (typeof cleanedAttrs.linkPreviousTextDecoration === "string") cleanedAttrs.textDecoration = cleanedAttrs.linkPreviousTextDecoration;
|
|
13726
|
+
}
|
|
13675
13727
|
return {
|
|
13676
13728
|
key: attrs.id ?? "",
|
|
13677
13729
|
type: attrs.nodeType,
|
|
@@ -14077,6 +14129,94 @@ var WeaveTextNode = class extends WeaveNode {
|
|
|
14077
14129
|
this.createTextAreaDOM(textNode, areaPosition);
|
|
14078
14130
|
this.instance.emitEvent("onEnterTextNodeEditMode", { node: textNode });
|
|
14079
14131
|
}
|
|
14132
|
+
/**
|
|
14133
|
+
* Wires the hover colour swap, link cursor and click-to-open behaviour for
|
|
14134
|
+
* a rendered text node. Runs on top of (not instead of) the generic
|
|
14135
|
+
* selection-hover-halo handling in setupDefaultNodeEvents()/node.ts, the
|
|
14136
|
+
* same way connector.ts layers its own handleMouseover/handleMouseout.
|
|
14137
|
+
*/
|
|
14138
|
+
setupLinkBehavior(text) {
|
|
14139
|
+
text.handleMouseover = () => {
|
|
14140
|
+
if (!text.getAttrs().link) return;
|
|
14141
|
+
text.fill(this.config.link.hoverColor);
|
|
14142
|
+
text.getLayer()?.batchDraw();
|
|
14143
|
+
};
|
|
14144
|
+
text.handleMouseout = () => {
|
|
14145
|
+
if (!text.getAttrs().link) return;
|
|
14146
|
+
text.fill(this.config.link.defaultColor);
|
|
14147
|
+
text.getLayer()?.batchDraw();
|
|
14148
|
+
};
|
|
14149
|
+
text.defineMousePointer = () => {
|
|
14150
|
+
return text.getAttrs().link ? "pointer" : "default";
|
|
14151
|
+
};
|
|
14152
|
+
let linkClickTimeout;
|
|
14153
|
+
const clearLinkClickTimeout = () => {
|
|
14154
|
+
if (linkClickTimeout) {
|
|
14155
|
+
clearTimeout(linkClickTimeout);
|
|
14156
|
+
linkClickTimeout = void 0;
|
|
14157
|
+
}
|
|
14158
|
+
};
|
|
14159
|
+
const previousDblClick = text.dblClick.bind(text);
|
|
14160
|
+
text.dblClick = () => {
|
|
14161
|
+
clearLinkClickTimeout();
|
|
14162
|
+
previousDblClick();
|
|
14163
|
+
};
|
|
14164
|
+
text.click = ({ wasSelected, ctrlOrMetaPressed }) => {
|
|
14165
|
+
if (!text.getAttrs().link) return;
|
|
14166
|
+
if (ctrlOrMetaPressed) {
|
|
14167
|
+
clearLinkClickTimeout();
|
|
14168
|
+
this.openTextLink(text);
|
|
14169
|
+
return;
|
|
14170
|
+
}
|
|
14171
|
+
if (wasSelected) {
|
|
14172
|
+
clearLinkClickTimeout();
|
|
14173
|
+
linkClickTimeout = setTimeout(() => {
|
|
14174
|
+
linkClickTimeout = void 0;
|
|
14175
|
+
if (!this.editing) this.openTextLink(text);
|
|
14176
|
+
}, Konva.dblClickWindow);
|
|
14177
|
+
}
|
|
14178
|
+
};
|
|
14179
|
+
}
|
|
14180
|
+
openTextLink(textNode) {
|
|
14181
|
+
if (this.instance.isServerSide()) return;
|
|
14182
|
+
const link = textNode.getAttrs().link;
|
|
14183
|
+
if (typeof link !== "string" || !isValidTextLink(link)) return;
|
|
14184
|
+
window.open(link, "_blank", "noopener,noreferrer");
|
|
14185
|
+
}
|
|
14186
|
+
/**
|
|
14187
|
+
* Public API to read/set/remove the URL a text node links to. Setting an
|
|
14188
|
+
* invalid or non-http(s) URL is a no-op (see isValidTextLink()).
|
|
14189
|
+
*
|
|
14190
|
+
* The node's real fill/textDecoration are captured once into
|
|
14191
|
+
* `linkPreviousFill`/`linkPreviousTextDecoration` the first time a link is
|
|
14192
|
+
* rendered (see onRender()/onUpdate()) and restored by serialize()
|
|
14193
|
+
* whenever the node is re-serialized while linked — so they survive any
|
|
14194
|
+
* number of resizes/drags/edits while the link is active. removeLink()
|
|
14195
|
+
* relies on that: it omits `link` *and* those two bookkeeping props from
|
|
14196
|
+
* the serialized props entirely, so all three are deleted from shared
|
|
14197
|
+
* state (see updateYjsMapFromObject in managers/state.ts) rather than
|
|
14198
|
+
* persisted as `undefined`, and the node's original fill/text decoration
|
|
14199
|
+
* reappear immediately.
|
|
14200
|
+
*/
|
|
14201
|
+
getLink(nodeInstance) {
|
|
14202
|
+
const link = nodeInstance.getAttrs().link;
|
|
14203
|
+
return typeof link === "string" ? link : void 0;
|
|
14204
|
+
}
|
|
14205
|
+
setLink(nodeInstance, url) {
|
|
14206
|
+
if (!isValidTextLink(url)) return;
|
|
14207
|
+
const serialized = this.serialize(nodeInstance);
|
|
14208
|
+
serialized.props.linkPreviousFill = serialized.props.fill;
|
|
14209
|
+
serialized.props.linkPreviousTextDecoration = serialized.props.textDecoration;
|
|
14210
|
+
serialized.props.link = url;
|
|
14211
|
+
this.instance.updateNode(serialized);
|
|
14212
|
+
}
|
|
14213
|
+
removeLink(nodeInstance) {
|
|
14214
|
+
const serialized = this.serialize(nodeInstance);
|
|
14215
|
+
delete serialized.props.link;
|
|
14216
|
+
delete serialized.props.linkPreviousFill;
|
|
14217
|
+
delete serialized.props.linkPreviousTextDecoration;
|
|
14218
|
+
this.instance.updateNode(serialized);
|
|
14219
|
+
}
|
|
14080
14220
|
onDestroyInstance() {
|
|
14081
14221
|
super.onDestroyInstance();
|
|
14082
14222
|
if (!this.instance.isServerSide() && this.keyPressHandler) {
|
|
@@ -14142,7 +14282,8 @@ var WeaveTextNode = class extends WeaveNode {
|
|
|
14142
14282
|
...props.strokeEnabled && { strokeEnabled: props.strokeEnabled },
|
|
14143
14283
|
...props.stroke && { stroke: props.stroke },
|
|
14144
14284
|
...props.strokeWidth && { strokeWidth: props.strokeWidth },
|
|
14145
|
-
...props.fillAfterStrokeEnabled && { fillAfterStrokeEnabled: props.fillAfterStrokeEnabled }
|
|
14285
|
+
...props.fillAfterStrokeEnabled && { fillAfterStrokeEnabled: props.fillAfterStrokeEnabled },
|
|
14286
|
+
...props.link && { link: props.link }
|
|
14146
14287
|
} });
|
|
14147
14288
|
}
|
|
14148
14289
|
static updateNodeState(prevNodeState, nextProps) {
|
|
@@ -14167,7 +14308,8 @@ var WeaveTextNode = class extends WeaveNode {
|
|
|
14167
14308
|
...nextProps.strokeEnabled && { strokeEnabled: nextProps.strokeEnabled },
|
|
14168
14309
|
...nextProps.stroke && { stroke: nextProps.stroke },
|
|
14169
14310
|
...nextProps.strokeWidth && { strokeWidth: nextProps.strokeWidth },
|
|
14170
|
-
...nextProps.fillAfterStrokeEnabled && { fillAfterStrokeEnabled: nextProps.fillAfterStrokeEnabled }
|
|
14311
|
+
...nextProps.fillAfterStrokeEnabled && { fillAfterStrokeEnabled: nextProps.fillAfterStrokeEnabled },
|
|
14312
|
+
...nextProps.link && { link: nextProps.link }
|
|
14171
14313
|
} });
|
|
14172
14314
|
}
|
|
14173
14315
|
static getSchema() {
|
|
@@ -14201,6 +14343,9 @@ var WeaveTextNode = class extends WeaveNode {
|
|
|
14201
14343
|
]).default("top").describe("Vertical alignment of the text, can be 'top', 'middle' or 'bottom'."),
|
|
14202
14344
|
fill: z.string().default("#000000ff").describe("Fill color of the text in hex format with alpha channel (e.g. #RRGGBBAA)."),
|
|
14203
14345
|
text: z.string().default("text").describe("The actual text content of the node."),
|
|
14346
|
+
link: z.string().url().refine((value) => isValidTextLink(value), { message: "Link must be an absolute http:// or https:// URL." }).optional().describe("External URL the whole text of the node links to. When set, the text is forced underlined and coloured with the configured link colours regardless of fill/textDecoration, is clickable, and opens the URL in a new tab. Only http(s) URLs are accepted. Omit/remove to make the node plain text again."),
|
|
14347
|
+
linkPreviousFill: z.string().optional().describe("Internal bookkeeping: the fill colour the node had right before a link was set, captured automatically so it can be restored when the link is removed. Managed automatically — do not set directly."),
|
|
14348
|
+
linkPreviousTextDecoration: z.string().optional().describe("Internal bookkeeping: the textDecoration the node had right before a link was set, captured automatically so it can be restored when the link is removed. Managed automatically — do not set directly."),
|
|
14204
14349
|
strokeEnabled: z.boolean().default(false).describe("Whether the text outline is enabled."),
|
|
14205
14350
|
stroke: z.string().optional().default("#d6d6d6").describe("Color of the text outline in hex format with alpha channel (e.g. #RRGGBBAA)."),
|
|
14206
14351
|
strokeWidth: z.number().optional().default(2).describe("Width of the text outline in pixels."),
|
|
@@ -17870,21 +18015,29 @@ var WeaveFrameNode = class extends WeaveNode {
|
|
|
17870
18015
|
const WEAVE_STROKE_NODE_TYPE = "stroke";
|
|
17871
18016
|
const WEAVE_STROKE_NODE_DEFAULT_CONFIG = {
|
|
17872
18017
|
splineResolution: 8,
|
|
18018
|
+
splineTargetEdge: 1,
|
|
18019
|
+
splineMaxSteps: 48,
|
|
17873
18020
|
resamplingSpacing: 2,
|
|
17874
18021
|
isEraser: false
|
|
17875
18022
|
};
|
|
17876
18023
|
//#endregion
|
|
17877
18024
|
//#region src/nodes/stroke/stroke.ts
|
|
17878
|
-
var WeaveStrokeNode = class extends WeaveNode {
|
|
18025
|
+
var WeaveStrokeNode = class WeaveStrokeNode extends WeaveNode {
|
|
17879
18026
|
config;
|
|
17880
18027
|
nodeType = WEAVE_STROKE_NODE_TYPE;
|
|
17881
18028
|
initialize = void 0;
|
|
18029
|
+
/**
|
|
18030
|
+
* Below this chord deviation (in canvas units) a spline span is treated as
|
|
18031
|
+
* straight and emitted as a single edge. Subdividing a straight span costs
|
|
18032
|
+
* vertices without changing any pixel.
|
|
18033
|
+
*/
|
|
18034
|
+
static SPLINE_FLATNESS_EPSILON = .08;
|
|
17882
18035
|
constructor(params) {
|
|
17883
18036
|
super();
|
|
17884
18037
|
const { config } = params ?? {};
|
|
17885
18038
|
this.config = mergeExceptArrays(WEAVE_STROKE_NODE_DEFAULT_CONFIG, config);
|
|
17886
18039
|
}
|
|
17887
|
-
resamplePoints(pts, minDist =
|
|
18040
|
+
resamplePoints(pts, minDist = this.config.resamplingSpacing) {
|
|
17888
18041
|
if (pts.length < 2) return pts;
|
|
17889
18042
|
const result = [pts[0]];
|
|
17890
18043
|
let last = pts[0];
|
|
@@ -17898,29 +18051,73 @@ var WeaveStrokeNode = class extends WeaveNode {
|
|
|
17898
18051
|
}
|
|
17899
18052
|
return result;
|
|
17900
18053
|
}
|
|
17901
|
-
|
|
18054
|
+
/** Perpendicular distance from `p` to the segment `a`-`b`. */
|
|
18055
|
+
distanceToSegment(p, a, b) {
|
|
18056
|
+
const dx = b.x - a.x;
|
|
18057
|
+
const dy = b.y - a.y;
|
|
18058
|
+
const lengthSq = dx * dx + dy * dy;
|
|
18059
|
+
let t = lengthSq ? ((p.x - a.x) * dx + (p.y - a.y) * dy) / lengthSq : 0;
|
|
18060
|
+
t = Math.max(0, Math.min(1, t));
|
|
18061
|
+
return Math.hypot(p.x - (a.x + dx * t), p.y - (a.y + dy * t));
|
|
18062
|
+
}
|
|
18063
|
+
/**
|
|
18064
|
+
* Evaluates the uniform Catmull-Rom basis for one 4-point window at `t`.
|
|
18065
|
+
*/
|
|
18066
|
+
catmullRomAt(p0, p1, p2, p3, t) {
|
|
18067
|
+
const tt = t * t;
|
|
18068
|
+
const ttt = tt * t;
|
|
18069
|
+
const q1 = -ttt + 2 * tt - t;
|
|
18070
|
+
const q2 = 3 * ttt - 5 * tt + 2;
|
|
18071
|
+
const q3 = -3 * ttt + 4 * tt + t;
|
|
18072
|
+
const q4 = ttt - tt;
|
|
18073
|
+
return {
|
|
18074
|
+
x: (q1 * p0.x + q2 * p1.x + q3 * p2.x + q4 * p3.x) / 2,
|
|
18075
|
+
y: (q1 * p0.y + q2 * p1.y + q3 * p2.y + q4 * p3.y) / 2,
|
|
18076
|
+
pressure: (q1 * p0.pressure + q2 * p1.pressure + q3 * p2.pressure + q4 * p3.pressure) / 2
|
|
18077
|
+
};
|
|
18078
|
+
}
|
|
18079
|
+
/**
|
|
18080
|
+
* Samples a Catmull-Rom spline through `pts`, subdividing each span by its
|
|
18081
|
+
* ARC LENGTH rather than by a fixed step count.
|
|
18082
|
+
*
|
|
18083
|
+
* A fixed count is the reason a finished stroke looks faceted while the
|
|
18084
|
+
* one being drawn looks smooth: both render with the same number of
|
|
18085
|
+
* subdivisions per span, but a live stroke's control points sit ~1-2px
|
|
18086
|
+
* apart while a finalized stroke's - after Douglas-Peucker simplification
|
|
18087
|
+
* - sit a median 9-28px apart. The same 8 subdivisions therefore produce
|
|
18088
|
+
* sub-pixel edges live and edges up to ~15px long once finalized, with
|
|
18089
|
+
* visible turns between them.
|
|
18090
|
+
*
|
|
18091
|
+
* `resolution` is now the MINIMUM number of subdivisions for a curved
|
|
18092
|
+
* span (so dense, live-drawn spans behave exactly as before); long spans
|
|
18093
|
+
* get proportionally more, capped so pathological input cannot explode
|
|
18094
|
+
* the vertex count. Spans whose midpoint deviates from their chord by
|
|
18095
|
+
* less than `SPLINE_FLATNESS_EPSILON` are effectively straight and are
|
|
18096
|
+
* emitted as a single edge - subdividing a straight line adds vertices
|
|
18097
|
+
* without changing a pixel.
|
|
18098
|
+
*/
|
|
18099
|
+
getSplinePoints(pts, resolution = this.config.splineResolution) {
|
|
18100
|
+
if (pts.length < 2) return [...pts];
|
|
18101
|
+
const targetEdge = this.config.splineTargetEdge;
|
|
18102
|
+
const maxSteps = this.config.splineMaxSteps;
|
|
17902
18103
|
const result = [];
|
|
17903
18104
|
for (let i = -1; i < pts.length - 2; i++) {
|
|
17904
18105
|
const p0 = pts[Math.max(i, 0)];
|
|
17905
18106
|
const p1 = pts[i + 1];
|
|
17906
18107
|
const p2 = pts[i + 2];
|
|
17907
18108
|
const p3 = pts[Math.min(i + 3, pts.length - 1)];
|
|
17908
|
-
|
|
17909
|
-
|
|
17910
|
-
|
|
17911
|
-
|
|
17912
|
-
|
|
17913
|
-
|
|
17914
|
-
|
|
17915
|
-
const
|
|
17916
|
-
|
|
17917
|
-
|
|
17918
|
-
|
|
17919
|
-
|
|
17920
|
-
y,
|
|
17921
|
-
pressure
|
|
17922
|
-
});
|
|
17923
|
-
}
|
|
18109
|
+
const chord = Math.hypot(p2.x - p1.x, p2.y - p1.y);
|
|
18110
|
+
let deviation = 0;
|
|
18111
|
+
for (const probe of [
|
|
18112
|
+
.25,
|
|
18113
|
+
.5,
|
|
18114
|
+
.75
|
|
18115
|
+
]) {
|
|
18116
|
+
const at = this.catmullRomAt(p0, p1, p2, p3, probe);
|
|
18117
|
+
deviation = Math.max(deviation, this.distanceToSegment(at, p1, p2));
|
|
18118
|
+
}
|
|
18119
|
+
const steps = deviation < WeaveStrokeNode.SPLINE_FLATNESS_EPSILON ? 1 : Math.min(Math.max(Math.ceil(chord / targetEdge), resolution), maxSteps);
|
|
18120
|
+
for (let s = 0; s < steps; s++) result.push(this.catmullRomAt(p0, p1, p2, p3, s / steps));
|
|
17924
18121
|
}
|
|
17925
18122
|
result.push(pts[pts.length - 1]);
|
|
17926
18123
|
return result;
|
|
@@ -17938,19 +18135,26 @@ var WeaveStrokeNode = class extends WeaveNode {
|
|
|
17938
18135
|
* Draws a filled polygon from the accumulated left/right outline points of a
|
|
17939
18136
|
* dash segment and adds round caps at both ends.
|
|
17940
18137
|
* NOTE: mutates `rightSide` via Array.reverse() — callers must not reuse it after this call.
|
|
18138
|
+
*
|
|
18139
|
+
* The outline is NOT re-smoothed here. It used to be, back when the
|
|
18140
|
+
* centerline was sampled at a fixed subdivision count and could be coarse;
|
|
18141
|
+
* now that the centerline is subdivided by arc length, its offset curves
|
|
18142
|
+
* are already smooth, and measurement showed the extra spline pass cost
|
|
18143
|
+
* roughly half of the node's total render time while changing the drawn
|
|
18144
|
+
* result by well under a pixel (95th-percentile outline edge 1.72px vs
|
|
18145
|
+
* 1.76px; byte-identical on long, gently-curved strokes).
|
|
17941
18146
|
*/
|
|
17942
18147
|
drawDashPolygon(ctx, leftSide, rightSide, color) {
|
|
17943
18148
|
const capStartL = leftSide[0];
|
|
17944
18149
|
const capStartR = rightSide[0];
|
|
17945
18150
|
const capEndL = leftSide.at(-1);
|
|
17946
18151
|
const capEndR = rightSide.at(-1);
|
|
17947
|
-
const
|
|
17948
|
-
const smoothRight = this.getSplinePoints(rightSide.reverse(), 4);
|
|
18152
|
+
const outlineRight = rightSide.reverse();
|
|
17949
18153
|
ctx.beginPath();
|
|
17950
18154
|
ctx.fillStyle = color;
|
|
17951
|
-
ctx.moveTo(
|
|
17952
|
-
for (const p of
|
|
17953
|
-
for (const p of
|
|
18155
|
+
ctx.moveTo(leftSide[0].x, leftSide[0].y);
|
|
18156
|
+
for (const p of leftSide) ctx.lineTo(p.x, p.y);
|
|
18157
|
+
for (const p of outlineRight) ctx.lineTo(p.x, p.y);
|
|
17954
18158
|
ctx.closePath();
|
|
17955
18159
|
ctx.fill();
|
|
17956
18160
|
this.drawRoundCap(ctx, capStartL, capStartR, color);
|
|
@@ -17967,13 +18171,23 @@ var WeaveStrokeNode = class extends WeaveNode {
|
|
|
17967
18171
|
ctx.fill();
|
|
17968
18172
|
return;
|
|
17969
18173
|
}
|
|
17970
|
-
const filtered = this.resamplePoints(pts,
|
|
17971
|
-
const centerline = this.getSplinePoints(filtered,
|
|
18174
|
+
const filtered = this.resamplePoints(pts, this.config.resamplingSpacing);
|
|
18175
|
+
const centerline = this.getSplinePoints(filtered, this.config.splineResolution);
|
|
17972
18176
|
let dashIndex = 0;
|
|
17973
18177
|
let dashOn = true;
|
|
17974
18178
|
let dashRemaining = dash.length ? dash[0] : Infinity;
|
|
17975
18179
|
let leftSide = [];
|
|
17976
18180
|
let rightSide = [];
|
|
18181
|
+
let pendingEndLeft = null;
|
|
18182
|
+
let pendingEndRight = null;
|
|
18183
|
+
const flushRun = () => {
|
|
18184
|
+
if (!dashOn || !leftSide.length || !rightSide.length) return;
|
|
18185
|
+
if (pendingEndLeft && pendingEndRight) {
|
|
18186
|
+
leftSide.push(pendingEndLeft);
|
|
18187
|
+
rightSide.push(pendingEndRight);
|
|
18188
|
+
}
|
|
18189
|
+
this.drawDashPolygon(ctx, leftSide, rightSide, color);
|
|
18190
|
+
};
|
|
17977
18191
|
for (let i = 0; i < centerline.length - 1; i++) {
|
|
17978
18192
|
const p0 = centerline[i];
|
|
17979
18193
|
const p1 = centerline[i + 1];
|
|
@@ -18006,22 +18220,24 @@ var WeaveStrokeNode = class extends WeaveNode {
|
|
|
18006
18220
|
y: y0 - ny * pw0,
|
|
18007
18221
|
pressure: 1
|
|
18008
18222
|
});
|
|
18009
|
-
|
|
18223
|
+
pendingEndLeft = {
|
|
18010
18224
|
x: x1 + nx * pw1,
|
|
18011
18225
|
y: y1 + ny * pw1,
|
|
18012
18226
|
pressure: 1
|
|
18013
|
-
}
|
|
18014
|
-
|
|
18227
|
+
};
|
|
18228
|
+
pendingEndRight = {
|
|
18015
18229
|
x: x1 - nx * pw1,
|
|
18016
18230
|
y: y1 - ny * pw1,
|
|
18017
18231
|
pressure: 1
|
|
18018
|
-
}
|
|
18232
|
+
};
|
|
18019
18233
|
}
|
|
18020
18234
|
dashRemaining -= step;
|
|
18021
18235
|
if (dashRemaining <= 0) {
|
|
18022
|
-
|
|
18236
|
+
flushRun();
|
|
18023
18237
|
leftSide = [];
|
|
18024
18238
|
rightSide = [];
|
|
18239
|
+
pendingEndLeft = null;
|
|
18240
|
+
pendingEndRight = null;
|
|
18025
18241
|
dashOn = !dashOn;
|
|
18026
18242
|
dashIndex = (dashIndex + 1) % dash.length;
|
|
18027
18243
|
dashRemaining = dash[dashIndex];
|
|
@@ -18029,7 +18245,7 @@ var WeaveStrokeNode = class extends WeaveNode {
|
|
|
18029
18245
|
traveled += step;
|
|
18030
18246
|
}
|
|
18031
18247
|
}
|
|
18032
|
-
|
|
18248
|
+
flushRun();
|
|
18033
18249
|
}
|
|
18034
18250
|
drawShape(ctx, shape) {
|
|
18035
18251
|
const strokeElements = shape.getAttrs().strokeElements;
|
|
@@ -24033,7 +24249,22 @@ const BRUSH_TOOL_STATE = {
|
|
|
24033
24249
|
["IDLE"]: "idle",
|
|
24034
24250
|
["DEFINE_STROKE"]: "defineStroke"
|
|
24035
24251
|
};
|
|
24036
|
-
|
|
24252
|
+
/**
|
|
24253
|
+
* Suffix applied to a finished stroke's preview node while it is briefly
|
|
24254
|
+
* kept on screen alongside the persisted node, so the two cannot collide on
|
|
24255
|
+
* the same id.
|
|
24256
|
+
*/
|
|
24257
|
+
const PREVIEW_ID_SUFFIX = "--preview";
|
|
24258
|
+
/**
|
|
24259
|
+
* How many frames the preview of a finished stroke may wait for its
|
|
24260
|
+
* persisted counterpart to be rendered before it is removed regardless.
|
|
24261
|
+
* Bounds the handover so a preview can never be orphaned on screen.
|
|
24262
|
+
*/
|
|
24263
|
+
const PREVIEW_HANDOVER_MAX_FRAMES = 30;
|
|
24264
|
+
const BRUSH_TOOL_DEFAULT_CONFIG = {
|
|
24265
|
+
interpolationSteps: 10,
|
|
24266
|
+
simplifyTolerance: .5
|
|
24267
|
+
};
|
|
24037
24268
|
//#endregion
|
|
24038
24269
|
//#region src/actions/brush-tool/brush-tool.ts
|
|
24039
24270
|
var WeaveBrushToolAction = class extends WeaveAction {
|
|
@@ -24050,6 +24281,7 @@ var WeaveBrushToolAction = class extends WeaveAction {
|
|
|
24050
24281
|
prevTouchAction;
|
|
24051
24282
|
penActive = false;
|
|
24052
24283
|
lastSmoothedPressure = .5;
|
|
24284
|
+
hasPressureSample = false;
|
|
24053
24285
|
lastPointerPos = null;
|
|
24054
24286
|
lastPointerTime = 0;
|
|
24055
24287
|
predictedCount = 0;
|
|
@@ -24081,26 +24313,84 @@ var WeaveBrushToolAction = class extends WeaveAction {
|
|
|
24081
24313
|
opacity: 1
|
|
24082
24314
|
};
|
|
24083
24315
|
}
|
|
24084
|
-
|
|
24316
|
+
/**
|
|
24317
|
+
* Velocity-adaptive exponential smoothing of a single raw pressure sample.
|
|
24318
|
+
*
|
|
24319
|
+
* This is the one place pressure smoothing happens. Every sample that
|
|
24320
|
+
* becomes a stroke point must go through it - including the
|
|
24321
|
+
* high-frequency coalesced samples a stylus reports (see
|
|
24322
|
+
* `handlePointerMove`), which previously bypassed it entirely and so
|
|
24323
|
+
* landed in the stroke with their raw value, no pressure floor, and
|
|
24324
|
+
* without advancing the smoothing state for later samples.
|
|
24325
|
+
*
|
|
24326
|
+
* Timing intentionally uses `performance.now()` (not the event's own
|
|
24327
|
+
* `timeStamp`), matching the original behaviour: the two are not
|
|
24328
|
+
* guaranteed to share a time origin, and mixing them corrupts the
|
|
24329
|
+
* velocity term that drives `alpha`.
|
|
24330
|
+
*
|
|
24331
|
+
* The first sample of a stroke SEEDS the filter with its own value
|
|
24332
|
+
* rather than being blended toward the neutral 0.5 baseline. Blending
|
|
24333
|
+
* from a constant gives every stroke a warm-up transient: the filter
|
|
24334
|
+
* starts at 0.5 and converges toward the pressure actually being
|
|
24335
|
+
* applied, so a stroke drawn lighter than 0.5 renders visibly fatter at
|
|
24336
|
+
* its start (and heavier than 0.5, thinner) until the filter catches
|
|
24337
|
+
* up. Seeding removes that transient entirely - smoothing then only
|
|
24338
|
+
* ever acts between real samples, which is its actual purpose.
|
|
24339
|
+
*/
|
|
24340
|
+
smoothPressureSample(raw, clientX, clientY) {
|
|
24085
24341
|
const now = performance.now();
|
|
24086
24342
|
let velocity = 0;
|
|
24087
|
-
|
|
24088
|
-
|
|
24089
|
-
const
|
|
24343
|
+
const hasPosition = Number.isFinite(clientX) && Number.isFinite(clientY);
|
|
24344
|
+
if (hasPosition && this.lastPointerPos && now - this.lastPointerTime > 0) {
|
|
24345
|
+
const dx = clientX - this.lastPointerPos.x;
|
|
24346
|
+
const dy = clientY - this.lastPointerPos.y;
|
|
24090
24347
|
velocity = Math.hypot(dx, dy) / (now - this.lastPointerTime) * 1e3;
|
|
24091
24348
|
}
|
|
24092
|
-
this.lastPointerPos = {
|
|
24093
|
-
x:
|
|
24094
|
-
y:
|
|
24349
|
+
if (hasPosition) this.lastPointerPos = {
|
|
24350
|
+
x: clientX,
|
|
24351
|
+
y: clientY
|
|
24095
24352
|
};
|
|
24096
24353
|
this.lastPointerTime = now;
|
|
24354
|
+
const safeRaw = Number.isFinite(raw) ? raw : .5;
|
|
24355
|
+
if (!this.hasPressureSample) {
|
|
24356
|
+
this.hasPressureSample = true;
|
|
24357
|
+
this.lastSmoothedPressure = safeRaw;
|
|
24358
|
+
return Math.max(this.lastSmoothedPressure, .15);
|
|
24359
|
+
}
|
|
24097
24360
|
const alpha = Math.min(Math.max(velocity / 1500, .15), .6);
|
|
24098
|
-
|
|
24099
|
-
|
|
24100
|
-
else raw = .5;
|
|
24101
|
-
this.lastSmoothedPressure = alpha * raw + (1 - alpha) * this.lastSmoothedPressure;
|
|
24361
|
+
const smoothed = alpha * safeRaw + (1 - alpha) * this.lastSmoothedPressure;
|
|
24362
|
+
this.lastSmoothedPressure = Number.isFinite(smoothed) ? smoothed : safeRaw;
|
|
24102
24363
|
return Math.max(this.lastSmoothedPressure, .15);
|
|
24103
24364
|
}
|
|
24365
|
+
/**
|
|
24366
|
+
* Raw pressure a pointer sample reports: the device's own reading for a
|
|
24367
|
+
* pen, a neutral constant for devices that do not sense pressure.
|
|
24368
|
+
*/
|
|
24369
|
+
getRawPressure(pointerType, pressure) {
|
|
24370
|
+
if (pointerType === "pen") return (typeof pressure === "number" ? pressure : 0) || .5;
|
|
24371
|
+
return .5;
|
|
24372
|
+
}
|
|
24373
|
+
getEventPressure(e) {
|
|
24374
|
+
return this.smoothPressureSample(this.getRawPressure(e.evt.pointerType, e.evt.pressure), e.evt.clientX, e.evt.clientY);
|
|
24375
|
+
}
|
|
24376
|
+
/**
|
|
24377
|
+
* Resets the pressure-smoothing state (smoothed pressure, last known pointer
|
|
24378
|
+
* position/time, and predicted-point bookkeeping) to a neutral baseline.
|
|
24379
|
+
*
|
|
24380
|
+
* This state is scoped to a single stroke: it must be reset before the
|
|
24381
|
+
* first pressure sample of a new stroke is computed (in `handlePointerDown`,
|
|
24382
|
+
* ahead of the `getEventPressure` call for point 0), not only afterwards -
|
|
24383
|
+
* otherwise that first sample can inherit smoothing state left behind by
|
|
24384
|
+
* the previous stroke (its ending pressure, pointer position and time),
|
|
24385
|
+
* inflating the very first point's pressure.
|
|
24386
|
+
*/
|
|
24387
|
+
resetPressureSmoothingState() {
|
|
24388
|
+
this.lastSmoothedPressure = .5;
|
|
24389
|
+
this.hasPressureSample = false;
|
|
24390
|
+
this.lastPointerPos = null;
|
|
24391
|
+
this.lastPointerTime = 0;
|
|
24392
|
+
this.predictedCount = 0;
|
|
24393
|
+
}
|
|
24104
24394
|
setupEvents() {
|
|
24105
24395
|
const stage = this.instance.getStage();
|
|
24106
24396
|
this.prevTouchAction = stage.container().style.touchAction;
|
|
@@ -24132,6 +24422,7 @@ var WeaveBrushToolAction = class extends WeaveAction {
|
|
|
24132
24422
|
if (e?.evt?.button !== 0) return;
|
|
24133
24423
|
if (e.evt.pointerType === "touch" && this.penActive) return;
|
|
24134
24424
|
if (e.evt.pointerType === "pen") this.penActive = true;
|
|
24425
|
+
this.resetPressureSmoothingState();
|
|
24135
24426
|
const pointPressure = this.getEventPressure(e);
|
|
24136
24427
|
this.handleStartStroke(pointPressure);
|
|
24137
24428
|
e.evt.stopPropagation();
|
|
@@ -24144,16 +24435,21 @@ var WeaveBrushToolAction = class extends WeaveAction {
|
|
|
24144
24435
|
if (this.getZoomPlugin()?.isPinching()) return;
|
|
24145
24436
|
const coalescedEvents = e.evt.getCoalescedEvents ? e.evt.getCoalescedEvents() : [];
|
|
24146
24437
|
if (coalescedEvents.length > 1) {
|
|
24147
|
-
|
|
24148
|
-
|
|
24149
|
-
|
|
24150
|
-
}
|
|
24438
|
+
const samples = coalescedEvents.map((ce) => ({
|
|
24439
|
+
pressure: this.smoothPressureSample(this.getRawPressure(ce.pointerType, ce.pressure), ce.clientX, ce.clientY),
|
|
24440
|
+
isPredicted: false
|
|
24441
|
+
}));
|
|
24151
24442
|
const predictedEvents = e.evt.getPredictedEvents ? e.evt.getPredictedEvents() : [];
|
|
24152
24443
|
if (predictedEvents.length > 0) {
|
|
24153
24444
|
const last = predictedEvents[predictedEvents.length - 1];
|
|
24154
|
-
const predPressure = last.pointerType
|
|
24155
|
-
|
|
24445
|
+
const predPressure = Math.max(.15 * this.getRawPressure(last.pointerType, last.pressure) + .85 * this.lastSmoothedPressure, .15);
|
|
24446
|
+
samples.push({
|
|
24447
|
+
pressure: predPressure,
|
|
24448
|
+
sourceEvent: last,
|
|
24449
|
+
isPredicted: true
|
|
24450
|
+
});
|
|
24156
24451
|
}
|
|
24452
|
+
this.applyMovementSamples(samples);
|
|
24157
24453
|
} else {
|
|
24158
24454
|
const pointPressure = this.getEventPressure(e);
|
|
24159
24455
|
this.handleMovement(pointPressure, void 0, false);
|
|
@@ -24199,10 +24495,7 @@ var WeaveBrushToolAction = class extends WeaveAction {
|
|
|
24199
24495
|
};
|
|
24200
24496
|
}
|
|
24201
24497
|
handleStartStroke(pressure) {
|
|
24202
|
-
this.
|
|
24203
|
-
this.lastPointerPos = null;
|
|
24204
|
-
this.lastPointerTime = 0;
|
|
24205
|
-
this.predictedCount = 0;
|
|
24498
|
+
this.resetPressureSmoothingState();
|
|
24206
24499
|
const { mousePoint, container, measureContainer } = this.instance.getMousePointer();
|
|
24207
24500
|
this.clickPoint = mousePoint;
|
|
24208
24501
|
this.container = container;
|
|
@@ -24231,36 +24524,60 @@ var WeaveBrushToolAction = class extends WeaveAction {
|
|
|
24231
24524
|
}
|
|
24232
24525
|
this.setState(BRUSH_TOOL_STATE.DEFINE_STROKE);
|
|
24233
24526
|
}
|
|
24234
|
-
|
|
24527
|
+
/**
|
|
24528
|
+
* Appends one or more pointer samples to the stroke in a single
|
|
24529
|
+
* read-modify-write, then renders once.
|
|
24530
|
+
*
|
|
24531
|
+
* Batching matters: a stylus reports a burst of coalesced samples per
|
|
24532
|
+
* frame, and applying them one at a time meant copying the whole point
|
|
24533
|
+
* array, recomputing the whole bounding box and issuing a full redraw
|
|
24534
|
+
* once PER SAMPLE. That is O(n) work repeated ~10x a frame, i.e.
|
|
24535
|
+
* quadratic in stroke length - which is why drawing fast could stall for
|
|
24536
|
+
* seconds. Here that O(n) work happens once per event instead.
|
|
24537
|
+
*/
|
|
24538
|
+
applyMovementSamples(samples) {
|
|
24235
24539
|
if (this.state !== BRUSH_TOOL_STATE.DEFINE_STROKE) return;
|
|
24540
|
+
if (samples.length === 0) return;
|
|
24236
24541
|
const stage = this.instance.getStage();
|
|
24237
|
-
const tempStroke =
|
|
24238
|
-
if (this.measureContainer
|
|
24239
|
-
|
|
24542
|
+
const tempStroke = stage.findOne(`#${this.strokeId}`);
|
|
24543
|
+
if (!this.measureContainer || !tempStroke) return;
|
|
24544
|
+
let newStrokeElements = [...tempStroke.getAttrs().strokeElements];
|
|
24545
|
+
for (const sample of samples) {
|
|
24546
|
+
if (sample.sourceEvent) stage.setPointersPositions(sample.sourceEvent);
|
|
24240
24547
|
const { mousePoint } = this.instance.getMousePointerRelativeToContainer(this.measureContainer);
|
|
24241
24548
|
const currentPoint = {
|
|
24242
24549
|
x: mousePoint.x - tempStroke.x(),
|
|
24243
24550
|
y: mousePoint.y - tempStroke.y(),
|
|
24244
|
-
pressure
|
|
24551
|
+
pressure: sample.pressure
|
|
24245
24552
|
};
|
|
24246
|
-
|
|
24247
|
-
if (!isPredicted && this.predictedCount > 0) {
|
|
24553
|
+
if (!sample.isPredicted && this.predictedCount > 0) {
|
|
24248
24554
|
newStrokeElements = newStrokeElements.slice(0, -1 * this.predictedCount);
|
|
24249
24555
|
this.predictedCount = 0;
|
|
24250
24556
|
}
|
|
24557
|
+
if (!sample.isPredicted && newStrokeElements.length === 1) newStrokeElements[0] = {
|
|
24558
|
+
...newStrokeElements[0],
|
|
24559
|
+
pressure: currentPoint.pressure
|
|
24560
|
+
};
|
|
24251
24561
|
newStrokeElements.push(currentPoint);
|
|
24252
|
-
if (isPredicted) this.predictedCount++;
|
|
24253
|
-
const box = this.getBoundingBox(newStrokeElements);
|
|
24254
|
-
tempStroke.setAttrs({
|
|
24255
|
-
width: box.width,
|
|
24256
|
-
height: box.height,
|
|
24257
|
-
x: 0,
|
|
24258
|
-
y: 0,
|
|
24259
|
-
strokeElements: newStrokeElements
|
|
24260
|
-
});
|
|
24261
|
-
const nodeHandler = this.instance.getNodeHandler("stroke");
|
|
24262
|
-
if (nodeHandler) nodeHandler.onUpdate(tempStroke, tempStroke.getAttrs());
|
|
24562
|
+
if (sample.isPredicted) this.predictedCount++;
|
|
24263
24563
|
}
|
|
24564
|
+
const box = this.getBoundingBox(newStrokeElements);
|
|
24565
|
+
tempStroke.setAttrs({
|
|
24566
|
+
width: box.width,
|
|
24567
|
+
height: box.height,
|
|
24568
|
+
x: 0,
|
|
24569
|
+
y: 0,
|
|
24570
|
+
strokeElements: newStrokeElements
|
|
24571
|
+
});
|
|
24572
|
+
const nodeHandler = this.instance.getNodeHandler("stroke");
|
|
24573
|
+
if (nodeHandler) nodeHandler.onUpdate(tempStroke, tempStroke.getAttrs());
|
|
24574
|
+
}
|
|
24575
|
+
handleMovement(pressure, predictedEvent, isPredicted = false) {
|
|
24576
|
+
this.applyMovementSamples([{
|
|
24577
|
+
pressure,
|
|
24578
|
+
sourceEvent: predictedEvent,
|
|
24579
|
+
isPredicted
|
|
24580
|
+
}]);
|
|
24264
24581
|
}
|
|
24265
24582
|
finalizeStroke(tempStroke, nodeHandler) {
|
|
24266
24583
|
const box = this.getBoundingBox(tempStroke.getAttrs().strokeElements);
|
|
@@ -24269,12 +24586,19 @@ var WeaveBrushToolAction = class extends WeaveAction {
|
|
|
24269
24586
|
newStrokeElements = newStrokeElements.slice(0, -1 * this.predictedCount);
|
|
24270
24587
|
this.predictedCount = 0;
|
|
24271
24588
|
}
|
|
24589
|
+
if (newStrokeElements.length >= 2) {
|
|
24590
|
+
const lastIndex = newStrokeElements.length - 1;
|
|
24591
|
+
newStrokeElements[lastIndex] = {
|
|
24592
|
+
...newStrokeElements[lastIndex],
|
|
24593
|
+
pressure: newStrokeElements[lastIndex - 1].pressure
|
|
24594
|
+
};
|
|
24595
|
+
}
|
|
24272
24596
|
newStrokeElements = newStrokeElements.map((point) => ({
|
|
24273
24597
|
...point,
|
|
24274
24598
|
x: point.x - box.x,
|
|
24275
24599
|
y: point.y - box.y
|
|
24276
24600
|
}));
|
|
24277
|
-
const compressedPoints = simplify(newStrokeElements,
|
|
24601
|
+
const compressedPoints = simplify(newStrokeElements, this.config.simplifyTolerance, true);
|
|
24278
24602
|
const sw = tempStroke.getAttrs().strokeWidth ?? 1;
|
|
24279
24603
|
const finalWidth = Math.max(box.width, sw);
|
|
24280
24604
|
const finalHeight = Math.max(box.height, sw);
|
|
@@ -24287,9 +24611,44 @@ var WeaveBrushToolAction = class extends WeaveAction {
|
|
|
24287
24611
|
y: finalY,
|
|
24288
24612
|
strokeElements: compressedPoints
|
|
24289
24613
|
});
|
|
24290
|
-
const
|
|
24291
|
-
|
|
24292
|
-
|
|
24614
|
+
const strokeNodeId = tempStroke.getAttrs().id ?? "";
|
|
24615
|
+
const serializedNode = nodeHandler.serialize(tempStroke);
|
|
24616
|
+
const hasPoints = tempStroke.getAttrs().strokeElements.length >= 1;
|
|
24617
|
+
const preview = this.instance.getStage().findOne(`#${strokeNodeId}`);
|
|
24618
|
+
if (!hasPoints) {
|
|
24619
|
+
preview?.destroy();
|
|
24620
|
+
return;
|
|
24621
|
+
}
|
|
24622
|
+
if (preview) preview.setAttrs({ id: `${strokeNodeId}${PREVIEW_ID_SUFFIX}` });
|
|
24623
|
+
this.instance.addNode(serializedNode, this.container?.getAttrs().id);
|
|
24624
|
+
this.removePreviewWhenRendered(preview, strokeNodeId);
|
|
24625
|
+
}
|
|
24626
|
+
/**
|
|
24627
|
+
* Destroys the finished stroke's preview node once its persisted
|
|
24628
|
+
* counterpart has actually been rendered onto the stage, so the stroke is
|
|
24629
|
+
* never absent from the canvas between the two.
|
|
24630
|
+
*
|
|
24631
|
+
* Falls back to destroying immediately where no frame scheduler exists
|
|
24632
|
+
* (non-browser hosts), and gives up waiting after a bounded number of
|
|
24633
|
+
* frames so a preview can never be orphaned if the node never arrives.
|
|
24634
|
+
*/
|
|
24635
|
+
removePreviewWhenRendered(preview, realNodeId) {
|
|
24636
|
+
if (!preview) return;
|
|
24637
|
+
const scheduleFrame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : void 0;
|
|
24638
|
+
if (!scheduleFrame) {
|
|
24639
|
+
preview.destroy();
|
|
24640
|
+
return;
|
|
24641
|
+
}
|
|
24642
|
+
let framesWaited = 0;
|
|
24643
|
+
const check = () => {
|
|
24644
|
+
if (this.instance.getStage().findOne(`#${realNodeId}`) || framesWaited >= 30) {
|
|
24645
|
+
preview.destroy();
|
|
24646
|
+
return;
|
|
24647
|
+
}
|
|
24648
|
+
framesWaited++;
|
|
24649
|
+
scheduleFrame(check);
|
|
24650
|
+
};
|
|
24651
|
+
check();
|
|
24293
24652
|
}
|
|
24294
24653
|
handleEndStroke() {
|
|
24295
24654
|
const tempStroke = this.instance.getStage().findOne(`#${this.strokeId}`);
|
|
@@ -32944,4 +33303,4 @@ function getJSONFromYjsBinary(actualState) {
|
|
|
32944
33303
|
return JSON.parse(actualStateString);
|
|
32945
33304
|
}
|
|
32946
33305
|
//#endregion
|
|
32947
|
-
export { ALIGN_NODES_ALIGN_TO, ALIGN_NODES_TOOL_ACTION_NAME, ALIGN_NODES_TOOL_STATE, BRUSH_TOOL_ACTION_NAME, BRUSH_TOOL_DEFAULT_CONFIG, BRUSH_TOOL_STATE, CONNECTOR_TOOL_ACTION_NAME, CONNECTOR_TOOL_DEFAULT_CONFIG, CONNECTOR_TOOL_STATE, COPY_PASTE_NODES_PLUGIN_STATE, DEFAULT_GUIDE_TOOL_ACTION_CONFIG, DEFAULT_SNAPPING_MANAGER_CONFIG, ELLIPSE_TOOL_ACTION_NAME, ELLIPSE_TOOL_STATE, ERASER_TOOL_ACTION_NAME, ERASER_TOOL_STATE, FRAME_TOOL_ACTION_NAME, FRAME_TOOL_STATE, GUIDE_DISTANCE_NAME, GUIDE_DISTANCE_ORIGIN, GUIDE_KIND, GUIDE_NAME, GUIDE_ORIENTATION, GUIDE_STATE, GUIDE_TOOL_ACTION_NAME, GUIDE_TOOL_STATE, LINE_TOOL_ACTION_NAME, LINE_TOOL_DEFAULT_CONFIG, LINE_TOOL_STATE, MEASURE_TOOL_ACTION_NAME, MEASURE_TOOL_STATE, MOVE_ORIENTATION, MOVE_TOOL_ACTION_NAME, MOVE_TOOL_STATE, PEN_TOOL_ACTION_NAME, PEN_TOOL_STATE, POLYGON_TOOL_ACTION_NAME, POLYGON_TOOL_STATE, RECTANGLE_TOOL_ACTION_NAME, RECTANGLE_TOOL_STATE, REGULAR_POLYGON_TOOL_ACTION_NAME, REGULAR_POLYGON_TOOL_STATE, SELECTION_TOOL_ACTION_NAME, SELECTION_TOOL_STATE, STAGE_MINIMAP_DEFAULT_CONFIG, STAR_TOOL_ACTION_NAME, STAR_TOOL_STATE, TEXT_LAYOUT, TEXT_TOOL_ACTION_NAME, TEXT_TOOL_STATE, VIDEO_TOOL_ACTION_NAME, VIDEO_TOOL_STATE, WEAVE_ARROW_NODE_TYPE, WEAVE_ARROW_TOOL_ACTION_NAME, WEAVE_ARROW_TOOL_STATE, WEAVE_COMMENTS_RENDERER_KEY, WEAVE_COMMENTS_TOOL_LAYER_ID, WEAVE_COMMENT_CREATE_ACTION, WEAVE_COMMENT_NODE_ACTION, WEAVE_COMMENT_NODE_DEFAULTS, WEAVE_COMMENT_NODE_TYPE, WEAVE_COMMENT_STATUS, WEAVE_COMMENT_TOOL_ACTION_NAME, WEAVE_COMMENT_TOOL_DEFAULT_CONFIG, WEAVE_COMMENT_TOOL_STATE, WEAVE_COMMENT_VIEW_ACTION, WEAVE_CONNECTOR_NODE_ANCHOR_ORIGIN, WEAVE_CONNECTOR_NODE_DECORATOR_TYPE, WEAVE_CONNECTOR_NODE_DEFAULT_CONFIG, WEAVE_CONNECTOR_NODE_LINE_ORIGIN, WEAVE_CONNECTOR_NODE_LINE_TYPE, WEAVE_CONNECTOR_NODE_TYPE, WEAVE_COPY_PASTE_CONFIG_DEFAULT, WEAVE_COPY_PASTE_NODES_KEY, WEAVE_COPY_PASTE_PASTE_CATCHER_ID, WEAVE_COPY_PASTE_PASTE_MODES, WEAVE_DEFAULT_USER_INFO_FUNCTION, WEAVE_ELLIPSE_NODE_TYPE, WEAVE_FRAME_DEFAULT_BACKGROUND_COLOR, WEAVE_FRAME_NODE_DEFAULT_CONFIG, WEAVE_FRAME_NODE_DEFAULT_PROPS, WEAVE_FRAME_NODE_TYPE, WEAVE_GRID_DEFAULT_CONFIG, WEAVE_GRID_DOT_TYPES, WEAVE_GRID_LAYER_ID, WEAVE_GRID_TYPES, WEAVE_GROUP_NODE_TYPE, WEAVE_IMAGES_TOOL_ACTION_NAME, WEAVE_IMAGES_TOOL_DEFAULT_CONFIG, WEAVE_IMAGES_TOOL_STATE, WEAVE_IMAGES_TOOL_UPLOAD_TYPE, WEAVE_IMAGE_CROP_ANCHOR_POSITION, WEAVE_IMAGE_CROP_END_TYPE, WEAVE_IMAGE_DEFAULT_CONFIG, WEAVE_IMAGE_NODE_TYPE, WEAVE_IMAGE_TOOL_ACTION_NAME, WEAVE_IMAGE_TOOL_CONFIG_DEFAULT, WEAVE_IMAGE_TOOL_STATE, WEAVE_IMAGE_TOOL_UPLOAD_TYPE, WEAVE_LAYER_NODE_TYPE, WEAVE_LINE_NODE_DEFAULT_CONFIG, WEAVE_LINE_NODE_TYPE, WEAVE_MEASURE_NODE_DEFAULT_CONFIG, WEAVE_MEASURE_NODE_TYPE, WEAVE_MEASURE_TOOL_DEFAULT_CONFIG, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_DEFAULT_CONFIG, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_KEY, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_LAYER_ID, WEAVE_NODES_SELECTION_DEFAULT_CONFIG, WEAVE_NODES_SELECTION_KEY, WEAVE_NODES_SELECTION_LAYER_ID, WEAVE_NODES_SNAPPING_PLUGIN_KEY, WEAVE_POLYGON_NODE_TYPE, WEAVE_POLYGON_PRESETS, WEAVE_RECTANGLE_NODE_TYPE, WEAVE_REGULAR_POLYGON_NODE_TYPE, WEAVE_SHAPE_LABEL_DEFAULTS, WEAVE_STAGE_DEFAULT_MODE, WEAVE_STAGE_DROP_AREA_KEY, WEAVE_STAGE_GRID_PLUGIN_KEY, WEAVE_STAGE_IMAGE_CROPPING_MODE, WEAVE_STAGE_KEYBOARD_MOVE_DEFAULT_CONFIG, WEAVE_STAGE_KEYBOARD_MOVE_KEY, WEAVE_STAGE_KEYBOARD_MOVE_ORIENTATION, WEAVE_STAGE_MINIMAP_KEY, WEAVE_STAGE_NODE_TYPE, WEAVE_STAGE_PANNING_DEFAULT_CONFIG, WEAVE_STAGE_PANNING_KEY, WEAVE_STAGE_PANNING_THROTTLE_MS, WEAVE_STAGE_SHAPE_LABEL_EDITION_MODE, WEAVE_STAGE_TEXT_EDITION_MODE, WEAVE_STAGE_ZOOM_DEFAULT_CONFIG, WEAVE_STAGE_ZOOM_KEY, WEAVE_STAGE_ZOOM_TYPE, WEAVE_STAR_NODE_TYPE, WEAVE_STROKE_NODE_DEFAULT_CONFIG, WEAVE_STROKE_NODE_TYPE, WEAVE_STROKE_SINGLE_NODE_DEFAULT_CONFIG, WEAVE_STROKE_SINGLE_NODE_TIP_SIDE, WEAVE_STROKE_SINGLE_NODE_TIP_TYPE, WEAVE_STROKE_SINGLE_NODE_TYPE, WEAVE_STROKE_TOOL_ACTION_NAME, WEAVE_STROKE_TOOL_ACTION_NAME_ALIASES, WEAVE_STROKE_TOOL_DEFAULT_CONFIG, WEAVE_STROKE_TOOL_STATE, WEAVE_TEXT_NODE_DEFAULT_CONFIG, WEAVE_TEXT_NODE_TYPE, WEAVE_USERS_POINTERS_CONFIG_DEFAULT_PROPS, WEAVE_USERS_POINTERS_KEY, WEAVE_USERS_PRESENCE_CONFIG_DEFAULT_PROPS, WEAVE_USERS_PRESENCE_PLUGIN_KEY, WEAVE_USERS_SELECTION_KEY, WEAVE_USER_POINTER_KEY, WEAVE_USER_PRESENCE_KEY, WEAVE_USER_SELECTION_KEY, WEAVE_VIDEO_DEFAULT_CONFIG, WEAVE_VIDEO_NODE_TYPE, Weave, WeaveAction, WeaveAlignNodesToolAction, WeaveArrowNode, WeaveArrowToolAction, WeaveBrushToolAction, WeaveCommentNode, WeaveCommentToolAction, WeaveCommentsRendererPlugin, WeaveConnectedUsersPlugin, WeaveConnectorNode, WeaveConnectorToolAction, WeaveContextMenuPlugin, WeaveCopyPasteNodesPlugin, WeaveEllipseNode, WeaveEllipseToolAction, WeaveEraserToolAction, WeaveExportNodesToolAction, WeaveExportStageToolAction, WeaveFitToScreenToolAction, WeaveFitToSelectionToolAction, WeaveFrameNode, WeaveFrameToolAction, WeaveGroupNode, WeaveGuideToolAction, WeaveImageNode, WeaveImageToolAction, WeaveImagesToolAction, WeaveLayerNode, WeaveLineNode, WeaveLineToolAction, WeaveMeasureNode, WeaveMeasureToolAction, WeaveMoveToolAction, WeaveNode, WeaveNodesMultiSelectionFeedbackPlugin, WeaveNodesSelectionPlugin, WeaveNodesSnappingPlugin, WeavePenToolAction, WeavePlugin, WeavePolygonNode, WeavePolygonToolAction, WeaveRectangleNode, WeaveRectangleToolAction, WeaveRegularPolygonNode, WeaveRegularPolygonToolAction, WeaveRenderer, WeaveSelectionToolAction, WeaveStageDropAreaPlugin, WeaveStageGridPlugin, WeaveStageKeyboardMovePlugin, WeaveStageMinimapPlugin, WeaveStageNode, WeaveStagePanningPlugin, WeaveStageResizePlugin, WeaveStageZoomPlugin, WeaveStarNode, WeaveStarToolAction, WeaveStateManipulation, WeaveStore, WeaveStrokeNode, WeaveStrokeSingleNode, WeaveStrokeToolAction, WeaveTextNode, WeaveTextToolAction, WeaveUsersPointersPlugin, WeaveUsersPresencePlugin, WeaveUsersSelectionPlugin, WeaveVideoNode, WeaveVideoToolAction, WeaveZoomInToolAction, WeaveZoomOutToolAction, buildAncestorGroupIds, canComposite, clearContainerTargets, computeEllipseLabelMinSize, computePolygonLabelMinSize, computeRectangleLabelMinSize, containerOverCursor, containsNodeDeep, defaultInitialState, downscaleImageFile, downscaleImageFromURL, getBoundingBox, getDownscaleRatio, getExportBoundingBox, getImageSizeFromFile, getJSONFromYjsBinary, getSelectedNodesMetadata, getShapeLabelSchemaFields, getStageClickPoint, getTargetAndSkipNodes, getTargetedNode, getTopmostShadowHost, getVisibleNodes, getVisibleNodesInViewport, hasFrames, hasImages, instantiatePreset, intersectArrays, isArray, isIOS, isInShadowDOM, isNodeInSelection, isNumber, isObject, isServer, labelId, loadImageSource, mapJsonToYjsArray, mapJsonToYjsElements, mapJsonToYjsMap, memoize, mergeExceptArrays, moveNodeToContainer, moveNodeToContainerNT, resetScale, sleep, spreadLabelProps, weavejsToYjsBinary };
|
|
33306
|
+
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, PREVIEW_HANDOVER_MAX_FRAMES, PREVIEW_ID_SUFFIX, 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_LINK_ALLOWED_PROTOCOLS, WEAVE_TEXT_NODE_DEFAULT_CONFIG, WEAVE_TEXT_NODE_TYPE, WEAVE_USERS_POINTERS_CONFIG_DEFAULT_PROPS, WEAVE_USERS_POINTERS_KEY, WEAVE_USERS_PRESENCE_CONFIG_DEFAULT_PROPS, WEAVE_USERS_PRESENCE_PLUGIN_KEY, WEAVE_USERS_SELECTION_KEY, WEAVE_USER_POINTER_KEY, WEAVE_USER_PRESENCE_KEY, WEAVE_USER_SELECTION_KEY, WEAVE_VIDEO_DEFAULT_CONFIG, WEAVE_VIDEO_NODE_TYPE, Weave, WeaveAction, WeaveAlignNodesToolAction, WeaveArrowNode, WeaveArrowToolAction, WeaveBrushToolAction, WeaveCommentNode, WeaveCommentToolAction, WeaveCommentsRendererPlugin, WeaveConnectedUsersPlugin, WeaveConnectorNode, WeaveConnectorToolAction, WeaveContextMenuPlugin, WeaveCopyPasteNodesPlugin, WeaveEllipseNode, WeaveEllipseToolAction, WeaveEraserToolAction, WeaveExportNodesToolAction, WeaveExportStageToolAction, WeaveFitToScreenToolAction, WeaveFitToSelectionToolAction, WeaveFrameNode, WeaveFrameToolAction, WeaveGroupNode, WeaveGuideToolAction, WeaveImageNode, WeaveImageToolAction, WeaveImagesToolAction, WeaveLayerNode, WeaveLineNode, WeaveLineToolAction, WeaveMeasureNode, WeaveMeasureToolAction, WeaveMoveToolAction, WeaveNode, WeaveNodesMultiSelectionFeedbackPlugin, WeaveNodesSelectionPlugin, WeaveNodesSnappingPlugin, WeavePenToolAction, WeavePlugin, WeavePolygonNode, WeavePolygonToolAction, WeaveRectangleNode, WeaveRectangleToolAction, WeaveRegularPolygonNode, WeaveRegularPolygonToolAction, WeaveRenderer, WeaveSelectionToolAction, WeaveStageDropAreaPlugin, WeaveStageGridPlugin, WeaveStageKeyboardMovePlugin, WeaveStageMinimapPlugin, WeaveStageNode, WeaveStagePanningPlugin, WeaveStageResizePlugin, WeaveStageZoomPlugin, WeaveStarNode, WeaveStarToolAction, WeaveStateManipulation, WeaveStore, WeaveStrokeNode, WeaveStrokeSingleNode, WeaveStrokeToolAction, WeaveTextNode, WeaveTextToolAction, WeaveUsersPointersPlugin, WeaveUsersPresencePlugin, WeaveUsersSelectionPlugin, WeaveVideoNode, WeaveVideoToolAction, WeaveZoomInToolAction, WeaveZoomOutToolAction, buildAncestorGroupIds, canComposite, clearContainerTargets, computeEllipseLabelMinSize, computePolygonLabelMinSize, computeRectangleLabelMinSize, containerOverCursor, containsNodeDeep, defaultInitialState, downscaleImageFile, downscaleImageFromURL, getBoundingBox, getDownscaleRatio, getExportBoundingBox, getImageSizeFromFile, getJSONFromYjsBinary, getSelectedNodesMetadata, getShapeLabelSchemaFields, getStageClickPoint, getTargetAndSkipNodes, getTargetedNode, getTopmostShadowHost, getVisibleNodes, getVisibleNodesInViewport, hasFrames, hasImages, instantiatePreset, intersectArrays, isArray, isIOS, isInShadowDOM, isNodeInSelection, isNumber, isObject, isServer, labelId, loadImageSource, mapJsonToYjsArray, mapJsonToYjsElements, mapJsonToYjsMap, memoize, mergeExceptArrays, moveNodeToContainer, moveNodeToContainerNT, resetScale, sleep, spreadLabelProps, weavejsToYjsBinary };
|