@fieldnotes/core 0.42.0 → 0.43.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.cjs +161 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +161 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -471,6 +471,8 @@ interface ViewportOptions {
|
|
|
471
471
|
contextMenu?: boolean;
|
|
472
472
|
/** Coast (inertial glide) after a pan flick. Default `true`. */
|
|
473
473
|
panInertia?: boolean;
|
|
474
|
+
/** Show an overview minimap (bottom-right) with tap/drag-to-navigate. Default `false`. */
|
|
475
|
+
minimap?: boolean;
|
|
474
476
|
}
|
|
475
477
|
declare class Viewport {
|
|
476
478
|
private readonly container;
|
|
@@ -506,6 +508,7 @@ declare class Viewport {
|
|
|
506
508
|
private readonly gridController;
|
|
507
509
|
private readonly interactions;
|
|
508
510
|
private contextMenu;
|
|
511
|
+
private minimap;
|
|
509
512
|
private readonly htmlRenderers;
|
|
510
513
|
constructor(container: HTMLElement, options?: ViewportOptions);
|
|
511
514
|
get ctx(): CanvasRenderingContext2D | null;
|
|
@@ -1057,6 +1060,6 @@ declare class LaserTool implements Tool {
|
|
|
1057
1060
|
private notifyOptionsChange;
|
|
1058
1061
|
}
|
|
1059
1062
|
|
|
1060
|
-
declare const VERSION = "0.
|
|
1063
|
+
declare const VERSION = "0.43.0";
|
|
1061
1064
|
|
|
1062
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -471,6 +471,8 @@ interface ViewportOptions {
|
|
|
471
471
|
contextMenu?: boolean;
|
|
472
472
|
/** Coast (inertial glide) after a pan flick. Default `true`. */
|
|
473
473
|
panInertia?: boolean;
|
|
474
|
+
/** Show an overview minimap (bottom-right) with tap/drag-to-navigate. Default `false`. */
|
|
475
|
+
minimap?: boolean;
|
|
474
476
|
}
|
|
475
477
|
declare class Viewport {
|
|
476
478
|
private readonly container;
|
|
@@ -506,6 +508,7 @@ declare class Viewport {
|
|
|
506
508
|
private readonly gridController;
|
|
507
509
|
private readonly interactions;
|
|
508
510
|
private contextMenu;
|
|
511
|
+
private minimap;
|
|
509
512
|
private readonly htmlRenderers;
|
|
510
513
|
constructor(container: HTMLElement, options?: ViewportOptions);
|
|
511
514
|
get ctx(): CanvasRenderingContext2D | null;
|
|
@@ -1057,6 +1060,6 @@ declare class LaserTool implements Tool {
|
|
|
1057
1060
|
private notifyOptionsChange;
|
|
1058
1061
|
}
|
|
1059
1062
|
|
|
1060
|
-
declare const VERSION = "0.
|
|
1063
|
+
declare const VERSION = "0.43.0";
|
|
1061
1064
|
|
|
1062
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 };
|
package/dist/index.js
CHANGED
|
@@ -4277,6 +4277,135 @@ var ContextMenu = class {
|
|
|
4277
4277
|
}
|
|
4278
4278
|
};
|
|
4279
4279
|
|
|
4280
|
+
// src/canvas/minimap-transform.ts
|
|
4281
|
+
function unionBounds(a, b) {
|
|
4282
|
+
const minX = Math.min(a.x, b.x);
|
|
4283
|
+
const minY = Math.min(a.y, b.y);
|
|
4284
|
+
const maxX = Math.max(a.x + a.w, b.x + b.w);
|
|
4285
|
+
const maxY = Math.max(a.y + a.h, b.y + b.h);
|
|
4286
|
+
return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };
|
|
4287
|
+
}
|
|
4288
|
+
function computeMinimapTransform(mapping, miniW, miniH, padding) {
|
|
4289
|
+
const availW = Math.max(1, miniW - 2 * padding);
|
|
4290
|
+
const availH = Math.max(1, miniH - 2 * padding);
|
|
4291
|
+
const w = Math.max(mapping.w, 1);
|
|
4292
|
+
const h = Math.max(mapping.h, 1);
|
|
4293
|
+
const scale = Math.min(availW / w, availH / h);
|
|
4294
|
+
const offsetX = (miniW - mapping.w * scale) / 2 - mapping.x * scale;
|
|
4295
|
+
const offsetY = (miniH - mapping.h * scale) / 2 - mapping.y * scale;
|
|
4296
|
+
return { scale, offsetX, offsetY };
|
|
4297
|
+
}
|
|
4298
|
+
function worldToMini(t, p) {
|
|
4299
|
+
return { x: p.x * t.scale + t.offsetX, y: p.y * t.scale + t.offsetY };
|
|
4300
|
+
}
|
|
4301
|
+
function miniToWorld(t, p) {
|
|
4302
|
+
return { x: (p.x - t.offsetX) / t.scale, y: (p.y - t.offsetY) / t.scale };
|
|
4303
|
+
}
|
|
4304
|
+
|
|
4305
|
+
// src/canvas/minimap.ts
|
|
4306
|
+
var WIDTH = 200;
|
|
4307
|
+
var HEIGHT = 140;
|
|
4308
|
+
var MARGIN = 16;
|
|
4309
|
+
var PADDING = 8;
|
|
4310
|
+
var NEUTRAL = "rgba(100,116,139,0.6)";
|
|
4311
|
+
var VIEWPORT_STROKE = "#3b82f6";
|
|
4312
|
+
function elementColor(el) {
|
|
4313
|
+
return "color" in el && typeof el.color === "string" ? el.color : NEUTRAL;
|
|
4314
|
+
}
|
|
4315
|
+
var Minimap = class {
|
|
4316
|
+
constructor(deps) {
|
|
4317
|
+
this.deps = deps;
|
|
4318
|
+
const canvas = document.createElement("canvas");
|
|
4319
|
+
canvas.width = WIDTH;
|
|
4320
|
+
canvas.height = HEIGHT;
|
|
4321
|
+
Object.assign(canvas.style, {
|
|
4322
|
+
position: "absolute",
|
|
4323
|
+
right: `${MARGIN}px`,
|
|
4324
|
+
bottom: `${MARGIN}px`,
|
|
4325
|
+
width: `${WIDTH}px`,
|
|
4326
|
+
height: `${HEIGHT}px`,
|
|
4327
|
+
background: "rgba(255,255,255,0.85)",
|
|
4328
|
+
border: "1px solid rgba(0,0,0,0.15)",
|
|
4329
|
+
borderRadius: "4px",
|
|
4330
|
+
touchAction: "none",
|
|
4331
|
+
cursor: "pointer",
|
|
4332
|
+
zIndex: "10"
|
|
4333
|
+
});
|
|
4334
|
+
canvas.addEventListener("pointerdown", this.onPointerDown);
|
|
4335
|
+
canvas.addEventListener("pointermove", this.onPointerMove);
|
|
4336
|
+
canvas.addEventListener("pointerup", this.onPointerUp);
|
|
4337
|
+
this.deps.container.appendChild(canvas);
|
|
4338
|
+
this.canvas = canvas;
|
|
4339
|
+
}
|
|
4340
|
+
canvas;
|
|
4341
|
+
rafId = null;
|
|
4342
|
+
dragging = false;
|
|
4343
|
+
scheduleDraw() {
|
|
4344
|
+
if (this.rafId !== null) return;
|
|
4345
|
+
this.rafId = this.deps.requestFrame(this.draw);
|
|
4346
|
+
}
|
|
4347
|
+
destroy() {
|
|
4348
|
+
if (this.rafId !== null) {
|
|
4349
|
+
this.deps.cancelFrame(this.rafId);
|
|
4350
|
+
this.rafId = null;
|
|
4351
|
+
}
|
|
4352
|
+
this.canvas.removeEventListener("pointerdown", this.onPointerDown);
|
|
4353
|
+
this.canvas.removeEventListener("pointermove", this.onPointerMove);
|
|
4354
|
+
this.canvas.removeEventListener("pointerup", this.onPointerUp);
|
|
4355
|
+
this.canvas.remove();
|
|
4356
|
+
}
|
|
4357
|
+
currentTransform() {
|
|
4358
|
+
const viewport = this.deps.getViewportRect();
|
|
4359
|
+
const content = this.deps.getContentBounds();
|
|
4360
|
+
const mapping = content ? unionBounds(content, viewport) : viewport;
|
|
4361
|
+
return computeMinimapTransform(mapping, WIDTH, HEIGHT, PADDING);
|
|
4362
|
+
}
|
|
4363
|
+
draw = () => {
|
|
4364
|
+
this.rafId = null;
|
|
4365
|
+
const ctx = this.canvas.getContext("2d");
|
|
4366
|
+
if (!ctx) return;
|
|
4367
|
+
const t = this.currentTransform();
|
|
4368
|
+
const viewport = this.deps.getViewportRect();
|
|
4369
|
+
ctx.clearRect(0, 0, WIDTH, HEIGHT);
|
|
4370
|
+
for (const el of this.deps.getElements()) {
|
|
4371
|
+
const b = getElementBounds(el);
|
|
4372
|
+
if (!b) continue;
|
|
4373
|
+
const tl = worldToMini(t, { x: b.x, y: b.y });
|
|
4374
|
+
ctx.fillStyle = elementColor(el);
|
|
4375
|
+
ctx.fillRect(tl.x, tl.y, Math.max(1, b.w * t.scale), Math.max(1, b.h * t.scale));
|
|
4376
|
+
}
|
|
4377
|
+
const vtl = worldToMini(t, { x: viewport.x, y: viewport.y });
|
|
4378
|
+
ctx.strokeStyle = VIEWPORT_STROKE;
|
|
4379
|
+
ctx.lineWidth = 1.5;
|
|
4380
|
+
ctx.strokeRect(vtl.x, vtl.y, viewport.w * t.scale, viewport.h * t.scale);
|
|
4381
|
+
};
|
|
4382
|
+
navigateFromEvent(e) {
|
|
4383
|
+
const rect = this.canvas.getBoundingClientRect();
|
|
4384
|
+
const point = { x: e.clientX - rect.left, y: e.clientY - rect.top };
|
|
4385
|
+
const world = miniToWorld(this.currentTransform(), point);
|
|
4386
|
+
this.deps.navigateTo(world);
|
|
4387
|
+
}
|
|
4388
|
+
onPointerDown = (e) => {
|
|
4389
|
+
e.stopPropagation();
|
|
4390
|
+
e.preventDefault();
|
|
4391
|
+
this.dragging = true;
|
|
4392
|
+
this.canvas.setPointerCapture?.(e.pointerId);
|
|
4393
|
+
this.navigateFromEvent(e);
|
|
4394
|
+
};
|
|
4395
|
+
onPointerMove = (e) => {
|
|
4396
|
+
if (!this.dragging) return;
|
|
4397
|
+
e.stopPropagation();
|
|
4398
|
+
this.navigateFromEvent(e);
|
|
4399
|
+
};
|
|
4400
|
+
onPointerUp = (e) => {
|
|
4401
|
+
this.dragging = false;
|
|
4402
|
+
try {
|
|
4403
|
+
this.canvas.releasePointerCapture(e.pointerId);
|
|
4404
|
+
} catch {
|
|
4405
|
+
}
|
|
4406
|
+
};
|
|
4407
|
+
};
|
|
4408
|
+
|
|
4280
4409
|
// src/canvas/viewport-dom.ts
|
|
4281
4410
|
function createWrapper() {
|
|
4282
4411
|
const el = document.createElement("div");
|
|
@@ -6402,7 +6531,7 @@ function getElementStyle(element) {
|
|
|
6402
6531
|
}
|
|
6403
6532
|
|
|
6404
6533
|
// src/canvas/selection-ops.ts
|
|
6405
|
-
function
|
|
6534
|
+
function unionBounds2(list) {
|
|
6406
6535
|
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
6407
6536
|
for (const b of list) {
|
|
6408
6537
|
minX = Math.min(minX, b.x);
|
|
@@ -6497,7 +6626,7 @@ var SelectionOps = class {
|
|
|
6497
6626
|
align(edge) {
|
|
6498
6627
|
const bounded = this.boundedSelection();
|
|
6499
6628
|
if (bounded.length < 2) return;
|
|
6500
|
-
const B =
|
|
6629
|
+
const B = unionBounds2(bounded.map((e) => e.bounds));
|
|
6501
6630
|
this.deps.recorder.begin();
|
|
6502
6631
|
const moved = [];
|
|
6503
6632
|
for (const { id, el, bounds: b } of bounded) {
|
|
@@ -6904,6 +7033,27 @@ var Viewport = class {
|
|
|
6904
7033
|
});
|
|
6905
7034
|
}
|
|
6906
7035
|
this.unsubToolChange = this.toolManager.onChange(() => this.contextMenu?.close());
|
|
7036
|
+
if (options.minimap) {
|
|
7037
|
+
const visibleEls = () => this.store.getAll().filter((el) => this.layerManager.isLayerVisible(el.layerId));
|
|
7038
|
+
this.minimap = new Minimap({
|
|
7039
|
+
container: this.wrapper,
|
|
7040
|
+
getElements: visibleEls,
|
|
7041
|
+
getContentBounds: () => getElementsBoundingBox(visibleEls()),
|
|
7042
|
+
getViewportRect: () => this.camera.getVisibleRect(this.canvasEl.clientWidth, this.canvasEl.clientHeight),
|
|
7043
|
+
navigateTo: (w) => {
|
|
7044
|
+
const z = this.camera.zoom;
|
|
7045
|
+
this.camera.moveTo(
|
|
7046
|
+
this.canvasEl.clientWidth / 2 - w.x * z,
|
|
7047
|
+
this.canvasEl.clientHeight / 2 - w.y * z
|
|
7048
|
+
);
|
|
7049
|
+
},
|
|
7050
|
+
requestFrame: (cb) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(cb) : 0,
|
|
7051
|
+
cancelFrame: (id) => {
|
|
7052
|
+
if (typeof cancelAnimationFrame !== "undefined") cancelAnimationFrame(id);
|
|
7053
|
+
}
|
|
7054
|
+
});
|
|
7055
|
+
this.minimap.scheduleDraw();
|
|
7056
|
+
}
|
|
6907
7057
|
this.domNodeManager = new DomNodeManager({
|
|
6908
7058
|
domLayer: this.domLayer,
|
|
6909
7059
|
onEditRequest: (id) => this.interactions.startEditingElement(id),
|
|
@@ -6936,6 +7086,7 @@ var Viewport = class {
|
|
|
6936
7086
|
this.applyCameraTransform();
|
|
6937
7087
|
this.noteEditor.updateToolbarPosition();
|
|
6938
7088
|
this.contextMenu?.close();
|
|
7089
|
+
this.minimap?.scheduleDraw();
|
|
6939
7090
|
this.requestRender();
|
|
6940
7091
|
});
|
|
6941
7092
|
this.gridController = new GridController({
|
|
@@ -6950,6 +7101,7 @@ var Viewport = class {
|
|
|
6950
7101
|
this.store.on("add", (el) => {
|
|
6951
7102
|
if (el.type === "grid") this.gridController.syncContext();
|
|
6952
7103
|
this.renderLoop.markLayerDirty(el.layerId);
|
|
7104
|
+
this.minimap?.scheduleDraw();
|
|
6953
7105
|
this.requestRender();
|
|
6954
7106
|
}),
|
|
6955
7107
|
this.store.on("remove", (el) => {
|
|
@@ -6957,6 +7109,7 @@ var Viewport = class {
|
|
|
6957
7109
|
this.unbindArrowsFrom(el);
|
|
6958
7110
|
this.domNodeManager.removeDomNode(el.id);
|
|
6959
7111
|
this.renderLoop.markLayerDirty(el.layerId);
|
|
7112
|
+
this.minimap?.scheduleDraw();
|
|
6960
7113
|
this.requestRender();
|
|
6961
7114
|
}),
|
|
6962
7115
|
this.store.on("update", ({ previous, current }) => {
|
|
@@ -6965,17 +7118,20 @@ var Viewport = class {
|
|
|
6965
7118
|
if (previous.layerId !== current.layerId) {
|
|
6966
7119
|
this.renderLoop.markLayerDirty(previous.layerId);
|
|
6967
7120
|
}
|
|
7121
|
+
this.minimap?.scheduleDraw();
|
|
6968
7122
|
this.requestRender();
|
|
6969
7123
|
}),
|
|
6970
7124
|
this.store.on("clear", () => {
|
|
6971
7125
|
this.domNodeManager.clearDomNodes();
|
|
6972
7126
|
this.renderLoop.markAllLayersDirty();
|
|
6973
7127
|
this.gridController.syncContext();
|
|
7128
|
+
this.minimap?.scheduleDraw();
|
|
6974
7129
|
this.requestRender();
|
|
6975
7130
|
})
|
|
6976
7131
|
];
|
|
6977
7132
|
this.layerManager.on("change", () => {
|
|
6978
7133
|
this.toolContext.activeLayerId = this.layerManager.activeLayerId;
|
|
7134
|
+
this.minimap?.scheduleDraw();
|
|
6979
7135
|
this.requestRender();
|
|
6980
7136
|
});
|
|
6981
7137
|
this.interactions = new ViewportInteractions({
|
|
@@ -7035,6 +7191,7 @@ var Viewport = class {
|
|
|
7035
7191
|
gridController;
|
|
7036
7192
|
interactions;
|
|
7037
7193
|
contextMenu = null;
|
|
7194
|
+
minimap = null;
|
|
7038
7195
|
htmlRenderers = /* @__PURE__ */ new Map();
|
|
7039
7196
|
get ctx() {
|
|
7040
7197
|
return this.canvasEl.getContext("2d");
|
|
@@ -7308,6 +7465,7 @@ var Viewport = class {
|
|
|
7308
7465
|
this.arrowLabelEditor.cancel();
|
|
7309
7466
|
this.historyRecorder.destroy();
|
|
7310
7467
|
this.contextMenu?.dispose();
|
|
7468
|
+
this.minimap?.destroy();
|
|
7311
7469
|
this.wrapper.removeEventListener("pointerdown", this.interactions.onTapDown);
|
|
7312
7470
|
this.wrapper.removeEventListener("pointerup", this.interactions.onDoubleTap);
|
|
7313
7471
|
this.wrapper.removeEventListener("dragover", this.interactions.onDragOver);
|
|
@@ -9810,7 +9968,7 @@ var LaserTool = class {
|
|
|
9810
9968
|
};
|
|
9811
9969
|
|
|
9812
9970
|
// src/index.ts
|
|
9813
|
-
var VERSION = "0.
|
|
9971
|
+
var VERSION = "0.43.0";
|
|
9814
9972
|
export {
|
|
9815
9973
|
ArrowTool,
|
|
9816
9974
|
AutoSave,
|