@fieldnotes/core 0.39.0 → 0.40.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/dist/index.cjs +165 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -3
- package/dist/index.d.ts +34 -3
- package/dist/index.js +164 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -29,6 +29,7 @@ __export(index_exports, {
|
|
|
29
29
|
HandTool: () => HandTool,
|
|
30
30
|
HistoryStack: () => HistoryStack,
|
|
31
31
|
ImageTool: () => ImageTool,
|
|
32
|
+
LaserTool: () => LaserTool,
|
|
32
33
|
LayerManager: () => LayerManager,
|
|
33
34
|
MeasureTool: () => MeasureTool,
|
|
34
35
|
NoteTool: () => NoteTool,
|
|
@@ -913,6 +914,11 @@ var KeyboardActions = class {
|
|
|
913
914
|
if (tool?.name !== "select") return null;
|
|
914
915
|
return { tool, ctx };
|
|
915
916
|
}
|
|
917
|
+
selectableElements(ctx) {
|
|
918
|
+
return ctx.store.getAll().filter(
|
|
919
|
+
(el) => !el.locked && (ctx.isLayerVisible?.(el.layerId) ?? true) && !(ctx.isLayerLocked?.(el.layerId) ?? false)
|
|
920
|
+
);
|
|
921
|
+
}
|
|
916
922
|
nudge(dx, dy, byCell) {
|
|
917
923
|
if (this.deps.isToolActive()) return false;
|
|
918
924
|
const sel = this.selectTool();
|
|
@@ -1055,12 +1061,28 @@ var KeyboardActions = class {
|
|
|
1055
1061
|
}
|
|
1056
1062
|
const sel = this.selectTool();
|
|
1057
1063
|
if (!sel) return;
|
|
1058
|
-
const ids = sel.ctx.
|
|
1059
|
-
(el) => !el.locked && (sel.ctx.isLayerVisible?.(el.layerId) ?? true) && !(sel.ctx.isLayerLocked?.(el.layerId) ?? false)
|
|
1060
|
-
).map((el) => el.id);
|
|
1064
|
+
const ids = this.selectableElements(sel.ctx).map((el) => el.id);
|
|
1061
1065
|
sel.tool.setSelection(ids);
|
|
1062
1066
|
sel.ctx.requestRender();
|
|
1063
1067
|
}
|
|
1068
|
+
cycleSelection(direction) {
|
|
1069
|
+
if (this.deps.isToolActive()) return;
|
|
1070
|
+
const tm = this.deps.getToolManager();
|
|
1071
|
+
const ctx = this.deps.getToolContext();
|
|
1072
|
+
if (!tm || !ctx) return;
|
|
1073
|
+
if (tm.activeTool?.name !== "select") ctx.switchTool?.("select");
|
|
1074
|
+
const sel = this.selectTool();
|
|
1075
|
+
if (!sel) return;
|
|
1076
|
+
const eligible = this.selectableElements(sel.ctx).filter((el) => el.type !== "grid");
|
|
1077
|
+
if (eligible.length === 0) return;
|
|
1078
|
+
const idxs = sel.tool.selectedIds.map((id) => eligible.findIndex((e) => e.id === id)).filter((i) => i >= 0);
|
|
1079
|
+
const anchor = idxs.length === 0 ? direction > 0 ? -1 : 0 : direction > 0 ? Math.max(...idxs) : Math.min(...idxs);
|
|
1080
|
+
const next = (anchor + direction + eligible.length) % eligible.length;
|
|
1081
|
+
const target = eligible[next];
|
|
1082
|
+
if (!target) return;
|
|
1083
|
+
sel.tool.setSelection([target.id]);
|
|
1084
|
+
sel.ctx.requestRender();
|
|
1085
|
+
}
|
|
1064
1086
|
zoomToFit() {
|
|
1065
1087
|
if (this.deps.isToolActive()) return;
|
|
1066
1088
|
this.deps.fitToContent?.();
|
|
@@ -1165,6 +1187,8 @@ var DEFAULT_BINDINGS = [
|
|
|
1165
1187
|
["undo", ["mod+z"]],
|
|
1166
1188
|
["redo", ["mod+y", "mod+shift+z"]],
|
|
1167
1189
|
["select-all", ["mod+a"]],
|
|
1190
|
+
["cycle-selection", ["tab"]],
|
|
1191
|
+
["cycle-selection-reverse", ["shift+tab"]],
|
|
1168
1192
|
["copy", ["mod+c"]],
|
|
1169
1193
|
["duplicate", ["mod+d"]],
|
|
1170
1194
|
["z-forward", ["]"]],
|
|
@@ -1435,6 +1459,14 @@ var KeyboardHandler = class {
|
|
|
1435
1459
|
e?.preventDefault();
|
|
1436
1460
|
this.deps.actions.selectAll();
|
|
1437
1461
|
return;
|
|
1462
|
+
case "cycle-selection":
|
|
1463
|
+
e?.preventDefault();
|
|
1464
|
+
this.deps.actions.cycleSelection(1);
|
|
1465
|
+
return;
|
|
1466
|
+
case "cycle-selection-reverse":
|
|
1467
|
+
e?.preventDefault();
|
|
1468
|
+
this.deps.actions.cycleSelection(-1);
|
|
1469
|
+
return;
|
|
1438
1470
|
case "copy":
|
|
1439
1471
|
e?.preventDefault();
|
|
1440
1472
|
this.deps.actions.copy();
|
|
@@ -7773,6 +7805,17 @@ function renderArrowHandles(canvasCtx, arrow, zoom) {
|
|
|
7773
7805
|
canvasCtx.stroke();
|
|
7774
7806
|
}
|
|
7775
7807
|
}
|
|
7808
|
+
function renderArrowHoverHandle(canvasCtx, arrow, zoom) {
|
|
7809
|
+
const mid = getArrowMidpoint(arrow.from, arrow.to, arrow.bend);
|
|
7810
|
+
const radius = HANDLE_RADIUS / zoom;
|
|
7811
|
+
canvasCtx.fillStyle = "#2196F3";
|
|
7812
|
+
canvasCtx.strokeStyle = "#2196F3";
|
|
7813
|
+
canvasCtx.lineWidth = 1.5 / zoom;
|
|
7814
|
+
canvasCtx.beginPath();
|
|
7815
|
+
canvasCtx.arc(mid.x, mid.y, radius, 0, Math.PI * 2);
|
|
7816
|
+
canvasCtx.fill();
|
|
7817
|
+
canvasCtx.stroke();
|
|
7818
|
+
}
|
|
7776
7819
|
|
|
7777
7820
|
// src/elements/snap-guides.ts
|
|
7778
7821
|
function xAnchors(b) {
|
|
@@ -8621,7 +8664,13 @@ var SelectTool = class {
|
|
|
8621
8664
|
if (this.hoveredId && this.ctx && this.mode.type === "idle") {
|
|
8622
8665
|
if (!this._selectedIds.includes(this.hoveredId)) {
|
|
8623
8666
|
const el = this.ctx.store.getById(this.hoveredId);
|
|
8624
|
-
if (el) {
|
|
8667
|
+
if (el?.type === "arrow") {
|
|
8668
|
+
canvasCtx.save();
|
|
8669
|
+
canvasCtx.globalAlpha = 0.35;
|
|
8670
|
+
canvasCtx.setLineDash([]);
|
|
8671
|
+
renderArrowHoverHandle(canvasCtx, el, this.ctx.camera.zoom);
|
|
8672
|
+
canvasCtx.restore();
|
|
8673
|
+
} else if (el) {
|
|
8625
8674
|
const b = getElementBounds(el);
|
|
8626
8675
|
if (b) {
|
|
8627
8676
|
canvasCtx.save();
|
|
@@ -9592,8 +9641,118 @@ var TemplateTool = class {
|
|
|
9592
9641
|
}
|
|
9593
9642
|
};
|
|
9594
9643
|
|
|
9644
|
+
// src/tools/laser-tool.ts
|
|
9645
|
+
var DEFAULT_COLOR = "#ff3b30";
|
|
9646
|
+
var DEFAULT_WIDTH = 4;
|
|
9647
|
+
var DEFAULT_FADE_MS = 1200;
|
|
9648
|
+
var LaserTool = class {
|
|
9649
|
+
name;
|
|
9650
|
+
color;
|
|
9651
|
+
width;
|
|
9652
|
+
fadeMs;
|
|
9653
|
+
trail = [];
|
|
9654
|
+
rafId = null;
|
|
9655
|
+
drawing = false;
|
|
9656
|
+
optionListeners = /* @__PURE__ */ new Set();
|
|
9657
|
+
constructor(options = {}) {
|
|
9658
|
+
this.name = options.name ?? "laser";
|
|
9659
|
+
this.color = options.color ?? DEFAULT_COLOR;
|
|
9660
|
+
this.width = options.width ?? DEFAULT_WIDTH;
|
|
9661
|
+
this.fadeMs = options.fadeMs ?? DEFAULT_FADE_MS;
|
|
9662
|
+
}
|
|
9663
|
+
now() {
|
|
9664
|
+
return performance.now();
|
|
9665
|
+
}
|
|
9666
|
+
onActivate(ctx) {
|
|
9667
|
+
ctx.setCursor?.("crosshair");
|
|
9668
|
+
}
|
|
9669
|
+
onDeactivate(ctx) {
|
|
9670
|
+
if (this.rafId !== null) {
|
|
9671
|
+
cancelAnimationFrame(this.rafId);
|
|
9672
|
+
this.rafId = null;
|
|
9673
|
+
}
|
|
9674
|
+
this.trail = [];
|
|
9675
|
+
this.drawing = false;
|
|
9676
|
+
ctx.setCursor?.("default");
|
|
9677
|
+
ctx.requestRender();
|
|
9678
|
+
}
|
|
9679
|
+
getOptions() {
|
|
9680
|
+
return {
|
|
9681
|
+
name: this.name,
|
|
9682
|
+
color: this.color,
|
|
9683
|
+
width: this.width,
|
|
9684
|
+
fadeMs: this.fadeMs
|
|
9685
|
+
};
|
|
9686
|
+
}
|
|
9687
|
+
onOptionsChange(listener) {
|
|
9688
|
+
this.optionListeners.add(listener);
|
|
9689
|
+
return () => this.optionListeners.delete(listener);
|
|
9690
|
+
}
|
|
9691
|
+
setOptions(options) {
|
|
9692
|
+
if (options.color !== void 0) this.color = options.color;
|
|
9693
|
+
if (options.width !== void 0) this.width = options.width;
|
|
9694
|
+
if (options.fadeMs !== void 0) this.fadeMs = options.fadeMs;
|
|
9695
|
+
this.notifyOptionsChange();
|
|
9696
|
+
}
|
|
9697
|
+
onPointerDown(state, ctx) {
|
|
9698
|
+
this.drawing = true;
|
|
9699
|
+
const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });
|
|
9700
|
+
this.trail.push({ x: world.x, y: world.y, t: this.now() });
|
|
9701
|
+
this.ensureAnimating(ctx);
|
|
9702
|
+
}
|
|
9703
|
+
onPointerMove(state, ctx) {
|
|
9704
|
+
if (!this.drawing) return;
|
|
9705
|
+
const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });
|
|
9706
|
+
this.trail.push({ x: world.x, y: world.y, t: this.now() });
|
|
9707
|
+
this.ensureAnimating(ctx);
|
|
9708
|
+
}
|
|
9709
|
+
onPointerUp(_state, _ctx) {
|
|
9710
|
+
this.drawing = false;
|
|
9711
|
+
}
|
|
9712
|
+
renderOverlay(ctx) {
|
|
9713
|
+
if (this.trail.length < 2) return;
|
|
9714
|
+
ctx.save();
|
|
9715
|
+
ctx.strokeStyle = this.color;
|
|
9716
|
+
ctx.lineWidth = this.width;
|
|
9717
|
+
ctx.lineCap = "round";
|
|
9718
|
+
ctx.lineJoin = "round";
|
|
9719
|
+
const now = this.now();
|
|
9720
|
+
for (let i = 0; i < this.trail.length - 1; i++) {
|
|
9721
|
+
const a = this.trail[i];
|
|
9722
|
+
const b = this.trail[i + 1];
|
|
9723
|
+
if (!a || !b) continue;
|
|
9724
|
+
const age = now - b.t;
|
|
9725
|
+
ctx.globalAlpha = Math.max(0, 1 - age / this.fadeMs);
|
|
9726
|
+
ctx.beginPath();
|
|
9727
|
+
ctx.moveTo(a.x, a.y);
|
|
9728
|
+
ctx.lineTo(b.x, b.y);
|
|
9729
|
+
ctx.stroke();
|
|
9730
|
+
}
|
|
9731
|
+
ctx.restore();
|
|
9732
|
+
}
|
|
9733
|
+
ensureAnimating(ctx) {
|
|
9734
|
+
if (this.rafId === null) {
|
|
9735
|
+
this.rafId = requestAnimationFrame(() => this.tick(ctx));
|
|
9736
|
+
}
|
|
9737
|
+
}
|
|
9738
|
+
tick(ctx) {
|
|
9739
|
+
const cutoff = this.now() - this.fadeMs;
|
|
9740
|
+
this.trail = this.trail.filter((p) => p.t >= cutoff);
|
|
9741
|
+
if (this.trail.length > 0) {
|
|
9742
|
+
ctx.requestRender();
|
|
9743
|
+
this.rafId = requestAnimationFrame(() => this.tick(ctx));
|
|
9744
|
+
} else {
|
|
9745
|
+
ctx.requestRender();
|
|
9746
|
+
this.rafId = null;
|
|
9747
|
+
}
|
|
9748
|
+
}
|
|
9749
|
+
notifyOptionsChange() {
|
|
9750
|
+
for (const listener of this.optionListeners) listener();
|
|
9751
|
+
}
|
|
9752
|
+
};
|
|
9753
|
+
|
|
9595
9754
|
// src/index.ts
|
|
9596
|
-
var VERSION = "0.
|
|
9755
|
+
var VERSION = "0.40.0";
|
|
9597
9756
|
// Annotate the CommonJS export names for ESM import in node:
|
|
9598
9757
|
0 && (module.exports = {
|
|
9599
9758
|
ArrowTool,
|
|
@@ -9605,6 +9764,7 @@ var VERSION = "0.39.0";
|
|
|
9605
9764
|
HandTool,
|
|
9606
9765
|
HistoryStack,
|
|
9607
9766
|
ImageTool,
|
|
9767
|
+
LaserTool,
|
|
9608
9768
|
LayerManager,
|
|
9609
9769
|
MeasureTool,
|
|
9610
9770
|
NoteTool,
|