@fieldnotes/core 0.55.0 → 0.56.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 +200 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +116 -2
- package/dist/index.d.ts +116 -2
- package/dist/index.js +199 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -39,6 +39,7 @@ __export(index_exports, {
|
|
|
39
39
|
NoteTool: () => NoteTool,
|
|
40
40
|
PING_PRESENCE_KIND: () => PING_PRESENCE_KIND,
|
|
41
41
|
PencilTool: () => PencilTool,
|
|
42
|
+
PingInput: () => PingInput,
|
|
42
43
|
PingTool: () => PingTool,
|
|
43
44
|
RemoteLaserOverlay: () => RemoteLaserOverlay,
|
|
44
45
|
RemotePingOverlay: () => RemotePingOverlay,
|
|
@@ -8941,6 +8942,191 @@ var RemotePingOverlay = class {
|
|
|
8941
8942
|
}
|
|
8942
8943
|
};
|
|
8943
8944
|
|
|
8945
|
+
// src/canvas/ping-input.ts
|
|
8946
|
+
var DEFAULT_LONG_PRESS_MS = 600;
|
|
8947
|
+
var DEFAULT_SLOP_PX = 8;
|
|
8948
|
+
var DEFAULT_COLOR3 = "#ff3b30";
|
|
8949
|
+
var DEFAULT_DURATION_MS2 = 1800;
|
|
8950
|
+
var DEFAULT_RADIUS2 = 48;
|
|
8951
|
+
var DEFAULT_MIN_INTERVAL_MS = 300;
|
|
8952
|
+
var PingInput = class {
|
|
8953
|
+
element;
|
|
8954
|
+
host;
|
|
8955
|
+
longPressEnabled;
|
|
8956
|
+
longPressMs;
|
|
8957
|
+
slopPx;
|
|
8958
|
+
color;
|
|
8959
|
+
durationMs;
|
|
8960
|
+
radius;
|
|
8961
|
+
minIntervalMs;
|
|
8962
|
+
shouldPing;
|
|
8963
|
+
press = null;
|
|
8964
|
+
downPointers = /* @__PURE__ */ new Set();
|
|
8965
|
+
lastPointerScreen = null;
|
|
8966
|
+
lastEmitAt = -Infinity;
|
|
8967
|
+
disposed = false;
|
|
8968
|
+
optionListeners = /* @__PURE__ */ new Set();
|
|
8969
|
+
pingListeners = /* @__PURE__ */ new Set();
|
|
8970
|
+
handlePointerDown = (e) => this.onPointerDown(e);
|
|
8971
|
+
handlePointerMove = (e) => this.onPointerMove(e);
|
|
8972
|
+
handlePointerUp = (e) => this.onPointerEnd(e);
|
|
8973
|
+
handlePointerCancel = (e) => this.onPointerEnd(e);
|
|
8974
|
+
handlePointerLeave = (e) => this.onPointerEnd(e);
|
|
8975
|
+
constructor(element, host, options = {}) {
|
|
8976
|
+
this.element = element;
|
|
8977
|
+
this.host = host;
|
|
8978
|
+
this.longPressEnabled = options.longPressEnabled ?? false;
|
|
8979
|
+
this.longPressMs = options.longPressMs ?? DEFAULT_LONG_PRESS_MS;
|
|
8980
|
+
this.slopPx = options.slopPx ?? DEFAULT_SLOP_PX;
|
|
8981
|
+
this.color = options.color ?? DEFAULT_COLOR3;
|
|
8982
|
+
this.durationMs = options.durationMs ?? DEFAULT_DURATION_MS2;
|
|
8983
|
+
this.radius = options.radius ?? DEFAULT_RADIUS2;
|
|
8984
|
+
this.minIntervalMs = options.minIntervalMs ?? DEFAULT_MIN_INTERVAL_MS;
|
|
8985
|
+
this.shouldPing = options.shouldPing;
|
|
8986
|
+
const opts = { passive: true };
|
|
8987
|
+
element.addEventListener("pointerdown", this.handlePointerDown, opts);
|
|
8988
|
+
element.addEventListener("pointermove", this.handlePointerMove, opts);
|
|
8989
|
+
element.addEventListener("pointerup", this.handlePointerUp, opts);
|
|
8990
|
+
element.addEventListener("pointercancel", this.handlePointerCancel, opts);
|
|
8991
|
+
element.addEventListener("pointerleave", this.handlePointerLeave, opts);
|
|
8992
|
+
}
|
|
8993
|
+
now() {
|
|
8994
|
+
return performance.now();
|
|
8995
|
+
}
|
|
8996
|
+
getOptions() {
|
|
8997
|
+
return {
|
|
8998
|
+
longPressEnabled: this.longPressEnabled,
|
|
8999
|
+
longPressMs: this.longPressMs,
|
|
9000
|
+
slopPx: this.slopPx,
|
|
9001
|
+
color: this.color,
|
|
9002
|
+
durationMs: this.durationMs,
|
|
9003
|
+
radius: this.radius,
|
|
9004
|
+
minIntervalMs: this.minIntervalMs,
|
|
9005
|
+
...this.shouldPing ? { shouldPing: this.shouldPing } : {}
|
|
9006
|
+
};
|
|
9007
|
+
}
|
|
9008
|
+
setOptions(options) {
|
|
9009
|
+
if (options.longPressEnabled !== void 0) {
|
|
9010
|
+
this.longPressEnabled = options.longPressEnabled;
|
|
9011
|
+
if (!this.longPressEnabled) this.cancelPress();
|
|
9012
|
+
}
|
|
9013
|
+
if (options.longPressMs !== void 0) this.longPressMs = options.longPressMs;
|
|
9014
|
+
if (options.slopPx !== void 0) this.slopPx = options.slopPx;
|
|
9015
|
+
if (options.color !== void 0) this.color = options.color;
|
|
9016
|
+
if (options.durationMs !== void 0) this.durationMs = options.durationMs;
|
|
9017
|
+
if (options.radius !== void 0) this.radius = options.radius;
|
|
9018
|
+
if (options.minIntervalMs !== void 0) this.minIntervalMs = options.minIntervalMs;
|
|
9019
|
+
if (options.shouldPing !== void 0) this.shouldPing = options.shouldPing;
|
|
9020
|
+
for (const listener of this.optionListeners) listener();
|
|
9021
|
+
}
|
|
9022
|
+
onOptionsChange(listener) {
|
|
9023
|
+
this.optionListeners.add(listener);
|
|
9024
|
+
return () => this.optionListeners.delete(listener);
|
|
9025
|
+
}
|
|
9026
|
+
/**
|
|
9027
|
+
* Subscribes to emitted pings. Listeners must not throw; a throwing
|
|
9028
|
+
* listener is isolated so it cannot break input handling or other
|
|
9029
|
+
* listeners.
|
|
9030
|
+
*/
|
|
9031
|
+
onPing(listener) {
|
|
9032
|
+
this.pingListeners.add(listener);
|
|
9033
|
+
return () => this.pingListeners.delete(listener);
|
|
9034
|
+
}
|
|
9035
|
+
/**
|
|
9036
|
+
* Pings at the last tracked pointer position (hover moves and presses),
|
|
9037
|
+
* world-converted at call time. Returns `false` when no pointer has been
|
|
9038
|
+
* seen yet, the host vetoes, or the rate limit drops the ping.
|
|
9039
|
+
*/
|
|
9040
|
+
pingAtPointer() {
|
|
9041
|
+
if (this.disposed || this.lastPointerScreen === null) return false;
|
|
9042
|
+
return this.emit(this.host.screenToWorld(this.lastPointerScreen));
|
|
9043
|
+
}
|
|
9044
|
+
/** Pings a world position directly. Same veto and rate limit as every path. */
|
|
9045
|
+
pingAt(world) {
|
|
9046
|
+
if (this.disposed) return false;
|
|
9047
|
+
return this.emit(world);
|
|
9048
|
+
}
|
|
9049
|
+
/** Removes all DOM listeners and cancels any pending press. Idempotent. */
|
|
9050
|
+
dispose() {
|
|
9051
|
+
if (this.disposed) return;
|
|
9052
|
+
this.disposed = true;
|
|
9053
|
+
this.cancelPress();
|
|
9054
|
+
this.downPointers.clear();
|
|
9055
|
+
this.element.removeEventListener("pointerdown", this.handlePointerDown);
|
|
9056
|
+
this.element.removeEventListener("pointermove", this.handlePointerMove);
|
|
9057
|
+
this.element.removeEventListener("pointerup", this.handlePointerUp);
|
|
9058
|
+
this.element.removeEventListener("pointercancel", this.handlePointerCancel);
|
|
9059
|
+
this.element.removeEventListener("pointerleave", this.handlePointerLeave);
|
|
9060
|
+
this.optionListeners.clear();
|
|
9061
|
+
this.pingListeners.clear();
|
|
9062
|
+
}
|
|
9063
|
+
toLocal(e) {
|
|
9064
|
+
const rect = this.element.getBoundingClientRect();
|
|
9065
|
+
return { x: e.clientX - rect.left, y: e.clientY - rect.top };
|
|
9066
|
+
}
|
|
9067
|
+
onPointerDown(e) {
|
|
9068
|
+
const local = this.toLocal(e);
|
|
9069
|
+
this.lastPointerScreen = local;
|
|
9070
|
+
const hadPointers = this.downPointers.size > 0;
|
|
9071
|
+
this.downPointers.add(e.pointerId);
|
|
9072
|
+
if (hadPointers) {
|
|
9073
|
+
this.cancelPress();
|
|
9074
|
+
return;
|
|
9075
|
+
}
|
|
9076
|
+
if (!this.longPressEnabled) return;
|
|
9077
|
+
if (e.pointerType === "mouse" && e.button !== 0) return;
|
|
9078
|
+
this.press = {
|
|
9079
|
+
pointerId: e.pointerId,
|
|
9080
|
+
x: local.x,
|
|
9081
|
+
y: local.y,
|
|
9082
|
+
timer: setTimeout(() => this.firePress(), this.longPressMs)
|
|
9083
|
+
};
|
|
9084
|
+
}
|
|
9085
|
+
onPointerMove(e) {
|
|
9086
|
+
const local = this.toLocal(e);
|
|
9087
|
+
this.lastPointerScreen = local;
|
|
9088
|
+
if (this.press === null || e.pointerId !== this.press.pointerId) return;
|
|
9089
|
+
const dx = local.x - this.press.x;
|
|
9090
|
+
const dy = local.y - this.press.y;
|
|
9091
|
+
if (Math.hypot(dx, dy) > this.slopPx) this.cancelPress();
|
|
9092
|
+
}
|
|
9093
|
+
onPointerEnd(e) {
|
|
9094
|
+
this.downPointers.delete(e.pointerId);
|
|
9095
|
+
if (this.press !== null && e.pointerId === this.press.pointerId) this.cancelPress();
|
|
9096
|
+
}
|
|
9097
|
+
cancelPress() {
|
|
9098
|
+
if (this.press === null) return;
|
|
9099
|
+
clearTimeout(this.press.timer);
|
|
9100
|
+
this.press = null;
|
|
9101
|
+
}
|
|
9102
|
+
firePress() {
|
|
9103
|
+
if (this.press === null) return;
|
|
9104
|
+
const screen = { x: this.press.x, y: this.press.y };
|
|
9105
|
+
this.press = null;
|
|
9106
|
+
this.emit(this.host.screenToWorld(screen));
|
|
9107
|
+
}
|
|
9108
|
+
emit(world) {
|
|
9109
|
+
if (this.shouldPing && !this.shouldPing()) return false;
|
|
9110
|
+
const t = this.now();
|
|
9111
|
+
if (t - this.lastEmitAt < this.minIntervalMs) return false;
|
|
9112
|
+
this.lastEmitAt = t;
|
|
9113
|
+
const emission = {
|
|
9114
|
+
x: world.x,
|
|
9115
|
+
y: world.y,
|
|
9116
|
+
color: this.color,
|
|
9117
|
+
durationMs: this.durationMs,
|
|
9118
|
+
radius: this.radius
|
|
9119
|
+
};
|
|
9120
|
+
for (const listener of this.pingListeners) {
|
|
9121
|
+
try {
|
|
9122
|
+
listener(emission);
|
|
9123
|
+
} catch {
|
|
9124
|
+
}
|
|
9125
|
+
}
|
|
9126
|
+
return true;
|
|
9127
|
+
}
|
|
9128
|
+
};
|
|
9129
|
+
|
|
8944
9130
|
// src/tools/hand-tool.ts
|
|
8945
9131
|
var HandTool = class {
|
|
8946
9132
|
name = "hand";
|
|
@@ -9202,7 +9388,7 @@ function erasePoints(points, eraser, radius) {
|
|
|
9202
9388
|
}
|
|
9203
9389
|
|
|
9204
9390
|
// src/tools/eraser-tool.ts
|
|
9205
|
-
var
|
|
9391
|
+
var DEFAULT_RADIUS3 = 20;
|
|
9206
9392
|
function makeEraserCursor(radius) {
|
|
9207
9393
|
const size = radius * 2;
|
|
9208
9394
|
const svg = `<svg xmlns='http://www.w3.org/2000/svg' width='${size}' height='${size}'><circle cx='${radius}' cy='${radius}' r='${radius - 1}' fill='none' stroke='%23666' stroke-width='1.5'/></svg>`;
|
|
@@ -9215,7 +9401,7 @@ var EraserTool = class {
|
|
|
9215
9401
|
cursor;
|
|
9216
9402
|
mode;
|
|
9217
9403
|
constructor(options = {}) {
|
|
9218
|
-
this.radius = options.radius ??
|
|
9404
|
+
this.radius = options.radius ?? DEFAULT_RADIUS3;
|
|
9219
9405
|
this.cursor = makeEraserCursor(this.radius);
|
|
9220
9406
|
this.mode = options.mode ?? "partial";
|
|
9221
9407
|
}
|
|
@@ -11497,7 +11683,7 @@ var TemplateTool = class {
|
|
|
11497
11683
|
};
|
|
11498
11684
|
|
|
11499
11685
|
// src/tools/laser-tool.ts
|
|
11500
|
-
var
|
|
11686
|
+
var DEFAULT_COLOR4 = "#ff3b30";
|
|
11501
11687
|
var DEFAULT_WIDTH2 = 4;
|
|
11502
11688
|
var DEFAULT_FADE_MS2 = 1200;
|
|
11503
11689
|
var LaserTool = class {
|
|
@@ -11513,7 +11699,7 @@ var LaserTool = class {
|
|
|
11513
11699
|
pendingEmission = [];
|
|
11514
11700
|
constructor(options = {}) {
|
|
11515
11701
|
this.name = options.name ?? "laser";
|
|
11516
|
-
this.color = options.color ??
|
|
11702
|
+
this.color = options.color ?? DEFAULT_COLOR4;
|
|
11517
11703
|
this.width = options.width ?? DEFAULT_WIDTH2;
|
|
11518
11704
|
this.fadeMs = options.fadeMs ?? DEFAULT_FADE_MS2;
|
|
11519
11705
|
}
|
|
@@ -11641,10 +11827,10 @@ var LaserTool = class {
|
|
|
11641
11827
|
};
|
|
11642
11828
|
|
|
11643
11829
|
// src/tools/ping-tool.ts
|
|
11644
|
-
var
|
|
11645
|
-
var
|
|
11646
|
-
var
|
|
11647
|
-
var
|
|
11830
|
+
var DEFAULT_COLOR5 = "#ff3b30";
|
|
11831
|
+
var DEFAULT_DURATION_MS3 = 1800;
|
|
11832
|
+
var DEFAULT_RADIUS4 = 48;
|
|
11833
|
+
var DEFAULT_MIN_INTERVAL_MS2 = 300;
|
|
11648
11834
|
var PingTool = class {
|
|
11649
11835
|
name;
|
|
11650
11836
|
color;
|
|
@@ -11658,10 +11844,10 @@ var PingTool = class {
|
|
|
11658
11844
|
pingListeners = /* @__PURE__ */ new Set();
|
|
11659
11845
|
constructor(options = {}) {
|
|
11660
11846
|
this.name = options.name ?? "ping";
|
|
11661
|
-
this.color = options.color ??
|
|
11662
|
-
this.durationMs = options.durationMs ??
|
|
11663
|
-
this.radius = options.radius ??
|
|
11664
|
-
this.minIntervalMs = options.minIntervalMs ??
|
|
11847
|
+
this.color = options.color ?? DEFAULT_COLOR5;
|
|
11848
|
+
this.durationMs = options.durationMs ?? DEFAULT_DURATION_MS3;
|
|
11849
|
+
this.radius = options.radius ?? DEFAULT_RADIUS4;
|
|
11850
|
+
this.minIntervalMs = options.minIntervalMs ?? DEFAULT_MIN_INTERVAL_MS2;
|
|
11665
11851
|
}
|
|
11666
11852
|
now() {
|
|
11667
11853
|
return performance.now();
|
|
@@ -11761,7 +11947,7 @@ var PingTool = class {
|
|
|
11761
11947
|
};
|
|
11762
11948
|
|
|
11763
11949
|
// src/index.ts
|
|
11764
|
-
var VERSION = "0.
|
|
11950
|
+
var VERSION = "0.56.0";
|
|
11765
11951
|
// Annotate the CommonJS export names for ESM import in node:
|
|
11766
11952
|
0 && (module.exports = {
|
|
11767
11953
|
ArrowTool,
|
|
@@ -11783,6 +11969,7 @@ var VERSION = "0.55.0";
|
|
|
11783
11969
|
NoteTool,
|
|
11784
11970
|
PING_PRESENCE_KIND,
|
|
11785
11971
|
PencilTool,
|
|
11972
|
+
PingInput,
|
|
11786
11973
|
PingTool,
|
|
11787
11974
|
RemoteLaserOverlay,
|
|
11788
11975
|
RemotePingOverlay,
|