@fieldnotes/core 0.29.0 → 0.30.0
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/README.md +595 -583
- package/dist/index.cjs +75 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -3
- package/dist/index.d.ts +14 -3
- package/dist/index.js +75 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2276,6 +2276,19 @@ function getArrowRenderGeometry(arrow) {
|
|
|
2276
2276
|
return geometry;
|
|
2277
2277
|
}
|
|
2278
2278
|
|
|
2279
|
+
// src/elements/shape-geometry.ts
|
|
2280
|
+
function lineEndpoints(shape) {
|
|
2281
|
+
const { x, y } = shape.position;
|
|
2282
|
+
const { w, h } = shape.size;
|
|
2283
|
+
return shape.flip ? [
|
|
2284
|
+
{ x, y: y + h },
|
|
2285
|
+
{ x: x + w, y }
|
|
2286
|
+
] : [
|
|
2287
|
+
{ x, y },
|
|
2288
|
+
{ x: x + w, y: y + h }
|
|
2289
|
+
];
|
|
2290
|
+
}
|
|
2291
|
+
|
|
2279
2292
|
// src/elements/arrow-binding.ts
|
|
2280
2293
|
var BINDABLE_TYPES = /* @__PURE__ */ new Set(["note", "text", "image", "html", "shape"]);
|
|
2281
2294
|
function isBindable(element) {
|
|
@@ -2800,6 +2813,7 @@ var ElementRenderer = class {
|
|
|
2800
2813
|
renderStroke(ctx, stroke) {
|
|
2801
2814
|
if (stroke.points.length < 2) return;
|
|
2802
2815
|
ctx.save();
|
|
2816
|
+
if (stroke.blendMode) ctx.globalCompositeOperation = stroke.blendMode;
|
|
2803
2817
|
ctx.translate(stroke.position.x, stroke.position.y);
|
|
2804
2818
|
ctx.strokeStyle = stroke.color;
|
|
2805
2819
|
ctx.lineCap = "round";
|
|
@@ -2922,7 +2936,7 @@ var ElementRenderer = class {
|
|
|
2922
2936
|
}
|
|
2923
2937
|
renderShape(ctx, shape) {
|
|
2924
2938
|
ctx.save();
|
|
2925
|
-
if (shape.fillColor !== "none") {
|
|
2939
|
+
if (shape.fillColor !== "none" && shape.shape !== "line") {
|
|
2926
2940
|
ctx.fillStyle = shape.fillColor;
|
|
2927
2941
|
this.fillShapePath(ctx, shape);
|
|
2928
2942
|
}
|
|
@@ -2961,6 +2975,15 @@ var ElementRenderer = class {
|
|
|
2961
2975
|
ctx.stroke();
|
|
2962
2976
|
break;
|
|
2963
2977
|
}
|
|
2978
|
+
case "line": {
|
|
2979
|
+
const [a, b] = lineEndpoints(shape);
|
|
2980
|
+
ctx.lineCap = "round";
|
|
2981
|
+
ctx.beginPath();
|
|
2982
|
+
ctx.moveTo(a.x, a.y);
|
|
2983
|
+
ctx.lineTo(b.x, b.y);
|
|
2984
|
+
ctx.stroke();
|
|
2985
|
+
break;
|
|
2986
|
+
}
|
|
2964
2987
|
}
|
|
2965
2988
|
}
|
|
2966
2989
|
renderGrid(ctx, grid) {
|
|
@@ -3234,7 +3257,7 @@ var ElementRenderer = class {
|
|
|
3234
3257
|
// src/elements/element-factory.ts
|
|
3235
3258
|
var DEFAULT_NOTE_FONT_SIZE = 18;
|
|
3236
3259
|
function createStroke(input) {
|
|
3237
|
-
|
|
3260
|
+
const result = {
|
|
3238
3261
|
id: createId("stroke"),
|
|
3239
3262
|
type: "stroke",
|
|
3240
3263
|
position: input.position ?? { x: 0, y: 0 },
|
|
@@ -3246,6 +3269,8 @@ function createStroke(input) {
|
|
|
3246
3269
|
width: input.width ?? 2,
|
|
3247
3270
|
opacity: input.opacity ?? 1
|
|
3248
3271
|
};
|
|
3272
|
+
if (input.blendMode) result.blendMode = input.blendMode;
|
|
3273
|
+
return result;
|
|
3249
3274
|
}
|
|
3250
3275
|
function createNote(input) {
|
|
3251
3276
|
return {
|
|
@@ -3310,7 +3335,7 @@ function createHtmlElement(input) {
|
|
|
3310
3335
|
return el;
|
|
3311
3336
|
}
|
|
3312
3337
|
function createShape(input) {
|
|
3313
|
-
|
|
3338
|
+
const result = {
|
|
3314
3339
|
id: createId("shape"),
|
|
3315
3340
|
type: "shape",
|
|
3316
3341
|
position: input.position,
|
|
@@ -3323,6 +3348,8 @@ function createShape(input) {
|
|
|
3323
3348
|
strokeWidth: input.strokeWidth ?? 2,
|
|
3324
3349
|
fillColor: input.fillColor ?? "none"
|
|
3325
3350
|
};
|
|
3351
|
+
if (input.flip) result.flip = input.flip;
|
|
3352
|
+
return result;
|
|
3326
3353
|
}
|
|
3327
3354
|
function createGrid(input) {
|
|
3328
3355
|
return {
|
|
@@ -6153,7 +6180,7 @@ var DEFAULT_MIN_POINT_DISTANCE = 3;
|
|
|
6153
6180
|
var DEFAULT_PROGRESSIVE_THRESHOLD = 200;
|
|
6154
6181
|
var PROGRESSIVE_HOT_ZONE = 30;
|
|
6155
6182
|
var PencilTool = class {
|
|
6156
|
-
name
|
|
6183
|
+
name;
|
|
6157
6184
|
drawing = false;
|
|
6158
6185
|
points = [];
|
|
6159
6186
|
color;
|
|
@@ -6162,14 +6189,19 @@ var PencilTool = class {
|
|
|
6162
6189
|
minPointDistance;
|
|
6163
6190
|
progressiveThreshold;
|
|
6164
6191
|
nextSimplifyAt;
|
|
6192
|
+
opacity;
|
|
6193
|
+
blendMode;
|
|
6165
6194
|
optionListeners = /* @__PURE__ */ new Set();
|
|
6166
6195
|
constructor(options = {}) {
|
|
6196
|
+
this.name = options.name ?? "pencil";
|
|
6167
6197
|
this.color = options.color ?? "#000000";
|
|
6168
6198
|
this.width = options.width ?? 2;
|
|
6169
6199
|
this.smoothing = options.smoothing ?? DEFAULT_SMOOTHING;
|
|
6170
6200
|
this.minPointDistance = options.minPointDistance ?? DEFAULT_MIN_POINT_DISTANCE;
|
|
6171
6201
|
this.progressiveThreshold = options.progressiveSimplifyThreshold ?? DEFAULT_PROGRESSIVE_THRESHOLD;
|
|
6172
6202
|
this.nextSimplifyAt = this.progressiveThreshold;
|
|
6203
|
+
this.opacity = options.opacity ?? 1;
|
|
6204
|
+
this.blendMode = options.blendMode;
|
|
6173
6205
|
}
|
|
6174
6206
|
onActivate(ctx) {
|
|
6175
6207
|
ctx.setCursor?.("crosshair");
|
|
@@ -6183,7 +6215,9 @@ var PencilTool = class {
|
|
|
6183
6215
|
width: this.width,
|
|
6184
6216
|
smoothing: this.smoothing,
|
|
6185
6217
|
minPointDistance: this.minPointDistance,
|
|
6186
|
-
progressiveSimplifyThreshold: this.progressiveThreshold
|
|
6218
|
+
progressiveSimplifyThreshold: this.progressiveThreshold,
|
|
6219
|
+
opacity: this.opacity,
|
|
6220
|
+
blendMode: this.blendMode
|
|
6187
6221
|
};
|
|
6188
6222
|
}
|
|
6189
6223
|
onOptionsChange(listener) {
|
|
@@ -6197,6 +6231,8 @@ var PencilTool = class {
|
|
|
6197
6231
|
if (options.minPointDistance !== void 0) this.minPointDistance = options.minPointDistance;
|
|
6198
6232
|
if (options.progressiveSimplifyThreshold !== void 0)
|
|
6199
6233
|
this.progressiveThreshold = options.progressiveSimplifyThreshold;
|
|
6234
|
+
if (options.opacity !== void 0) this.opacity = options.opacity;
|
|
6235
|
+
if (options.blendMode !== void 0) this.blendMode = options.blendMode;
|
|
6200
6236
|
this.notifyOptionsChange();
|
|
6201
6237
|
}
|
|
6202
6238
|
onPointerDown(state, ctx) {
|
|
@@ -6238,7 +6274,9 @@ var PencilTool = class {
|
|
|
6238
6274
|
points: simplified,
|
|
6239
6275
|
color: this.color,
|
|
6240
6276
|
width: this.width,
|
|
6241
|
-
layerId: ctx.activeLayerId ?? ""
|
|
6277
|
+
layerId: ctx.activeLayerId ?? "",
|
|
6278
|
+
opacity: this.opacity,
|
|
6279
|
+
blendMode: this.blendMode
|
|
6242
6280
|
});
|
|
6243
6281
|
ctx.store.add(stroke);
|
|
6244
6282
|
computeStrokeSegments(stroke);
|
|
@@ -6254,7 +6292,8 @@ var PencilTool = class {
|
|
|
6254
6292
|
ctx.strokeStyle = this.color;
|
|
6255
6293
|
ctx.lineCap = "round";
|
|
6256
6294
|
ctx.lineJoin = "round";
|
|
6257
|
-
ctx.globalAlpha = 0.8;
|
|
6295
|
+
ctx.globalAlpha = this.blendMode ? this.opacity : 0.8;
|
|
6296
|
+
if (this.blendMode) ctx.globalCompositeOperation = this.blendMode;
|
|
6258
6297
|
const segments = smoothToSegments(this.points);
|
|
6259
6298
|
for (const seg of segments) {
|
|
6260
6299
|
const w = (pressureToWidth(seg.start.pressure, this.width) + pressureToWidth(seg.end.pressure, this.width)) / 2;
|
|
@@ -7144,6 +7183,11 @@ var SelectTool = class {
|
|
|
7144
7183
|
}
|
|
7145
7184
|
isInsideBounds(point, el) {
|
|
7146
7185
|
if (el.type === "grid") return false;
|
|
7186
|
+
if (el.type === "shape" && el.shape === "line") {
|
|
7187
|
+
const [a, b] = lineEndpoints(el);
|
|
7188
|
+
const threshold = Math.max(el.strokeWidth / 2, 6);
|
|
7189
|
+
return distSqToSegment(point, a, b) <= threshold * threshold;
|
|
7190
|
+
}
|
|
7147
7191
|
if ("size" in el) {
|
|
7148
7192
|
const s = el.size;
|
|
7149
7193
|
return point.x >= el.position.x && point.x <= el.position.x + s.w && point.y >= el.position.y && point.y <= el.position.y + s.h;
|
|
@@ -7457,6 +7501,15 @@ var ImageTool = class {
|
|
|
7457
7501
|
};
|
|
7458
7502
|
|
|
7459
7503
|
// src/tools/shape-tool.ts
|
|
7504
|
+
function snapTo45(start, end) {
|
|
7505
|
+
const dx = end.x - start.x;
|
|
7506
|
+
const dy = end.y - start.y;
|
|
7507
|
+
const len = Math.hypot(dx, dy);
|
|
7508
|
+
if (len === 0) return { ...end };
|
|
7509
|
+
const step = Math.PI / 4;
|
|
7510
|
+
const angle = Math.round(Math.atan2(dy, dx) / step) * step;
|
|
7511
|
+
return { x: start.x + Math.cos(angle) * len, y: start.y + Math.sin(angle) * len };
|
|
7512
|
+
}
|
|
7460
7513
|
var ShapeTool = class {
|
|
7461
7514
|
name = "shape";
|
|
7462
7515
|
drawing = false;
|
|
@@ -7514,13 +7567,17 @@ var ShapeTool = class {
|
|
|
7514
7567
|
onPointerMove(state, ctx) {
|
|
7515
7568
|
if (!this.drawing) return;
|
|
7516
7569
|
this.end = this.snap(ctx.camera.screenToWorld({ x: state.x, y: state.y }), ctx);
|
|
7570
|
+
if (this.shape === "line" && this.shiftHeld) {
|
|
7571
|
+
this.end = snapTo45(this.start, this.end);
|
|
7572
|
+
}
|
|
7517
7573
|
ctx.requestRender();
|
|
7518
7574
|
}
|
|
7519
7575
|
onPointerUp(_state, ctx) {
|
|
7520
7576
|
if (!this.drawing) return;
|
|
7521
7577
|
this.drawing = false;
|
|
7522
7578
|
const { position, size } = this.computeRect();
|
|
7523
|
-
|
|
7579
|
+
const isLine = this.shape === "line";
|
|
7580
|
+
if (isLine ? size.w === 0 && size.h === 0 : size.w === 0 || size.h === 0) return;
|
|
7524
7581
|
const shape = createShape({
|
|
7525
7582
|
position,
|
|
7526
7583
|
size,
|
|
@@ -7528,6 +7585,7 @@ var ShapeTool = class {
|
|
|
7528
7585
|
strokeColor: this.strokeColor,
|
|
7529
7586
|
strokeWidth: this.strokeWidth,
|
|
7530
7587
|
fillColor: this.fillColor,
|
|
7588
|
+
...isLine ? { flip: this.end.x > this.start.x !== this.end.y > this.start.y } : {},
|
|
7531
7589
|
layerId: ctx.activeLayerId ?? ""
|
|
7532
7590
|
});
|
|
7533
7591
|
ctx.store.add(shape);
|
|
@@ -7561,6 +7619,13 @@ var ShapeTool = class {
|
|
|
7561
7619
|
ctx.stroke();
|
|
7562
7620
|
break;
|
|
7563
7621
|
}
|
|
7622
|
+
case "line":
|
|
7623
|
+
ctx.lineCap = "round";
|
|
7624
|
+
ctx.beginPath();
|
|
7625
|
+
ctx.moveTo(this.start.x, this.start.y);
|
|
7626
|
+
ctx.lineTo(this.end.x, this.end.y);
|
|
7627
|
+
ctx.stroke();
|
|
7628
|
+
break;
|
|
7564
7629
|
}
|
|
7565
7630
|
ctx.restore();
|
|
7566
7631
|
}
|
|
@@ -7569,7 +7634,7 @@ var ShapeTool = class {
|
|
|
7569
7634
|
let y = Math.min(this.start.y, this.end.y);
|
|
7570
7635
|
let w = Math.abs(this.end.x - this.start.x);
|
|
7571
7636
|
let h = Math.abs(this.end.y - this.start.y);
|
|
7572
|
-
if (this.shiftHeld) {
|
|
7637
|
+
if (this.shiftHeld && this.shape !== "line") {
|
|
7573
7638
|
const side = Math.max(w, h);
|
|
7574
7639
|
w = side;
|
|
7575
7640
|
h = side;
|
|
@@ -7985,7 +8050,7 @@ var TemplateTool = class {
|
|
|
7985
8050
|
};
|
|
7986
8051
|
|
|
7987
8052
|
// src/index.ts
|
|
7988
|
-
var VERSION = "0.
|
|
8053
|
+
var VERSION = "0.30.0";
|
|
7989
8054
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7990
8055
|
0 && (module.exports = {
|
|
7991
8056
|
ArrowTool,
|