@freegridjs/core 0.8.0 → 1.0.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.
@@ -1,3 +1,37 @@
1
+ /** A cell value, optionally with an Excel number format and text styles. Colors are ARGB hex like 'FFDC2626'. */
2
+ type XlsxValue = string | number | boolean | Date | null | undefined;
3
+ interface XlsxStyle {
4
+ fmt?: string;
5
+ bold?: boolean;
6
+ align?: 'left' | 'center' | 'right';
7
+ color?: string;
8
+ fill?: string;
9
+ /** Header look: bold on a light gray fill. */
10
+ header?: boolean;
11
+ }
12
+ type XlsxCell = XlsxValue | ({
13
+ v: XlsxValue;
14
+ } & XlsxStyle);
15
+ interface XlsxSheet {
16
+ name?: string;
17
+ rows: XlsxCell[][];
18
+ /** Column widths in characters. */
19
+ widths?: number[];
20
+ /** Ranges like "A1:C1". */
21
+ merges?: string[];
22
+ /** Rows frozen at the top (also the AutoFilter row when `autoFilter` is set). */
23
+ freezeRows?: number;
24
+ autoFilter?: boolean;
25
+ }
26
+ /** Build an .xlsx workbook (stored zip) from rows of values. */
27
+ declare function writeXlsx(sheets: XlsxSheet[]): Uint8Array;
28
+ interface ReadSheet {
29
+ name: string;
30
+ rows: XlsxValue[][];
31
+ }
32
+ /** Read every sheet of an .xlsx file. Dates come back as Date, numbers as number, booleans as boolean. */
33
+ declare function readXlsx(input: ArrayBuffer | Uint8Array): Promise<ReadSheet[]>;
34
+
1
35
  type Row = Record<string, any>;
2
36
  type Region = 'left' | 'center' | 'right';
3
37
  type ColumnType = 'text' | 'number' | 'date' | 'boolean';
@@ -30,7 +64,23 @@ interface SetFilterModel {
30
64
  type: 'set';
31
65
  values: unknown[];
32
66
  }
33
- type FilterModel = TextFilterModel | NumberFilterModel | DateFilterModel | SetFilterModel;
67
+ /** Two or more conditions on the same column, joined with and / or. */
68
+ interface CombinedFilterModel {
69
+ type: 'combined';
70
+ operator: 'and' | 'or';
71
+ conditions: FilterModel[];
72
+ }
73
+ type FilterModel = TextFilterModel | NumberFilterModel | DateFilterModel | SetFilterModel | CombinedFilterModel;
74
+ /** A condition on one column inside an advanced filter. */
75
+ interface AdvancedFilterCondition {
76
+ colId: string;
77
+ model: FilterModel;
78
+ }
79
+ /** Conditions across columns, nested as deep as needed: (a AND b) OR c. */
80
+ interface AdvancedFilter {
81
+ operator: 'and' | 'or';
82
+ conditions: Array<AdvancedFilterCondition | AdvancedFilter>;
83
+ }
34
84
  interface SortItem {
35
85
  colId: string;
36
86
  dir: SortDir;
@@ -111,6 +161,19 @@ interface ColumnDef {
111
161
  header: string;
112
162
  column: ColumnDef;
113
163
  }) => string | HTMLElement;
164
+ /** Text shown when hovering the header. */
165
+ headerTooltip?: string;
166
+ /** Hover text for cells: true shows the value; a function returns the text (or null for none). */
167
+ tooltip?: boolean | ((params: CellParams) => string | null | undefined);
168
+ /** The cell value is an array of numbers drawn as a small chart: true = line, or { type: 'line' | 'bar' | 'area', color? }. */
169
+ sparkline?: boolean | {
170
+ type?: 'line' | 'bar' | 'area';
171
+ color?: string;
172
+ };
173
+ /** Column groups: start opened (see columnGroupShow). */
174
+ openByDefault?: boolean;
175
+ /** Inside a group: show this column only while the group is 'open' or only while it is 'closed'. The group header gets a toggle. */
176
+ columnGroupShow?: 'open' | 'closed';
114
177
  /** Extra class names on the header cell (also for column groups). */
115
178
  headerClass?: string | ((column: ColumnDef) => string | undefined);
116
179
  /** Aggregate shown in group rows: 'sum' | 'avg' | 'min' | 'max' | 'count' | (values, rows) => value. */
@@ -123,6 +186,42 @@ interface InvalidCell {
123
186
  colId: string;
124
187
  message: string;
125
188
  }
189
+ /** Everything a person can change in the grid, as plain JSON (save it per user, restore it later). */
190
+ interface SavedGridState {
191
+ columns?: ColumnState[];
192
+ sort?: SortItem[];
193
+ filters?: Record<string, FilterModel>;
194
+ quickFilter?: string;
195
+ groupBy?: string[];
196
+ pivot?: PivotConfig | null;
197
+ advancedFilter?: AdvancedFilter | null;
198
+ /** Opened (true) or closed column groups, by group id. */
199
+ columnGroups?: Record<string, boolean>;
200
+ /** Expanded or collapsed groups and tree rows, by key. */
201
+ expanded?: Record<string, boolean>;
202
+ page?: number;
203
+ pageSize?: number;
204
+ /** Selected row ids (needs getRowId to survive reloads). */
205
+ selected?: string[];
206
+ }
207
+ type SavedStatePart = keyof SavedGridState;
208
+ /** Row changes from outside (a server push, a websocket): matched by getRowId, not undoable, not tracked as edits. */
209
+ interface RowTransaction {
210
+ add?: Row[];
211
+ /** Where to insert added rows in the source data (default: the end). */
212
+ addIndex?: number;
213
+ /** Rows with the id of an existing row; their fields are copied onto it. */
214
+ update?: Row[];
215
+ /** Rows (or objects with the id fields) to take out. */
216
+ remove?: Row[];
217
+ }
218
+ interface TransactionResult {
219
+ added: Row[];
220
+ updated: Row[];
221
+ removed: Row[];
222
+ /** Update or remove entries whose id matched no row. */
223
+ notFound: Row[];
224
+ }
126
225
  interface ScrollPosition {
127
226
  top: number;
128
227
  left: number;
@@ -175,7 +274,7 @@ type EditorSpec = {
175
274
  | {
176
275
  type: 'datetime';
177
276
  } | ((params: EditorParams) => CustomEditor);
178
- type KeyAction = 'edit' | 'clear' | 'undo' | 'redo' | 'copy' | 'paste' | 'selectAll' | 'find' | 'none';
277
+ type KeyAction = 'edit' | 'clear' | 'undo' | 'redo' | 'copy' | 'cut' | 'paste' | 'selectAll' | 'find' | 'none';
179
278
  interface ColumnState {
180
279
  colId: string;
181
280
  width: number;
@@ -210,10 +309,15 @@ interface Messages {
210
309
  close: string;
211
310
  copy: string;
212
311
  copyWithHeaders: string;
312
+ cut: string;
213
313
  paste: string;
214
314
  pasteHint: string;
215
315
  required: string;
216
316
  invalidValue: string;
317
+ and: string;
318
+ or: string;
319
+ advancedFilter: string;
320
+ addCondition: string;
217
321
  duplicate: string;
218
322
  undo: string;
219
323
  redo: string;
@@ -258,6 +362,9 @@ interface Messages {
258
362
  addColumn: string;
259
363
  chartBar: string;
260
364
  chartStacked: string;
365
+ chartDonut: string;
366
+ chartCombo: string;
367
+ chartScatter: string;
261
368
  chartLine: string;
262
369
  chartArea: string;
263
370
  chartPie: string;
@@ -322,6 +429,15 @@ interface ServerParams {
322
429
  sort: SortItem[];
323
430
  filters: Record<string, FilterModel>;
324
431
  quickFilter: string;
432
+ /** setAdvancedFilter, when set. */
433
+ advancedFilter?: AdvancedFilter | null;
434
+ /**
435
+ * Server-side grouping (groupBy with a datasource): the grouped columns, and the values of the open
436
+ * groups above this request. While groupKeys.length < groupBy.length, answer one row per group of
437
+ * groupBy[groupKeys.length], e.g. { status: 'new', count: 12, qty: 340 } (count and aggregates by column id).
438
+ */
439
+ groupBy?: string[];
440
+ groupKeys?: unknown[];
325
441
  }
326
442
  interface Datasource {
327
443
  /** Return the rows of the range; `total` is the row count when known (omit it for infinite scroll). */
@@ -357,7 +473,7 @@ interface PivotConfig {
357
473
  totals?: boolean;
358
474
  }
359
475
  interface ChartOptions {
360
- type?: 'bar' | 'stackedBar' | 'line' | 'area' | 'pie';
476
+ type?: 'bar' | 'stackedBar' | 'line' | 'area' | 'pie' | 'donut' | 'combo' | 'scatter';
361
477
  /** Cells to chart; default: the current range, else every displayed row. */
362
478
  range?: GridRange;
363
479
  /** Draw into this element instead of a floating panel inside the grid. */
@@ -367,7 +483,7 @@ interface ChartOptions {
367
483
  interface ChartHandle {
368
484
  /** Element the SVG is drawn in. */
369
485
  el: HTMLElement;
370
- setType(type: 'bar' | 'stackedBar' | 'line' | 'area' | 'pie'): void;
486
+ setType(type: 'bar' | 'stackedBar' | 'line' | 'area' | 'pie' | 'donut' | 'combo' | 'scatter'): void;
371
487
  update(): void;
372
488
  destroy(): void;
373
489
  }
@@ -433,6 +549,35 @@ interface GridOptions {
433
549
  detailHeight?: number;
434
550
  /** Which rows can expand a detail panel (default: all rows). */
435
551
  isRowMaster?: (row: Row) => boolean;
552
+ /** 'row': editing a row keeps it open across its cells (Tab stays in the row); Enter or leaving the row saves it, Escape puts the whole row back. */
553
+ editType?: 'cell' | 'row';
554
+ /** Briefly highlight cells whose value changed through applyTransaction (default true). */
555
+ flashCells?: boolean;
556
+ /** Row spacing: 'compact', 'normal' (default) or 'comfortable'. Fixed rowHeight / headerHeight win. */
557
+ density?: 'compact' | 'normal' | 'comfortable';
558
+ /** Shown when there are no rows: text, or a function returning text or an element (filtered: the filters hide every row). */
559
+ noRowsOverlay?: string | ((params: {
560
+ filtered: boolean;
561
+ }) => string | HTMLElement);
562
+ /** Shown while server rows load. */
563
+ loadingOverlay?: string | ((params: {
564
+ filtered: boolean;
565
+ }) => string | HTMLElement);
566
+ /** The grid grows with its rows instead of scrolling inside (no height needed on the container). Best for up to a few hundred rows. */
567
+ autoHeight?: boolean;
568
+ /** Height in px for this row; return nothing for the default rowHeight. */
569
+ getRowHeight?: (row: Row) => number | null | undefined;
570
+ /** false hides "Advanced filter…" in the right-click menu (setAdvancedFilter still works). */
571
+ advancedFilter?: boolean;
572
+ /** Show the full text of cells that are cut off when hovered (default true). */
573
+ overflowTooltip?: boolean;
574
+ /** Boxes under the header that filter as you type: text contains; numbers >10, <=5, 10~20; dates >2026-01-01; a list for set columns. */
575
+ filterRow?: boolean;
576
+ /** A pinned column numbering the data rows 1, 2, 3… (continues across pages). Click a number to select the row. */
577
+ rowNumbers?: boolean | {
578
+ width?: number;
579
+ header?: string;
580
+ };
436
581
  /** Add a handle column for dragging rows into a new order (and between grids with the same `group`). */
437
582
  rowDrag?: boolean | RowDragOptions;
438
583
  /** Show rows as cards (header: value lines) when the grid is narrower than this many px; true = 640. */
@@ -443,6 +588,8 @@ interface GridOptions {
443
588
  autoRowHeight?: boolean;
444
589
  /** Rows that may be checked; others show a disabled checkbox and are skipped by select-all. */
445
590
  isRowSelectable?: (row: Row) => boolean;
591
+ /** Tree data: checking a parent row also checks (or unchecks) all of its children. Group rows always do. */
592
+ groupSelectsChildren?: boolean;
446
593
  /** Show the select-all checkbox in the header (default true). */
447
594
  headerCheckbox?: boolean;
448
595
  /** Show rows one page at a time with a pager under the grid. */
@@ -551,6 +698,32 @@ interface GridEvents {
551
698
  };
552
699
  /** The rows area scrolled (also from setScrollPosition). */
553
700
  scroll: ScrollPosition;
701
+ /** editType 'row': a row started or finished editing; `changes` lists the cells that differ from before. */
702
+ rowEditStart: {
703
+ row: Row;
704
+ rowIndex: number;
705
+ };
706
+ rowEditStop: {
707
+ row: Row;
708
+ rowIndex: number;
709
+ committed: boolean;
710
+ changes: {
711
+ colId: string;
712
+ oldValue: unknown;
713
+ newValue: unknown;
714
+ }[];
715
+ };
716
+ /** setAdvancedFilter or the filter builder changed the advanced filter. */
717
+ advancedFilterChange: {
718
+ advancedFilter: AdvancedFilter | null;
719
+ };
720
+ /** A collapsible column group was opened or closed. */
721
+ columnGroupOpened: {
722
+ groupId: string;
723
+ open: boolean;
724
+ };
725
+ /** applyTransaction (or a batch of applyTransactionAsync) finished. */
726
+ transactionApplied: TransactionResult;
554
727
  /** A row was dropped on this grid (also from another grid of the same drag group). */
555
728
  rowDrop: RowDropParams & {
556
729
  fromGrid: GridApi | null;
@@ -620,7 +793,10 @@ interface GridApi {
620
793
  getData(): Row[];
621
794
  setColumns(columns: ColumnDef[]): void;
622
795
  getColumnState(): ColumnState[];
623
- applyColumnState(state: ColumnState[]): void;
796
+ /** Entries may be partial: only the fields given change. */
797
+ applyColumnState(state: (Partial<ColumnState> & {
798
+ colId: string;
799
+ })[]): void;
624
800
  setSort(sort: SortItem[]): void;
625
801
  getSort(): SortItem[];
626
802
  setFilter(colId: string, model: FilterModel | null): void;
@@ -631,6 +807,38 @@ interface GridApi {
631
807
  deselectAll(): void;
632
808
  getDisplayedRowCount(): number;
633
809
  scrollToRow(index: number): void;
810
+ /** The grid's current view (columns, sort, filters, grouping, page, selection…) as plain JSON. */
811
+ getState(): SavedGridState;
812
+ /** Restore a saved view; `parts` limits what is applied. Unknown columns are skipped. */
813
+ setState(state: SavedGridState, options?: {
814
+ parts?: SavedStatePart[];
815
+ }): void;
816
+ /** Add, update and remove rows by id in one go (for live data). Changed cells flash unless flashCells is false. */
817
+ applyTransaction(tx: RowTransaction): TransactionResult;
818
+ /** Queue a transaction; queued ones are merged and applied together about every 50 ms. */
819
+ applyTransactionAsync(tx: RowTransaction): void;
820
+ /** Conditions across columns, applied together with the column filters; null clears it. */
821
+ setAdvancedFilter(filter: AdvancedFilter | null): void;
822
+ getAdvancedFilter(): AdvancedFilter | null;
823
+ /** Dialog for building an advanced filter. */
824
+ openFilterBuilder(): void;
825
+ /** Open or close a column group that has columnGroupShow children. */
826
+ setColumnGroupOpened(groupId: string, open: boolean): void;
827
+ isColumnGroupOpened(groupId: string): boolean;
828
+ /** One worksheet of the rows, for buildWorkbook / exportWorkbook. */
829
+ getXlsxSheet(options?: ExportOptions): XlsxSheet;
830
+ setDensity(density: 'compact' | 'normal' | 'comfortable'): void;
831
+ getDensity(): 'compact' | 'normal' | 'comfortable';
832
+ /** Show the 'loading' or 'noRows' overlay yourself (for example while your own request runs); null goes back to automatic. */
833
+ showOverlay(kind: 'loading' | 'noRows' | null): void;
834
+ /** Print the rows as a table (current sort and filters; same options as the exports, plus a title). */
835
+ print(options?: ExportOptions & {
836
+ title?: string;
837
+ }): void;
838
+ /** The HTML page print() would print. */
839
+ getPrintHtml(options?: ExportOptions & {
840
+ title?: string;
841
+ }): string;
634
842
  /** Check every editable cell against required, unique and validate. Empty when all rows are valid. */
635
843
  validate(): InvalidCell[];
636
844
  /** Scroll offsets of the rows area in px. */
@@ -664,6 +872,10 @@ interface GridApi {
664
872
  headers?: boolean;
665
873
  rows?: boolean;
666
874
  }): string;
875
+ /** Copy the range like copySelection, then clear its editable cells (one undo step). */
876
+ cutSelection(): string;
877
+ /** editType 'row': finish the row being edited (cancel puts it back). */
878
+ stopRowEdit(cancel?: boolean): void;
667
879
  /** Paste Excel/TSV text at the range or focused cell into editable columns. */
668
880
  pasteText(text: string): {
669
881
  changed: number;
@@ -746,4 +958,4 @@ interface GridApi {
746
958
  destroy(): void;
747
959
  }
748
960
 
749
- export type { Aggregator as A, SortDir as B, CellEvent as C, Datasource as D, EditorParams as E, FilterModel as F, GridOptions as G, SortItem as H, InvalidCell as I, SpanParams as J, KeyAction as K, LocalePack as L, Messages as M, NumberFilterModel as N, SummaryCell as O, PivotConfig as P, SummaryOptions as Q, Region as R, ScrollPosition as S, SummaryRowDef as T, TextFilterModel as U, TextOp as V, GridApi as a, CellParams as b, ChartHandle as c, ChartOptions as d, ColumnDef as e, ColumnState as f, ColumnType as g, ContextMenuItem as h, ContextMenuParams as i, CustomEditor as j, DateFilterModel as k, DateOp as l, EditorSpec as m, ExportOptions as n, FilterOp as o, FilterType as p, GridEvents as q, GridRange as r, NumberOp as s, Row as t, RowDragOptions as u, RowDropParams as v, RowDropPosition as w, SelectOption as x, ServerParams as y, SetFilterModel as z };
961
+ export { type TextOp as $, type AdvancedFilter as A, type RowTransaction as B, type CellEvent as C, type Datasource as D, type ExportOptions as E, type FilterModel as F, type GridOptions as G, type SavedStatePart as H, type InvalidCell as I, type ScrollPosition as J, type KeyAction as K, type LocalePack as L, type Messages as M, type NumberFilterModel as N, type SelectOption as O, type PivotConfig as P, type ServerParams as Q, type Row as R, type SavedGridState as S, type SetFilterModel as T, type SortDir as U, type SortItem as V, type SpanParams as W, type SummaryCell as X, type SummaryOptions as Y, type SummaryRowDef as Z, type TextFilterModel as _, type GridApi as a, type TransactionResult as a0, type XlsxCell as a1, type XlsxSheet as a2, readXlsx as a3, writeXlsx as a4, type AdvancedFilterCondition as b, type Aggregator as c, type CellParams as d, type ChartHandle as e, type ChartOptions as f, type ColumnDef as g, type ColumnState as h, type ColumnType as i, type CombinedFilterModel as j, type ContextMenuItem as k, type ContextMenuParams as l, type CustomEditor as m, type DateFilterModel as n, type DateOp as o, type EditorParams as p, type EditorSpec as q, type FilterOp as r, type FilterType as s, type GridEvents as t, type GridRange as u, type NumberOp as v, type Region as w, type RowDragOptions as x, type RowDropParams as y, type RowDropPosition as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@freegridjs/core",
3
- "version": "0.8.0",
3
+ "version": "1.0.0",
4
4
  "description": "FreeGrid — a fast data grid for the web (free for personal use): virtual scrolling, grouping, pivot, charts, Excel export, 7 languages.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",