@inandu-solutions/grid-vue 0.0.0-stage → 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.
- package/LICENSE +21 -0
- package/README.md +159 -3
- package/dist/components/DataRow.vue.d.ts +34 -0
- package/dist/components/EditCell.vue.d.ts +16 -0
- package/dist/components/FilterControl.vue.d.ts +16 -0
- package/dist/components/InanduGrid.vue.d.ts +225 -0
- package/dist/components/internal.d.ts +60 -0
- package/dist/components/types.d.ts +6 -0
- package/dist/composables/useInanduGrid.d.ts +236 -0
- package/dist/core/aggregate.d.ts +5 -0
- package/dist/core/columns.d.ts +11 -0
- package/dist/core/constants.d.ts +14 -0
- package/dist/core/dom.d.ts +8 -0
- package/dist/core/export/csv.d.ts +2 -0
- package/dist/core/export/download.d.ts +2 -0
- package/dist/core/export/markup.d.ts +2 -0
- package/dist/core/export/pdf.d.ts +3 -0
- package/dist/core/filter.d.ts +26 -0
- package/dist/core/format.d.ts +24 -0
- package/dist/core/i18n/en.d.ts +46 -0
- package/dist/core/i18n/es.d.ts +46 -0
- package/dist/core/i18n/fr.d.ts +46 -0
- package/dist/core/i18n/index.d.ts +8 -0
- package/dist/core/i18n/it.d.ts +46 -0
- package/dist/core/i18n/zh.d.ts +46 -0
- package/dist/core/index.d.ts +17 -0
- package/dist/core/parse.d.ts +14 -0
- package/dist/core/sort.d.ts +1 -0
- package/dist/core/tree.d.ts +28 -0
- package/dist/core/types.d.ts +46 -0
- package/dist/inandu-grid-vue.cjs +3 -0
- package/dist/inandu-grid-vue.js +1892 -0
- package/dist/index.d.ts +11 -0
- package/dist/style.css +358 -0
- package/dist/utils/exporters.d.ts +29 -0
- package/dist/utils/measureColumn.d.ts +15 -0
- package/dist/utils/translate.d.ts +10 -0
- package/package.json +90 -4
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
CHANGED
|
@@ -1,3 +1,159 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# inandu-grid-vue
|
|
2
|
+
|
|
3
|
+
**A lightweight Vue 3 data grid with the essentials other grids gate behind a paid enterprise
|
|
4
|
+
licence — row grouping, aggregates, inline editing and Excel-compatible export — fully MIT.** The
|
|
5
|
+
Vue port of [`@inandu-solutions/grid-angular`](https://github.com/inandusolutions/inandu-grid),
|
|
6
|
+
kept in sync feature-for-feature by hand (and with its React sibling,
|
|
7
|
+
[`@inandu-solutions/grid-react`](https://github.com/inandusolutions/inandu-grid-react)).
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/@inandu-solutions/grid-vue)
|
|
10
|
+
[](https://github.com/inandusolutions/inandu-grid-vue/actions/workflows/ci.yml)
|
|
11
|
+
[](LICENSE)
|
|
12
|
+

|
|
13
|
+
[](https://inandusolutions.github.io/inandu-grid-vue/)
|
|
14
|
+
[](https://stackblitz.com/github/inandusolutions/inandu-grid-vue/tree/main/examples/stackblitz)
|
|
15
|
+
|
|
16
|
+
## Try it in 30 seconds
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @inandu-solutions/grid-vue
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```vue
|
|
23
|
+
<script setup lang="ts">
|
|
24
|
+
import { InanduGrid, type InanduGridColumn } from '@inandu-solutions/grid-vue';
|
|
25
|
+
import '@inandu-solutions/grid-vue/style.css';
|
|
26
|
+
|
|
27
|
+
const rows = [{ name: 'Ada', age: 36 }, { name: 'Alan', age: 41 }];
|
|
28
|
+
const columns: InanduGridColumn[] = [{ field: 'name', headerText: 'Name' }, { field: 'age', headerText: 'Age', type: 'number' }];
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<!-- sorting + filtering are on by default -->
|
|
33
|
+
<InanduGrid :rows="rows" :columns="columns" :page-size="25" />
|
|
34
|
+
</template>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- **▶️ [Live demo](https://inandusolutions.github.io/inandu-grid-vue/)** — try every feature in the browser.
|
|
38
|
+
- **⚡ [Edit in StackBlitz](https://stackblitz.com/github/inandusolutions/inandu-grid-vue/tree/main/examples/stackblitz)** —
|
|
39
|
+
installs `@inandu-solutions/grid-vue` from npm; edit `src/App.vue` and it updates live ([source](examples/stackblitz)).
|
|
40
|
+
- **📦 [`@inandu-solutions/grid-vue` on npm](https://www.npmjs.com/package/@inandu-solutions/grid-vue)**
|
|
41
|
+
(MIT) — `0.x` while the API settles; expect breaking changes between minors until `1.0.0`.
|
|
42
|
+
|
|
43
|
+
## Who is this for?
|
|
44
|
+
|
|
45
|
+
- **CRUD / business apps** that need sortable, filterable, editable tables without pulling in a
|
|
46
|
+
full enterprise grid framework.
|
|
47
|
+
- **Admin dashboards** that need grouping, aggregates and CSV/Excel/PDF export out of the box.
|
|
48
|
+
- **Data-heavy Vue apps** that need virtual scroll for large datasets, without the bundle size of a
|
|
49
|
+
kitchen-sink grid.
|
|
50
|
+
|
|
51
|
+
**When not to use it:** if you need pivot tables or integrated charting built into the grid itself,
|
|
52
|
+
this isn't that — see [Not included](#not-included) below.
|
|
53
|
+
|
|
54
|
+
## Angular and React versions
|
|
55
|
+
|
|
56
|
+
[`inandu-grid`](https://github.com/inandusolutions/inandu-grid) is the original, feature-complete,
|
|
57
|
+
MIT-licensed Angular grid this repo is ported from, and
|
|
58
|
+
[`inandu-grid-react`](https://github.com/inandusolutions/inandu-grid-react) is its React port — same
|
|
59
|
+
feature set, same core logic, adapted for Vue's composition API (`computed`/`shallowRef`, SFCs,
|
|
60
|
+
scoped slots, emitted events) instead of Angular signals or React hooks.
|
|
61
|
+
|
|
62
|
+
## Not included
|
|
63
|
+
|
|
64
|
+
Deliberately *not* a kitchen sink: no pivoting and no integrated charts — those stay out of scope
|
|
65
|
+
so the core stays small and auditable. Everything else on this page (grouping, aggregates, editing,
|
|
66
|
+
export, virtual scroll) is included, free, no enterprise tier.
|
|
67
|
+
|
|
68
|
+
## Commercial add-ons
|
|
69
|
+
|
|
70
|
+
`@inandu-solutions/grid-pro-vue` *(private, paid, not released yet)* — the Vue port of
|
|
71
|
+
`@inandu-solutions/grid-pro`, depends on this package the same way grid-pro depends on grid-angular.
|
|
72
|
+
|
|
73
|
+
## Features
|
|
74
|
+
|
|
75
|
+
**Feature-complete with grid-angular and grid-react.** The framework-agnostic core (sorting,
|
|
76
|
+
filtering, aggregation, export, i18n) is ported from grid-angular's
|
|
77
|
+
[`core/`](https://github.com/inandusolutions/inandu-grid/tree/main/projects/inandu-grid/src/lib/core)
|
|
78
|
+
folder and kept in sync by hand across the three repos. The Vue-specific layer — the
|
|
79
|
+
[`<InanduGrid>`](#api-shape) component and the [`useInanduGrid()`](#api-shape) headless
|
|
80
|
+
composable — covers:
|
|
81
|
+
|
|
82
|
+
- Sorting — single-column, or multi-column via shift-click
|
|
83
|
+
- Free-text search and per-column filtering, plus an `extra-row-filter` escape hatch for your own predicates
|
|
84
|
+
- Pagination, single-column grouping with aggregates, row selection
|
|
85
|
+
- CSV / Excel (`.xls`) / PDF export, and print
|
|
86
|
+
- i18n — 5 built-in languages via a `lang` prop
|
|
87
|
+
- Inline row editing, creation and deletion, with validation (required / min / max / pattern / custom / async)
|
|
88
|
+
- Excel-style Ctrl+C / Ctrl+V clipboard copy/paste
|
|
89
|
+
- Runtime column show/hide, sticky (pinned left/right) columns, drag-reorder
|
|
90
|
+
- Column resize (drag a header's handle) and autosize (double-click it to fit content)
|
|
91
|
+
- Row drag-reorder
|
|
92
|
+
- Tree data (`tree-children-key`) — display and expand only, no inline editing/drag/clipboard on
|
|
93
|
+
tree rows, same restriction as grid-angular
|
|
94
|
+
- Master-detail — a `#detail="{ row }"` slot (or a `renderDetail` render-function prop)
|
|
95
|
+
- Custom cell / header / edit-control rendering per column — `#cell-<field>`, `#header-<field>` and
|
|
96
|
+
`#editor-<field>` scoped slots, or `renderCell` / `renderHeader` / `renderEditor` render functions
|
|
97
|
+
on the column definition — without losing sorting, resizing, or validation
|
|
98
|
+
- Excel-style cell range selection (`cell-range-selection`, `multi-range`) — click-and-drag or
|
|
99
|
+
shift-click across cells to select a rectangular block; `Ctrl+C` copies the whole range as TSV
|
|
100
|
+
when `clipboard` is also on
|
|
101
|
+
- Row virtualization (`virtual-scroll`) for large datasets
|
|
102
|
+
|
|
103
|
+
Two things work slightly differently from grid-angular because they need a real browser layout
|
|
104
|
+
engine that a unit-test environment can't provide: virtual scroll's row height isn't
|
|
105
|
+
auto-measured — pass `virtual-row-height` explicitly — and autosize's content measurement itself is
|
|
106
|
+
trusted (ported verbatim, same DOM APIs) rather than end-to-end tested; see
|
|
107
|
+
[`measureColumn.ts`](src/utils/measureColumn.ts)'s doc comment for exactly what its test suite does
|
|
108
|
+
and doesn't cover.
|
|
109
|
+
|
|
110
|
+
## API shape
|
|
111
|
+
|
|
112
|
+
```vue
|
|
113
|
+
<script setup lang="ts">
|
|
114
|
+
import { useTemplateRef } from 'vue';
|
|
115
|
+
import { InanduGrid, useInanduGrid, type InanduGridRowSave } from '@inandu-solutions/grid-vue';
|
|
116
|
+
import '@inandu-solutions/grid-vue/style.css'; // optional default styling — skip it and bring your own
|
|
117
|
+
|
|
118
|
+
// Component: batteries-included table. The grid never mutates `rows` — events hand you the change.
|
|
119
|
+
function onRowSave({ row, values }: InanduGridRowSave) {
|
|
120
|
+
rows.value = rows.value.map(r => (r === row ? { ...r, ...values } : r));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Its headless engine is exposed on a template ref, for programmatic control.
|
|
124
|
+
const gridRef = useTemplateRef('grid');
|
|
125
|
+
const sortByName = () => gridRef.value?.grid.toggleSort('name');
|
|
126
|
+
|
|
127
|
+
// Composable: headless — bring your own markup. Pass a getter to follow reactive data; every
|
|
128
|
+
// piece of state is a reactive getter (`headless.visibleRows`, no `.value`).
|
|
129
|
+
const headless = useInanduGrid(() => ({ rows: rows.value, columns, pageSize: 25 }));
|
|
130
|
+
</script>
|
|
131
|
+
|
|
132
|
+
<template>
|
|
133
|
+
<InanduGrid ref="grid" :rows="rows" :columns="columns" selectable @row-save="onRowSave" @selection-change="selected = $event">
|
|
134
|
+
<template #cell-status="{ value }"><StatusBadge :status="value" /></template>
|
|
135
|
+
<template #detail="{ row }"><OrderLines :order="row" /></template>
|
|
136
|
+
</InanduGrid>
|
|
137
|
+
</template>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Events: `selection-change`, `row-save`, `row-create`, `row-delete`, `rows-delete`, `cells-paste`,
|
|
141
|
+
`row-order-change`, `cell-range-change`, `cell-ranges-change`.
|
|
142
|
+
|
|
143
|
+
## Development
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
npm install
|
|
147
|
+
npm test # Vitest + Vue Testing Library
|
|
148
|
+
npm run typecheck # vue-tsc --noEmit
|
|
149
|
+
npm run build # library build (dist/)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Contributing
|
|
153
|
+
|
|
154
|
+
Issues and PRs welcome. Please read [`CONTRIBUTING.md`](CONTRIBUTING.md) first, and note the
|
|
155
|
+
[Code of Conduct](.github/CODE_OF_CONDUCT.md). Security reports: [`.github/SECURITY.md`](.github/SECURITY.md).
|
|
156
|
+
|
|
157
|
+
## License
|
|
158
|
+
|
|
159
|
+
MIT © [Inandu SAS](https://www.inandu.com/)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { InanduGridRow } from '../core';
|
|
2
|
+
import { RowContext } from './internal';
|
|
3
|
+
/** One data row — its own read-only cells, or (while it's the row being edited) `editableColumns` as controls bound to the shared draft, plus a trailing Edit/Save/Cancel/Delete actions cell when `hasRowActions`. */
|
|
4
|
+
type __VLS_Props = {
|
|
5
|
+
ctx: RowContext;
|
|
6
|
+
row: InanduGridRow;
|
|
7
|
+
rowIndex: number;
|
|
8
|
+
/** Adds a leading drag-handle `<td>` and wires the whole row for drag-and-drop reordering — only in the flat, non-grouped render path, same restriction grid-angular's `rowReorder` has. */
|
|
9
|
+
hasRowDragHandle?: boolean;
|
|
10
|
+
isDragOverRow?: boolean;
|
|
11
|
+
/** Adds a leading expand/collapse toggle `<td>` and (while expanded) a full-width detail row right below — only in the flat, non-grouped render path, same restriction grid-angular's `hasMasterDetail` has. */
|
|
12
|
+
hasMasterDetail?: boolean;
|
|
13
|
+
isRowExpanded?: boolean;
|
|
14
|
+
};
|
|
15
|
+
declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
16
|
+
rowDragStart: () => any;
|
|
17
|
+
rowDragOver: () => any;
|
|
18
|
+
rowDragLeave: () => any;
|
|
19
|
+
rowDrop: () => any;
|
|
20
|
+
toggleExpanded: () => any;
|
|
21
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
22
|
+
onRowDragStart?: (() => any) | undefined;
|
|
23
|
+
onRowDragOver?: (() => any) | undefined;
|
|
24
|
+
onRowDragLeave?: (() => any) | undefined;
|
|
25
|
+
onRowDrop?: (() => any) | undefined;
|
|
26
|
+
onToggleExpanded?: (() => any) | undefined;
|
|
27
|
+
}>, {
|
|
28
|
+
hasRowDragHandle: boolean;
|
|
29
|
+
isDragOverRow: boolean;
|
|
30
|
+
hasMasterDetail: boolean;
|
|
31
|
+
isRowExpanded: boolean;
|
|
32
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
33
|
+
declare const _default: typeof __VLS_export;
|
|
34
|
+
export default _default;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { InanduGridColumn } from '../composables/useInanduGrid';
|
|
2
|
+
import { Translator } from './internal';
|
|
3
|
+
/** One editable cell's control, bound to the shared row draft in the same *raw control* shape `parseDraftValue()` expects (a string for text/number/date, a boolean for the checkbox) — plus its inline validation message, if any. */
|
|
4
|
+
type __VLS_Props = {
|
|
5
|
+
column: InanduGridColumn;
|
|
6
|
+
value: unknown;
|
|
7
|
+
error: string | undefined;
|
|
8
|
+
t: Translator;
|
|
9
|
+
};
|
|
10
|
+
declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
11
|
+
change: (value: unknown) => any;
|
|
12
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
13
|
+
onChange?: ((value: unknown) => any) | undefined;
|
|
14
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { InanduGridColumnFilterValue } from '../core';
|
|
2
|
+
import { InanduGridColumn } from '../composables/useInanduGrid';
|
|
3
|
+
import { Translator } from './internal';
|
|
4
|
+
/** One filter control per column type, all working off the same `InanduGridColumnFilterValue` shape the core understands. */
|
|
5
|
+
type __VLS_Props = {
|
|
6
|
+
column: InanduGridColumn;
|
|
7
|
+
value: InanduGridColumnFilterValue | undefined;
|
|
8
|
+
t: Translator;
|
|
9
|
+
};
|
|
10
|
+
declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
11
|
+
change: (patch: Partial<InanduGridColumnFilterValue>) => any;
|
|
12
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
13
|
+
onChange?: ((patch: Partial<InanduGridColumnFilterValue>) => any) | undefined;
|
|
14
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { VNodeChild } from 'vue';
|
|
2
|
+
import { InanduGridColumnFilterValue, InanduGridRow } from '../core';
|
|
3
|
+
import { InanduCellRenderContext, InanduEditRenderContext, InanduGridCellPaste, InanduGridColumn, InanduGridRowSave, InanduHeaderRenderContext } from '../composables/useInanduGrid';
|
|
4
|
+
import { InanduGridCellRangeSelection } from './types';
|
|
5
|
+
type __VLS_Props = {
|
|
6
|
+
rows: InanduGridRow[];
|
|
7
|
+
columns: InanduGridColumn[];
|
|
8
|
+
/** Drives number/date formatting (`Intl`-based). Default: 'en'. */
|
|
9
|
+
locale?: string;
|
|
10
|
+
/** Drives built-in UI string translation (one of `INANDU_GRID_TRANSLATIONS`'s keys). Default: `locale`'s primary subtag. */
|
|
11
|
+
lang?: string;
|
|
12
|
+
/** 0 (default) disables pagination — every filtered/sorted row renders. Ignored while grouped. */
|
|
13
|
+
pageSize?: number;
|
|
14
|
+
/** Adds a checkbox column with row + select-all selection. Default: false. */
|
|
15
|
+
selectable?: boolean;
|
|
16
|
+
/** Adds a CSV/Excel/PDF export toolbar above the table. Default: false. */
|
|
17
|
+
exportable?: boolean;
|
|
18
|
+
/** Base filename (without extension) for exports. Default: 'inandu-grid'. */
|
|
19
|
+
exportFilenameBase?: string;
|
|
20
|
+
/** Adds a per-row "Delete" button. Default: false. */
|
|
21
|
+
deletable?: boolean;
|
|
22
|
+
/** `window.confirm()`-gates a single row's delete. Unset: deletes immediately. */
|
|
23
|
+
deleteConfirmMessage?: string;
|
|
24
|
+
/** `window.confirm()`-gates the "Delete selected" bulk action (shown when `selectable && deletable` with at least one row selected). Unset: deletes immediately. */
|
|
25
|
+
bulkDeleteConfirmMessage?: string;
|
|
26
|
+
/** Adds an "Add row" trigger with a blank draft row. Default: false. Has no effect unless at least one column is `editable`. */
|
|
27
|
+
creatable?: boolean;
|
|
28
|
+
/** Opts into `Ctrl+C`/`Ctrl+V` cell copy/paste (Excel-style TSV). Default: false. */
|
|
29
|
+
clipboard?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Opt-in Excel-style range selection — click-and-drag (or shift-click, without dragging) across
|
|
32
|
+
* cells in the flat, non-grouped, non-tree, non-virtualized render path (same restriction
|
|
33
|
+
* `rowReorder`/`clipboard` already document) selects a rectangular block of cells, highlighted via
|
|
34
|
+
* `.inandu-cell-range-selected`. Off by default. When `clipboard` is *also* on, `Ctrl+C` copies
|
|
35
|
+
* the *entire* selected range as TSV instead of just the focused cell — otherwise this is purely a
|
|
36
|
+
* selection/highlight feature with no built-in side effect; the `cell-range-change`/
|
|
37
|
+
* `cell-ranges-change` events are how a consumer observes what's currently selected.
|
|
38
|
+
*/
|
|
39
|
+
cellRangeSelection?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Lets a Ctrl/Cmd-drag (or Ctrl/Cmd-click) *add* another rectangle to the selection instead of
|
|
42
|
+
* replacing it, the same convention spreadsheets use. A plain click still resets to one
|
|
43
|
+
* rectangle. Only meaningful with `cellRangeSelection` on. `cell-range-change` keeps reporting
|
|
44
|
+
* the *active* (last) rectangle; `cell-ranges-change` reports the whole list. `Ctrl+C` copies
|
|
45
|
+
* only the active rectangle. Default: false.
|
|
46
|
+
*/
|
|
47
|
+
multiRange?: boolean;
|
|
48
|
+
/** Adds a "Columns" toolbar button + popup letting the user show/hide individual columns at runtime. Default: false. */
|
|
49
|
+
columnToggle?: boolean;
|
|
50
|
+
/** Adds a per-row drag handle to reorder rows. Default: false. Auto-disabled while grouped, same as grid-angular. */
|
|
51
|
+
rowReorder?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Turns on tree mode: the field on each row holding its child rows (a nested array of the same
|
|
54
|
+
* shape). `rows` is then the root rows. Auto-disabled while grouped. Tree rows are display +
|
|
55
|
+
* expand only — inline editing, drag-reorder and clipboard don't apply to them, same as
|
|
56
|
+
* grid-angular.
|
|
57
|
+
*/
|
|
58
|
+
treeChildrenKey?: string;
|
|
59
|
+
/** Initial expand state for tree mode. Default: `'none'`. */
|
|
60
|
+
treeDefaultExpanded?: 'none' | 'all' | number;
|
|
61
|
+
/**
|
|
62
|
+
* Enables master-detail as a render function: renders a leading expand/collapse toggle per row,
|
|
63
|
+
* and (while expanded) a full-width detail row right below it, with whatever this returns. The
|
|
64
|
+
* `#detail="{ row }"` slot does the same template-side (and wins when both are set). Auto-disabled
|
|
65
|
+
* while grouped, same as grid-angular's `detailTemplate`/`hasMasterDetail`. Unset (default): off.
|
|
66
|
+
*/
|
|
67
|
+
renderDetail?: (row: InanduGridRow) => VNodeChild;
|
|
68
|
+
/** 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. */
|
|
69
|
+
singleDetailExpand?: boolean;
|
|
70
|
+
/** An extra per-row predicate ANDed onto the free-text + column filters — same as grid-angular's `extraRowFilter`. Lets a caller layer its own filtering (e.g. an advanced-filter query) on top of the grid's own. Unset: no extra filtering. */
|
|
71
|
+
extraRowFilter?: (row: InanduGridRow) => boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Opt-in row virtualization for large datasets — only rows scrolled into view (plus a small
|
|
74
|
+
* overscan runway) are actually mounted. Bypasses pagination entirely, same as grouping.
|
|
75
|
+
* Auto-disabled while grouped (this port doesn't interleave group headers into the virtualized
|
|
76
|
+
* window the way grid-angular does); also disables master-detail, row drag-reorder, tree data,
|
|
77
|
+
* and the totals `<tfoot>`, same restrictions grid-angular's `virtualScroll` has. Default: false.
|
|
78
|
+
*/
|
|
79
|
+
virtualScroll?: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Fixed row height (px) the virtualization math uses to compute scroll position and how many
|
|
82
|
+
* rows to render. Unlike grid-angular, this port doesn't auto-measure a rendered row's real
|
|
83
|
+
* height — pass the actual rendered row height for correct scrolling. Default: 40.
|
|
84
|
+
*/
|
|
85
|
+
virtualRowHeight?: number;
|
|
86
|
+
/** The scrollable viewport's own height (px) — only used while `virtualScroll`. Default: 400. */
|
|
87
|
+
height?: number;
|
|
88
|
+
/** 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. */
|
|
89
|
+
overscan?: number;
|
|
90
|
+
/**
|
|
91
|
+
* Double-click a column's resize handle to fit its width to its widest currently-rendered value
|
|
92
|
+
* (header included). Measures real rendered text width via the DOM (`measureColumnContentWidth`)
|
|
93
|
+
* — like grid-angular's own autosize, this only measures what's actually mounted (one page, or
|
|
94
|
+
* the virtual window), not the full dataset. Default: false.
|
|
95
|
+
*/
|
|
96
|
+
autosize?: boolean;
|
|
97
|
+
};
|
|
98
|
+
type __VLS_Slots = {
|
|
99
|
+
/** Custom cell content for column `<field>`: `#cell-name="{ value, row, field }"`. */
|
|
100
|
+
[key: `cell-${string}`]: (ctx: InanduCellRenderContext) => VNodeChild;
|
|
101
|
+
/** Custom header label for column `<field>`: `#header-name="{ title, field }"`. */
|
|
102
|
+
[key: `header-${string}`]: (ctx: InanduHeaderRenderContext) => VNodeChild;
|
|
103
|
+
/** Custom editor for editable column `<field>`: `#editor-name="{ value, setValue, error, row, field }"`. */
|
|
104
|
+
[key: `editor-${string}`]: (ctx: InanduEditRenderContext) => VNodeChild;
|
|
105
|
+
/** Master-detail content for an expanded row — its presence turns master-detail on. */
|
|
106
|
+
detail?: (ctx: {
|
|
107
|
+
row: InanduGridRow;
|
|
108
|
+
}) => VNodeChild;
|
|
109
|
+
};
|
|
110
|
+
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {
|
|
111
|
+
grid: {
|
|
112
|
+
readonly visibleColumns: InanduGridColumn[];
|
|
113
|
+
readonly allColumns: InanduGridColumn[];
|
|
114
|
+
stickyOffset: (field: string) => number;
|
|
115
|
+
stickyOffsetRight: (field: string) => number;
|
|
116
|
+
columnPinnedSide: (field: string) => import('..').InanduColumnStickySide | undefined;
|
|
117
|
+
setColumnPinned: (field: string, side: import('..').InanduColumnStickySide | undefined) => void;
|
|
118
|
+
readonly hideableColumns: InanduGridColumn[];
|
|
119
|
+
isColumnHidden: (field: string) => boolean;
|
|
120
|
+
toggleColumnVisibility: (field: string) => void;
|
|
121
|
+
setColumnOrder: (fields: readonly string[]) => void;
|
|
122
|
+
readonly draggingField: string | undefined;
|
|
123
|
+
onColumnDragStart: (field: string) => void;
|
|
124
|
+
onColumnDrop: (targetField: string) => void;
|
|
125
|
+
effectiveWidth: (field: string) => number;
|
|
126
|
+
isColumnResized: (field: string) => boolean;
|
|
127
|
+
setColumnWidth: (field: string, width: number) => void;
|
|
128
|
+
readonly draggingRow: InanduGridRow | undefined;
|
|
129
|
+
onRowDragStart: (row: InanduGridRow) => void;
|
|
130
|
+
onRowDrop: (targetRow: InanduGridRow) => void;
|
|
131
|
+
readonly hasTreeData: boolean;
|
|
132
|
+
readonly treeRows: import('..').TreeVisibleRow<InanduGridRow>[];
|
|
133
|
+
isTreeRowExpanded: (row: InanduGridRow) => boolean;
|
|
134
|
+
toggleTreeRow: (row: InanduGridRow) => void;
|
|
135
|
+
setAllTreeRowsExpanded: (expanded: boolean) => void;
|
|
136
|
+
isRowExpanded: (row: InanduGridRow) => boolean;
|
|
137
|
+
toggleRowExpanded: (row: InanduGridRow) => void;
|
|
138
|
+
readonly hasVirtualScroll: boolean;
|
|
139
|
+
readonly visibleRows: InanduGridRow[];
|
|
140
|
+
readonly exportRows: InanduGridRow[];
|
|
141
|
+
readonly sortedRows: InanduGridRow[];
|
|
142
|
+
readonly filteredRowCount: number;
|
|
143
|
+
readonly locale: string;
|
|
144
|
+
readonly sortCriteria: import('..').InanduGridSort[];
|
|
145
|
+
setSort: (criteria: import('..').InanduGridSort[]) => void;
|
|
146
|
+
toggleSort: (field: string, additive?: boolean) => void;
|
|
147
|
+
sortDirectionFor: (field: string) => "asc" | "desc" | undefined;
|
|
148
|
+
sortPriorityFor: (field: string) => number | undefined;
|
|
149
|
+
readonly filterValues: Record<string, InanduGridColumnFilterValue>;
|
|
150
|
+
setFilterValue: (field: string, value: InanduGridColumnFilterValue) => void;
|
|
151
|
+
clearAllFilters: () => void;
|
|
152
|
+
readonly filterQuery: string;
|
|
153
|
+
setFilterQuery: (query: string) => void;
|
|
154
|
+
readonly page: number;
|
|
155
|
+
setPage: (next: number) => void;
|
|
156
|
+
readonly pageCount: number;
|
|
157
|
+
readonly groupByField: string | undefined;
|
|
158
|
+
setGroupByField: (field: string | undefined) => void;
|
|
159
|
+
readonly groups: import('..').InanduGridGroup[] | null;
|
|
160
|
+
readonly totals: Record<string, number>;
|
|
161
|
+
readonly selectedRows: Set<InanduGridRow>;
|
|
162
|
+
isRowSelected: (row: InanduGridRow) => boolean;
|
|
163
|
+
toggleRowSelection: (row: InanduGridRow) => void;
|
|
164
|
+
readonly allSelected: boolean;
|
|
165
|
+
readonly someSelected: boolean;
|
|
166
|
+
toggleSelectAll: () => void;
|
|
167
|
+
clearSelection: () => void;
|
|
168
|
+
readonly editableColumns: InanduGridColumn[];
|
|
169
|
+
readonly editingRow: InanduGridRow | undefined;
|
|
170
|
+
readonly isAddingRow: boolean;
|
|
171
|
+
readonly rowDraft: Record<string, unknown>;
|
|
172
|
+
readonly fieldErrors: Record<string, string>;
|
|
173
|
+
readonly isValidating: boolean;
|
|
174
|
+
isEditingRow: (row: InanduGridRow) => boolean;
|
|
175
|
+
isAnotherRowEditing: (row: InanduGridRow) => boolean;
|
|
176
|
+
startEditingRow: (row: InanduGridRow) => void;
|
|
177
|
+
cancelRowEdit: () => void;
|
|
178
|
+
setRowDraftValue: (field: string, value: unknown) => void;
|
|
179
|
+
saveRow: (row: InanduGridRow) => Promise<void>;
|
|
180
|
+
deleteRow: (row: InanduGridRow) => void;
|
|
181
|
+
deleteSelectedRows: () => void;
|
|
182
|
+
startAddingRow: () => void;
|
|
183
|
+
cancelAddRow: () => void;
|
|
184
|
+
saveNewRow: () => Promise<void>;
|
|
185
|
+
validateCell: (column: InanduGridColumn, value: unknown, row?: Record<string, unknown>) => string | null;
|
|
186
|
+
copyCellText: (rowIndex: number, field: string) => string;
|
|
187
|
+
pasteAt: (anchorRowIndex: number, anchorField: string, text: string) => void;
|
|
188
|
+
};
|
|
189
|
+
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
190
|
+
selectionChange: (selectedRows: InanduGridRow[]) => any;
|
|
191
|
+
rowSave: (event: InanduGridRowSave) => any;
|
|
192
|
+
rowCreate: (values: Record<string, unknown>) => any;
|
|
193
|
+
rowDelete: (row: InanduGridRow) => any;
|
|
194
|
+
rowsDelete: (rows: InanduGridRow[]) => any;
|
|
195
|
+
cellsPaste: (updates: InanduGridCellPaste[]) => any;
|
|
196
|
+
cellRangeChange: (selection: InanduGridCellRangeSelection | undefined) => any;
|
|
197
|
+
cellRangesChange: (selections: InanduGridCellRangeSelection[]) => any;
|
|
198
|
+
rowOrderChange: (rows: InanduGridRow[]) => any;
|
|
199
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
200
|
+
onSelectionChange?: ((selectedRows: InanduGridRow[]) => any) | undefined;
|
|
201
|
+
onRowSave?: ((event: InanduGridRowSave) => any) | undefined;
|
|
202
|
+
onRowCreate?: ((values: Record<string, unknown>) => any) | undefined;
|
|
203
|
+
onRowDelete?: ((row: InanduGridRow) => any) | undefined;
|
|
204
|
+
onRowsDelete?: ((rows: InanduGridRow[]) => any) | undefined;
|
|
205
|
+
onCellsPaste?: ((updates: InanduGridCellPaste[]) => any) | undefined;
|
|
206
|
+
onCellRangeChange?: ((selection: InanduGridCellRangeSelection | undefined) => any) | undefined;
|
|
207
|
+
onCellRangesChange?: ((selections: InanduGridCellRangeSelection[]) => any) | undefined;
|
|
208
|
+
onRowOrderChange?: ((rows: InanduGridRow[]) => any) | undefined;
|
|
209
|
+
}>, {
|
|
210
|
+
locale: string;
|
|
211
|
+
pageSize: number;
|
|
212
|
+
treeDefaultExpanded: number | "none" | "all";
|
|
213
|
+
exportFilenameBase: string;
|
|
214
|
+
virtualRowHeight: number;
|
|
215
|
+
height: number;
|
|
216
|
+
overscan: number;
|
|
217
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
218
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
219
|
+
declare const _default: typeof __VLS_export;
|
|
220
|
+
export default _default;
|
|
221
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
222
|
+
new (): {
|
|
223
|
+
$slots: S;
|
|
224
|
+
};
|
|
225
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { CSSProperties, PropType, VNodeChild } from 'vue';
|
|
2
|
+
import { InanduGridRow } from '../core';
|
|
3
|
+
import { InanduGridColumn } from '../composables/useInanduGrid';
|
|
4
|
+
import { InanduGridMessageKey } from '../utils/translate';
|
|
5
|
+
export type Translator = (key: InanduGridMessageKey, params?: Record<string, string | number>) => string;
|
|
6
|
+
/** Renders whatever VNode children it's handed — how a slot or a column's `renderCell`/`renderHeader`/`renderEditor` result is mounted from inside a template. */
|
|
7
|
+
export declare const RenderNodes: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
|
|
8
|
+
nodes: {
|
|
9
|
+
type: PropType<VNodeChild>;
|
|
10
|
+
default: null;
|
|
11
|
+
};
|
|
12
|
+
}>, () => never, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
|
|
13
|
+
nodes: {
|
|
14
|
+
type: PropType<VNodeChild>;
|
|
15
|
+
default: null;
|
|
16
|
+
};
|
|
17
|
+
}>> & Readonly<{}>, {
|
|
18
|
+
nodes: VNodeChild;
|
|
19
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
20
|
+
/**
|
|
21
|
+
* Everything a `<DataRow>` needs from the grid, bundled into one prop rather than ~30 — the Vue
|
|
22
|
+
* counterpart of the React port's spread `rowProps`. Built once per render by `<InanduGrid>`.
|
|
23
|
+
*/
|
|
24
|
+
export interface RowContext {
|
|
25
|
+
columns: InanduGridColumn[];
|
|
26
|
+
t: Translator;
|
|
27
|
+
selectable: boolean;
|
|
28
|
+
selectColumnStyle: CSSProperties | undefined;
|
|
29
|
+
columnStyle: (column: InanduGridColumn) => CSSProperties;
|
|
30
|
+
isRowSelected: (row: InanduGridRow) => boolean;
|
|
31
|
+
toggleRowSelection: (row: InanduGridRow) => void;
|
|
32
|
+
hasRowActions: boolean;
|
|
33
|
+
editableColumnCount: number;
|
|
34
|
+
isEditingRow: (row: InanduGridRow) => boolean;
|
|
35
|
+
isAnotherRowEditing: (row: InanduGridRow) => boolean;
|
|
36
|
+
startEditingRow: (row: InanduGridRow) => void;
|
|
37
|
+
cancelRowEdit: () => void;
|
|
38
|
+
saveRow: (row: InanduGridRow) => void;
|
|
39
|
+
deleteRow: (row: InanduGridRow) => void;
|
|
40
|
+
deletable: boolean;
|
|
41
|
+
rowDraft: Record<string, unknown>;
|
|
42
|
+
fieldErrors: Record<string, string>;
|
|
43
|
+
isValidating: boolean;
|
|
44
|
+
setRowDraftValue: (field: string, value: unknown) => void;
|
|
45
|
+
/** A cell's display content: the `#cell-<field>` slot, else the column's `renderCell`, else the formatted value. */
|
|
46
|
+
cellContent: (column: InanduGridColumn, row: InanduGridRow) => VNodeChild;
|
|
47
|
+
/** A custom editor (`#editor-<field>` slot or `renderEditor`), or `undefined` to fall back to the built-in `<EditCell>`. */
|
|
48
|
+
editorContent: (column: InanduGridColumn, row: InanduGridRow) => VNodeChild | undefined;
|
|
49
|
+
/** Master-detail content for an expanded row (`#detail` slot or `renderDetail`). */
|
|
50
|
+
detailContent: (row: InanduGridRow) => VNodeChild;
|
|
51
|
+
/** Adds the `tabindex` `onTableKeyDown` resolves a Ctrl+C/Ctrl+V onto — `data-row-index`/`data-field` are always present (flat, non-grouped render path only), same as grid-angular. */
|
|
52
|
+
clipboard: boolean;
|
|
53
|
+
/** Marks cells `.inandu-cell-range-selected` and wires the drag/shift-click gesture — only in the flat, non-grouped, non-tree, non-virtualized render path, same restriction grid-angular's `cellRangeSelection` has. */
|
|
54
|
+
cellRangeSelection: boolean;
|
|
55
|
+
isCellInRange: (rowIndex: number, colIndex: number) => boolean;
|
|
56
|
+
onCellRangeMouseDown: (event: MouseEvent, rowIndex: number, colIndex: number) => void;
|
|
57
|
+
onCellRangeMouseEnter: (rowIndex: number, colIndex: number) => void;
|
|
58
|
+
/** Column count a full-width row (`colspan`) must span: `columns.length` plus every leading/trailing extra column. */
|
|
59
|
+
extraColumnCount: number;
|
|
60
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { InanduGridRow } from '../core';
|
|
2
|
+
/** The currently selected cell range — see `<InanduGrid cell-range-selection>` and its `cell-range-change` event. `rows`/`fields` are the full row objects and field names spanning the selected rectangle, in `visibleRows`/`visibleColumns` order. */
|
|
3
|
+
export interface InanduGridCellRangeSelection {
|
|
4
|
+
rows: InanduGridRow[];
|
|
5
|
+
fields: string[];
|
|
6
|
+
}
|