@fieldnotes/core 0.44.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.d.cts CHANGED
@@ -304,10 +304,17 @@ declare class LayerManager {
304
304
  private findFallbackLayer;
305
305
  }
306
306
 
307
+ interface StorageAdapter {
308
+ load(key: string): Promise<string | null>;
309
+ save(key: string, value: string): Promise<void>;
310
+ clear(key: string): Promise<void>;
311
+ }
312
+
307
313
  interface AutoSaveOptions {
308
314
  key?: string;
309
315
  debounceMs?: number;
310
316
  layerManager?: LayerManager;
317
+ adapter?: StorageAdapter;
311
318
  onError?: (error: Error) => void;
312
319
  }
313
320
  declare class AutoSave {
@@ -316,19 +323,52 @@ declare class AutoSave {
316
323
  private readonly key;
317
324
  private readonly debounceMs;
318
325
  private readonly layerManager?;
326
+ private readonly adapter;
319
327
  private timerId;
320
328
  private unsubscribers;
321
329
  private readonly onError?;
330
+ private saving;
331
+ private pendingSave;
322
332
  constructor(store: ElementStore, camera: Camera, options?: AutoSaveOptions);
323
333
  start(): void;
324
334
  stop(): void;
325
- load(): CanvasState | null;
326
- clear(): void;
335
+ load(): Promise<CanvasState | null>;
336
+ clear(): Promise<void>;
327
337
  private scheduleSave;
328
338
  private cancelPending;
329
339
  private save;
330
340
  }
331
341
 
342
+ declare class MemoryAdapter implements StorageAdapter {
343
+ private store;
344
+ load(key: string): Promise<string | null>;
345
+ save(key: string, value: string): Promise<void>;
346
+ clear(key: string): Promise<void>;
347
+ }
348
+
349
+ declare class LocalStorageAdapter implements StorageAdapter {
350
+ load(key: string): Promise<string | null>;
351
+ save(key: string, value: string): Promise<void>;
352
+ clear(key: string): Promise<void>;
353
+ }
354
+
355
+ interface IndexedDBAdapterOptions {
356
+ dbName?: string;
357
+ storeName?: string;
358
+ indexedDB?: IDBFactory;
359
+ }
360
+ declare class IndexedDBAdapter implements StorageAdapter {
361
+ private readonly dbName;
362
+ private readonly storeName;
363
+ private readonly idb;
364
+ private dbPromise;
365
+ constructor(options?: IndexedDBAdapterOptions);
366
+ private open;
367
+ load(key: string): Promise<string | null>;
368
+ save(key: string, value: string): Promise<void>;
369
+ clear(key: string): Promise<void>;
370
+ }
371
+
332
372
  type BackgroundPattern = 'dots' | 'grid' | 'none';
333
373
  interface BackgroundOptions {
334
374
  pattern?: BackgroundPattern;
@@ -1065,6 +1105,6 @@ declare class LaserTool implements Tool {
1065
1105
  private notifyOptionsChange;
1066
1106
  }
1067
1107
 
1068
- declare const VERSION = "0.44.0";
1108
+ declare const VERSION = "0.45.0";
1069
1109
 
1070
- export { type ActiveFormats, type AlignEdge, type ArrowElement, type ArrowStrokeStyle, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, type BackgroundOptions, type BackgroundPattern, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, DEFAULT_NOTE_FONT_SIZE, type DistributeAxis, ElementStore, type ElementStyle, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportImageOptions, type ExportSvgOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, LaserTool, type LaserToolOptions, type Layer, LayerManager, MeasureTool, type MeasureToolOptions, type Measurement, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, type RenderStatsSnapshot, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type ShortcutBindings, type ShortcutOptions, type ShortcutsApi, type Size, type StrokeElement, type StrokePoint, type TemplateElement, type TemplateRenderStyle, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, VERSION, Viewport, type ViewportOptions, boundsIntersect, createArrow, createGrid, createHtmlElement, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, exportSvg, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getElementBounds, getElementStyle, getElementsBoundingBox, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
1110
+ export { type ActiveFormats, type AlignEdge, type ArrowElement, type ArrowStrokeStyle, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, type BackgroundOptions, type BackgroundPattern, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, DEFAULT_NOTE_FONT_SIZE, type DistributeAxis, ElementStore, type ElementStyle, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportImageOptions, type ExportSvgOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, IndexedDBAdapter, type IndexedDBAdapterOptions, LaserTool, type LaserToolOptions, type Layer, LayerManager, LocalStorageAdapter, MeasureTool, type MeasureToolOptions, type Measurement, MemoryAdapter, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, type RenderStatsSnapshot, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type ShortcutBindings, type ShortcutOptions, type ShortcutsApi, type Size, type StorageAdapter, type StrokeElement, type StrokePoint, type TemplateElement, type TemplateRenderStyle, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, VERSION, Viewport, type ViewportOptions, boundsIntersect, createArrow, createGrid, createHtmlElement, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, exportSvg, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getElementBounds, getElementStyle, getElementsBoundingBox, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
package/dist/index.d.ts CHANGED
@@ -304,10 +304,17 @@ declare class LayerManager {
304
304
  private findFallbackLayer;
305
305
  }
306
306
 
307
+ interface StorageAdapter {
308
+ load(key: string): Promise<string | null>;
309
+ save(key: string, value: string): Promise<void>;
310
+ clear(key: string): Promise<void>;
311
+ }
312
+
307
313
  interface AutoSaveOptions {
308
314
  key?: string;
309
315
  debounceMs?: number;
310
316
  layerManager?: LayerManager;
317
+ adapter?: StorageAdapter;
311
318
  onError?: (error: Error) => void;
312
319
  }
313
320
  declare class AutoSave {
@@ -316,19 +323,52 @@ declare class AutoSave {
316
323
  private readonly key;
317
324
  private readonly debounceMs;
318
325
  private readonly layerManager?;
326
+ private readonly adapter;
319
327
  private timerId;
320
328
  private unsubscribers;
321
329
  private readonly onError?;
330
+ private saving;
331
+ private pendingSave;
322
332
  constructor(store: ElementStore, camera: Camera, options?: AutoSaveOptions);
323
333
  start(): void;
324
334
  stop(): void;
325
- load(): CanvasState | null;
326
- clear(): void;
335
+ load(): Promise<CanvasState | null>;
336
+ clear(): Promise<void>;
327
337
  private scheduleSave;
328
338
  private cancelPending;
329
339
  private save;
330
340
  }
331
341
 
342
+ declare class MemoryAdapter implements StorageAdapter {
343
+ private store;
344
+ load(key: string): Promise<string | null>;
345
+ save(key: string, value: string): Promise<void>;
346
+ clear(key: string): Promise<void>;
347
+ }
348
+
349
+ declare class LocalStorageAdapter implements StorageAdapter {
350
+ load(key: string): Promise<string | null>;
351
+ save(key: string, value: string): Promise<void>;
352
+ clear(key: string): Promise<void>;
353
+ }
354
+
355
+ interface IndexedDBAdapterOptions {
356
+ dbName?: string;
357
+ storeName?: string;
358
+ indexedDB?: IDBFactory;
359
+ }
360
+ declare class IndexedDBAdapter implements StorageAdapter {
361
+ private readonly dbName;
362
+ private readonly storeName;
363
+ private readonly idb;
364
+ private dbPromise;
365
+ constructor(options?: IndexedDBAdapterOptions);
366
+ private open;
367
+ load(key: string): Promise<string | null>;
368
+ save(key: string, value: string): Promise<void>;
369
+ clear(key: string): Promise<void>;
370
+ }
371
+
332
372
  type BackgroundPattern = 'dots' | 'grid' | 'none';
333
373
  interface BackgroundOptions {
334
374
  pattern?: BackgroundPattern;
@@ -1065,6 +1105,6 @@ declare class LaserTool implements Tool {
1065
1105
  private notifyOptionsChange;
1066
1106
  }
1067
1107
 
1068
- declare const VERSION = "0.44.0";
1108
+ declare const VERSION = "0.45.0";
1069
1109
 
1070
- export { type ActiveFormats, type AlignEdge, type ArrowElement, type ArrowStrokeStyle, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, type BackgroundOptions, type BackgroundPattern, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, DEFAULT_NOTE_FONT_SIZE, type DistributeAxis, ElementStore, type ElementStyle, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportImageOptions, type ExportSvgOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, LaserTool, type LaserToolOptions, type Layer, LayerManager, MeasureTool, type MeasureToolOptions, type Measurement, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, type RenderStatsSnapshot, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type ShortcutBindings, type ShortcutOptions, type ShortcutsApi, type Size, type StrokeElement, type StrokePoint, type TemplateElement, type TemplateRenderStyle, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, VERSION, Viewport, type ViewportOptions, boundsIntersect, createArrow, createGrid, createHtmlElement, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, exportSvg, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getElementBounds, getElementStyle, getElementsBoundingBox, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
1110
+ export { type ActiveFormats, type AlignEdge, type ArrowElement, type ArrowStrokeStyle, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, type BackgroundOptions, type BackgroundPattern, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, DEFAULT_NOTE_FONT_SIZE, type DistributeAxis, ElementStore, type ElementStyle, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportImageOptions, type ExportSvgOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, IndexedDBAdapter, type IndexedDBAdapterOptions, LaserTool, type LaserToolOptions, type Layer, LayerManager, LocalStorageAdapter, MeasureTool, type MeasureToolOptions, type Measurement, MemoryAdapter, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, type RenderStatsSnapshot, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type ShortcutBindings, type ShortcutOptions, type ShortcutsApi, type Size, type StorageAdapter, type StrokeElement, type StrokePoint, type TemplateElement, type TemplateRenderStyle, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, VERSION, Viewport, type ViewportOptions, boundsIntersect, createArrow, createGrid, createHtmlElement, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, exportSvg, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getElementBounds, getElementStyle, getElementsBoundingBox, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
package/dist/index.js CHANGED
@@ -285,6 +285,22 @@ function migrateElement(obj) {
285
285
  }
286
286
  }
287
287
 
288
+ // src/core/storage/local-storage-adapter.ts
289
+ var LocalStorageAdapter = class {
290
+ async load(key) {
291
+ if (typeof localStorage === "undefined") return null;
292
+ return localStorage.getItem(key);
293
+ }
294
+ async save(key, value) {
295
+ if (typeof localStorage === "undefined") return;
296
+ localStorage.setItem(key, value);
297
+ }
298
+ async clear(key) {
299
+ if (typeof localStorage === "undefined") return;
300
+ localStorage.removeItem(key);
301
+ }
302
+ };
303
+
288
304
  // src/core/auto-save.ts
289
305
  var DEFAULT_KEY = "fieldnotes-autosave";
290
306
  var DEFAULT_DEBOUNCE_MS = 1e3;
@@ -295,14 +311,18 @@ var AutoSave = class {
295
311
  this.key = options.key ?? DEFAULT_KEY;
296
312
  this.debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;
297
313
  this.layerManager = options.layerManager;
314
+ this.adapter = options.adapter ?? new LocalStorageAdapter();
298
315
  this.onError = options.onError;
299
316
  }
300
317
  key;
301
318
  debounceMs;
302
319
  layerManager;
320
+ adapter;
303
321
  timerId = null;
304
322
  unsubscribers = [];
305
323
  onError;
324
+ saving = false;
325
+ pendingSave = false;
306
326
  start() {
307
327
  const schedule = () => this.scheduleSave();
308
328
  this.unsubscribers = [
@@ -320,9 +340,8 @@ var AutoSave = class {
320
340
  this.unsubscribers.forEach((fn) => fn());
321
341
  this.unsubscribers = [];
322
342
  }
323
- load() {
324
- if (typeof localStorage === "undefined") return null;
325
- const json = localStorage.getItem(this.key);
343
+ async load() {
344
+ const json = await this.adapter.load(this.key);
326
345
  if (!json) return null;
327
346
  try {
328
347
  return parseState(json);
@@ -330,13 +349,12 @@ var AutoSave = class {
330
349
  return null;
331
350
  }
332
351
  }
333
- clear() {
334
- if (typeof localStorage === "undefined") return;
335
- localStorage.removeItem(this.key);
352
+ async clear() {
353
+ await this.adapter.clear(this.key);
336
354
  }
337
355
  scheduleSave() {
338
356
  this.cancelPending();
339
- this.timerId = setTimeout(() => this.save(), this.debounceMs);
357
+ this.timerId = setTimeout(() => void this.save(), this.debounceMs);
340
358
  }
341
359
  cancelPending() {
342
360
  if (this.timerId !== null) {
@@ -344,16 +362,105 @@ var AutoSave = class {
344
362
  this.timerId = null;
345
363
  }
346
364
  }
347
- save() {
348
- if (typeof localStorage === "undefined") return;
349
- const layers = this.layerManager?.snapshot() ?? [];
350
- const state = exportState(this.store.snapshot(), this.camera, layers);
365
+ async save() {
366
+ if (this.saving) {
367
+ this.pendingSave = true;
368
+ return;
369
+ }
370
+ this.saving = true;
351
371
  try {
352
- localStorage.setItem(this.key, JSON.stringify(state));
372
+ const layers = this.layerManager?.snapshot() ?? [];
373
+ const state = exportState(this.store.snapshot(), this.camera, layers);
374
+ await this.adapter.save(this.key, JSON.stringify(state));
353
375
  } catch (e) {
354
- console.warn("Auto-save failed: storage quota exceeded. State too large for localStorage.");
355
376
  this.onError?.(e instanceof Error ? e : new Error(String(e)));
377
+ } finally {
378
+ this.saving = false;
379
+ if (this.pendingSave) {
380
+ this.pendingSave = false;
381
+ void this.save();
382
+ }
383
+ }
384
+ }
385
+ };
386
+
387
+ // src/core/storage/memory-adapter.ts
388
+ var MemoryAdapter = class {
389
+ store = /* @__PURE__ */ new Map();
390
+ async load(key) {
391
+ return this.store.get(key) ?? null;
392
+ }
393
+ async save(key, value) {
394
+ this.store.set(key, value);
395
+ }
396
+ async clear(key) {
397
+ this.store.delete(key);
398
+ }
399
+ };
400
+
401
+ // src/core/storage/indexeddb-adapter.ts
402
+ var DEFAULT_DB = "fieldnotes";
403
+ var DEFAULT_STORE = "state";
404
+ var IndexedDBAdapter = class {
405
+ dbName;
406
+ storeName;
407
+ idb;
408
+ dbPromise = null;
409
+ constructor(options = {}) {
410
+ this.dbName = options.dbName ?? DEFAULT_DB;
411
+ this.storeName = options.storeName ?? DEFAULT_STORE;
412
+ this.idb = options.indexedDB ?? (typeof indexedDB !== "undefined" ? indexedDB : null);
413
+ }
414
+ open() {
415
+ const idb = this.idb;
416
+ if (!idb) return Promise.reject(new Error("IndexedDB unavailable"));
417
+ if (!this.dbPromise) {
418
+ const storeName = this.storeName;
419
+ this.dbPromise = new Promise((resolve, reject) => {
420
+ const req = idb.open(this.dbName, 1);
421
+ req.onupgradeneeded = () => {
422
+ const db = req.result;
423
+ if (!db.objectStoreNames.contains(storeName)) db.createObjectStore(storeName);
424
+ };
425
+ req.onsuccess = () => resolve(req.result);
426
+ req.onerror = () => reject(req.error ?? new Error("IndexedDB open failed"));
427
+ });
356
428
  }
429
+ return this.dbPromise;
430
+ }
431
+ async load(key) {
432
+ if (!this.idb) return null;
433
+ const db = await this.open();
434
+ return new Promise((resolve, reject) => {
435
+ const req = db.transaction(this.storeName, "readonly").objectStore(this.storeName).get(key);
436
+ req.onsuccess = () => {
437
+ const v = req.result;
438
+ resolve(typeof v === "string" ? v : null);
439
+ };
440
+ req.onerror = () => reject(req.error ?? new Error("IndexedDB read failed"));
441
+ });
442
+ }
443
+ async save(key, value) {
444
+ if (!this.idb) return;
445
+ const db = await this.open();
446
+ return new Promise((resolve, reject) => {
447
+ const tx = db.transaction(this.storeName, "readwrite");
448
+ tx.objectStore(this.storeName).put(value, key);
449
+ tx.oncomplete = () => resolve();
450
+ tx.onerror = () => reject(tx.error ?? new Error("IndexedDB write failed"));
451
+ tx.onabort = () => reject(tx.error ?? new Error("IndexedDB write aborted"));
452
+ });
453
+ }
454
+ async clear(key) {
455
+ if (!this.idb) return;
456
+ const db = await this.open();
457
+ return new Promise((resolve, reject) => {
458
+ const tx = db.transaction(this.storeName, "readwrite");
459
+ tx.objectStore(this.storeName).delete(key);
460
+ tx.oncomplete = () => resolve();
461
+ tx.onerror = () => reject(tx.error ?? new Error("IndexedDB delete failed"));
462
+ tx.onabort = () => reject(tx.error ?? new Error("IndexedDB delete aborted"));
463
+ });
357
464
  }
358
465
  };
359
466
 
@@ -9974,7 +10081,7 @@ var LaserTool = class {
9974
10081
  };
9975
10082
 
9976
10083
  // src/index.ts
9977
- var VERSION = "0.44.0";
10084
+ var VERSION = "0.45.0";
9978
10085
  export {
9979
10086
  ArrowTool,
9980
10087
  AutoSave,
@@ -9985,9 +10092,12 @@ export {
9985
10092
  HandTool,
9986
10093
  HistoryStack,
9987
10094
  ImageTool,
10095
+ IndexedDBAdapter,
9988
10096
  LaserTool,
9989
10097
  LayerManager,
10098
+ LocalStorageAdapter,
9990
10099
  MeasureTool,
10100
+ MemoryAdapter,
9991
10101
  NoteTool,
9992
10102
  PencilTool,
9993
10103
  SelectTool,