@fieldnotes/core 0.52.2 → 0.54.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 +273 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +157 -33
- package/dist/index.d.ts +157 -33
- package/dist/index.js +269 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ __export(index_exports, {
|
|
|
30
30
|
HistoryStack: () => HistoryStack,
|
|
31
31
|
ImageTool: () => ImageTool,
|
|
32
32
|
IndexedDBAdapter: () => IndexedDBAdapter,
|
|
33
|
+
LASER_TRAIL_PRESENCE_KIND: () => LASER_TRAIL_PRESENCE_KIND,
|
|
33
34
|
LaserTool: () => LaserTool,
|
|
34
35
|
LayerManager: () => LayerManager,
|
|
35
36
|
LocalStorageAdapter: () => LocalStorageAdapter,
|
|
@@ -37,6 +38,7 @@ __export(index_exports, {
|
|
|
37
38
|
MemoryAdapter: () => MemoryAdapter,
|
|
38
39
|
NoteTool: () => NoteTool,
|
|
39
40
|
PencilTool: () => PencilTool,
|
|
41
|
+
RemoteLaserOverlay: () => RemoteLaserOverlay,
|
|
40
42
|
SelectTool: () => SelectTool,
|
|
41
43
|
ShapeTool: () => ShapeTool,
|
|
42
44
|
TemplateTool: () => TemplateTool,
|
|
@@ -72,12 +74,14 @@ __export(index_exports, {
|
|
|
72
74
|
getHexCellsInRectangle: () => getHexCellsInRectangle,
|
|
73
75
|
getHexCellsInSquare: () => getHexCellsInSquare,
|
|
74
76
|
getHexDistance: () => getHexDistance,
|
|
77
|
+
isLaserTrailPresence: () => isLaserTrailPresence,
|
|
75
78
|
isNearBezier: () => isNearBezier,
|
|
76
79
|
setFontSize: () => setFontSize,
|
|
77
80
|
smartSnap: () => smartSnap,
|
|
78
81
|
snapPoint: () => snapPoint,
|
|
79
82
|
snapToHexCenter: () => snapToHexCenter,
|
|
80
83
|
styleToPatch: () => styleToPatch,
|
|
84
|
+
toLaserTrailPresence: () => toLaserTrailPresence,
|
|
81
85
|
toggleBold: () => toggleBold,
|
|
82
86
|
toggleItalic: () => toggleItalic,
|
|
83
87
|
toggleStrikethrough: () => toggleStrikethrough,
|
|
@@ -6922,6 +6926,7 @@ var RenderLoop = class {
|
|
|
6922
6926
|
// set on recenter/viewport-change; consumed by the grid block
|
|
6923
6927
|
stats = new RenderStats();
|
|
6924
6928
|
layerGroups = /* @__PURE__ */ new Map();
|
|
6929
|
+
overlays = /* @__PURE__ */ new Set();
|
|
6925
6930
|
gridCacheCanvas = null;
|
|
6926
6931
|
gridCacheCtx = null;
|
|
6927
6932
|
lastGridRefs = [];
|
|
@@ -6980,6 +6985,29 @@ var RenderLoop = class {
|
|
|
6980
6985
|
getStats() {
|
|
6981
6986
|
return this.stats.getSnapshot();
|
|
6982
6987
|
}
|
|
6988
|
+
/**
|
|
6989
|
+
* Registers a viewport overlay drawn beneath the active tool's own overlay.
|
|
6990
|
+
* Returns an idempotent unsubscribe that also erases the overlay's last
|
|
6991
|
+
* frame.
|
|
6992
|
+
*/
|
|
6993
|
+
registerOverlay(draw) {
|
|
6994
|
+
this.overlays.add(draw);
|
|
6995
|
+
this.requestRender();
|
|
6996
|
+
return () => {
|
|
6997
|
+
if (this.overlays.delete(draw)) this.requestRender();
|
|
6998
|
+
};
|
|
6999
|
+
}
|
|
7000
|
+
drawRegisteredOverlays(ctx) {
|
|
7001
|
+
for (const draw of this.overlays) {
|
|
7002
|
+
ctx.save();
|
|
7003
|
+
try {
|
|
7004
|
+
draw(ctx);
|
|
7005
|
+
} catch {
|
|
7006
|
+
} finally {
|
|
7007
|
+
ctx.restore();
|
|
7008
|
+
}
|
|
7009
|
+
}
|
|
7010
|
+
}
|
|
6983
7011
|
compositeLayerCache(ctx, layerId, opacity) {
|
|
6984
7012
|
const cached = this.layerCache.getCanvas(layerId);
|
|
6985
7013
|
const offset = this.marginViewport.compositeOffset(
|
|
@@ -7113,7 +7141,8 @@ var RenderLoop = class {
|
|
|
7113
7141
|
}
|
|
7114
7142
|
const activeTool = this.toolManager.activeTool;
|
|
7115
7143
|
const overlayOrder = visibleElements.length + 1;
|
|
7116
|
-
|
|
7144
|
+
const hasOverlay = activeTool?.renderOverlay !== void 0 || this.overlays.size > 0;
|
|
7145
|
+
if (hybridActive && hasOverlay) hybridOrders.add(overlayOrder);
|
|
7117
7146
|
this.hybridSurface.beginFrame(hybridOrders, this.canvasEl.width, this.canvasEl.height);
|
|
7118
7147
|
for (const [layerId, elements] of this.layerGroups) {
|
|
7119
7148
|
const isActiveDrawingLayer = layerId === this.activeDrawingLayerId;
|
|
@@ -7223,7 +7252,7 @@ var RenderLoop = class {
|
|
|
7223
7252
|
hybridCtx.restore();
|
|
7224
7253
|
}
|
|
7225
7254
|
const overlayT0 = performance.now();
|
|
7226
|
-
if (hybridActive &&
|
|
7255
|
+
if (hybridActive && hasOverlay) {
|
|
7227
7256
|
const overlayCtx = this.hybridSurface.getContext(overlayOrder);
|
|
7228
7257
|
if (overlayCtx) {
|
|
7229
7258
|
overlayCtx.clearRect(0, 0, this.canvasEl.width, this.canvasEl.height);
|
|
@@ -7231,11 +7260,13 @@ var RenderLoop = class {
|
|
|
7231
7260
|
overlayCtx.scale(dpr, dpr);
|
|
7232
7261
|
overlayCtx.translate(this.camera.position.x, this.camera.position.y);
|
|
7233
7262
|
overlayCtx.scale(this.camera.zoom, this.camera.zoom);
|
|
7234
|
-
|
|
7263
|
+
this.drawRegisteredOverlays(overlayCtx);
|
|
7264
|
+
if (activeTool?.renderOverlay) activeTool.renderOverlay(overlayCtx);
|
|
7235
7265
|
overlayCtx.restore();
|
|
7236
7266
|
}
|
|
7237
|
-
} else if (
|
|
7238
|
-
|
|
7267
|
+
} else if (hasOverlay) {
|
|
7268
|
+
this.drawRegisteredOverlays(ctx);
|
|
7269
|
+
if (activeTool?.renderOverlay) activeTool.renderOverlay(ctx);
|
|
7239
7270
|
}
|
|
7240
7271
|
const overlayMs = performance.now() - overlayT0;
|
|
7241
7272
|
ctx.restore();
|
|
@@ -8184,6 +8215,7 @@ var Viewport = class {
|
|
|
8184
8215
|
noteEditor;
|
|
8185
8216
|
arrowLabelEditor;
|
|
8186
8217
|
historyRecorder;
|
|
8218
|
+
transactionDepth = 0;
|
|
8187
8219
|
selectionOps;
|
|
8188
8220
|
toolContext;
|
|
8189
8221
|
marginViewport;
|
|
@@ -8228,6 +8260,17 @@ var Viewport = class {
|
|
|
8228
8260
|
requestRender() {
|
|
8229
8261
|
this.renderLoop.requestRender();
|
|
8230
8262
|
}
|
|
8263
|
+
/**
|
|
8264
|
+
* Registers a world-space overlay drawn above elements on every frame,
|
|
8265
|
+
* regardless of the active tool — the surface for remote presence visuals
|
|
8266
|
+
* such as laser trails, cursors, pings, and shared rulers. Overlays draw
|
|
8267
|
+
* beneath the active tool's own `renderOverlay` and never touch elements,
|
|
8268
|
+
* history, or persisted state. Returns an idempotent unsubscribe that also
|
|
8269
|
+
* erases the overlay's last frame.
|
|
8270
|
+
*/
|
|
8271
|
+
registerOverlay(draw) {
|
|
8272
|
+
return this.renderLoop.registerOverlay(draw);
|
|
8273
|
+
}
|
|
8231
8274
|
exportState() {
|
|
8232
8275
|
return exportState(
|
|
8233
8276
|
this.store.snapshot(),
|
|
@@ -8297,6 +8340,35 @@ var Viewport = class {
|
|
|
8297
8340
|
get shortcuts() {
|
|
8298
8341
|
return this.inputHandler.shortcuts;
|
|
8299
8342
|
}
|
|
8343
|
+
/**
|
|
8344
|
+
* Groups synchronous local store and layer mutations into one undo step.
|
|
8345
|
+
* Nested calls join the outer transaction. If the callback throws, mutations
|
|
8346
|
+
* already applied remain undoable and the original error is rethrown.
|
|
8347
|
+
*/
|
|
8348
|
+
transaction(operation) {
|
|
8349
|
+
const isOuterTransaction = this.transactionDepth === 0;
|
|
8350
|
+
if (isOuterTransaction) {
|
|
8351
|
+
this.inputHandler.flushPendingHistory();
|
|
8352
|
+
this.historyRecorder.begin();
|
|
8353
|
+
}
|
|
8354
|
+
this.transactionDepth += 1;
|
|
8355
|
+
try {
|
|
8356
|
+
return operation();
|
|
8357
|
+
} finally {
|
|
8358
|
+
this.transactionDepth -= 1;
|
|
8359
|
+
if (isOuterTransaction) this.historyRecorder.commit();
|
|
8360
|
+
}
|
|
8361
|
+
}
|
|
8362
|
+
/** Removes existing elements as one undoable operation and returns the number removed. */
|
|
8363
|
+
removeElements(ids) {
|
|
8364
|
+
const existingIds = [...new Set(ids)].filter((id) => this.store.getById(id) !== void 0);
|
|
8365
|
+
if (existingIds.length === 0) return 0;
|
|
8366
|
+
this.transaction(() => {
|
|
8367
|
+
for (const id of existingIds) this.store.remove(id);
|
|
8368
|
+
});
|
|
8369
|
+
this.requestRender();
|
|
8370
|
+
return existingIds.length;
|
|
8371
|
+
}
|
|
8300
8372
|
undo() {
|
|
8301
8373
|
this.inputHandler.flushPendingHistory();
|
|
8302
8374
|
this.historyRecorder.pause();
|
|
@@ -8546,6 +8618,154 @@ var Viewport = class {
|
|
|
8546
8618
|
}
|
|
8547
8619
|
};
|
|
8548
8620
|
|
|
8621
|
+
// src/canvas/remote-laser-overlay.ts
|
|
8622
|
+
var LASER_TRAIL_PRESENCE_KIND = "laser";
|
|
8623
|
+
function isFinitePoint(value) {
|
|
8624
|
+
if (typeof value !== "object" || value === null) return false;
|
|
8625
|
+
const point = value;
|
|
8626
|
+
return typeof point.x === "number" && Number.isFinite(point.x) && typeof point.y === "number" && Number.isFinite(point.y);
|
|
8627
|
+
}
|
|
8628
|
+
function isLaserTrailPresence(data) {
|
|
8629
|
+
if (typeof data !== "object" || data === null) return false;
|
|
8630
|
+
const payload = data;
|
|
8631
|
+
if (payload.kind !== LASER_TRAIL_PRESENCE_KIND) return false;
|
|
8632
|
+
if (!Array.isArray(payload.points) || !payload.points.every(isFinitePoint)) return false;
|
|
8633
|
+
if (payload.color !== void 0 && typeof payload.color !== "string") return false;
|
|
8634
|
+
if (payload.width !== void 0 && !(typeof payload.width === "number" && payload.width > 0)) {
|
|
8635
|
+
return false;
|
|
8636
|
+
}
|
|
8637
|
+
if (payload.fadeMs !== void 0 && !(typeof payload.fadeMs === "number" && payload.fadeMs > 0)) {
|
|
8638
|
+
return false;
|
|
8639
|
+
}
|
|
8640
|
+
return true;
|
|
8641
|
+
}
|
|
8642
|
+
function toLaserTrailPresence(emission) {
|
|
8643
|
+
return {
|
|
8644
|
+
kind: LASER_TRAIL_PRESENCE_KIND,
|
|
8645
|
+
points: emission.points.map((point) => ({ x: point.x, y: point.y })),
|
|
8646
|
+
color: emission.color,
|
|
8647
|
+
width: emission.width,
|
|
8648
|
+
fadeMs: emission.fadeMs
|
|
8649
|
+
};
|
|
8650
|
+
}
|
|
8651
|
+
var DEFAULT_COLOR = "#ff3b30";
|
|
8652
|
+
var DEFAULT_WIDTH = 4;
|
|
8653
|
+
var DEFAULT_FADE_MS = 1200;
|
|
8654
|
+
var DEFAULT_MAX_POINTS = 512;
|
|
8655
|
+
var RemoteLaserOverlay = class {
|
|
8656
|
+
host;
|
|
8657
|
+
color;
|
|
8658
|
+
width;
|
|
8659
|
+
fadeMs;
|
|
8660
|
+
maxPointsPerSender;
|
|
8661
|
+
trails = /* @__PURE__ */ new Map();
|
|
8662
|
+
unregister;
|
|
8663
|
+
rafId = null;
|
|
8664
|
+
disposed = false;
|
|
8665
|
+
constructor(host, options = {}) {
|
|
8666
|
+
this.host = host;
|
|
8667
|
+
this.color = options.color ?? DEFAULT_COLOR;
|
|
8668
|
+
this.width = options.width ?? DEFAULT_WIDTH;
|
|
8669
|
+
this.fadeMs = options.fadeMs ?? DEFAULT_FADE_MS;
|
|
8670
|
+
this.maxPointsPerSender = options.maxPointsPerSender ?? DEFAULT_MAX_POINTS;
|
|
8671
|
+
this.unregister = host.registerOverlay((ctx) => this.renderTrails(ctx));
|
|
8672
|
+
}
|
|
8673
|
+
now() {
|
|
8674
|
+
return performance.now();
|
|
8675
|
+
}
|
|
8676
|
+
/**
|
|
8677
|
+
* Applies a presence payload from `sender` (any opaque per-sender key, e.g.
|
|
8678
|
+
* the envelope `from`). Non-laser or malformed payloads are ignored and
|
|
8679
|
+
* reported as `false`, so hosts can feed every presence frame through.
|
|
8680
|
+
*/
|
|
8681
|
+
apply(sender, data) {
|
|
8682
|
+
if (this.disposed || !isLaserTrailPresence(data)) return false;
|
|
8683
|
+
let trail = this.trails.get(sender);
|
|
8684
|
+
if (!trail) {
|
|
8685
|
+
trail = { points: [], color: this.color, width: this.width, fadeMs: this.fadeMs };
|
|
8686
|
+
this.trails.set(sender, trail);
|
|
8687
|
+
}
|
|
8688
|
+
trail.color = data.color ?? this.color;
|
|
8689
|
+
trail.width = data.width ?? this.width;
|
|
8690
|
+
trail.fadeMs = data.fadeMs ?? this.fadeMs;
|
|
8691
|
+
const t = this.now();
|
|
8692
|
+
for (const point of data.points) {
|
|
8693
|
+
trail.points.push({ x: point.x, y: point.y, t });
|
|
8694
|
+
}
|
|
8695
|
+
const excess = trail.points.length - this.maxPointsPerSender;
|
|
8696
|
+
if (excess > 0) trail.points.splice(0, excess);
|
|
8697
|
+
this.ensureAnimating();
|
|
8698
|
+
this.host.requestRender();
|
|
8699
|
+
return true;
|
|
8700
|
+
}
|
|
8701
|
+
/** Removes a sender's trail immediately (presence-leave/disconnect). */
|
|
8702
|
+
remove(sender) {
|
|
8703
|
+
if (this.trails.delete(sender)) this.host.requestRender();
|
|
8704
|
+
}
|
|
8705
|
+
/** Removes every trail immediately. */
|
|
8706
|
+
clear() {
|
|
8707
|
+
if (this.trails.size === 0) return;
|
|
8708
|
+
this.trails.clear();
|
|
8709
|
+
this.host.requestRender();
|
|
8710
|
+
}
|
|
8711
|
+
/** Number of senders with a live (unfaded) trail. */
|
|
8712
|
+
get activeSenderCount() {
|
|
8713
|
+
return this.trails.size;
|
|
8714
|
+
}
|
|
8715
|
+
/** Unregisters the overlay and stops the fade loop. Idempotent. */
|
|
8716
|
+
dispose() {
|
|
8717
|
+
if (this.disposed) return;
|
|
8718
|
+
this.disposed = true;
|
|
8719
|
+
if (this.rafId !== null) {
|
|
8720
|
+
cancelAnimationFrame(this.rafId);
|
|
8721
|
+
this.rafId = null;
|
|
8722
|
+
}
|
|
8723
|
+
this.trails.clear();
|
|
8724
|
+
this.unregister?.();
|
|
8725
|
+
this.unregister = null;
|
|
8726
|
+
}
|
|
8727
|
+
ensureAnimating() {
|
|
8728
|
+
if (this.rafId === null) {
|
|
8729
|
+
this.rafId = requestAnimationFrame(() => this.tick());
|
|
8730
|
+
}
|
|
8731
|
+
}
|
|
8732
|
+
tick() {
|
|
8733
|
+
if (this.disposed) return;
|
|
8734
|
+
const now = this.now();
|
|
8735
|
+
for (const [sender, trail] of this.trails) {
|
|
8736
|
+
const cutoff = now - trail.fadeMs;
|
|
8737
|
+
trail.points = trail.points.filter((point) => point.t >= cutoff);
|
|
8738
|
+
if (trail.points.length === 0) this.trails.delete(sender);
|
|
8739
|
+
}
|
|
8740
|
+
this.host.requestRender();
|
|
8741
|
+
this.rafId = this.trails.size > 0 ? requestAnimationFrame(() => this.tick()) : null;
|
|
8742
|
+
}
|
|
8743
|
+
renderTrails(ctx) {
|
|
8744
|
+
if (this.trails.size === 0) return;
|
|
8745
|
+
const now = this.now();
|
|
8746
|
+
for (const trail of this.trails.values()) {
|
|
8747
|
+
if (trail.points.length < 2) continue;
|
|
8748
|
+
ctx.save();
|
|
8749
|
+
ctx.strokeStyle = trail.color;
|
|
8750
|
+
ctx.lineWidth = trail.width;
|
|
8751
|
+
ctx.lineCap = "round";
|
|
8752
|
+
ctx.lineJoin = "round";
|
|
8753
|
+
for (let i = 0; i < trail.points.length - 1; i++) {
|
|
8754
|
+
const a = trail.points[i];
|
|
8755
|
+
const b = trail.points[i + 1];
|
|
8756
|
+
if (!a || !b) continue;
|
|
8757
|
+
const age = now - b.t;
|
|
8758
|
+
ctx.globalAlpha = Math.max(0, 1 - age / trail.fadeMs);
|
|
8759
|
+
ctx.beginPath();
|
|
8760
|
+
ctx.moveTo(a.x, a.y);
|
|
8761
|
+
ctx.lineTo(b.x, b.y);
|
|
8762
|
+
ctx.stroke();
|
|
8763
|
+
}
|
|
8764
|
+
ctx.restore();
|
|
8765
|
+
}
|
|
8766
|
+
}
|
|
8767
|
+
};
|
|
8768
|
+
|
|
8549
8769
|
// src/tools/hand-tool.ts
|
|
8550
8770
|
var HandTool = class {
|
|
8551
8771
|
name = "hand";
|
|
@@ -11102,9 +11322,9 @@ var TemplateTool = class {
|
|
|
11102
11322
|
};
|
|
11103
11323
|
|
|
11104
11324
|
// src/tools/laser-tool.ts
|
|
11105
|
-
var
|
|
11106
|
-
var
|
|
11107
|
-
var
|
|
11325
|
+
var DEFAULT_COLOR2 = "#ff3b30";
|
|
11326
|
+
var DEFAULT_WIDTH2 = 4;
|
|
11327
|
+
var DEFAULT_FADE_MS2 = 1200;
|
|
11108
11328
|
var LaserTool = class {
|
|
11109
11329
|
name;
|
|
11110
11330
|
color;
|
|
@@ -11114,11 +11334,13 @@ var LaserTool = class {
|
|
|
11114
11334
|
rafId = null;
|
|
11115
11335
|
drawing = false;
|
|
11116
11336
|
optionListeners = /* @__PURE__ */ new Set();
|
|
11337
|
+
trailListeners = /* @__PURE__ */ new Set();
|
|
11338
|
+
pendingEmission = [];
|
|
11117
11339
|
constructor(options = {}) {
|
|
11118
11340
|
this.name = options.name ?? "laser";
|
|
11119
|
-
this.color = options.color ??
|
|
11120
|
-
this.width = options.width ??
|
|
11121
|
-
this.fadeMs = options.fadeMs ??
|
|
11341
|
+
this.color = options.color ?? DEFAULT_COLOR2;
|
|
11342
|
+
this.width = options.width ?? DEFAULT_WIDTH2;
|
|
11343
|
+
this.fadeMs = options.fadeMs ?? DEFAULT_FADE_MS2;
|
|
11122
11344
|
}
|
|
11123
11345
|
now() {
|
|
11124
11346
|
return performance.now();
|
|
@@ -11133,6 +11355,7 @@ var LaserTool = class {
|
|
|
11133
11355
|
}
|
|
11134
11356
|
this.trail = [];
|
|
11135
11357
|
this.drawing = false;
|
|
11358
|
+
this.pendingEmission = [];
|
|
11136
11359
|
ctx.setCursor?.("default");
|
|
11137
11360
|
ctx.requestRender();
|
|
11138
11361
|
}
|
|
@@ -11148,6 +11371,16 @@ var LaserTool = class {
|
|
|
11148
11371
|
this.optionListeners.add(listener);
|
|
11149
11372
|
return () => this.optionListeners.delete(listener);
|
|
11150
11373
|
}
|
|
11374
|
+
/**
|
|
11375
|
+
* Subscribes to coalesced trail emissions. Points recorded by pointer input
|
|
11376
|
+
* are batched and delivered at most once per animation frame, keeping
|
|
11377
|
+
* outgoing presence packets small. Listeners must not throw; a throwing
|
|
11378
|
+
* listener is isolated so it cannot stall the fade loop.
|
|
11379
|
+
*/
|
|
11380
|
+
onTrail(listener) {
|
|
11381
|
+
this.trailListeners.add(listener);
|
|
11382
|
+
return () => this.trailListeners.delete(listener);
|
|
11383
|
+
}
|
|
11151
11384
|
setOptions(options) {
|
|
11152
11385
|
if (options.color !== void 0) this.color = options.color;
|
|
11153
11386
|
if (options.width !== void 0) this.width = options.width;
|
|
@@ -11156,14 +11389,18 @@ var LaserTool = class {
|
|
|
11156
11389
|
}
|
|
11157
11390
|
onPointerDown(state, ctx) {
|
|
11158
11391
|
this.drawing = true;
|
|
11159
|
-
|
|
11160
|
-
this.trail.push({ x: world.x, y: world.y, t: this.now() });
|
|
11161
|
-
this.ensureAnimating(ctx);
|
|
11392
|
+
this.recordPoint(state, ctx);
|
|
11162
11393
|
}
|
|
11163
11394
|
onPointerMove(state, ctx) {
|
|
11164
11395
|
if (!this.drawing) return;
|
|
11396
|
+
this.recordPoint(state, ctx);
|
|
11397
|
+
}
|
|
11398
|
+
recordPoint(state, ctx) {
|
|
11165
11399
|
const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });
|
|
11166
11400
|
this.trail.push({ x: world.x, y: world.y, t: this.now() });
|
|
11401
|
+
if (this.trailListeners.size > 0) {
|
|
11402
|
+
this.pendingEmission.push({ x: world.x, y: world.y });
|
|
11403
|
+
}
|
|
11167
11404
|
this.ensureAnimating(ctx);
|
|
11168
11405
|
}
|
|
11169
11406
|
onPointerUp(_state, _ctx) {
|
|
@@ -11195,7 +11432,24 @@ var LaserTool = class {
|
|
|
11195
11432
|
this.rafId = requestAnimationFrame(() => this.tick(ctx));
|
|
11196
11433
|
}
|
|
11197
11434
|
}
|
|
11435
|
+
flushEmission() {
|
|
11436
|
+
if (this.pendingEmission.length === 0) return;
|
|
11437
|
+
const emission = {
|
|
11438
|
+
points: this.pendingEmission,
|
|
11439
|
+
color: this.color,
|
|
11440
|
+
width: this.width,
|
|
11441
|
+
fadeMs: this.fadeMs
|
|
11442
|
+
};
|
|
11443
|
+
this.pendingEmission = [];
|
|
11444
|
+
for (const listener of this.trailListeners) {
|
|
11445
|
+
try {
|
|
11446
|
+
listener(emission);
|
|
11447
|
+
} catch {
|
|
11448
|
+
}
|
|
11449
|
+
}
|
|
11450
|
+
}
|
|
11198
11451
|
tick(ctx) {
|
|
11452
|
+
this.flushEmission();
|
|
11199
11453
|
const cutoff = this.now() - this.fadeMs;
|
|
11200
11454
|
this.trail = this.trail.filter((p) => p.t >= cutoff);
|
|
11201
11455
|
if (this.trail.length > 0) {
|
|
@@ -11212,7 +11466,7 @@ var LaserTool = class {
|
|
|
11212
11466
|
};
|
|
11213
11467
|
|
|
11214
11468
|
// src/index.ts
|
|
11215
|
-
var VERSION = "0.
|
|
11469
|
+
var VERSION = "0.54.0";
|
|
11216
11470
|
// Annotate the CommonJS export names for ESM import in node:
|
|
11217
11471
|
0 && (module.exports = {
|
|
11218
11472
|
ArrowTool,
|
|
@@ -11225,6 +11479,7 @@ var VERSION = "0.52.2";
|
|
|
11225
11479
|
HistoryStack,
|
|
11226
11480
|
ImageTool,
|
|
11227
11481
|
IndexedDBAdapter,
|
|
11482
|
+
LASER_TRAIL_PRESENCE_KIND,
|
|
11228
11483
|
LaserTool,
|
|
11229
11484
|
LayerManager,
|
|
11230
11485
|
LocalStorageAdapter,
|
|
@@ -11232,6 +11487,7 @@ var VERSION = "0.52.2";
|
|
|
11232
11487
|
MemoryAdapter,
|
|
11233
11488
|
NoteTool,
|
|
11234
11489
|
PencilTool,
|
|
11490
|
+
RemoteLaserOverlay,
|
|
11235
11491
|
SelectTool,
|
|
11236
11492
|
ShapeTool,
|
|
11237
11493
|
TemplateTool,
|
|
@@ -11267,12 +11523,14 @@ var VERSION = "0.52.2";
|
|
|
11267
11523
|
getHexCellsInRectangle,
|
|
11268
11524
|
getHexCellsInSquare,
|
|
11269
11525
|
getHexDistance,
|
|
11526
|
+
isLaserTrailPresence,
|
|
11270
11527
|
isNearBezier,
|
|
11271
11528
|
setFontSize,
|
|
11272
11529
|
smartSnap,
|
|
11273
11530
|
snapPoint,
|
|
11274
11531
|
snapToHexCenter,
|
|
11275
11532
|
styleToPatch,
|
|
11533
|
+
toLaserTrailPresence,
|
|
11276
11534
|
toggleBold,
|
|
11277
11535
|
toggleItalic,
|
|
11278
11536
|
toggleStrikethrough,
|