@freegridjs/core 0.7.0 → 0.8.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,4 +1,4 @@
1
- import { L as LocalePack } from '../types-DZ66BpLd.js';
1
+ import { L as LocalePack } from '../types-e45suTSB.js';
2
2
 
3
3
  declare const de: LocalePack;
4
4
 
@@ -32,6 +32,7 @@ var de = {
32
32
  pasteHint: "Der Browser hat die Zwischenablage blockiert. Dr\xFCcken Sie Ctrl+V zum Einf\xFCgen.",
33
33
  required: "Dieses Feld ist erforderlich",
34
34
  invalidValue: "Ung\xFCltiger Wert",
35
+ duplicate: "Dieser Wert wird bereits verwendet",
35
36
  undo: "R\xFCckg\xE4ngig",
36
37
  redo: "Wiederholen",
37
38
  deleteRows: "Ausgew\xE4hlte Zeilen l\xF6schen",
@@ -78,6 +79,7 @@ var de = {
78
79
  chartLine: "Liniendiagramm",
79
80
  chartArea: "Fl\xE4chendiagramm",
80
81
  chartPie: "Kreisdiagramm",
82
+ freeBadge: "Kostenlose Version",
81
83
  ops: {
82
84
  contains: "Enth\xE4lt",
83
85
  equals: "Gleich",
@@ -1,4 +1,4 @@
1
- import { L as LocalePack } from '../types-DZ66BpLd.js';
1
+ import { L as LocalePack } from '../types-e45suTSB.js';
2
2
 
3
3
  declare const en: LocalePack;
4
4
 
@@ -32,6 +32,7 @@ var en = {
32
32
  pasteHint: "Clipboard access was blocked. Press Ctrl+V to paste.",
33
33
  required: "This field is required",
34
34
  invalidValue: "Invalid value",
35
+ duplicate: "This value is already used",
35
36
  undo: "Undo",
36
37
  redo: "Redo",
37
38
  deleteRows: "Delete selected rows",
@@ -78,6 +79,7 @@ var en = {
78
79
  chartLine: "Line chart",
79
80
  chartArea: "Area chart",
80
81
  chartPie: "Pie chart",
82
+ freeBadge: "Free version",
81
83
  ops: {
82
84
  contains: "Contains",
83
85
  equals: "Equals",
@@ -1,4 +1,4 @@
1
- import { L as LocalePack } from '../types-DZ66BpLd.js';
1
+ import { L as LocalePack } from '../types-e45suTSB.js';
2
2
 
3
3
  declare const es: LocalePack;
4
4
 
@@ -32,6 +32,7 @@ var es = {
32
32
  pasteHint: "El navegador bloque\xF3 el portapapeles. Pulsa Ctrl+V para pegar.",
33
33
  required: "Este campo es obligatorio",
34
34
  invalidValue: "Valor no v\xE1lido",
35
+ duplicate: "Este valor ya est\xE1 en uso",
35
36
  undo: "Deshacer",
36
37
  redo: "Rehacer",
37
38
  deleteRows: "Eliminar filas seleccionadas",
@@ -78,6 +79,7 @@ var es = {
78
79
  chartLine: "Gr\xE1fico de l\xEDneas",
79
80
  chartArea: "Gr\xE1fico de \xE1reas",
80
81
  chartPie: "Gr\xE1fico circular",
82
+ freeBadge: "Versi\xF3n gratuita",
81
83
  ops: {
82
84
  contains: "Contiene",
83
85
  equals: "Igual a",
@@ -1,4 +1,4 @@
1
- import { L as LocalePack } from '../types-DZ66BpLd.js';
1
+ import { L as LocalePack } from '../types-e45suTSB.js';
2
2
 
3
3
  declare const fr: LocalePack;
4
4
 
@@ -32,6 +32,7 @@ var fr = {
32
32
  pasteHint: "Le navigateur a bloqu\xE9 le presse-papiers. Appuyez sur Ctrl+V pour coller.",
33
33
  required: "Ce champ est obligatoire",
34
34
  invalidValue: "Valeur non valide",
35
+ duplicate: "Cette valeur est d\xE9j\xE0 utilis\xE9e",
35
36
  undo: "Annuler",
36
37
  redo: "R\xE9tablir",
37
38
  deleteRows: "Supprimer les lignes s\xE9lectionn\xE9es",
@@ -78,6 +79,7 @@ var fr = {
78
79
  chartLine: "Courbes",
79
80
  chartArea: "Aires",
80
81
  chartPie: "Secteurs",
82
+ freeBadge: "Version gratuite",
81
83
  ops: {
82
84
  contains: "Contient",
83
85
  equals: "\xC9gal \xE0",
@@ -1,4 +1,4 @@
1
- import { L as LocalePack } from '../types-DZ66BpLd.js';
1
+ import { L as LocalePack } from '../types-e45suTSB.js';
2
2
 
3
3
  declare const ja: LocalePack;
4
4
 
@@ -32,6 +32,7 @@ var ja = {
32
32
  pasteHint: "\u30D6\u30E9\u30A6\u30B6\u30FC\u304C\u30AF\u30EA\u30C3\u30D7\u30DC\u30FC\u30C9\u3078\u306E\u30A2\u30AF\u30BB\u30B9\u3092\u30D6\u30ED\u30C3\u30AF\u3057\u307E\u3057\u305F\u3002Ctrl+V \u3067\u8CBC\u308A\u4ED8\u3051\u3066\u304F\u3060\u3055\u3044\u3002",
33
33
  required: "\u3053\u306E\u9805\u76EE\u306F\u5FC5\u9808\u3067\u3059",
34
34
  invalidValue: "\u7121\u52B9\u306A\u5024\u3067\u3059",
35
+ duplicate: "\u3053\u306E\u5024\u306F\u3059\u3067\u306B\u4F7F\u308F\u308C\u3066\u3044\u307E\u3059",
35
36
  undo: "\u5143\u306B\u623B\u3059",
36
37
  redo: "\u3084\u308A\u76F4\u3057",
37
38
  deleteRows: "\u9078\u629E\u3057\u305F\u884C\u3092\u524A\u9664",
@@ -78,6 +79,7 @@ var ja = {
78
79
  chartLine: "\u6298\u308C\u7DDA\u30B0\u30E9\u30D5",
79
80
  chartArea: "\u9762\u30B0\u30E9\u30D5",
80
81
  chartPie: "\u5186\u30B0\u30E9\u30D5",
82
+ freeBadge: "\u7121\u6599\u7248\u3092\u4F7F\u7528\u4E2D",
81
83
  ops: {
82
84
  contains: "\u542B\u3080",
83
85
  equals: "\u7B49\u3057\u3044",
@@ -1,4 +1,4 @@
1
- import { L as LocalePack } from '../types-DZ66BpLd.js';
1
+ import { L as LocalePack } from '../types-e45suTSB.js';
2
2
 
3
3
  declare const ko: LocalePack;
4
4
 
@@ -32,6 +32,7 @@ var ko = {
32
32
  pasteHint: "\uBE0C\uB77C\uC6B0\uC800\uAC00 \uD074\uB9BD\uBCF4\uB4DC \uC811\uADFC\uC744 \uB9C9\uC558\uC2B5\uB2C8\uB2E4. Ctrl+V\uB85C \uBD99\uC5EC\uB123\uC73C\uC138\uC694.",
33
33
  required: "\uD544\uC218 \uC785\uB825 \uD56D\uBAA9\uC785\uB2C8\uB2E4",
34
34
  invalidValue: "\uC62C\uBC14\uB978 \uAC12\uC774 \uC544\uB2D9\uB2C8\uB2E4",
35
+ duplicate: "\uC774\uBBF8 \uC0AC\uC6A9 \uC911\uC778 \uAC12\uC785\uB2C8\uB2E4",
35
36
  undo: "\uC2E4\uD589 \uCDE8\uC18C",
36
37
  redo: "\uB2E4\uC2DC \uC2E4\uD589",
37
38
  deleteRows: "\uC120\uD0DD\uD55C \uD589 \uC0AD\uC81C",
@@ -78,6 +79,7 @@ var ko = {
78
79
  chartLine: "\uAEBE\uC740\uC120 \uCC28\uD2B8",
79
80
  chartArea: "\uC601\uC5ED \uCC28\uD2B8",
80
81
  chartPie: "\uC6D0\uD615 \uCC28\uD2B8",
82
+ freeBadge: "\uBB34\uB8CC \uC0AC\uC6A9 \uC911",
81
83
  ops: {
82
84
  contains: "\uD3EC\uD568",
83
85
  equals: "\uAC19\uC74C",
@@ -1,4 +1,4 @@
1
- import { L as LocalePack } from '../types-DZ66BpLd.js';
1
+ import { L as LocalePack } from '../types-e45suTSB.js';
2
2
 
3
3
  declare const zhCN: LocalePack;
4
4
 
@@ -32,6 +32,7 @@ var zhCN = {
32
32
  pasteHint: "\u6D4F\u89C8\u5668\u963B\u6B62\u4E86\u526A\u8D34\u677F\u8BBF\u95EE\u3002\u8BF7\u6309 Ctrl+V \u7C98\u8D34\u3002",
33
33
  required: "\u6B64\u9879\u4E3A\u5FC5\u586B\u9879",
34
34
  invalidValue: "\u503C\u65E0\u6548",
35
+ duplicate: "\u8BE5\u503C\u5DF2\u88AB\u4F7F\u7528",
35
36
  undo: "\u64A4\u9500",
36
37
  redo: "\u91CD\u505A",
37
38
  deleteRows: "\u5220\u9664\u6240\u9009\u884C",
@@ -78,6 +79,7 @@ var zhCN = {
78
79
  chartLine: "\u6298\u7EBF\u56FE",
79
80
  chartArea: "\u9762\u79EF\u56FE",
80
81
  chartPie: "\u997C\u56FE",
82
+ freeBadge: "\u514D\u8D39\u4F7F\u7528\u4E2D",
81
83
  ops: {
82
84
  contains: "\u5305\u542B",
83
85
  equals: "\u7B49\u4E8E",
package/dist/styles.css CHANGED
@@ -6,7 +6,7 @@
6
6
  --fg-shadow: 0 12px 32px rgba(15, 23, 42, .16), 0 2px 6px rgba(15, 23, 42, .08);
7
7
  }
8
8
  .fg-theme-light {
9
- --fg-bg: #ffffff; --fg-fg: #1f2430; --fg-muted: #6b7385;
9
+ --fg-bg: #ffffff; --fg-fg: #1f2430; --fg-muted: #636b7c;
10
10
  --fg-header-bg: #f6f7f9; --fg-header-fg: #39404f; --fg-border: #e3e6eb; --fg-row-border: #eef0f3;
11
11
  --fg-row-odd: #fbfbfc; --fg-row-hover: #f2f6ff; --fg-row-selected: #e3edff;
12
12
  --fg-accent: #2563eb; --fg-accent-fg: #ffffff; --fg-focus: #2563eb; --fg-popup-bg: #ffffff; --fg-input-bg: #ffffff;
@@ -29,6 +29,7 @@
29
29
  }
30
30
  .fg-root *, .fg-menu * { box-sizing: border-box; }
31
31
  .fg-main { position: relative; display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; overflow: hidden; }
32
+ .fg-grid { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; outline: none; }
32
33
  .fg-root [hidden], .fg-menu [hidden] { display: none !important; }
33
34
  .fg-header { display: flex; flex: none; background: var(--fg-header-bg); color: var(--fg-header-fg); border-bottom: var(--fg-header-border, 1px solid var(--fg-border)); }
34
35
  .fg-header-pane { position: relative; overflow: hidden; flex: none; }
@@ -291,7 +292,11 @@ textarea.fg-editor-control { padding-top: 8px; resize: none; }
291
292
  .fg-drag-handle.fg-drag-disabled { opacity: .35; cursor: not-allowed; }
292
293
  .fg-row-dragging, .fg-row-dragging * { cursor: grabbing !important; }
293
294
  .fg-row-drop-marker { position: absolute; left: 0; right: 0; height: 2px; background: var(--fg-accent); z-index: 6; pointer-events: none; }
295
+ .fg-row-drop-marker.fg-row-drop-inside { background: color-mix(in srgb, var(--fg-accent) 8%, transparent); box-shadow: inset 0 0 0 2px var(--fg-accent); }
294
296
  @media (prefers-reduced-motion: reduce) { .fg-group-toggle svg, .fg-tree-toggle svg, .fg-detail-toggle svg { transition: none; } }
297
+ .fg-tree-loading svg { animation: fg-spin .8s linear infinite; opacity: .6; }
298
+ @keyframes fg-spin { to { transform: rotate(360deg); } }
299
+ @media (prefers-reduced-motion: reduce) { .fg-tree-loading svg { animation: none; } }
295
300
 
296
301
  /* pagination and server rows */
297
302
  .fg-pager {
@@ -366,3 +371,51 @@ textarea.fg-editor-control { padding-top: 8px; resize: none; }
366
371
  .fg-chart-plot:hover .fg-chart-bar:not(:hover), .fg-chart:hover .fg-chart-slice:not(:hover) { opacity: .55; }
367
372
  .fg-chart-slice { stroke: var(--fg-popup-bg, #fff); stroke-width: 1.5; }
368
373
  @media (prefers-reduced-motion: reduce) { .fg-chart-bar, .fg-chart-slice, .fg-chart-point { transition: none; } }
374
+
375
+ /* free-use badge (unlicensed company domains) */
376
+ .fg-free-badge {
377
+ position: absolute; right: 22px; bottom: 22px; z-index: 30; display: inline-flex; align-items: center; gap: 6px;
378
+ padding: 4px 10px 4px 6px; border-radius: 999px; background: rgba(255, 255, 255, .92); border: 1px solid rgba(14, 23, 38, .15);
379
+ box-shadow: 0 2px 8px rgba(14, 23, 38, .12); color: #0E1726; font: 600 11px/1.2 var(--fg-font); text-decoration: none; opacity: .9;
380
+ }
381
+ .fg-free-badge:hover { opacity: 1; }
382
+ .fg-free-badge svg { flex: none; }
383
+
384
+ /* column spans */
385
+ .fg-cell-span-hidden { visibility: hidden; }
386
+ .fg-cell-colspan { z-index: 1; background: inherit; }
387
+
388
+ /* per-cell locks */
389
+ .fg-cell-readonly { color: var(--fg-muted); background-image: linear-gradient(rgba(14, 23, 38, .025), rgba(14, 23, 38, .025)); }
390
+ .fg-cell-select-locked .fg-checkbox { cursor: not-allowed; opacity: .45; }
391
+
392
+ /* wrapped cells (autoRowHeight grows the row to fit) */
393
+ .fg-cell-wrap { white-space: normal; overflow-wrap: anywhere; text-overflow: clip; line-height: 1.45; padding-top: 6px; padding-bottom: 6px; }
394
+
395
+ /* right-to-left: mirror the grid area, then turn every cell back so text reads normally */
396
+ /* the root keeps dir=rtl (side bar on the left); the grid inside is laid out ltr and mirrored */
397
+ .fg-rtl .fg-main { transform: scaleX(-1); direction: ltr; }
398
+ .fg-rtl .fg-cell, .fg-rtl .fg-header-cell, .fg-rtl .fg-statusbar, .fg-rtl .fg-pager, .fg-rtl .fg-group-panel,
399
+ .fg-rtl .fg-overlay, .fg-rtl .fg-find, .fg-rtl .fg-chart-panel, .fg-rtl .fg-row-detail .fg-detail { transform: scaleX(-1); direction: rtl; }
400
+ .fg-rtl .fg-sidebar { direction: rtl; border-left: 0; border-right: 1px solid var(--fg-border); }
401
+
402
+ /* touch */
403
+ .fg-body { touch-action: pan-x pan-y; }
404
+ @media (pointer: coarse) {
405
+ .fg-editor input, .fg-editor select, .fg-editor textarea { font-size: 16px; } /* no zoom-in on focus in mobile Safari */
406
+ }
407
+
408
+ /* card view for narrow screens */
409
+ .fg-card-mode .fg-header, .fg-card-mode .fg-body, .fg-card-mode .fg-grid, .fg-card-mode .fg-summary, .fg-card-mode .fg-pinned-rows { display: none; }
410
+ .fg-cards { flex: 1; min-height: 0; overflow: auto; padding: 10px; -webkit-overflow-scrolling: touch; }
411
+ .fg-cards-canvas { position: relative; }
412
+ .fg-card {
413
+ position: absolute; left: 0; right: 0; top: 0; box-sizing: border-box; padding: 10px 14px; overflow: hidden;
414
+ border: 1px solid var(--fg-border); border-radius: 10px; background: var(--fg-bg); box-shadow: 0 1px 2px rgba(14, 23, 38, .06);
415
+ }
416
+ .fg-card-selected { border-color: var(--fg-accent); background: var(--fg-row-selected); }
417
+ .fg-card-other { background: var(--fg-header-bg); font-weight: 600; display: flex; align-items: center; }
418
+ .fg-card-head { display: flex; align-items: center; gap: 8px; height: var(--fg-card-line, 27px); color: var(--fg-muted); font-size: .92em; }
419
+ .fg-card-line { display: grid; grid-template-columns: minmax(80px, 38%) 1fr; gap: 10px; align-items: center; height: var(--fg-card-line, 27px); }
420
+ .fg-card-label { color: var(--fg-muted); font-size: .92em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
421
+ .fg-card-value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@@ -42,6 +42,11 @@ interface CellParams {
42
42
  rowIndex: number;
43
43
  column: ColumnDef;
44
44
  }
45
+ interface SpanParams {
46
+ value: unknown;
47
+ row: Row;
48
+ rowIndex: number;
49
+ }
45
50
  interface ColumnDef {
46
51
  /** Column id; defaults to `field`. Required when `field` is absent. */
47
52
  id?: string;
@@ -71,24 +76,77 @@ interface ColumnDef {
71
76
  chooser?: boolean;
72
77
  /** Users cannot hide this column from the UI (API still can). */
73
78
  lockVisible?: boolean;
74
- /** Allow editing and pasting into this column (requires `field`). */
75
- editable?: boolean;
79
+ /** Allow editing and pasting into this column (requires `field`); a function decides per cell. */
80
+ editable?: boolean | ((params: SpanParams & {
81
+ column: ColumnDef;
82
+ }) => boolean);
76
83
  /** Editor for editable columns; defaults by type (text, number, date, boolean toggle). */
77
84
  editor?: EditorSpec;
78
85
  /** Reject blank values on edit. */
79
86
  required?: boolean;
87
+ /** Cells may hold formulas like `=qty*price` (same-row fields); the result is shown, sorted and exported. */
88
+ formulas?: boolean;
89
+ /** Reject a value another row already has in this column (blank values are allowed). */
90
+ unique?: boolean;
91
+ /** Set false (or return false) to keep values out of copies: blocked cells copy as empty text. */
92
+ copyable?: boolean | ((params: {
93
+ value: unknown;
94
+ row: Row;
95
+ column: ColumnDef;
96
+ }) => boolean);
80
97
  /** Return true to accept, or a message to reject the edited value. */
81
98
  validate?: (value: unknown, row: Row) => true | string;
82
99
  /** Merge consecutive rows with the same value into one tall cell (or decide with a function). */
83
100
  merge?: boolean | ((a: unknown, b: unknown, rowA: Row, rowB: Row) => boolean);
84
101
  /** Let a long header label wrap onto more lines. */
85
102
  wrapHeaderText?: boolean;
103
+ /** Rows this cell covers downwards (1 = itself). Takes precedence over `merge`. */
104
+ rowSpan?: (params: SpanParams) => number;
105
+ /** Columns this cell covers to the right within its pinned area (1 = itself). */
106
+ colSpan?: (params: SpanParams) => number;
107
+ /** Wrap long text onto more lines (with `autoRowHeight` the row grows to fit). */
108
+ wrapText?: boolean;
109
+ /** Header content instead of the plain text (icons, buttons, links). Sorting and the menu button stay. */
110
+ headerRenderer?: (params: {
111
+ header: string;
112
+ column: ColumnDef;
113
+ }) => string | HTMLElement;
114
+ /** Extra class names on the header cell (also for column groups). */
115
+ headerClass?: string | ((column: ColumnDef) => string | undefined);
86
116
  /** Aggregate shown in group rows: 'sum' | 'avg' | 'min' | 'max' | 'count' | (values, rows) => value. */
87
117
  aggFunc?: Aggregator;
88
118
  }
119
+ interface InvalidCell {
120
+ row: Row;
121
+ /** Displayed row index; -1 when the row is filtered out or in a collapsed group. */
122
+ rowIndex: number;
123
+ colId: string;
124
+ message: string;
125
+ }
126
+ interface ScrollPosition {
127
+ top: number;
128
+ left: number;
129
+ }
130
+ type RowDropPosition = 'before' | 'after' | 'inside';
131
+ interface RowDropParams {
132
+ row: Row;
133
+ /** Row under the pointer; null = below the last row. */
134
+ target: Row | null;
135
+ /** 'inside' makes the row a child of the target (tree data only). */
136
+ position: RowDropPosition;
137
+ /** True when the row comes from another grid. */
138
+ fromOtherGrid: boolean;
139
+ }
140
+ interface RowDragOptions {
141
+ /** Grids with the same group accept rows dragged between them. */
142
+ group?: string;
143
+ /** Return false to refuse a drop target. */
144
+ canDrop?: (params: RowDropParams) => boolean;
145
+ }
89
146
  type SelectOption = unknown | {
90
147
  value: unknown;
91
148
  label?: string;
149
+ disabled?: boolean;
92
150
  };
93
151
  interface EditorParams {
94
152
  value: unknown;
@@ -108,6 +166,14 @@ type EditorSpec = {
108
166
  options: SelectOption[] | ((row: Row) => SelectOption[]);
109
167
  } | {
110
168
  type: 'textarea';
169
+ }
170
+ /** Time of day as 'HH:mm'. */
171
+ | {
172
+ type: 'time';
173
+ }
174
+ /** Date and time; Date values stay Dates, otherwise 'YYYY-MM-DDTHH:mm'. Default for date columns with format 'datetime'. */
175
+ | {
176
+ type: 'datetime';
111
177
  } | ((params: EditorParams) => CustomEditor);
112
178
  type KeyAction = 'edit' | 'clear' | 'undo' | 'redo' | 'copy' | 'paste' | 'selectAll' | 'find' | 'none';
113
179
  interface ColumnState {
@@ -148,6 +214,7 @@ interface Messages {
148
214
  pasteHint: string;
149
215
  required: string;
150
216
  invalidValue: string;
217
+ duplicate: string;
151
218
  undo: string;
152
219
  redo: string;
153
220
  deleteRows: string;
@@ -194,6 +261,7 @@ interface Messages {
194
261
  chartLine: string;
195
262
  chartArea: string;
196
263
  chartPie: string;
264
+ freeBadge: string;
197
265
  ops: Record<FilterOp, string>;
198
266
  }
199
267
  interface LocalePack extends Messages {
@@ -273,6 +341,8 @@ interface ExportOptions {
273
341
  sheetName?: string;
274
342
  /** CSV separator, default ','. */
275
343
  separator?: string;
344
+ /** xlsx: carry column align and the text color, background and bold of `cellClass` into the file. Default true. */
345
+ styles?: boolean;
276
346
  }
277
347
  interface PivotConfig {
278
348
  /** Row fields; every field but the last becomes a group level. */
@@ -347,6 +417,12 @@ interface GridOptions {
347
417
  /** Nest rows under their parent. Needs `getRowId`; `getParentId` returns the parent's id or null. */
348
418
  treeData?: {
349
419
  getParentId: (row: Row) => unknown;
420
+ /** Store a new parent id on the row (null = top level). Needed to drag rows to another parent. */
421
+ setParentId?: (row: Row, parentId: unknown, parent: Row | null) => void;
422
+ /** Rows whose children are not loaded yet but exist (e.g. folders on a server). */
423
+ hasChildren?: (row: Row) => boolean;
424
+ /** Fetch the children of a row on its first expand; they must carry the row's id as parent id. */
425
+ loadChildren?: (row: Row) => Promise<Row[]> | Row[];
350
426
  };
351
427
  /** Content of the expandable panel under a master row. */
352
428
  detailRenderer?: (params: {
@@ -357,8 +433,18 @@ interface GridOptions {
357
433
  detailHeight?: number;
358
434
  /** Which rows can expand a detail panel (default: all rows). */
359
435
  isRowMaster?: (row: Row) => boolean;
360
- /** Add a handle column for dragging rows into a new order. */
361
- rowDrag?: boolean;
436
+ /** Add a handle column for dragging rows into a new order (and between grids with the same `group`). */
437
+ rowDrag?: boolean | RowDragOptions;
438
+ /** Show rows as cards (header: value lines) when the grid is narrower than this many px; true = 640. */
439
+ cardView?: boolean | number;
440
+ /** 'rtl' lays the grid out right to left (Arabic, Hebrew…): first column on the right. */
441
+ direction?: 'ltr' | 'rtl';
442
+ /** Grow each row to fit its wrapped cells (`wrapText` columns); `rowHeight` is the minimum. */
443
+ autoRowHeight?: boolean;
444
+ /** Rows that may be checked; others show a disabled checkbox and are skipped by select-all. */
445
+ isRowSelectable?: (row: Row) => boolean;
446
+ /** Show the select-all checkbox in the header (default true). */
447
+ headerCheckbox?: boolean;
362
448
  /** Show rows one page at a time with a pager under the grid. */
363
449
  pagination?: boolean | {
364
450
  pageSize?: number;
@@ -463,6 +549,12 @@ interface GridEvents {
463
549
  fromIndex: number;
464
550
  toIndex: number;
465
551
  };
552
+ /** The rows area scrolled (also from setScrollPosition). */
553
+ scroll: ScrollPosition;
554
+ /** A row was dropped on this grid (also from another grid of the same drag group). */
555
+ rowDrop: RowDropParams & {
556
+ fromGrid: GridApi | null;
557
+ };
466
558
  pageChange: {
467
559
  page: number;
468
560
  pageSize: number;
@@ -478,12 +570,53 @@ interface GridEvents {
478
570
  end: number;
479
571
  error: unknown;
480
572
  };
573
+ /** treeData.loadChildren finished for a row. */
574
+ childrenLoaded: {
575
+ row: Row;
576
+ rows: Row[];
577
+ };
578
+ childrenLoadFailed: {
579
+ row: Row;
580
+ error: unknown;
581
+ };
481
582
  pivotChange: {
482
583
  pivot: PivotConfig | null;
483
584
  };
585
+ /** Fired before the change; call cancel() to stop it (e.g. to sort or filter on a server instead). */
586
+ beforeSort: {
587
+ sort: SortItem[];
588
+ cancel(): void;
589
+ };
590
+ beforeFilter: {
591
+ colId: string;
592
+ model: FilterModel | null;
593
+ cancel(): void;
594
+ };
595
+ beforePageChange: {
596
+ page: number;
597
+ pageSize: number;
598
+ cancel(): void;
599
+ };
600
+ beforeEdit: {
601
+ row: Row;
602
+ rowIndex: number;
603
+ colId: string;
604
+ cancel(): void;
605
+ };
606
+ beforeCellChange: {
607
+ row: Row;
608
+ rowIndex: number;
609
+ colId: string;
610
+ oldValue: unknown;
611
+ newValue: unknown;
612
+ cancel(): void;
613
+ };
484
614
  }
485
615
  interface GridApi {
486
- setData(rows: Row[]): void;
616
+ /** Replace all rows. The scroll position stays unless `scrollToTop` is set. */
617
+ setData(rows: Row[], options?: {
618
+ scrollToTop?: boolean;
619
+ }): void;
487
620
  getData(): Row[];
488
621
  setColumns(columns: ColumnDef[]): void;
489
622
  getColumnState(): ColumnState[];
@@ -498,6 +631,14 @@ interface GridApi {
498
631
  deselectAll(): void;
499
632
  getDisplayedRowCount(): number;
500
633
  scrollToRow(index: number): void;
634
+ /** Check every editable cell against required, unique and validate. Empty when all rows are valid. */
635
+ validate(): InvalidCell[];
636
+ /** Scroll offsets of the rows area in px. */
637
+ getScrollPosition(): ScrollPosition;
638
+ /** Scroll the rows area; omitted axes stay where they are. */
639
+ setScrollPosition(position: Partial<ScrollPosition>): void;
640
+ /** Keep this grid and `other` scrolled together; returns a function that unlinks them. */
641
+ syncScroll(other: GridApi, axis?: 'both' | 'vertical' | 'horizontal'): () => void;
501
642
  setTheme(theme: string): void;
502
643
  setLocale(locale: string | Partial<LocalePack>): void;
503
644
  setFont(font: {
@@ -515,6 +656,9 @@ interface GridApi {
515
656
  getSummaryValues(): Record<string, unknown>[];
516
657
  getRange(): GridRange | null;
517
658
  setRange(range: GridRange | null): void;
659
+ /** Every selected range (Ctrl+click adds one); the last is the active range. */
660
+ getRanges(): GridRange[];
661
+ setRanges(ranges: GridRange[]): void;
518
662
  /** Copy the range (or checked rows, or the focused cell) as Excel TSV; also writes the clipboard when allowed. */
519
663
  copySelection(options?: {
520
664
  headers?: boolean;
@@ -569,6 +713,8 @@ interface GridApi {
569
713
  isDetailExpanded(row: Row): boolean;
570
714
  /** Move a row to a new index in the source data. False while sorting, filtering or grouping is active. */
571
715
  moveRow(row: Row, toIndex: number): boolean;
716
+ /** Move a row before, after or (tree data) inside another row; null target = to the end. False when refused. */
717
+ dropRow(row: Row, target: Row | null, position?: RowDropPosition): boolean;
572
718
  /** 0-based page; clamped to the available pages. */
573
719
  setPage(page: number): void;
574
720
  getPage(): number;
@@ -600,4 +746,4 @@ interface GridApi {
600
746
  destroy(): void;
601
747
  }
602
748
 
603
- export type { Aggregator as A, SummaryRowDef as B, CellEvent as C, Datasource as D, EditorParams as E, FilterModel as F, GridOptions as G, TextOp as H, KeyAction as K, LocalePack as L, Messages as M, NumberFilterModel as N, PivotConfig as P, Region as R, SelectOption as S, TextFilterModel as T, 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, ServerParams as u, SetFilterModel as v, SortDir as w, SortItem as x, SummaryCell as y, SummaryOptions as z };
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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@freegridjs/core",
3
- "version": "0.7.0",
3
+ "version": "0.8.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",