@fieldnotes/core 0.1.2 → 0.2.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
@@ -73,6 +73,34 @@ declare function exportState(elements: CanvasElement[], camera: {
73
73
  }): CanvasState;
74
74
  declare function parseState(json: string): CanvasState;
75
75
 
76
+ interface ElementUpdateEvent {
77
+ previous: CanvasElement;
78
+ current: CanvasElement;
79
+ }
80
+ interface ElementStoreEvents {
81
+ add: CanvasElement;
82
+ remove: CanvasElement;
83
+ update: ElementUpdateEvent;
84
+ clear: null;
85
+ }
86
+ declare class ElementStore {
87
+ private elements;
88
+ private bus;
89
+ get count(): number;
90
+ getAll(): CanvasElement[];
91
+ getById(id: string): CanvasElement | undefined;
92
+ getElementsByType<T extends ElementType>(type: T): Extract<CanvasElement, {
93
+ type: T;
94
+ }>[];
95
+ add(element: CanvasElement): void;
96
+ update(id: string, partial: Partial<CanvasElement>): void;
97
+ remove(id: string): void;
98
+ clear(): void;
99
+ snapshot(): CanvasElement[];
100
+ loadSnapshot(elements: CanvasElement[]): void;
101
+ on<K extends keyof ElementStoreEvents>(event: K, listener: (data: ElementStoreEvents[K]) => void): () => void;
102
+ }
103
+
76
104
  interface CameraOptions {
77
105
  minZoom?: number;
78
106
  maxZoom?: number;
@@ -98,6 +126,27 @@ declare class Camera {
98
126
  private notifyChange;
99
127
  }
100
128
 
129
+ interface AutoSaveOptions {
130
+ key?: string;
131
+ debounceMs?: number;
132
+ }
133
+ declare class AutoSave {
134
+ private readonly store;
135
+ private readonly camera;
136
+ private readonly key;
137
+ private readonly debounceMs;
138
+ private timerId;
139
+ private unsubscribers;
140
+ constructor(store: ElementStore, camera: Camera, options?: AutoSaveOptions);
141
+ start(): void;
142
+ stop(): void;
143
+ load(): CanvasState | null;
144
+ clear(): void;
145
+ private scheduleSave;
146
+ private cancelPending;
147
+ private save;
148
+ }
149
+
101
150
  type BackgroundPattern = 'dots' | 'grid' | 'none';
102
151
  interface BackgroundOptions {
103
152
  pattern?: BackgroundPattern;
@@ -119,34 +168,6 @@ declare class Background {
119
168
  private renderGrid;
120
169
  }
121
170
 
122
- interface ElementUpdateEvent {
123
- previous: CanvasElement;
124
- current: CanvasElement;
125
- }
126
- interface ElementStoreEvents {
127
- add: CanvasElement;
128
- remove: CanvasElement;
129
- update: ElementUpdateEvent;
130
- clear: null;
131
- }
132
- declare class ElementStore {
133
- private elements;
134
- private bus;
135
- get count(): number;
136
- getAll(): CanvasElement[];
137
- getById(id: string): CanvasElement | undefined;
138
- getElementsByType<T extends ElementType>(type: T): Extract<CanvasElement, {
139
- type: T;
140
- }>[];
141
- add(element: CanvasElement): void;
142
- update(id: string, partial: Partial<CanvasElement>): void;
143
- remove(id: string): void;
144
- clear(): void;
145
- snapshot(): CanvasElement[];
146
- loadSnapshot(elements: CanvasElement[]): void;
147
- on<K extends keyof ElementStoreEvents>(event: K, listener: (data: ElementStoreEvents[K]) => void): () => void;
148
- }
149
-
150
171
  interface ToolContext {
151
172
  camera: Camera;
152
173
  store: ElementStore;
@@ -580,4 +601,4 @@ declare class ImageTool implements Tool {
580
601
 
581
602
  declare const VERSION = "0.1.2";
582
603
 
583
- export { AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Bounds, Camera, type CameraOptions, type CanvasElement, type CanvasState, type Command, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, HandTool, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, NoteEditor, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, RemoveElementCommand, SelectTool, type Size, type StrokeElement, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, VERSION, Viewport, type ViewportOptions, createArrow, createHtmlElement, createId, createImage, createNote, createStroke, exportState, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, isNearBezier, parseState };
604
+ export { AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Bounds, Camera, type CameraOptions, type CanvasElement, type CanvasState, type Command, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, HandTool, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, NoteEditor, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, RemoveElementCommand, SelectTool, type Size, type StrokeElement, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, VERSION, Viewport, type ViewportOptions, createArrow, createHtmlElement, createId, createImage, createNote, createStroke, exportState, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, isNearBezier, parseState };
package/dist/index.d.ts CHANGED
@@ -73,6 +73,34 @@ declare function exportState(elements: CanvasElement[], camera: {
73
73
  }): CanvasState;
74
74
  declare function parseState(json: string): CanvasState;
75
75
 
76
+ interface ElementUpdateEvent {
77
+ previous: CanvasElement;
78
+ current: CanvasElement;
79
+ }
80
+ interface ElementStoreEvents {
81
+ add: CanvasElement;
82
+ remove: CanvasElement;
83
+ update: ElementUpdateEvent;
84
+ clear: null;
85
+ }
86
+ declare class ElementStore {
87
+ private elements;
88
+ private bus;
89
+ get count(): number;
90
+ getAll(): CanvasElement[];
91
+ getById(id: string): CanvasElement | undefined;
92
+ getElementsByType<T extends ElementType>(type: T): Extract<CanvasElement, {
93
+ type: T;
94
+ }>[];
95
+ add(element: CanvasElement): void;
96
+ update(id: string, partial: Partial<CanvasElement>): void;
97
+ remove(id: string): void;
98
+ clear(): void;
99
+ snapshot(): CanvasElement[];
100
+ loadSnapshot(elements: CanvasElement[]): void;
101
+ on<K extends keyof ElementStoreEvents>(event: K, listener: (data: ElementStoreEvents[K]) => void): () => void;
102
+ }
103
+
76
104
  interface CameraOptions {
77
105
  minZoom?: number;
78
106
  maxZoom?: number;
@@ -98,6 +126,27 @@ declare class Camera {
98
126
  private notifyChange;
99
127
  }
100
128
 
129
+ interface AutoSaveOptions {
130
+ key?: string;
131
+ debounceMs?: number;
132
+ }
133
+ declare class AutoSave {
134
+ private readonly store;
135
+ private readonly camera;
136
+ private readonly key;
137
+ private readonly debounceMs;
138
+ private timerId;
139
+ private unsubscribers;
140
+ constructor(store: ElementStore, camera: Camera, options?: AutoSaveOptions);
141
+ start(): void;
142
+ stop(): void;
143
+ load(): CanvasState | null;
144
+ clear(): void;
145
+ private scheduleSave;
146
+ private cancelPending;
147
+ private save;
148
+ }
149
+
101
150
  type BackgroundPattern = 'dots' | 'grid' | 'none';
102
151
  interface BackgroundOptions {
103
152
  pattern?: BackgroundPattern;
@@ -119,34 +168,6 @@ declare class Background {
119
168
  private renderGrid;
120
169
  }
121
170
 
122
- interface ElementUpdateEvent {
123
- previous: CanvasElement;
124
- current: CanvasElement;
125
- }
126
- interface ElementStoreEvents {
127
- add: CanvasElement;
128
- remove: CanvasElement;
129
- update: ElementUpdateEvent;
130
- clear: null;
131
- }
132
- declare class ElementStore {
133
- private elements;
134
- private bus;
135
- get count(): number;
136
- getAll(): CanvasElement[];
137
- getById(id: string): CanvasElement | undefined;
138
- getElementsByType<T extends ElementType>(type: T): Extract<CanvasElement, {
139
- type: T;
140
- }>[];
141
- add(element: CanvasElement): void;
142
- update(id: string, partial: Partial<CanvasElement>): void;
143
- remove(id: string): void;
144
- clear(): void;
145
- snapshot(): CanvasElement[];
146
- loadSnapshot(elements: CanvasElement[]): void;
147
- on<K extends keyof ElementStoreEvents>(event: K, listener: (data: ElementStoreEvents[K]) => void): () => void;
148
- }
149
-
150
171
  interface ToolContext {
151
172
  camera: Camera;
152
173
  store: ElementStore;
@@ -580,4 +601,4 @@ declare class ImageTool implements Tool {
580
601
 
581
602
  declare const VERSION = "0.1.2";
582
603
 
583
- export { AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Bounds, Camera, type CameraOptions, type CanvasElement, type CanvasState, type Command, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, HandTool, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, NoteEditor, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, RemoveElementCommand, SelectTool, type Size, type StrokeElement, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, VERSION, Viewport, type ViewportOptions, createArrow, createHtmlElement, createId, createImage, createNote, createStroke, exportState, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, isNearBezier, parseState };
604
+ export { AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Bounds, Camera, type CameraOptions, type CanvasElement, type CanvasState, type Command, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, HandTool, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, NoteEditor, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, RemoveElementCommand, SelectTool, type Size, type StrokeElement, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, VERSION, Viewport, type ViewportOptions, createArrow, createHtmlElement, createId, createImage, createNote, createStroke, exportState, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, isNearBezier, parseState };
package/dist/index.js CHANGED
@@ -91,6 +91,65 @@ function migrateElement(obj) {
91
91
  }
92
92
  }
93
93
 
94
+ // src/core/auto-save.ts
95
+ var DEFAULT_KEY = "fieldnotes-autosave";
96
+ var DEFAULT_DEBOUNCE_MS = 1e3;
97
+ var AutoSave = class {
98
+ constructor(store, camera, options = {}) {
99
+ this.store = store;
100
+ this.camera = camera;
101
+ this.key = options.key ?? DEFAULT_KEY;
102
+ this.debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;
103
+ }
104
+ key;
105
+ debounceMs;
106
+ timerId = null;
107
+ unsubscribers = [];
108
+ start() {
109
+ const schedule = () => this.scheduleSave();
110
+ this.unsubscribers = [
111
+ this.store.on("add", schedule),
112
+ this.store.on("remove", schedule),
113
+ this.store.on("update", schedule),
114
+ this.camera.onChange(schedule)
115
+ ];
116
+ }
117
+ stop() {
118
+ this.cancelPending();
119
+ this.unsubscribers.forEach((fn) => fn());
120
+ this.unsubscribers = [];
121
+ }
122
+ load() {
123
+ if (typeof localStorage === "undefined") return null;
124
+ const json = localStorage.getItem(this.key);
125
+ if (!json) return null;
126
+ try {
127
+ return parseState(json);
128
+ } catch {
129
+ return null;
130
+ }
131
+ }
132
+ clear() {
133
+ if (typeof localStorage === "undefined") return;
134
+ localStorage.removeItem(this.key);
135
+ }
136
+ scheduleSave() {
137
+ this.cancelPending();
138
+ this.timerId = setTimeout(() => this.save(), this.debounceMs);
139
+ }
140
+ cancelPending() {
141
+ if (this.timerId !== null) {
142
+ clearTimeout(this.timerId);
143
+ this.timerId = null;
144
+ }
145
+ }
146
+ save() {
147
+ if (typeof localStorage === "undefined") return;
148
+ const state = exportState(this.store.snapshot(), this.camera);
149
+ localStorage.setItem(this.key, JSON.stringify(state));
150
+ }
151
+ };
152
+
94
153
  // src/canvas/camera.ts
95
154
  var DEFAULT_MIN_ZOOM = 0.1;
96
155
  var DEFAULT_MAX_ZOOM = 10;
@@ -2162,6 +2221,7 @@ var VERSION = "0.1.2";
2162
2221
  export {
2163
2222
  AddElementCommand,
2164
2223
  ArrowTool,
2224
+ AutoSave,
2165
2225
  Background,
2166
2226
  BatchCommand,
2167
2227
  Camera,