@fieldnotes/core 0.43.0 → 0.45.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 +137 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +49 -4
- package/dist/index.d.ts +49 -4
- package/dist/index.js +134 -18
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -29,9 +29,12 @@ __export(index_exports, {
|
|
|
29
29
|
HandTool: () => HandTool,
|
|
30
30
|
HistoryStack: () => HistoryStack,
|
|
31
31
|
ImageTool: () => ImageTool,
|
|
32
|
+
IndexedDBAdapter: () => IndexedDBAdapter,
|
|
32
33
|
LaserTool: () => LaserTool,
|
|
33
34
|
LayerManager: () => LayerManager,
|
|
35
|
+
LocalStorageAdapter: () => LocalStorageAdapter,
|
|
34
36
|
MeasureTool: () => MeasureTool,
|
|
37
|
+
MemoryAdapter: () => MemoryAdapter,
|
|
35
38
|
NoteTool: () => NoteTool,
|
|
36
39
|
PencilTool: () => PencilTool,
|
|
37
40
|
SelectTool: () => SelectTool,
|
|
@@ -368,6 +371,22 @@ function migrateElement(obj) {
|
|
|
368
371
|
}
|
|
369
372
|
}
|
|
370
373
|
|
|
374
|
+
// src/core/storage/local-storage-adapter.ts
|
|
375
|
+
var LocalStorageAdapter = class {
|
|
376
|
+
async load(key) {
|
|
377
|
+
if (typeof localStorage === "undefined") return null;
|
|
378
|
+
return localStorage.getItem(key);
|
|
379
|
+
}
|
|
380
|
+
async save(key, value) {
|
|
381
|
+
if (typeof localStorage === "undefined") return;
|
|
382
|
+
localStorage.setItem(key, value);
|
|
383
|
+
}
|
|
384
|
+
async clear(key) {
|
|
385
|
+
if (typeof localStorage === "undefined") return;
|
|
386
|
+
localStorage.removeItem(key);
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
|
|
371
390
|
// src/core/auto-save.ts
|
|
372
391
|
var DEFAULT_KEY = "fieldnotes-autosave";
|
|
373
392
|
var DEFAULT_DEBOUNCE_MS = 1e3;
|
|
@@ -378,14 +397,18 @@ var AutoSave = class {
|
|
|
378
397
|
this.key = options.key ?? DEFAULT_KEY;
|
|
379
398
|
this.debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;
|
|
380
399
|
this.layerManager = options.layerManager;
|
|
400
|
+
this.adapter = options.adapter ?? new LocalStorageAdapter();
|
|
381
401
|
this.onError = options.onError;
|
|
382
402
|
}
|
|
383
403
|
key;
|
|
384
404
|
debounceMs;
|
|
385
405
|
layerManager;
|
|
406
|
+
adapter;
|
|
386
407
|
timerId = null;
|
|
387
408
|
unsubscribers = [];
|
|
388
409
|
onError;
|
|
410
|
+
saving = false;
|
|
411
|
+
pendingSave = false;
|
|
389
412
|
start() {
|
|
390
413
|
const schedule = () => this.scheduleSave();
|
|
391
414
|
this.unsubscribers = [
|
|
@@ -403,9 +426,8 @@ var AutoSave = class {
|
|
|
403
426
|
this.unsubscribers.forEach((fn) => fn());
|
|
404
427
|
this.unsubscribers = [];
|
|
405
428
|
}
|
|
406
|
-
load() {
|
|
407
|
-
|
|
408
|
-
const json = localStorage.getItem(this.key);
|
|
429
|
+
async load() {
|
|
430
|
+
const json = await this.adapter.load(this.key);
|
|
409
431
|
if (!json) return null;
|
|
410
432
|
try {
|
|
411
433
|
return parseState(json);
|
|
@@ -413,13 +435,12 @@ var AutoSave = class {
|
|
|
413
435
|
return null;
|
|
414
436
|
}
|
|
415
437
|
}
|
|
416
|
-
clear() {
|
|
417
|
-
|
|
418
|
-
localStorage.removeItem(this.key);
|
|
438
|
+
async clear() {
|
|
439
|
+
await this.adapter.clear(this.key);
|
|
419
440
|
}
|
|
420
441
|
scheduleSave() {
|
|
421
442
|
this.cancelPending();
|
|
422
|
-
this.timerId = setTimeout(() => this.save(), this.debounceMs);
|
|
443
|
+
this.timerId = setTimeout(() => void this.save(), this.debounceMs);
|
|
423
444
|
}
|
|
424
445
|
cancelPending() {
|
|
425
446
|
if (this.timerId !== null) {
|
|
@@ -427,19 +448,108 @@ var AutoSave = class {
|
|
|
427
448
|
this.timerId = null;
|
|
428
449
|
}
|
|
429
450
|
}
|
|
430
|
-
save() {
|
|
431
|
-
if (
|
|
432
|
-
|
|
433
|
-
|
|
451
|
+
async save() {
|
|
452
|
+
if (this.saving) {
|
|
453
|
+
this.pendingSave = true;
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
this.saving = true;
|
|
434
457
|
try {
|
|
435
|
-
|
|
458
|
+
const layers = this.layerManager?.snapshot() ?? [];
|
|
459
|
+
const state = exportState(this.store.snapshot(), this.camera, layers);
|
|
460
|
+
await this.adapter.save(this.key, JSON.stringify(state));
|
|
436
461
|
} catch (e) {
|
|
437
|
-
console.warn("Auto-save failed: storage quota exceeded. State too large for localStorage.");
|
|
438
462
|
this.onError?.(e instanceof Error ? e : new Error(String(e)));
|
|
463
|
+
} finally {
|
|
464
|
+
this.saving = false;
|
|
465
|
+
if (this.pendingSave) {
|
|
466
|
+
this.pendingSave = false;
|
|
467
|
+
void this.save();
|
|
468
|
+
}
|
|
439
469
|
}
|
|
440
470
|
}
|
|
441
471
|
};
|
|
442
472
|
|
|
473
|
+
// src/core/storage/memory-adapter.ts
|
|
474
|
+
var MemoryAdapter = class {
|
|
475
|
+
store = /* @__PURE__ */ new Map();
|
|
476
|
+
async load(key) {
|
|
477
|
+
return this.store.get(key) ?? null;
|
|
478
|
+
}
|
|
479
|
+
async save(key, value) {
|
|
480
|
+
this.store.set(key, value);
|
|
481
|
+
}
|
|
482
|
+
async clear(key) {
|
|
483
|
+
this.store.delete(key);
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
|
|
487
|
+
// src/core/storage/indexeddb-adapter.ts
|
|
488
|
+
var DEFAULT_DB = "fieldnotes";
|
|
489
|
+
var DEFAULT_STORE = "state";
|
|
490
|
+
var IndexedDBAdapter = class {
|
|
491
|
+
dbName;
|
|
492
|
+
storeName;
|
|
493
|
+
idb;
|
|
494
|
+
dbPromise = null;
|
|
495
|
+
constructor(options = {}) {
|
|
496
|
+
this.dbName = options.dbName ?? DEFAULT_DB;
|
|
497
|
+
this.storeName = options.storeName ?? DEFAULT_STORE;
|
|
498
|
+
this.idb = options.indexedDB ?? (typeof indexedDB !== "undefined" ? indexedDB : null);
|
|
499
|
+
}
|
|
500
|
+
open() {
|
|
501
|
+
const idb = this.idb;
|
|
502
|
+
if (!idb) return Promise.reject(new Error("IndexedDB unavailable"));
|
|
503
|
+
if (!this.dbPromise) {
|
|
504
|
+
const storeName = this.storeName;
|
|
505
|
+
this.dbPromise = new Promise((resolve, reject) => {
|
|
506
|
+
const req = idb.open(this.dbName, 1);
|
|
507
|
+
req.onupgradeneeded = () => {
|
|
508
|
+
const db = req.result;
|
|
509
|
+
if (!db.objectStoreNames.contains(storeName)) db.createObjectStore(storeName);
|
|
510
|
+
};
|
|
511
|
+
req.onsuccess = () => resolve(req.result);
|
|
512
|
+
req.onerror = () => reject(req.error ?? new Error("IndexedDB open failed"));
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
return this.dbPromise;
|
|
516
|
+
}
|
|
517
|
+
async load(key) {
|
|
518
|
+
if (!this.idb) return null;
|
|
519
|
+
const db = await this.open();
|
|
520
|
+
return new Promise((resolve, reject) => {
|
|
521
|
+
const req = db.transaction(this.storeName, "readonly").objectStore(this.storeName).get(key);
|
|
522
|
+
req.onsuccess = () => {
|
|
523
|
+
const v = req.result;
|
|
524
|
+
resolve(typeof v === "string" ? v : null);
|
|
525
|
+
};
|
|
526
|
+
req.onerror = () => reject(req.error ?? new Error("IndexedDB read failed"));
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
async save(key, value) {
|
|
530
|
+
if (!this.idb) return;
|
|
531
|
+
const db = await this.open();
|
|
532
|
+
return new Promise((resolve, reject) => {
|
|
533
|
+
const tx = db.transaction(this.storeName, "readwrite");
|
|
534
|
+
tx.objectStore(this.storeName).put(value, key);
|
|
535
|
+
tx.oncomplete = () => resolve();
|
|
536
|
+
tx.onerror = () => reject(tx.error ?? new Error("IndexedDB write failed"));
|
|
537
|
+
tx.onabort = () => reject(tx.error ?? new Error("IndexedDB write aborted"));
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
async clear(key) {
|
|
541
|
+
if (!this.idb) return;
|
|
542
|
+
const db = await this.open();
|
|
543
|
+
return new Promise((resolve, reject) => {
|
|
544
|
+
const tx = db.transaction(this.storeName, "readwrite");
|
|
545
|
+
tx.objectStore(this.storeName).delete(key);
|
|
546
|
+
tx.oncomplete = () => resolve();
|
|
547
|
+
tx.onerror = () => reject(tx.error ?? new Error("IndexedDB delete failed"));
|
|
548
|
+
tx.onabort = () => reject(tx.error ?? new Error("IndexedDB delete aborted"));
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
|
|
443
553
|
// src/canvas/camera.ts
|
|
444
554
|
var DEFAULT_MIN_ZOOM = 0.1;
|
|
445
555
|
var DEFAULT_MAX_ZOOM = 10;
|
|
@@ -3204,7 +3314,7 @@ function drawHexPath(ctx, cx, cy, cellSize, orientation) {
|
|
|
3204
3314
|
// src/elements/renderers/template-renderer.ts
|
|
3205
3315
|
function renderTemplate(ctx, template, store) {
|
|
3206
3316
|
const grid = store?.getElementsByType("grid")[0];
|
|
3207
|
-
if (grid && grid.gridType === "hex") {
|
|
3317
|
+
if (grid && grid.gridType === "hex" && template.renderStyle !== "geometric") {
|
|
3208
3318
|
renderHexTemplate(ctx, template, grid.cellSize, grid.hexOrientation);
|
|
3209
3319
|
return;
|
|
3210
3320
|
}
|
|
@@ -3880,7 +3990,8 @@ function createTemplate(input) {
|
|
|
3880
3990
|
strokeWidth: input.strokeWidth ?? 2,
|
|
3881
3991
|
opacity: input.opacity ?? 0.6,
|
|
3882
3992
|
feetPerCell: input.feetPerCell,
|
|
3883
|
-
radiusFeet: input.radiusFeet
|
|
3993
|
+
radiusFeet: input.radiusFeet,
|
|
3994
|
+
...input.renderStyle !== void 0 ? { renderStyle: input.renderStyle } : {}
|
|
3884
3995
|
};
|
|
3885
3996
|
}
|
|
3886
3997
|
|
|
@@ -9695,6 +9806,7 @@ var TemplateTool = class {
|
|
|
9695
9806
|
strokeWidth;
|
|
9696
9807
|
opacity;
|
|
9697
9808
|
feetPerCell;
|
|
9809
|
+
renderStyle;
|
|
9698
9810
|
optionListeners = /* @__PURE__ */ new Set();
|
|
9699
9811
|
constructor(options = {}) {
|
|
9700
9812
|
this.templateShape = options.templateShape ?? "circle";
|
|
@@ -9703,6 +9815,7 @@ var TemplateTool = class {
|
|
|
9703
9815
|
this.strokeWidth = options.strokeWidth ?? 2;
|
|
9704
9816
|
this.opacity = options.opacity ?? 0.6;
|
|
9705
9817
|
this.feetPerCell = options.feetPerCell ?? 5;
|
|
9818
|
+
this.renderStyle = options.renderStyle ?? "cells";
|
|
9706
9819
|
}
|
|
9707
9820
|
getOptions() {
|
|
9708
9821
|
return {
|
|
@@ -9711,7 +9824,8 @@ var TemplateTool = class {
|
|
|
9711
9824
|
strokeColor: this.strokeColor,
|
|
9712
9825
|
strokeWidth: this.strokeWidth,
|
|
9713
9826
|
opacity: this.opacity,
|
|
9714
|
-
feetPerCell: this.feetPerCell
|
|
9827
|
+
feetPerCell: this.feetPerCell,
|
|
9828
|
+
renderStyle: this.renderStyle
|
|
9715
9829
|
};
|
|
9716
9830
|
}
|
|
9717
9831
|
setOptions(options) {
|
|
@@ -9721,6 +9835,7 @@ var TemplateTool = class {
|
|
|
9721
9835
|
if (options.strokeWidth !== void 0) this.strokeWidth = options.strokeWidth;
|
|
9722
9836
|
if (options.opacity !== void 0) this.opacity = options.opacity;
|
|
9723
9837
|
if (options.feetPerCell !== void 0) this.feetPerCell = options.feetPerCell;
|
|
9838
|
+
if (options.renderStyle !== void 0) this.renderStyle = options.renderStyle;
|
|
9724
9839
|
this.notifyOptionsChange();
|
|
9725
9840
|
}
|
|
9726
9841
|
onOptionsChange(listener) {
|
|
@@ -9763,6 +9878,7 @@ var TemplateTool = class {
|
|
|
9763
9878
|
opacity: this.opacity,
|
|
9764
9879
|
feetPerCell: this.feetPerCell,
|
|
9765
9880
|
radiusFeet: radiusFeet > 0 ? radiusFeet : void 0,
|
|
9881
|
+
renderStyle: this.renderStyle,
|
|
9766
9882
|
layerId: ctx.activeLayerId ?? ""
|
|
9767
9883
|
});
|
|
9768
9884
|
ctx.store.add(element);
|
|
@@ -9778,7 +9894,7 @@ var TemplateTool = class {
|
|
|
9778
9894
|
if (!this.drawing) return;
|
|
9779
9895
|
const radius = this.computeRadius();
|
|
9780
9896
|
if (radius <= 0) return;
|
|
9781
|
-
if (this.gridType === "hex" && this.hexOrientation) {
|
|
9897
|
+
if (this.gridType === "hex" && this.hexOrientation && this.renderStyle !== "geometric") {
|
|
9782
9898
|
this.renderHexOverlay(ctx, radius);
|
|
9783
9899
|
return;
|
|
9784
9900
|
}
|
|
@@ -10051,7 +10167,7 @@ var LaserTool = class {
|
|
|
10051
10167
|
};
|
|
10052
10168
|
|
|
10053
10169
|
// src/index.ts
|
|
10054
|
-
var VERSION = "0.
|
|
10170
|
+
var VERSION = "0.45.0";
|
|
10055
10171
|
// Annotate the CommonJS export names for ESM import in node:
|
|
10056
10172
|
0 && (module.exports = {
|
|
10057
10173
|
ArrowTool,
|
|
@@ -10063,9 +10179,12 @@ var VERSION = "0.43.0";
|
|
|
10063
10179
|
HandTool,
|
|
10064
10180
|
HistoryStack,
|
|
10065
10181
|
ImageTool,
|
|
10182
|
+
IndexedDBAdapter,
|
|
10066
10183
|
LaserTool,
|
|
10067
10184
|
LayerManager,
|
|
10185
|
+
LocalStorageAdapter,
|
|
10068
10186
|
MeasureTool,
|
|
10187
|
+
MemoryAdapter,
|
|
10069
10188
|
NoteTool,
|
|
10070
10189
|
PencilTool,
|
|
10071
10190
|
SelectTool,
|