@fieldnotes/core 0.41.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 +257 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +257 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -469,6 +469,10 @@ interface ViewportOptions {
|
|
|
469
469
|
panBufferMargin?: number;
|
|
470
470
|
/** Enable the built-in context menu. Default `true`. */
|
|
471
471
|
contextMenu?: boolean;
|
|
472
|
+
/** Coast (inertial glide) after a pan flick. Default `true`. */
|
|
473
|
+
panInertia?: boolean;
|
|
474
|
+
/** Show an overview minimap (bottom-right) with tap/drag-to-navigate. Default `false`. */
|
|
475
|
+
minimap?: boolean;
|
|
472
476
|
}
|
|
473
477
|
declare class Viewport {
|
|
474
478
|
private readonly container;
|
|
@@ -504,6 +508,7 @@ declare class Viewport {
|
|
|
504
508
|
private readonly gridController;
|
|
505
509
|
private readonly interactions;
|
|
506
510
|
private contextMenu;
|
|
511
|
+
private minimap;
|
|
507
512
|
private readonly htmlRenderers;
|
|
508
513
|
constructor(container: HTMLElement, options?: ViewportOptions);
|
|
509
514
|
get ctx(): CanvasRenderingContext2D | null;
|
|
@@ -1055,6 +1060,6 @@ declare class LaserTool implements Tool {
|
|
|
1055
1060
|
private notifyOptionsChange;
|
|
1056
1061
|
}
|
|
1057
1062
|
|
|
1058
|
-
declare const VERSION = "0.
|
|
1063
|
+
declare const VERSION = "0.43.0";
|
|
1059
1064
|
|
|
1060
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
|
@@ -469,6 +469,10 @@ interface ViewportOptions {
|
|
|
469
469
|
panBufferMargin?: number;
|
|
470
470
|
/** Enable the built-in context menu. Default `true`. */
|
|
471
471
|
contextMenu?: boolean;
|
|
472
|
+
/** Coast (inertial glide) after a pan flick. Default `true`. */
|
|
473
|
+
panInertia?: boolean;
|
|
474
|
+
/** Show an overview minimap (bottom-right) with tap/drag-to-navigate. Default `false`. */
|
|
475
|
+
minimap?: boolean;
|
|
472
476
|
}
|
|
473
477
|
declare class Viewport {
|
|
474
478
|
private readonly container;
|
|
@@ -504,6 +508,7 @@ declare class Viewport {
|
|
|
504
508
|
private readonly gridController;
|
|
505
509
|
private readonly interactions;
|
|
506
510
|
private contextMenu;
|
|
511
|
+
private minimap;
|
|
507
512
|
private readonly htmlRenderers;
|
|
508
513
|
constructor(container: HTMLElement, options?: ViewportOptions);
|
|
509
514
|
get ctx(): CanvasRenderingContext2D | null;
|
|
@@ -1055,6 +1060,6 @@ declare class LaserTool implements Tool {
|
|
|
1055
1060
|
private notifyOptionsChange;
|
|
1056
1061
|
}
|
|
1057
1062
|
|
|
1058
|
-
declare const VERSION = "0.
|
|
1063
|
+
declare const VERSION = "0.43.0";
|
|
1059
1064
|
|
|
1060
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
|
@@ -1471,6 +1471,81 @@ var KeyboardHandler = class {
|
|
|
1471
1471
|
}
|
|
1472
1472
|
};
|
|
1473
1473
|
|
|
1474
|
+
// src/canvas/pan-inertia.ts
|
|
1475
|
+
var VELOCITY_WINDOW_MS = 60;
|
|
1476
|
+
var FRICTION = 0.92;
|
|
1477
|
+
var MIN_START_SPEED = 2;
|
|
1478
|
+
var MIN_STOP_SPEED = 0.3;
|
|
1479
|
+
var PanInertia = class {
|
|
1480
|
+
constructor(deps) {
|
|
1481
|
+
this.deps = deps;
|
|
1482
|
+
}
|
|
1483
|
+
samples = [];
|
|
1484
|
+
vx = 0;
|
|
1485
|
+
vy = 0;
|
|
1486
|
+
rafId = null;
|
|
1487
|
+
sample(dx, dy) {
|
|
1488
|
+
const t = this.deps.now();
|
|
1489
|
+
this.samples.push({ dx, dy, t });
|
|
1490
|
+
this.prune(t);
|
|
1491
|
+
}
|
|
1492
|
+
release() {
|
|
1493
|
+
if (!this.deps.enabled()) {
|
|
1494
|
+
this.reset();
|
|
1495
|
+
return;
|
|
1496
|
+
}
|
|
1497
|
+
const t = this.deps.now();
|
|
1498
|
+
this.prune(t);
|
|
1499
|
+
const recent = this.samples;
|
|
1500
|
+
if (recent.length === 0) {
|
|
1501
|
+
this.reset();
|
|
1502
|
+
return;
|
|
1503
|
+
}
|
|
1504
|
+
let sx = 0;
|
|
1505
|
+
let sy = 0;
|
|
1506
|
+
for (const s of recent) {
|
|
1507
|
+
sx += s.dx;
|
|
1508
|
+
sy += s.dy;
|
|
1509
|
+
}
|
|
1510
|
+
this.vx = sx / recent.length;
|
|
1511
|
+
this.vy = sy / recent.length;
|
|
1512
|
+
this.samples = [];
|
|
1513
|
+
if (Math.hypot(this.vx, this.vy) < MIN_START_SPEED) {
|
|
1514
|
+
this.vx = 0;
|
|
1515
|
+
this.vy = 0;
|
|
1516
|
+
return;
|
|
1517
|
+
}
|
|
1518
|
+
this.rafId = this.deps.requestFrame(this.step);
|
|
1519
|
+
}
|
|
1520
|
+
cancel() {
|
|
1521
|
+
this.reset();
|
|
1522
|
+
}
|
|
1523
|
+
step = () => {
|
|
1524
|
+
if (this.rafId === null) return;
|
|
1525
|
+
this.deps.pan(this.vx, this.vy);
|
|
1526
|
+
this.vx *= FRICTION;
|
|
1527
|
+
this.vy *= FRICTION;
|
|
1528
|
+
if (Math.hypot(this.vx, this.vy) >= MIN_STOP_SPEED) {
|
|
1529
|
+
this.rafId = this.deps.requestFrame(this.step);
|
|
1530
|
+
} else {
|
|
1531
|
+
this.reset();
|
|
1532
|
+
}
|
|
1533
|
+
};
|
|
1534
|
+
prune(now) {
|
|
1535
|
+
const cutoff = now - VELOCITY_WINDOW_MS;
|
|
1536
|
+
this.samples = this.samples.filter((s) => s.t >= cutoff);
|
|
1537
|
+
}
|
|
1538
|
+
reset() {
|
|
1539
|
+
if (this.rafId !== null) {
|
|
1540
|
+
this.deps.cancelFrame(this.rafId);
|
|
1541
|
+
this.rafId = null;
|
|
1542
|
+
}
|
|
1543
|
+
this.samples = [];
|
|
1544
|
+
this.vx = 0;
|
|
1545
|
+
this.vy = 0;
|
|
1546
|
+
}
|
|
1547
|
+
};
|
|
1548
|
+
|
|
1474
1549
|
// src/canvas/input-handler.ts
|
|
1475
1550
|
var ZOOM_SENSITIVITY = 1e-3;
|
|
1476
1551
|
var MIDDLE_BUTTON = 1;
|
|
@@ -1496,6 +1571,16 @@ var InputHandler = class {
|
|
|
1496
1571
|
getLastPointerWorld: () => this.lastPointerWorld()
|
|
1497
1572
|
});
|
|
1498
1573
|
this.openContextMenu = options.openContextMenu;
|
|
1574
|
+
this.panInertiaEnabled = options.panInertia ?? true;
|
|
1575
|
+
this.panInertia = new PanInertia({
|
|
1576
|
+
pan: (dx, dy) => this.camera.pan(dx, dy),
|
|
1577
|
+
now: () => typeof performance !== "undefined" ? performance.now() : Date.now(),
|
|
1578
|
+
requestFrame: (cb) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(cb) : 0,
|
|
1579
|
+
cancelFrame: (id) => {
|
|
1580
|
+
if (typeof cancelAnimationFrame !== "undefined") cancelAnimationFrame(id);
|
|
1581
|
+
},
|
|
1582
|
+
enabled: () => this.panInertiaEnabled
|
|
1583
|
+
});
|
|
1499
1584
|
this.scope = options.shortcuts?.scope ?? "focus";
|
|
1500
1585
|
this.keyboard = new KeyboardHandler({
|
|
1501
1586
|
element: this.element,
|
|
@@ -1545,6 +1630,8 @@ var InputHandler = class {
|
|
|
1545
1630
|
keyboard;
|
|
1546
1631
|
scope;
|
|
1547
1632
|
openContextMenu;
|
|
1633
|
+
panInertia;
|
|
1634
|
+
panInertiaEnabled;
|
|
1548
1635
|
setToolManager(toolManager, toolContext) {
|
|
1549
1636
|
this.toolManager = toolManager;
|
|
1550
1637
|
this.toolContext = toolContext;
|
|
@@ -1556,6 +1643,7 @@ var InputHandler = class {
|
|
|
1556
1643
|
return this.keyboard.shortcuts;
|
|
1557
1644
|
}
|
|
1558
1645
|
destroy() {
|
|
1646
|
+
this.panInertia.cancel();
|
|
1559
1647
|
this.actions.dispose();
|
|
1560
1648
|
this.abortController.abort();
|
|
1561
1649
|
this.inputFilter.reset();
|
|
@@ -1579,6 +1667,7 @@ var InputHandler = class {
|
|
|
1579
1667
|
}
|
|
1580
1668
|
onWheel = (e) => {
|
|
1581
1669
|
e.preventDefault();
|
|
1670
|
+
this.panInertia.cancel();
|
|
1582
1671
|
const rect = this.element.getBoundingClientRect();
|
|
1583
1672
|
const zoomFactor = 1 - e.deltaY * ZOOM_SENSITIVITY;
|
|
1584
1673
|
const newZoom = this.camera.zoom * zoomFactor;
|
|
@@ -1588,6 +1677,7 @@ var InputHandler = class {
|
|
|
1588
1677
|
});
|
|
1589
1678
|
};
|
|
1590
1679
|
onPointerDown = (e) => {
|
|
1680
|
+
this.panInertia.cancel();
|
|
1591
1681
|
this.focusSelf();
|
|
1592
1682
|
this.activePointers.set(e.pointerId, { x: e.clientX, y: e.clientY });
|
|
1593
1683
|
this.element.setPointerCapture?.(e.pointerId);
|
|
@@ -1628,6 +1718,7 @@ var InputHandler = class {
|
|
|
1628
1718
|
const dy = e.clientY - this.lastPointer.y;
|
|
1629
1719
|
this.lastPointer = { x: e.clientX, y: e.clientY };
|
|
1630
1720
|
this.camera.pan(dx, dy);
|
|
1721
|
+
this.panInertia.sample(dx, dy);
|
|
1631
1722
|
return;
|
|
1632
1723
|
}
|
|
1633
1724
|
if (e.pointerType === "pen" && !this.activePointers.has(e.pointerId)) {
|
|
@@ -1658,6 +1749,7 @@ var InputHandler = class {
|
|
|
1658
1749
|
}
|
|
1659
1750
|
if (this.isPanning && this.activePointers.size === 0) {
|
|
1660
1751
|
this.isPanning = false;
|
|
1752
|
+
this.panInertia.release();
|
|
1661
1753
|
}
|
|
1662
1754
|
const upResult = this.inputFilter.filterUp(e);
|
|
1663
1755
|
if (this.isToolActive) {
|
|
@@ -1678,6 +1770,7 @@ var InputHandler = class {
|
|
|
1678
1770
|
return this.actions.hasClipboard();
|
|
1679
1771
|
}
|
|
1680
1772
|
startPinch() {
|
|
1773
|
+
this.panInertia.cancel();
|
|
1681
1774
|
this.cancelLongPress();
|
|
1682
1775
|
this.inputFilter.reset();
|
|
1683
1776
|
this.deferredDown = null;
|
|
@@ -1699,6 +1792,7 @@ var InputHandler = class {
|
|
|
1699
1792
|
const dx = center2.x - this.lastPointer.x;
|
|
1700
1793
|
const dy = center2.y - this.lastPointer.y;
|
|
1701
1794
|
this.camera.pan(dx, dy);
|
|
1795
|
+
this.panInertia.sample(dx, dy);
|
|
1702
1796
|
this.lastPinchDistance = dist;
|
|
1703
1797
|
this.lastPinchCenter = center2;
|
|
1704
1798
|
this.lastPointer = { ...center2 };
|
|
@@ -4183,6 +4277,135 @@ var ContextMenu = class {
|
|
|
4183
4277
|
}
|
|
4184
4278
|
};
|
|
4185
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
|
+
|
|
4186
4409
|
// src/canvas/viewport-dom.ts
|
|
4187
4410
|
function createWrapper() {
|
|
4188
4411
|
const el = document.createElement("div");
|
|
@@ -6308,7 +6531,7 @@ function getElementStyle(element) {
|
|
|
6308
6531
|
}
|
|
6309
6532
|
|
|
6310
6533
|
// src/canvas/selection-ops.ts
|
|
6311
|
-
function
|
|
6534
|
+
function unionBounds2(list) {
|
|
6312
6535
|
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
6313
6536
|
for (const b of list) {
|
|
6314
6537
|
minX = Math.min(minX, b.x);
|
|
@@ -6403,7 +6626,7 @@ var SelectionOps = class {
|
|
|
6403
6626
|
align(edge) {
|
|
6404
6627
|
const bounded = this.boundedSelection();
|
|
6405
6628
|
if (bounded.length < 2) return;
|
|
6406
|
-
const B =
|
|
6629
|
+
const B = unionBounds2(bounded.map((e) => e.bounds));
|
|
6407
6630
|
this.deps.recorder.begin();
|
|
6408
6631
|
const moved = [];
|
|
6409
6632
|
for (const { id, el, bounds: b } of bounded) {
|
|
@@ -6800,7 +7023,8 @@ var Viewport = class {
|
|
|
6800
7023
|
shortcuts: options.shortcuts,
|
|
6801
7024
|
addImage: (src, world) => this.addImage(src, world),
|
|
6802
7025
|
getCenteredWorld: () => this.centeredPosition({ w: 300, h: 200 }),
|
|
6803
|
-
onPaste: options.onPaste
|
|
7026
|
+
onPaste: options.onPaste,
|
|
7027
|
+
panInertia: options.panInertia
|
|
6804
7028
|
});
|
|
6805
7029
|
if (options.contextMenu !== false) {
|
|
6806
7030
|
this.contextMenu = new ContextMenu({
|
|
@@ -6809,6 +7033,27 @@ var Viewport = class {
|
|
|
6809
7033
|
});
|
|
6810
7034
|
}
|
|
6811
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
|
+
}
|
|
6812
7057
|
this.domNodeManager = new DomNodeManager({
|
|
6813
7058
|
domLayer: this.domLayer,
|
|
6814
7059
|
onEditRequest: (id) => this.interactions.startEditingElement(id),
|
|
@@ -6841,6 +7086,7 @@ var Viewport = class {
|
|
|
6841
7086
|
this.applyCameraTransform();
|
|
6842
7087
|
this.noteEditor.updateToolbarPosition();
|
|
6843
7088
|
this.contextMenu?.close();
|
|
7089
|
+
this.minimap?.scheduleDraw();
|
|
6844
7090
|
this.requestRender();
|
|
6845
7091
|
});
|
|
6846
7092
|
this.gridController = new GridController({
|
|
@@ -6855,6 +7101,7 @@ var Viewport = class {
|
|
|
6855
7101
|
this.store.on("add", (el) => {
|
|
6856
7102
|
if (el.type === "grid") this.gridController.syncContext();
|
|
6857
7103
|
this.renderLoop.markLayerDirty(el.layerId);
|
|
7104
|
+
this.minimap?.scheduleDraw();
|
|
6858
7105
|
this.requestRender();
|
|
6859
7106
|
}),
|
|
6860
7107
|
this.store.on("remove", (el) => {
|
|
@@ -6862,6 +7109,7 @@ var Viewport = class {
|
|
|
6862
7109
|
this.unbindArrowsFrom(el);
|
|
6863
7110
|
this.domNodeManager.removeDomNode(el.id);
|
|
6864
7111
|
this.renderLoop.markLayerDirty(el.layerId);
|
|
7112
|
+
this.minimap?.scheduleDraw();
|
|
6865
7113
|
this.requestRender();
|
|
6866
7114
|
}),
|
|
6867
7115
|
this.store.on("update", ({ previous, current }) => {
|
|
@@ -6870,17 +7118,20 @@ var Viewport = class {
|
|
|
6870
7118
|
if (previous.layerId !== current.layerId) {
|
|
6871
7119
|
this.renderLoop.markLayerDirty(previous.layerId);
|
|
6872
7120
|
}
|
|
7121
|
+
this.minimap?.scheduleDraw();
|
|
6873
7122
|
this.requestRender();
|
|
6874
7123
|
}),
|
|
6875
7124
|
this.store.on("clear", () => {
|
|
6876
7125
|
this.domNodeManager.clearDomNodes();
|
|
6877
7126
|
this.renderLoop.markAllLayersDirty();
|
|
6878
7127
|
this.gridController.syncContext();
|
|
7128
|
+
this.minimap?.scheduleDraw();
|
|
6879
7129
|
this.requestRender();
|
|
6880
7130
|
})
|
|
6881
7131
|
];
|
|
6882
7132
|
this.layerManager.on("change", () => {
|
|
6883
7133
|
this.toolContext.activeLayerId = this.layerManager.activeLayerId;
|
|
7134
|
+
this.minimap?.scheduleDraw();
|
|
6884
7135
|
this.requestRender();
|
|
6885
7136
|
});
|
|
6886
7137
|
this.interactions = new ViewportInteractions({
|
|
@@ -6940,6 +7191,7 @@ var Viewport = class {
|
|
|
6940
7191
|
gridController;
|
|
6941
7192
|
interactions;
|
|
6942
7193
|
contextMenu = null;
|
|
7194
|
+
minimap = null;
|
|
6943
7195
|
htmlRenderers = /* @__PURE__ */ new Map();
|
|
6944
7196
|
get ctx() {
|
|
6945
7197
|
return this.canvasEl.getContext("2d");
|
|
@@ -7213,6 +7465,7 @@ var Viewport = class {
|
|
|
7213
7465
|
this.arrowLabelEditor.cancel();
|
|
7214
7466
|
this.historyRecorder.destroy();
|
|
7215
7467
|
this.contextMenu?.dispose();
|
|
7468
|
+
this.minimap?.destroy();
|
|
7216
7469
|
this.wrapper.removeEventListener("pointerdown", this.interactions.onTapDown);
|
|
7217
7470
|
this.wrapper.removeEventListener("pointerup", this.interactions.onDoubleTap);
|
|
7218
7471
|
this.wrapper.removeEventListener("dragover", this.interactions.onDragOver);
|
|
@@ -9715,7 +9968,7 @@ var LaserTool = class {
|
|
|
9715
9968
|
};
|
|
9716
9969
|
|
|
9717
9970
|
// src/index.ts
|
|
9718
|
-
var VERSION = "0.
|
|
9971
|
+
var VERSION = "0.43.0";
|
|
9719
9972
|
export {
|
|
9720
9973
|
ArrowTool,
|
|
9721
9974
|
AutoSave,
|