@fieldnotes/core 0.58.0 → 0.60.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 +206 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +62 -2
- package/dist/index.d.ts +62 -2
- package/dist/index.js +206 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -410,6 +410,7 @@ declare class ToolManager {
|
|
|
410
410
|
private tools;
|
|
411
411
|
private current;
|
|
412
412
|
private changeListeners;
|
|
413
|
+
private registerListeners;
|
|
413
414
|
get activeTool(): Tool | null;
|
|
414
415
|
get toolNames(): string[];
|
|
415
416
|
register(tool: Tool): void;
|
|
@@ -419,6 +420,7 @@ declare class ToolManager {
|
|
|
419
420
|
handlePointerMove(state: PointerState, ctx: ToolContext): void;
|
|
420
421
|
handlePointerUp(state: PointerState, ctx: ToolContext): void;
|
|
421
422
|
onChange(listener: (name: string) => void): () => void;
|
|
423
|
+
onRegister(listener: (tool: Tool) => void): () => void;
|
|
422
424
|
}
|
|
423
425
|
|
|
424
426
|
interface Command {
|
|
@@ -469,6 +471,32 @@ interface ExportImageOptions extends ExportResourceOptions, HtmlExportOptions {
|
|
|
469
471
|
padding?: number;
|
|
470
472
|
background?: string;
|
|
471
473
|
filter?: (element: CanvasElement) => boolean;
|
|
474
|
+
/**
|
|
475
|
+
* Optional world-space crop. When set it replaces the computed content
|
|
476
|
+
* bounds; `padding` still applies around it. Elements outside the region
|
|
477
|
+
* clip naturally. A region export with no intersecting elements still
|
|
478
|
+
* produces a background-filled image.
|
|
479
|
+
*/
|
|
480
|
+
region?: {
|
|
481
|
+
x: number;
|
|
482
|
+
y: number;
|
|
483
|
+
w: number;
|
|
484
|
+
h: number;
|
|
485
|
+
};
|
|
486
|
+
/**
|
|
487
|
+
* Output encoding. Defaults to 'png'. JPEG output is opaque — a transparent
|
|
488
|
+
* `background` renders as black; keep the default `#ffffff` (or any opaque color)
|
|
489
|
+
* for JPEG exports.
|
|
490
|
+
*/
|
|
491
|
+
format?: 'png' | 'jpeg';
|
|
492
|
+
/** Encoder quality in (0, 1]. Only meaningful for 'jpeg'. */
|
|
493
|
+
quality?: number;
|
|
494
|
+
/**
|
|
495
|
+
* 'exact' (default) throws when scale × bounds exceeds maxDimension/maxPixels.
|
|
496
|
+
* 'fit' reduces the effective scale to the largest value that satisfies both
|
|
497
|
+
* caps (never above the requested scale).
|
|
498
|
+
*/
|
|
499
|
+
scaleMode?: 'exact' | 'fit';
|
|
472
500
|
}
|
|
473
501
|
type ExportAssetErrorReason = 'load' | 'timeout' | 'encode';
|
|
474
502
|
interface ExportAssetError {
|
|
@@ -532,6 +560,11 @@ declare function getElementStyle(element: CanvasElement): ElementStyle;
|
|
|
532
560
|
|
|
533
561
|
type RotateDirection = 'cw' | 'ccw';
|
|
534
562
|
|
|
563
|
+
interface SelectionStyleDetails {
|
|
564
|
+
common: ElementStyle;
|
|
565
|
+
applicable: readonly (keyof ElementStyle)[];
|
|
566
|
+
mixed: readonly (keyof ElementStyle)[];
|
|
567
|
+
}
|
|
535
568
|
type AlignEdge = 'left' | 'center-x' | 'right' | 'top' | 'middle' | 'bottom';
|
|
536
569
|
type DistributeAxis = 'horizontal' | 'vertical';
|
|
537
570
|
|
|
@@ -611,6 +644,11 @@ declare class Viewport {
|
|
|
611
644
|
private minimap;
|
|
612
645
|
private readonly htmlRenderers;
|
|
613
646
|
private readonly resizeListeners;
|
|
647
|
+
private readonly selectionListeners;
|
|
648
|
+
private detachSelectionSource;
|
|
649
|
+
private unsubToolRegister;
|
|
650
|
+
private pendingSelectionPrune;
|
|
651
|
+
private unsubRecorderEnd;
|
|
614
652
|
constructor(container: HTMLElement, options?: ViewportOptions);
|
|
615
653
|
get ctx(): CanvasRenderingContext2D | null;
|
|
616
654
|
get snapToGrid(): boolean;
|
|
@@ -704,12 +742,34 @@ declare class Viewport {
|
|
|
704
742
|
getGridInfo(): GridInfo | null;
|
|
705
743
|
onGridChange(listener: (info: GridInfo | null) => void): () => void;
|
|
706
744
|
private getSelectTool;
|
|
745
|
+
private pruneSelection;
|
|
746
|
+
private handleRemovedElement;
|
|
747
|
+
private static isSelectionSource;
|
|
748
|
+
private emitSelectionChange;
|
|
749
|
+
private attachSelectionSource;
|
|
750
|
+
/**
|
|
751
|
+
* getSelectedIds() and the onSelectionChange emitter never surface stale ids:
|
|
752
|
+
* once the enclosing history transaction completes, both reflect
|
|
753
|
+
* the current selection.
|
|
754
|
+
*/
|
|
707
755
|
getSelectedIds(): string[];
|
|
708
756
|
runAction(action: string): void;
|
|
709
757
|
canPaste(): boolean;
|
|
710
758
|
openContextMenu(screenPos: Point): void;
|
|
759
|
+
/**
|
|
760
|
+
* Persistent, viewport-owned selection-change emitter. Subscribing works
|
|
761
|
+
* regardless of whether a select tool is registered yet; it forwards
|
|
762
|
+
* events from whichever select tool is currently attached via
|
|
763
|
+
* `toolManager.onRegister`. Never delivers stale ids once the enclosing
|
|
764
|
+
* history transaction completes.
|
|
765
|
+
*/
|
|
711
766
|
onSelectionChange(listener: () => void): () => void;
|
|
712
767
|
getSelectionStyle(): ElementStyle | null;
|
|
768
|
+
/**
|
|
769
|
+
* Unlike `getSelectionStyle()` — which returns `{}` for a style-less
|
|
770
|
+
* selection — this returns `null` when no style field is applicable.
|
|
771
|
+
*/
|
|
772
|
+
getSelectionStyleDetails(): SelectionStyleDetails | null;
|
|
713
773
|
applyStyleToSelection(style: ElementStyle): void;
|
|
714
774
|
groupSelection(): void;
|
|
715
775
|
ungroupSelection(): void;
|
|
@@ -1729,6 +1789,6 @@ declare class TemplateTool implements Tool {
|
|
|
1729
1789
|
private notifyOptionsChange;
|
|
1730
1790
|
}
|
|
1731
1791
|
|
|
1732
|
-
declare const VERSION = "0.
|
|
1792
|
+
declare const VERSION = "0.60.0";
|
|
1733
1793
|
|
|
1734
|
-
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 ExportAssetError, type ExportAssetErrorReason, type ExportImageOptions, type ExportResourceOptions, type ExportSvgOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type HtmlExportError, type HtmlExportErrorReason, type HtmlExportOptions, type HtmlExportRenderer, type ImageElement, ImageTool, type ImageToolOptions, IndexedDBAdapter, type IndexedDBAdapterOptions, LASER_TRAIL_PRESENCE_KIND, LaserTool, type LaserToolOptions, type LaserTrailEmission, type LaserTrailPresence, type Layer, LayerManager, LocalStorageAdapter, MEASURE_PRESENCE_KIND, type MeasureEmission, type MeasurePresence, MeasureTool, type MeasureToolOptions, type Measurement, MemoryAdapter, MinimapController, type MinimapControllerOptions, type NoteElement, NoteTool, type NoteToolOptions, type OverlayRenderer, PING_PRESENCE_KIND, PencilTool, type PencilToolOptions, type PingEmission, PingInput, type PingInputHost, type PingInputOptions, type PingPresence, PingTool, type PingToolOptions, type Point, type PointerState, RemoteLaserOverlay, type RemoteLaserOverlayHost, type RemoteLaserOverlayOptions, RemoteMeasureOverlay, type RemoteMeasureOverlayHost, type RemoteMeasureOverlayOptions, RemotePingOverlay, type RemotePingOverlayHost, type RemotePingOverlayOptions, 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, isLaserTrailPresence, isMeasurePresence, isNearBezier, isPingPresence, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toLaserTrailPresence, toMeasurePresence, toPingPresence, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
|
|
1794
|
+
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 ExportAssetError, type ExportAssetErrorReason, type ExportImageOptions, type ExportResourceOptions, type ExportSvgOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type HtmlExportError, type HtmlExportErrorReason, type HtmlExportOptions, type HtmlExportRenderer, type ImageElement, ImageTool, type ImageToolOptions, IndexedDBAdapter, type IndexedDBAdapterOptions, LASER_TRAIL_PRESENCE_KIND, LaserTool, type LaserToolOptions, type LaserTrailEmission, type LaserTrailPresence, type Layer, LayerManager, LocalStorageAdapter, MEASURE_PRESENCE_KIND, type MeasureEmission, type MeasurePresence, MeasureTool, type MeasureToolOptions, type Measurement, MemoryAdapter, MinimapController, type MinimapControllerOptions, type NoteElement, NoteTool, type NoteToolOptions, type OverlayRenderer, PING_PRESENCE_KIND, PencilTool, type PencilToolOptions, type PingEmission, PingInput, type PingInputHost, type PingInputOptions, type PingPresence, PingTool, type PingToolOptions, type Point, type PointerState, RemoteLaserOverlay, type RemoteLaserOverlayHost, type RemoteLaserOverlayOptions, RemoteMeasureOverlay, type RemoteMeasureOverlayHost, type RemoteMeasureOverlayOptions, RemotePingOverlay, type RemotePingOverlayHost, type RemotePingOverlayOptions, type RenderStatsSnapshot, type RotateDirection, SelectTool, type SelectionStyleDetails, 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, isLaserTrailPresence, isMeasurePresence, isNearBezier, isPingPresence, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toLaserTrailPresence, toMeasurePresence, toPingPresence, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
|
package/dist/index.d.ts
CHANGED
|
@@ -410,6 +410,7 @@ declare class ToolManager {
|
|
|
410
410
|
private tools;
|
|
411
411
|
private current;
|
|
412
412
|
private changeListeners;
|
|
413
|
+
private registerListeners;
|
|
413
414
|
get activeTool(): Tool | null;
|
|
414
415
|
get toolNames(): string[];
|
|
415
416
|
register(tool: Tool): void;
|
|
@@ -419,6 +420,7 @@ declare class ToolManager {
|
|
|
419
420
|
handlePointerMove(state: PointerState, ctx: ToolContext): void;
|
|
420
421
|
handlePointerUp(state: PointerState, ctx: ToolContext): void;
|
|
421
422
|
onChange(listener: (name: string) => void): () => void;
|
|
423
|
+
onRegister(listener: (tool: Tool) => void): () => void;
|
|
422
424
|
}
|
|
423
425
|
|
|
424
426
|
interface Command {
|
|
@@ -469,6 +471,32 @@ interface ExportImageOptions extends ExportResourceOptions, HtmlExportOptions {
|
|
|
469
471
|
padding?: number;
|
|
470
472
|
background?: string;
|
|
471
473
|
filter?: (element: CanvasElement) => boolean;
|
|
474
|
+
/**
|
|
475
|
+
* Optional world-space crop. When set it replaces the computed content
|
|
476
|
+
* bounds; `padding` still applies around it. Elements outside the region
|
|
477
|
+
* clip naturally. A region export with no intersecting elements still
|
|
478
|
+
* produces a background-filled image.
|
|
479
|
+
*/
|
|
480
|
+
region?: {
|
|
481
|
+
x: number;
|
|
482
|
+
y: number;
|
|
483
|
+
w: number;
|
|
484
|
+
h: number;
|
|
485
|
+
};
|
|
486
|
+
/**
|
|
487
|
+
* Output encoding. Defaults to 'png'. JPEG output is opaque — a transparent
|
|
488
|
+
* `background` renders as black; keep the default `#ffffff` (or any opaque color)
|
|
489
|
+
* for JPEG exports.
|
|
490
|
+
*/
|
|
491
|
+
format?: 'png' | 'jpeg';
|
|
492
|
+
/** Encoder quality in (0, 1]. Only meaningful for 'jpeg'. */
|
|
493
|
+
quality?: number;
|
|
494
|
+
/**
|
|
495
|
+
* 'exact' (default) throws when scale × bounds exceeds maxDimension/maxPixels.
|
|
496
|
+
* 'fit' reduces the effective scale to the largest value that satisfies both
|
|
497
|
+
* caps (never above the requested scale).
|
|
498
|
+
*/
|
|
499
|
+
scaleMode?: 'exact' | 'fit';
|
|
472
500
|
}
|
|
473
501
|
type ExportAssetErrorReason = 'load' | 'timeout' | 'encode';
|
|
474
502
|
interface ExportAssetError {
|
|
@@ -532,6 +560,11 @@ declare function getElementStyle(element: CanvasElement): ElementStyle;
|
|
|
532
560
|
|
|
533
561
|
type RotateDirection = 'cw' | 'ccw';
|
|
534
562
|
|
|
563
|
+
interface SelectionStyleDetails {
|
|
564
|
+
common: ElementStyle;
|
|
565
|
+
applicable: readonly (keyof ElementStyle)[];
|
|
566
|
+
mixed: readonly (keyof ElementStyle)[];
|
|
567
|
+
}
|
|
535
568
|
type AlignEdge = 'left' | 'center-x' | 'right' | 'top' | 'middle' | 'bottom';
|
|
536
569
|
type DistributeAxis = 'horizontal' | 'vertical';
|
|
537
570
|
|
|
@@ -611,6 +644,11 @@ declare class Viewport {
|
|
|
611
644
|
private minimap;
|
|
612
645
|
private readonly htmlRenderers;
|
|
613
646
|
private readonly resizeListeners;
|
|
647
|
+
private readonly selectionListeners;
|
|
648
|
+
private detachSelectionSource;
|
|
649
|
+
private unsubToolRegister;
|
|
650
|
+
private pendingSelectionPrune;
|
|
651
|
+
private unsubRecorderEnd;
|
|
614
652
|
constructor(container: HTMLElement, options?: ViewportOptions);
|
|
615
653
|
get ctx(): CanvasRenderingContext2D | null;
|
|
616
654
|
get snapToGrid(): boolean;
|
|
@@ -704,12 +742,34 @@ declare class Viewport {
|
|
|
704
742
|
getGridInfo(): GridInfo | null;
|
|
705
743
|
onGridChange(listener: (info: GridInfo | null) => void): () => void;
|
|
706
744
|
private getSelectTool;
|
|
745
|
+
private pruneSelection;
|
|
746
|
+
private handleRemovedElement;
|
|
747
|
+
private static isSelectionSource;
|
|
748
|
+
private emitSelectionChange;
|
|
749
|
+
private attachSelectionSource;
|
|
750
|
+
/**
|
|
751
|
+
* getSelectedIds() and the onSelectionChange emitter never surface stale ids:
|
|
752
|
+
* once the enclosing history transaction completes, both reflect
|
|
753
|
+
* the current selection.
|
|
754
|
+
*/
|
|
707
755
|
getSelectedIds(): string[];
|
|
708
756
|
runAction(action: string): void;
|
|
709
757
|
canPaste(): boolean;
|
|
710
758
|
openContextMenu(screenPos: Point): void;
|
|
759
|
+
/**
|
|
760
|
+
* Persistent, viewport-owned selection-change emitter. Subscribing works
|
|
761
|
+
* regardless of whether a select tool is registered yet; it forwards
|
|
762
|
+
* events from whichever select tool is currently attached via
|
|
763
|
+
* `toolManager.onRegister`. Never delivers stale ids once the enclosing
|
|
764
|
+
* history transaction completes.
|
|
765
|
+
*/
|
|
711
766
|
onSelectionChange(listener: () => void): () => void;
|
|
712
767
|
getSelectionStyle(): ElementStyle | null;
|
|
768
|
+
/**
|
|
769
|
+
* Unlike `getSelectionStyle()` — which returns `{}` for a style-less
|
|
770
|
+
* selection — this returns `null` when no style field is applicable.
|
|
771
|
+
*/
|
|
772
|
+
getSelectionStyleDetails(): SelectionStyleDetails | null;
|
|
713
773
|
applyStyleToSelection(style: ElementStyle): void;
|
|
714
774
|
groupSelection(): void;
|
|
715
775
|
ungroupSelection(): void;
|
|
@@ -1729,6 +1789,6 @@ declare class TemplateTool implements Tool {
|
|
|
1729
1789
|
private notifyOptionsChange;
|
|
1730
1790
|
}
|
|
1731
1791
|
|
|
1732
|
-
declare const VERSION = "0.
|
|
1792
|
+
declare const VERSION = "0.60.0";
|
|
1733
1793
|
|
|
1734
|
-
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 ExportAssetError, type ExportAssetErrorReason, type ExportImageOptions, type ExportResourceOptions, type ExportSvgOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type HtmlExportError, type HtmlExportErrorReason, type HtmlExportOptions, type HtmlExportRenderer, type ImageElement, ImageTool, type ImageToolOptions, IndexedDBAdapter, type IndexedDBAdapterOptions, LASER_TRAIL_PRESENCE_KIND, LaserTool, type LaserToolOptions, type LaserTrailEmission, type LaserTrailPresence, type Layer, LayerManager, LocalStorageAdapter, MEASURE_PRESENCE_KIND, type MeasureEmission, type MeasurePresence, MeasureTool, type MeasureToolOptions, type Measurement, MemoryAdapter, MinimapController, type MinimapControllerOptions, type NoteElement, NoteTool, type NoteToolOptions, type OverlayRenderer, PING_PRESENCE_KIND, PencilTool, type PencilToolOptions, type PingEmission, PingInput, type PingInputHost, type PingInputOptions, type PingPresence, PingTool, type PingToolOptions, type Point, type PointerState, RemoteLaserOverlay, type RemoteLaserOverlayHost, type RemoteLaserOverlayOptions, RemoteMeasureOverlay, type RemoteMeasureOverlayHost, type RemoteMeasureOverlayOptions, RemotePingOverlay, type RemotePingOverlayHost, type RemotePingOverlayOptions, 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, isLaserTrailPresence, isMeasurePresence, isNearBezier, isPingPresence, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toLaserTrailPresence, toMeasurePresence, toPingPresence, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
|
|
1794
|
+
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 ExportAssetError, type ExportAssetErrorReason, type ExportImageOptions, type ExportResourceOptions, type ExportSvgOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type HtmlExportError, type HtmlExportErrorReason, type HtmlExportOptions, type HtmlExportRenderer, type ImageElement, ImageTool, type ImageToolOptions, IndexedDBAdapter, type IndexedDBAdapterOptions, LASER_TRAIL_PRESENCE_KIND, LaserTool, type LaserToolOptions, type LaserTrailEmission, type LaserTrailPresence, type Layer, LayerManager, LocalStorageAdapter, MEASURE_PRESENCE_KIND, type MeasureEmission, type MeasurePresence, MeasureTool, type MeasureToolOptions, type Measurement, MemoryAdapter, MinimapController, type MinimapControllerOptions, type NoteElement, NoteTool, type NoteToolOptions, type OverlayRenderer, PING_PRESENCE_KIND, PencilTool, type PencilToolOptions, type PingEmission, PingInput, type PingInputHost, type PingInputOptions, type PingPresence, PingTool, type PingToolOptions, type Point, type PointerState, RemoteLaserOverlay, type RemoteLaserOverlayHost, type RemoteLaserOverlayOptions, RemoteMeasureOverlay, type RemoteMeasureOverlayHost, type RemoteMeasureOverlayOptions, RemotePingOverlay, type RemotePingOverlayHost, type RemotePingOverlayOptions, type RenderStatsSnapshot, type RotateDirection, SelectTool, type SelectionStyleDetails, 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, isLaserTrailPresence, isMeasurePresence, isNearBezier, isPingPresence, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toLaserTrailPresence, toMeasurePresence, toPingPresence, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
|
package/dist/index.js
CHANGED
|
@@ -5170,6 +5170,7 @@ var ToolManager = class {
|
|
|
5170
5170
|
tools = /* @__PURE__ */ new Map();
|
|
5171
5171
|
current = null;
|
|
5172
5172
|
changeListeners = /* @__PURE__ */ new Set();
|
|
5173
|
+
registerListeners = /* @__PURE__ */ new Set();
|
|
5173
5174
|
get activeTool() {
|
|
5174
5175
|
return this.current;
|
|
5175
5176
|
}
|
|
@@ -5178,6 +5179,7 @@ var ToolManager = class {
|
|
|
5178
5179
|
}
|
|
5179
5180
|
register(tool) {
|
|
5180
5181
|
this.tools.set(tool.name, tool);
|
|
5182
|
+
this.registerListeners.forEach((fn) => fn(tool));
|
|
5181
5183
|
}
|
|
5182
5184
|
getTool(name) {
|
|
5183
5185
|
return this.tools.get(name);
|
|
@@ -5203,6 +5205,10 @@ var ToolManager = class {
|
|
|
5203
5205
|
this.changeListeners.add(listener);
|
|
5204
5206
|
return () => this.changeListeners.delete(listener);
|
|
5205
5207
|
}
|
|
5208
|
+
onRegister(listener) {
|
|
5209
|
+
this.registerListeners.add(listener);
|
|
5210
|
+
return () => this.registerListeners.delete(listener);
|
|
5211
|
+
}
|
|
5206
5212
|
};
|
|
5207
5213
|
|
|
5208
5214
|
// src/history/history-stack.ts
|
|
@@ -5394,6 +5400,7 @@ var HistoryRecorder = class {
|
|
|
5394
5400
|
generation = 0;
|
|
5395
5401
|
updateSnapshots = /* @__PURE__ */ new Map();
|
|
5396
5402
|
unsubscribers;
|
|
5403
|
+
transactionEndListeners = /* @__PURE__ */ new Set();
|
|
5397
5404
|
pause() {
|
|
5398
5405
|
this.recording = false;
|
|
5399
5406
|
}
|
|
@@ -5411,19 +5418,35 @@ var HistoryRecorder = class {
|
|
|
5411
5418
|
get currentTransactionId() {
|
|
5412
5419
|
return this.transaction !== null ? this.generation : null;
|
|
5413
5420
|
}
|
|
5421
|
+
onTransactionEnd(listener) {
|
|
5422
|
+
this.transactionEndListeners.add(listener);
|
|
5423
|
+
return () => this.transactionEndListeners.delete(listener);
|
|
5424
|
+
}
|
|
5425
|
+
notifyTransactionEnd() {
|
|
5426
|
+
for (const listener of this.transactionEndListeners) {
|
|
5427
|
+
try {
|
|
5428
|
+
listener();
|
|
5429
|
+
} catch {
|
|
5430
|
+
}
|
|
5431
|
+
}
|
|
5432
|
+
}
|
|
5414
5433
|
commit() {
|
|
5415
5434
|
if (!this.transaction) return;
|
|
5416
5435
|
const finalCommands = this.flushUpdateSnapshots();
|
|
5417
5436
|
const all = [...this.transaction, ...finalCommands];
|
|
5418
5437
|
this.transaction = null;
|
|
5419
5438
|
this.updateSnapshots.clear();
|
|
5420
|
-
if (all.length
|
|
5421
|
-
|
|
5422
|
-
|
|
5439
|
+
if (all.length > 0) {
|
|
5440
|
+
const first = all[0];
|
|
5441
|
+
this.stack.push(all.length === 1 && first ? first : new BatchCommand(all));
|
|
5442
|
+
}
|
|
5443
|
+
this.notifyTransactionEnd();
|
|
5423
5444
|
}
|
|
5424
5445
|
rollback() {
|
|
5446
|
+
const wasOpen = this.transaction !== null;
|
|
5425
5447
|
this.transaction = null;
|
|
5426
5448
|
this.updateSnapshots.clear();
|
|
5449
|
+
if (wasOpen) this.notifyTransactionEnd();
|
|
5427
5450
|
}
|
|
5428
5451
|
destroy() {
|
|
5429
5452
|
this.unsubscribers.forEach((fn) => fn());
|
|
@@ -5753,6 +5776,19 @@ function computeBounds(elements, padding) {
|
|
|
5753
5776
|
h: maxY - minY + padding * 2
|
|
5754
5777
|
};
|
|
5755
5778
|
}
|
|
5779
|
+
function resolveExportBounds(region, elements, padding) {
|
|
5780
|
+
if (!region) return computeBounds(elements, padding);
|
|
5781
|
+
const finite = Number.isFinite(region.x) && Number.isFinite(region.y) && Number.isFinite(region.w) && Number.isFinite(region.h);
|
|
5782
|
+
if (!finite || region.w <= 0 || region.h <= 0) {
|
|
5783
|
+
throw new RangeError("region must have finite coordinates and positive w/h");
|
|
5784
|
+
}
|
|
5785
|
+
return {
|
|
5786
|
+
x: region.x - padding,
|
|
5787
|
+
y: region.y - padding,
|
|
5788
|
+
w: region.w + padding * 2,
|
|
5789
|
+
h: region.h + padding * 2
|
|
5790
|
+
};
|
|
5791
|
+
}
|
|
5756
5792
|
function renderGridForBounds(ctx, grid, bounds) {
|
|
5757
5793
|
const visibleBounds = {
|
|
5758
5794
|
minX: bounds.x,
|
|
@@ -5795,6 +5831,29 @@ function nonNegativeOption(value, fallback, name) {
|
|
|
5795
5831
|
}
|
|
5796
5832
|
return resolved;
|
|
5797
5833
|
}
|
|
5834
|
+
function fitExportScale(bounds, requestedScale, options) {
|
|
5835
|
+
const maxDimension = positiveOption(options.maxDimension, DEFAULT_MAX_DIMENSION, "maxDimension");
|
|
5836
|
+
const maxPixels = positiveOption(options.maxPixels, DEFAULT_MAX_PIXELS, "maxPixels");
|
|
5837
|
+
const fits = (scale) => {
|
|
5838
|
+
const w = Math.ceil(bounds.w * scale);
|
|
5839
|
+
const h = Math.ceil(bounds.h * scale);
|
|
5840
|
+
return w <= maxDimension && h <= maxDimension && w * h <= maxPixels;
|
|
5841
|
+
};
|
|
5842
|
+
if (fits(requestedScale)) return requestedScale;
|
|
5843
|
+
const analytical = Math.min(
|
|
5844
|
+
maxDimension / Math.max(bounds.w, bounds.h),
|
|
5845
|
+
Math.sqrt(maxPixels) / Math.sqrt(bounds.w) / Math.sqrt(bounds.h)
|
|
5846
|
+
);
|
|
5847
|
+
let hi = Math.min(requestedScale, analytical);
|
|
5848
|
+
if (fits(hi)) return hi;
|
|
5849
|
+
let lo = 0;
|
|
5850
|
+
for (let i = 0; i < 40; i++) {
|
|
5851
|
+
const mid = (lo + hi) / 2;
|
|
5852
|
+
if (fits(mid)) lo = mid;
|
|
5853
|
+
else hi = mid;
|
|
5854
|
+
}
|
|
5855
|
+
return lo;
|
|
5856
|
+
}
|
|
5798
5857
|
function assertExportSize(width, height, options) {
|
|
5799
5858
|
const maxDimension = positiveOption(options.maxDimension, DEFAULT_MAX_DIMENSION, "maxDimension");
|
|
5800
5859
|
const maxPixels = positiveOption(options.maxPixels, DEFAULT_MAX_PIXELS, "maxPixels");
|
|
@@ -5869,10 +5928,23 @@ function loadImages(elements, options = {}) {
|
|
|
5869
5928
|
});
|
|
5870
5929
|
}
|
|
5871
5930
|
async function exportImage(store, options = {}, layerManager) {
|
|
5872
|
-
const
|
|
5931
|
+
const requestedScale = positiveOption(options.scale, 2, "scale");
|
|
5932
|
+
const scaleMode = options.scaleMode ?? "exact";
|
|
5933
|
+
if (scaleMode !== "exact" && scaleMode !== "fit") {
|
|
5934
|
+
throw new RangeError(`scaleMode must be 'exact' or 'fit'`);
|
|
5935
|
+
}
|
|
5873
5936
|
const padding = nonNegativeOption(options.padding, 0, "padding");
|
|
5874
5937
|
validateExportResourceOptions(options);
|
|
5875
5938
|
validateHtmlExportOptions(options);
|
|
5939
|
+
const format = options.format ?? "png";
|
|
5940
|
+
if (format !== "png" && format !== "jpeg") {
|
|
5941
|
+
throw new RangeError(`format must be 'png' or 'jpeg'`);
|
|
5942
|
+
}
|
|
5943
|
+
if (options.quality !== void 0) {
|
|
5944
|
+
if (!Number.isFinite(options.quality) || options.quality <= 0 || options.quality > 1) {
|
|
5945
|
+
throw new RangeError("quality must be a finite number in (0, 1]");
|
|
5946
|
+
}
|
|
5947
|
+
}
|
|
5876
5948
|
const background = options.background ?? "#ffffff";
|
|
5877
5949
|
const filter = options.filter;
|
|
5878
5950
|
const allElements = store.getAll();
|
|
@@ -5880,8 +5952,9 @@ async function exportImage(store, options = {}, layerManager) {
|
|
|
5880
5952
|
if (filter) {
|
|
5881
5953
|
visibleElements = visibleElements.filter(filter);
|
|
5882
5954
|
}
|
|
5883
|
-
const bounds =
|
|
5955
|
+
const bounds = resolveExportBounds(options.region, visibleElements, padding);
|
|
5884
5956
|
if (!bounds) return null;
|
|
5957
|
+
const scale = scaleMode === "fit" ? fitExportScale(bounds, requestedScale, options) : requestedScale;
|
|
5885
5958
|
const width = Math.ceil(bounds.w * scale);
|
|
5886
5959
|
const height = Math.ceil(bounds.h * scale);
|
|
5887
5960
|
assertExportSize(width, height, options);
|
|
@@ -5983,8 +6056,9 @@ async function exportImage(store, options = {}, layerManager) {
|
|
|
5983
6056
|
renderGridForBounds(ctx, grid, bounds);
|
|
5984
6057
|
ctx.restore();
|
|
5985
6058
|
}
|
|
6059
|
+
const mimeType = format === "jpeg" ? "image/jpeg" : "image/png";
|
|
5986
6060
|
return new Promise((resolve) => {
|
|
5987
|
-
canvas.toBlob((blob) => resolve(blob),
|
|
6061
|
+
canvas.toBlob((blob) => resolve(blob), mimeType, options.quality);
|
|
5988
6062
|
});
|
|
5989
6063
|
}
|
|
5990
6064
|
|
|
@@ -7664,6 +7738,14 @@ function rotateElementPatch(el, bounds, pivot, delta) {
|
|
|
7664
7738
|
}
|
|
7665
7739
|
|
|
7666
7740
|
// src/canvas/selection-ops.ts
|
|
7741
|
+
var STYLE_FIELDS = [
|
|
7742
|
+
"color",
|
|
7743
|
+
"fillColor",
|
|
7744
|
+
"strokeWidth",
|
|
7745
|
+
"opacity",
|
|
7746
|
+
"fontSize",
|
|
7747
|
+
"strokeStyle"
|
|
7748
|
+
];
|
|
7667
7749
|
function sharedValue(values) {
|
|
7668
7750
|
const present = values.filter((v) => v !== void 0);
|
|
7669
7751
|
if (present.length === 0) return void 0;
|
|
@@ -7698,6 +7780,42 @@ var SelectionOps = class {
|
|
|
7698
7780
|
if (strokeStyle !== void 0) result.strokeStyle = strokeStyle;
|
|
7699
7781
|
return result;
|
|
7700
7782
|
}
|
|
7783
|
+
/**
|
|
7784
|
+
* Unlike `getStyle()` — which returns `{}` for a selection whose elements
|
|
7785
|
+
* have no applicable style fields (e.g. images) — this returns `null` when
|
|
7786
|
+
* no field is applicable, so callers can distinguish "nothing to show" from
|
|
7787
|
+
* "everything shared but empty".
|
|
7788
|
+
*/
|
|
7789
|
+
getStyleDetails() {
|
|
7790
|
+
const ids = this.deps.getSelectedIds();
|
|
7791
|
+
if (ids.length === 0) return null;
|
|
7792
|
+
const styles = [];
|
|
7793
|
+
for (const id of ids) {
|
|
7794
|
+
const el = this.deps.store.getById(id);
|
|
7795
|
+
if (el) styles.push(getElementStyle(el));
|
|
7796
|
+
}
|
|
7797
|
+
if (styles.length === 0) return null;
|
|
7798
|
+
const common = {};
|
|
7799
|
+
const applicable = [];
|
|
7800
|
+
const mixed = [];
|
|
7801
|
+
for (const field of STYLE_FIELDS) {
|
|
7802
|
+
const allValues = styles.map((s) => s[field]);
|
|
7803
|
+
const values = [];
|
|
7804
|
+
for (const v of allValues) {
|
|
7805
|
+
if (v !== void 0) values.push(v);
|
|
7806
|
+
}
|
|
7807
|
+
if (values.length === 0) continue;
|
|
7808
|
+
applicable.push(field);
|
|
7809
|
+
const distinct = new Set(values);
|
|
7810
|
+
if (distinct.size > 1) {
|
|
7811
|
+
mixed.push(field);
|
|
7812
|
+
} else {
|
|
7813
|
+
common[field] = values[0];
|
|
7814
|
+
}
|
|
7815
|
+
}
|
|
7816
|
+
if (applicable.length === 0) return null;
|
|
7817
|
+
return { common, applicable, mixed };
|
|
7818
|
+
}
|
|
7701
7819
|
applyStyle(style) {
|
|
7702
7820
|
const ids = this.deps.getSelectedIds();
|
|
7703
7821
|
if (ids.length === 0) return;
|
|
@@ -8072,7 +8190,7 @@ var ViewportInteractions = class {
|
|
|
8072
8190
|
var EMPTY_IDS = [];
|
|
8073
8191
|
function noop() {
|
|
8074
8192
|
}
|
|
8075
|
-
var Viewport = class {
|
|
8193
|
+
var Viewport = class _Viewport {
|
|
8076
8194
|
constructor(container, options = {}) {
|
|
8077
8195
|
this.container = container;
|
|
8078
8196
|
this.camera = new Camera(options.camera);
|
|
@@ -8081,6 +8199,13 @@ var Viewport = class {
|
|
|
8081
8199
|
this.store = new ElementStore();
|
|
8082
8200
|
this.layerManager = new LayerManager(this.store);
|
|
8083
8201
|
this.toolManager = new ToolManager();
|
|
8202
|
+
this.unsubToolRegister = this.toolManager.onRegister((tool) => {
|
|
8203
|
+
if (_Viewport.isSelectionSource(tool)) this.attachSelectionSource(tool);
|
|
8204
|
+
});
|
|
8205
|
+
const existingSelect = this.getSelectTool();
|
|
8206
|
+
if (existingSelect && _Viewport.isSelectionSource(existingSelect)) {
|
|
8207
|
+
this.attachSelectionSource(existingSelect);
|
|
8208
|
+
}
|
|
8084
8209
|
this.renderer = new ElementRenderer();
|
|
8085
8210
|
this.renderer.setStore(this.store);
|
|
8086
8211
|
this.renderer.setCamera(this.camera);
|
|
@@ -8115,6 +8240,11 @@ var Viewport = class {
|
|
|
8115
8240
|
this.dropHandler = options.onDrop;
|
|
8116
8241
|
this.history = new HistoryStack();
|
|
8117
8242
|
this.historyRecorder = new HistoryRecorder(this.store, this.history, this.layerManager);
|
|
8243
|
+
this.unsubRecorderEnd = this.historyRecorder.onTransactionEnd(() => {
|
|
8244
|
+
if (!this.pendingSelectionPrune) return;
|
|
8245
|
+
this.pendingSelectionPrune = false;
|
|
8246
|
+
this.pruneSelection();
|
|
8247
|
+
});
|
|
8118
8248
|
this.selectionOps = new SelectionOps({
|
|
8119
8249
|
store: this.store,
|
|
8120
8250
|
recorder: this.historyRecorder,
|
|
@@ -8234,6 +8364,7 @@ var Viewport = class {
|
|
|
8234
8364
|
this.domNodeManager.removeDomNode(el.id);
|
|
8235
8365
|
this.renderLoop.markLayerDirty(el.layerId);
|
|
8236
8366
|
this.requestRender();
|
|
8367
|
+
this.handleRemovedElement(el.id);
|
|
8237
8368
|
}),
|
|
8238
8369
|
this.store.on("update", ({ previous, current }) => {
|
|
8239
8370
|
if (current.type === "grid") this.gridController.syncContext();
|
|
@@ -8248,6 +8379,7 @@ var Viewport = class {
|
|
|
8248
8379
|
this.renderLoop.markAllLayersDirty();
|
|
8249
8380
|
this.gridController.syncContext();
|
|
8250
8381
|
this.requestRender();
|
|
8382
|
+
this.pruneSelection();
|
|
8251
8383
|
})
|
|
8252
8384
|
];
|
|
8253
8385
|
this.layerManager.on("change", () => {
|
|
@@ -8317,6 +8449,13 @@ var Viewport = class {
|
|
|
8317
8449
|
minimap = null;
|
|
8318
8450
|
htmlRenderers = /* @__PURE__ */ new Map();
|
|
8319
8451
|
resizeListeners = /* @__PURE__ */ new Set();
|
|
8452
|
+
selectionListeners = /* @__PURE__ */ new Set();
|
|
8453
|
+
detachSelectionSource = null;
|
|
8454
|
+
unsubToolRegister = () => {
|
|
8455
|
+
};
|
|
8456
|
+
pendingSelectionPrune = false;
|
|
8457
|
+
unsubRecorderEnd = () => {
|
|
8458
|
+
};
|
|
8320
8459
|
get ctx() {
|
|
8321
8460
|
return this.canvasEl.getContext("2d");
|
|
8322
8461
|
}
|
|
@@ -8575,6 +8714,42 @@ var Viewport = class {
|
|
|
8575
8714
|
getSelectTool() {
|
|
8576
8715
|
return this.toolManager.getTool("select");
|
|
8577
8716
|
}
|
|
8717
|
+
pruneSelection() {
|
|
8718
|
+
const tool = this.getSelectTool();
|
|
8719
|
+
if (!tool) return;
|
|
8720
|
+
const ids = tool.selectedIds;
|
|
8721
|
+
const filtered = ids.filter((id) => this.store.getById(id) !== void 0);
|
|
8722
|
+
if (filtered.length !== ids.length) tool.setSelection(filtered);
|
|
8723
|
+
}
|
|
8724
|
+
handleRemovedElement(id) {
|
|
8725
|
+
if (!this.getSelectedIds().includes(id)) return;
|
|
8726
|
+
if (this.historyRecorder.currentTransactionId !== null) {
|
|
8727
|
+
this.pendingSelectionPrune = true;
|
|
8728
|
+
return;
|
|
8729
|
+
}
|
|
8730
|
+
this.pruneSelection();
|
|
8731
|
+
}
|
|
8732
|
+
static isSelectionSource(tool) {
|
|
8733
|
+
const candidate = tool;
|
|
8734
|
+
return tool.name === "select" && typeof candidate.onSelectionChange === "function" && typeof candidate.setSelection === "function";
|
|
8735
|
+
}
|
|
8736
|
+
emitSelectionChange() {
|
|
8737
|
+
for (const listener of this.selectionListeners) {
|
|
8738
|
+
try {
|
|
8739
|
+
listener();
|
|
8740
|
+
} catch {
|
|
8741
|
+
}
|
|
8742
|
+
}
|
|
8743
|
+
}
|
|
8744
|
+
attachSelectionSource(tool) {
|
|
8745
|
+
this.detachSelectionSource?.();
|
|
8746
|
+
this.detachSelectionSource = tool.onSelectionChange(() => this.emitSelectionChange());
|
|
8747
|
+
}
|
|
8748
|
+
/**
|
|
8749
|
+
* getSelectedIds() and the onSelectionChange emitter never surface stale ids:
|
|
8750
|
+
* once the enclosing history transaction completes, both reflect
|
|
8751
|
+
* the current selection.
|
|
8752
|
+
*/
|
|
8578
8753
|
getSelectedIds() {
|
|
8579
8754
|
return this.getSelectTool()?.selectedIds ?? EMPTY_IDS;
|
|
8580
8755
|
}
|
|
@@ -8608,13 +8783,29 @@ var Viewport = class {
|
|
|
8608
8783
|
if (items.length === 0) return;
|
|
8609
8784
|
this.contextMenu.open(items, screenPos);
|
|
8610
8785
|
}
|
|
8786
|
+
/**
|
|
8787
|
+
* Persistent, viewport-owned selection-change emitter. Subscribing works
|
|
8788
|
+
* regardless of whether a select tool is registered yet; it forwards
|
|
8789
|
+
* events from whichever select tool is currently attached via
|
|
8790
|
+
* `toolManager.onRegister`. Never delivers stale ids once the enclosing
|
|
8791
|
+
* history transaction completes.
|
|
8792
|
+
*/
|
|
8611
8793
|
onSelectionChange(listener) {
|
|
8612
|
-
|
|
8613
|
-
return
|
|
8794
|
+
this.selectionListeners.add(listener);
|
|
8795
|
+
return () => {
|
|
8796
|
+
this.selectionListeners.delete(listener);
|
|
8797
|
+
};
|
|
8614
8798
|
}
|
|
8615
8799
|
getSelectionStyle() {
|
|
8616
8800
|
return this.selectionOps.getStyle();
|
|
8617
8801
|
}
|
|
8802
|
+
/**
|
|
8803
|
+
* Unlike `getSelectionStyle()` — which returns `{}` for a style-less
|
|
8804
|
+
* selection — this returns `null` when no style field is applicable.
|
|
8805
|
+
*/
|
|
8806
|
+
getSelectionStyleDetails() {
|
|
8807
|
+
return this.selectionOps.getStyleDetails();
|
|
8808
|
+
}
|
|
8618
8809
|
applyStyleToSelection(style) {
|
|
8619
8810
|
this.selectionOps.applyStyle(style);
|
|
8620
8811
|
}
|
|
@@ -8663,6 +8854,11 @@ var Viewport = class {
|
|
|
8663
8854
|
this.inputHandler.destroy();
|
|
8664
8855
|
this.unsubCamera();
|
|
8665
8856
|
this.unsubToolChange();
|
|
8857
|
+
this.unsubToolRegister();
|
|
8858
|
+
this.unsubRecorderEnd();
|
|
8859
|
+
this.detachSelectionSource?.();
|
|
8860
|
+
this.detachSelectionSource = null;
|
|
8861
|
+
this.selectionListeners.clear();
|
|
8666
8862
|
this.unsubStore.forEach((fn) => fn());
|
|
8667
8863
|
this.resizeObserver?.disconnect();
|
|
8668
8864
|
this.resizeObserver = null;
|
|
@@ -12264,7 +12460,7 @@ var PingTool = class {
|
|
|
12264
12460
|
};
|
|
12265
12461
|
|
|
12266
12462
|
// src/index.ts
|
|
12267
|
-
var VERSION = "0.
|
|
12463
|
+
var VERSION = "0.60.0";
|
|
12268
12464
|
export {
|
|
12269
12465
|
ArrowTool,
|
|
12270
12466
|
AutoSave,
|