@fieldnotes/core 0.26.0 → 0.27.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
@@ -394,6 +394,16 @@ interface RenderStatsSnapshot {
394
394
  frameCount: number;
395
395
  }
396
396
 
397
+ interface ElementStyle {
398
+ color?: string;
399
+ fillColor?: string;
400
+ strokeWidth?: number;
401
+ opacity?: number;
402
+ fontSize?: number;
403
+ }
404
+ declare function styleToPatch(element: CanvasElement, style: ElementStyle): Partial<CanvasElement>;
405
+ declare function getElementStyle(element: CanvasElement): ElementStyle;
406
+
397
407
  interface GridInfo {
398
408
  gridType: 'square' | 'hex';
399
409
  hexOrientation: 'pointy' | 'flat';
@@ -494,6 +504,11 @@ declare class Viewport {
494
504
  removeGrid(): void;
495
505
  getGridInfo(): GridInfo | null;
496
506
  onGridChange(listener: (info: GridInfo | null) => void): () => void;
507
+ private getSelectTool;
508
+ getSelectedIds(): string[];
509
+ onSelectionChange(listener: () => void): () => void;
510
+ getSelectionStyle(): ElementStyle | null;
511
+ applyStyleToSelection(style: ElementStyle): void;
497
512
  getRenderStats(): RenderStatsSnapshot;
498
513
  logPerformance(intervalMs?: number): () => void;
499
514
  destroy(): void;
@@ -700,6 +715,7 @@ declare class EraserTool implements Tool {
700
715
  declare class SelectTool implements Tool {
701
716
  readonly name = "select";
702
717
  private _selectedIds;
718
+ private selectionListeners;
703
719
  private mode;
704
720
  private lastWorld;
705
721
  private currentWorld;
@@ -709,6 +725,8 @@ declare class SelectTool implements Tool {
709
725
  private resizeAspectRatio;
710
726
  private hoveredId;
711
727
  get selectedIds(): string[];
728
+ onSelectionChange(listener: () => void): () => void;
729
+ private setSelectedIds;
712
730
  setSelection(ids: string[]): void;
713
731
  get isMarqueeActive(): boolean;
714
732
  onActivate(ctx: ToolContext): void;
@@ -933,6 +951,6 @@ declare class TemplateTool implements Tool {
933
951
  private notifyOptionsChange;
934
952
  }
935
953
 
936
- declare const VERSION = "0.26.0";
954
+ declare const VERSION = "0.27.0";
937
955
 
938
- export { type ActiveFormats, type ArrowElement, 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, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportImageOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, 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, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getElementBounds, getElementsBoundingBox, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
956
+ export { type ActiveFormats, type ArrowElement, 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, ElementStore, type ElementStyle, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportImageOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, 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, 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
@@ -394,6 +394,16 @@ interface RenderStatsSnapshot {
394
394
  frameCount: number;
395
395
  }
396
396
 
397
+ interface ElementStyle {
398
+ color?: string;
399
+ fillColor?: string;
400
+ strokeWidth?: number;
401
+ opacity?: number;
402
+ fontSize?: number;
403
+ }
404
+ declare function styleToPatch(element: CanvasElement, style: ElementStyle): Partial<CanvasElement>;
405
+ declare function getElementStyle(element: CanvasElement): ElementStyle;
406
+
397
407
  interface GridInfo {
398
408
  gridType: 'square' | 'hex';
399
409
  hexOrientation: 'pointy' | 'flat';
@@ -494,6 +504,11 @@ declare class Viewport {
494
504
  removeGrid(): void;
495
505
  getGridInfo(): GridInfo | null;
496
506
  onGridChange(listener: (info: GridInfo | null) => void): () => void;
507
+ private getSelectTool;
508
+ getSelectedIds(): string[];
509
+ onSelectionChange(listener: () => void): () => void;
510
+ getSelectionStyle(): ElementStyle | null;
511
+ applyStyleToSelection(style: ElementStyle): void;
497
512
  getRenderStats(): RenderStatsSnapshot;
498
513
  logPerformance(intervalMs?: number): () => void;
499
514
  destroy(): void;
@@ -700,6 +715,7 @@ declare class EraserTool implements Tool {
700
715
  declare class SelectTool implements Tool {
701
716
  readonly name = "select";
702
717
  private _selectedIds;
718
+ private selectionListeners;
703
719
  private mode;
704
720
  private lastWorld;
705
721
  private currentWorld;
@@ -709,6 +725,8 @@ declare class SelectTool implements Tool {
709
725
  private resizeAspectRatio;
710
726
  private hoveredId;
711
727
  get selectedIds(): string[];
728
+ onSelectionChange(listener: () => void): () => void;
729
+ private setSelectedIds;
712
730
  setSelection(ids: string[]): void;
713
731
  get isMarqueeActive(): boolean;
714
732
  onActivate(ctx: ToolContext): void;
@@ -933,6 +951,6 @@ declare class TemplateTool implements Tool {
933
951
  private notifyOptionsChange;
934
952
  }
935
953
 
936
- declare const VERSION = "0.26.0";
954
+ declare const VERSION = "0.27.0";
937
955
 
938
- export { type ActiveFormats, type ArrowElement, 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, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportImageOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, 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, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getElementBounds, getElementsBoundingBox, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
956
+ export { type ActiveFormats, type ArrowElement, 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, ElementStore, type ElementStyle, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportImageOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, 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, 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
@@ -5155,7 +5155,103 @@ var MarginViewport = class {
5155
5155
  }
5156
5156
  };
5157
5157
 
5158
+ // src/elements/element-style.ts
5159
+ function styleToPatch(element, style) {
5160
+ const { color, fillColor, strokeWidth, opacity, fontSize } = style;
5161
+ switch (element.type) {
5162
+ case "stroke":
5163
+ return {
5164
+ ...color !== void 0 ? { color } : {},
5165
+ ...strokeWidth !== void 0 ? { width: strokeWidth } : {},
5166
+ ...opacity !== void 0 ? { opacity } : {}
5167
+ };
5168
+ case "arrow":
5169
+ return {
5170
+ ...color !== void 0 ? { color } : {},
5171
+ ...strokeWidth !== void 0 ? { width: strokeWidth } : {}
5172
+ };
5173
+ case "shape":
5174
+ return {
5175
+ ...color !== void 0 ? { strokeColor: color } : {},
5176
+ ...fillColor !== void 0 ? { fillColor } : {},
5177
+ ...strokeWidth !== void 0 ? { strokeWidth } : {}
5178
+ };
5179
+ case "text":
5180
+ return {
5181
+ ...color !== void 0 ? { color } : {},
5182
+ ...fontSize !== void 0 ? { fontSize } : {}
5183
+ };
5184
+ case "note":
5185
+ return {
5186
+ ...color !== void 0 ? { textColor: color } : {},
5187
+ ...fillColor !== void 0 ? { backgroundColor: fillColor } : {},
5188
+ ...fontSize !== void 0 ? { fontSize } : {}
5189
+ };
5190
+ case "grid":
5191
+ return {
5192
+ ...color !== void 0 ? { strokeColor: color } : {},
5193
+ ...strokeWidth !== void 0 ? { strokeWidth } : {},
5194
+ ...opacity !== void 0 ? { opacity } : {}
5195
+ };
5196
+ case "template":
5197
+ return {
5198
+ ...color !== void 0 ? { strokeColor: color } : {},
5199
+ ...fillColor !== void 0 ? { fillColor } : {},
5200
+ ...strokeWidth !== void 0 ? { strokeWidth } : {},
5201
+ ...opacity !== void 0 ? { opacity } : {}
5202
+ };
5203
+ default:
5204
+ return {};
5205
+ }
5206
+ }
5207
+ function getElementStyle(element) {
5208
+ switch (element.type) {
5209
+ case "stroke":
5210
+ return { color: element.color, strokeWidth: element.width, opacity: element.opacity };
5211
+ case "arrow":
5212
+ return { color: element.color, strokeWidth: element.width };
5213
+ case "shape":
5214
+ return {
5215
+ color: element.strokeColor,
5216
+ fillColor: element.fillColor,
5217
+ strokeWidth: element.strokeWidth
5218
+ };
5219
+ case "text":
5220
+ return { color: element.color, fontSize: element.fontSize };
5221
+ case "note":
5222
+ return {
5223
+ color: element.textColor,
5224
+ fillColor: element.backgroundColor,
5225
+ ...element.fontSize !== void 0 ? { fontSize: element.fontSize } : {}
5226
+ };
5227
+ case "grid":
5228
+ return {
5229
+ color: element.strokeColor,
5230
+ strokeWidth: element.strokeWidth,
5231
+ opacity: element.opacity
5232
+ };
5233
+ case "template":
5234
+ return {
5235
+ color: element.strokeColor,
5236
+ fillColor: element.fillColor,
5237
+ strokeWidth: element.strokeWidth,
5238
+ opacity: element.opacity
5239
+ };
5240
+ default:
5241
+ return {};
5242
+ }
5243
+ }
5244
+
5158
5245
  // src/canvas/viewport.ts
5246
+ var EMPTY_IDS = [];
5247
+ function noop() {
5248
+ }
5249
+ function sharedValue(values) {
5250
+ const present = values.filter((v) => v !== void 0);
5251
+ if (present.length === 0) return void 0;
5252
+ const first = present[0];
5253
+ return present.every((v) => v === first) ? first : void 0;
5254
+ }
5159
5255
  var Viewport = class {
5160
5256
  constructor(container, options = {}) {
5161
5257
  this.container = container;
@@ -5507,6 +5603,52 @@ var Viewport = class {
5507
5603
  this.gridChangeListeners.delete(listener);
5508
5604
  };
5509
5605
  }
5606
+ getSelectTool() {
5607
+ return this.toolManager.getTool("select");
5608
+ }
5609
+ getSelectedIds() {
5610
+ return this.getSelectTool()?.selectedIds ?? EMPTY_IDS;
5611
+ }
5612
+ onSelectionChange(listener) {
5613
+ const tool = this.getSelectTool();
5614
+ return tool ? tool.onSelectionChange(listener) : noop;
5615
+ }
5616
+ getSelectionStyle() {
5617
+ const ids = this.getSelectedIds();
5618
+ if (ids.length === 0) return null;
5619
+ const styles = [];
5620
+ for (const id of ids) {
5621
+ const el = this.store.getById(id);
5622
+ if (el) styles.push(getElementStyle(el));
5623
+ }
5624
+ if (styles.length === 0) return null;
5625
+ const result = {};
5626
+ const color = sharedValue(styles.map((s) => s.color));
5627
+ if (color !== void 0) result.color = color;
5628
+ const fillColor = sharedValue(styles.map((s) => s.fillColor));
5629
+ if (fillColor !== void 0) result.fillColor = fillColor;
5630
+ const strokeWidth = sharedValue(styles.map((s) => s.strokeWidth));
5631
+ if (strokeWidth !== void 0) result.strokeWidth = strokeWidth;
5632
+ const opacity = sharedValue(styles.map((s) => s.opacity));
5633
+ if (opacity !== void 0) result.opacity = opacity;
5634
+ const fontSize = sharedValue(styles.map((s) => s.fontSize));
5635
+ if (fontSize !== void 0) result.fontSize = fontSize;
5636
+ return result;
5637
+ }
5638
+ applyStyleToSelection(style) {
5639
+ const ids = this.getSelectedIds();
5640
+ if (ids.length === 0) return;
5641
+ this.historyRecorder.begin();
5642
+ for (const id of ids) {
5643
+ const el = this.store.getById(id);
5644
+ if (!el) continue;
5645
+ const patch = styleToPatch(el, style);
5646
+ if (Object.keys(patch).length > 0) {
5647
+ this.store.update(id, patch);
5648
+ }
5649
+ }
5650
+ this.historyRecorder.commit();
5651
+ }
5510
5652
  getRenderStats() {
5511
5653
  return this.renderLoop.getStats();
5512
5654
  }
@@ -6122,6 +6264,7 @@ var HANDLE_CURSORS = {
6122
6264
  var SelectTool = class {
6123
6265
  name = "select";
6124
6266
  _selectedIds = [];
6267
+ selectionListeners = /* @__PURE__ */ new Set();
6125
6268
  mode = { type: "idle" };
6126
6269
  lastWorld = { x: 0, y: 0 };
6127
6270
  currentWorld = { x: 0, y: 0 };
@@ -6131,10 +6274,22 @@ var SelectTool = class {
6131
6274
  resizeAspectRatio = 0;
6132
6275
  hoveredId = null;
6133
6276
  get selectedIds() {
6134
- return [...this._selectedIds];
6277
+ return this._selectedIds;
6135
6278
  }
6136
- setSelection(ids) {
6279
+ onSelectionChange(listener) {
6280
+ this.selectionListeners.add(listener);
6281
+ return () => {
6282
+ this.selectionListeners.delete(listener);
6283
+ };
6284
+ }
6285
+ setSelectedIds(ids) {
6286
+ const prev = this._selectedIds;
6287
+ if (prev.length === ids.length && prev.every((id, i) => id === ids[i])) return;
6137
6288
  this._selectedIds = ids;
6289
+ for (const listener of this.selectionListeners) listener();
6290
+ }
6291
+ setSelection(ids) {
6292
+ this.setSelectedIds(ids);
6138
6293
  this.ctx?.requestRender();
6139
6294
  }
6140
6295
  get isMarqueeActive() {
@@ -6144,7 +6299,7 @@ var SelectTool = class {
6144
6299
  this.ctx = ctx;
6145
6300
  }
6146
6301
  onDeactivate(ctx) {
6147
- this._selectedIds = [];
6302
+ this.setSelectedIds([]);
6148
6303
  this.mode = { type: "idle" };
6149
6304
  this.hoveredId = null;
6150
6305
  ctx.setCursor?.("default");
@@ -6195,22 +6350,22 @@ var SelectTool = class {
6195
6350
  const alreadySelected = this._selectedIds.includes(hit.id);
6196
6351
  if (state.shiftKey) {
6197
6352
  if (alreadySelected) {
6198
- this._selectedIds = this._selectedIds.filter((id) => id !== hit.id);
6353
+ this.setSelectedIds(this._selectedIds.filter((id) => id !== hit.id));
6199
6354
  this.mode = { type: "idle" };
6200
6355
  } else {
6201
- this._selectedIds = [...this._selectedIds, hit.id];
6356
+ this.setSelectedIds([...this._selectedIds, hit.id]);
6202
6357
  this.mode = hit.locked ? { type: "idle" } : { type: "dragging" };
6203
6358
  }
6204
6359
  } else {
6205
6360
  if (!alreadySelected) {
6206
- this._selectedIds = [hit.id];
6361
+ this.setSelectedIds([hit.id]);
6207
6362
  } else if (this._selectedIds.length > 1) {
6208
6363
  this.pendingSingleSelectId = hit.id;
6209
6364
  }
6210
6365
  this.mode = hit.locked ? { type: "idle" } : { type: "dragging" };
6211
6366
  }
6212
6367
  } else {
6213
- this._selectedIds = [];
6368
+ this.setSelectedIds([]);
6214
6369
  this.mode = { type: "marquee", start: world };
6215
6370
  }
6216
6371
  ctx.requestRender();
@@ -6283,12 +6438,12 @@ var SelectTool = class {
6283
6438
  if (this.mode.type === "marquee") {
6284
6439
  const rect = this.getMarqueeRect();
6285
6440
  if (rect) {
6286
- this._selectedIds = this.findElementsInRect(rect, ctx);
6441
+ this.setSelectedIds(this.findElementsInRect(rect, ctx));
6287
6442
  }
6288
6443
  ctx.requestRender();
6289
6444
  }
6290
6445
  if (!this.hasDragged && this.pendingSingleSelectId !== null) {
6291
- this._selectedIds = [this.pendingSingleSelectId];
6446
+ this.setSelectedIds([this.pendingSingleSelectId]);
6292
6447
  }
6293
6448
  this.pendingSingleSelectId = null;
6294
6449
  this.hasDragged = false;
@@ -7510,7 +7665,7 @@ var TemplateTool = class {
7510
7665
  };
7511
7666
 
7512
7667
  // src/index.ts
7513
- var VERSION = "0.26.0";
7668
+ var VERSION = "0.27.0";
7514
7669
  export {
7515
7670
  ArrowTool,
7516
7671
  AutoSave,
@@ -7551,6 +7706,7 @@ export {
7551
7706
  getArrowTangentAngle,
7552
7707
  getBendFromPoint,
7553
7708
  getElementBounds,
7709
+ getElementStyle,
7554
7710
  getElementsBoundingBox,
7555
7711
  getHexCellsInCone,
7556
7712
  getHexCellsInLine,
@@ -7562,6 +7718,7 @@ export {
7562
7718
  smartSnap,
7563
7719
  snapPoint,
7564
7720
  snapToHexCenter,
7721
+ styleToPatch,
7565
7722
  toggleBold,
7566
7723
  toggleItalic,
7567
7724
  toggleStrikethrough,