@inandu-solutions/grid-react 0.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.
Files changed (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +70 -0
  3. package/dist/components/InanduGrid.d.ts +97 -0
  4. package/dist/core/aggregate.d.ts +5 -0
  5. package/dist/core/columns.d.ts +11 -0
  6. package/dist/core/constants.d.ts +14 -0
  7. package/dist/core/export/csv.d.ts +2 -0
  8. package/dist/core/export/download.d.ts +2 -0
  9. package/dist/core/export/markup.d.ts +2 -0
  10. package/dist/core/export/pdf.d.ts +3 -0
  11. package/dist/core/filter.d.ts +26 -0
  12. package/dist/core/format.d.ts +24 -0
  13. package/dist/core/i18n/en.d.ts +46 -0
  14. package/dist/core/i18n/es.d.ts +46 -0
  15. package/dist/core/i18n/fr.d.ts +46 -0
  16. package/dist/core/i18n/index.d.ts +8 -0
  17. package/dist/core/i18n/it.d.ts +46 -0
  18. package/dist/core/i18n/zh.d.ts +46 -0
  19. package/dist/core/index.d.ts +16 -0
  20. package/dist/core/parse.d.ts +14 -0
  21. package/dist/core/sort.d.ts +1 -0
  22. package/dist/core/tree.d.ts +28 -0
  23. package/dist/core/types.d.ts +46 -0
  24. package/dist/hooks/useInanduGrid.d.ts +187 -0
  25. package/dist/html2canvas-BE2ZQbtv.js +4021 -0
  26. package/dist/html2canvas-o9-HsXBE.cjs +5 -0
  27. package/dist/inandu-grid-react.cjs +2 -0
  28. package/dist/inandu-grid-react.js +1656 -0
  29. package/dist/index.d.ts +11 -0
  30. package/dist/index.es-BqzICVsf.cjs +5 -0
  31. package/dist/index.es-CPZG9pTc.js +5752 -0
  32. package/dist/jspdf.es.min-D_8zJvYC.cjs +78 -0
  33. package/dist/jspdf.es.min-DiTFVZBc.js +18250 -0
  34. package/dist/purify.es-3_UFdOhH.js +805 -0
  35. package/dist/purify.es-DXMFKXT6.cjs +3 -0
  36. package/dist/utils/exporters.d.ts +29 -0
  37. package/dist/utils/measureColumn.d.ts +15 -0
  38. package/dist/utils/translate.d.ts +10 -0
  39. package/package.json +89 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Inandu SAS (https://inandu.com)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # inandu-grid-react
2
+
3
+ The React port of [`@inandu-solutions/grid-angular`](https://github.com/inandusolutions/inandu-grid) —
4
+ a standalone data grid: sorting, filtering, grouping, pagination, virtual scroll, inline editing,
5
+ CSV/Excel/PDF export and i18n, with a deliberately small dependency footprint.
6
+
7
+ [![license](https://img.shields.io/badge/license-MIT-0e7c74.svg)](LICENSE)
8
+ ![React](https://img.shields.io/badge/React-18%20%7C%2019-61dafb)
9
+ [![Open in StackBlitz](https://img.shields.io/badge/StackBlitz-open%20example-1389FD?logo=stackblitz&logoColor=white)](https://stackblitz.com/github/inandusolutions/inandu-grid-react/tree/main/examples/stackblitz)
10
+
11
+ **Feature-complete with grid-angular — not yet published to npm** (see the "Package" bullet
12
+ below). The framework-agnostic core (sorting, filtering, aggregation, export, i18n) is
13
+ ported from grid-angular's
14
+ [`core/`](https://github.com/inandusolutions/inandu-grid/tree/main/projects/inandu-grid/src/lib/core)
15
+ folder and kept in sync by hand across the two repos. The React-specific layer — the `<InanduGrid>`
16
+ component and the `useInanduGrid()` headless hook — covers sorting (single- and, via shift-click,
17
+ multi-column), free-text search, per-column filtering, pagination, single-column grouping with
18
+ aggregates, row selection, CSV/Excel(.xls)/PDF export, print, i18n (the 5 built-in languages, via a
19
+ `lang` prop), inline row editing/creation/deletion with validation
20
+ (required/min/max/pattern/custom/async), Excel-style Ctrl+C/Ctrl+V clipboard copy/paste, runtime
21
+ column show/hide, sticky (pinned left/right) columns, column drag-reorder, column resize (drag a
22
+ header's handle) and autosize (double-click it to fit content), row drag-reorder, tree data
23
+ (`treeChildrenKey`, display + expand only — no inline editing/drag/clipboard on tree rows, same
24
+ restriction as grid-angular), master-detail (`renderDetail`), and row virtualization
25
+ (`virtualScroll`) for large datasets.
26
+
27
+ Two things work slightly differently from grid-angular because they need a real browser layout
28
+ engine that a unit-test environment can't provide: virtual scroll's row height isn't
29
+ auto-measured — pass `virtualRowHeight` explicitly — and autosize's content measurement itself is
30
+ trusted (ported verbatim, same DOM APIs) rather than end-to-end tested; see
31
+ [`measureColumn.ts`](src/utils/measureColumn.ts)'s doc comment for exactly what its test suite does
32
+ and doesn't cover.
33
+
34
+ - **Angular version:** [`inandu-grid`](https://github.com/inandusolutions/inandu-grid) — the
35
+ original, feature-complete, MIT-licensed grid. Start there if you need something production-ready
36
+ today.
37
+ - **Commercial add-ons for React:** `@inandu-solutions/grid-pro-react` *(private, paid, not released
38
+ yet)* — the React port of `@inandu-solutions/grid-pro`, depends on this package the same way
39
+ grid-pro depends on grid-angular.
40
+ - **Package:** will ship as [`@inandu-solutions/grid-react`](https://www.npmjs.com/package/@inandu-solutions/grid-react)
41
+ (MIT) — npm publishing is deferred until the API stabilizes.
42
+ - **⚡ StackBlitz:** [a minimal editable example](https://stackblitz.com/github/inandusolutions/inandu-grid-react/tree/main/examples/stackblitz) —
43
+ the grid in a bare React app; edit `src/App.tsx` and it updates live ([source](examples/stackblitz)).
44
+ Imports straight from this repo's source (not npm — the package isn't published yet).
45
+
46
+ ## Development
47
+
48
+ ```bash
49
+ npm install
50
+ npm run dev # Vite dev server
51
+ npm test # Vitest + React Testing Library
52
+ npm run build # library build (dist/)
53
+ ```
54
+
55
+ ## API shape
56
+
57
+ ```tsx
58
+ import { InanduGrid, useInanduGrid } from '@inandu-solutions/grid-react';
59
+
60
+ // Component: batteries-included table.
61
+ <InanduGrid rows={rows} columns={columns} />;
62
+
63
+ // Hook: headless — bring your own markup.
64
+ const { visibleRows, filteredRowCount, sort, setSort, filterValues, setFilterValue, page, setPage, pageCount } =
65
+ useInanduGrid({ rows, columns, pageSize: 25 });
66
+ ```
67
+
68
+ ## License
69
+
70
+ MIT © [Inandu SAS](https://inandu.com)
@@ -0,0 +1,97 @@
1
+ import { ReactNode } from 'react';
2
+ import { InanduGridRow } from '../core';
3
+ import { InanduGridCellPaste, InanduGridColumn, InanduGridRowSave } from '../hooks/useInanduGrid';
4
+ export interface InanduGridProps {
5
+ rows: InanduGridRow[];
6
+ columns: InanduGridColumn[];
7
+ /** Drives number/date formatting (`Intl`-based). Default: 'en'. */
8
+ locale?: string;
9
+ /** Drives built-in UI string translation (one of `INANDU_GRID_TRANSLATIONS`'s keys). Default: `locale`'s primary subtag. */
10
+ lang?: string;
11
+ /** 0 (default) disables pagination — every filtered/sorted row renders. Ignored while grouped. */
12
+ pageSize?: number;
13
+ /** Adds a checkbox column with row + select-all selection. Default: false. */
14
+ selectable?: boolean;
15
+ /** Called after every selection change with the current full selection, as an array. */
16
+ onSelectionChange?: (selectedRows: InanduGridRow[]) => void;
17
+ /** Adds a CSV/Excel/PDF export toolbar above the table. Default: false. */
18
+ exportable?: boolean;
19
+ /** Base filename (without extension) for exports. Default: 'inandu-grid'. */
20
+ exportFilenameBase?: string;
21
+ /** Adds a per-row "Delete" button. Default: false. */
22
+ deletable?: boolean;
23
+ /** `window.confirm()`-gates a single row's delete. Unset: deletes immediately. */
24
+ deleteConfirmMessage?: string;
25
+ /** `window.confirm()`-gates the "Delete selected" bulk action (shown when `selectable && deletable` with at least one row selected). Unset: deletes immediately. */
26
+ bulkDeleteConfirmMessage?: string;
27
+ /** Adds an "Add row" trigger with a blank draft row. Default: false. Has no effect unless at least one column is `editable`. */
28
+ creatable?: boolean;
29
+ /** Called once a row edit passes validation. The grid never mutates `rows` itself — applying `values` onto `row` is the caller's job. */
30
+ onRowSave?: (event: InanduGridRowSave) => void;
31
+ /** Called once a new row's draft passes validation. No row reference — it doesn't exist in `rows` yet. */
32
+ onRowCreate?: (values: Record<string, unknown>) => void;
33
+ /** Called after a single-row delete is confirmed (or clicked, if no `deleteConfirmMessage`). */
34
+ onRowDelete?: (row: InanduGridRow) => void;
35
+ /** Called after the bulk "Delete selected" action is confirmed (or clicked, if no `bulkDeleteConfirmMessage`). */
36
+ onRowsDelete?: (rows: InanduGridRow[]) => void;
37
+ /** Opts into `Ctrl+C`/`Ctrl+V` cell copy/paste (Excel-style TSV). Default: false. */
38
+ clipboard?: boolean;
39
+ /** Called with every parsed cell update from a `Ctrl+V`. The grid never mutates `rows` itself. */
40
+ onCellsPaste?: (updates: InanduGridCellPaste[]) => void;
41
+ /** Adds a "Columns" toolbar button + popup letting the user show/hide individual columns at runtime. Default: false. */
42
+ columnToggle?: boolean;
43
+ /** Adds a per-row drag handle to reorder rows. Default: false. Auto-disabled while grouped, same as grid-angular. */
44
+ rowReorder?: boolean;
45
+ /** Called with the fully reordered row array after a row drag-and-drop. The grid never mutates `rows` itself. */
46
+ onRowOrderChange?: (rows: InanduGridRow[]) => void;
47
+ /**
48
+ * Turns on tree mode: the field on each row holding its child rows (a nested array of the same
49
+ * shape). `rows` is then the root rows. Auto-disabled while grouped. Tree rows are display +
50
+ * expand only — inline editing, drag-reorder and clipboard don't apply to them, same as
51
+ * grid-angular.
52
+ */
53
+ treeChildrenKey?: string;
54
+ /** Initial expand state for tree mode. Default: `'none'`. */
55
+ treeDefaultExpanded?: 'none' | 'all' | number;
56
+ /**
57
+ * Enables master-detail: renders a leading expand/collapse toggle per row, and (while expanded)
58
+ * a full-width detail row right below it, with whatever this returns. Auto-disabled while
59
+ * grouped, same as grid-angular's `detailTemplate`/`hasMasterDetail`. Unset (default): off.
60
+ */
61
+ renderDetail?: (row: InanduGridRow) => ReactNode;
62
+ /** Collapses any other expanded row first, accordion-style, when a new one expands. Off (any number of rows can be expanded at once) by default. */
63
+ singleDetailExpand?: boolean;
64
+ /**
65
+ * Opt-in row virtualization for large datasets — only rows scrolled into view (plus a small
66
+ * overscan runway) are actually mounted. Bypasses pagination entirely, same as grouping.
67
+ * Auto-disabled while grouped (this port doesn't interleave group headers into the virtualized
68
+ * window the way grid-angular does); also disables master-detail, row drag-reorder, tree data,
69
+ * and the totals `<tfoot>`, same restrictions grid-angular's `virtualScroll` has. Default: false.
70
+ */
71
+ virtualScroll?: boolean;
72
+ /**
73
+ * Fixed row height (px) the virtualization math uses to compute scroll position and how many
74
+ * rows to render. Unlike grid-angular, this port doesn't auto-measure a rendered row's real
75
+ * height (that needs a real layout engine to verify, which unit tests can't provide) — pass the
76
+ * actual rendered row height for correct scrolling. Default: 40.
77
+ */
78
+ virtualRowHeight?: number;
79
+ /** The scrollable viewport's own height (px) — only used while `virtualScroll`. Default: 400. */
80
+ height?: number;
81
+ /** Extra rows rendered above/below the visible window, so a fast scroll doesn't flash empty space before the next render catches up. Default: 4. */
82
+ overscan?: number;
83
+ /**
84
+ * Double-click a column's resize handle to fit its width to its widest currently-rendered value
85
+ * (header included). Measures real rendered text width via the DOM (`measureColumnContentWidth`)
86
+ * — like grid-angular's own autosize, this only measures what's actually mounted (one page, or
87
+ * the virtual window), not the full dataset. Default: false.
88
+ */
89
+ autosize?: boolean;
90
+ }
91
+ /**
92
+ * Batteries-included table over `useInanduGrid`: sorting, free-text search, a per-column filter
93
+ * row, pagination, single-column grouping with per-group + grand-total aggregates, row selection,
94
+ * CSV/Excel/PDF export, i18n, inline row editing/creation/deletion with validation, and row
95
+ * virtualization for large datasets.
96
+ */
97
+ export declare function InanduGrid({ rows, columns, locale, lang, pageSize, selectable, onSelectionChange, exportable, exportFilenameBase, deletable, deleteConfirmMessage, bulkDeleteConfirmMessage, creatable, onRowSave, onRowCreate, onRowDelete, onRowsDelete, clipboard, onCellsPaste, columnToggle, rowReorder, onRowOrderChange, treeChildrenKey, treeDefaultExpanded, renderDetail, singleDetailExpand, virtualScroll, virtualRowHeight, height, overscan, autosize, }: InanduGridProps): import('react').JSX.Element;
@@ -0,0 +1,5 @@
1
+ import { ColumnConfig, InanduColumnAggregate, InanduGridRow } from './types';
2
+ /** Short, language-agnostic symbol shown for each `InanduColumnAggregate` kind — deliberately not translated (the same way units like "CSV"/"PDF" aren't). */
3
+ export declare const AGGREGATE_SYMBOLS: Record<Exclude<InanduColumnAggregate, ''>, string>;
4
+ /** One numeric aggregate per `aggregateColumns` entry, computed over `rows` — `'count'` just counts rows (works for any column type); the rest ignore rows whose raw value isn't a finite number. */
5
+ export declare function computeGroupAggregates(rows: InanduGridRow[], aggregateColumns: readonly ColumnConfig[]): Record<string, number>;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Columns with an explicit `order` land at that 0-based slot; columns without one
3
+ * fill the remaining slots in declaration order. Equal/out-of-range `order` values
4
+ * degrade gracefully by falling back to declaration order among themselves.
5
+ *
6
+ * Generic over the column type: works for `InanduColumnComponent` instances or any object with
7
+ * an `order()` accessor.
8
+ */
9
+ export declare function placeColumnsByOrder<C extends {
10
+ order(): number | undefined;
11
+ }>(columns: readonly C[]): C[];
@@ -0,0 +1,14 @@
1
+ /** Floor enforced while dragging a resize handle, so a column can never be shrunk to zero/negative width. */
2
+ export declare const MIN_COLUMN_WIDTH = 30;
3
+ /** Ceiling `autosize` (double-click a resize handle to fit content) will grow a column to, so one
4
+ * very long value can't blow the column out to the width of the page. The drag handle itself is
5
+ * not capped by this. */
6
+ export declare const MAX_COLUMN_WIDTH = 600;
7
+ /** Must match `.inandu-select-column`'s CSS width — used by `stickyOffset()` to account for the (always-sticky) checkbox column. */
8
+ export declare const SELECT_COLUMN_WIDTH = 36;
9
+ /** Must match `.inandu-row-drag-column`'s CSS width — used by `stickyOffset()` to account for the (always-leading, when enabled) drag-handle column. */
10
+ export declare const ROW_DRAG_COLUMN_WIDTH = 32;
11
+ /** Must match `.inandu-detail-toggle-column`'s CSS width — used by `stickyOffset()` to account for the (always-leading-most, when enabled) master-detail expand/collapse column. */
12
+ export declare const DETAIL_TOGGLE_COLUMN_WIDTH = 32;
13
+ /** `localStorage` key prefix for `stateKey`-based persistence, so this library's own saved blobs don't collide with anything else a host app stores. */
14
+ export declare const STATE_STORAGE_PREFIX = "inandu-grid-state:";
@@ -0,0 +1,2 @@
1
+ /** Quotes `value` for a CSV cell (doubling internal quotes) only if it contains a comma, quote, or newline. */
2
+ export declare function escapeCsvValue(value: string): string;
@@ -0,0 +1,2 @@
1
+ /** Triggers a browser download of `content` as `filename`, via a throwaway object URL + `<a>` click. */
2
+ export declare function downloadBlob(content: string | Blob, filename: string, mimeType?: string): void;
@@ -0,0 +1,2 @@
1
+ /** Escapes `&`/`</>` for safe use as XML/HTML element text content — shared by `exportExcel()` and `printTable()`. */
2
+ export declare function escapeMarkup(value: string): string;
@@ -0,0 +1,3 @@
1
+ import { jsPDF } from 'jspdf';
2
+ /** Shortens `text` with a trailing "…" until it fits `maxWidth` (in the PDF's current font), unchanged if it already fits. */
3
+ export declare function truncatePdfText(doc: jsPDF, text: string, maxWidth: number): string;
@@ -0,0 +1,26 @@
1
+ import { ColumnConfig, InanduGridColumnFilterValue, InanduGridRow } from './types';
2
+ import { NumberFormatter } from './format';
3
+ /**
4
+ * Whether `value` has at least one non-empty key — an entry can exist (e.g. after typing then
5
+ * clearing) without actually narrowing anything. `values` is the one exception: unlike every other
6
+ * key, an *empty* array is still meaningful (see `matchesColumnFilter`) — the presence of the key
7
+ * at all is what counts, not its length. Only an entirely absent/`undefined` `values` reads as "no
8
+ * set-filter constraint".
9
+ */
10
+ export declare function hasMeaningfulFilterValue(value: InanduGridColumnFilterValue | undefined): boolean;
11
+ /**
12
+ * Whether `row` satisfies `column`'s own filter control. An empty/absent `filterValue` (no
13
+ * constraint entered for this column yet) always matches. Range checks (`'number'`/`'date'`) are
14
+ * inclusive on both ends; a cell that can't be parsed as that column's type never matches once at
15
+ * least one bound is set.
16
+ *
17
+ * `filterValue.values` (the set filter) is the one key that's *present-vs-absent*, not
18
+ * *non-empty-vs-empty*: an `undefined` `values` falls through to the type-specific checks below,
19
+ * same as omitting it; a *defined* `values` — even `[]` — takes over matching for the column
20
+ * entirely, checked against the formatted display value. This is deliberate: `[]` is how "every
21
+ * checkbox is unchecked" (match nothing) is told apart from "the set filter was never touched"
22
+ * (match everything, i.e. don't constrain) — collapsing them to the same "no constraint" meaning,
23
+ * like every other filter key's blank state does, would make unchecking every box a no-op instead
24
+ * of the empty result a consumer building a set-filter checklist actually needs.
25
+ */
26
+ export declare function matchesColumnFilter(column: ColumnConfig, row: InanduGridRow, filterValue: InanduGridColumnFilterValue, locale: string, numberFormatter?: NumberFormatter): boolean;
@@ -0,0 +1,24 @@
1
+ import { InanduColumnType } from './types';
2
+ /**
3
+ * Turns a raw numeric value into its display string. `digitsInfo` is a `DecimalPipe`-style
4
+ * `'{minInt}.{minFrac}-{maxFrac}'` string (e.g. `"1.2-2"`), or empty for the default.
5
+ *
6
+ * Injected into `formatCellValue()` so the framework layer can choose the implementation: the
7
+ * Angular component passes one backed by `@angular/common`'s `formatNumber` (honouring whatever
8
+ * locale data the host app registered), keeping its output byte-identical to before this folder
9
+ * existed. `defaultNumberFormatter` below is the standalone fallback for a non-Angular consumer.
10
+ */
11
+ export type NumberFormatter = (value: number, locale: string, digitsInfo?: string) => string;
12
+ /** `Intl.NumberFormat`-based `NumberFormatter`. Parses the `digitsInfo` mini-syntax; falls back to Angular's own default of up to 3 fraction digits (`'1.0-3'`) when it's absent. */
13
+ export declare function defaultNumberFormatter(value: number, locale: string, digitsInfo?: string): string;
14
+ /**
15
+ * Coerces a raw cell value to a `Date` for `type="date"` columns — accepts a `Date`, a timestamp,
16
+ * or a string. Safari's `Date` string parser is stricter than Chrome's; notably it returns an
17
+ * Invalid Date for a space-separated `"yyyy-mm-dd hh:mm[:ss]"` that Chrome happily parses. That one
18
+ * common case is normalised to the ISO `T` form before parsing, so a `type="date"` column renders
19
+ * and filters identically in both. Anything still unparseable comes back as an Invalid Date — every
20
+ * caller already guards with `Number.isNaN(date.getTime())`.
21
+ */
22
+ export declare function coerceToDate(value: unknown): Date;
23
+ export declare function formatDateValue(date: Date, format: string): string;
24
+ export declare function formatCellValue(value: unknown, type: InanduColumnType, format: string, locale: string, numberFormatter?: NumberFormatter): string;
@@ -0,0 +1,46 @@
1
+ export declare const en: {
2
+ MsgNoData: string;
3
+ MsgFirstPage: string;
4
+ MsgPreviousPage: string;
5
+ MsgNextPage: string;
6
+ MsgLastPage: string;
7
+ MsgSortBy: string;
8
+ MsgPageOf: string;
9
+ MsgFilterPlaceholder: string;
10
+ MsgFilterColumn: string;
11
+ MsgFilterMin: string;
12
+ MsgFilterMax: string;
13
+ MsgFilterFrom: string;
14
+ MsgFilterTo: string;
15
+ MsgAll: string;
16
+ MsgCancelFilter: string;
17
+ MsgCancelAllFilters: string;
18
+ MsgGroupByHint: string;
19
+ MsgGroupedBy: string;
20
+ MsgGroupHeader: string;
21
+ MsgCancelGrouping: string;
22
+ MsgSelectAll: string;
23
+ MsgSelectRow: string;
24
+ MsgExportCsv: string;
25
+ MsgExportExcel: string;
26
+ MsgExportPdf: string;
27
+ MsgPrint: string;
28
+ MsgToggleColumns: string;
29
+ MsgToggleColumn: string;
30
+ MsgEditCell: string;
31
+ MsgEditRow: string;
32
+ MsgSaveRow: string;
33
+ MsgCancelRowEdit: string;
34
+ MsgDeleteRow: string;
35
+ MsgAddRow: string;
36
+ MsgLoading: string;
37
+ MsgDragRow: string;
38
+ MsgAutosizeColumn: string;
39
+ MsgExpandDetail: string;
40
+ MsgCollapseDetail: string;
41
+ MsgDeleteSelected: string;
42
+ MsgValidationRequired: string;
43
+ MsgValidationMin: string;
44
+ MsgValidationMax: string;
45
+ MsgValidationPattern: string;
46
+ };
@@ -0,0 +1,46 @@
1
+ export declare const es: {
2
+ MsgNoData: string;
3
+ MsgFirstPage: string;
4
+ MsgPreviousPage: string;
5
+ MsgNextPage: string;
6
+ MsgLastPage: string;
7
+ MsgSortBy: string;
8
+ MsgPageOf: string;
9
+ MsgFilterPlaceholder: string;
10
+ MsgFilterColumn: string;
11
+ MsgFilterMin: string;
12
+ MsgFilterMax: string;
13
+ MsgFilterFrom: string;
14
+ MsgFilterTo: string;
15
+ MsgAll: string;
16
+ MsgCancelFilter: string;
17
+ MsgCancelAllFilters: string;
18
+ MsgGroupByHint: string;
19
+ MsgGroupedBy: string;
20
+ MsgGroupHeader: string;
21
+ MsgCancelGrouping: string;
22
+ MsgSelectAll: string;
23
+ MsgSelectRow: string;
24
+ MsgExportCsv: string;
25
+ MsgExportExcel: string;
26
+ MsgExportPdf: string;
27
+ MsgPrint: string;
28
+ MsgToggleColumns: string;
29
+ MsgToggleColumn: string;
30
+ MsgEditCell: string;
31
+ MsgEditRow: string;
32
+ MsgSaveRow: string;
33
+ MsgCancelRowEdit: string;
34
+ MsgDeleteRow: string;
35
+ MsgAddRow: string;
36
+ MsgLoading: string;
37
+ MsgDragRow: string;
38
+ MsgAutosizeColumn: string;
39
+ MsgExpandDetail: string;
40
+ MsgCollapseDetail: string;
41
+ MsgDeleteSelected: string;
42
+ MsgValidationRequired: string;
43
+ MsgValidationMin: string;
44
+ MsgValidationMax: string;
45
+ MsgValidationPattern: string;
46
+ };
@@ -0,0 +1,46 @@
1
+ export declare const fr: {
2
+ MsgNoData: string;
3
+ MsgFirstPage: string;
4
+ MsgPreviousPage: string;
5
+ MsgNextPage: string;
6
+ MsgLastPage: string;
7
+ MsgSortBy: string;
8
+ MsgPageOf: string;
9
+ MsgFilterPlaceholder: string;
10
+ MsgFilterColumn: string;
11
+ MsgFilterMin: string;
12
+ MsgFilterMax: string;
13
+ MsgFilterFrom: string;
14
+ MsgFilterTo: string;
15
+ MsgAll: string;
16
+ MsgCancelFilter: string;
17
+ MsgCancelAllFilters: string;
18
+ MsgGroupByHint: string;
19
+ MsgGroupedBy: string;
20
+ MsgGroupHeader: string;
21
+ MsgCancelGrouping: string;
22
+ MsgSelectAll: string;
23
+ MsgSelectRow: string;
24
+ MsgExportCsv: string;
25
+ MsgExportExcel: string;
26
+ MsgExportPdf: string;
27
+ MsgPrint: string;
28
+ MsgToggleColumns: string;
29
+ MsgToggleColumn: string;
30
+ MsgEditCell: string;
31
+ MsgEditRow: string;
32
+ MsgSaveRow: string;
33
+ MsgCancelRowEdit: string;
34
+ MsgDeleteRow: string;
35
+ MsgAddRow: string;
36
+ MsgLoading: string;
37
+ MsgDragRow: string;
38
+ MsgAutosizeColumn: string;
39
+ MsgExpandDetail: string;
40
+ MsgCollapseDetail: string;
41
+ MsgDeleteSelected: string;
42
+ MsgValidationRequired: string;
43
+ MsgValidationMin: string;
44
+ MsgValidationMax: string;
45
+ MsgValidationPattern: string;
46
+ };
@@ -0,0 +1,8 @@
1
+ import { en } from './en';
2
+ import { es } from './es';
3
+ import { fr } from './fr';
4
+ import { it } from './it';
5
+ import { zh } from './zh';
6
+ export { en, es, fr, it, zh };
7
+ /** Every built-in dictionary, keyed by primary language subtag. */
8
+ export declare const INANDU_GRID_TRANSLATIONS: Record<string, Record<string, string>>;
@@ -0,0 +1,46 @@
1
+ export declare const it: {
2
+ MsgNoData: string;
3
+ MsgFirstPage: string;
4
+ MsgPreviousPage: string;
5
+ MsgNextPage: string;
6
+ MsgLastPage: string;
7
+ MsgSortBy: string;
8
+ MsgPageOf: string;
9
+ MsgFilterPlaceholder: string;
10
+ MsgFilterColumn: string;
11
+ MsgFilterMin: string;
12
+ MsgFilterMax: string;
13
+ MsgFilterFrom: string;
14
+ MsgFilterTo: string;
15
+ MsgAll: string;
16
+ MsgCancelFilter: string;
17
+ MsgCancelAllFilters: string;
18
+ MsgGroupByHint: string;
19
+ MsgGroupedBy: string;
20
+ MsgGroupHeader: string;
21
+ MsgCancelGrouping: string;
22
+ MsgSelectAll: string;
23
+ MsgSelectRow: string;
24
+ MsgExportCsv: string;
25
+ MsgExportExcel: string;
26
+ MsgExportPdf: string;
27
+ MsgPrint: string;
28
+ MsgToggleColumns: string;
29
+ MsgToggleColumn: string;
30
+ MsgEditCell: string;
31
+ MsgEditRow: string;
32
+ MsgSaveRow: string;
33
+ MsgCancelRowEdit: string;
34
+ MsgDeleteRow: string;
35
+ MsgAddRow: string;
36
+ MsgLoading: string;
37
+ MsgDragRow: string;
38
+ MsgAutosizeColumn: string;
39
+ MsgExpandDetail: string;
40
+ MsgCollapseDetail: string;
41
+ MsgDeleteSelected: string;
42
+ MsgValidationRequired: string;
43
+ MsgValidationMin: string;
44
+ MsgValidationMax: string;
45
+ MsgValidationPattern: string;
46
+ };
@@ -0,0 +1,46 @@
1
+ export declare const zh: {
2
+ MsgNoData: string;
3
+ MsgFirstPage: string;
4
+ MsgPreviousPage: string;
5
+ MsgNextPage: string;
6
+ MsgLastPage: string;
7
+ MsgSortBy: string;
8
+ MsgPageOf: string;
9
+ MsgFilterPlaceholder: string;
10
+ MsgFilterColumn: string;
11
+ MsgFilterMin: string;
12
+ MsgFilterMax: string;
13
+ MsgFilterFrom: string;
14
+ MsgFilterTo: string;
15
+ MsgAll: string;
16
+ MsgCancelFilter: string;
17
+ MsgCancelAllFilters: string;
18
+ MsgGroupByHint: string;
19
+ MsgGroupedBy: string;
20
+ MsgGroupHeader: string;
21
+ MsgCancelGrouping: string;
22
+ MsgSelectAll: string;
23
+ MsgSelectRow: string;
24
+ MsgExportCsv: string;
25
+ MsgExportExcel: string;
26
+ MsgExportPdf: string;
27
+ MsgPrint: string;
28
+ MsgToggleColumns: string;
29
+ MsgToggleColumn: string;
30
+ MsgEditCell: string;
31
+ MsgEditRow: string;
32
+ MsgSaveRow: string;
33
+ MsgCancelRowEdit: string;
34
+ MsgDeleteRow: string;
35
+ MsgAddRow: string;
36
+ MsgLoading: string;
37
+ MsgDragRow: string;
38
+ MsgAutosizeColumn: string;
39
+ MsgExpandDetail: string;
40
+ MsgCollapseDetail: string;
41
+ MsgDeleteSelected: string;
42
+ MsgValidationRequired: string;
43
+ MsgValidationMin: string;
44
+ MsgValidationMax: string;
45
+ MsgValidationPattern: string;
46
+ };
@@ -0,0 +1,16 @@
1
+ export type { InanduColumnType, InanduColumnStickySide, InanduColumnAggregate, InanduGridRow, InanduGridColumnFilterValue, ColumnConfig, } from './types';
2
+ export { MIN_COLUMN_WIDTH, MAX_COLUMN_WIDTH, SELECT_COLUMN_WIDTH, ROW_DRAG_COLUMN_WIDTH, DETAIL_TOGGLE_COLUMN_WIDTH, STATE_STORAGE_PREFIX, } from './constants';
3
+ export { coerceToDate, formatDateValue, formatCellValue, defaultNumberFormatter, } from './format';
4
+ export type { NumberFormatter } from './format';
5
+ export { compareCellValues } from './sort';
6
+ export { flattenTree, collectTreeRows } from './tree';
7
+ export type { TreeVisibleRow, FlattenTreeOptions } from './tree';
8
+ export { hasMeaningfulFilterValue, matchesColumnFilter } from './filter';
9
+ export { AGGREGATE_SYMBOLS, computeGroupAggregates } from './aggregate';
10
+ export { placeColumnsByOrder } from './columns';
11
+ export { parseDraftValue, parsePastedCellValue } from './parse';
12
+ export { escapeCsvValue } from './export/csv';
13
+ export { escapeMarkup } from './export/markup';
14
+ export { truncatePdfText } from './export/pdf';
15
+ export { downloadBlob } from './export/download';
16
+ export { en, es, fr, it, zh, INANDU_GRID_TRANSLATIONS } from './i18n';
@@ -0,0 +1,14 @@
1
+ import { InanduColumnType } from './types';
2
+ /**
3
+ * Parses a row-edit draft's raw control value (a string for text/number/date, a boolean for the
4
+ * checkbox — see `InanduGridComponent.onRowFieldChange`) per the column's `type`. Returns `undefined` for
5
+ * an unparseable `'number'`/`'date'`, the signal `saveRow()` uses to omit that field from `values`
6
+ * rather than committing garbage.
7
+ */
8
+ export declare function parseDraftValue(raw: unknown, type: InanduColumnType): unknown;
9
+ /**
10
+ * Parses one pasted TSV cell's raw text per `type` — like `parseDraftValue()`, except `'boolean'`:
11
+ * a pasted cell is always plain text (`"true"`/`"false"`, whatever the clipboard actually held),
12
+ * never an already-boolean checkbox `.checked` the way a manual row edit's draft value is.
13
+ */
14
+ export declare function parsePastedCellValue(raw: string, type: InanduColumnType): unknown;
@@ -0,0 +1 @@
1
+ export declare function compareCellValues(a: unknown, b: unknown, locale?: string): number;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Tree-data flattening (#3) — pure, framework-agnostic. Walks a nested-children hierarchy into the
3
+ * flat list of rows that should render right now: a node's children appear directly below it, but
4
+ * only while that node is expanded. Filtering keeps a node when it (or any descendant) matches, and
5
+ * force-expands the ancestors of a match so it's visible; an optional comparator sorts each level.
6
+ */
7
+ export interface TreeVisibleRow<T> {
8
+ row: T;
9
+ /** 0 for a root, +1 per level. Drives the first cell's indentation. */
10
+ depth: number;
11
+ /** Has at least one (surviving) child — i.e. worth showing a toggle. */
12
+ expandable: boolean;
13
+ /** Currently showing its children. */
14
+ expanded: boolean;
15
+ }
16
+ export interface FlattenTreeOptions<T> {
17
+ /** A node's children array (or `undefined` / `[]` for a leaf). */
18
+ getChildren: (row: T) => readonly T[] | undefined;
19
+ /** Whether `row` is expanded — consulted only when there is no active `match`. */
20
+ isExpanded: (row: T) => boolean;
21
+ /** When set, a node survives iff it or a descendant returns `true`; matches render expanded. */
22
+ match?: (row: T) => boolean;
23
+ /** Sorts the siblings at every level (applied after filtering). */
24
+ compare?: (a: T, b: T) => number;
25
+ }
26
+ export declare function flattenTree<T>(roots: readonly T[], options: FlattenTreeOptions<T>): TreeVisibleRow<T>[];
27
+ /** Every node in the hierarchy, depth-first — used for "expand all" / counting. */
28
+ export declare function collectTreeRows<T>(roots: readonly T[], getChildren: (row: T) => readonly T[] | undefined): T[];