@fieldnotes/core 0.23.0 → 0.25.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 +6 -0
- package/dist/index.cjs +509 -606
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -369
- package/dist/index.d.ts +39 -369
- package/dist/index.js +508 -574
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -20,50 +20,30 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
AddElementCommand: () => AddElementCommand,
|
|
24
23
|
ArrowTool: () => ArrowTool,
|
|
25
24
|
AutoSave: () => AutoSave,
|
|
26
|
-
Background: () => Background,
|
|
27
|
-
BatchCommand: () => BatchCommand,
|
|
28
25
|
Camera: () => Camera,
|
|
29
|
-
CreateLayerCommand: () => CreateLayerCommand,
|
|
30
|
-
DEFAULT_FONT_SIZE_PRESETS: () => DEFAULT_FONT_SIZE_PRESETS,
|
|
31
26
|
DEFAULT_NOTE_FONT_SIZE: () => DEFAULT_NOTE_FONT_SIZE,
|
|
32
|
-
DoubleTapDetector: () => DoubleTapDetector,
|
|
33
|
-
ElementRenderer: () => ElementRenderer,
|
|
34
27
|
ElementStore: () => ElementStore,
|
|
35
28
|
EraserTool: () => EraserTool,
|
|
36
|
-
EventBus: () => EventBus,
|
|
37
29
|
HandTool: () => HandTool,
|
|
38
|
-
HistoryRecorder: () => HistoryRecorder,
|
|
39
30
|
HistoryStack: () => HistoryStack,
|
|
40
31
|
ImageTool: () => ImageTool,
|
|
41
|
-
InputFilter: () => InputFilter,
|
|
42
|
-
InputHandler: () => InputHandler,
|
|
43
32
|
LayerManager: () => LayerManager,
|
|
44
33
|
MeasureTool: () => MeasureTool,
|
|
45
|
-
NoteEditor: () => NoteEditor,
|
|
46
34
|
NoteTool: () => NoteTool,
|
|
47
|
-
NoteToolbar: () => NoteToolbar,
|
|
48
35
|
PencilTool: () => PencilTool,
|
|
49
|
-
Quadtree: () => Quadtree,
|
|
50
|
-
RemoveElementCommand: () => RemoveElementCommand,
|
|
51
|
-
RemoveLayerCommand: () => RemoveLayerCommand,
|
|
52
36
|
SelectTool: () => SelectTool,
|
|
53
37
|
ShapeTool: () => ShapeTool,
|
|
54
38
|
TemplateTool: () => TemplateTool,
|
|
55
39
|
TextTool: () => TextTool,
|
|
56
40
|
ToolManager: () => ToolManager,
|
|
57
|
-
UpdateElementCommand: () => UpdateElementCommand,
|
|
58
|
-
UpdateLayerCommand: () => UpdateLayerCommand,
|
|
59
41
|
VERSION: () => VERSION,
|
|
60
42
|
Viewport: () => Viewport,
|
|
61
43
|
boundsIntersect: () => boundsIntersect,
|
|
62
|
-
clearStaleBindings: () => clearStaleBindings,
|
|
63
44
|
createArrow: () => createArrow,
|
|
64
45
|
createGrid: () => createGrid,
|
|
65
46
|
createHtmlElement: () => createHtmlElement,
|
|
66
|
-
createId: () => createId,
|
|
67
47
|
createImage: () => createImage,
|
|
68
48
|
createNote: () => createNote,
|
|
69
49
|
createShape: () => createShape,
|
|
@@ -72,29 +52,20 @@ __export(index_exports, {
|
|
|
72
52
|
createText: () => createText,
|
|
73
53
|
drawHexPath: () => drawHexPath,
|
|
74
54
|
exportImage: () => exportImage,
|
|
75
|
-
exportState: () => exportState,
|
|
76
|
-
findBindTarget: () => findBindTarget,
|
|
77
|
-
findBoundArrows: () => findBoundArrows,
|
|
78
55
|
getActiveFormats: () => getActiveFormats,
|
|
79
56
|
getArrowBounds: () => getArrowBounds,
|
|
80
57
|
getArrowControlPoint: () => getArrowControlPoint,
|
|
81
58
|
getArrowMidpoint: () => getArrowMidpoint,
|
|
82
59
|
getArrowTangentAngle: () => getArrowTangentAngle,
|
|
83
60
|
getBendFromPoint: () => getBendFromPoint,
|
|
84
|
-
getEdgeIntersection: () => getEdgeIntersection,
|
|
85
61
|
getElementBounds: () => getElementBounds,
|
|
86
|
-
getElementCenter: () => getElementCenter,
|
|
87
62
|
getElementsBoundingBox: () => getElementsBoundingBox,
|
|
88
63
|
getHexCellsInCone: () => getHexCellsInCone,
|
|
89
64
|
getHexCellsInLine: () => getHexCellsInLine,
|
|
90
65
|
getHexCellsInRadius: () => getHexCellsInRadius,
|
|
91
66
|
getHexCellsInSquare: () => getHexCellsInSquare,
|
|
92
67
|
getHexDistance: () => getHexDistance,
|
|
93
|
-
isBindable: () => isBindable,
|
|
94
68
|
isNearBezier: () => isNearBezier,
|
|
95
|
-
isNoteContentEmpty: () => isNoteContentEmpty,
|
|
96
|
-
parseState: () => parseState,
|
|
97
|
-
sanitizeNoteHtml: () => sanitizeNoteHtml,
|
|
98
69
|
setFontSize: () => setFontSize,
|
|
99
70
|
smartSnap: () => smartSnap,
|
|
100
71
|
snapPoint: () => snapPoint,
|
|
@@ -102,188 +73,41 @@ __export(index_exports, {
|
|
|
102
73
|
toggleBold: () => toggleBold,
|
|
103
74
|
toggleItalic: () => toggleItalic,
|
|
104
75
|
toggleStrikethrough: () => toggleStrikethrough,
|
|
105
|
-
toggleUnderline: () => toggleUnderline
|
|
106
|
-
unbindArrow: () => unbindArrow,
|
|
107
|
-
updateBoundArrow: () => updateBoundArrow
|
|
76
|
+
toggleUnderline: () => toggleUnderline
|
|
108
77
|
});
|
|
109
78
|
module.exports = __toCommonJS(index_exports);
|
|
110
79
|
|
|
111
|
-
// src/core/
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
existing.add(listener);
|
|
118
|
-
} else {
|
|
119
|
-
const set = /* @__PURE__ */ new Set([listener]);
|
|
120
|
-
this.listeners.set(event, set);
|
|
121
|
-
}
|
|
122
|
-
return () => this.off(event, listener);
|
|
123
|
-
}
|
|
124
|
-
off(event, listener) {
|
|
125
|
-
this.listeners.get(event)?.delete(listener);
|
|
126
|
-
}
|
|
127
|
-
emit(event, data) {
|
|
128
|
-
this.listeners.get(event)?.forEach((listener) => {
|
|
129
|
-
try {
|
|
130
|
-
listener(data);
|
|
131
|
-
} catch (err) {
|
|
132
|
-
console.error(`[fieldnotes] listener error for "${String(event)}"`, err);
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
clear() {
|
|
137
|
-
this.listeners.clear();
|
|
138
|
-
}
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
// src/core/quadtree.ts
|
|
142
|
-
var MAX_ITEMS = 8;
|
|
143
|
-
var MAX_DEPTH = 8;
|
|
144
|
-
function intersects(a, b) {
|
|
145
|
-
return a.x <= b.x + b.w && a.x + a.w >= b.x && a.y <= b.y + b.h && a.y + a.h >= b.y;
|
|
80
|
+
// src/core/snap.ts
|
|
81
|
+
function snapPoint(point, gridSize) {
|
|
82
|
+
return {
|
|
83
|
+
x: Math.round(point.x / gridSize) * gridSize || 0,
|
|
84
|
+
y: Math.round(point.y / gridSize) * gridSize || 0
|
|
85
|
+
};
|
|
146
86
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
this.items.push(entry);
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
this.items.push(entry);
|
|
166
|
-
if (this.items.length > MAX_ITEMS && this.depth < MAX_DEPTH) {
|
|
167
|
-
this.split();
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
remove(id) {
|
|
171
|
-
const idx = this.items.findIndex((e) => e.id === id);
|
|
172
|
-
if (idx !== -1) {
|
|
173
|
-
this.items.splice(idx, 1);
|
|
174
|
-
return true;
|
|
175
|
-
}
|
|
176
|
-
if (this.children) {
|
|
177
|
-
for (const child of this.children) {
|
|
178
|
-
if (child.remove(id)) {
|
|
179
|
-
this.collapseIfEmpty();
|
|
180
|
-
return true;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
return false;
|
|
185
|
-
}
|
|
186
|
-
query(rect, result) {
|
|
187
|
-
if (!intersects(this.bounds, rect)) return;
|
|
188
|
-
for (const item of this.items) {
|
|
189
|
-
if (intersects(item.bounds, rect)) {
|
|
190
|
-
result.push(item.id);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
if (this.children) {
|
|
194
|
-
for (const child of this.children) {
|
|
195
|
-
child.query(rect, result);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
getChildIndex(itemBounds) {
|
|
200
|
-
const midX = this.bounds.x + this.bounds.w / 2;
|
|
201
|
-
const midY = this.bounds.y + this.bounds.h / 2;
|
|
202
|
-
const left = itemBounds.x >= this.bounds.x && itemBounds.x + itemBounds.w <= midX;
|
|
203
|
-
const right = itemBounds.x >= midX && itemBounds.x + itemBounds.w <= this.bounds.x + this.bounds.w;
|
|
204
|
-
const top = itemBounds.y >= this.bounds.y && itemBounds.y + itemBounds.h <= midY;
|
|
205
|
-
const bottom = itemBounds.y >= midY && itemBounds.y + itemBounds.h <= this.bounds.y + this.bounds.h;
|
|
206
|
-
if (left && top) return 0;
|
|
207
|
-
if (right && top) return 1;
|
|
208
|
-
if (left && bottom) return 2;
|
|
209
|
-
if (right && bottom) return 3;
|
|
210
|
-
return -1;
|
|
211
|
-
}
|
|
212
|
-
split() {
|
|
213
|
-
const { x, y, w, h } = this.bounds;
|
|
214
|
-
const halfW = w / 2;
|
|
215
|
-
const halfH = h / 2;
|
|
216
|
-
const d = this.depth + 1;
|
|
217
|
-
this.children = [
|
|
218
|
-
new _QuadNode({ x, y, w: halfW, h: halfH }, d),
|
|
219
|
-
new _QuadNode({ x: x + halfW, y, w: halfW, h: halfH }, d),
|
|
220
|
-
new _QuadNode({ x, y: y + halfH, w: halfW, h: halfH }, d),
|
|
221
|
-
new _QuadNode({ x: x + halfW, y: y + halfH, w: halfW, h: halfH }, d)
|
|
222
|
-
];
|
|
223
|
-
const remaining = [];
|
|
224
|
-
for (const item of this.items) {
|
|
225
|
-
const idx = this.getChildIndex(item.bounds);
|
|
226
|
-
if (idx !== -1) {
|
|
227
|
-
const target = this.children[idx];
|
|
228
|
-
if (target) target.insert(item);
|
|
229
|
-
} else {
|
|
230
|
-
remaining.push(item);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
this.items = remaining;
|
|
234
|
-
}
|
|
235
|
-
collapseIfEmpty() {
|
|
236
|
-
if (!this.children) return;
|
|
237
|
-
let totalItems = this.items.length;
|
|
238
|
-
for (const child of this.children) {
|
|
239
|
-
if (child.children) return;
|
|
240
|
-
totalItems += child.items.length;
|
|
241
|
-
}
|
|
242
|
-
if (totalItems <= MAX_ITEMS) {
|
|
243
|
-
for (const child of this.children) {
|
|
244
|
-
this.items.push(...child.items);
|
|
245
|
-
}
|
|
246
|
-
this.children = null;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
};
|
|
250
|
-
var Quadtree = class {
|
|
251
|
-
root;
|
|
252
|
-
_size = 0;
|
|
253
|
-
worldBounds;
|
|
254
|
-
constructor(worldBounds) {
|
|
255
|
-
this.worldBounds = worldBounds;
|
|
256
|
-
this.root = new QuadNode(worldBounds, 0);
|
|
257
|
-
}
|
|
258
|
-
get size() {
|
|
259
|
-
return this._size;
|
|
260
|
-
}
|
|
261
|
-
insert(id, bounds) {
|
|
262
|
-
this.root.insert({ id, bounds });
|
|
263
|
-
this._size++;
|
|
264
|
-
}
|
|
265
|
-
remove(id) {
|
|
266
|
-
if (this.root.remove(id)) {
|
|
267
|
-
this._size--;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
update(id, newBounds) {
|
|
271
|
-
this.remove(id);
|
|
272
|
-
this.insert(id, newBounds);
|
|
273
|
-
}
|
|
274
|
-
query(rect) {
|
|
275
|
-
const result = [];
|
|
276
|
-
this.root.query(rect, result);
|
|
277
|
-
return result;
|
|
278
|
-
}
|
|
279
|
-
queryPoint(point) {
|
|
280
|
-
return this.query({ x: point.x, y: point.y, w: 0, h: 0 });
|
|
87
|
+
function snapToHexCenter(point, cellSize, orientation) {
|
|
88
|
+
if (orientation === "pointy") {
|
|
89
|
+
const hexW = Math.sqrt(3) * cellSize;
|
|
90
|
+
const rowH = 1.5 * cellSize;
|
|
91
|
+
const row = Math.round(point.y / rowH);
|
|
92
|
+
const offsetX = row % 2 !== 0 ? hexW / 2 : 0;
|
|
93
|
+
const col = Math.round((point.x - offsetX) / hexW);
|
|
94
|
+
return { x: col * hexW + offsetX || 0, y: row * rowH || 0 };
|
|
95
|
+
} else {
|
|
96
|
+
const hexH = Math.sqrt(3) * cellSize;
|
|
97
|
+
const colW = 1.5 * cellSize;
|
|
98
|
+
const col = Math.round(point.x / colW);
|
|
99
|
+
const offsetY = col % 2 !== 0 ? hexH / 2 : 0;
|
|
100
|
+
const row = Math.round((point.y - offsetY) / hexH);
|
|
101
|
+
return { x: col * colW || 0, y: row * hexH + offsetY || 0 };
|
|
281
102
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
103
|
+
}
|
|
104
|
+
function smartSnap(point, ctx) {
|
|
105
|
+
if (!ctx.snapToGrid || !ctx.gridSize) return point;
|
|
106
|
+
if (ctx.gridType === "hex" && ctx.hexOrientation) {
|
|
107
|
+
return snapToHexCenter(point, ctx.gridSize, ctx.hexOrientation);
|
|
285
108
|
}
|
|
286
|
-
|
|
109
|
+
return snapPoint(point, ctx.gridSize);
|
|
110
|
+
}
|
|
287
111
|
|
|
288
112
|
// src/elements/note-sanitizer.ts
|
|
289
113
|
var BOLD_TAGS = /* @__PURE__ */ new Set(["b", "strong"]);
|
|
@@ -540,38 +364,6 @@ function migrateElement(obj) {
|
|
|
540
364
|
}
|
|
541
365
|
}
|
|
542
366
|
|
|
543
|
-
// src/core/snap.ts
|
|
544
|
-
function snapPoint(point, gridSize) {
|
|
545
|
-
return {
|
|
546
|
-
x: Math.round(point.x / gridSize) * gridSize || 0,
|
|
547
|
-
y: Math.round(point.y / gridSize) * gridSize || 0
|
|
548
|
-
};
|
|
549
|
-
}
|
|
550
|
-
function snapToHexCenter(point, cellSize, orientation) {
|
|
551
|
-
if (orientation === "pointy") {
|
|
552
|
-
const hexW = Math.sqrt(3) * cellSize;
|
|
553
|
-
const rowH = 1.5 * cellSize;
|
|
554
|
-
const row = Math.round(point.y / rowH);
|
|
555
|
-
const offsetX = row % 2 !== 0 ? hexW / 2 : 0;
|
|
556
|
-
const col = Math.round((point.x - offsetX) / hexW);
|
|
557
|
-
return { x: col * hexW + offsetX || 0, y: row * rowH || 0 };
|
|
558
|
-
} else {
|
|
559
|
-
const hexH = Math.sqrt(3) * cellSize;
|
|
560
|
-
const colW = 1.5 * cellSize;
|
|
561
|
-
const col = Math.round(point.x / colW);
|
|
562
|
-
const offsetY = col % 2 !== 0 ? hexH / 2 : 0;
|
|
563
|
-
const row = Math.round((point.y - offsetY) / hexH);
|
|
564
|
-
return { x: col * colW || 0, y: row * hexH + offsetY || 0 };
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
function smartSnap(point, ctx) {
|
|
568
|
-
if (!ctx.snapToGrid || !ctx.gridSize) return point;
|
|
569
|
-
if (ctx.gridType === "hex" && ctx.hexOrientation) {
|
|
570
|
-
return snapToHexCenter(point, ctx.gridSize, ctx.hexOrientation);
|
|
571
|
-
}
|
|
572
|
-
return snapPoint(point, ctx.gridSize);
|
|
573
|
-
}
|
|
574
|
-
|
|
575
367
|
// src/core/auto-save.ts
|
|
576
368
|
var DEFAULT_KEY = "fieldnotes-autosave";
|
|
577
369
|
var DEFAULT_DEBOUNCE_MS = 1e3;
|
|
@@ -735,143 +527,6 @@ var Camera = class {
|
|
|
735
527
|
}
|
|
736
528
|
};
|
|
737
529
|
|
|
738
|
-
// src/canvas/background.ts
|
|
739
|
-
var MIN_PATTERN_SPACING = 16;
|
|
740
|
-
var DEFAULTS = {
|
|
741
|
-
pattern: "dots",
|
|
742
|
-
spacing: 24,
|
|
743
|
-
color: "#d0d0d0",
|
|
744
|
-
dotRadius: 1,
|
|
745
|
-
lineWidth: 0.5
|
|
746
|
-
};
|
|
747
|
-
var Background = class {
|
|
748
|
-
pattern;
|
|
749
|
-
spacing;
|
|
750
|
-
color;
|
|
751
|
-
dotRadius;
|
|
752
|
-
lineWidth;
|
|
753
|
-
cachedCanvas = null;
|
|
754
|
-
cachedCtx = null;
|
|
755
|
-
lastZoom = -1;
|
|
756
|
-
lastOffsetX = -Infinity;
|
|
757
|
-
lastOffsetY = -Infinity;
|
|
758
|
-
lastWidth = 0;
|
|
759
|
-
lastHeight = 0;
|
|
760
|
-
constructor(options = {}) {
|
|
761
|
-
this.pattern = options.pattern ?? DEFAULTS.pattern;
|
|
762
|
-
this.spacing = options.spacing ?? DEFAULTS.spacing;
|
|
763
|
-
this.color = options.color ?? DEFAULTS.color;
|
|
764
|
-
this.dotRadius = options.dotRadius ?? DEFAULTS.dotRadius;
|
|
765
|
-
this.lineWidth = options.lineWidth ?? DEFAULTS.lineWidth;
|
|
766
|
-
}
|
|
767
|
-
render(ctx, camera) {
|
|
768
|
-
const { width, height } = ctx.canvas;
|
|
769
|
-
const dpr = typeof devicePixelRatio !== "undefined" ? devicePixelRatio : 1;
|
|
770
|
-
const cssWidth = width / dpr;
|
|
771
|
-
const cssHeight = height / dpr;
|
|
772
|
-
ctx.save();
|
|
773
|
-
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
774
|
-
ctx.clearRect(0, 0, cssWidth, cssHeight);
|
|
775
|
-
if (this.pattern === "none") {
|
|
776
|
-
ctx.restore();
|
|
777
|
-
return;
|
|
778
|
-
}
|
|
779
|
-
const spacing = this.adaptSpacing(this.spacing, camera.zoom);
|
|
780
|
-
const keyZoom = camera.zoom;
|
|
781
|
-
const keyX = Math.floor(camera.position.x % spacing);
|
|
782
|
-
const keyY = Math.floor(camera.position.y % spacing);
|
|
783
|
-
if (this.cachedCanvas !== null && keyZoom === this.lastZoom && keyX === this.lastOffsetX && keyY === this.lastOffsetY && cssWidth === this.lastWidth && cssHeight === this.lastHeight) {
|
|
784
|
-
ctx.drawImage(this.cachedCanvas, 0, 0);
|
|
785
|
-
ctx.restore();
|
|
786
|
-
return;
|
|
787
|
-
}
|
|
788
|
-
this.ensureCachedCanvas(cssWidth, cssHeight, dpr);
|
|
789
|
-
if (this.cachedCtx === null) {
|
|
790
|
-
if (this.pattern === "dots") {
|
|
791
|
-
this.renderDots(ctx, camera, cssWidth, cssHeight);
|
|
792
|
-
} else if (this.pattern === "grid") {
|
|
793
|
-
this.renderGrid(ctx, camera, cssWidth, cssHeight);
|
|
794
|
-
}
|
|
795
|
-
ctx.restore();
|
|
796
|
-
return;
|
|
797
|
-
}
|
|
798
|
-
const offCtx = this.cachedCtx;
|
|
799
|
-
offCtx.clearRect(0, 0, cssWidth, cssHeight);
|
|
800
|
-
if (this.pattern === "dots") {
|
|
801
|
-
this.renderDots(offCtx, camera, cssWidth, cssHeight);
|
|
802
|
-
} else if (this.pattern === "grid") {
|
|
803
|
-
this.renderGrid(offCtx, camera, cssWidth, cssHeight);
|
|
804
|
-
}
|
|
805
|
-
this.lastZoom = keyZoom;
|
|
806
|
-
this.lastOffsetX = keyX;
|
|
807
|
-
this.lastOffsetY = keyY;
|
|
808
|
-
this.lastWidth = cssWidth;
|
|
809
|
-
this.lastHeight = cssHeight;
|
|
810
|
-
ctx.drawImage(this.cachedCanvas, 0, 0);
|
|
811
|
-
ctx.restore();
|
|
812
|
-
}
|
|
813
|
-
ensureCachedCanvas(cssWidth, cssHeight, dpr) {
|
|
814
|
-
if (this.cachedCanvas !== null && this.lastWidth === cssWidth && this.lastHeight === cssHeight) {
|
|
815
|
-
return;
|
|
816
|
-
}
|
|
817
|
-
const physWidth = Math.round(cssWidth * dpr);
|
|
818
|
-
const physHeight = Math.round(cssHeight * dpr);
|
|
819
|
-
if (typeof OffscreenCanvas !== "undefined") {
|
|
820
|
-
this.cachedCanvas = new OffscreenCanvas(physWidth, physHeight);
|
|
821
|
-
} else if (typeof document !== "undefined") {
|
|
822
|
-
const el = document.createElement("canvas");
|
|
823
|
-
el.width = physWidth;
|
|
824
|
-
el.height = physHeight;
|
|
825
|
-
this.cachedCanvas = el;
|
|
826
|
-
} else {
|
|
827
|
-
this.cachedCanvas = null;
|
|
828
|
-
this.cachedCtx = null;
|
|
829
|
-
return;
|
|
830
|
-
}
|
|
831
|
-
const offCtx = this.cachedCanvas.getContext("2d");
|
|
832
|
-
if (offCtx !== null) {
|
|
833
|
-
offCtx.scale(dpr, dpr);
|
|
834
|
-
}
|
|
835
|
-
this.cachedCtx = offCtx;
|
|
836
|
-
this.lastZoom = -1;
|
|
837
|
-
}
|
|
838
|
-
adaptSpacing(baseSpacing, zoom) {
|
|
839
|
-
let spacing = baseSpacing * zoom;
|
|
840
|
-
while (spacing < MIN_PATTERN_SPACING) {
|
|
841
|
-
spacing *= 2;
|
|
842
|
-
}
|
|
843
|
-
return spacing;
|
|
844
|
-
}
|
|
845
|
-
renderDots(ctx, camera, width, height) {
|
|
846
|
-
const spacing = this.adaptSpacing(this.spacing, camera.zoom);
|
|
847
|
-
const offsetX = camera.position.x % spacing;
|
|
848
|
-
const offsetY = camera.position.y % spacing;
|
|
849
|
-
const radius = this.dotRadius * Math.min(camera.zoom, 2);
|
|
850
|
-
ctx.fillStyle = this.color;
|
|
851
|
-
ctx.beginPath();
|
|
852
|
-
for (let x = offsetX; x < width; x += spacing) {
|
|
853
|
-
for (let y = offsetY; y < height; y += spacing) {
|
|
854
|
-
ctx.moveTo(x + radius, y);
|
|
855
|
-
ctx.arc(x, y, radius, 0, Math.PI * 2);
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
ctx.fill();
|
|
859
|
-
}
|
|
860
|
-
renderGrid(ctx, camera, width, height) {
|
|
861
|
-
const spacing = this.adaptSpacing(this.spacing, camera.zoom);
|
|
862
|
-
const offsetX = camera.position.x % spacing;
|
|
863
|
-
const offsetY = camera.position.y % spacing;
|
|
864
|
-
const lineW = this.lineWidth * Math.min(camera.zoom, 2);
|
|
865
|
-
ctx.fillStyle = this.color;
|
|
866
|
-
for (let x = offsetX; x < width; x += spacing) {
|
|
867
|
-
ctx.fillRect(x, 0, lineW, height);
|
|
868
|
-
}
|
|
869
|
-
for (let y = offsetY; y < height; y += spacing) {
|
|
870
|
-
ctx.fillRect(0, y, width, lineW);
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
};
|
|
874
|
-
|
|
875
530
|
// src/canvas/input-filter.ts
|
|
876
531
|
var InputFilter = class _InputFilter {
|
|
877
532
|
activePenId = null;
|
|
@@ -1033,16 +688,17 @@ var KeyboardActions = class {
|
|
|
1033
688
|
this.pasteCount = 0;
|
|
1034
689
|
}
|
|
1035
690
|
paste() {
|
|
691
|
+
if (this.deps.isToolActive()) return;
|
|
1036
692
|
this.flushPendingNudge();
|
|
1037
|
-
if (this.clipboard.length === 0
|
|
693
|
+
if (this.clipboard.length === 0) return;
|
|
1038
694
|
const sel = this.selectTool();
|
|
1039
695
|
if (!sel) return;
|
|
1040
696
|
this.pasteCount++;
|
|
1041
697
|
this.insertClones(this.clipboard, this.pasteCount * 20, sel);
|
|
1042
698
|
}
|
|
1043
699
|
duplicate() {
|
|
1044
|
-
this.flushPendingNudge();
|
|
1045
700
|
if (this.deps.isToolActive()) return;
|
|
701
|
+
this.flushPendingNudge();
|
|
1046
702
|
const sel = this.selectTool();
|
|
1047
703
|
if (!sel) return;
|
|
1048
704
|
const source = [];
|
|
@@ -1226,6 +882,11 @@ function parseBinding(binding) {
|
|
|
1226
882
|
throw new Error(`Invalid shortcut binding "${binding}": unknown modifier "${part}"`);
|
|
1227
883
|
}
|
|
1228
884
|
}
|
|
885
|
+
if (parsed.mod && (parsed.ctrl || parsed.meta)) {
|
|
886
|
+
throw new Error(
|
|
887
|
+
`Invalid shortcut binding "${binding}": "mod" already means Ctrl or Cmd; don't combine it with ctrl/meta`
|
|
888
|
+
);
|
|
889
|
+
}
|
|
1229
890
|
return parsed;
|
|
1230
891
|
}
|
|
1231
892
|
function bindingMatches(p, e, allowShift) {
|
|
@@ -1369,6 +1030,10 @@ var InputHandler = class {
|
|
|
1369
1030
|
this.inputFilter.reset();
|
|
1370
1031
|
this.deferredDown = null;
|
|
1371
1032
|
this.lastPointerEvent = null;
|
|
1033
|
+
if (this.scope === "focus") {
|
|
1034
|
+
this.element.removeAttribute("tabindex");
|
|
1035
|
+
this.element.style.outline = "";
|
|
1036
|
+
}
|
|
1372
1037
|
}
|
|
1373
1038
|
bind() {
|
|
1374
1039
|
const opts = { signal: this.abortController.signal };
|
|
@@ -1559,145 +1224,433 @@ var InputHandler = class {
|
|
|
1559
1224
|
}
|
|
1560
1225
|
return;
|
|
1561
1226
|
}
|
|
1562
|
-
default:
|
|
1563
|
-
if (action.startsWith("tool:")) {
|
|
1564
|
-
if (this.isToolActive) return;
|
|
1565
|
-
e.preventDefault();
|
|
1566
|
-
this.toolContext?.switchTool?.(action.slice("tool:".length));
|
|
1567
|
-
return;
|
|
1568
|
-
}
|
|
1569
|
-
console.warn(`[fieldnotes] unknown shortcut action "${action}"`);
|
|
1227
|
+
default:
|
|
1228
|
+
if (action.startsWith("tool:")) {
|
|
1229
|
+
if (this.isToolActive) return;
|
|
1230
|
+
e.preventDefault();
|
|
1231
|
+
this.toolContext?.switchTool?.(action.slice("tool:".length));
|
|
1232
|
+
return;
|
|
1233
|
+
}
|
|
1234
|
+
console.warn(`[fieldnotes] unknown shortcut action "${action}"`);
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
startPinch() {
|
|
1238
|
+
this.inputFilter.reset();
|
|
1239
|
+
this.deferredDown = null;
|
|
1240
|
+
this.isPanning = true;
|
|
1241
|
+
const [a, b] = this.getPinchPoints();
|
|
1242
|
+
this.lastPinchDistance = this.distance(a, b);
|
|
1243
|
+
this.lastPinchCenter = this.midpoint(a, b);
|
|
1244
|
+
this.lastPointer = { ...this.lastPinchCenter };
|
|
1245
|
+
}
|
|
1246
|
+
handlePinchMove() {
|
|
1247
|
+
const [a, b] = this.getPinchPoints();
|
|
1248
|
+
const dist = this.distance(a, b);
|
|
1249
|
+
const center = this.midpoint(a, b);
|
|
1250
|
+
if (this.lastPinchDistance > 0) {
|
|
1251
|
+
const scale = dist / this.lastPinchDistance;
|
|
1252
|
+
const newZoom = this.camera.zoom * scale;
|
|
1253
|
+
this.camera.zoomAt(newZoom, center);
|
|
1254
|
+
}
|
|
1255
|
+
const dx = center.x - this.lastPointer.x;
|
|
1256
|
+
const dy = center.y - this.lastPointer.y;
|
|
1257
|
+
this.camera.pan(dx, dy);
|
|
1258
|
+
this.lastPinchDistance = dist;
|
|
1259
|
+
this.lastPinchCenter = center;
|
|
1260
|
+
this.lastPointer = { ...center };
|
|
1261
|
+
}
|
|
1262
|
+
getPinchPoints() {
|
|
1263
|
+
const pts = [...this.activePointers.values()];
|
|
1264
|
+
return [pts[0] ?? { x: 0, y: 0 }, pts[1] ?? { x: 0, y: 0 }];
|
|
1265
|
+
}
|
|
1266
|
+
distance(a, b) {
|
|
1267
|
+
const dx = a.x - b.x;
|
|
1268
|
+
const dy = a.y - b.y;
|
|
1269
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
1270
|
+
}
|
|
1271
|
+
midpoint(a, b) {
|
|
1272
|
+
return { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };
|
|
1273
|
+
}
|
|
1274
|
+
toPointerState(e) {
|
|
1275
|
+
const rect = this.element.getBoundingClientRect();
|
|
1276
|
+
return {
|
|
1277
|
+
x: e.clientX - rect.left,
|
|
1278
|
+
y: e.clientY - rect.top,
|
|
1279
|
+
pressure: e.pressure,
|
|
1280
|
+
pointerType: e.pointerType === "touch" || e.pointerType === "pen" ? e.pointerType : "mouse",
|
|
1281
|
+
shiftKey: e.shiftKey
|
|
1282
|
+
};
|
|
1283
|
+
}
|
|
1284
|
+
dispatchToolDown(e) {
|
|
1285
|
+
if (!this.toolManager || !this.toolContext) return;
|
|
1286
|
+
this.actions.flushPendingNudge();
|
|
1287
|
+
this.historyRecorder?.begin();
|
|
1288
|
+
this.isToolActive = true;
|
|
1289
|
+
this.toolManager.handlePointerDown(this.toPointerState(e), this.toolContext);
|
|
1290
|
+
}
|
|
1291
|
+
dispatchToolMove(e) {
|
|
1292
|
+
if (!this.toolManager || !this.toolContext) return;
|
|
1293
|
+
this.toolManager.handlePointerMove(this.toPointerState(e), this.toolContext);
|
|
1294
|
+
}
|
|
1295
|
+
dispatchToolHover(e) {
|
|
1296
|
+
if (!this.toolManager?.activeTool || !this.toolContext) return;
|
|
1297
|
+
const tool = this.toolManager.activeTool;
|
|
1298
|
+
if (tool.onHover) {
|
|
1299
|
+
tool.onHover(this.toPointerState(e), this.toolContext);
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
dispatchToolUp(e) {
|
|
1303
|
+
if (!this.toolManager || !this.toolContext) return;
|
|
1304
|
+
this.toolManager.handlePointerUp(this.toPointerState(e), this.toolContext);
|
|
1305
|
+
this.historyRecorder?.commit();
|
|
1306
|
+
}
|
|
1307
|
+
isInScope() {
|
|
1308
|
+
if (this.scope === "window") return true;
|
|
1309
|
+
const active = document.activeElement;
|
|
1310
|
+
return active === this.element || this.element.contains(active);
|
|
1311
|
+
}
|
|
1312
|
+
focusSelf() {
|
|
1313
|
+
if (this.scope !== "focus" || this.isInScope()) return;
|
|
1314
|
+
this.element.focus({ preventScroll: true });
|
|
1315
|
+
}
|
|
1316
|
+
cancelToolIfActive(e) {
|
|
1317
|
+
if (this.isToolActive) {
|
|
1318
|
+
this.dispatchToolUp(e);
|
|
1319
|
+
this.isToolActive = false;
|
|
1320
|
+
}
|
|
1321
|
+
this.deferredDown = null;
|
|
1322
|
+
}
|
|
1323
|
+
};
|
|
1324
|
+
|
|
1325
|
+
// src/canvas/background.ts
|
|
1326
|
+
var MIN_PATTERN_SPACING = 16;
|
|
1327
|
+
var DEFAULTS = {
|
|
1328
|
+
pattern: "dots",
|
|
1329
|
+
spacing: 24,
|
|
1330
|
+
color: "#d0d0d0",
|
|
1331
|
+
dotRadius: 1,
|
|
1332
|
+
lineWidth: 0.5
|
|
1333
|
+
};
|
|
1334
|
+
var Background = class {
|
|
1335
|
+
pattern;
|
|
1336
|
+
spacing;
|
|
1337
|
+
color;
|
|
1338
|
+
dotRadius;
|
|
1339
|
+
lineWidth;
|
|
1340
|
+
cachedCanvas = null;
|
|
1341
|
+
cachedCtx = null;
|
|
1342
|
+
lastZoom = -1;
|
|
1343
|
+
lastOffsetX = -Infinity;
|
|
1344
|
+
lastOffsetY = -Infinity;
|
|
1345
|
+
lastWidth = 0;
|
|
1346
|
+
lastHeight = 0;
|
|
1347
|
+
constructor(options = {}) {
|
|
1348
|
+
this.pattern = options.pattern ?? DEFAULTS.pattern;
|
|
1349
|
+
this.spacing = options.spacing ?? DEFAULTS.spacing;
|
|
1350
|
+
this.color = options.color ?? DEFAULTS.color;
|
|
1351
|
+
this.dotRadius = options.dotRadius ?? DEFAULTS.dotRadius;
|
|
1352
|
+
this.lineWidth = options.lineWidth ?? DEFAULTS.lineWidth;
|
|
1353
|
+
}
|
|
1354
|
+
render(ctx, camera) {
|
|
1355
|
+
const { width, height } = ctx.canvas;
|
|
1356
|
+
const dpr = typeof devicePixelRatio !== "undefined" ? devicePixelRatio : 1;
|
|
1357
|
+
const cssWidth = width / dpr;
|
|
1358
|
+
const cssHeight = height / dpr;
|
|
1359
|
+
ctx.save();
|
|
1360
|
+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
1361
|
+
ctx.clearRect(0, 0, cssWidth, cssHeight);
|
|
1362
|
+
if (this.pattern === "none") {
|
|
1363
|
+
ctx.restore();
|
|
1364
|
+
return;
|
|
1365
|
+
}
|
|
1366
|
+
const spacing = this.adaptSpacing(this.spacing, camera.zoom);
|
|
1367
|
+
const keyZoom = camera.zoom;
|
|
1368
|
+
const keyX = Math.floor(camera.position.x % spacing);
|
|
1369
|
+
const keyY = Math.floor(camera.position.y % spacing);
|
|
1370
|
+
if (this.cachedCanvas !== null && keyZoom === this.lastZoom && keyX === this.lastOffsetX && keyY === this.lastOffsetY && cssWidth === this.lastWidth && cssHeight === this.lastHeight) {
|
|
1371
|
+
ctx.drawImage(this.cachedCanvas, 0, 0);
|
|
1372
|
+
ctx.restore();
|
|
1373
|
+
return;
|
|
1374
|
+
}
|
|
1375
|
+
this.ensureCachedCanvas(cssWidth, cssHeight, dpr);
|
|
1376
|
+
if (this.cachedCtx === null) {
|
|
1377
|
+
if (this.pattern === "dots") {
|
|
1378
|
+
this.renderDots(ctx, camera, cssWidth, cssHeight);
|
|
1379
|
+
} else if (this.pattern === "grid") {
|
|
1380
|
+
this.renderGrid(ctx, camera, cssWidth, cssHeight);
|
|
1381
|
+
}
|
|
1382
|
+
ctx.restore();
|
|
1383
|
+
return;
|
|
1384
|
+
}
|
|
1385
|
+
const offCtx = this.cachedCtx;
|
|
1386
|
+
offCtx.clearRect(0, 0, cssWidth, cssHeight);
|
|
1387
|
+
if (this.pattern === "dots") {
|
|
1388
|
+
this.renderDots(offCtx, camera, cssWidth, cssHeight);
|
|
1389
|
+
} else if (this.pattern === "grid") {
|
|
1390
|
+
this.renderGrid(offCtx, camera, cssWidth, cssHeight);
|
|
1391
|
+
}
|
|
1392
|
+
this.lastZoom = keyZoom;
|
|
1393
|
+
this.lastOffsetX = keyX;
|
|
1394
|
+
this.lastOffsetY = keyY;
|
|
1395
|
+
this.lastWidth = cssWidth;
|
|
1396
|
+
this.lastHeight = cssHeight;
|
|
1397
|
+
ctx.drawImage(this.cachedCanvas, 0, 0);
|
|
1398
|
+
ctx.restore();
|
|
1399
|
+
}
|
|
1400
|
+
ensureCachedCanvas(cssWidth, cssHeight, dpr) {
|
|
1401
|
+
if (this.cachedCanvas !== null && this.lastWidth === cssWidth && this.lastHeight === cssHeight) {
|
|
1402
|
+
return;
|
|
1403
|
+
}
|
|
1404
|
+
const physWidth = Math.round(cssWidth * dpr);
|
|
1405
|
+
const physHeight = Math.round(cssHeight * dpr);
|
|
1406
|
+
if (typeof OffscreenCanvas !== "undefined") {
|
|
1407
|
+
this.cachedCanvas = new OffscreenCanvas(physWidth, physHeight);
|
|
1408
|
+
} else if (typeof document !== "undefined") {
|
|
1409
|
+
const el = document.createElement("canvas");
|
|
1410
|
+
el.width = physWidth;
|
|
1411
|
+
el.height = physHeight;
|
|
1412
|
+
this.cachedCanvas = el;
|
|
1413
|
+
} else {
|
|
1414
|
+
this.cachedCanvas = null;
|
|
1415
|
+
this.cachedCtx = null;
|
|
1416
|
+
return;
|
|
1417
|
+
}
|
|
1418
|
+
const offCtx = this.cachedCanvas.getContext("2d");
|
|
1419
|
+
if (offCtx !== null) {
|
|
1420
|
+
offCtx.scale(dpr, dpr);
|
|
1421
|
+
}
|
|
1422
|
+
this.cachedCtx = offCtx;
|
|
1423
|
+
this.lastZoom = -1;
|
|
1424
|
+
}
|
|
1425
|
+
adaptSpacing(baseSpacing, zoom) {
|
|
1426
|
+
let spacing = baseSpacing * zoom;
|
|
1427
|
+
while (spacing < MIN_PATTERN_SPACING) {
|
|
1428
|
+
spacing *= 2;
|
|
1429
|
+
}
|
|
1430
|
+
return spacing;
|
|
1431
|
+
}
|
|
1432
|
+
renderDots(ctx, camera, width, height) {
|
|
1433
|
+
const spacing = this.adaptSpacing(this.spacing, camera.zoom);
|
|
1434
|
+
const offsetX = camera.position.x % spacing;
|
|
1435
|
+
const offsetY = camera.position.y % spacing;
|
|
1436
|
+
const radius = this.dotRadius * Math.min(camera.zoom, 2);
|
|
1437
|
+
ctx.fillStyle = this.color;
|
|
1438
|
+
ctx.beginPath();
|
|
1439
|
+
for (let x = offsetX; x < width; x += spacing) {
|
|
1440
|
+
for (let y = offsetY; y < height; y += spacing) {
|
|
1441
|
+
ctx.moveTo(x + radius, y);
|
|
1442
|
+
ctx.arc(x, y, radius, 0, Math.PI * 2);
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
ctx.fill();
|
|
1446
|
+
}
|
|
1447
|
+
renderGrid(ctx, camera, width, height) {
|
|
1448
|
+
const spacing = this.adaptSpacing(this.spacing, camera.zoom);
|
|
1449
|
+
const offsetX = camera.position.x % spacing;
|
|
1450
|
+
const offsetY = camera.position.y % spacing;
|
|
1451
|
+
const lineW = this.lineWidth * Math.min(camera.zoom, 2);
|
|
1452
|
+
ctx.fillStyle = this.color;
|
|
1453
|
+
for (let x = offsetX; x < width; x += spacing) {
|
|
1454
|
+
ctx.fillRect(x, 0, lineW, height);
|
|
1455
|
+
}
|
|
1456
|
+
for (let y = offsetY; y < height; y += spacing) {
|
|
1457
|
+
ctx.fillRect(0, y, width, lineW);
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
};
|
|
1461
|
+
|
|
1462
|
+
// src/core/event-bus.ts
|
|
1463
|
+
var EventBus = class {
|
|
1464
|
+
listeners = /* @__PURE__ */ new Map();
|
|
1465
|
+
on(event, listener) {
|
|
1466
|
+
const existing = this.listeners.get(event);
|
|
1467
|
+
if (existing) {
|
|
1468
|
+
existing.add(listener);
|
|
1469
|
+
} else {
|
|
1470
|
+
const set = /* @__PURE__ */ new Set([listener]);
|
|
1471
|
+
this.listeners.set(event, set);
|
|
1472
|
+
}
|
|
1473
|
+
return () => this.off(event, listener);
|
|
1474
|
+
}
|
|
1475
|
+
off(event, listener) {
|
|
1476
|
+
this.listeners.get(event)?.delete(listener);
|
|
1477
|
+
}
|
|
1478
|
+
emit(event, data) {
|
|
1479
|
+
this.listeners.get(event)?.forEach((listener) => {
|
|
1480
|
+
try {
|
|
1481
|
+
listener(data);
|
|
1482
|
+
} catch (err) {
|
|
1483
|
+
console.error(`[fieldnotes] listener error for "${String(event)}"`, err);
|
|
1484
|
+
}
|
|
1485
|
+
});
|
|
1486
|
+
}
|
|
1487
|
+
clear() {
|
|
1488
|
+
this.listeners.clear();
|
|
1489
|
+
}
|
|
1490
|
+
};
|
|
1491
|
+
|
|
1492
|
+
// src/core/quadtree.ts
|
|
1493
|
+
var MAX_ITEMS = 8;
|
|
1494
|
+
var MAX_DEPTH = 8;
|
|
1495
|
+
function intersects(a, b) {
|
|
1496
|
+
return a.x <= b.x + b.w && a.x + a.w >= b.x && a.y <= b.y + b.h && a.y + a.h >= b.y;
|
|
1497
|
+
}
|
|
1498
|
+
var QuadNode = class _QuadNode {
|
|
1499
|
+
constructor(bounds, depth) {
|
|
1500
|
+
this.bounds = bounds;
|
|
1501
|
+
this.depth = depth;
|
|
1502
|
+
}
|
|
1503
|
+
items = [];
|
|
1504
|
+
children = null;
|
|
1505
|
+
insert(entry) {
|
|
1506
|
+
if (this.children) {
|
|
1507
|
+
const idx = this.getChildIndex(entry.bounds);
|
|
1508
|
+
if (idx !== -1) {
|
|
1509
|
+
const child = this.children[idx];
|
|
1510
|
+
if (child) child.insert(entry);
|
|
1511
|
+
return;
|
|
1512
|
+
}
|
|
1513
|
+
this.items.push(entry);
|
|
1514
|
+
return;
|
|
1515
|
+
}
|
|
1516
|
+
this.items.push(entry);
|
|
1517
|
+
if (this.items.length > MAX_ITEMS && this.depth < MAX_DEPTH) {
|
|
1518
|
+
this.split();
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
remove(id) {
|
|
1522
|
+
const idx = this.items.findIndex((e) => e.id === id);
|
|
1523
|
+
if (idx !== -1) {
|
|
1524
|
+
this.items.splice(idx, 1);
|
|
1525
|
+
return true;
|
|
1526
|
+
}
|
|
1527
|
+
if (this.children) {
|
|
1528
|
+
for (const child of this.children) {
|
|
1529
|
+
if (child.remove(id)) {
|
|
1530
|
+
this.collapseIfEmpty();
|
|
1531
|
+
return true;
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
return false;
|
|
1536
|
+
}
|
|
1537
|
+
query(rect, result) {
|
|
1538
|
+
if (!intersects(this.bounds, rect)) return;
|
|
1539
|
+
for (const item of this.items) {
|
|
1540
|
+
if (intersects(item.bounds, rect)) {
|
|
1541
|
+
result.push(item.id);
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
if (this.children) {
|
|
1545
|
+
for (const child of this.children) {
|
|
1546
|
+
child.query(rect, result);
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
getChildIndex(itemBounds) {
|
|
1551
|
+
const midX = this.bounds.x + this.bounds.w / 2;
|
|
1552
|
+
const midY = this.bounds.y + this.bounds.h / 2;
|
|
1553
|
+
const left = itemBounds.x >= this.bounds.x && itemBounds.x + itemBounds.w <= midX;
|
|
1554
|
+
const right = itemBounds.x >= midX && itemBounds.x + itemBounds.w <= this.bounds.x + this.bounds.w;
|
|
1555
|
+
const top = itemBounds.y >= this.bounds.y && itemBounds.y + itemBounds.h <= midY;
|
|
1556
|
+
const bottom = itemBounds.y >= midY && itemBounds.y + itemBounds.h <= this.bounds.y + this.bounds.h;
|
|
1557
|
+
if (left && top) return 0;
|
|
1558
|
+
if (right && top) return 1;
|
|
1559
|
+
if (left && bottom) return 2;
|
|
1560
|
+
if (right && bottom) return 3;
|
|
1561
|
+
return -1;
|
|
1562
|
+
}
|
|
1563
|
+
split() {
|
|
1564
|
+
const { x, y, w, h } = this.bounds;
|
|
1565
|
+
const halfW = w / 2;
|
|
1566
|
+
const halfH = h / 2;
|
|
1567
|
+
const d = this.depth + 1;
|
|
1568
|
+
this.children = [
|
|
1569
|
+
new _QuadNode({ x, y, w: halfW, h: halfH }, d),
|
|
1570
|
+
new _QuadNode({ x: x + halfW, y, w: halfW, h: halfH }, d),
|
|
1571
|
+
new _QuadNode({ x, y: y + halfH, w: halfW, h: halfH }, d),
|
|
1572
|
+
new _QuadNode({ x: x + halfW, y: y + halfH, w: halfW, h: halfH }, d)
|
|
1573
|
+
];
|
|
1574
|
+
const remaining = [];
|
|
1575
|
+
for (const item of this.items) {
|
|
1576
|
+
const idx = this.getChildIndex(item.bounds);
|
|
1577
|
+
if (idx !== -1) {
|
|
1578
|
+
const target = this.children[idx];
|
|
1579
|
+
if (target) target.insert(item);
|
|
1580
|
+
} else {
|
|
1581
|
+
remaining.push(item);
|
|
1582
|
+
}
|
|
1570
1583
|
}
|
|
1584
|
+
this.items = remaining;
|
|
1571
1585
|
}
|
|
1572
|
-
|
|
1573
|
-
this.
|
|
1574
|
-
|
|
1575
|
-
this.
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
const center = this.midpoint(a, b);
|
|
1585
|
-
if (this.lastPinchDistance > 0) {
|
|
1586
|
-
const scale = dist / this.lastPinchDistance;
|
|
1587
|
-
const newZoom = this.camera.zoom * scale;
|
|
1588
|
-
this.camera.zoomAt(newZoom, center);
|
|
1586
|
+
collapseIfEmpty() {
|
|
1587
|
+
if (!this.children) return;
|
|
1588
|
+
let totalItems = this.items.length;
|
|
1589
|
+
for (const child of this.children) {
|
|
1590
|
+
if (child.children) return;
|
|
1591
|
+
totalItems += child.items.length;
|
|
1592
|
+
}
|
|
1593
|
+
if (totalItems <= MAX_ITEMS) {
|
|
1594
|
+
for (const child of this.children) {
|
|
1595
|
+
this.items.push(...child.items);
|
|
1596
|
+
}
|
|
1597
|
+
this.children = null;
|
|
1589
1598
|
}
|
|
1590
|
-
const dx = center.x - this.lastPointer.x;
|
|
1591
|
-
const dy = center.y - this.lastPointer.y;
|
|
1592
|
-
this.camera.pan(dx, dy);
|
|
1593
|
-
this.lastPinchDistance = dist;
|
|
1594
|
-
this.lastPinchCenter = center;
|
|
1595
|
-
this.lastPointer = { ...center };
|
|
1596
|
-
}
|
|
1597
|
-
getPinchPoints() {
|
|
1598
|
-
const pts = [...this.activePointers.values()];
|
|
1599
|
-
return [pts[0] ?? { x: 0, y: 0 }, pts[1] ?? { x: 0, y: 0 }];
|
|
1600
|
-
}
|
|
1601
|
-
distance(a, b) {
|
|
1602
|
-
const dx = a.x - b.x;
|
|
1603
|
-
const dy = a.y - b.y;
|
|
1604
|
-
return Math.sqrt(dx * dx + dy * dy);
|
|
1605
|
-
}
|
|
1606
|
-
midpoint(a, b) {
|
|
1607
|
-
return { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };
|
|
1608
1599
|
}
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
};
|
|
1600
|
+
};
|
|
1601
|
+
var Quadtree = class {
|
|
1602
|
+
root;
|
|
1603
|
+
_size = 0;
|
|
1604
|
+
worldBounds;
|
|
1605
|
+
constructor(worldBounds) {
|
|
1606
|
+
this.worldBounds = worldBounds;
|
|
1607
|
+
this.root = new QuadNode(worldBounds, 0);
|
|
1618
1608
|
}
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
this.actions.flushPendingNudge();
|
|
1622
|
-
this.historyRecorder?.begin();
|
|
1623
|
-
this.isToolActive = true;
|
|
1624
|
-
this.toolManager.handlePointerDown(this.toPointerState(e), this.toolContext);
|
|
1609
|
+
get size() {
|
|
1610
|
+
return this._size;
|
|
1625
1611
|
}
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
this.
|
|
1612
|
+
insert(id, bounds) {
|
|
1613
|
+
this.root.insert({ id, bounds });
|
|
1614
|
+
this._size++;
|
|
1629
1615
|
}
|
|
1630
|
-
|
|
1631
|
-
if (
|
|
1632
|
-
|
|
1633
|
-
if (tool.onHover) {
|
|
1634
|
-
tool.onHover(this.toPointerState(e), this.toolContext);
|
|
1616
|
+
remove(id) {
|
|
1617
|
+
if (this.root.remove(id)) {
|
|
1618
|
+
this._size--;
|
|
1635
1619
|
}
|
|
1636
1620
|
}
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
this.
|
|
1640
|
-
this.historyRecorder?.commit();
|
|
1621
|
+
update(id, newBounds) {
|
|
1622
|
+
this.remove(id);
|
|
1623
|
+
this.insert(id, newBounds);
|
|
1641
1624
|
}
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
return
|
|
1625
|
+
query(rect) {
|
|
1626
|
+
const result = [];
|
|
1627
|
+
this.root.query(rect, result);
|
|
1628
|
+
return result;
|
|
1646
1629
|
}
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
this.element.focus({ preventScroll: true });
|
|
1630
|
+
queryPoint(point) {
|
|
1631
|
+
return this.query({ x: point.x, y: point.y, w: 0, h: 0 });
|
|
1650
1632
|
}
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
this.isToolActive = false;
|
|
1655
|
-
}
|
|
1656
|
-
this.deferredDown = null;
|
|
1633
|
+
clear() {
|
|
1634
|
+
this.root = new QuadNode(this.worldBounds, 0);
|
|
1635
|
+
this._size = 0;
|
|
1657
1636
|
}
|
|
1658
1637
|
};
|
|
1659
1638
|
|
|
1660
|
-
// src/
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
hasPendingTap = false;
|
|
1670
|
-
constructor(options) {
|
|
1671
|
-
this.timeout = options?.timeout ?? DEFAULT_TIMEOUT;
|
|
1672
|
-
this.maxDistance = options?.maxDistance ?? DEFAULT_MAX_DISTANCE;
|
|
1673
|
-
}
|
|
1674
|
-
feed(e) {
|
|
1675
|
-
const now = Date.now();
|
|
1676
|
-
const x = e.clientX;
|
|
1677
|
-
const y = e.clientY;
|
|
1678
|
-
if (this.hasPendingTap) {
|
|
1679
|
-
const elapsed = now - this.lastTapTime;
|
|
1680
|
-
const dx = x - this.lastTapX;
|
|
1681
|
-
const dy = y - this.lastTapY;
|
|
1682
|
-
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
1683
|
-
if (elapsed <= this.timeout && dist <= this.maxDistance) {
|
|
1684
|
-
this.reset();
|
|
1685
|
-
return true;
|
|
1686
|
-
}
|
|
1687
|
-
}
|
|
1688
|
-
this.lastTapTime = now;
|
|
1689
|
-
this.lastTapX = x;
|
|
1690
|
-
this.lastTapY = y;
|
|
1691
|
-
this.hasPendingTap = true;
|
|
1692
|
-
return false;
|
|
1693
|
-
}
|
|
1694
|
-
reset() {
|
|
1695
|
-
this.hasPendingTap = false;
|
|
1696
|
-
this.lastTapTime = 0;
|
|
1697
|
-
this.lastTapX = 0;
|
|
1698
|
-
this.lastTapY = 0;
|
|
1639
|
+
// src/core/geometry.ts
|
|
1640
|
+
function distSqToSegment(p, a, b) {
|
|
1641
|
+
const abx = b.x - a.x;
|
|
1642
|
+
const aby = b.y - a.y;
|
|
1643
|
+
const apx = p.x - a.x;
|
|
1644
|
+
const apy = p.y - a.y;
|
|
1645
|
+
const lenSq = abx * abx + aby * aby;
|
|
1646
|
+
if (lenSq === 0) {
|
|
1647
|
+
return apx * apx + apy * apy;
|
|
1699
1648
|
}
|
|
1700
|
-
|
|
1649
|
+
const t = Math.max(0, Math.min(1, (apx * abx + apy * aby) / lenSq));
|
|
1650
|
+
const dx = p.x - (a.x + t * abx);
|
|
1651
|
+
const dy = p.y - (a.y + t * aby);
|
|
1652
|
+
return dx * dx + dy * dy;
|
|
1653
|
+
}
|
|
1701
1654
|
|
|
1702
1655
|
// src/elements/arrow-geometry.ts
|
|
1703
1656
|
function getArrowControlPoint(from, to, bend) {
|
|
@@ -1787,16 +1740,7 @@ function bezierPoint(from, cp, to, t) {
|
|
|
1787
1740
|
};
|
|
1788
1741
|
}
|
|
1789
1742
|
function isNearLine(point, a, b, threshold) {
|
|
1790
|
-
|
|
1791
|
-
const dy = b.y - a.y;
|
|
1792
|
-
const lenSq = dx * dx + dy * dy;
|
|
1793
|
-
if (lenSq === 0) {
|
|
1794
|
-
return Math.hypot(point.x - a.x, point.y - a.y) <= threshold;
|
|
1795
|
-
}
|
|
1796
|
-
const t = Math.max(0, Math.min(1, ((point.x - a.x) * dx + (point.y - a.y) * dy) / lenSq));
|
|
1797
|
-
const projX = a.x + t * dx;
|
|
1798
|
-
const projY = a.y + t * dy;
|
|
1799
|
-
return Math.hypot(point.x - projX, point.y - projY) <= threshold;
|
|
1743
|
+
return distSqToSegment(point, a, b) <= threshold * threshold;
|
|
1800
1744
|
}
|
|
1801
1745
|
|
|
1802
1746
|
// src/elements/element-bounds.ts
|
|
@@ -2337,51 +2281,6 @@ function updateBoundArrow(arrow, store) {
|
|
|
2337
2281
|
}
|
|
2338
2282
|
return Object.keys(updates).length > 0 ? updates : null;
|
|
2339
2283
|
}
|
|
2340
|
-
function clearStaleBindings(arrow, store) {
|
|
2341
|
-
const updates = {};
|
|
2342
|
-
let hasUpdates = false;
|
|
2343
|
-
if (arrow.fromBinding && !store.getById(arrow.fromBinding.elementId)) {
|
|
2344
|
-
updates.fromBinding = void 0;
|
|
2345
|
-
hasUpdates = true;
|
|
2346
|
-
}
|
|
2347
|
-
if (arrow.toBinding && !store.getById(arrow.toBinding.elementId)) {
|
|
2348
|
-
updates.toBinding = void 0;
|
|
2349
|
-
hasUpdates = true;
|
|
2350
|
-
}
|
|
2351
|
-
return hasUpdates ? updates : null;
|
|
2352
|
-
}
|
|
2353
|
-
function unbindArrow(arrow, store) {
|
|
2354
|
-
const updates = {};
|
|
2355
|
-
if (arrow.fromBinding) {
|
|
2356
|
-
const el = store.getById(arrow.fromBinding.elementId);
|
|
2357
|
-
const bounds = el ? getElementBounds(el) : null;
|
|
2358
|
-
if (bounds) {
|
|
2359
|
-
const angle = getArrowTangentAngle(arrow.from, arrow.to, arrow.bend, 0);
|
|
2360
|
-
const rayTarget = {
|
|
2361
|
-
x: arrow.from.x + Math.cos(angle) * 1e3,
|
|
2362
|
-
y: arrow.from.y + Math.sin(angle) * 1e3
|
|
2363
|
-
};
|
|
2364
|
-
const edge = getEdgeIntersection(bounds, rayTarget);
|
|
2365
|
-
updates.from = edge;
|
|
2366
|
-
updates.position = edge;
|
|
2367
|
-
}
|
|
2368
|
-
updates.fromBinding = void 0;
|
|
2369
|
-
}
|
|
2370
|
-
if (arrow.toBinding) {
|
|
2371
|
-
const el = store.getById(arrow.toBinding.elementId);
|
|
2372
|
-
const bounds = el ? getElementBounds(el) : null;
|
|
2373
|
-
if (bounds) {
|
|
2374
|
-
const angle = getArrowTangentAngle(arrow.from, arrow.to, arrow.bend, 1);
|
|
2375
|
-
const rayTarget = {
|
|
2376
|
-
x: arrow.to.x - Math.cos(angle) * 1e3,
|
|
2377
|
-
y: arrow.to.y - Math.sin(angle) * 1e3
|
|
2378
|
-
};
|
|
2379
|
-
updates.to = getEdgeIntersection(bounds, rayTarget);
|
|
2380
|
-
}
|
|
2381
|
-
updates.toBinding = void 0;
|
|
2382
|
-
}
|
|
2383
|
-
return updates;
|
|
2384
|
-
}
|
|
2385
2284
|
|
|
2386
2285
|
// src/elements/grid-renderer.ts
|
|
2387
2286
|
function getSquareGridLines(bounds, cellSize) {
|
|
@@ -3227,9 +3126,9 @@ var ElementRenderer = class {
|
|
|
3227
3126
|
});
|
|
3228
3127
|
}
|
|
3229
3128
|
};
|
|
3230
|
-
img.onerror = () => {
|
|
3129
|
+
img.onerror = (event) => {
|
|
3231
3130
|
this.imageCache.set(src, "failed");
|
|
3232
|
-
this.onImageError?.(src);
|
|
3131
|
+
this.onImageError?.(src, event);
|
|
3233
3132
|
this.onImageLoad?.();
|
|
3234
3133
|
};
|
|
3235
3134
|
return null;
|
|
@@ -3654,7 +3553,10 @@ var NoteEditor = class {
|
|
|
3654
3553
|
this.editingNode.removeAttribute("data-fn-placeholder");
|
|
3655
3554
|
this.editingNode.removeAttribute("data-fn-empty");
|
|
3656
3555
|
const text = sanitizeNoteHtml(this.editingNode.innerHTML);
|
|
3657
|
-
store.
|
|
3556
|
+
const current = store.getById(this.editingId);
|
|
3557
|
+
if (current && (current.type === "note" || current.type === "text") && current.text !== text) {
|
|
3558
|
+
store.update(this.editingId, { text });
|
|
3559
|
+
}
|
|
3658
3560
|
this.editingNode.contentEditable = "false";
|
|
3659
3561
|
Object.assign(this.editingNode.style, {
|
|
3660
3562
|
userSelect: "none",
|
|
@@ -4571,6 +4473,48 @@ var InteractMode = class {
|
|
|
4571
4473
|
};
|
|
4572
4474
|
};
|
|
4573
4475
|
|
|
4476
|
+
// src/canvas/double-tap-detector.ts
|
|
4477
|
+
var DEFAULT_TIMEOUT = 300;
|
|
4478
|
+
var DEFAULT_MAX_DISTANCE = 20;
|
|
4479
|
+
var DoubleTapDetector = class {
|
|
4480
|
+
timeout;
|
|
4481
|
+
maxDistance;
|
|
4482
|
+
lastTapTime = 0;
|
|
4483
|
+
lastTapX = 0;
|
|
4484
|
+
lastTapY = 0;
|
|
4485
|
+
hasPendingTap = false;
|
|
4486
|
+
constructor(options) {
|
|
4487
|
+
this.timeout = options?.timeout ?? DEFAULT_TIMEOUT;
|
|
4488
|
+
this.maxDistance = options?.maxDistance ?? DEFAULT_MAX_DISTANCE;
|
|
4489
|
+
}
|
|
4490
|
+
feed(e) {
|
|
4491
|
+
const now = Date.now();
|
|
4492
|
+
const x = e.clientX;
|
|
4493
|
+
const y = e.clientY;
|
|
4494
|
+
if (this.hasPendingTap) {
|
|
4495
|
+
const elapsed = now - this.lastTapTime;
|
|
4496
|
+
const dx = x - this.lastTapX;
|
|
4497
|
+
const dy = y - this.lastTapY;
|
|
4498
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
4499
|
+
if (elapsed <= this.timeout && dist <= this.maxDistance) {
|
|
4500
|
+
this.reset();
|
|
4501
|
+
return true;
|
|
4502
|
+
}
|
|
4503
|
+
}
|
|
4504
|
+
this.lastTapTime = now;
|
|
4505
|
+
this.lastTapX = x;
|
|
4506
|
+
this.lastTapY = y;
|
|
4507
|
+
this.hasPendingTap = true;
|
|
4508
|
+
return false;
|
|
4509
|
+
}
|
|
4510
|
+
reset() {
|
|
4511
|
+
this.hasPendingTap = false;
|
|
4512
|
+
this.lastTapTime = 0;
|
|
4513
|
+
this.lastTapX = 0;
|
|
4514
|
+
this.lastTapY = 0;
|
|
4515
|
+
}
|
|
4516
|
+
};
|
|
4517
|
+
|
|
4574
4518
|
// src/canvas/dom-node-manager.ts
|
|
4575
4519
|
var DomNodeManager = class {
|
|
4576
4520
|
domNodes = /* @__PURE__ */ new Map();
|
|
@@ -5251,13 +5195,13 @@ var Viewport = class {
|
|
|
5251
5195
|
this.renderLoop.markAllLayersDirty();
|
|
5252
5196
|
this.requestRender();
|
|
5253
5197
|
});
|
|
5254
|
-
this.renderer.setOnImageError((src) => {
|
|
5198
|
+
this.renderer.setOnImageError((src, cause) => {
|
|
5255
5199
|
const elementIds = [];
|
|
5256
5200
|
for (const el of this.store.getAll()) {
|
|
5257
5201
|
if (el.type === "image" && el.src === src) elementIds.push(el.id);
|
|
5258
5202
|
}
|
|
5259
5203
|
if (options.onImageError) {
|
|
5260
|
-
options.onImageError({ src, elementIds });
|
|
5204
|
+
options.onImageError({ src, elementIds, cause });
|
|
5261
5205
|
} else {
|
|
5262
5206
|
console.warn(`[fieldnotes] image failed to load: ${src}`);
|
|
5263
5207
|
}
|
|
@@ -5476,6 +5420,10 @@ var Viewport = class {
|
|
|
5476
5420
|
this.loadState(parseState(json));
|
|
5477
5421
|
}
|
|
5478
5422
|
setTool(name) {
|
|
5423
|
+
if (!this.toolManager.getTool(name)) {
|
|
5424
|
+
console.warn(`[fieldnotes] setTool: no tool registered as "${name}"`);
|
|
5425
|
+
return;
|
|
5426
|
+
}
|
|
5479
5427
|
this.toolManager.setTool(name, this.toolContext);
|
|
5480
5428
|
}
|
|
5481
5429
|
get shortcuts() {
|
|
@@ -5972,20 +5920,6 @@ var PencilTool = class {
|
|
|
5972
5920
|
};
|
|
5973
5921
|
|
|
5974
5922
|
// src/elements/stroke-hit.ts
|
|
5975
|
-
function distSqToSegment(p, a, b) {
|
|
5976
|
-
const abx = b.x - a.x;
|
|
5977
|
-
const aby = b.y - a.y;
|
|
5978
|
-
const apx = p.x - a.x;
|
|
5979
|
-
const apy = p.y - a.y;
|
|
5980
|
-
const lenSq = abx * abx + aby * aby;
|
|
5981
|
-
if (lenSq === 0) {
|
|
5982
|
-
return apx * apx + apy * apy;
|
|
5983
|
-
}
|
|
5984
|
-
const t = Math.max(0, Math.min(1, (apx * abx + apy * aby) / lenSq));
|
|
5985
|
-
const dx = p.x - (a.x + t * abx);
|
|
5986
|
-
const dy = p.y - (a.y + t * aby);
|
|
5987
|
-
return dx * dx + dy * dy;
|
|
5988
|
-
}
|
|
5989
5923
|
function hitTestStroke(stroke, point, radius) {
|
|
5990
5924
|
const bounds = getElementBounds(stroke);
|
|
5991
5925
|
if (!bounds) return false;
|
|
@@ -7582,53 +7516,33 @@ var TemplateTool = class {
|
|
|
7582
7516
|
};
|
|
7583
7517
|
|
|
7584
7518
|
// src/index.ts
|
|
7585
|
-
var VERSION = "0.
|
|
7519
|
+
var VERSION = "0.25.0";
|
|
7586
7520
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7587
7521
|
0 && (module.exports = {
|
|
7588
|
-
AddElementCommand,
|
|
7589
7522
|
ArrowTool,
|
|
7590
7523
|
AutoSave,
|
|
7591
|
-
Background,
|
|
7592
|
-
BatchCommand,
|
|
7593
7524
|
Camera,
|
|
7594
|
-
CreateLayerCommand,
|
|
7595
|
-
DEFAULT_FONT_SIZE_PRESETS,
|
|
7596
7525
|
DEFAULT_NOTE_FONT_SIZE,
|
|
7597
|
-
DoubleTapDetector,
|
|
7598
|
-
ElementRenderer,
|
|
7599
7526
|
ElementStore,
|
|
7600
7527
|
EraserTool,
|
|
7601
|
-
EventBus,
|
|
7602
7528
|
HandTool,
|
|
7603
|
-
HistoryRecorder,
|
|
7604
7529
|
HistoryStack,
|
|
7605
7530
|
ImageTool,
|
|
7606
|
-
InputFilter,
|
|
7607
|
-
InputHandler,
|
|
7608
7531
|
LayerManager,
|
|
7609
7532
|
MeasureTool,
|
|
7610
|
-
NoteEditor,
|
|
7611
7533
|
NoteTool,
|
|
7612
|
-
NoteToolbar,
|
|
7613
7534
|
PencilTool,
|
|
7614
|
-
Quadtree,
|
|
7615
|
-
RemoveElementCommand,
|
|
7616
|
-
RemoveLayerCommand,
|
|
7617
7535
|
SelectTool,
|
|
7618
7536
|
ShapeTool,
|
|
7619
7537
|
TemplateTool,
|
|
7620
7538
|
TextTool,
|
|
7621
7539
|
ToolManager,
|
|
7622
|
-
UpdateElementCommand,
|
|
7623
|
-
UpdateLayerCommand,
|
|
7624
7540
|
VERSION,
|
|
7625
7541
|
Viewport,
|
|
7626
7542
|
boundsIntersect,
|
|
7627
|
-
clearStaleBindings,
|
|
7628
7543
|
createArrow,
|
|
7629
7544
|
createGrid,
|
|
7630
7545
|
createHtmlElement,
|
|
7631
|
-
createId,
|
|
7632
7546
|
createImage,
|
|
7633
7547
|
createNote,
|
|
7634
7548
|
createShape,
|
|
@@ -7637,29 +7551,20 @@ var VERSION = "0.23.0";
|
|
|
7637
7551
|
createText,
|
|
7638
7552
|
drawHexPath,
|
|
7639
7553
|
exportImage,
|
|
7640
|
-
exportState,
|
|
7641
|
-
findBindTarget,
|
|
7642
|
-
findBoundArrows,
|
|
7643
7554
|
getActiveFormats,
|
|
7644
7555
|
getArrowBounds,
|
|
7645
7556
|
getArrowControlPoint,
|
|
7646
7557
|
getArrowMidpoint,
|
|
7647
7558
|
getArrowTangentAngle,
|
|
7648
7559
|
getBendFromPoint,
|
|
7649
|
-
getEdgeIntersection,
|
|
7650
7560
|
getElementBounds,
|
|
7651
|
-
getElementCenter,
|
|
7652
7561
|
getElementsBoundingBox,
|
|
7653
7562
|
getHexCellsInCone,
|
|
7654
7563
|
getHexCellsInLine,
|
|
7655
7564
|
getHexCellsInRadius,
|
|
7656
7565
|
getHexCellsInSquare,
|
|
7657
7566
|
getHexDistance,
|
|
7658
|
-
isBindable,
|
|
7659
7567
|
isNearBezier,
|
|
7660
|
-
isNoteContentEmpty,
|
|
7661
|
-
parseState,
|
|
7662
|
-
sanitizeNoteHtml,
|
|
7663
7568
|
setFontSize,
|
|
7664
7569
|
smartSnap,
|
|
7665
7570
|
snapPoint,
|
|
@@ -7667,8 +7572,6 @@ var VERSION = "0.23.0";
|
|
|
7667
7572
|
toggleBold,
|
|
7668
7573
|
toggleItalic,
|
|
7669
7574
|
toggleStrikethrough,
|
|
7670
|
-
toggleUnderline
|
|
7671
|
-
unbindArrow,
|
|
7672
|
-
updateBoundArrow
|
|
7575
|
+
toggleUnderline
|
|
7673
7576
|
});
|
|
7674
7577
|
//# sourceMappingURL=index.cjs.map
|