@fieldnotes/core 0.48.0 → 0.49.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
@@ -487,6 +487,8 @@ interface ElementStyle {
487
487
  declare function styleToPatch(element: CanvasElement, style: ElementStyle): Partial<CanvasElement>;
488
488
  declare function getElementStyle(element: CanvasElement): ElementStyle;
489
489
 
490
+ type RotateDirection = 'cw' | 'ccw';
491
+
490
492
  type AlignEdge = 'left' | 'center-x' | 'right' | 'top' | 'middle' | 'bottom';
491
493
  type DistributeAxis = 'horizontal' | 'vertical';
492
494
 
@@ -641,6 +643,7 @@ declare class Viewport {
641
643
  toggleLockSelection(): void;
642
644
  alignSelection(edge: AlignEdge): void;
643
645
  distributeSelection(axis: DistributeAxis): void;
646
+ rotateSelection(direction: RotateDirection): void;
644
647
  getRenderStats(): RenderStatsSnapshot;
645
648
  logPerformance(intervalMs?: number): () => void;
646
649
  destroy(): void;
@@ -1120,6 +1123,6 @@ declare class LaserTool implements Tool {
1120
1123
  private notifyOptionsChange;
1121
1124
  }
1122
1125
 
1123
- declare const VERSION = "0.48.0";
1126
+ declare const VERSION = "0.49.0";
1124
1127
 
1125
- 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, type ElementChangeMeta, 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, getHexCellsInRectangle, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
1128
+ 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, type ElementChangeMeta, 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, type RotateDirection, 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, getHexCellsInRectangle, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
package/dist/index.d.ts CHANGED
@@ -487,6 +487,8 @@ interface ElementStyle {
487
487
  declare function styleToPatch(element: CanvasElement, style: ElementStyle): Partial<CanvasElement>;
488
488
  declare function getElementStyle(element: CanvasElement): ElementStyle;
489
489
 
490
+ type RotateDirection = 'cw' | 'ccw';
491
+
490
492
  type AlignEdge = 'left' | 'center-x' | 'right' | 'top' | 'middle' | 'bottom';
491
493
  type DistributeAxis = 'horizontal' | 'vertical';
492
494
 
@@ -641,6 +643,7 @@ declare class Viewport {
641
643
  toggleLockSelection(): void;
642
644
  alignSelection(edge: AlignEdge): void;
643
645
  distributeSelection(axis: DistributeAxis): void;
646
+ rotateSelection(direction: RotateDirection): void;
644
647
  getRenderStats(): RenderStatsSnapshot;
645
648
  logPerformance(intervalMs?: number): () => void;
646
649
  destroy(): void;
@@ -1120,6 +1123,6 @@ declare class LaserTool implements Tool {
1120
1123
  private notifyOptionsChange;
1121
1124
  }
1122
1125
 
1123
- declare const VERSION = "0.48.0";
1126
+ declare const VERSION = "0.49.0";
1124
1127
 
1125
- 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, type ElementChangeMeta, 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, getHexCellsInRectangle, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
1128
+ 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, type ElementChangeMeta, 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, type RotateDirection, 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, getHexCellsInRectangle, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
package/dist/index.js CHANGED
@@ -1155,6 +1155,14 @@ var KeyboardActions = class {
1155
1155
  if (this.deps.isToolActive()) return;
1156
1156
  this.deps.toggleLock?.();
1157
1157
  }
1158
+ rotate(direction) {
1159
+ if (this.deps.isToolActive()) return;
1160
+ this.flushPendingNudge();
1161
+ const sel = this.selectTool();
1162
+ if (!sel) return;
1163
+ if (sel.tool.selectedIds.length === 0) return;
1164
+ this.deps.rotate?.(direction);
1165
+ }
1158
1166
  zOrder(operation) {
1159
1167
  if (this.deps.isToolActive()) return;
1160
1168
  this.flushPendingNudge();
@@ -1259,6 +1267,8 @@ var DEFAULT_BINDINGS = [
1259
1267
  ["ungroup", ["mod+shift+g"]],
1260
1268
  ["cut", ["mod+x"]],
1261
1269
  ["toggle-lock", ["mod+shift+l"]],
1270
+ ["rotate-cw", ["r"]],
1271
+ ["rotate-ccw", ["shift+r"]],
1262
1272
  ["nudge-left", ["arrowleft"]],
1263
1273
  ["nudge-right", ["arrowright"]],
1264
1274
  ["nudge-up", ["arrowup"]],
@@ -1571,6 +1581,14 @@ var KeyboardHandler = class {
1571
1581
  e?.preventDefault();
1572
1582
  this.deps.actions.toggleLock();
1573
1583
  return;
1584
+ case "rotate-cw":
1585
+ e?.preventDefault();
1586
+ this.deps.actions.rotate("cw");
1587
+ return;
1588
+ case "rotate-ccw":
1589
+ e?.preventDefault();
1590
+ this.deps.actions.rotate("ccw");
1591
+ return;
1574
1592
  case "zoom-in":
1575
1593
  e?.preventDefault();
1576
1594
  this.zoomByFactor(ZOOM_STEP);
@@ -1707,6 +1725,7 @@ var InputHandler = class {
1707
1725
  group: options.group,
1708
1726
  ungroup: options.ungroup,
1709
1727
  toggleLock: options.toggleLock,
1728
+ rotate: options.rotate,
1710
1729
  getLastPointerWorld: () => this.lastPointerWorld()
1711
1730
  });
1712
1731
  this.openContextMenu = options.openContextMenu;
@@ -6795,7 +6814,7 @@ function getElementStyle(element) {
6795
6814
  }
6796
6815
  }
6797
6816
 
6798
- // src/canvas/selection-ops.ts
6817
+ // src/canvas/selection-rotate.ts
6799
6818
  function unionBounds2(list) {
6800
6819
  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
6801
6820
  for (const b of list) {
@@ -6806,6 +6825,39 @@ function unionBounds2(list) {
6806
6825
  }
6807
6826
  return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };
6808
6827
  }
6828
+ function rotationPivot(items) {
6829
+ const first = items[0];
6830
+ if (items.length === 1 && first) {
6831
+ return { x: first.bounds.x + first.bounds.w / 2, y: first.bounds.y + first.bounds.h / 2 };
6832
+ }
6833
+ const u = unionBounds2(items.map((it) => rotatedAABB(it.bounds, it.el.rotation ?? 0)));
6834
+ return { x: u.x + u.w / 2, y: u.y + u.h / 2 };
6835
+ }
6836
+ function rotateElementPatch(el, bounds, pivot, delta) {
6837
+ if (el.type === "arrow") {
6838
+ const center3 = { x: bounds.x + bounds.w / 2, y: bounds.y + bounds.h / 2 };
6839
+ const moved2 = rotatePoint(center3, pivot, delta);
6840
+ return {
6841
+ position: { x: el.position.x + moved2.x - center3.x, y: el.position.y + moved2.y - center3.y },
6842
+ from: rotatePoint(el.from, pivot, delta),
6843
+ to: rotatePoint(el.to, pivot, delta)
6844
+ };
6845
+ }
6846
+ if (el.type === "template") {
6847
+ return {
6848
+ position: rotatePoint(el.position, pivot, delta),
6849
+ angle: normalizeAngle(el.angle + delta)
6850
+ };
6851
+ }
6852
+ const center2 = { x: bounds.x + bounds.w / 2, y: bounds.y + bounds.h / 2 };
6853
+ const moved = rotatePoint(center2, pivot, delta);
6854
+ return {
6855
+ position: { x: el.position.x + moved.x - center2.x, y: el.position.y + moved.y - center2.y },
6856
+ rotation: normalizeAngle((el.rotation ?? 0) + delta)
6857
+ };
6858
+ }
6859
+
6860
+ // src/canvas/selection-ops.ts
6809
6861
  function sharedValue(values) {
6810
6862
  const present = values.filter((v) => v !== void 0);
6811
6863
  if (present.length === 0) return void 0;
@@ -6953,6 +7005,21 @@ var SelectionOps = class {
6953
7005
  this.deps.recorder.commit();
6954
7006
  this.deps.requestRender();
6955
7007
  }
7008
+ rotateSelection(direction) {
7009
+ const eligible = this.boundedSelection().filter(({ el }) => this.isMovable(el));
7010
+ if (eligible.length === 0) return;
7011
+ const delta = direction === "cw" ? Math.PI / 2 : -Math.PI / 2;
7012
+ const pivot = rotationPivot(eligible);
7013
+ this.deps.recorder.begin();
7014
+ const moved = [];
7015
+ for (const { id, el, bounds } of eligible) {
7016
+ this.deps.store.update(id, rotateElementPatch(el, bounds, pivot, delta));
7017
+ moved.push(id);
7018
+ }
7019
+ updateArrowsBoundToElements(moved, this.deps.store);
7020
+ this.deps.recorder.commit();
7021
+ this.deps.requestRender();
7022
+ }
6956
7023
  boundedSelection() {
6957
7024
  const out = [];
6958
7025
  for (const id of this.deps.getSelectedIds()) {
@@ -7281,6 +7348,7 @@ var Viewport = class {
7281
7348
  group: () => this.groupSelection(),
7282
7349
  ungroup: () => this.ungroupSelection(),
7283
7350
  toggleLock: () => this.toggleLockSelection(),
7351
+ rotate: (direction) => this.rotateSelection(direction),
7284
7352
  openContextMenu: (screenPos, world) => {
7285
7353
  this.getSelectTool()?.selectAtPoint(world, this.toolContext);
7286
7354
  this.openContextMenu(screenPos);
@@ -7678,6 +7746,8 @@ var Viewport = class {
7678
7746
  items.push({ label: "Bring Forward", action: "z-forward" });
7679
7747
  items.push({ label: "Send Backward", action: "z-backward" });
7680
7748
  items.push({ label: "Send to Back", action: "z-back" });
7749
+ items.push({ label: "Rotate 90\xB0 CW", action: "rotate-cw" });
7750
+ items.push({ label: "Rotate 90\xB0 CCW", action: "rotate-ccw" });
7681
7751
  const allLocked = ids.every((id) => this.store.getById(id)?.locked);
7682
7752
  items.push({ label: allLocked ? "Unlock" : "Lock", action: "toggle-lock" });
7683
7753
  } else if (this.canPaste()) {
@@ -7711,6 +7781,9 @@ var Viewport = class {
7711
7781
  distributeSelection(axis) {
7712
7782
  this.selectionOps.distribute(axis);
7713
7783
  }
7784
+ rotateSelection(direction) {
7785
+ this.selectionOps.rotateSelection(direction);
7786
+ }
7714
7787
  getRenderStats() {
7715
7788
  return this.renderLoop.getStats();
7716
7789
  }
@@ -10453,7 +10526,7 @@ var LaserTool = class {
10453
10526
  };
10454
10527
 
10455
10528
  // src/index.ts
10456
- var VERSION = "0.48.0";
10529
+ var VERSION = "0.49.0";
10457
10530
  export {
10458
10531
  ArrowTool,
10459
10532
  AutoSave,