@ngx-km/grid 0.0.2 → 0.0.3
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/fesm2022/ngx-km-grid.mjs +104 -16
- package/fesm2022/ngx-km-grid.mjs.map +1 -1
- package/index.d.ts +59 -7
- package/package.json +1 -1
package/fesm2022/ngx-km-grid.mjs
CHANGED
|
@@ -136,6 +136,19 @@ const DEFAULT_VIEWPORT_STATE = {
|
|
|
136
136
|
y: 0,
|
|
137
137
|
zoom: 1,
|
|
138
138
|
};
|
|
139
|
+
/**
|
|
140
|
+
* Built-in easing functions
|
|
141
|
+
*/
|
|
142
|
+
const EASING_FUNCTIONS = {
|
|
143
|
+
'linear': (t) => t,
|
|
144
|
+
'ease-out': (t) => 1 - Math.pow(1 - t, 3),
|
|
145
|
+
'ease-in': (t) => Math.pow(t, 3),
|
|
146
|
+
'ease-in-out': (t) => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2,
|
|
147
|
+
};
|
|
148
|
+
/** Default animation duration in milliseconds */
|
|
149
|
+
const DEFAULT_ANIMATION_DURATION = 300;
|
|
150
|
+
/** Default easing function name */
|
|
151
|
+
const DEFAULT_EASING = 'ease-out';
|
|
139
152
|
|
|
140
153
|
class GridComponent {
|
|
141
154
|
elementRef = inject(ElementRef);
|
|
@@ -176,6 +189,8 @@ class GridComponent {
|
|
|
176
189
|
elementPositions = new Map();
|
|
177
190
|
/** Track if we're currently dragging to avoid overwriting drag position */
|
|
178
191
|
syncPositionsFromInput = true;
|
|
192
|
+
/** Animation frame ID for viewport animation (used for cancellation) */
|
|
193
|
+
viewportAnimationId = null;
|
|
179
194
|
constructor() {
|
|
180
195
|
// Sync element positions from input when elements change
|
|
181
196
|
// This allows external code to update positions programmatically
|
|
@@ -343,6 +358,8 @@ class GridComponent {
|
|
|
343
358
|
// Only pan on left mouse button
|
|
344
359
|
if (event.button !== 0)
|
|
345
360
|
return;
|
|
361
|
+
// Cancel any running animation when user starts panning
|
|
362
|
+
this.cancelViewportAnimation();
|
|
346
363
|
this.isPanning.set(true);
|
|
347
364
|
this.panStartX = event.clientX;
|
|
348
365
|
this.panStartY = event.clientY;
|
|
@@ -446,28 +463,97 @@ class GridComponent {
|
|
|
446
463
|
window.removeEventListener('mousemove', this.onElementMouseMove);
|
|
447
464
|
window.removeEventListener('mouseup', this.onElementMouseUp);
|
|
448
465
|
};
|
|
449
|
-
|
|
450
|
-
|
|
466
|
+
// ============================================================================
|
|
467
|
+
// Animation Methods
|
|
468
|
+
// ============================================================================
|
|
469
|
+
/**
|
|
470
|
+
* Cancel any running viewport animation
|
|
471
|
+
*/
|
|
472
|
+
cancelViewportAnimation() {
|
|
473
|
+
if (this.viewportAnimationId !== null) {
|
|
474
|
+
cancelAnimationFrame(this.viewportAnimationId);
|
|
475
|
+
this.viewportAnimationId = null;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Animate viewport to a target state
|
|
480
|
+
* @param to Target viewport state
|
|
481
|
+
* @param options Animation options
|
|
482
|
+
*/
|
|
483
|
+
animateViewport(to, options = {}) {
|
|
484
|
+
// Cancel any existing animation
|
|
485
|
+
this.cancelViewportAnimation();
|
|
486
|
+
const duration = options.duration ?? DEFAULT_ANIMATION_DURATION;
|
|
487
|
+
const easingOption = options.easing ?? DEFAULT_EASING;
|
|
488
|
+
// Resolve easing function
|
|
489
|
+
const easingFn = typeof easingOption === 'function'
|
|
490
|
+
? easingOption
|
|
491
|
+
: EASING_FUNCTIONS[easingOption] ?? EASING_FUNCTIONS[DEFAULT_EASING];
|
|
492
|
+
const from = this.viewport();
|
|
493
|
+
const startTime = performance.now();
|
|
494
|
+
const animate = (currentTime) => {
|
|
495
|
+
const elapsed = currentTime - startTime;
|
|
496
|
+
const progress = Math.min(elapsed / duration, 1);
|
|
497
|
+
const easedProgress = easingFn(progress);
|
|
498
|
+
const currentViewport = {
|
|
499
|
+
x: from.x + (to.x - from.x) * easedProgress,
|
|
500
|
+
y: from.y + (to.y - from.y) * easedProgress,
|
|
501
|
+
zoom: from.zoom + (to.zoom - from.zoom) * easedProgress,
|
|
502
|
+
};
|
|
503
|
+
this.viewport.set(currentViewport);
|
|
504
|
+
this.viewportChange.emit(currentViewport);
|
|
505
|
+
if (progress < 1) {
|
|
506
|
+
this.viewportAnimationId = requestAnimationFrame(animate);
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
509
|
+
this.viewportAnimationId = null;
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
this.viewportAnimationId = requestAnimationFrame(animate);
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Set viewport with optional animation
|
|
516
|
+
* @param newViewport Target viewport state
|
|
517
|
+
* @param options Animation options (if animated is false or undefined, sets immediately)
|
|
518
|
+
*/
|
|
519
|
+
setViewport(newViewport, options) {
|
|
520
|
+
if (options?.animated) {
|
|
521
|
+
this.animateViewport(newViewport, options);
|
|
522
|
+
}
|
|
523
|
+
else {
|
|
524
|
+
this.cancelViewportAnimation();
|
|
525
|
+
this.viewport.set(newViewport);
|
|
526
|
+
this.viewportChange.emit(newViewport);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
// ============================================================================
|
|
530
|
+
// Viewport Control Methods
|
|
531
|
+
// ============================================================================
|
|
532
|
+
/**
|
|
533
|
+
* Reset viewport to default position
|
|
534
|
+
* @param options Animation options
|
|
535
|
+
*/
|
|
536
|
+
resetViewport(options) {
|
|
451
537
|
const newViewport = { ...DEFAULT_VIEWPORT_STATE };
|
|
452
|
-
this.
|
|
453
|
-
this.viewportChange.emit(newViewport);
|
|
538
|
+
this.setViewport(newViewport, options);
|
|
454
539
|
}
|
|
455
540
|
/**
|
|
456
541
|
* Fit all content to view
|
|
457
542
|
* Centers content in the viewport, optionally zooming out to fit everything
|
|
458
543
|
* @param fitZoom If true, zooms out if needed to fit all content (never zooms in beyond 1.0)
|
|
459
544
|
* @param padding Padding around content in pixels (default: 40)
|
|
545
|
+
* @param options Animation options
|
|
460
546
|
*/
|
|
461
|
-
fitToView(fitZoom = false, padding = 40) {
|
|
547
|
+
fitToView(fitZoom = false, padding = 40, options) {
|
|
462
548
|
const currentElements = this.elements();
|
|
463
549
|
if (currentElements.length === 0) {
|
|
464
|
-
this.resetViewport();
|
|
550
|
+
this.resetViewport(options);
|
|
465
551
|
return;
|
|
466
552
|
}
|
|
467
553
|
// Calculate bounding box of all elements
|
|
468
554
|
const bounds = this.calculateContentBounds();
|
|
469
555
|
if (!bounds) {
|
|
470
|
-
this.resetViewport();
|
|
556
|
+
this.resetViewport(options);
|
|
471
557
|
return;
|
|
472
558
|
}
|
|
473
559
|
// Get container dimensions
|
|
@@ -503,8 +589,7 @@ class GridComponent {
|
|
|
503
589
|
y: newY,
|
|
504
590
|
zoom: newZoom,
|
|
505
591
|
};
|
|
506
|
-
this.
|
|
507
|
-
this.viewportChange.emit(newViewport);
|
|
592
|
+
this.setViewport(newViewport, options);
|
|
508
593
|
}
|
|
509
594
|
/**
|
|
510
595
|
* Check if an element is fully visible in the viewport
|
|
@@ -532,8 +617,9 @@ class GridComponent {
|
|
|
532
617
|
/**
|
|
533
618
|
* Center viewport on a specific element (no zoom change)
|
|
534
619
|
* @param elementId The element ID to center on
|
|
620
|
+
* @param options Animation options
|
|
535
621
|
*/
|
|
536
|
-
centerOnElement(elementId) {
|
|
622
|
+
centerOnElement(elementId, options) {
|
|
537
623
|
const bounds = this.getElementBounds(elementId);
|
|
538
624
|
if (!bounds)
|
|
539
625
|
return;
|
|
@@ -550,16 +636,16 @@ class GridComponent {
|
|
|
550
636
|
y: newY,
|
|
551
637
|
zoom: vp.zoom,
|
|
552
638
|
};
|
|
553
|
-
this.
|
|
554
|
-
this.viewportChange.emit(newViewport);
|
|
639
|
+
this.setViewport(newViewport, options);
|
|
555
640
|
}
|
|
556
641
|
/**
|
|
557
642
|
* Scroll element into view with minimal pan
|
|
558
643
|
* Only pans if element is not fully visible
|
|
559
644
|
* @param elementId The element ID to scroll into view
|
|
560
645
|
* @param padding Padding from viewport edges (default: 40)
|
|
646
|
+
* @param options Animation options
|
|
561
647
|
*/
|
|
562
|
-
scrollToElement(elementId, padding = 40) {
|
|
648
|
+
scrollToElement(elementId, padding = 40, options) {
|
|
563
649
|
if (this.isElementVisible(elementId, padding)) {
|
|
564
650
|
return; // Already visible, no need to scroll
|
|
565
651
|
}
|
|
@@ -600,8 +686,7 @@ class GridComponent {
|
|
|
600
686
|
y: newY,
|
|
601
687
|
zoom: vp.zoom,
|
|
602
688
|
};
|
|
603
|
-
this.
|
|
604
|
-
this.viewportChange.emit(newViewport);
|
|
689
|
+
this.setViewport(newViewport, options);
|
|
605
690
|
}
|
|
606
691
|
}
|
|
607
692
|
/**
|
|
@@ -691,6 +776,8 @@ class GridComponent {
|
|
|
691
776
|
return;
|
|
692
777
|
// Prevent default scroll behavior
|
|
693
778
|
event.preventDefault();
|
|
779
|
+
// Cancel any running animation when user starts zooming
|
|
780
|
+
this.cancelViewportAnimation();
|
|
694
781
|
const zoomMin = cfg.zoomMin ?? DEFAULT_ZOOM_MIN;
|
|
695
782
|
const zoomMax = cfg.zoomMax ?? DEFAULT_ZOOM_MAX;
|
|
696
783
|
const zoomSpeed = cfg.zoomSpeed ?? DEFAULT_ZOOM_SPEED;
|
|
@@ -728,6 +815,7 @@ class GridComponent {
|
|
|
728
815
|
}
|
|
729
816
|
/** Clean up resources */
|
|
730
817
|
ngOnDestroy() {
|
|
818
|
+
this.cancelViewportAnimation();
|
|
731
819
|
this.cleanupResizeObserver();
|
|
732
820
|
if (this.dimensionUpdateTimer) {
|
|
733
821
|
clearTimeout(this.dimensionUpdateTimer);
|
|
@@ -816,5 +904,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
816
904
|
* Generated bundle index. Do not edit.
|
|
817
905
|
*/
|
|
818
906
|
|
|
819
|
-
export { DEFAULT_BACKGROUND_COLOR, DEFAULT_CELL_SIZE, DEFAULT_GRID_CONFIG, DEFAULT_PATTERN_COLOR, DEFAULT_VIEWPORT_STATE, DEFAULT_ZOOM_MAX, DEFAULT_ZOOM_MIN, DEFAULT_ZOOM_SPEED, GRID_ELEMENT_DATA, GridComponent, ToolbarComponent };
|
|
907
|
+
export { DEFAULT_ANIMATION_DURATION, DEFAULT_BACKGROUND_COLOR, DEFAULT_CELL_SIZE, DEFAULT_EASING, DEFAULT_GRID_CONFIG, DEFAULT_PATTERN_COLOR, DEFAULT_VIEWPORT_STATE, DEFAULT_ZOOM_MAX, DEFAULT_ZOOM_MIN, DEFAULT_ZOOM_SPEED, EASING_FUNCTIONS, GRID_ELEMENT_DATA, GridComponent, ToolbarComponent };
|
|
820
908
|
//# sourceMappingURL=ngx-km-grid.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngx-km-grid.mjs","sources":["../../../../libs/ngx-km-grid/src/lib/directives/grid-element-ref.directive.ts","../../../../libs/ngx-km-grid/src/lib/components/toolbar/toolbar.component.ts","../../../../libs/ngx-km-grid/src/lib/models/grid.models.ts","../../../../libs/ngx-km-grid/src/lib/ngx-grid/ngx-grid.ts","../../../../libs/ngx-km-grid/src/lib/ngx-grid/ngx-grid.html","../../../../libs/ngx-km-grid/src/index.ts","../../../../libs/ngx-km-grid/src/ngx-km-grid.ts"],"sourcesContent":["import { Directive, ElementRef, inject, input, OnInit, OnDestroy } from '@angular/core';\nimport { GridComponent } from '../ngx-grid/ngx-grid';\n\n/**\n * Directive that automatically registers/unregisters grid elements for dimension tracking\n */\n@Directive({\n selector: '[gridElementRef]',\n standalone: true,\n})\nexport class GridElementRefDirective implements OnInit, OnDestroy {\n private readonly elementRef = inject(ElementRef);\n private readonly gridComponent = inject(GridComponent);\n\n /** The element ID to register */\n gridElementRef = input.required<string>();\n\n ngOnInit(): void {\n this.gridComponent.registerElement(\n this.gridElementRef(),\n this.elementRef.nativeElement\n );\n }\n\n ngOnDestroy(): void {\n this.gridComponent.unregisterElement(this.gridElementRef());\n }\n}\n","import { Component, input, computed, inject } from '@angular/core';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { ToolbarConfig, ToolbarButton } from '../../models/grid.models';\n\n@Component({\n selector: 'ngx-grid-toolbar',\n standalone: true,\n template: `\n <div class=\"toolbar\" [class]=\"toolbarClasses()\">\n @for (button of config().buttons; track button.id) {\n <button\n class=\"toolbar-btn\"\n [class.active]=\"button.active\"\n [class.disabled]=\"button.disabled\"\n [disabled]=\"button.disabled\"\n [title]=\"button.label\"\n (click)=\"onButtonClick(button, $event)\">\n @if (button.icon) {\n <span class=\"btn-icon\" [innerHTML]=\"sanitizeHtml(button.icon)\"></span>\n } @else {\n <span class=\"btn-label\">{{ button.label }}</span>\n }\n </button>\n }\n </div>\n `,\n styles: [`\n :host {\n position: absolute;\n z-index: 100;\n pointer-events: none;\n }\n\n .toolbar {\n display: flex;\n gap: 4px;\n padding: 6px;\n background: rgba(30, 30, 46, 0.95);\n border: 1px solid #444;\n border-radius: 6px;\n backdrop-filter: blur(4px);\n pointer-events: auto;\n }\n\n /* Position classes */\n :host(.pos-top-left) {\n top: 12px;\n left: 12px;\n }\n\n :host(.pos-top-center) {\n top: 12px;\n left: 50%;\n transform: translateX(-50%);\n }\n\n :host(.pos-top-right) {\n top: 12px;\n right: 12px;\n }\n\n :host(.pos-bottom-left) {\n bottom: 12px;\n left: 12px;\n }\n\n :host(.pos-bottom-center) {\n bottom: 12px;\n left: 50%;\n transform: translateX(-50%);\n }\n\n :host(.pos-bottom-right) {\n bottom: 12px;\n right: 12px;\n }\n\n .toolbar-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 32px;\n height: 32px;\n padding: 0 8px;\n border: 1px solid #555;\n background: #2a2a3e;\n color: #fff;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.15s ease;\n font-size: 0.875rem;\n }\n\n .toolbar-btn:hover:not(.disabled) {\n background: #3a3a4e;\n border-color: #666;\n }\n\n .toolbar-btn.active {\n background: #4a4a6e;\n border-color: #6a6a8e;\n }\n\n .toolbar-btn.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .btn-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n pointer-events: none;\n }\n\n .btn-icon ::ng-deep svg {\n width: 100%;\n height: 100%;\n pointer-events: none;\n }\n\n .btn-label {\n white-space: nowrap;\n }\n `],\n host: {\n '[class]': 'hostClasses()',\n },\n})\nexport class ToolbarComponent {\n private readonly sanitizer = inject(DomSanitizer);\n\n /** Toolbar configuration */\n config = input.required<ToolbarConfig>();\n\n /** Computed host classes based on position */\n hostClasses = computed(() => {\n const cfg = this.config();\n const posClass = `pos-${cfg.position}`;\n return cfg.className ? `${posClass} ${cfg.className}` : posClass;\n });\n\n /** Computed classes for the toolbar div */\n toolbarClasses = computed(() => {\n return '';\n });\n\n /** Sanitize HTML for safe rendering of SVG icons */\n sanitizeHtml(html: string): SafeHtml {\n return this.sanitizer.bypassSecurityTrustHtml(html);\n }\n\n /** Handle button click */\n onButtonClick(button: ToolbarButton, event: MouseEvent): void {\n event.stopPropagation();\n if (!button.disabled && button.onClick) {\n button.onClick();\n }\n }\n}\n","import { Type, InjectionToken, Signal } from '@angular/core';\n\n/**\n * Injection token for accessing element data in dynamically rendered components.\n * The data can be either a plain value or a Signal for reactive updates.\n */\nexport const GRID_ELEMENT_DATA = new InjectionToken<unknown>('GRID_ELEMENT_DATA');\n\n/**\n * Type alias for data that can be either a plain value or a Signal.\n * Use Signal<T> when you need the component to reactively update based on data changes.\n */\nexport type ReactiveData<T> = T | Signal<T>;\n\n/**\n * Dimension mode for the grid container\n * - 'fixed': Uses explicit width/height values\n * - 'full': Fills the parent container (100% width/height)\n */\nexport type DimensionMode = 'fixed' | 'full';\n\n/**\n * Background mode for the grid\n * - 'lines': Grid lines pattern\n * - 'dots': Dot pattern at intersections\n * - 'none': No background pattern\n */\nexport type BackgroundMode = 'lines' | 'dots' | 'none';\n\n/**\n * Configuration for the grid component\n */\nexport interface GridConfig {\n /** How the grid should size itself */\n dimensionMode: DimensionMode;\n\n /** Fixed width in pixels (only used when dimensionMode is 'fixed') */\n width?: number;\n\n /** Fixed height in pixels (only used when dimensionMode is 'fixed') */\n height?: number;\n\n /** Minimum width constraint in pixels */\n minWidth?: number;\n\n /** Minimum height constraint in pixels */\n minHeight?: number;\n\n /** Maximum width constraint in pixels */\n maxWidth?: number;\n\n /** Maximum height constraint in pixels */\n maxHeight?: number;\n\n /** Background pattern mode (default: 'lines') */\n backgroundMode?: BackgroundMode;\n\n /** Size of each grid cell in pixels (default: 20) */\n cellSize?: number;\n\n /** Color of the grid lines/dots (default: '#2a2a4a') */\n backgroundPatternColor?: string;\n\n /** Opacity of the background pattern 0-1 (default: 1) */\n backgroundPatternOpacity?: number;\n\n /** Background color of the grid (default: '#1a1a2e') */\n backgroundColor?: string;\n\n /** Enable panning (default: true) */\n panEnabled?: boolean;\n\n /** Minimum X pan boundary (undefined = infinite) */\n panMinX?: number;\n\n /** Maximum X pan boundary (undefined = infinite) */\n panMaxX?: number;\n\n /** Minimum Y pan boundary (undefined = infinite) */\n panMinY?: number;\n\n /** Maximum Y pan boundary (undefined = infinite) */\n panMaxY?: number;\n\n /** Enable zooming (default: true) */\n zoomEnabled?: boolean;\n\n /** Minimum zoom level (default: 0.1) */\n zoomMin?: number;\n\n /** Maximum zoom level (default: 5) */\n zoomMax?: number;\n\n /** Zoom speed multiplier (default: 0.001) */\n zoomSpeed?: number;\n\n /** Enable element dragging (default: true) */\n dragEnabled?: boolean;\n\n /** Enable snap-to-grid during drag (default: false) */\n snapEnabled?: boolean;\n\n /** Snap grid size in pixels (default: uses cellSize) */\n snapGridSize?: number;\n\n /** Toolbar configuration (renders toolbar inside grid) */\n toolbar?: GridToolbarConfig;\n\n /** Show loading overlay (default: false) */\n loading?: boolean;\n}\n\n/**\n * Configuration for the grid's integrated toolbar\n */\nexport interface GridToolbarConfig {\n /** Position of the toolbar within the grid */\n position?: ToolbarPosition;\n /** Show default zoom controls (default: true) */\n showZoomControls?: boolean;\n /** Show reset view button (default: true) */\n showResetView?: boolean;\n /** Additional custom buttons */\n customButtons?: ToolbarButton[];\n}\n\n/**\n * Viewport state representing pan and zoom\n */\nexport interface ViewportState {\n /** X offset (pan) */\n x: number;\n /** Y offset (pan) */\n y: number;\n /** Zoom level (1 = 100%) */\n zoom: number;\n}\n\n/**\n * Definition for an element to render on the grid\n * @template T Type of the data passed to the component\n */\nexport interface GridElement<T = unknown> {\n /** Unique identifier for this element */\n id: string;\n /** Angular component class to render */\n component: Type<unknown>;\n /**\n * Data to pass to the component via GRID_ELEMENT_DATA injection token.\n * Can be a plain value or a Signal for reactive updates.\n * When using Signal<T>, the component can reactively respond to data changes.\n */\n data?: ReactiveData<T>;\n /** X coordinate in world space */\n x: number;\n /** Y coordinate in world space */\n y: number;\n}\n\n/**\n * Rendered element with tracked dimensions\n */\nexport interface RenderedElement {\n /** Element ID */\n id: string;\n /** X coordinate in world space */\n x: number;\n /** Y coordinate in world space */\n y: number;\n /** Rendered width in pixels */\n width: number;\n /** Rendered height in pixels */\n height: number;\n}\n\n/**\n * Event emitted when an element position changes during drag\n */\nexport interface ElementPositionChange {\n /** Element ID being dragged */\n id: string;\n /** New X coordinate in world space */\n x: number;\n /** New Y coordinate in world space */\n y: number;\n /** Previous X coordinate */\n previousX: number;\n /** Previous Y coordinate */\n previousY: number;\n}\n\n/** Default cell size in pixels */\nexport const DEFAULT_CELL_SIZE = 20;\n\n/** Default background pattern color */\nexport const DEFAULT_PATTERN_COLOR = '#3a3a5a';\n\n/** Default minimum zoom level */\nexport const DEFAULT_ZOOM_MIN = 0.1;\n\n/** Default maximum zoom level */\nexport const DEFAULT_ZOOM_MAX = 5;\n\n/** Default zoom speed multiplier */\nexport const DEFAULT_ZOOM_SPEED = 0.001;\n\n/** Default background color */\nexport const DEFAULT_BACKGROUND_COLOR = '#1a1a2e';\n\n/**\n * Default grid configuration\n */\nexport const DEFAULT_GRID_CONFIG: GridConfig = {\n dimensionMode: 'full',\n backgroundMode: 'lines',\n cellSize: DEFAULT_CELL_SIZE,\n backgroundPatternColor: DEFAULT_PATTERN_COLOR,\n backgroundPatternOpacity: 1,\n backgroundColor: DEFAULT_BACKGROUND_COLOR,\n panEnabled: true,\n};\n\n/**\n * Default viewport state\n */\nexport const DEFAULT_VIEWPORT_STATE: ViewportState = {\n x: 0,\n y: 0,\n zoom: 1,\n};\n\n/**\n * Position for the floating toolbar\n */\nexport type ToolbarPosition =\n | 'top-left'\n | 'top-center'\n | 'top-right'\n | 'bottom-left'\n | 'bottom-center'\n | 'bottom-right';\n\n/**\n * Configuration for a toolbar button\n */\nexport interface ToolbarButton {\n /** Unique identifier for the button */\n id: string;\n /** Button label text (used as tooltip if icon is provided) */\n label: string;\n /** Optional icon (SVG string or icon name) */\n icon?: string;\n /** Whether the button is currently active/toggled */\n active?: boolean;\n /** Whether the button is disabled */\n disabled?: boolean;\n /** Callback function when button is clicked */\n onClick: () => void;\n}\n\n/**\n * Configuration for the toolbar\n */\nexport interface ToolbarConfig {\n /** Position of the toolbar within the grid */\n position: ToolbarPosition;\n /** Array of button configurations */\n buttons: ToolbarButton[];\n /** Optional CSS class to apply to the toolbar */\n className?: string;\n}\n","import { Component, computed, input, signal, output, ElementRef, inject, Injector, OnDestroy, AfterViewInit, effect, DestroyRef, untracked } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { NgStyle, NgComponentOutlet } from '@angular/common';\nimport { GridElementRefDirective } from '../directives/grid-element-ref.directive';\nimport { ToolbarComponent } from '../components/toolbar/toolbar.component';\nimport {\n GridConfig,\n DEFAULT_GRID_CONFIG,\n DEFAULT_CELL_SIZE,\n DEFAULT_PATTERN_COLOR,\n DEFAULT_BACKGROUND_COLOR,\n ViewportState,\n DEFAULT_VIEWPORT_STATE,\n DEFAULT_ZOOM_MIN,\n DEFAULT_ZOOM_MAX,\n DEFAULT_ZOOM_SPEED,\n GridElement,\n GRID_ELEMENT_DATA,\n RenderedElement,\n ElementPositionChange,\n ToolbarConfig,\n ToolbarButton,\n} from '../models/grid.models';\n\n@Component({\n selector: 'ngx-grid',\n imports: [NgStyle, NgComponentOutlet, GridElementRefDirective, ToolbarComponent],\n templateUrl: './ngx-grid.html',\n styleUrl: './ngx-grid.scss',\n})\nexport class GridComponent implements AfterViewInit, OnDestroy {\n private readonly elementRef = inject(ElementRef);\n private readonly injector = inject(Injector);\n private readonly destroyRef = inject(DestroyRef);\n\n /** Grid configuration */\n config = input<GridConfig>(DEFAULT_GRID_CONFIG);\n\n /** Elements to render on the grid */\n elements = input<GridElement[]>([]);\n\n /** Current viewport state (pan offset and zoom) */\n viewport = signal<ViewportState>({ ...DEFAULT_VIEWPORT_STATE });\n\n /** Emits when viewport changes */\n viewportChange = output<ViewportState>();\n\n /** Emits when element dimensions are measured or change */\n elementsRendered = output<RenderedElement[]>();\n\n /** Emits when an element is dragged to a new position */\n elementPositionChange = output<ElementPositionChange>();\n\n /** Map of element IDs to their DOM elements for dimension tracking */\n private elementRefs = new Map<string, HTMLElement>();\n\n /** ResizeObserver for tracking element dimension changes */\n private resizeObserver: ResizeObserver | null = null;\n\n /** Debounce timer for batching dimension updates */\n private dimensionUpdateTimer: ReturnType<typeof setTimeout> | null = null;\n\n /** Internal state for pan tracking */\n private isPanning = signal(false);\n private panStartX = 0;\n private panStartY = 0;\n private panStartViewportX = 0;\n private panStartViewportY = 0;\n\n /** Internal state for element drag tracking */\n private isDraggingElement = signal(false);\n private draggingElementId: string | null = null;\n private dragStartX = 0;\n private dragStartY = 0;\n private dragStartElementX = 0;\n private dragStartElementY = 0;\n\n /** Internal copy of element positions for drag updates */\n private elementPositions = new Map<string, { x: number; y: number }>();\n\n /** Track if we're currently dragging to avoid overwriting drag position */\n private syncPositionsFromInput = true;\n\n constructor() {\n // Sync element positions from input when elements change\n // This allows external code to update positions programmatically\n effect(() => {\n const inputElements = this.elements();\n\n untracked(() => {\n // Skip sync if currently dragging\n if (this.isDraggingElement()) return;\n\n // Update internal positions from input\n inputElements.forEach(el => {\n const currentPos = this.elementPositions.get(el.id);\n // Only update if position is different (allows external updates)\n if (!currentPos || currentPos.x !== el.x || currentPos.y !== el.y) {\n this.elementPositions.set(el.id, { x: el.x, y: el.y });\n }\n });\n\n // Remove positions for elements that no longer exist\n const inputIds = new Set(inputElements.map(e => e.id));\n for (const id of this.elementPositions.keys()) {\n if (!inputIds.has(id)) {\n this.elementPositions.delete(id);\n }\n }\n });\n });\n }\n\n /** Computed container styles based on config */\n containerStyles = computed(() => {\n const cfg = this.config();\n const styles: Record<string, string> = {};\n\n if (cfg.dimensionMode === 'fixed') {\n if (cfg.width) styles['width'] = `${cfg.width}px`;\n if (cfg.height) styles['height'] = `${cfg.height}px`;\n } else {\n styles['width'] = '100%';\n styles['height'] = '100%';\n }\n\n if (cfg.minWidth) styles['min-width'] = `${cfg.minWidth}px`;\n if (cfg.minHeight) styles['min-height'] = `${cfg.minHeight}px`;\n if (cfg.maxWidth) styles['max-width'] = `${cfg.maxWidth}px`;\n if (cfg.maxHeight) styles['max-height'] = `${cfg.maxHeight}px`;\n\n // Background color\n styles['background-color'] = cfg.backgroundColor ?? DEFAULT_BACKGROUND_COLOR;\n\n // Cursor style\n const panEnabled = cfg.panEnabled ?? true;\n if (panEnabled) {\n styles['cursor'] = this.isPanning() ? 'grabbing' : 'grab';\n }\n\n return styles;\n });\n\n /** Computed background styles for the pattern layer */\n backgroundStyles = computed(() => {\n const cfg = this.config();\n const vp = this.viewport();\n const mode = cfg.backgroundMode ?? 'lines';\n const cellSize = cfg.cellSize ?? DEFAULT_CELL_SIZE;\n const patternColor = cfg.backgroundPatternColor ?? DEFAULT_PATTERN_COLOR;\n const opacity = cfg.backgroundPatternOpacity ?? 1;\n\n const styles: Record<string, string> = {};\n\n if (mode === 'none') {\n return styles;\n }\n\n // Apply zoom to cell size\n const scaledCellSize = cellSize * vp.zoom;\n\n if (mode === 'lines') {\n styles['background-image'] = `linear-gradient(to right, ${patternColor} 1px, transparent 1px), linear-gradient(to bottom, ${patternColor} 1px, transparent 1px)`;\n styles['background-size'] = `${scaledCellSize}px ${scaledCellSize}px`;\n } else if (mode === 'dots') {\n // Scale dot size with zoom\n const dotSize = 1.5 * vp.zoom;\n styles['background-image'] = `radial-gradient(circle, ${patternColor} ${dotSize}px, transparent ${dotSize}px)`;\n styles['background-size'] = `${scaledCellSize}px ${scaledCellSize}px`;\n }\n\n // Apply pan offset to background position for seamless scrolling\n styles['background-position'] = `${vp.x}px ${vp.y}px`;\n styles['opacity'] = String(opacity);\n\n return styles;\n });\n\n /** Computed transform styles for the viewport layer (contains all elements) */\n viewportTransform = computed(() => {\n const vp = this.viewport();\n return `translate(${vp.x}px, ${vp.y}px) scale(${vp.zoom})`;\n });\n\n /** Whether the integrated toolbar should be shown */\n showToolbar = computed(() => !!this.config().toolbar);\n\n /** Whether the loading overlay should be shown */\n isLoading = computed(() => !!this.config().loading);\n\n /** Computed toolbar configuration for the integrated toolbar */\n integratedToolbarConfig = computed<ToolbarConfig | null>(() => {\n const cfg = this.config();\n if (!cfg.toolbar) return null;\n\n const toolbarCfg = cfg.toolbar;\n const buttons: ToolbarButton[] = [];\n\n // Add reset view button if enabled (default: true)\n if (toolbarCfg.showResetView !== false) {\n buttons.push({\n id: 'grid-reset-view',\n label: 'Reset View',\n icon: '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\"/><path d=\"M3 3v5h5\"/></svg>',\n onClick: () => this.resetViewport(),\n });\n }\n\n // Add zoom controls if enabled (default: true)\n if (toolbarCfg.showZoomControls !== false) {\n buttons.push({\n id: 'grid-zoom-in',\n label: 'Zoom In',\n icon: '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"/><line x1=\"11\" y1=\"8\" x2=\"11\" y2=\"14\"/><line x1=\"8\" y1=\"11\" x2=\"14\" y2=\"11\"/></svg>',\n onClick: () => this.zoomIn(),\n });\n buttons.push({\n id: 'grid-zoom-out',\n label: 'Zoom Out',\n icon: '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"/><line x1=\"8\" y1=\"11\" x2=\"14\" y2=\"11\"/></svg>',\n onClick: () => this.zoomOut(),\n });\n }\n\n // Add custom buttons\n if (toolbarCfg.customButtons?.length) {\n buttons.push(...toolbarCfg.customButtons);\n }\n\n return {\n position: toolbarCfg.position ?? 'top-left',\n buttons,\n };\n });\n\n /** Get screen position styles for an element */\n getElementStyles(element: GridElement): Record<string, string> {\n // Use tracked position if dragging, otherwise use input position\n const pos = this.elementPositions.get(element.id) ?? { x: element.x, y: element.y };\n const cfg = this.config();\n const dragEnabled = cfg.dragEnabled ?? true;\n\n return {\n position: 'absolute',\n left: `${pos.x}px`,\n top: `${pos.y}px`,\n 'transform-origin': 'top left',\n cursor: dragEnabled ? (this.isDraggingElement() && this.draggingElementId === element.id ? 'grabbing' : 'grab') : 'default',\n };\n }\n\n /** Create an injector for passing data to a dynamically rendered component */\n createElementInjector(element: GridElement): Injector {\n return Injector.create({\n providers: [\n { provide: GRID_ELEMENT_DATA, useValue: element.data },\n ],\n parent: this.injector,\n });\n }\n\n /** Handle mouse down to start panning */\n onMouseDown(event: MouseEvent): void {\n const cfg = this.config();\n if (!(cfg.panEnabled ?? true)) return;\n\n // Only pan on left mouse button\n if (event.button !== 0) return;\n\n this.isPanning.set(true);\n this.panStartX = event.clientX;\n this.panStartY = event.clientY;\n const vp = this.viewport();\n this.panStartViewportX = vp.x;\n this.panStartViewportY = vp.y;\n\n // Prevent text selection during drag\n event.preventDefault();\n\n // Add window-level listeners for move and up\n window.addEventListener('mousemove', this.onMouseMove);\n window.addEventListener('mouseup', this.onMouseUp);\n }\n\n /** Handle mouse move during panning */\n private onMouseMove = (event: MouseEvent): void => {\n if (!this.isPanning()) return;\n\n const deltaX = event.clientX - this.panStartX;\n const deltaY = event.clientY - this.panStartY;\n\n let newX = this.panStartViewportX + deltaX;\n let newY = this.panStartViewportY + deltaY;\n\n // Apply boundaries if configured\n const cfg = this.config();\n if (cfg.panMinX !== undefined) newX = Math.max(cfg.panMinX, newX);\n if (cfg.panMaxX !== undefined) newX = Math.min(cfg.panMaxX, newX);\n if (cfg.panMinY !== undefined) newY = Math.max(cfg.panMinY, newY);\n if (cfg.panMaxY !== undefined) newY = Math.min(cfg.panMaxY, newY);\n\n const currentVp = this.viewport();\n const newViewport: ViewportState = { ...currentVp, x: newX, y: newY };\n this.viewport.set(newViewport);\n this.viewportChange.emit(newViewport);\n };\n\n /** Handle mouse up to stop panning */\n private onMouseUp = (): void => {\n this.isPanning.set(false);\n window.removeEventListener('mousemove', this.onMouseMove);\n window.removeEventListener('mouseup', this.onMouseUp);\n };\n\n /** Handle mouse down on an element to start dragging */\n onElementMouseDown(event: MouseEvent, element: GridElement): void {\n const cfg = this.config();\n if (!(cfg.dragEnabled ?? true)) return;\n\n // Only drag on left mouse button\n if (event.button !== 0) return;\n\n // Stop propagation to prevent pan from starting\n event.stopPropagation();\n event.preventDefault();\n\n // Initialize position tracking if not already done\n if (!this.elementPositions.has(element.id)) {\n this.elementPositions.set(element.id, { x: element.x, y: element.y });\n }\n\n const pos = this.elementPositions.get(element.id)!;\n\n this.isDraggingElement.set(true);\n this.draggingElementId = element.id;\n this.dragStartX = event.clientX;\n this.dragStartY = event.clientY;\n this.dragStartElementX = pos.x;\n this.dragStartElementY = pos.y;\n\n // Add window-level listeners for move and up\n window.addEventListener('mousemove', this.onElementMouseMove);\n window.addEventListener('mouseup', this.onElementMouseUp);\n }\n\n /** Handle mouse move during element dragging */\n private onElementMouseMove = (event: MouseEvent): void => {\n if (!this.isDraggingElement() || !this.draggingElementId) return;\n\n const cfg = this.config();\n\n // Calculate delta in screen space, then convert to world space (account for zoom)\n const vp = this.viewport();\n const deltaX = (event.clientX - this.dragStartX) / vp.zoom;\n const deltaY = (event.clientY - this.dragStartY) / vp.zoom;\n\n let newX = this.dragStartElementX + deltaX;\n let newY = this.dragStartElementY + deltaY;\n\n // Apply snap if enabled\n if (cfg.snapEnabled) {\n const snapSize = cfg.snapGridSize ?? cfg.cellSize ?? DEFAULT_CELL_SIZE;\n newX = Math.round(newX / snapSize) * snapSize;\n newY = Math.round(newY / snapSize) * snapSize;\n }\n\n const previousPos = this.elementPositions.get(this.draggingElementId) ?? { x: this.dragStartElementX, y: this.dragStartElementY };\n\n // Update internal position\n this.elementPositions.set(this.draggingElementId, { x: newX, y: newY });\n\n // Emit position change\n this.elementPositionChange.emit({\n id: this.draggingElementId,\n x: newX,\n y: newY,\n previousX: previousPos.x,\n previousY: previousPos.y,\n });\n };\n\n /** Handle mouse up to stop element dragging */\n private onElementMouseUp = (): void => {\n this.isDraggingElement.set(false);\n this.draggingElementId = null;\n window.removeEventListener('mousemove', this.onElementMouseMove);\n window.removeEventListener('mouseup', this.onElementMouseUp);\n };\n\n /** Reset viewport to default position */\n resetViewport(): void {\n const newViewport = { ...DEFAULT_VIEWPORT_STATE };\n this.viewport.set(newViewport);\n this.viewportChange.emit(newViewport);\n }\n\n /**\n * Fit all content to view\n * Centers content in the viewport, optionally zooming out to fit everything\n * @param fitZoom If true, zooms out if needed to fit all content (never zooms in beyond 1.0)\n * @param padding Padding around content in pixels (default: 40)\n */\n fitToView(fitZoom = false, padding = 40): void {\n const currentElements = this.elements();\n if (currentElements.length === 0) {\n this.resetViewport();\n return;\n }\n\n // Calculate bounding box of all elements\n const bounds = this.calculateContentBounds();\n if (!bounds) {\n this.resetViewport();\n return;\n }\n\n // Get container dimensions\n const containerRect = this.elementRef.nativeElement.getBoundingClientRect();\n const containerWidth = containerRect.width;\n const containerHeight = containerRect.height;\n\n // Available space for content (with padding)\n const availableWidth = containerWidth - padding * 2;\n const availableHeight = containerHeight - padding * 2;\n\n let newZoom = 1;\n\n if (fitZoom) {\n // Calculate zoom needed to fit content\n const scaleX = availableWidth / bounds.width;\n const scaleY = availableHeight / bounds.height;\n const fitScale = Math.min(scaleX, scaleY);\n\n // Never zoom in beyond 1.0, only zoom out if needed\n newZoom = Math.min(1, fitScale);\n\n // Respect zoom limits\n const cfg = this.config();\n const zoomMin = cfg.zoomMin ?? DEFAULT_ZOOM_MIN;\n newZoom = Math.max(zoomMin, newZoom);\n }\n\n // Calculate center of content in world space\n const contentCenterX = bounds.x + bounds.width / 2;\n const contentCenterY = bounds.y + bounds.height / 2;\n\n // Calculate viewport offset to center content\n // Container center = contentCenter * zoom + offset\n // offset = containerCenter - contentCenter * zoom\n const newX = containerWidth / 2 - contentCenterX * newZoom;\n const newY = containerHeight / 2 - contentCenterY * newZoom;\n\n const newViewport: ViewportState = {\n x: newX,\n y: newY,\n zoom: newZoom,\n };\n\n this.viewport.set(newViewport);\n this.viewportChange.emit(newViewport);\n }\n\n /**\n * Check if an element is fully visible in the viewport\n * @param elementId The element ID to check\n * @param padding Padding from viewport edges (default: 0)\n * @returns true if element is fully visible, false otherwise\n */\n isElementVisible(elementId: string, padding = 0): boolean {\n const bounds = this.getElementBounds(elementId);\n if (!bounds) return false;\n\n const vp = this.viewport();\n const containerRect = this.elementRef.nativeElement.getBoundingClientRect();\n\n // Convert element bounds to screen space\n const screenLeft = bounds.x * vp.zoom + vp.x;\n const screenTop = bounds.y * vp.zoom + vp.y;\n const screenRight = (bounds.x + bounds.width) * vp.zoom + vp.x;\n const screenBottom = (bounds.y + bounds.height) * vp.zoom + vp.y;\n\n // Check if fully within viewport (with padding)\n return (\n screenLeft >= padding &&\n screenTop >= padding &&\n screenRight <= containerRect.width - padding &&\n screenBottom <= containerRect.height - padding\n );\n }\n\n /**\n * Center viewport on a specific element (no zoom change)\n * @param elementId The element ID to center on\n */\n centerOnElement(elementId: string): void {\n const bounds = this.getElementBounds(elementId);\n if (!bounds) return;\n\n const vp = this.viewport();\n const containerRect = this.elementRef.nativeElement.getBoundingClientRect();\n\n // Calculate element center in world space\n const elementCenterX = bounds.x + bounds.width / 2;\n const elementCenterY = bounds.y + bounds.height / 2;\n\n // Calculate viewport offset to center element\n const newX = containerRect.width / 2 - elementCenterX * vp.zoom;\n const newY = containerRect.height / 2 - elementCenterY * vp.zoom;\n\n const newViewport: ViewportState = {\n x: newX,\n y: newY,\n zoom: vp.zoom,\n };\n\n this.viewport.set(newViewport);\n this.viewportChange.emit(newViewport);\n }\n\n /**\n * Scroll element into view with minimal pan\n * Only pans if element is not fully visible\n * @param elementId The element ID to scroll into view\n * @param padding Padding from viewport edges (default: 40)\n */\n scrollToElement(elementId: string, padding = 40): void {\n if (this.isElementVisible(elementId, padding)) {\n return; // Already visible, no need to scroll\n }\n\n const bounds = this.getElementBounds(elementId);\n if (!bounds) return;\n\n const vp = this.viewport();\n const containerRect = this.elementRef.nativeElement.getBoundingClientRect();\n\n // Convert element bounds to screen space\n const screenLeft = bounds.x * vp.zoom + vp.x;\n const screenTop = bounds.y * vp.zoom + vp.y;\n const screenRight = (bounds.x + bounds.width) * vp.zoom + vp.x;\n const screenBottom = (bounds.y + bounds.height) * vp.zoom + vp.y;\n\n let newX = vp.x;\n let newY = vp.y;\n\n // Calculate minimal pan needed to bring element into view\n // Check horizontal\n if (screenLeft < padding) {\n // Element is too far left, pan right\n newX = vp.x + (padding - screenLeft);\n } else if (screenRight > containerRect.width - padding) {\n // Element is too far right, pan left\n newX = vp.x - (screenRight - (containerRect.width - padding));\n }\n\n // Check vertical\n if (screenTop < padding) {\n // Element is too far up, pan down\n newY = vp.y + (padding - screenTop);\n } else if (screenBottom > containerRect.height - padding) {\n // Element is too far down, pan up\n newY = vp.y - (screenBottom - (containerRect.height - padding));\n }\n\n if (newX !== vp.x || newY !== vp.y) {\n const newViewport: ViewportState = {\n x: newX,\n y: newY,\n zoom: vp.zoom,\n };\n\n this.viewport.set(newViewport);\n this.viewportChange.emit(newViewport);\n }\n }\n\n /**\n * Get bounds of a specific element\n * @param elementId The element ID\n * @returns Element bounds in world coordinates, or null if not found\n */\n private getElementBounds(elementId: string): { x: number; y: number; width: number; height: number } | null {\n const element = this.elements().find(e => e.id === elementId);\n if (!element) return null;\n\n const pos = this.elementPositions.get(elementId) ?? { x: element.x, y: element.y };\n const domElement = this.elementRefs.get(elementId);\n\n let width = 100; // default\n let height = 50; // default\n if (domElement) {\n const rect = domElement.getBoundingClientRect();\n const zoom = this.viewport().zoom;\n width = rect.width / zoom;\n height = rect.height / zoom;\n }\n\n return {\n x: pos.x,\n y: pos.y,\n width,\n height,\n };\n }\n\n /**\n * Calculate the bounding box of all elements\n * @returns Bounding box in world coordinates, or null if no elements\n */\n private calculateContentBounds(): { x: number; y: number; width: number; height: number } | null {\n const currentElements = this.elements();\n if (currentElements.length === 0) return null;\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const element of currentElements) {\n const bounds = this.getElementBounds(element.id);\n if (!bounds) continue;\n\n minX = Math.min(minX, bounds.x);\n minY = Math.min(minY, bounds.y);\n maxX = Math.max(maxX, bounds.x + bounds.width);\n maxY = Math.max(maxY, bounds.y + bounds.height);\n }\n\n if (minX === Infinity) return null;\n\n return {\n x: minX,\n y: minY,\n width: maxX - minX,\n height: maxY - minY,\n };\n }\n\n /** Zoom in by a factor (default 1.25x) */\n zoomIn(factor = 1.25): void {\n const cfg = this.config();\n const zoomMax = cfg.zoomMax ?? DEFAULT_ZOOM_MAX;\n const vp = this.viewport();\n const newZoom = Math.min(zoomMax, vp.zoom * factor);\n\n if (newZoom === vp.zoom) return;\n\n const newViewport: ViewportState = { ...vp, zoom: newZoom };\n this.viewport.set(newViewport);\n this.viewportChange.emit(newViewport);\n }\n\n /** Zoom out by a factor (default 1.25x) */\n zoomOut(factor = 1.25): void {\n const cfg = this.config();\n const zoomMin = cfg.zoomMin ?? DEFAULT_ZOOM_MIN;\n const vp = this.viewport();\n const newZoom = Math.max(zoomMin, vp.zoom / factor);\n\n if (newZoom === vp.zoom) return;\n\n const newViewport: ViewportState = { ...vp, zoom: newZoom };\n this.viewport.set(newViewport);\n this.viewportChange.emit(newViewport);\n }\n\n /** Handle mouse wheel for zooming */\n onWheel(event: WheelEvent): void {\n const cfg = this.config();\n if (!(cfg.zoomEnabled ?? true)) return;\n\n // Prevent default scroll behavior\n event.preventDefault();\n\n const zoomMin = cfg.zoomMin ?? DEFAULT_ZOOM_MIN;\n const zoomMax = cfg.zoomMax ?? DEFAULT_ZOOM_MAX;\n const zoomSpeed = cfg.zoomSpeed ?? DEFAULT_ZOOM_SPEED;\n\n const vp = this.viewport();\n\n // Calculate new zoom level\n const delta = -event.deltaY * zoomSpeed;\n const newZoom = Math.max(zoomMin, Math.min(zoomMax, vp.zoom * (1 + delta)));\n\n // If zoom hasn't changed (at limits), don't update\n if (newZoom === vp.zoom) return;\n\n // Get cursor position relative to the grid container\n const rect = this.elementRef.nativeElement.getBoundingClientRect();\n const cursorX = event.clientX - rect.left;\n const cursorY = event.clientY - rect.top;\n\n // Calculate the world position under the cursor before zoom\n // worldX = (cursorX - vp.x) / vp.zoom\n const worldX = (cursorX - vp.x) / vp.zoom;\n const worldY = (cursorY - vp.y) / vp.zoom;\n\n // After zoom, we want the same world position under the cursor\n // cursorX = worldX * newZoom + newVpX\n // newVpX = cursorX - worldX * newZoom\n const newX = cursorX - worldX * newZoom;\n const newY = cursorY - worldY * newZoom;\n\n const newViewport: ViewportState = {\n x: newX,\n y: newY,\n zoom: newZoom,\n };\n\n this.viewport.set(newViewport);\n this.viewportChange.emit(newViewport);\n }\n\n /** Initialize ResizeObserver after view is ready */\n ngAfterViewInit(): void {\n this.setupResizeObserver();\n }\n\n /** Clean up resources */\n ngOnDestroy(): void {\n this.cleanupResizeObserver();\n if (this.dimensionUpdateTimer) {\n clearTimeout(this.dimensionUpdateTimer);\n }\n }\n\n /** Register an element for dimension tracking */\n registerElement(elementId: string, element: HTMLElement): void {\n this.elementRefs.set(elementId, element);\n if (this.resizeObserver) {\n this.resizeObserver.observe(element);\n }\n this.scheduleDimensionUpdate();\n }\n\n /** Unregister an element from dimension tracking */\n unregisterElement(elementId: string): void {\n const element = this.elementRefs.get(elementId);\n if (element && this.resizeObserver) {\n this.resizeObserver.unobserve(element);\n }\n this.elementRefs.delete(elementId);\n this.scheduleDimensionUpdate();\n }\n\n /** Set up the ResizeObserver to track element dimension changes */\n private setupResizeObserver(): void {\n if (typeof ResizeObserver === 'undefined') {\n return;\n }\n\n this.resizeObserver = new ResizeObserver(() => {\n this.scheduleDimensionUpdate();\n });\n\n // Observe any already-registered elements\n this.elementRefs.forEach((element) => {\n this.resizeObserver!.observe(element);\n });\n }\n\n /** Clean up the ResizeObserver */\n private cleanupResizeObserver(): void {\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n }\n\n /** Schedule a debounced dimension update */\n private scheduleDimensionUpdate(): void {\n if (this.dimensionUpdateTimer) {\n clearTimeout(this.dimensionUpdateTimer);\n }\n\n this.dimensionUpdateTimer = setTimeout(() => {\n this.emitRenderedElements();\n }, 10);\n }\n\n /** Collect and emit all rendered element dimensions */\n private emitRenderedElements(): void {\n const currentElements = this.elements();\n const renderedElements: RenderedElement[] = [];\n\n for (const element of currentElements) {\n const domElement = this.elementRefs.get(element.id);\n if (domElement) {\n const rect = domElement.getBoundingClientRect();\n // Get the actual size without zoom transform\n const zoom = this.viewport().zoom;\n renderedElements.push({\n id: element.id,\n x: element.x,\n y: element.y,\n width: rect.width / zoom,\n height: rect.height / zoom,\n });\n }\n }\n\n if (renderedElements.length > 0) {\n this.elementsRendered.emit(renderedElements);\n }\n }\n}\n","<div\n class=\"grid-container\"\n [ngStyle]=\"containerStyles()\"\n (mousedown)=\"onMouseDown($event)\"\n (wheel)=\"onWheel($event)\">\n <div class=\"grid-background\" [ngStyle]=\"backgroundStyles()\"></div>\n <div class=\"grid-viewport\" [style.transform]=\"viewportTransform()\">\n @for (element of elements(); track element.id) {\n <div\n class=\"grid-element\"\n [gridElementRef]=\"element.id\"\n [ngStyle]=\"getElementStyles(element)\"\n (mousedown)=\"onElementMouseDown($event, element)\">\n <ng-container\n *ngComponentOutlet=\"element.component; injector: createElementInjector(element)\" />\n </div>\n }\n </div>\n @if (showToolbar() && integratedToolbarConfig()) {\n <ngx-grid-toolbar [config]=\"integratedToolbarConfig()!\" />\n }\n @if (isLoading()) {\n <div class=\"loading-overlay\">\n <div class=\"loading-spinner\"></div>\n </div>\n }\n</div>\n","// Components\nexport { GridComponent } from './lib/ngx-grid/ngx-grid';\nexport { ToolbarComponent } from './lib/components/toolbar/toolbar.component';\n\n// Models\nexport type {\n GridConfig,\n GridToolbarConfig,\n DimensionMode,\n BackgroundMode,\n ViewportState,\n GridElement,\n ReactiveData,\n RenderedElement,\n ElementPositionChange,\n ToolbarPosition,\n ToolbarButton,\n ToolbarConfig,\n} from './lib/models/grid.models';\nexport {\n DEFAULT_GRID_CONFIG,\n DEFAULT_CELL_SIZE,\n DEFAULT_PATTERN_COLOR,\n DEFAULT_BACKGROUND_COLOR,\n DEFAULT_VIEWPORT_STATE,\n DEFAULT_ZOOM_MIN,\n DEFAULT_ZOOM_MAX,\n DEFAULT_ZOOM_SPEED,\n GRID_ELEMENT_DATA,\n} from './lib/models/grid.models';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngx-km-grid.mjs","sources":["../../../../libs/ngx-km-grid/src/lib/directives/grid-element-ref.directive.ts","../../../../libs/ngx-km-grid/src/lib/components/toolbar/toolbar.component.ts","../../../../libs/ngx-km-grid/src/lib/models/grid.models.ts","../../../../libs/ngx-km-grid/src/lib/ngx-grid/ngx-grid.ts","../../../../libs/ngx-km-grid/src/lib/ngx-grid/ngx-grid.html","../../../../libs/ngx-km-grid/src/index.ts","../../../../libs/ngx-km-grid/src/ngx-km-grid.ts"],"sourcesContent":["import { Directive, ElementRef, inject, input, OnInit, OnDestroy } from '@angular/core';\nimport { GridComponent } from '../ngx-grid/ngx-grid';\n\n/**\n * Directive that automatically registers/unregisters grid elements for dimension tracking\n */\n@Directive({\n selector: '[gridElementRef]',\n standalone: true,\n})\nexport class GridElementRefDirective implements OnInit, OnDestroy {\n private readonly elementRef = inject(ElementRef);\n private readonly gridComponent = inject(GridComponent);\n\n /** The element ID to register */\n gridElementRef = input.required<string>();\n\n ngOnInit(): void {\n this.gridComponent.registerElement(\n this.gridElementRef(),\n this.elementRef.nativeElement\n );\n }\n\n ngOnDestroy(): void {\n this.gridComponent.unregisterElement(this.gridElementRef());\n }\n}\n","import { Component, input, computed, inject } from '@angular/core';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { ToolbarConfig, ToolbarButton } from '../../models/grid.models';\n\n@Component({\n selector: 'ngx-grid-toolbar',\n standalone: true,\n template: `\n <div class=\"toolbar\" [class]=\"toolbarClasses()\">\n @for (button of config().buttons; track button.id) {\n <button\n class=\"toolbar-btn\"\n [class.active]=\"button.active\"\n [class.disabled]=\"button.disabled\"\n [disabled]=\"button.disabled\"\n [title]=\"button.label\"\n (click)=\"onButtonClick(button, $event)\">\n @if (button.icon) {\n <span class=\"btn-icon\" [innerHTML]=\"sanitizeHtml(button.icon)\"></span>\n } @else {\n <span class=\"btn-label\">{{ button.label }}</span>\n }\n </button>\n }\n </div>\n `,\n styles: [`\n :host {\n position: absolute;\n z-index: 100;\n pointer-events: none;\n }\n\n .toolbar {\n display: flex;\n gap: 4px;\n padding: 6px;\n background: rgba(30, 30, 46, 0.95);\n border: 1px solid #444;\n border-radius: 6px;\n backdrop-filter: blur(4px);\n pointer-events: auto;\n }\n\n /* Position classes */\n :host(.pos-top-left) {\n top: 12px;\n left: 12px;\n }\n\n :host(.pos-top-center) {\n top: 12px;\n left: 50%;\n transform: translateX(-50%);\n }\n\n :host(.pos-top-right) {\n top: 12px;\n right: 12px;\n }\n\n :host(.pos-bottom-left) {\n bottom: 12px;\n left: 12px;\n }\n\n :host(.pos-bottom-center) {\n bottom: 12px;\n left: 50%;\n transform: translateX(-50%);\n }\n\n :host(.pos-bottom-right) {\n bottom: 12px;\n right: 12px;\n }\n\n .toolbar-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 32px;\n height: 32px;\n padding: 0 8px;\n border: 1px solid #555;\n background: #2a2a3e;\n color: #fff;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.15s ease;\n font-size: 0.875rem;\n }\n\n .toolbar-btn:hover:not(.disabled) {\n background: #3a3a4e;\n border-color: #666;\n }\n\n .toolbar-btn.active {\n background: #4a4a6e;\n border-color: #6a6a8e;\n }\n\n .toolbar-btn.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .btn-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n pointer-events: none;\n }\n\n .btn-icon ::ng-deep svg {\n width: 100%;\n height: 100%;\n pointer-events: none;\n }\n\n .btn-label {\n white-space: nowrap;\n }\n `],\n host: {\n '[class]': 'hostClasses()',\n },\n})\nexport class ToolbarComponent {\n private readonly sanitizer = inject(DomSanitizer);\n\n /** Toolbar configuration */\n config = input.required<ToolbarConfig>();\n\n /** Computed host classes based on position */\n hostClasses = computed(() => {\n const cfg = this.config();\n const posClass = `pos-${cfg.position}`;\n return cfg.className ? `${posClass} ${cfg.className}` : posClass;\n });\n\n /** Computed classes for the toolbar div */\n toolbarClasses = computed(() => {\n return '';\n });\n\n /** Sanitize HTML for safe rendering of SVG icons */\n sanitizeHtml(html: string): SafeHtml {\n return this.sanitizer.bypassSecurityTrustHtml(html);\n }\n\n /** Handle button click */\n onButtonClick(button: ToolbarButton, event: MouseEvent): void {\n event.stopPropagation();\n if (!button.disabled && button.onClick) {\n button.onClick();\n }\n }\n}\n","import { Type, InjectionToken, Signal } from '@angular/core';\n\n/**\n * Injection token for accessing element data in dynamically rendered components.\n * The data can be either a plain value or a Signal for reactive updates.\n */\nexport const GRID_ELEMENT_DATA = new InjectionToken<unknown>('GRID_ELEMENT_DATA');\n\n/**\n * Type alias for data that can be either a plain value or a Signal.\n * Use Signal<T> when you need the component to reactively update based on data changes.\n */\nexport type ReactiveData<T> = T | Signal<T>;\n\n/**\n * Dimension mode for the grid container\n * - 'fixed': Uses explicit width/height values\n * - 'full': Fills the parent container (100% width/height)\n */\nexport type DimensionMode = 'fixed' | 'full';\n\n/**\n * Background mode for the grid\n * - 'lines': Grid lines pattern\n * - 'dots': Dot pattern at intersections\n * - 'none': No background pattern\n */\nexport type BackgroundMode = 'lines' | 'dots' | 'none';\n\n/**\n * Configuration for the grid component\n */\nexport interface GridConfig {\n /** How the grid should size itself */\n dimensionMode: DimensionMode;\n\n /** Fixed width in pixels (only used when dimensionMode is 'fixed') */\n width?: number;\n\n /** Fixed height in pixels (only used when dimensionMode is 'fixed') */\n height?: number;\n\n /** Minimum width constraint in pixels */\n minWidth?: number;\n\n /** Minimum height constraint in pixels */\n minHeight?: number;\n\n /** Maximum width constraint in pixels */\n maxWidth?: number;\n\n /** Maximum height constraint in pixels */\n maxHeight?: number;\n\n /** Background pattern mode (default: 'lines') */\n backgroundMode?: BackgroundMode;\n\n /** Size of each grid cell in pixels (default: 20) */\n cellSize?: number;\n\n /** Color of the grid lines/dots (default: '#2a2a4a') */\n backgroundPatternColor?: string;\n\n /** Opacity of the background pattern 0-1 (default: 1) */\n backgroundPatternOpacity?: number;\n\n /** Background color of the grid (default: '#1a1a2e') */\n backgroundColor?: string;\n\n /** Enable panning (default: true) */\n panEnabled?: boolean;\n\n /** Minimum X pan boundary (undefined = infinite) */\n panMinX?: number;\n\n /** Maximum X pan boundary (undefined = infinite) */\n panMaxX?: number;\n\n /** Minimum Y pan boundary (undefined = infinite) */\n panMinY?: number;\n\n /** Maximum Y pan boundary (undefined = infinite) */\n panMaxY?: number;\n\n /** Enable zooming (default: true) */\n zoomEnabled?: boolean;\n\n /** Minimum zoom level (default: 0.1) */\n zoomMin?: number;\n\n /** Maximum zoom level (default: 5) */\n zoomMax?: number;\n\n /** Zoom speed multiplier (default: 0.001) */\n zoomSpeed?: number;\n\n /** Enable element dragging (default: true) */\n dragEnabled?: boolean;\n\n /** Enable snap-to-grid during drag (default: false) */\n snapEnabled?: boolean;\n\n /** Snap grid size in pixels (default: uses cellSize) */\n snapGridSize?: number;\n\n /** Toolbar configuration (renders toolbar inside grid) */\n toolbar?: GridToolbarConfig;\n\n /** Show loading overlay (default: false) */\n loading?: boolean;\n}\n\n/**\n * Configuration for the grid's integrated toolbar\n */\nexport interface GridToolbarConfig {\n /** Position of the toolbar within the grid */\n position?: ToolbarPosition;\n /** Show default zoom controls (default: true) */\n showZoomControls?: boolean;\n /** Show reset view button (default: true) */\n showResetView?: boolean;\n /** Additional custom buttons */\n customButtons?: ToolbarButton[];\n}\n\n/**\n * Viewport state representing pan and zoom\n */\nexport interface ViewportState {\n /** X offset (pan) */\n x: number;\n /** Y offset (pan) */\n y: number;\n /** Zoom level (1 = 100%) */\n zoom: number;\n}\n\n/**\n * Definition for an element to render on the grid\n * @template T Type of the data passed to the component\n */\nexport interface GridElement<T = unknown> {\n /** Unique identifier for this element */\n id: string;\n /** Angular component class to render */\n component: Type<unknown>;\n /**\n * Data to pass to the component via GRID_ELEMENT_DATA injection token.\n * Can be a plain value or a Signal for reactive updates.\n * When using Signal<T>, the component can reactively respond to data changes.\n */\n data?: ReactiveData<T>;\n /** X coordinate in world space */\n x: number;\n /** Y coordinate in world space */\n y: number;\n}\n\n/**\n * Rendered element with tracked dimensions\n */\nexport interface RenderedElement {\n /** Element ID */\n id: string;\n /** X coordinate in world space */\n x: number;\n /** Y coordinate in world space */\n y: number;\n /** Rendered width in pixels */\n width: number;\n /** Rendered height in pixels */\n height: number;\n}\n\n/**\n * Event emitted when an element position changes during drag\n */\nexport interface ElementPositionChange {\n /** Element ID being dragged */\n id: string;\n /** New X coordinate in world space */\n x: number;\n /** New Y coordinate in world space */\n y: number;\n /** Previous X coordinate */\n previousX: number;\n /** Previous Y coordinate */\n previousY: number;\n}\n\n/** Default cell size in pixels */\nexport const DEFAULT_CELL_SIZE = 20;\n\n/** Default background pattern color */\nexport const DEFAULT_PATTERN_COLOR = '#3a3a5a';\n\n/** Default minimum zoom level */\nexport const DEFAULT_ZOOM_MIN = 0.1;\n\n/** Default maximum zoom level */\nexport const DEFAULT_ZOOM_MAX = 5;\n\n/** Default zoom speed multiplier */\nexport const DEFAULT_ZOOM_SPEED = 0.001;\n\n/** Default background color */\nexport const DEFAULT_BACKGROUND_COLOR = '#1a1a2e';\n\n/**\n * Default grid configuration\n */\nexport const DEFAULT_GRID_CONFIG: GridConfig = {\n dimensionMode: 'full',\n backgroundMode: 'lines',\n cellSize: DEFAULT_CELL_SIZE,\n backgroundPatternColor: DEFAULT_PATTERN_COLOR,\n backgroundPatternOpacity: 1,\n backgroundColor: DEFAULT_BACKGROUND_COLOR,\n panEnabled: true,\n};\n\n/**\n * Default viewport state\n */\nexport const DEFAULT_VIEWPORT_STATE: ViewportState = {\n x: 0,\n y: 0,\n zoom: 1,\n};\n\n// ============================================================================\n// Animation Types\n// ============================================================================\n\n/**\n * Easing function type for animations\n * Takes a progress value (0-1) and returns an eased value (0-1)\n */\nexport type EasingFunction = (t: number) => number;\n\n/**\n * Built-in easing function names\n */\nexport type EasingName = 'linear' | 'ease-out' | 'ease-in' | 'ease-in-out';\n\n/**\n * Options for animated viewport transitions\n */\nexport interface ViewportAnimationOptions {\n /** Whether to animate the transition (default: false) */\n animated?: boolean;\n /** Animation duration in milliseconds (default: 300) */\n duration?: number;\n /** Easing function name or custom function (default: 'ease-out') */\n easing?: EasingName | EasingFunction;\n}\n\n/**\n * Built-in easing functions\n */\nexport const EASING_FUNCTIONS: Record<EasingName, EasingFunction> = {\n 'linear': (t) => t,\n 'ease-out': (t) => 1 - Math.pow(1 - t, 3),\n 'ease-in': (t) => Math.pow(t, 3),\n 'ease-in-out': (t) => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2,\n};\n\n/** Default animation duration in milliseconds */\nexport const DEFAULT_ANIMATION_DURATION = 300;\n\n/** Default easing function name */\nexport const DEFAULT_EASING: EasingName = 'ease-out';\n\n// ============================================================================\n// Toolbar Types\n// ============================================================================\n\n/**\n * Position for the floating toolbar\n */\nexport type ToolbarPosition =\n | 'top-left'\n | 'top-center'\n | 'top-right'\n | 'bottom-left'\n | 'bottom-center'\n | 'bottom-right';\n\n/**\n * Configuration for a toolbar button\n */\nexport interface ToolbarButton {\n /** Unique identifier for the button */\n id: string;\n /** Button label text (used as tooltip if icon is provided) */\n label: string;\n /** Optional icon (SVG string or icon name) */\n icon?: string;\n /** Whether the button is currently active/toggled */\n active?: boolean;\n /** Whether the button is disabled */\n disabled?: boolean;\n /** Callback function when button is clicked */\n onClick: () => void;\n}\n\n/**\n * Configuration for the toolbar\n */\nexport interface ToolbarConfig {\n /** Position of the toolbar within the grid */\n position: ToolbarPosition;\n /** Array of button configurations */\n buttons: ToolbarButton[];\n /** Optional CSS class to apply to the toolbar */\n className?: string;\n}\n","import { Component, computed, input, signal, output, ElementRef, inject, Injector, OnDestroy, AfterViewInit, effect, DestroyRef, untracked } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { NgStyle, NgComponentOutlet } from '@angular/common';\nimport { GridElementRefDirective } from '../directives/grid-element-ref.directive';\nimport { ToolbarComponent } from '../components/toolbar/toolbar.component';\nimport {\n GridConfig,\n DEFAULT_GRID_CONFIG,\n DEFAULT_CELL_SIZE,\n DEFAULT_PATTERN_COLOR,\n DEFAULT_BACKGROUND_COLOR,\n ViewportState,\n DEFAULT_VIEWPORT_STATE,\n DEFAULT_ZOOM_MIN,\n DEFAULT_ZOOM_MAX,\n DEFAULT_ZOOM_SPEED,\n GridElement,\n GRID_ELEMENT_DATA,\n RenderedElement,\n ElementPositionChange,\n ToolbarConfig,\n ToolbarButton,\n ViewportAnimationOptions,\n EasingFunction,\n EasingName,\n EASING_FUNCTIONS,\n DEFAULT_ANIMATION_DURATION,\n DEFAULT_EASING,\n} from '../models/grid.models';\n\n@Component({\n selector: 'ngx-grid',\n imports: [NgStyle, NgComponentOutlet, GridElementRefDirective, ToolbarComponent],\n templateUrl: './ngx-grid.html',\n styleUrl: './ngx-grid.scss',\n})\nexport class GridComponent implements AfterViewInit, OnDestroy {\n private readonly elementRef = inject(ElementRef);\n private readonly injector = inject(Injector);\n private readonly destroyRef = inject(DestroyRef);\n\n /** Grid configuration */\n config = input<GridConfig>(DEFAULT_GRID_CONFIG);\n\n /** Elements to render on the grid */\n elements = input<GridElement[]>([]);\n\n /** Current viewport state (pan offset and zoom) */\n viewport = signal<ViewportState>({ ...DEFAULT_VIEWPORT_STATE });\n\n /** Emits when viewport changes */\n viewportChange = output<ViewportState>();\n\n /** Emits when element dimensions are measured or change */\n elementsRendered = output<RenderedElement[]>();\n\n /** Emits when an element is dragged to a new position */\n elementPositionChange = output<ElementPositionChange>();\n\n /** Map of element IDs to their DOM elements for dimension tracking */\n private elementRefs = new Map<string, HTMLElement>();\n\n /** ResizeObserver for tracking element dimension changes */\n private resizeObserver: ResizeObserver | null = null;\n\n /** Debounce timer for batching dimension updates */\n private dimensionUpdateTimer: ReturnType<typeof setTimeout> | null = null;\n\n /** Internal state for pan tracking */\n private isPanning = signal(false);\n private panStartX = 0;\n private panStartY = 0;\n private panStartViewportX = 0;\n private panStartViewportY = 0;\n\n /** Internal state for element drag tracking */\n private isDraggingElement = signal(false);\n private draggingElementId: string | null = null;\n private dragStartX = 0;\n private dragStartY = 0;\n private dragStartElementX = 0;\n private dragStartElementY = 0;\n\n /** Internal copy of element positions for drag updates */\n private elementPositions = new Map<string, { x: number; y: number }>();\n\n /** Track if we're currently dragging to avoid overwriting drag position */\n private syncPositionsFromInput = true;\n\n /** Animation frame ID for viewport animation (used for cancellation) */\n private viewportAnimationId: number | null = null;\n\n constructor() {\n // Sync element positions from input when elements change\n // This allows external code to update positions programmatically\n effect(() => {\n const inputElements = this.elements();\n\n untracked(() => {\n // Skip sync if currently dragging\n if (this.isDraggingElement()) return;\n\n // Update internal positions from input\n inputElements.forEach(el => {\n const currentPos = this.elementPositions.get(el.id);\n // Only update if position is different (allows external updates)\n if (!currentPos || currentPos.x !== el.x || currentPos.y !== el.y) {\n this.elementPositions.set(el.id, { x: el.x, y: el.y });\n }\n });\n\n // Remove positions for elements that no longer exist\n const inputIds = new Set(inputElements.map(e => e.id));\n for (const id of this.elementPositions.keys()) {\n if (!inputIds.has(id)) {\n this.elementPositions.delete(id);\n }\n }\n });\n });\n }\n\n /** Computed container styles based on config */\n containerStyles = computed(() => {\n const cfg = this.config();\n const styles: Record<string, string> = {};\n\n if (cfg.dimensionMode === 'fixed') {\n if (cfg.width) styles['width'] = `${cfg.width}px`;\n if (cfg.height) styles['height'] = `${cfg.height}px`;\n } else {\n styles['width'] = '100%';\n styles['height'] = '100%';\n }\n\n if (cfg.minWidth) styles['min-width'] = `${cfg.minWidth}px`;\n if (cfg.minHeight) styles['min-height'] = `${cfg.minHeight}px`;\n if (cfg.maxWidth) styles['max-width'] = `${cfg.maxWidth}px`;\n if (cfg.maxHeight) styles['max-height'] = `${cfg.maxHeight}px`;\n\n // Background color\n styles['background-color'] = cfg.backgroundColor ?? DEFAULT_BACKGROUND_COLOR;\n\n // Cursor style\n const panEnabled = cfg.panEnabled ?? true;\n if (panEnabled) {\n styles['cursor'] = this.isPanning() ? 'grabbing' : 'grab';\n }\n\n return styles;\n });\n\n /** Computed background styles for the pattern layer */\n backgroundStyles = computed(() => {\n const cfg = this.config();\n const vp = this.viewport();\n const mode = cfg.backgroundMode ?? 'lines';\n const cellSize = cfg.cellSize ?? DEFAULT_CELL_SIZE;\n const patternColor = cfg.backgroundPatternColor ?? DEFAULT_PATTERN_COLOR;\n const opacity = cfg.backgroundPatternOpacity ?? 1;\n\n const styles: Record<string, string> = {};\n\n if (mode === 'none') {\n return styles;\n }\n\n // Apply zoom to cell size\n const scaledCellSize = cellSize * vp.zoom;\n\n if (mode === 'lines') {\n styles['background-image'] = `linear-gradient(to right, ${patternColor} 1px, transparent 1px), linear-gradient(to bottom, ${patternColor} 1px, transparent 1px)`;\n styles['background-size'] = `${scaledCellSize}px ${scaledCellSize}px`;\n } else if (mode === 'dots') {\n // Scale dot size with zoom\n const dotSize = 1.5 * vp.zoom;\n styles['background-image'] = `radial-gradient(circle, ${patternColor} ${dotSize}px, transparent ${dotSize}px)`;\n styles['background-size'] = `${scaledCellSize}px ${scaledCellSize}px`;\n }\n\n // Apply pan offset to background position for seamless scrolling\n styles['background-position'] = `${vp.x}px ${vp.y}px`;\n styles['opacity'] = String(opacity);\n\n return styles;\n });\n\n /** Computed transform styles for the viewport layer (contains all elements) */\n viewportTransform = computed(() => {\n const vp = this.viewport();\n return `translate(${vp.x}px, ${vp.y}px) scale(${vp.zoom})`;\n });\n\n /** Whether the integrated toolbar should be shown */\n showToolbar = computed(() => !!this.config().toolbar);\n\n /** Whether the loading overlay should be shown */\n isLoading = computed(() => !!this.config().loading);\n\n /** Computed toolbar configuration for the integrated toolbar */\n integratedToolbarConfig = computed<ToolbarConfig | null>(() => {\n const cfg = this.config();\n if (!cfg.toolbar) return null;\n\n const toolbarCfg = cfg.toolbar;\n const buttons: ToolbarButton[] = [];\n\n // Add reset view button if enabled (default: true)\n if (toolbarCfg.showResetView !== false) {\n buttons.push({\n id: 'grid-reset-view',\n label: 'Reset View',\n icon: '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\"/><path d=\"M3 3v5h5\"/></svg>',\n onClick: () => this.resetViewport(),\n });\n }\n\n // Add zoom controls if enabled (default: true)\n if (toolbarCfg.showZoomControls !== false) {\n buttons.push({\n id: 'grid-zoom-in',\n label: 'Zoom In',\n icon: '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"/><line x1=\"11\" y1=\"8\" x2=\"11\" y2=\"14\"/><line x1=\"8\" y1=\"11\" x2=\"14\" y2=\"11\"/></svg>',\n onClick: () => this.zoomIn(),\n });\n buttons.push({\n id: 'grid-zoom-out',\n label: 'Zoom Out',\n icon: '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"/><line x1=\"8\" y1=\"11\" x2=\"14\" y2=\"11\"/></svg>',\n onClick: () => this.zoomOut(),\n });\n }\n\n // Add custom buttons\n if (toolbarCfg.customButtons?.length) {\n buttons.push(...toolbarCfg.customButtons);\n }\n\n return {\n position: toolbarCfg.position ?? 'top-left',\n buttons,\n };\n });\n\n /** Get screen position styles for an element */\n getElementStyles(element: GridElement): Record<string, string> {\n // Use tracked position if dragging, otherwise use input position\n const pos = this.elementPositions.get(element.id) ?? { x: element.x, y: element.y };\n const cfg = this.config();\n const dragEnabled = cfg.dragEnabled ?? true;\n\n return {\n position: 'absolute',\n left: `${pos.x}px`,\n top: `${pos.y}px`,\n 'transform-origin': 'top left',\n cursor: dragEnabled ? (this.isDraggingElement() && this.draggingElementId === element.id ? 'grabbing' : 'grab') : 'default',\n };\n }\n\n /** Create an injector for passing data to a dynamically rendered component */\n createElementInjector(element: GridElement): Injector {\n return Injector.create({\n providers: [\n { provide: GRID_ELEMENT_DATA, useValue: element.data },\n ],\n parent: this.injector,\n });\n }\n\n /** Handle mouse down to start panning */\n onMouseDown(event: MouseEvent): void {\n const cfg = this.config();\n if (!(cfg.panEnabled ?? true)) return;\n\n // Only pan on left mouse button\n if (event.button !== 0) return;\n\n // Cancel any running animation when user starts panning\n this.cancelViewportAnimation();\n\n this.isPanning.set(true);\n this.panStartX = event.clientX;\n this.panStartY = event.clientY;\n const vp = this.viewport();\n this.panStartViewportX = vp.x;\n this.panStartViewportY = vp.y;\n\n // Prevent text selection during drag\n event.preventDefault();\n\n // Add window-level listeners for move and up\n window.addEventListener('mousemove', this.onMouseMove);\n window.addEventListener('mouseup', this.onMouseUp);\n }\n\n /** Handle mouse move during panning */\n private onMouseMove = (event: MouseEvent): void => {\n if (!this.isPanning()) return;\n\n const deltaX = event.clientX - this.panStartX;\n const deltaY = event.clientY - this.panStartY;\n\n let newX = this.panStartViewportX + deltaX;\n let newY = this.panStartViewportY + deltaY;\n\n // Apply boundaries if configured\n const cfg = this.config();\n if (cfg.panMinX !== undefined) newX = Math.max(cfg.panMinX, newX);\n if (cfg.panMaxX !== undefined) newX = Math.min(cfg.panMaxX, newX);\n if (cfg.panMinY !== undefined) newY = Math.max(cfg.panMinY, newY);\n if (cfg.panMaxY !== undefined) newY = Math.min(cfg.panMaxY, newY);\n\n const currentVp = this.viewport();\n const newViewport: ViewportState = { ...currentVp, x: newX, y: newY };\n this.viewport.set(newViewport);\n this.viewportChange.emit(newViewport);\n };\n\n /** Handle mouse up to stop panning */\n private onMouseUp = (): void => {\n this.isPanning.set(false);\n window.removeEventListener('mousemove', this.onMouseMove);\n window.removeEventListener('mouseup', this.onMouseUp);\n };\n\n /** Handle mouse down on an element to start dragging */\n onElementMouseDown(event: MouseEvent, element: GridElement): void {\n const cfg = this.config();\n if (!(cfg.dragEnabled ?? true)) return;\n\n // Only drag on left mouse button\n if (event.button !== 0) return;\n\n // Stop propagation to prevent pan from starting\n event.stopPropagation();\n event.preventDefault();\n\n // Initialize position tracking if not already done\n if (!this.elementPositions.has(element.id)) {\n this.elementPositions.set(element.id, { x: element.x, y: element.y });\n }\n\n const pos = this.elementPositions.get(element.id)!;\n\n this.isDraggingElement.set(true);\n this.draggingElementId = element.id;\n this.dragStartX = event.clientX;\n this.dragStartY = event.clientY;\n this.dragStartElementX = pos.x;\n this.dragStartElementY = pos.y;\n\n // Add window-level listeners for move and up\n window.addEventListener('mousemove', this.onElementMouseMove);\n window.addEventListener('mouseup', this.onElementMouseUp);\n }\n\n /** Handle mouse move during element dragging */\n private onElementMouseMove = (event: MouseEvent): void => {\n if (!this.isDraggingElement() || !this.draggingElementId) return;\n\n const cfg = this.config();\n\n // Calculate delta in screen space, then convert to world space (account for zoom)\n const vp = this.viewport();\n const deltaX = (event.clientX - this.dragStartX) / vp.zoom;\n const deltaY = (event.clientY - this.dragStartY) / vp.zoom;\n\n let newX = this.dragStartElementX + deltaX;\n let newY = this.dragStartElementY + deltaY;\n\n // Apply snap if enabled\n if (cfg.snapEnabled) {\n const snapSize = cfg.snapGridSize ?? cfg.cellSize ?? DEFAULT_CELL_SIZE;\n newX = Math.round(newX / snapSize) * snapSize;\n newY = Math.round(newY / snapSize) * snapSize;\n }\n\n const previousPos = this.elementPositions.get(this.draggingElementId) ?? { x: this.dragStartElementX, y: this.dragStartElementY };\n\n // Update internal position\n this.elementPositions.set(this.draggingElementId, { x: newX, y: newY });\n\n // Emit position change\n this.elementPositionChange.emit({\n id: this.draggingElementId,\n x: newX,\n y: newY,\n previousX: previousPos.x,\n previousY: previousPos.y,\n });\n };\n\n /** Handle mouse up to stop element dragging */\n private onElementMouseUp = (): void => {\n this.isDraggingElement.set(false);\n this.draggingElementId = null;\n window.removeEventListener('mousemove', this.onElementMouseMove);\n window.removeEventListener('mouseup', this.onElementMouseUp);\n };\n\n // ============================================================================\n // Animation Methods\n // ============================================================================\n\n /**\n * Cancel any running viewport animation\n */\n cancelViewportAnimation(): void {\n if (this.viewportAnimationId !== null) {\n cancelAnimationFrame(this.viewportAnimationId);\n this.viewportAnimationId = null;\n }\n }\n\n /**\n * Animate viewport to a target state\n * @param to Target viewport state\n * @param options Animation options\n */\n private animateViewport(\n to: ViewportState,\n options: ViewportAnimationOptions = {}\n ): void {\n // Cancel any existing animation\n this.cancelViewportAnimation();\n\n const duration = options.duration ?? DEFAULT_ANIMATION_DURATION;\n const easingOption = options.easing ?? DEFAULT_EASING;\n\n // Resolve easing function\n const easingFn: EasingFunction =\n typeof easingOption === 'function'\n ? easingOption\n : EASING_FUNCTIONS[easingOption] ?? EASING_FUNCTIONS[DEFAULT_EASING];\n\n const from = this.viewport();\n const startTime = performance.now();\n\n const animate = (currentTime: number): void => {\n const elapsed = currentTime - startTime;\n const progress = Math.min(elapsed / duration, 1);\n const easedProgress = easingFn(progress);\n\n const currentViewport: ViewportState = {\n x: from.x + (to.x - from.x) * easedProgress,\n y: from.y + (to.y - from.y) * easedProgress,\n zoom: from.zoom + (to.zoom - from.zoom) * easedProgress,\n };\n\n this.viewport.set(currentViewport);\n this.viewportChange.emit(currentViewport);\n\n if (progress < 1) {\n this.viewportAnimationId = requestAnimationFrame(animate);\n } else {\n this.viewportAnimationId = null;\n }\n };\n\n this.viewportAnimationId = requestAnimationFrame(animate);\n }\n\n /**\n * Set viewport with optional animation\n * @param newViewport Target viewport state\n * @param options Animation options (if animated is false or undefined, sets immediately)\n */\n private setViewport(newViewport: ViewportState, options?: ViewportAnimationOptions): void {\n if (options?.animated) {\n this.animateViewport(newViewport, options);\n } else {\n this.cancelViewportAnimation();\n this.viewport.set(newViewport);\n this.viewportChange.emit(newViewport);\n }\n }\n\n // ============================================================================\n // Viewport Control Methods\n // ============================================================================\n\n /**\n * Reset viewport to default position\n * @param options Animation options\n */\n resetViewport(options?: ViewportAnimationOptions): void {\n const newViewport = { ...DEFAULT_VIEWPORT_STATE };\n this.setViewport(newViewport, options);\n }\n\n /**\n * Fit all content to view\n * Centers content in the viewport, optionally zooming out to fit everything\n * @param fitZoom If true, zooms out if needed to fit all content (never zooms in beyond 1.0)\n * @param padding Padding around content in pixels (default: 40)\n * @param options Animation options\n */\n fitToView(fitZoom = false, padding = 40, options?: ViewportAnimationOptions): void {\n const currentElements = this.elements();\n if (currentElements.length === 0) {\n this.resetViewport(options);\n return;\n }\n\n // Calculate bounding box of all elements\n const bounds = this.calculateContentBounds();\n if (!bounds) {\n this.resetViewport(options);\n return;\n }\n\n // Get container dimensions\n const containerRect = this.elementRef.nativeElement.getBoundingClientRect();\n const containerWidth = containerRect.width;\n const containerHeight = containerRect.height;\n\n // Available space for content (with padding)\n const availableWidth = containerWidth - padding * 2;\n const availableHeight = containerHeight - padding * 2;\n\n let newZoom = 1;\n\n if (fitZoom) {\n // Calculate zoom needed to fit content\n const scaleX = availableWidth / bounds.width;\n const scaleY = availableHeight / bounds.height;\n const fitScale = Math.min(scaleX, scaleY);\n\n // Never zoom in beyond 1.0, only zoom out if needed\n newZoom = Math.min(1, fitScale);\n\n // Respect zoom limits\n const cfg = this.config();\n const zoomMin = cfg.zoomMin ?? DEFAULT_ZOOM_MIN;\n newZoom = Math.max(zoomMin, newZoom);\n }\n\n // Calculate center of content in world space\n const contentCenterX = bounds.x + bounds.width / 2;\n const contentCenterY = bounds.y + bounds.height / 2;\n\n // Calculate viewport offset to center content\n // Container center = contentCenter * zoom + offset\n // offset = containerCenter - contentCenter * zoom\n const newX = containerWidth / 2 - contentCenterX * newZoom;\n const newY = containerHeight / 2 - contentCenterY * newZoom;\n\n const newViewport: ViewportState = {\n x: newX,\n y: newY,\n zoom: newZoom,\n };\n\n this.setViewport(newViewport, options);\n }\n\n /**\n * Check if an element is fully visible in the viewport\n * @param elementId The element ID to check\n * @param padding Padding from viewport edges (default: 0)\n * @returns true if element is fully visible, false otherwise\n */\n isElementVisible(elementId: string, padding = 0): boolean {\n const bounds = this.getElementBounds(elementId);\n if (!bounds) return false;\n\n const vp = this.viewport();\n const containerRect = this.elementRef.nativeElement.getBoundingClientRect();\n\n // Convert element bounds to screen space\n const screenLeft = bounds.x * vp.zoom + vp.x;\n const screenTop = bounds.y * vp.zoom + vp.y;\n const screenRight = (bounds.x + bounds.width) * vp.zoom + vp.x;\n const screenBottom = (bounds.y + bounds.height) * vp.zoom + vp.y;\n\n // Check if fully within viewport (with padding)\n return (\n screenLeft >= padding &&\n screenTop >= padding &&\n screenRight <= containerRect.width - padding &&\n screenBottom <= containerRect.height - padding\n );\n }\n\n /**\n * Center viewport on a specific element (no zoom change)\n * @param elementId The element ID to center on\n * @param options Animation options\n */\n centerOnElement(elementId: string, options?: ViewportAnimationOptions): void {\n const bounds = this.getElementBounds(elementId);\n if (!bounds) return;\n\n const vp = this.viewport();\n const containerRect = this.elementRef.nativeElement.getBoundingClientRect();\n\n // Calculate element center in world space\n const elementCenterX = bounds.x + bounds.width / 2;\n const elementCenterY = bounds.y + bounds.height / 2;\n\n // Calculate viewport offset to center element\n const newX = containerRect.width / 2 - elementCenterX * vp.zoom;\n const newY = containerRect.height / 2 - elementCenterY * vp.zoom;\n\n const newViewport: ViewportState = {\n x: newX,\n y: newY,\n zoom: vp.zoom,\n };\n\n this.setViewport(newViewport, options);\n }\n\n /**\n * Scroll element into view with minimal pan\n * Only pans if element is not fully visible\n * @param elementId The element ID to scroll into view\n * @param padding Padding from viewport edges (default: 40)\n * @param options Animation options\n */\n scrollToElement(elementId: string, padding = 40, options?: ViewportAnimationOptions): void {\n if (this.isElementVisible(elementId, padding)) {\n return; // Already visible, no need to scroll\n }\n\n const bounds = this.getElementBounds(elementId);\n if (!bounds) return;\n\n const vp = this.viewport();\n const containerRect = this.elementRef.nativeElement.getBoundingClientRect();\n\n // Convert element bounds to screen space\n const screenLeft = bounds.x * vp.zoom + vp.x;\n const screenTop = bounds.y * vp.zoom + vp.y;\n const screenRight = (bounds.x + bounds.width) * vp.zoom + vp.x;\n const screenBottom = (bounds.y + bounds.height) * vp.zoom + vp.y;\n\n let newX = vp.x;\n let newY = vp.y;\n\n // Calculate minimal pan needed to bring element into view\n // Check horizontal\n if (screenLeft < padding) {\n // Element is too far left, pan right\n newX = vp.x + (padding - screenLeft);\n } else if (screenRight > containerRect.width - padding) {\n // Element is too far right, pan left\n newX = vp.x - (screenRight - (containerRect.width - padding));\n }\n\n // Check vertical\n if (screenTop < padding) {\n // Element is too far up, pan down\n newY = vp.y + (padding - screenTop);\n } else if (screenBottom > containerRect.height - padding) {\n // Element is too far down, pan up\n newY = vp.y - (screenBottom - (containerRect.height - padding));\n }\n\n if (newX !== vp.x || newY !== vp.y) {\n const newViewport: ViewportState = {\n x: newX,\n y: newY,\n zoom: vp.zoom,\n };\n\n this.setViewport(newViewport, options);\n }\n }\n\n /**\n * Get bounds of a specific element\n * @param elementId The element ID\n * @returns Element bounds in world coordinates, or null if not found\n */\n private getElementBounds(elementId: string): { x: number; y: number; width: number; height: number } | null {\n const element = this.elements().find(e => e.id === elementId);\n if (!element) return null;\n\n const pos = this.elementPositions.get(elementId) ?? { x: element.x, y: element.y };\n const domElement = this.elementRefs.get(elementId);\n\n let width = 100; // default\n let height = 50; // default\n if (domElement) {\n const rect = domElement.getBoundingClientRect();\n const zoom = this.viewport().zoom;\n width = rect.width / zoom;\n height = rect.height / zoom;\n }\n\n return {\n x: pos.x,\n y: pos.y,\n width,\n height,\n };\n }\n\n /**\n * Calculate the bounding box of all elements\n * @returns Bounding box in world coordinates, or null if no elements\n */\n private calculateContentBounds(): { x: number; y: number; width: number; height: number } | null {\n const currentElements = this.elements();\n if (currentElements.length === 0) return null;\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const element of currentElements) {\n const bounds = this.getElementBounds(element.id);\n if (!bounds) continue;\n\n minX = Math.min(minX, bounds.x);\n minY = Math.min(minY, bounds.y);\n maxX = Math.max(maxX, bounds.x + bounds.width);\n maxY = Math.max(maxY, bounds.y + bounds.height);\n }\n\n if (minX === Infinity) return null;\n\n return {\n x: minX,\n y: minY,\n width: maxX - minX,\n height: maxY - minY,\n };\n }\n\n /** Zoom in by a factor (default 1.25x) */\n zoomIn(factor = 1.25): void {\n const cfg = this.config();\n const zoomMax = cfg.zoomMax ?? DEFAULT_ZOOM_MAX;\n const vp = this.viewport();\n const newZoom = Math.min(zoomMax, vp.zoom * factor);\n\n if (newZoom === vp.zoom) return;\n\n const newViewport: ViewportState = { ...vp, zoom: newZoom };\n this.viewport.set(newViewport);\n this.viewportChange.emit(newViewport);\n }\n\n /** Zoom out by a factor (default 1.25x) */\n zoomOut(factor = 1.25): void {\n const cfg = this.config();\n const zoomMin = cfg.zoomMin ?? DEFAULT_ZOOM_MIN;\n const vp = this.viewport();\n const newZoom = Math.max(zoomMin, vp.zoom / factor);\n\n if (newZoom === vp.zoom) return;\n\n const newViewport: ViewportState = { ...vp, zoom: newZoom };\n this.viewport.set(newViewport);\n this.viewportChange.emit(newViewport);\n }\n\n /** Handle mouse wheel for zooming */\n onWheel(event: WheelEvent): void {\n const cfg = this.config();\n if (!(cfg.zoomEnabled ?? true)) return;\n\n // Prevent default scroll behavior\n event.preventDefault();\n\n // Cancel any running animation when user starts zooming\n this.cancelViewportAnimation();\n\n const zoomMin = cfg.zoomMin ?? DEFAULT_ZOOM_MIN;\n const zoomMax = cfg.zoomMax ?? DEFAULT_ZOOM_MAX;\n const zoomSpeed = cfg.zoomSpeed ?? DEFAULT_ZOOM_SPEED;\n\n const vp = this.viewport();\n\n // Calculate new zoom level\n const delta = -event.deltaY * zoomSpeed;\n const newZoom = Math.max(zoomMin, Math.min(zoomMax, vp.zoom * (1 + delta)));\n\n // If zoom hasn't changed (at limits), don't update\n if (newZoom === vp.zoom) return;\n\n // Get cursor position relative to the grid container\n const rect = this.elementRef.nativeElement.getBoundingClientRect();\n const cursorX = event.clientX - rect.left;\n const cursorY = event.clientY - rect.top;\n\n // Calculate the world position under the cursor before zoom\n // worldX = (cursorX - vp.x) / vp.zoom\n const worldX = (cursorX - vp.x) / vp.zoom;\n const worldY = (cursorY - vp.y) / vp.zoom;\n\n // After zoom, we want the same world position under the cursor\n // cursorX = worldX * newZoom + newVpX\n // newVpX = cursorX - worldX * newZoom\n const newX = cursorX - worldX * newZoom;\n const newY = cursorY - worldY * newZoom;\n\n const newViewport: ViewportState = {\n x: newX,\n y: newY,\n zoom: newZoom,\n };\n\n this.viewport.set(newViewport);\n this.viewportChange.emit(newViewport);\n }\n\n /** Initialize ResizeObserver after view is ready */\n ngAfterViewInit(): void {\n this.setupResizeObserver();\n }\n\n /** Clean up resources */\n ngOnDestroy(): void {\n this.cancelViewportAnimation();\n this.cleanupResizeObserver();\n if (this.dimensionUpdateTimer) {\n clearTimeout(this.dimensionUpdateTimer);\n }\n }\n\n /** Register an element for dimension tracking */\n registerElement(elementId: string, element: HTMLElement): void {\n this.elementRefs.set(elementId, element);\n if (this.resizeObserver) {\n this.resizeObserver.observe(element);\n }\n this.scheduleDimensionUpdate();\n }\n\n /** Unregister an element from dimension tracking */\n unregisterElement(elementId: string): void {\n const element = this.elementRefs.get(elementId);\n if (element && this.resizeObserver) {\n this.resizeObserver.unobserve(element);\n }\n this.elementRefs.delete(elementId);\n this.scheduleDimensionUpdate();\n }\n\n /** Set up the ResizeObserver to track element dimension changes */\n private setupResizeObserver(): void {\n if (typeof ResizeObserver === 'undefined') {\n return;\n }\n\n this.resizeObserver = new ResizeObserver(() => {\n this.scheduleDimensionUpdate();\n });\n\n // Observe any already-registered elements\n this.elementRefs.forEach((element) => {\n this.resizeObserver!.observe(element);\n });\n }\n\n /** Clean up the ResizeObserver */\n private cleanupResizeObserver(): void {\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n }\n\n /** Schedule a debounced dimension update */\n private scheduleDimensionUpdate(): void {\n if (this.dimensionUpdateTimer) {\n clearTimeout(this.dimensionUpdateTimer);\n }\n\n this.dimensionUpdateTimer = setTimeout(() => {\n this.emitRenderedElements();\n }, 10);\n }\n\n /** Collect and emit all rendered element dimensions */\n private emitRenderedElements(): void {\n const currentElements = this.elements();\n const renderedElements: RenderedElement[] = [];\n\n for (const element of currentElements) {\n const domElement = this.elementRefs.get(element.id);\n if (domElement) {\n const rect = domElement.getBoundingClientRect();\n // Get the actual size without zoom transform\n const zoom = this.viewport().zoom;\n renderedElements.push({\n id: element.id,\n x: element.x,\n y: element.y,\n width: rect.width / zoom,\n height: rect.height / zoom,\n });\n }\n }\n\n if (renderedElements.length > 0) {\n this.elementsRendered.emit(renderedElements);\n }\n }\n}\n","<div\n class=\"grid-container\"\n [ngStyle]=\"containerStyles()\"\n (mousedown)=\"onMouseDown($event)\"\n (wheel)=\"onWheel($event)\">\n <div class=\"grid-background\" [ngStyle]=\"backgroundStyles()\"></div>\n <div class=\"grid-viewport\" [style.transform]=\"viewportTransform()\">\n @for (element of elements(); track element.id) {\n <div\n class=\"grid-element\"\n [gridElementRef]=\"element.id\"\n [ngStyle]=\"getElementStyles(element)\"\n (mousedown)=\"onElementMouseDown($event, element)\">\n <ng-container\n *ngComponentOutlet=\"element.component; injector: createElementInjector(element)\" />\n </div>\n }\n </div>\n @if (showToolbar() && integratedToolbarConfig()) {\n <ngx-grid-toolbar [config]=\"integratedToolbarConfig()!\" />\n }\n @if (isLoading()) {\n <div class=\"loading-overlay\">\n <div class=\"loading-spinner\"></div>\n </div>\n }\n</div>\n","// Components\nexport { GridComponent } from './lib/ngx-grid/ngx-grid';\nexport { ToolbarComponent } from './lib/components/toolbar/toolbar.component';\n\n// Models\nexport type {\n GridConfig,\n GridToolbarConfig,\n DimensionMode,\n BackgroundMode,\n ViewportState,\n GridElement,\n ReactiveData,\n RenderedElement,\n ElementPositionChange,\n ToolbarPosition,\n ToolbarButton,\n ToolbarConfig,\n // Animation types\n EasingFunction,\n EasingName,\n ViewportAnimationOptions,\n} from './lib/models/grid.models';\nexport {\n DEFAULT_GRID_CONFIG,\n DEFAULT_CELL_SIZE,\n DEFAULT_PATTERN_COLOR,\n DEFAULT_BACKGROUND_COLOR,\n DEFAULT_VIEWPORT_STATE,\n DEFAULT_ZOOM_MIN,\n DEFAULT_ZOOM_MAX,\n DEFAULT_ZOOM_SPEED,\n GRID_ELEMENT_DATA,\n // Animation exports\n EASING_FUNCTIONS,\n DEFAULT_ANIMATION_DURATION,\n DEFAULT_EASING,\n} from './lib/models/grid.models';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/index.d.ts
CHANGED
|
@@ -176,6 +176,34 @@ declare const DEFAULT_GRID_CONFIG: GridConfig;
|
|
|
176
176
|
* Default viewport state
|
|
177
177
|
*/
|
|
178
178
|
declare const DEFAULT_VIEWPORT_STATE: ViewportState;
|
|
179
|
+
/**
|
|
180
|
+
* Easing function type for animations
|
|
181
|
+
* Takes a progress value (0-1) and returns an eased value (0-1)
|
|
182
|
+
*/
|
|
183
|
+
type EasingFunction = (t: number) => number;
|
|
184
|
+
/**
|
|
185
|
+
* Built-in easing function names
|
|
186
|
+
*/
|
|
187
|
+
type EasingName = 'linear' | 'ease-out' | 'ease-in' | 'ease-in-out';
|
|
188
|
+
/**
|
|
189
|
+
* Options for animated viewport transitions
|
|
190
|
+
*/
|
|
191
|
+
interface ViewportAnimationOptions {
|
|
192
|
+
/** Whether to animate the transition (default: false) */
|
|
193
|
+
animated?: boolean;
|
|
194
|
+
/** Animation duration in milliseconds (default: 300) */
|
|
195
|
+
duration?: number;
|
|
196
|
+
/** Easing function name or custom function (default: 'ease-out') */
|
|
197
|
+
easing?: EasingName | EasingFunction;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Built-in easing functions
|
|
201
|
+
*/
|
|
202
|
+
declare const EASING_FUNCTIONS: Record<EasingName, EasingFunction>;
|
|
203
|
+
/** Default animation duration in milliseconds */
|
|
204
|
+
declare const DEFAULT_ANIMATION_DURATION = 300;
|
|
205
|
+
/** Default easing function name */
|
|
206
|
+
declare const DEFAULT_EASING: EasingName;
|
|
179
207
|
/**
|
|
180
208
|
* Position for the floating toolbar
|
|
181
209
|
*/
|
|
@@ -248,6 +276,8 @@ declare class GridComponent implements AfterViewInit, OnDestroy {
|
|
|
248
276
|
private elementPositions;
|
|
249
277
|
/** Track if we're currently dragging to avoid overwriting drag position */
|
|
250
278
|
private syncPositionsFromInput;
|
|
279
|
+
/** Animation frame ID for viewport animation (used for cancellation) */
|
|
280
|
+
private viewportAnimationId;
|
|
251
281
|
constructor();
|
|
252
282
|
/** Computed container styles based on config */
|
|
253
283
|
containerStyles: _angular_core.Signal<Record<string, string>>;
|
|
@@ -277,15 +307,35 @@ declare class GridComponent implements AfterViewInit, OnDestroy {
|
|
|
277
307
|
private onElementMouseMove;
|
|
278
308
|
/** Handle mouse up to stop element dragging */
|
|
279
309
|
private onElementMouseUp;
|
|
280
|
-
/**
|
|
281
|
-
|
|
310
|
+
/**
|
|
311
|
+
* Cancel any running viewport animation
|
|
312
|
+
*/
|
|
313
|
+
cancelViewportAnimation(): void;
|
|
314
|
+
/**
|
|
315
|
+
* Animate viewport to a target state
|
|
316
|
+
* @param to Target viewport state
|
|
317
|
+
* @param options Animation options
|
|
318
|
+
*/
|
|
319
|
+
private animateViewport;
|
|
320
|
+
/**
|
|
321
|
+
* Set viewport with optional animation
|
|
322
|
+
* @param newViewport Target viewport state
|
|
323
|
+
* @param options Animation options (if animated is false or undefined, sets immediately)
|
|
324
|
+
*/
|
|
325
|
+
private setViewport;
|
|
326
|
+
/**
|
|
327
|
+
* Reset viewport to default position
|
|
328
|
+
* @param options Animation options
|
|
329
|
+
*/
|
|
330
|
+
resetViewport(options?: ViewportAnimationOptions): void;
|
|
282
331
|
/**
|
|
283
332
|
* Fit all content to view
|
|
284
333
|
* Centers content in the viewport, optionally zooming out to fit everything
|
|
285
334
|
* @param fitZoom If true, zooms out if needed to fit all content (never zooms in beyond 1.0)
|
|
286
335
|
* @param padding Padding around content in pixels (default: 40)
|
|
336
|
+
* @param options Animation options
|
|
287
337
|
*/
|
|
288
|
-
fitToView(fitZoom?: boolean, padding?: number): void;
|
|
338
|
+
fitToView(fitZoom?: boolean, padding?: number, options?: ViewportAnimationOptions): void;
|
|
289
339
|
/**
|
|
290
340
|
* Check if an element is fully visible in the viewport
|
|
291
341
|
* @param elementId The element ID to check
|
|
@@ -296,15 +346,17 @@ declare class GridComponent implements AfterViewInit, OnDestroy {
|
|
|
296
346
|
/**
|
|
297
347
|
* Center viewport on a specific element (no zoom change)
|
|
298
348
|
* @param elementId The element ID to center on
|
|
349
|
+
* @param options Animation options
|
|
299
350
|
*/
|
|
300
|
-
centerOnElement(elementId: string): void;
|
|
351
|
+
centerOnElement(elementId: string, options?: ViewportAnimationOptions): void;
|
|
301
352
|
/**
|
|
302
353
|
* Scroll element into view with minimal pan
|
|
303
354
|
* Only pans if element is not fully visible
|
|
304
355
|
* @param elementId The element ID to scroll into view
|
|
305
356
|
* @param padding Padding from viewport edges (default: 40)
|
|
357
|
+
* @param options Animation options
|
|
306
358
|
*/
|
|
307
|
-
scrollToElement(elementId: string, padding?: number): void;
|
|
359
|
+
scrollToElement(elementId: string, padding?: number, options?: ViewportAnimationOptions): void;
|
|
308
360
|
/**
|
|
309
361
|
* Get bounds of a specific element
|
|
310
362
|
* @param elementId The element ID
|
|
@@ -358,5 +410,5 @@ declare class ToolbarComponent {
|
|
|
358
410
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ToolbarComponent, "ngx-grid-toolbar", never, { "config": { "alias": "config"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
359
411
|
}
|
|
360
412
|
|
|
361
|
-
export { DEFAULT_BACKGROUND_COLOR, DEFAULT_CELL_SIZE, DEFAULT_GRID_CONFIG, DEFAULT_PATTERN_COLOR, DEFAULT_VIEWPORT_STATE, DEFAULT_ZOOM_MAX, DEFAULT_ZOOM_MIN, DEFAULT_ZOOM_SPEED, GRID_ELEMENT_DATA, GridComponent, ToolbarComponent };
|
|
362
|
-
export type { BackgroundMode, DimensionMode, ElementPositionChange, GridConfig, GridElement, GridToolbarConfig, ReactiveData, RenderedElement, ToolbarButton, ToolbarConfig, ToolbarPosition, ViewportState };
|
|
413
|
+
export { DEFAULT_ANIMATION_DURATION, DEFAULT_BACKGROUND_COLOR, DEFAULT_CELL_SIZE, DEFAULT_EASING, DEFAULT_GRID_CONFIG, DEFAULT_PATTERN_COLOR, DEFAULT_VIEWPORT_STATE, DEFAULT_ZOOM_MAX, DEFAULT_ZOOM_MIN, DEFAULT_ZOOM_SPEED, EASING_FUNCTIONS, GRID_ELEMENT_DATA, GridComponent, ToolbarComponent };
|
|
414
|
+
export type { BackgroundMode, DimensionMode, EasingFunction, EasingName, ElementPositionChange, GridConfig, GridElement, GridToolbarConfig, ReactiveData, RenderedElement, ToolbarButton, ToolbarConfig, ToolbarPosition, ViewportAnimationOptions, ViewportState };
|