@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.d.cts CHANGED
@@ -108,6 +108,7 @@ interface GridElement extends BaseElement {
108
108
  opacity: number;
109
109
  }
110
110
  type TemplateShape = 'circle' | 'cone' | 'line' | 'square';
111
+ type TemplateRenderStyle = 'cells' | 'geometric';
111
112
  interface TemplateElement extends BaseElement {
112
113
  type: 'template';
113
114
  templateShape: TemplateShape;
@@ -119,6 +120,7 @@ interface TemplateElement extends BaseElement {
119
120
  opacity: number;
120
121
  feetPerCell?: number;
121
122
  radiusFeet?: number;
123
+ renderStyle?: TemplateRenderStyle;
122
124
  }
123
125
  type CanvasElement = StrokeElement | NoteElement | ArrowElement | ImageElement | HtmlElement | TextElement | ShapeElement | GridElement | TemplateElement;
124
126
  type ElementType = CanvasElement['type'];
@@ -302,10 +304,17 @@ declare class LayerManager {
302
304
  private findFallbackLayer;
303
305
  }
304
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
+
305
313
  interface AutoSaveOptions {
306
314
  key?: string;
307
315
  debounceMs?: number;
308
316
  layerManager?: LayerManager;
317
+ adapter?: StorageAdapter;
309
318
  onError?: (error: Error) => void;
310
319
  }
311
320
  declare class AutoSave {
@@ -314,19 +323,52 @@ declare class AutoSave {
314
323
  private readonly key;
315
324
  private readonly debounceMs;
316
325
  private readonly layerManager?;
326
+ private readonly adapter;
317
327
  private timerId;
318
328
  private unsubscribers;
319
329
  private readonly onError?;
330
+ private saving;
331
+ private pendingSave;
320
332
  constructor(store: ElementStore, camera: Camera, options?: AutoSaveOptions);
321
333
  start(): void;
322
334
  stop(): void;
323
- load(): CanvasState | null;
324
- clear(): void;
335
+ load(): Promise<CanvasState | null>;
336
+ clear(): Promise<void>;
325
337
  private scheduleSave;
326
338
  private cancelPending;
327
339
  private save;
328
340
  }
329
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
+
330
372
  type BackgroundPattern = 'dots' | 'grid' | 'none';
331
373
  interface BackgroundOptions {
332
374
  pattern?: BackgroundPattern;
@@ -701,6 +743,7 @@ interface TemplateInput extends BaseDefaults {
701
743
  opacity?: number;
702
744
  feetPerCell?: number;
703
745
  radiusFeet?: number;
746
+ renderStyle?: TemplateRenderStyle;
704
747
  }
705
748
  declare function createTemplate(input: TemplateInput): TemplateElement;
706
749
 
@@ -995,6 +1038,7 @@ interface TemplateToolOptions {
995
1038
  strokeWidth?: number;
996
1039
  opacity?: number;
997
1040
  feetPerCell?: number;
1041
+ renderStyle?: TemplateRenderStyle;
998
1042
  }
999
1043
  declare class TemplateTool implements Tool {
1000
1044
  readonly name = "template";
@@ -1011,6 +1055,7 @@ declare class TemplateTool implements Tool {
1011
1055
  private strokeWidth;
1012
1056
  private opacity;
1013
1057
  private feetPerCell;
1058
+ private renderStyle;
1014
1059
  private optionListeners;
1015
1060
  constructor(options?: TemplateToolOptions);
1016
1061
  getOptions(): TemplateToolOptions;
@@ -1060,6 +1105,6 @@ declare class LaserTool implements Tool {
1060
1105
  private notifyOptionsChange;
1061
1106
  }
1062
1107
 
1063
- declare const VERSION = "0.43.0";
1108
+ declare const VERSION = "0.45.0";
1064
1109
 
1065
- 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 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
@@ -108,6 +108,7 @@ interface GridElement extends BaseElement {
108
108
  opacity: number;
109
109
  }
110
110
  type TemplateShape = 'circle' | 'cone' | 'line' | 'square';
111
+ type TemplateRenderStyle = 'cells' | 'geometric';
111
112
  interface TemplateElement extends BaseElement {
112
113
  type: 'template';
113
114
  templateShape: TemplateShape;
@@ -119,6 +120,7 @@ interface TemplateElement extends BaseElement {
119
120
  opacity: number;
120
121
  feetPerCell?: number;
121
122
  radiusFeet?: number;
123
+ renderStyle?: TemplateRenderStyle;
122
124
  }
123
125
  type CanvasElement = StrokeElement | NoteElement | ArrowElement | ImageElement | HtmlElement | TextElement | ShapeElement | GridElement | TemplateElement;
124
126
  type ElementType = CanvasElement['type'];
@@ -302,10 +304,17 @@ declare class LayerManager {
302
304
  private findFallbackLayer;
303
305
  }
304
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
+
305
313
  interface AutoSaveOptions {
306
314
  key?: string;
307
315
  debounceMs?: number;
308
316
  layerManager?: LayerManager;
317
+ adapter?: StorageAdapter;
309
318
  onError?: (error: Error) => void;
310
319
  }
311
320
  declare class AutoSave {
@@ -314,19 +323,52 @@ declare class AutoSave {
314
323
  private readonly key;
315
324
  private readonly debounceMs;
316
325
  private readonly layerManager?;
326
+ private readonly adapter;
317
327
  private timerId;
318
328
  private unsubscribers;
319
329
  private readonly onError?;
330
+ private saving;
331
+ private pendingSave;
320
332
  constructor(store: ElementStore, camera: Camera, options?: AutoSaveOptions);
321
333
  start(): void;
322
334
  stop(): void;
323
- load(): CanvasState | null;
324
- clear(): void;
335
+ load(): Promise<CanvasState | null>;
336
+ clear(): Promise<void>;
325
337
  private scheduleSave;
326
338
  private cancelPending;
327
339
  private save;
328
340
  }
329
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
+
330
372
  type BackgroundPattern = 'dots' | 'grid' | 'none';
331
373
  interface BackgroundOptions {
332
374
  pattern?: BackgroundPattern;
@@ -701,6 +743,7 @@ interface TemplateInput extends BaseDefaults {
701
743
  opacity?: number;
702
744
  feetPerCell?: number;
703
745
  radiusFeet?: number;
746
+ renderStyle?: TemplateRenderStyle;
704
747
  }
705
748
  declare function createTemplate(input: TemplateInput): TemplateElement;
706
749
 
@@ -995,6 +1038,7 @@ interface TemplateToolOptions {
995
1038
  strokeWidth?: number;
996
1039
  opacity?: number;
997
1040
  feetPerCell?: number;
1041
+ renderStyle?: TemplateRenderStyle;
998
1042
  }
999
1043
  declare class TemplateTool implements Tool {
1000
1044
  readonly name = "template";
@@ -1011,6 +1055,7 @@ declare class TemplateTool implements Tool {
1011
1055
  private strokeWidth;
1012
1056
  private opacity;
1013
1057
  private feetPerCell;
1058
+ private renderStyle;
1014
1059
  private optionListeners;
1015
1060
  constructor(options?: TemplateToolOptions);
1016
1061
  getOptions(): TemplateToolOptions;
@@ -1060,6 +1105,6 @@ declare class LaserTool implements Tool {
1060
1105
  private notifyOptionsChange;
1061
1106
  }
1062
1107
 
1063
- declare const VERSION = "0.43.0";
1108
+ declare const VERSION = "0.45.0";
1064
1109
 
1065
- 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 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,19 +362,108 @@ 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
+ }
356
383
  }
357
384
  }
358
385
  };
359
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
+ });
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
+ });
464
+ }
465
+ };
466
+
360
467
  // src/canvas/camera.ts
361
468
  var DEFAULT_MIN_ZOOM = 0.1;
362
469
  var DEFAULT_MAX_ZOOM = 10;
@@ -3121,7 +3228,7 @@ function drawHexPath(ctx, cx, cy, cellSize, orientation) {
3121
3228
  // src/elements/renderers/template-renderer.ts
3122
3229
  function renderTemplate(ctx, template, store) {
3123
3230
  const grid = store?.getElementsByType("grid")[0];
3124
- if (grid && grid.gridType === "hex") {
3231
+ if (grid && grid.gridType === "hex" && template.renderStyle !== "geometric") {
3125
3232
  renderHexTemplate(ctx, template, grid.cellSize, grid.hexOrientation);
3126
3233
  return;
3127
3234
  }
@@ -3797,7 +3904,8 @@ function createTemplate(input) {
3797
3904
  strokeWidth: input.strokeWidth ?? 2,
3798
3905
  opacity: input.opacity ?? 0.6,
3799
3906
  feetPerCell: input.feetPerCell,
3800
- radiusFeet: input.radiusFeet
3907
+ radiusFeet: input.radiusFeet,
3908
+ ...input.renderStyle !== void 0 ? { renderStyle: input.renderStyle } : {}
3801
3909
  };
3802
3910
  }
3803
3911
 
@@ -9612,6 +9720,7 @@ var TemplateTool = class {
9612
9720
  strokeWidth;
9613
9721
  opacity;
9614
9722
  feetPerCell;
9723
+ renderStyle;
9615
9724
  optionListeners = /* @__PURE__ */ new Set();
9616
9725
  constructor(options = {}) {
9617
9726
  this.templateShape = options.templateShape ?? "circle";
@@ -9620,6 +9729,7 @@ var TemplateTool = class {
9620
9729
  this.strokeWidth = options.strokeWidth ?? 2;
9621
9730
  this.opacity = options.opacity ?? 0.6;
9622
9731
  this.feetPerCell = options.feetPerCell ?? 5;
9732
+ this.renderStyle = options.renderStyle ?? "cells";
9623
9733
  }
9624
9734
  getOptions() {
9625
9735
  return {
@@ -9628,7 +9738,8 @@ var TemplateTool = class {
9628
9738
  strokeColor: this.strokeColor,
9629
9739
  strokeWidth: this.strokeWidth,
9630
9740
  opacity: this.opacity,
9631
- feetPerCell: this.feetPerCell
9741
+ feetPerCell: this.feetPerCell,
9742
+ renderStyle: this.renderStyle
9632
9743
  };
9633
9744
  }
9634
9745
  setOptions(options) {
@@ -9638,6 +9749,7 @@ var TemplateTool = class {
9638
9749
  if (options.strokeWidth !== void 0) this.strokeWidth = options.strokeWidth;
9639
9750
  if (options.opacity !== void 0) this.opacity = options.opacity;
9640
9751
  if (options.feetPerCell !== void 0) this.feetPerCell = options.feetPerCell;
9752
+ if (options.renderStyle !== void 0) this.renderStyle = options.renderStyle;
9641
9753
  this.notifyOptionsChange();
9642
9754
  }
9643
9755
  onOptionsChange(listener) {
@@ -9680,6 +9792,7 @@ var TemplateTool = class {
9680
9792
  opacity: this.opacity,
9681
9793
  feetPerCell: this.feetPerCell,
9682
9794
  radiusFeet: radiusFeet > 0 ? radiusFeet : void 0,
9795
+ renderStyle: this.renderStyle,
9683
9796
  layerId: ctx.activeLayerId ?? ""
9684
9797
  });
9685
9798
  ctx.store.add(element);
@@ -9695,7 +9808,7 @@ var TemplateTool = class {
9695
9808
  if (!this.drawing) return;
9696
9809
  const radius = this.computeRadius();
9697
9810
  if (radius <= 0) return;
9698
- if (this.gridType === "hex" && this.hexOrientation) {
9811
+ if (this.gridType === "hex" && this.hexOrientation && this.renderStyle !== "geometric") {
9699
9812
  this.renderHexOverlay(ctx, radius);
9700
9813
  return;
9701
9814
  }
@@ -9968,7 +10081,7 @@ var LaserTool = class {
9968
10081
  };
9969
10082
 
9970
10083
  // src/index.ts
9971
- var VERSION = "0.43.0";
10084
+ var VERSION = "0.45.0";
9972
10085
  export {
9973
10086
  ArrowTool,
9974
10087
  AutoSave,
@@ -9979,9 +10092,12 @@ export {
9979
10092
  HandTool,
9980
10093
  HistoryStack,
9981
10094
  ImageTool,
10095
+ IndexedDBAdapter,
9982
10096
  LaserTool,
9983
10097
  LayerManager,
10098
+ LocalStorageAdapter,
9984
10099
  MeasureTool,
10100
+ MemoryAdapter,
9985
10101
  NoteTool,
9986
10102
  PencilTool,
9987
10103
  SelectTool,