@toclocoinc/lattice-grid 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1232 @@
1
+ /*!
2
+ * Lattice Grid 1.1.0 — type declarations
3
+ * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
4
+ * https://latticegrid.dev
5
+ */
6
+ /**
7
+ * Lattice Grid — public type declarations.
8
+ * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
9
+ *
10
+ * These declarations describe the public API of the vanilla-JavaScript
11
+ * implementation. They are shipped for consumer tooling only; nothing in the
12
+ * build pipeline reads them.
13
+ */
14
+
15
+ // ---------------------------------------------------------------------------
16
+ // Primitives
17
+ // ---------------------------------------------------------------------------
18
+
19
+ export type TypeName =
20
+ | 'text' | 'number' | 'boolean' | 'date' | 'dateString' | 'object' | 'lookup'
21
+ | (string & {});
22
+
23
+ export type Align = 'start' | 'center' | 'end';
24
+ export type Density = 'compact' | 'comfortable';
25
+ export type Theme = 'light' | 'dark' | (string & {});
26
+ export type ColumnRef = string;
27
+ export type Comparator = (
28
+ a: unknown, b: unknown, rowA?: Row, rowB?: Row, descending?: boolean,
29
+ ) => number;
30
+
31
+ export interface CellStyle { [cssProperty: string]: string | number | null | undefined }
32
+
33
+ // ---------------------------------------------------------------------------
34
+ // Rows
35
+ // ---------------------------------------------------------------------------
36
+
37
+ export interface Row {
38
+ key: string;
39
+ data: unknown | null;
40
+ level: number;
41
+ parent: Row | null;
42
+ children?: Row[];
43
+ filteredChildren?: Row[];
44
+ sortedChildren?: Row[];
45
+ group: boolean;
46
+ expanded: boolean;
47
+ leafCount: number;
48
+ totals?: Record<string, unknown>;
49
+ detail?: boolean;
50
+ master?: boolean;
51
+ height: number;
52
+ index: number | null;
53
+ selected: boolean | 'partial';
54
+ /** Physical index into the ColumnStore. Null for synthetic rows. */
55
+ physical?: number | null;
56
+ /** Group rows only: the column id this level groups on, and the group value. */
57
+ groupColumn?: string;
58
+ groupValue?: unknown;
59
+ /** Stable path of group keys from root to this row. */
60
+ groupPath?: string[];
61
+ hasChildren?: boolean;
62
+ }
63
+
64
+ export interface RowChange {
65
+ add?: unknown[];
66
+ at?: number;
67
+ update?: unknown[];
68
+ remove?: unknown[] | string[];
69
+ }
70
+
71
+ export interface ChangeResult {
72
+ added: Row[];
73
+ updated: Row[];
74
+ removed: string[];
75
+ }
76
+
77
+ // ---------------------------------------------------------------------------
78
+ // Parameter bags handed to user callbacks
79
+ // ---------------------------------------------------------------------------
80
+
81
+ export interface ValueParams {
82
+ value: unknown;
83
+ data: unknown;
84
+ row: Row;
85
+ column: Column;
86
+ colId: string;
87
+ grid: Grid;
88
+ context: unknown;
89
+ }
90
+
91
+ export interface CellParams extends ValueParams {
92
+ text: string;
93
+ index: number;
94
+ props?: Record<string, unknown>;
95
+ }
96
+
97
+ export interface FormatParams extends ValueParams { locale: string }
98
+ export interface ParseParams { text: string; value: unknown; data: unknown; row: Row; column: Column; grid: Grid; context: unknown }
99
+ export interface ApplyParams { value: unknown; oldValue: unknown; data: unknown; row: Row; column: Column; grid: Grid; context: unknown }
100
+ export interface KeyParams extends ValueParams {}
101
+ export interface ValidateParams extends ApplyParams {}
102
+ export interface SpanParams extends CellParams {}
103
+ export interface ValueContext { data: unknown; row: Row; column: Column; grid: Grid; context: unknown }
104
+ export type DepValues = Record<string, unknown>;
105
+
106
+ // ---------------------------------------------------------------------------
107
+ // Formatting (spec 8.5)
108
+ // ---------------------------------------------------------------------------
109
+
110
+ export interface NumberFormat {
111
+ type?: 'number';
112
+ style?: 'decimal' | 'currency' | 'percent';
113
+ currency?: string;
114
+ currencyDisplay?: 'symbol' | 'code' | 'name' | 'narrowSymbol';
115
+ decimals?: number;
116
+ minDecimals?: number;
117
+ maxDecimals?: number;
118
+ thousandsSeparator?: boolean | string;
119
+ decimalSeparator?: string;
120
+ notation?: 'standard' | 'compact' | 'scientific';
121
+ negative?: 'minus' | 'parentheses' | 'suffix';
122
+ negativeClass?: string;
123
+ prefix?: string;
124
+ suffix?: string;
125
+ zeroDisplay?: string;
126
+ nullDisplay?: string;
127
+ locale?: string;
128
+ scale?: number;
129
+ }
130
+
131
+ export interface DateFormat {
132
+ type: 'date';
133
+ pattern?: string;
134
+ dateStyle?: 'short' | 'medium' | 'long' | 'full';
135
+ timeStyle?: 'short' | 'medium' | 'long';
136
+ timeZone?: string;
137
+ relative?: boolean | { threshold?: number };
138
+ nullDisplay?: string;
139
+ locale?: string;
140
+ }
141
+
142
+ export interface BooleanFormat {
143
+ type: 'boolean';
144
+ display?: 'checkbox' | 'switch' | 'text' | 'icon';
145
+ trueLabel?: string;
146
+ falseLabel?: string;
147
+ nullLabel?: string;
148
+ trueIcon?: string;
149
+ falseIcon?: string;
150
+ }
151
+
152
+ export interface TextFormat {
153
+ type: 'text';
154
+ transform?: 'none' | 'upper' | 'lower' | 'title';
155
+ truncate?: number | { chars: number; ellipsis?: string };
156
+ nullDisplay?: string;
157
+ emptyDisplay?: string;
158
+ }
159
+
160
+ export type FormatSpec = NumberFormat | DateFormat | BooleanFormat | TextFormat;
161
+
162
+ // ---------------------------------------------------------------------------
163
+ // Data types (spec 8.2)
164
+ // ---------------------------------------------------------------------------
165
+
166
+ export interface DataType {
167
+ base: 'text' | 'number' | 'boolean' | 'date' | 'dateString' | 'object';
168
+ extends?: TypeName;
169
+ matches?: (value: unknown) => boolean;
170
+ format?: (p: FormatParams) => string;
171
+ parse?: (p: ParseParams) => unknown;
172
+ compare?: Comparator;
173
+ defaults?: {
174
+ filter?: FilterName;
175
+ editor?: EditorName;
176
+ total?: TotalName;
177
+ align?: Align;
178
+ };
179
+ storage?: 'float64' | 'int32' | 'bitset' | 'dictionary' | 'object';
180
+ excel?: string;
181
+ toClipboard?: (v: unknown) => string;
182
+ fromClipboard?: (s: string) => unknown;
183
+ }
184
+
185
+ // ---------------------------------------------------------------------------
186
+ // Lookups (spec 8.3)
187
+ // ---------------------------------------------------------------------------
188
+
189
+ export interface Option {
190
+ id: unknown;
191
+ label: string;
192
+ disabled?: boolean;
193
+ variant?: VariantName;
194
+ icon?: string;
195
+ group?: string;
196
+ }
197
+
198
+ export interface LookupSpec {
199
+ options?: Option[] | (() => Option[] | Promise<Option[]>);
200
+ valueKey?: string;
201
+ labelKey?: string;
202
+ groupKey?: string;
203
+ multiple?: boolean;
204
+ allowCustom?: boolean;
205
+ unknownLabel?: string | ((v: unknown) => string);
206
+ search?: (query: string, signal: AbortSignal) => Promise<Option[]>;
207
+ sortBy?: 'label' | 'value' | 'optionOrder' | 'count';
208
+ separator?: string;
209
+ }
210
+
211
+ // ---------------------------------------------------------------------------
212
+ // Decoration and variants (spec 8.7)
213
+ // ---------------------------------------------------------------------------
214
+
215
+ export type DecorationName = 'plain' | 'fill' | 'pill' | 'dot' | 'bar' | 'heat' | 'icon';
216
+ export type VariantName = 'neutral' | 'info' | 'success' | 'warning' | 'danger' | 'accent' | 'none' | (string & {});
217
+
218
+ export interface DecorationSpec {
219
+ type: DecorationName;
220
+ size?: 'sm' | 'md' | 'lg';
221
+ shape?: 'pill' | 'rounded' | 'square';
222
+ outline?: boolean;
223
+ edge?: boolean;
224
+ position?: 'start' | 'end';
225
+ name?: string | Record<string, string>;
226
+ min?: number;
227
+ max?: number;
228
+ origin?: number;
229
+ showValue?: boolean;
230
+ track?: boolean;
231
+ ramp?: string;
232
+ midpoint?: number;
233
+ }
234
+
235
+ export interface VariantWhen { op: Operator; value?: unknown; use: VariantName }
236
+
237
+ export type VariantSpec =
238
+ | VariantName
239
+ | { map: Record<string, VariantName>; default?: VariantName }
240
+ | { when: VariantWhen[]; default?: VariantName }
241
+ | ((p: CellParams) => VariantName);
242
+
243
+ export interface VariantDefinition {
244
+ light: { fill: string; text: string; border: string };
245
+ dark: { fill: string; text: string; border: string };
246
+ }
247
+
248
+ // ---------------------------------------------------------------------------
249
+ // Renderers, editors, filters
250
+ // ---------------------------------------------------------------------------
251
+
252
+ export interface Renderer {
253
+ init(p: CellParams): void;
254
+ element(): HTMLElement;
255
+ refresh?(p: CellParams): boolean;
256
+ attached?(): void;
257
+ destroy?(): void;
258
+ }
259
+ export type RendererCtor = new () => Renderer;
260
+ export type RenderFn = (p: CellParams) => string | HTMLElement;
261
+
262
+ export interface Editor {
263
+ init(p: EditorParams): void;
264
+ element(): HTMLElement;
265
+ value(): unknown;
266
+ attached?(): void;
267
+ cancelBeforeStart?(): boolean;
268
+ cancelOnClose?(): boolean;
269
+ popup?: boolean;
270
+ destroy?(): void;
271
+ }
272
+ export type EditorCtor = new () => Editor;
273
+ export type EditorName = 'text' | 'textarea' | 'number' | 'date' | 'checkbox' | 'select' | 'multiSelect' | (string & {});
274
+
275
+ export interface EditorParams extends CellParams {
276
+ stop(cancel?: boolean): void;
277
+ key?: string;
278
+ charPress?: string;
279
+ }
280
+
281
+ export interface Filter {
282
+ init(p: FilterParams): void;
283
+ active(): boolean;
284
+ passes(p: { row: Row; data: unknown }): boolean;
285
+ get(): unknown;
286
+ set(state: unknown): void;
287
+ element(): HTMLElement;
288
+ onRowsChanged?(): void;
289
+ }
290
+ export type FilterCtor = new () => Filter;
291
+ export type FilterName = 'text' | 'number' | 'date' | 'boolean' | 'set' | 'multi' | 'none' | (string & {});
292
+
293
+ export interface FilterParams {
294
+ column: Column;
295
+ colId: string;
296
+ grid: Grid;
297
+ context: unknown;
298
+ props?: Record<string, unknown>;
299
+ changed(): void;
300
+ }
301
+
302
+ // ---------------------------------------------------------------------------
303
+ // Totals
304
+ // ---------------------------------------------------------------------------
305
+
306
+ export type TotalName = 'sum' | 'min' | 'max' | 'avg' | 'count' | 'first' | 'last' | 'countValues' | (string & {});
307
+ export type TotalFn = (values: unknown[], ctx: { row: Row; column: Column; grid: Grid; context: unknown }) => unknown;
308
+
309
+ // ---------------------------------------------------------------------------
310
+ // Columns (spec 8.1)
311
+ // ---------------------------------------------------------------------------
312
+
313
+ export interface ColumnValueSpec {
314
+ compute?: (deps: DepValues, ctx: ValueContext) => unknown;
315
+ deps?: string[] | '*';
316
+ pure?: boolean;
317
+ format?: (p: FormatParams) => string;
318
+ apply?: (p: ApplyParams) => boolean;
319
+ parse?: (p: ParseParams) => unknown;
320
+ key?: (p: KeyParams) => string;
321
+ compare?: Comparator;
322
+ quickFilterText?: (p: ValueParams) => string;
323
+ }
324
+
325
+ export interface ColumnCellSpec {
326
+ decoration?: DecorationName | DecorationSpec;
327
+ variant?: VariantSpec;
328
+ template?: string;
329
+ render?: string | RenderFn | RendererCtor;
330
+ props?: Record<string, unknown>;
331
+ css?: (p: CellParams) => CellStyle;
332
+ class?: string | string[] | ((p: CellParams) => string | string[]);
333
+ classWhen?: Record<string, string | ((p: CellParams) => boolean)>;
334
+ style?: CellStyle | ((p: CellParams) => CellStyle);
335
+ tooltip?: string | ((p: CellParams) => string);
336
+ align?: Align;
337
+ wrap?: boolean;
338
+ autoHeight?: boolean;
339
+ flash?: boolean;
340
+ spanColumns?: (p: SpanParams) => number;
341
+ spanRows?: (p: SpanParams) => number;
342
+ }
343
+
344
+ export interface ColumnEditSpec {
345
+ enabled?: boolean | ((p: CellParams) => boolean);
346
+ editor?: string | EditorCtor;
347
+ props?: Record<string, unknown>;
348
+ popup?: boolean;
349
+ validate?: (p: ValidateParams) => true | string;
350
+ }
351
+
352
+ export interface ColumnSortSpec {
353
+ enabled?: boolean;
354
+ direction?: 'asc' | 'desc' | null;
355
+ order?: number;
356
+ nullsFirst?: boolean;
357
+ }
358
+
359
+ export interface ColumnFilterSpec {
360
+ enabled?: boolean;
361
+ type?: FilterName | FilterCtor;
362
+ props?: Record<string, unknown>;
363
+ }
364
+
365
+ export interface ColumnLayoutSpec {
366
+ width?: number;
367
+ min?: number;
368
+ max?: number;
369
+ flex?: number;
370
+ pin?: 'start' | 'end' | null;
371
+ hidden?: boolean;
372
+ resizable?: boolean;
373
+ movable?: boolean;
374
+ lockVisible?: boolean;
375
+ lockPosition?: boolean | 'start' | 'end';
376
+ }
377
+
378
+ export interface ColumnHeaderSpec {
379
+ template?: string;
380
+ render?: string | RendererCtor;
381
+ props?: Record<string, unknown>;
382
+ class?: string | string[];
383
+ tooltip?: string;
384
+ align?: Align;
385
+ }
386
+
387
+ export interface ColumnExportSpec {
388
+ lookup?: 'label' | 'value' | 'columns';
389
+ csv?: boolean;
390
+ excel?: boolean;
391
+ }
392
+
393
+ export interface Column {
394
+ id?: string;
395
+ field?: string;
396
+ title?: string;
397
+ type?: TypeName | false;
398
+ preset?: string | string[];
399
+ format?: FormatSpec | string;
400
+ lookup?: LookupSpec;
401
+ value?: ColumnValueSpec;
402
+ cell?: ColumnCellSpec | string;
403
+ edit?: ColumnEditSpec | boolean | string;
404
+ sort?: ColumnSortSpec | boolean;
405
+ filter?: ColumnFilterSpec | boolean | FilterName;
406
+ group?: { enabled?: boolean; index?: number; explode?: boolean } | boolean;
407
+ pivot?: { enabled?: boolean; index?: number } | boolean;
408
+ total?: TotalName | TotalFn;
409
+ layout?: ColumnLayoutSpec | number;
410
+ header?: ColumnHeaderSpec | string;
411
+ export?: ColumnExportSpec;
412
+ allowGroup?: boolean;
413
+ allowPivot?: boolean;
414
+ allowTotal?: boolean;
415
+ nullable?: boolean;
416
+ }
417
+
418
+ export interface ColumnGroup {
419
+ id?: string;
420
+ title: string;
421
+ columns: (Column | ColumnGroup)[];
422
+ collapsible?: boolean;
423
+ openByDefault?: boolean;
424
+ showWhen?: 'open' | 'closed' | 'always';
425
+ marryChildren?: boolean;
426
+ header?: { render?: string | RendererCtor; props?: Record<string, unknown>; class?: string | string[] };
427
+ }
428
+
429
+ /** A column after presets, type defaults and grid defaults are folded in. */
430
+ export interface ResolvedColumn {
431
+ id: string;
432
+ field: string | null;
433
+ title: string;
434
+ type: TypeName;
435
+ dataType: DataType;
436
+ nullable: boolean;
437
+ align: Align;
438
+ value: Required<Pick<ColumnValueSpec, 'pure'>> & ColumnValueSpec;
439
+ cell: ColumnCellSpec;
440
+ edit: ColumnEditSpec;
441
+ sort: ColumnSortSpec;
442
+ filter: ColumnFilterSpec;
443
+ group: { enabled: boolean; index: number; explode: boolean };
444
+ pivot: { enabled: boolean; index: number };
445
+ total: TotalName | TotalFn | null;
446
+ layout: ColumnLayoutSpec;
447
+ header: ColumnHeaderSpec;
448
+ export: ColumnExportSpec;
449
+ lookup: LookupSpec | null;
450
+ allowGroup: boolean;
451
+ allowPivot: boolean;
452
+ allowTotal: boolean;
453
+ /** Compiled display-text producer. */
454
+ formatValue(value: unknown, row?: Row, data?: unknown): string;
455
+ /** Resolve the value for a row, through the computed-value graph. */
456
+ getValue(data: unknown, row?: Row): unknown;
457
+ def: Column;
458
+ }
459
+
460
+ // ---------------------------------------------------------------------------
461
+ // Filter wire format (spec 9.3)
462
+ // ---------------------------------------------------------------------------
463
+
464
+ export type Operator =
465
+ | 'eq' | 'ne'
466
+ | 'lt' | 'lte' | 'gt' | 'gte'
467
+ | 'between' | 'notBetween'
468
+ | 'in' | 'notIn'
469
+ | 'contains' | 'notContains' | 'startsWith' | 'endsWith' | 'matches'
470
+ | 'blank' | 'notBlank'
471
+ | 'containsAny' | 'containsAll' | 'containsNone';
472
+
473
+ export interface Condition {
474
+ col: string;
475
+ type?: TypeName;
476
+ op: Operator;
477
+ value?: unknown;
478
+ bounds?: '[]' | '[)' | '(]' | '()';
479
+ caseSensitive?: boolean;
480
+ meta?: Record<string, unknown>;
481
+ }
482
+
483
+ export interface FilterGroup {
484
+ op: 'and' | 'or' | 'not';
485
+ conditions: FilterSet[];
486
+ }
487
+
488
+ export type FilterSet = FilterGroup | Condition | null;
489
+
490
+ export interface SortEntry {
491
+ col: string;
492
+ dir: 'asc' | 'desc';
493
+ nullsFirst?: boolean;
494
+ }
495
+
496
+ // ---------------------------------------------------------------------------
497
+ // Sources (spec 4)
498
+ // ---------------------------------------------------------------------------
499
+
500
+ export interface ReloadOptions { keepExpanded?: boolean; keepSelection?: boolean }
501
+
502
+ export interface Source {
503
+ readonly mode: 'memory' | 'paged' | 'remote' | 'stream';
504
+ count(): number;
505
+ at(index: number): Row | undefined;
506
+ byKey(key: string): Row | undefined;
507
+ loaded(index: number): boolean;
508
+ hint(start: number, end: number): void;
509
+ apply(change: RowChange): ChangeResult;
510
+ reload(opts?: ReloadOptions): void;
511
+ destroy?(): void;
512
+ }
513
+
514
+ export interface MemorySourceConfig { mode: 'memory'; columnarBelow?: number }
515
+
516
+ export interface PagedSourceConfig {
517
+ mode: 'paged';
518
+ pageSize?: number;
519
+ maxCachedPages?: number;
520
+ fetch(req: {
521
+ range: { start: number; end: number };
522
+ sort: SortEntry[];
523
+ filters: FilterSet;
524
+ quick?: string;
525
+ context: unknown;
526
+ signal: AbortSignal;
527
+ }): Promise<{ rows: unknown[]; total?: number }>;
528
+ }
529
+
530
+ export interface RemoteRequest {
531
+ protocol: 1;
532
+ range: { start: number; end: number };
533
+ groupPath: string[];
534
+ groupBy: ColumnRef[];
535
+ totals: ColumnRef[];
536
+ pivotBy: ColumnRef[];
537
+ pivotMode: boolean;
538
+ filters: FilterSet;
539
+ quick?: string;
540
+ sort: SortEntry[];
541
+ context: unknown;
542
+ signal: AbortSignal;
543
+ }
544
+
545
+ export interface RemoteResult {
546
+ rows: unknown[];
547
+ count?: number;
548
+ pivotFields?: string[];
549
+ }
550
+
551
+ export interface RemoteSourceConfig {
552
+ mode: 'remote';
553
+ pageSize?: number;
554
+ maxCachedPages?: number;
555
+ fetch(req: RemoteRequest): Promise<RemoteResult>;
556
+ }
557
+
558
+ export interface Chunk {
559
+ rows: unknown[];
560
+ progress?: { loaded: number; estimated?: number };
561
+ done?: boolean;
562
+ }
563
+
564
+ export interface StreamSourceConfig {
565
+ mode: 'stream';
566
+ open(req: {
567
+ sort: SortEntry[];
568
+ filters: FilterSet;
569
+ quick?: string;
570
+ context: unknown;
571
+ signal: AbortSignal;
572
+ }): AsyncIterable<Chunk>;
573
+ promoteToMemoryBelow?: number;
574
+ coalesceMs?: number;
575
+ }
576
+
577
+ export type SourceConfig =
578
+ | MemorySourceConfig | PagedSourceConfig | RemoteSourceConfig | StreamSourceConfig;
579
+
580
+ // ---------------------------------------------------------------------------
581
+ // Grid configuration (spec 18.1)
582
+ // ---------------------------------------------------------------------------
583
+
584
+ export interface TreeConfig {
585
+ path?: (row: unknown) => string[];
586
+ parentKey?: string | ((row: unknown) => unknown);
587
+ orphans?: 'root' | string;
588
+ hasChildren?: (row: unknown) => boolean;
589
+ loadChildren?: (row: Row, signal: AbortSignal) => Promise<unknown[]>;
590
+ }
591
+
592
+ export interface DetailConfig {
593
+ enabled?: boolean;
594
+ render?: string | RendererCtor;
595
+ config?: GridConfig;
596
+ rows?: (row: Row) => unknown[] | Promise<unknown[]>;
597
+ height?: number | 'auto' | ((row: Row) => number);
598
+ cacheLimit?: number;
599
+ isMaster?: (row: unknown) => boolean;
600
+ }
601
+
602
+ export interface SelectionConfig {
603
+ mode?: 'none' | 'single' | 'multiple';
604
+ checkbox?: boolean;
605
+ headerCheckbox?: boolean;
606
+ groupSelectsChildren?: boolean;
607
+ groupSelectsFiltered?: boolean;
608
+ ranges?: boolean;
609
+ fillHandle?: boolean;
610
+ fill?: (p: { source: unknown[]; target: { row: Row; column: ResolvedColumn }[]; direction: string }) => unknown[];
611
+ }
612
+
613
+ export interface EditConfig {
614
+ enabled?: boolean;
615
+ mode?: 'cell' | 'row';
616
+ start?: 'single' | 'double' | 'key';
617
+ enterMovesDown?: boolean;
618
+ undoDepth?: number;
619
+ }
620
+
621
+ export interface PaginationConfig {
622
+ enabled?: boolean;
623
+ pageSize?: number;
624
+ pageSizes?: number[];
625
+ }
626
+
627
+ export interface GridConfig {
628
+ columns?: (Column | ColumnGroup)[];
629
+ columnGroups?: ColumnGroup[];
630
+ rows?: unknown[];
631
+ rowKey?: string | ((row: unknown) => string);
632
+ source?: SourceConfig;
633
+ columnDefaults?: Column;
634
+ columnPresets?: Record<string, Column>;
635
+ dataTypes?: Record<string, DataType>;
636
+ components?: Record<string, RendererCtor | EditorCtor | FilterCtor>;
637
+ pipes?: Record<string, (value: unknown, ...args: string[]) => string>;
638
+ totalFns?: Record<string, TotalFn>;
639
+ variants?: Record<string, VariantDefinition>;
640
+ tree?: TreeConfig;
641
+ detail?: DetailConfig;
642
+ selection?: SelectionConfig | 'single' | 'multiple' | 'none';
643
+ edit?: EditConfig | boolean;
644
+ pagination?: PaginationConfig | boolean;
645
+ locale?: string;
646
+ /**
647
+ * IANA zone every date column formats in, e.g. 'Europe/London' or 'UTC'.
648
+ * Omit to use each viewer's own zone. A column's own `format.timeZone` wins.
649
+ */
650
+ timeZone?: string;
651
+ theme?: Theme;
652
+ density?: Density;
653
+ rowHeight?: number | ((row: Row) => number);
654
+ headerHeight?: number;
655
+ overscan?: number;
656
+ autoHeight?: boolean | 'visible';
657
+ state?: GridState;
658
+ licence?: string;
659
+ maximise?: boolean;
660
+ allowUnsafeTemplates?: boolean;
661
+ hostFilter?: { active(): boolean; passes(row: Row): boolean };
662
+ context?: unknown;
663
+ workerThreshold?: number;
664
+ useWorker?: boolean;
665
+ workerUrl?: string;
666
+ sharedMemory?: boolean;
667
+ groupFooter?: boolean;
668
+ /**
669
+ * Where the grand total goes. `'bottom'` pins it below the rows; omitted
670
+ * leaves it inline with the data. Only the string is recognised — `true`
671
+ * does nothing.
672
+ */
673
+ grandTotalRow?: 'bottom';
674
+ totalFilteredOnly?: boolean;
675
+ totalOnlyChangedColumns?: boolean;
676
+ showTotalInHeader?: boolean;
677
+ columnVirtualisationAbove?: number;
678
+ statusBar?: boolean | { panels?: string[] };
679
+ /**
680
+ * The cell right-click menu. A function supplies custom items; `false`
681
+ * suppresses it entirely, which is what a read-only grid wants — the default
682
+ * menu offers Paste, Clear and Fill down.
683
+ */
684
+ contextMenu?: boolean | ((p: CellParams) => MenuItem[]);
685
+ /** The header's 3-dot menu. `false` suppresses it. Default true. */
686
+ columnMenu?: boolean;
687
+ /**
688
+ * Flash a cell when its value changes. `true` takes the defaults; an object
689
+ * names a colour, a duration in milliseconds, or both.
690
+ */
691
+ highlightOnChange?: boolean | string | {
692
+ colour?: string;
693
+ color?: string;
694
+ /** Milliseconds. `0` leaves the highlight until it is cleared. */
695
+ duration?: number;
696
+ enabled?: boolean;
697
+ };
698
+ /** A class, or classes, for every row. Re-evaluated on each repaint. */
699
+ rowClass?: string | string[] | ((p: RowStyleParams) => string | string[]);
700
+ /** Inline styles for every row. Camel-case or hyphenated property names. */
701
+ rowStyle?: CellStyle | ((p: RowStyleParams) => CellStyle);
702
+ toolPanel?: boolean | {
703
+ /** Built-in names: `columns`, `filters`, `views`, `quick`. */
704
+ panels?: string[];
705
+ openPanel?: string;
706
+ /** Which edge to dock against. `left` is the icon rail; default `right`. */
707
+ side?: 'left' | 'right';
708
+ /** Icon-only tabs. Defaults to true for `side: 'left'`, false otherwise. */
709
+ icons?: boolean;
710
+ /**
711
+ * Rail action buttons: `undo`, `redo`, `export`, `restore`. Defaults to all
712
+ * four on the left rail and none on the right; `false` drops them.
713
+ */
714
+ actions?: false | ('undo' | 'redo' | 'export' | 'restore')[];
715
+ /** File name for the export action, without the extension. */
716
+ exportName?: string;
717
+ };
718
+ quickFilterText?: string;
719
+ /**
720
+ * Per-column read/write/hidden policy (§8.1). A usability control, not a
721
+ * security boundary — hidden data is still resident in the store. Enforce the
722
+ * same policy server-side with `permittedColumns` / `permittedExport`.
723
+ */
724
+ permissions?: PermissionPolicy;
725
+ /** Prior state for diff and audit mode (§12). */
726
+ diff?: { snapshot?: unknown[] | Map<string, unknown>; strictNull?: boolean; addedColumns?: 'unchanged' | 'changed' };
727
+ /** Saved views (§15): a storage adapter and any pre-loaded views. */
728
+ views?: { storage?: { read(): unknown[]; write(views: unknown[]): void }; saved?: unknown[] };
729
+ /** The undo toolbar. `element` mounts it into the host's own chrome. */
730
+ historyBar?: boolean | { element?: HTMLElement; timeline?: boolean };
731
+ /**
732
+ * The AI skill layer. The grid makes no network call of its own: `ask` is the
733
+ * host's, and owns the model, the key and the privacy decision.
734
+ */
735
+ ai?: {
736
+ ask(p: { prompt: string; schema: unknown; context?: unknown }): Promise<unknown>;
737
+ schemaOptions?: object;
738
+ context?: unknown;
739
+ element?: HTMLElement;
740
+ placeholder?: string;
741
+ };
742
+ pivot?: { enabled?: boolean; groupTotals?: 'before' | 'after' | false; maxColumns?: number; separator?: string };
743
+ }
744
+
745
+ /**
746
+ * The four corners of read × write. `writeOnly` is a secret: the column is
747
+ * present and editable, its value never shown, exported, copied or searched.
748
+ */
749
+ export type PermissionLevel = 'hidden' | 'read' | 'writeOnly' | 'write';
750
+
751
+ export type PermissionPolicy =
752
+ | PermissionLevel
753
+ | Record<string, PermissionLevel>
754
+ | { field?: string; id?: string; permission: PermissionLevel }[]
755
+ | ((column: ResolvedColumn, params: { colId: string; context?: unknown; grid?: unknown }) => PermissionLevel | undefined)
756
+ | {
757
+ default?: PermissionLevel;
758
+ columns?: Record<string, PermissionLevel>;
759
+ resolve?(column: ResolvedColumn, params: { colId: string; context?: unknown }): PermissionLevel | undefined;
760
+ };
761
+
762
+ export interface MenuItem {
763
+ name?: string;
764
+ icon?: string;
765
+ shortcut?: string;
766
+ action?: () => void;
767
+ disabled?: boolean;
768
+ separator?: boolean;
769
+ children?: MenuItem[];
770
+ }
771
+
772
+ // ---------------------------------------------------------------------------
773
+ // State (spec 15)
774
+ // ---------------------------------------------------------------------------
775
+
776
+ export interface ColumnState {
777
+ id: string;
778
+ width?: number;
779
+ flex?: number;
780
+ hidden?: boolean;
781
+ pin?: 'start' | 'end' | null;
782
+ sort?: 'asc' | 'desc' | null;
783
+ sortIndex?: number | null;
784
+ groupIndex?: number | null;
785
+ pivotIndex?: number | null;
786
+ total?: TotalName | null;
787
+ }
788
+
789
+ export interface GridState {
790
+ version: number;
791
+ columns?: ColumnState[];
792
+ columnOrder?: string[];
793
+ filters?: FilterSet;
794
+ quick?: string;
795
+ sort?: SortEntry[];
796
+ group?: string[];
797
+ pivot?: { enabled: boolean; columns: string[] };
798
+ expanded?: string[];
799
+ selection?: string[];
800
+ scroll?: { top: number; left: number };
801
+ pagination?: { page: number; pageSize: number };
802
+ }
803
+
804
+ export interface StateApplyReport {
805
+ applied: string[];
806
+ skipped: { key: string; reason: string }[];
807
+ }
808
+
809
+ // ---------------------------------------------------------------------------
810
+ // Events (spec 18.4)
811
+ // ---------------------------------------------------------------------------
812
+
813
+ export type EventName =
814
+ | 'ready' | 'destroy' | 'render:first' | 'model:changed' | 'rows:changed' | 'rows:queued'
815
+ | 'cell:changed' | 'cell:clicked' | 'cell:dblclicked' | 'cell:contextmenu'
816
+ | 'cell:edit:start' | 'cell:edit:end' | 'row:edit:start' | 'row:edit:end'
817
+ | 'row:clicked' | 'row:dblclicked' | 'group:toggled'
818
+ | 'sort:changed' | 'filter:changed'
819
+ | 'column:moved' | 'column:resized' | 'column:visible' | 'column:pinned'
820
+ | 'column:grouped' | 'column:pivoted'
821
+ | 'selection:changed' | 'range:changed'
822
+ | 'page:changed' | 'scroll' | 'scroll:end' | 'size:changed'
823
+ | 'state:changed' | 'stream:chunk' | 'stream:end' | 'source:error'
824
+ | '*';
825
+
826
+ export interface GridEvent {
827
+ type: string;
828
+ origin: 'api' | 'user' | 'init';
829
+ grid: Grid;
830
+ [key: string]: unknown;
831
+ }
832
+
833
+ export type EventHandler = (e: GridEvent) => void;
834
+ export type Unsubscribe = () => void;
835
+
836
+ // ---------------------------------------------------------------------------
837
+ // Modules and licensing (spec 2, 3.3)
838
+ // ---------------------------------------------------------------------------
839
+
840
+ export interface GridModule {
841
+ name: string;
842
+ version?: string;
843
+ install(ctx: ModuleContext): void;
844
+ uninstall?(ctx: ModuleContext): void;
845
+ }
846
+
847
+ export interface ModuleContext {
848
+ registry: Registry;
849
+ grid?: Grid;
850
+ }
851
+
852
+ export interface Registry {
853
+ modules(): GridModule[];
854
+ has(name: string): boolean;
855
+ renderer(name: string): RendererCtor | RenderFn | undefined;
856
+ editor(name: string): EditorCtor | undefined;
857
+ filter(name: string): FilterCtor | undefined;
858
+ dataType(name: string): DataType | undefined;
859
+ totalFn(name: string): TotalFn | undefined;
860
+ pipe(name: string): ((v: unknown, ...a: string[]) => string) | undefined;
861
+ register(kind: string, name: string, impl: unknown): void;
862
+ }
863
+
864
+ export interface LicenceInfo {
865
+ valid: boolean;
866
+ product?: string;
867
+ issuedTo?: string;
868
+ expires?: string;
869
+ reason?: string;
870
+ }
871
+
872
+ // ---------------------------------------------------------------------------
873
+ // Export options (spec 14)
874
+ // ---------------------------------------------------------------------------
875
+
876
+ export interface CsvExportOptions {
877
+ delimiter?: string;
878
+ quote?: string;
879
+ lineEnding?: string;
880
+ headers?: boolean;
881
+ columns?: string[];
882
+ rows?: 'visible' | 'all' | 'selected';
883
+ fileName?: string;
884
+ processCell?: (p: CellParams) => string;
885
+ download?: boolean;
886
+ }
887
+
888
+ export interface ExcelExportOptions extends Omit<CsvExportOptions, 'delimiter' | 'quote' | 'lineEnding'> {
889
+ sheetName?: string;
890
+ freezePanes?: boolean;
891
+ variantFills?: boolean;
892
+ onProgress?: (p: { written: number; total: number }) => void;
893
+ }
894
+
895
+ export interface ClipboardOptions {
896
+ headers?: boolean;
897
+ rows?: 'visible' | 'all' | 'selected' | 'range';
898
+ }
899
+
900
+ // ---------------------------------------------------------------------------
901
+ // Grid API (spec 18.3)
902
+ // ---------------------------------------------------------------------------
903
+
904
+ export interface RowsApi {
905
+ /** Replace the data. Sort, filters, grouping and column layout are kept. */
906
+ load(rows: unknown[]): void;
907
+ apply(change: RowChange): ChangeResult;
908
+ queue(change: RowChange): Promise<ChangeResult>;
909
+ get(index: number): Row | undefined;
910
+ byKey(key: string): Row | undefined;
911
+ count(): number;
912
+ /** Rows in the source before filtering; under pagination, across every page. */
913
+ totalCount(): number;
914
+ data(): unknown[];
915
+ forEach(fn: (row: Row, index: number) => void): void;
916
+ value(key: string, colId: string): unknown;
917
+ text(key: string, colId: string): string;
918
+ values(key: string): Record<string, unknown>;
919
+ refresh(opts?: { rows?: string[]; columns?: string[]; force?: boolean }): void;
920
+ expand(key: string, deep?: boolean): void;
921
+ collapse(key: string): void;
922
+ expandAll(): void;
923
+ collapseAll(): void;
924
+ }
925
+
926
+ export interface ColumnsApi {
927
+ get(id: string): ResolvedColumn | undefined;
928
+ all(): ResolvedColumn[];
929
+ visible(): ResolvedColumn[];
930
+ state(): ColumnState[];
931
+ apply(state: ColumnState[]): void;
932
+ show(ids: string | string[]): void;
933
+ hide(ids: string | string[]): void;
934
+ move(id: string, to: number): void;
935
+ pin(id: string, side: 'start' | 'end' | null): void;
936
+ resize(id: string, px: number): void;
937
+ autoSize(ids?: string | string[]): void;
938
+ fit(): void;
939
+ group(ids: string | string[]): void;
940
+ pivot(ids: string | string[]): void;
941
+ totals(ids: string | string[]): void;
942
+ }
943
+
944
+ export interface SelectionApi {
945
+ rows(): Row[];
946
+ keys(): string[];
947
+ set(keys: string[]): void;
948
+ all(): void;
949
+ clear(): void;
950
+ cells(): { key: string; colId: string }[];
951
+ ranges(): CellRange[];
952
+ setRange(range: CellRange): void;
953
+ }
954
+
955
+ export interface CellRange {
956
+ startRow: number;
957
+ endRow: number;
958
+ columns: string[];
959
+ }
960
+
961
+ export interface FiltersApi {
962
+ get(): FilterSet;
963
+ set(filters: FilterSet): void;
964
+ clear(): void;
965
+ quick(text: string): void;
966
+ }
967
+
968
+ export interface SortApi {
969
+ get(): SortEntry[];
970
+ set(entries: SortEntry[]): void;
971
+ clear(): void;
972
+ }
973
+
974
+ export interface EditApi {
975
+ start(key: string, colId: string): void;
976
+ stop(cancel?: boolean): void;
977
+ undo(): void;
978
+ redo(): void;
979
+ }
980
+
981
+ export interface ScrollApi {
982
+ toRow(index: number, align?: 'start' | 'center' | 'end' | 'auto'): void;
983
+ toColumn(id: string): void;
984
+ position(): { top: number; left: number };
985
+ }
986
+
987
+ export interface ExportApi {
988
+ csv(opts?: CsvExportOptions): string | Promise<Blob>;
989
+ excel(opts?: ExcelExportOptions): Promise<Blob>;
990
+ clipboard(opts?: ClipboardOptions): Promise<void>;
991
+ print(): void;
992
+ }
993
+
994
+ export interface SavedView {
995
+ id: string;
996
+ name: string;
997
+ description: string;
998
+ shared: boolean;
999
+ isDefault: boolean;
1000
+ /** Supplied in `config.views.saved`: listed apart, and not renamable or deletable. */
1001
+ builtin: boolean;
1002
+ createdAt: number;
1003
+ updatedAt: number;
1004
+ /** A partial `GridState`; only the sections it names are applied. */
1005
+ state: GridState;
1006
+ }
1007
+
1008
+ export interface ViewStorage {
1009
+ /** Load the user's views. Called at construction and by `views.reload()`. */
1010
+ read(): SavedView[];
1011
+ /**
1012
+ * Mirror the views somewhere synchronous — `localStorage`, an in-memory
1013
+ * cache. For a server, listen for `view:saved` / `view:removed` and do the
1014
+ * write yourself: the grid does not make network calls and does not want to
1015
+ * know whether yours succeeded.
1016
+ */
1017
+ write(views: SavedView[], change: ViewChange): void;
1018
+ }
1019
+
1020
+ export interface ViewChange {
1021
+ reason: 'save' | 'update' | 'rename' | 'remove' | 'default' | 'import' | 'seed' | 'replace';
1022
+ /** The view the change concerns; null for a bulk replace. */
1023
+ view: SavedView | null;
1024
+ }
1025
+
1026
+ export interface RowStyleParams {
1027
+ row: Row;
1028
+ key: string;
1029
+ index: number;
1030
+ data: unknown;
1031
+ grid: Grid;
1032
+ context: unknown;
1033
+ }
1034
+
1035
+ export interface HighlightApi {
1036
+ /** Highlight a cell (`{key, colId}`), a row (`{key}`) or a column (`{colId}`). */
1037
+ (target: { key?: string; colId?: string } | string,
1038
+ opts?: { colour?: string; color?: string; duration?: number }): boolean;
1039
+ /** Clear one target, or every highlight when called with nothing. */
1040
+ clear(target?: { key?: string; colId?: string } | string): boolean;
1041
+ list(): { scope: string; key: string | null; colId: string | null; colour: string; duration: number }[];
1042
+ colourFor(key: string, colId: string): string | null;
1043
+ }
1044
+
1045
+ export interface StateApi {
1046
+ get(): GridState;
1047
+ apply(state: GridState, opts?: { skip?: (keyof GridState)[] }): StateApplyReport;
1048
+ /** The state the grid started in, captured once after `config.state`. */
1049
+ baseline(): GridState | null;
1050
+ /** Put the grid back the way it started, as one undoable step. */
1051
+ reset(): StateApplyReport | null;
1052
+ /** Whether anything has changed since construction. */
1053
+ modified(): boolean;
1054
+ }
1055
+
1056
+ export interface OverlayApi {
1057
+ show(kind: 'loading' | 'empty' | (string & {}), message?: string): void;
1058
+ hide(): void;
1059
+ }
1060
+
1061
+ export interface HistoryEntry {
1062
+ label: string;
1063
+ kind: string;
1064
+ [key: string]: unknown;
1065
+ }
1066
+
1067
+ export interface HistoryApi {
1068
+ undo(): HistoryEntry | null;
1069
+ redo(): HistoryEntry | null;
1070
+ canUndo(): boolean;
1071
+ canRedo(): boolean;
1072
+ /** What undo or redo would apply next, for labelling a button. */
1073
+ peek(direction?: 'undo' | 'redo'): HistoryEntry | null;
1074
+ list(): HistoryEntry[];
1075
+ /** Group everything `fn` does into one undoable step. */
1076
+ transaction(label: string, fn: () => void): HistoryEntry | null;
1077
+ clear(): void;
1078
+ }
1079
+
1080
+ export interface ViewsApi {
1081
+ list(): SavedView[];
1082
+ get(id: string): SavedView | undefined;
1083
+ readonly activeId: string | null;
1084
+ save(name: string, opts?: { id?: string; overwrite?: boolean }): SavedView;
1085
+ apply(id: string): SavedView | null;
1086
+ rename(id: string, name: string): SavedView | null;
1087
+ duplicate(id: string, name?: string): SavedView | null;
1088
+ remove(id: string): boolean;
1089
+ /** Mark the view applied on load; null clears it. */
1090
+ setDefault(id: string | null): SavedView | null;
1091
+ defaultView(): SavedView | null;
1092
+ /** What applying the view would change, without applying it. */
1093
+ diff(id: string): Record<string, unknown> | null;
1094
+ export(id: string): string;
1095
+ import(json: string): SavedView;
1096
+ /** Re-read from storage, after another tab or the server changed it. */
1097
+ reload(): void;
1098
+ }
1099
+
1100
+ export interface DiffApi {
1101
+ readonly enabled: boolean;
1102
+ /** Set the baseline every row is compared against. */
1103
+ setSnapshot(rows: unknown[] | null): void;
1104
+ clear(): void;
1105
+ summary(): { added: number; removed: number; changed: number; unchanged: number };
1106
+ statusOf(key: string): 'added' | 'removed' | 'changed' | 'unchanged';
1107
+ cellStatus(key: string, colId: string): 'changed' | 'unchanged';
1108
+ isChanged(key: string, colId?: string): boolean;
1109
+ changedColumns(key: string): string[];
1110
+ /** The value a cell held in the baseline. */
1111
+ before(key: string, colId: string): unknown;
1112
+ beforeRow(key: string): unknown;
1113
+ removedKeys(): string[];
1114
+ removedRows(): unknown[];
1115
+ report(): Record<string, unknown>;
1116
+ }
1117
+
1118
+ export type PermissionLevel = 'hidden' | 'read' | 'write' | 'writeOnly';
1119
+
1120
+ export interface PermissionsApi {
1121
+ levelOf(column: string | ResolvedColumn): PermissionLevel;
1122
+ isHidden(column: string | ResolvedColumn): boolean;
1123
+ isReadable(column: string | ResolvedColumn): boolean;
1124
+ isEditable(column: string | ResolvedColumn): boolean;
1125
+ /** True only at `writeOnly`: writable, never shown or exported. */
1126
+ isSecret(column: string | ResolvedColumn): boolean;
1127
+ isExportable(column: string | ResolvedColumn): boolean;
1128
+ levels(): Record<string, PermissionLevel>;
1129
+ /** Change the context permissions are evaluated against, and re-evaluate. */
1130
+ setContext(context: unknown): void;
1131
+ invalidate(): void;
1132
+ }
1133
+
1134
+ export interface AiApi {
1135
+ /** A machine-readable description of the grid, for a model's context. */
1136
+ schema(opts?: { maxColumns?: number; maxRows?: number }): Record<string, unknown>;
1137
+ /** The same schema as a tool definition. */
1138
+ tool(opts?: { maxColumns?: number; maxRows?: number }): Record<string, unknown>;
1139
+ prompt(text: string, opts?: Record<string, unknown>): string;
1140
+ buildPrompt(text: string, opts?: Record<string, unknown>): string;
1141
+ /** Parse what the model returned into a plan. */
1142
+ plan(reply: string | Record<string, unknown>, opts?: Record<string, unknown>): Record<string, unknown>;
1143
+ /** Run a plan as one undoable step. */
1144
+ apply(plan: Record<string, unknown>): Record<string, unknown>;
1145
+ }
1146
+
1147
+ export interface LicenceApi {
1148
+ set(key: string): LicenceInfo;
1149
+ info(): LicenceInfo;
1150
+ state(): 'licensed' | 'localhost' | 'trial';
1151
+ watermark(): boolean;
1152
+ /** Settles when the licence check finishes. */
1153
+ readonly ready: Promise<LicenceInfo>;
1154
+ }
1155
+
1156
+ export interface PaginationApi {
1157
+ get(): { page: number; pageSize: number; total: number; pageCount: number };
1158
+ set(next: { page?: number; pageSize?: number }): void;
1159
+ applyPage(next: { page?: number; pageSize?: number }): void;
1160
+ }
1161
+
1162
+ /**
1163
+ * Fills the browser window with the grid and puts it back. Present on grids
1164
+ * created with `createGrid` unless `maximise: false`; never on a headless grid,
1165
+ * which has no window to fill.
1166
+ */
1167
+ export interface MaximiseApi {
1168
+ enter(): boolean;
1169
+ exit(): boolean;
1170
+ toggle(): boolean;
1171
+ active(): boolean;
1172
+ }
1173
+
1174
+ export interface Grid {
1175
+ readonly rows: RowsApi;
1176
+ readonly columns: ColumnsApi;
1177
+ readonly selection: SelectionApi;
1178
+ readonly filters: FiltersApi;
1179
+ readonly sort: SortApi;
1180
+ readonly edit: EditApi;
1181
+ readonly scroll: ScrollApi;
1182
+ readonly export: ExportApi;
1183
+ readonly state: StateApi;
1184
+ readonly overlay: OverlayApi;
1185
+ readonly history: HistoryApi;
1186
+ readonly views: ViewsApi;
1187
+ readonly diff: DiffApi;
1188
+ readonly permissions: PermissionsApi;
1189
+ readonly ai: AiApi;
1190
+ readonly licence: LicenceApi;
1191
+ readonly pagination: PaginationApi;
1192
+ readonly highlight: HighlightApi;
1193
+ readonly maximise?: MaximiseApi;
1194
+ readonly element: HTMLElement | null;
1195
+ readonly destroyed: boolean;
1196
+ /** False until the first render has been laid out. */
1197
+ readonly ready: boolean;
1198
+
1199
+ /** The resolved configuration, as one object. */
1200
+ config(): GridConfig;
1201
+ get<K extends keyof GridConfig>(key: K): GridConfig[K];
1202
+ set<K extends keyof GridConfig>(key: K, value: GridConfig[K]): void;
1203
+ setAll(values: Partial<GridConfig>): void;
1204
+
1205
+ on(event: EventName, handler: EventHandler): Unsubscribe;
1206
+ once(event: EventName, handler: EventHandler): Unsubscribe;
1207
+ off(event: EventName, handler: EventHandler): void;
1208
+ emit(event: string, payload?: Record<string, unknown>): void;
1209
+
1210
+ getVersion(): string;
1211
+ destroy(): void;
1212
+ }
1213
+
1214
+ // ---------------------------------------------------------------------------
1215
+ // Entry points
1216
+ // ---------------------------------------------------------------------------
1217
+
1218
+ export function createGrid(element: HTMLElement, config?: GridConfig): Grid;
1219
+ export function createHeadlessGrid(config?: GridConfig): Grid;
1220
+ export function registerModules(modules: GridModule[], opts?: { licence?: string }): void;
1221
+ export function setLicence(licence: string): LicenceInfo;
1222
+ export function version(): string;
1223
+
1224
+ export const LatticeGrid: {
1225
+ createGrid: typeof createGrid;
1226
+ createHeadlessGrid: typeof createHeadlessGrid;
1227
+ registerModules: typeof registerModules;
1228
+ setLicence: typeof setLicence;
1229
+ version: typeof version;
1230
+ };
1231
+
1232
+ export default LatticeGrid;