@ngx-km/grid 0.0.1
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/README.md +310 -0
- package/fesm2022/ngx-km-grid.mjs +820 -0
- package/fesm2022/ngx-km-grid.mjs.map +1 -0
- package/index.d.ts +362 -0
- package/package.json +24 -0
package/README.md
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
# @ngx-km/grid
|
|
2
|
+
|
|
3
|
+
Interactive infinite canvas grid component for Angular 19+.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Infinite canvas** with smooth pan and zoom
|
|
8
|
+
- **Render any Angular component** at specific coordinates
|
|
9
|
+
- **Automatic dimension tracking** with ResizeObserver
|
|
10
|
+
- **Element dragging** with optional grid snapping
|
|
11
|
+
- **Configurable backgrounds** (lines, dots, or none)
|
|
12
|
+
- **Floating toolbar** with built-in zoom controls
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @ngx-km/grid
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { Component } from '@angular/core';
|
|
24
|
+
import { GridComponent, GridConfig } from '@ngx-km/grid';
|
|
25
|
+
|
|
26
|
+
@Component({
|
|
27
|
+
selector: 'app-example',
|
|
28
|
+
standalone: true,
|
|
29
|
+
imports: [GridComponent],
|
|
30
|
+
template: `
|
|
31
|
+
<div style="width: 100%; height: 500px;">
|
|
32
|
+
<ngx-grid [config]="gridConfig" />
|
|
33
|
+
</div>
|
|
34
|
+
`
|
|
35
|
+
})
|
|
36
|
+
export class ExampleComponent {
|
|
37
|
+
gridConfig: GridConfig = {
|
|
38
|
+
dimensionMode: 'full',
|
|
39
|
+
backgroundMode: 'lines',
|
|
40
|
+
cellSize: 20,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## API Reference
|
|
46
|
+
|
|
47
|
+
### GridComponent
|
|
48
|
+
|
|
49
|
+
**Selector:** `ngx-grid`
|
|
50
|
+
|
|
51
|
+
#### Inputs
|
|
52
|
+
|
|
53
|
+
| Input | Type | Default | Description |
|
|
54
|
+
|-------|------|---------|-------------|
|
|
55
|
+
| `config` | `GridConfig` | See defaults | Grid configuration |
|
|
56
|
+
| `elements` | `GridElement[]` | `[]` | Elements to render on the grid |
|
|
57
|
+
|
|
58
|
+
#### Outputs
|
|
59
|
+
|
|
60
|
+
| Output | Type | Description |
|
|
61
|
+
|--------|------|-------------|
|
|
62
|
+
| `viewportChange` | `ViewportState` | Emitted when pan/zoom changes |
|
|
63
|
+
| `elementsRendered` | `RenderedElement[]` | Emitted when element dimensions are measured |
|
|
64
|
+
| `elementPositionChange` | `ElementPositionChange` | Emitted when an element is dragged |
|
|
65
|
+
|
|
66
|
+
#### Public Methods
|
|
67
|
+
|
|
68
|
+
| Method | Description |
|
|
69
|
+
|--------|-------------|
|
|
70
|
+
| `resetViewport()` | Reset pan and zoom to origin |
|
|
71
|
+
| `zoomIn(factor?)` | Zoom in by factor (default 1.25x) |
|
|
72
|
+
| `zoomOut(factor?)` | Zoom out by factor (default 1.25x) |
|
|
73
|
+
|
|
74
|
+
### GridConfig
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
interface GridConfig {
|
|
78
|
+
// Dimension settings
|
|
79
|
+
dimensionMode: 'fixed' | 'full';
|
|
80
|
+
width?: number; // For fixed mode
|
|
81
|
+
height?: number; // For fixed mode
|
|
82
|
+
minWidth?: number;
|
|
83
|
+
minHeight?: number;
|
|
84
|
+
maxWidth?: number;
|
|
85
|
+
maxHeight?: number;
|
|
86
|
+
|
|
87
|
+
// Background settings
|
|
88
|
+
backgroundMode?: 'lines' | 'dots' | 'none';
|
|
89
|
+
cellSize?: number; // Default: 20
|
|
90
|
+
backgroundPatternColor?: string;
|
|
91
|
+
backgroundPatternOpacity?: number;
|
|
92
|
+
backgroundColor?: string;
|
|
93
|
+
|
|
94
|
+
// Pan settings
|
|
95
|
+
panEnabled?: boolean; // Default: true
|
|
96
|
+
panMinX?: number; // Infinite if not set
|
|
97
|
+
panMaxX?: number;
|
|
98
|
+
panMinY?: number;
|
|
99
|
+
panMaxY?: number;
|
|
100
|
+
|
|
101
|
+
// Zoom settings
|
|
102
|
+
zoomEnabled?: boolean; // Default: true
|
|
103
|
+
zoomMin?: number; // Default: 0.1
|
|
104
|
+
zoomMax?: number; // Default: 5
|
|
105
|
+
zoomSpeed?: number; // Default: 0.001
|
|
106
|
+
|
|
107
|
+
// Drag settings
|
|
108
|
+
dragEnabled?: boolean; // Default: true
|
|
109
|
+
snapEnabled?: boolean; // Default: false
|
|
110
|
+
snapGridSize?: number; // Default: uses cellSize
|
|
111
|
+
|
|
112
|
+
// Toolbar settings
|
|
113
|
+
toolbar?: GridToolbarConfig;
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### GridElement
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
interface GridElement<T = unknown> {
|
|
121
|
+
id: string; // Unique identifier
|
|
122
|
+
component: Type<unknown>; // Angular component to render
|
|
123
|
+
data?: T; // Data passed to component
|
|
124
|
+
x: number; // X position in world space
|
|
125
|
+
y: number; // Y position in world space
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Usage Examples
|
|
130
|
+
|
|
131
|
+
### Rendering Custom Components
|
|
132
|
+
|
|
133
|
+
Create a node component that receives data via the `GRID_ELEMENT_DATA` token:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import { Component, inject } from '@angular/core';
|
|
137
|
+
import { GRID_ELEMENT_DATA } from '@ngx-km/grid';
|
|
138
|
+
|
|
139
|
+
interface NodeData {
|
|
140
|
+
title: string;
|
|
141
|
+
color: string;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@Component({
|
|
145
|
+
selector: 'app-node',
|
|
146
|
+
standalone: true,
|
|
147
|
+
template: `
|
|
148
|
+
<div class="node" [style.background]="data.color">
|
|
149
|
+
{{ data.title }}
|
|
150
|
+
</div>
|
|
151
|
+
`,
|
|
152
|
+
styles: [`
|
|
153
|
+
.node {
|
|
154
|
+
padding: 16px 24px;
|
|
155
|
+
border-radius: 8px;
|
|
156
|
+
color: white;
|
|
157
|
+
font-weight: bold;
|
|
158
|
+
}
|
|
159
|
+
`]
|
|
160
|
+
})
|
|
161
|
+
export class NodeComponent {
|
|
162
|
+
data = inject<NodeData>(GRID_ELEMENT_DATA);
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Use it in your grid:
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
import { Component, signal } from '@angular/core';
|
|
170
|
+
import { GridComponent, GridConfig, GridElement } from '@ngx-km/grid';
|
|
171
|
+
import { NodeComponent, NodeData } from './node.component';
|
|
172
|
+
|
|
173
|
+
@Component({
|
|
174
|
+
selector: 'app-graph',
|
|
175
|
+
standalone: true,
|
|
176
|
+
imports: [GridComponent],
|
|
177
|
+
template: `
|
|
178
|
+
<ngx-grid
|
|
179
|
+
[config]="config"
|
|
180
|
+
[elements]="elements()"
|
|
181
|
+
(elementPositionChange)="onDrag($event)" />
|
|
182
|
+
`
|
|
183
|
+
})
|
|
184
|
+
export class GraphComponent {
|
|
185
|
+
config: GridConfig = {
|
|
186
|
+
dimensionMode: 'full',
|
|
187
|
+
backgroundMode: 'dots',
|
|
188
|
+
dragEnabled: true,
|
|
189
|
+
snapEnabled: true,
|
|
190
|
+
snapGridSize: 20,
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
elements = signal<GridElement<NodeData>[]>([
|
|
194
|
+
{
|
|
195
|
+
id: 'node-1',
|
|
196
|
+
component: NodeComponent,
|
|
197
|
+
data: { title: 'Start', color: '#22c55e' },
|
|
198
|
+
x: 100,
|
|
199
|
+
y: 100,
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
id: 'node-2',
|
|
203
|
+
component: NodeComponent,
|
|
204
|
+
data: { title: 'End', color: '#ef4444' },
|
|
205
|
+
x: 300,
|
|
206
|
+
y: 200,
|
|
207
|
+
},
|
|
208
|
+
]);
|
|
209
|
+
|
|
210
|
+
onDrag(event: ElementPositionChange) {
|
|
211
|
+
console.log(`Element ${event.id} moved to (${event.x}, ${event.y})`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Adding a Toolbar
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
const config: GridConfig = {
|
|
220
|
+
dimensionMode: 'full',
|
|
221
|
+
toolbar: {
|
|
222
|
+
position: 'top-right',
|
|
223
|
+
showZoomControls: true,
|
|
224
|
+
showResetView: true,
|
|
225
|
+
customButtons: [
|
|
226
|
+
{
|
|
227
|
+
id: 'add-node',
|
|
228
|
+
label: 'Add Node',
|
|
229
|
+
icon: '<svg>...</svg>',
|
|
230
|
+
onClick: () => this.addNode(),
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
id: 'toggle-snap',
|
|
234
|
+
label: 'Toggle Snap',
|
|
235
|
+
active: this.snapEnabled(),
|
|
236
|
+
onClick: () => this.toggleSnap(),
|
|
237
|
+
},
|
|
238
|
+
],
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Tracking Element Dimensions
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
@Component({
|
|
247
|
+
template: `
|
|
248
|
+
<ngx-grid
|
|
249
|
+
[config]="config"
|
|
250
|
+
[elements]="elements()"
|
|
251
|
+
(elementsRendered)="onElementsRendered($event)" />
|
|
252
|
+
`
|
|
253
|
+
})
|
|
254
|
+
export class MyComponent {
|
|
255
|
+
onElementsRendered(elements: RenderedElement[]) {
|
|
256
|
+
elements.forEach(el => {
|
|
257
|
+
console.log(`${el.id}: ${el.width}x${el.height} at (${el.x}, ${el.y})`);
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Controlling Viewport Programmatically
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
@Component({
|
|
267
|
+
template: `
|
|
268
|
+
<ngx-grid #grid [config]="config" />
|
|
269
|
+
<button (click)="grid.resetViewport()">Reset</button>
|
|
270
|
+
<button (click)="grid.zoomIn()">Zoom In</button>
|
|
271
|
+
<button (click)="grid.zoomOut()">Zoom Out</button>
|
|
272
|
+
`
|
|
273
|
+
})
|
|
274
|
+
export class MyComponent {}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## Exports
|
|
278
|
+
|
|
279
|
+
### Components
|
|
280
|
+
- `GridComponent` - Main grid component
|
|
281
|
+
- `ToolbarComponent` - Standalone toolbar (used internally)
|
|
282
|
+
|
|
283
|
+
### Types
|
|
284
|
+
- `GridConfig` - Grid configuration interface
|
|
285
|
+
- `GridToolbarConfig` - Toolbar configuration
|
|
286
|
+
- `GridElement<T>` - Element definition
|
|
287
|
+
- `RenderedElement` - Element with tracked dimensions
|
|
288
|
+
- `ElementPositionChange` - Drag event data
|
|
289
|
+
- `ViewportState` - Pan/zoom state
|
|
290
|
+
- `DimensionMode` - 'fixed' | 'full'
|
|
291
|
+
- `BackgroundMode` - 'lines' | 'dots' | 'none'
|
|
292
|
+
- `ToolbarPosition` - Toolbar position options
|
|
293
|
+
- `ToolbarButton` - Button configuration
|
|
294
|
+
- `ToolbarConfig` - Full toolbar config
|
|
295
|
+
|
|
296
|
+
### Constants
|
|
297
|
+
- `DEFAULT_GRID_CONFIG` - Default configuration
|
|
298
|
+
- `DEFAULT_VIEWPORT_STATE` - Default viewport
|
|
299
|
+
- `GRID_ELEMENT_DATA` - Injection token for element data
|
|
300
|
+
- `DEFAULT_CELL_SIZE`, `DEFAULT_ZOOM_MIN`, etc.
|
|
301
|
+
|
|
302
|
+
## Running Tests
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
nx test ngx-grid
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## License
|
|
309
|
+
|
|
310
|
+
MIT
|