@ngx-km/grid
v0.0.3
Published
Interactive infinite canvas grid component for Angular 19+.
Downloads
329
Readme
@ngx-km/grid
Interactive infinite canvas grid component for Angular 19+.
Features
- Infinite canvas with smooth pan and zoom
- Render any Angular component at specific coordinates
- Automatic dimension tracking with ResizeObserver
- Element dragging with optional grid snapping
- Configurable backgrounds (lines, dots, or none)
- Floating toolbar with built-in zoom controls
Installation
npm install @ngx-km/gridQuick Start
import { Component } from '@angular/core';
import { GridComponent, GridConfig } from '@ngx-km/grid';
@Component({
selector: 'app-example',
standalone: true,
imports: [GridComponent],
template: `
<div style="width: 100%; height: 500px;">
<ngx-grid [config]="gridConfig" />
</div>
`
})
export class ExampleComponent {
gridConfig: GridConfig = {
dimensionMode: 'full',
backgroundMode: 'lines',
cellSize: 20,
};
}API Reference
GridComponent
Selector: ngx-grid
Inputs
| Input | Type | Default | Description |
|-------|------|---------|-------------|
| config | GridConfig | See defaults | Grid configuration |
| elements | GridElement[] | [] | Elements to render on the grid |
Outputs
| Output | Type | Description |
|--------|------|-------------|
| viewportChange | ViewportState | Emitted when pan/zoom changes |
| elementsRendered | RenderedElement[] | Emitted when element dimensions are measured |
| elementPositionChange | ElementPositionChange | Emitted when an element is dragged |
Public Methods
| Method | Description |
|--------|-------------|
| resetViewport() | Reset pan and zoom to origin |
| zoomIn(factor?) | Zoom in by factor (default 1.25x) |
| zoomOut(factor?) | Zoom out by factor (default 1.25x) |
GridConfig
interface GridConfig {
// Dimension settings
dimensionMode: 'fixed' | 'full';
width?: number; // For fixed mode
height?: number; // For fixed mode
minWidth?: number;
minHeight?: number;
maxWidth?: number;
maxHeight?: number;
// Background settings
backgroundMode?: 'lines' | 'dots' | 'none';
cellSize?: number; // Default: 20
backgroundPatternColor?: string;
backgroundPatternOpacity?: number;
backgroundColor?: string;
// Pan settings
panEnabled?: boolean; // Default: true
panMinX?: number; // Infinite if not set
panMaxX?: number;
panMinY?: number;
panMaxY?: number;
// Zoom settings
zoomEnabled?: boolean; // Default: true
zoomMin?: number; // Default: 0.1
zoomMax?: number; // Default: 5
zoomSpeed?: number; // Default: 0.001
// Drag settings
dragEnabled?: boolean; // Default: true
snapEnabled?: boolean; // Default: false
snapGridSize?: number; // Default: uses cellSize
// Toolbar settings
toolbar?: GridToolbarConfig;
}GridElement
interface GridElement<T = unknown> {
id: string; // Unique identifier
component: Type<unknown>; // Angular component to render
data?: T; // Data passed to component
x: number; // X position in world space
y: number; // Y position in world space
}Usage Examples
Rendering Custom Components
Create a node component that receives data via the GRID_ELEMENT_DATA token:
import { Component, inject } from '@angular/core';
import { GRID_ELEMENT_DATA } from '@ngx-km/grid';
interface NodeData {
title: string;
color: string;
}
@Component({
selector: 'app-node',
standalone: true,
template: `
<div class="node" [style.background]="data.color">
{{ data.title }}
</div>
`,
styles: [`
.node {
padding: 16px 24px;
border-radius: 8px;
color: white;
font-weight: bold;
}
`]
})
export class NodeComponent {
data = inject<NodeData>(GRID_ELEMENT_DATA);
}Use it in your grid:
import { Component, signal } from '@angular/core';
import { GridComponent, GridConfig, GridElement } from '@ngx-km/grid';
import { NodeComponent, NodeData } from './node.component';
@Component({
selector: 'app-graph',
standalone: true,
imports: [GridComponent],
template: `
<ngx-grid
[config]="config"
[elements]="elements()"
(elementPositionChange)="onDrag($event)" />
`
})
export class GraphComponent {
config: GridConfig = {
dimensionMode: 'full',
backgroundMode: 'dots',
dragEnabled: true,
snapEnabled: true,
snapGridSize: 20,
};
elements = signal<GridElement<NodeData>[]>([
{
id: 'node-1',
component: NodeComponent,
data: { title: 'Start', color: '#22c55e' },
x: 100,
y: 100,
},
{
id: 'node-2',
component: NodeComponent,
data: { title: 'End', color: '#ef4444' },
x: 300,
y: 200,
},
]);
onDrag(event: ElementPositionChange) {
console.log(`Element ${event.id} moved to (${event.x}, ${event.y})`);
}
}Adding a Toolbar
const config: GridConfig = {
dimensionMode: 'full',
toolbar: {
position: 'top-right',
showZoomControls: true,
showResetView: true,
customButtons: [
{
id: 'add-node',
label: 'Add Node',
icon: '<svg>...</svg>',
onClick: () => this.addNode(),
},
{
id: 'toggle-snap',
label: 'Toggle Snap',
active: this.snapEnabled(),
onClick: () => this.toggleSnap(),
},
],
},
};Tracking Element Dimensions
@Component({
template: `
<ngx-grid
[config]="config"
[elements]="elements()"
(elementsRendered)="onElementsRendered($event)" />
`
})
export class MyComponent {
onElementsRendered(elements: RenderedElement[]) {
elements.forEach(el => {
console.log(`${el.id}: ${el.width}x${el.height} at (${el.x}, ${el.y})`);
});
}
}Controlling Viewport Programmatically
@Component({
template: `
<ngx-grid #grid [config]="config" />
<button (click)="grid.resetViewport()">Reset</button>
<button (click)="grid.zoomIn()">Zoom In</button>
<button (click)="grid.zoomOut()">Zoom Out</button>
`
})
export class MyComponent {}Exports
Components
GridComponent- Main grid componentToolbarComponent- Standalone toolbar (used internally)
Types
GridConfig- Grid configuration interfaceGridToolbarConfig- Toolbar configurationGridElement<T>- Element definitionRenderedElement- Element with tracked dimensionsElementPositionChange- Drag event dataViewportState- Pan/zoom stateDimensionMode- 'fixed' | 'full'BackgroundMode- 'lines' | 'dots' | 'none'ToolbarPosition- Toolbar position optionsToolbarButton- Button configurationToolbarConfig- Full toolbar config
Constants
DEFAULT_GRID_CONFIG- Default configurationDEFAULT_VIEWPORT_STATE- Default viewportGRID_ELEMENT_DATA- Injection token for element dataDEFAULT_CELL_SIZE,DEFAULT_ZOOM_MIN, etc.
Running Tests
nx test ngx-gridLicense
MIT
