@fieldnotes/core 0.31.1 → 0.32.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
@@ -410,6 +410,8 @@ interface ElementStyle {
410
410
  declare function styleToPatch(element: CanvasElement, style: ElementStyle): Partial<CanvasElement>;
411
411
  declare function getElementStyle(element: CanvasElement): ElementStyle;
412
412
 
413
+ type AlignEdge = 'left' | 'center-x' | 'right' | 'top' | 'middle' | 'bottom';
414
+ type DistributeAxis = 'horizontal' | 'vertical';
413
415
  interface GridInfo {
414
416
  gridType: 'square' | 'hex';
415
417
  hexOrientation: 'pointy' | 'flat';
@@ -516,6 +518,10 @@ declare class Viewport {
516
518
  onSelectionChange(listener: () => void): () => void;
517
519
  getSelectionStyle(): ElementStyle | null;
518
520
  applyStyleToSelection(style: ElementStyle): void;
521
+ alignSelection(edge: AlignEdge): void;
522
+ distributeSelection(axis: DistributeAxis): void;
523
+ private boundedSelection;
524
+ private isMovable;
519
525
  getRenderStats(): RenderStatsSnapshot;
520
526
  logPerformance(intervalMs?: number): () => void;
521
527
  destroy(): void;
@@ -973,6 +979,6 @@ declare class TemplateTool implements Tool {
973
979
  private notifyOptionsChange;
974
980
  }
975
981
 
976
- declare const VERSION = "0.31.1";
982
+ declare const VERSION = "0.32.0";
977
983
 
978
- 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 };
984
+ export { type ActiveFormats, type AlignEdge, 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, type DistributeAxis, 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
@@ -410,6 +410,8 @@ interface ElementStyle {
410
410
  declare function styleToPatch(element: CanvasElement, style: ElementStyle): Partial<CanvasElement>;
411
411
  declare function getElementStyle(element: CanvasElement): ElementStyle;
412
412
 
413
+ type AlignEdge = 'left' | 'center-x' | 'right' | 'top' | 'middle' | 'bottom';
414
+ type DistributeAxis = 'horizontal' | 'vertical';
413
415
  interface GridInfo {
414
416
  gridType: 'square' | 'hex';
415
417
  hexOrientation: 'pointy' | 'flat';
@@ -516,6 +518,10 @@ declare class Viewport {
516
518
  onSelectionChange(listener: () => void): () => void;
517
519
  getSelectionStyle(): ElementStyle | null;
518
520
  applyStyleToSelection(style: ElementStyle): void;
521
+ alignSelection(edge: AlignEdge): void;
522
+ distributeSelection(axis: DistributeAxis): void;
523
+ private boundedSelection;
524
+ private isMovable;
519
525
  getRenderStats(): RenderStatsSnapshot;
520
526
  logPerformance(intervalMs?: number): () => void;
521
527
  destroy(): void;
@@ -973,6 +979,6 @@ declare class TemplateTool implements Tool {
973
979
  private notifyOptionsChange;
974
980
  }
975
981
 
976
- declare const VERSION = "0.31.1";
982
+ declare const VERSION = "0.32.0";
977
983
 
978
- 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 };
984
+ export { type ActiveFormats, type AlignEdge, 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, type DistributeAxis, 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
@@ -2270,6 +2270,23 @@ function distToBounds(point, bounds) {
2270
2270
  function findBoundArrows(elementId, store) {
2271
2271
  return store.getElementsByType("arrow").filter((a) => a.fromBinding?.elementId === elementId || a.toBinding?.elementId === elementId);
2272
2272
  }
2273
+ function updateArrowsBoundToElements(movedIds, store) {
2274
+ const movedNonArrowIds = /* @__PURE__ */ new Set();
2275
+ for (const id of movedIds) {
2276
+ const el = store.getById(id);
2277
+ if (el && el.type !== "arrow") movedNonArrowIds.add(id);
2278
+ }
2279
+ if (movedNonArrowIds.size === 0) return;
2280
+ const updated = /* @__PURE__ */ new Set();
2281
+ for (const id of movedNonArrowIds) {
2282
+ for (const ba of findBoundArrows(id, store)) {
2283
+ if (updated.has(ba.id)) continue;
2284
+ updated.add(ba.id);
2285
+ const updates = updateBoundArrow(ba, store);
2286
+ if (updates) store.update(ba.id, updates);
2287
+ }
2288
+ }
2289
+ }
2273
2290
  function updateBoundArrow(arrow, store) {
2274
2291
  if (!arrow.fromBinding && !arrow.toBinding) return null;
2275
2292
  const updates = {};
@@ -3697,6 +3714,19 @@ var NoteEditor = class {
3697
3714
  }
3698
3715
  };
3699
3716
 
3717
+ // src/elements/translate.ts
3718
+ function translateElementPatch(el, dx, dy) {
3719
+ const position = { x: el.position.x + dx, y: el.position.y + dy };
3720
+ if (el.type === "arrow") {
3721
+ return {
3722
+ position,
3723
+ from: { x: el.from.x + dx, y: el.from.y + dy },
3724
+ to: { x: el.to.x + dx, y: el.to.y + dy }
3725
+ };
3726
+ }
3727
+ return { position };
3728
+ }
3729
+
3700
3730
  // src/elements/arrow-label-editor.ts
3701
3731
  var ArrowLabelEditor = class {
3702
3732
  input = null;
@@ -5383,6 +5413,16 @@ function getElementStyle(element) {
5383
5413
  }
5384
5414
 
5385
5415
  // src/canvas/viewport.ts
5416
+ function unionBounds(list) {
5417
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
5418
+ for (const b of list) {
5419
+ minX = Math.min(minX, b.x);
5420
+ minY = Math.min(minY, b.y);
5421
+ maxX = Math.max(maxX, b.x + b.w);
5422
+ maxY = Math.max(maxY, b.y + b.h);
5423
+ }
5424
+ return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };
5425
+ }
5386
5426
  var EMPTY_IDS = [];
5387
5427
  var ARROW_HIT_THRESHOLD = 10;
5388
5428
  function noop() {
@@ -5792,6 +5832,86 @@ var Viewport = class {
5792
5832
  }
5793
5833
  this.historyRecorder.commit();
5794
5834
  }
5835
+ alignSelection(edge) {
5836
+ const bounded = this.boundedSelection();
5837
+ if (bounded.length < 2) return;
5838
+ const B = unionBounds(bounded.map((e) => e.bounds));
5839
+ this.historyRecorder.begin();
5840
+ const moved = [];
5841
+ for (const { id, el, bounds: b } of bounded) {
5842
+ if (!this.isMovable(el)) continue;
5843
+ let dx = 0;
5844
+ let dy = 0;
5845
+ switch (edge) {
5846
+ case "left":
5847
+ dx = B.x - b.x;
5848
+ break;
5849
+ case "right":
5850
+ dx = B.x + B.w - (b.x + b.w);
5851
+ break;
5852
+ case "center-x":
5853
+ dx = B.x + B.w / 2 - (b.x + b.w / 2);
5854
+ break;
5855
+ case "top":
5856
+ dy = B.y - b.y;
5857
+ break;
5858
+ case "bottom":
5859
+ dy = B.y + B.h - (b.y + b.h);
5860
+ break;
5861
+ case "middle":
5862
+ dy = B.y + B.h / 2 - (b.y + b.h / 2);
5863
+ break;
5864
+ }
5865
+ if (dx === 0 && dy === 0) continue;
5866
+ this.store.update(id, translateElementPatch(el, dx, dy));
5867
+ moved.push(id);
5868
+ }
5869
+ updateArrowsBoundToElements(moved, this.store);
5870
+ this.historyRecorder.commit();
5871
+ this.requestRender();
5872
+ }
5873
+ distributeSelection(axis) {
5874
+ const bounded = this.boundedSelection();
5875
+ if (bounded.length < 3) return;
5876
+ const center = (b) => axis === "horizontal" ? b.x + b.w / 2 : b.y + b.h / 2;
5877
+ const sorted = [...bounded].sort((p, q) => center(p.bounds) - center(q.bounds));
5878
+ const first = sorted[0];
5879
+ const last = sorted[sorted.length - 1];
5880
+ if (!first || !last) return;
5881
+ const c0 = center(first.bounds);
5882
+ const cN = center(last.bounds);
5883
+ const n = sorted.length;
5884
+ this.historyRecorder.begin();
5885
+ const moved = [];
5886
+ for (let i = 1; i < n - 1; i++) {
5887
+ const item = sorted[i];
5888
+ if (!item || !this.isMovable(item.el)) continue;
5889
+ const target = c0 + i * (cN - c0) / (n - 1);
5890
+ const delta = target - center(item.bounds);
5891
+ if (delta === 0) continue;
5892
+ const [dx, dy] = axis === "horizontal" ? [delta, 0] : [0, delta];
5893
+ this.store.update(item.id, translateElementPatch(item.el, dx, dy));
5894
+ moved.push(item.id);
5895
+ }
5896
+ updateArrowsBoundToElements(moved, this.store);
5897
+ this.historyRecorder.commit();
5898
+ this.requestRender();
5899
+ }
5900
+ boundedSelection() {
5901
+ const out = [];
5902
+ for (const id of this.getSelectedIds()) {
5903
+ const el = this.store.getById(id);
5904
+ if (!el) continue;
5905
+ const bounds = getElementBounds(el);
5906
+ if (bounds) out.push({ id, el, bounds });
5907
+ }
5908
+ return out;
5909
+ }
5910
+ isMovable(el) {
5911
+ if (el.locked) return false;
5912
+ if (el.type === "arrow" && (el.fromBinding ?? el.toBinding)) return false;
5913
+ return true;
5914
+ }
5795
5915
  getRenderStats() {
5796
5916
  return this.renderLoop.getStats();
5797
5917
  }
@@ -6799,40 +6919,15 @@ var SelectTool = class {
6799
6919
  }
6800
6920
  }
6801
6921
  updateArrowsBoundTo(ids, ctx) {
6802
- const movedNonArrowIds = /* @__PURE__ */ new Set();
6803
- for (const id of ids) {
6804
- const el = ctx.store.getById(id);
6805
- if (el && el.type !== "arrow") movedNonArrowIds.add(id);
6806
- }
6807
- if (movedNonArrowIds.size === 0) return;
6808
- const updatedArrows = /* @__PURE__ */ new Set();
6809
- for (const id of movedNonArrowIds) {
6810
- const boundArrows = findBoundArrows(id, ctx.store);
6811
- for (const ba of boundArrows) {
6812
- if (updatedArrows.has(ba.id)) continue;
6813
- updatedArrows.add(ba.id);
6814
- const updates = updateBoundArrow(ba, ctx.store);
6815
- if (updates) ctx.store.update(ba.id, updates);
6816
- }
6817
- }
6922
+ updateArrowsBoundToElements(ids, ctx.store);
6818
6923
  }
6819
6924
  nudgeSelection(dx, dy, ctx) {
6820
6925
  let moved = false;
6821
6926
  for (const id of this._selectedIds) {
6822
6927
  const el = ctx.store.getById(id);
6823
6928
  if (!el || el.locked) continue;
6824
- if (el.type === "arrow") {
6825
- if (el.fromBinding || el.toBinding) continue;
6826
- ctx.store.update(id, {
6827
- position: { x: el.position.x + dx, y: el.position.y + dy },
6828
- from: { x: el.from.x + dx, y: el.from.y + dy },
6829
- to: { x: el.to.x + dx, y: el.to.y + dy }
6830
- });
6831
- } else {
6832
- ctx.store.update(id, {
6833
- position: { x: el.position.x + dx, y: el.position.y + dy }
6834
- });
6835
- }
6929
+ if (el.type === "arrow" && (el.fromBinding || el.toBinding)) continue;
6930
+ ctx.store.update(id, translateElementPatch(el, dx, dy));
6836
6931
  moved = true;
6837
6932
  }
6838
6933
  if (moved) {
@@ -8024,7 +8119,7 @@ var TemplateTool = class {
8024
8119
  };
8025
8120
 
8026
8121
  // src/index.ts
8027
- var VERSION = "0.31.1";
8122
+ var VERSION = "0.32.0";
8028
8123
  export {
8029
8124
  ArrowTool,
8030
8125
  AutoSave,