@keenmate/web-grid 1.0.4 → 1.0.5
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/README.md +212 -35
- package/dist/web-grid.js +1197 -1168
- package/dist/web-grid.umd.js +63 -70
- package/package.json +1 -1
- package/src/css/_variables.css +1 -1
package/README.md
CHANGED
|
@@ -2,62 +2,239 @@
|
|
|
2
2
|
|
|
3
3
|
A feature-rich, framework-agnostic data grid web component built with TypeScript. Sorting, filtering, pagination, inline editing (8 editor types), cell range selection, clipboard support, row toolbar, context menus, frozen columns, column reorder/resize, fill handle, virtual scroll, dark mode, and full CSS variable theming — all in a Shadow DOM encapsulated `<web-grid>` element.
|
|
4
4
|
|
|
5
|
+
## What's New in v1.0.5
|
|
6
|
+
|
|
7
|
+
- **Context menus flip at screen edges**: Both cell and header context menus now correctly flip to the opposite side when opened near a viewport edge (they were clipping before). Switched the root menu to `strategy: 'fixed'` + `position: fixed` so Floating UI's `flip`/`shift` run in viewport coordinates.
|
|
8
|
+
- **Header submenus are viewport-aware**: Header menu submenus (e.g. Column Visibility) now use Floating UI with `placement: 'right-start'` and `flip` fallbacks, replacing the old CSS-only `left: 100%` positioning. A short hide delay lets the cursor cross the gap between parent item and submenu.
|
|
9
|
+
- **Context menu closes on grid-internal scroll**: The menu now subscribes to both the `'window'` and `'container'` scroll sources. Previously, scrolling within the grid didn't close the menu because scroll events aren't composed across shadow DOM.
|
|
10
|
+
- **Context menu offset flips with placement**: `contextMenuXOffset`/`contextMenuYOffset` are now applied via Floating UI's `offset` middleware (`mainAxis` / `alignmentAxis`), so the gap between cursor and menu stays correct even when the menu flips to `*-end` or `top-*`.
|
|
11
|
+
- **Dropdown selected option readable in dark mode**: The selected option in select/combobox/autocomplete dropdowns no longer renders as pale blue against the dark surface. `--wg-accent-color-light` now falls back to a transparent `color-mix` that blends with the underlying surface in either theme.
|
|
12
|
+
|
|
5
13
|
## What's New in v1.0.4
|
|
6
14
|
|
|
7
15
|
- **Dirty cell/row indicator**: New `isDirtyIndicatorVisible` property (default: `true`). Edited cells show a subtle orange tint + corner triangle; row numbers get an orange left border. Themable via `--wg-dirty-*` variables. Public methods: `isCellDirty()`, `isRowDirty()`.
|
|
8
16
|
- **Dropdown positioning fix**: Fixed dropdown editors appearing offset in shadow DOM by switching from `position: fixed` to `position: absolute`.
|
|
9
17
|
|
|
10
|
-
|
|
18
|
+
## Installation
|
|
11
19
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- **Z-index layer system**: All z-index values now use CSS custom properties (`--wg-z-header`, `--wg-z-frozen`, etc.). Fixes cell selection bleeding through sticky header and frozen header stacking.
|
|
20
|
+
```bash
|
|
21
|
+
npm install @keenmate/web-grid
|
|
22
|
+
```
|
|
16
23
|
|
|
17
|
-
|
|
24
|
+
Or via CDN (no bundler):
|
|
18
25
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
- **Tooltip show delay**: Reduced default from 400ms to 200ms.
|
|
26
|
+
```html
|
|
27
|
+
<script type="module" src="https://unpkg.com/@keenmate/web-grid"></script>
|
|
28
|
+
```
|
|
23
29
|
|
|
24
|
-
##
|
|
30
|
+
## Getting Started
|
|
25
31
|
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
### Step 1 — Import the component
|
|
33
|
+
|
|
34
|
+
Importing the package registers the `<web-grid>` custom element globally. You only need to import it once anywhere in your app.
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
import '@keenmate/web-grid'
|
|
28
38
|
```
|
|
29
39
|
|
|
30
|
-
|
|
40
|
+
For vanilla HTML without a bundler:
|
|
41
|
+
|
|
42
|
+
```html
|
|
43
|
+
<script type="module" src="https://unpkg.com/@keenmate/web-grid"></script>
|
|
44
|
+
```
|
|
31
45
|
|
|
32
|
-
###
|
|
46
|
+
### Step 2 — Drop the element into your markup
|
|
33
47
|
|
|
34
48
|
```html
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
49
|
+
<web-grid id="grid" style="max-height: 400px"></web-grid>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`max-height` (or `height`) on the host is how you control sizing — see [Height Modes](#height-modes).
|
|
53
|
+
|
|
54
|
+
### Step 3 — Assign data and columns
|
|
55
|
+
|
|
56
|
+
The grid reads its configuration from properties on the element, not attributes. Grab a reference and set what you need:
|
|
57
|
+
|
|
58
|
+
```javascript
|
|
59
|
+
const grid = document.getElementById('grid')
|
|
60
|
+
|
|
61
|
+
grid.items = [
|
|
62
|
+
{ id: 1, name: 'Alice', age: 28, department: 'Engineering' },
|
|
63
|
+
{ id: 2, name: 'Bob', age: 34, department: 'Marketing' }
|
|
64
|
+
]
|
|
38
65
|
|
|
39
|
-
|
|
66
|
+
grid.columns = [
|
|
67
|
+
{ field: 'id', title: 'ID', width: '60px' },
|
|
68
|
+
{ field: 'name', title: 'Name', width: '160px' },
|
|
69
|
+
{ field: 'age', title: 'Age', width: '80px', horizontalAlign: 'right' },
|
|
70
|
+
{ field: 'department', title: 'Department', width: '160px' }
|
|
71
|
+
]
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
That's the minimum — a read-only grid with the headers, rows, and columns you defined.
|
|
75
|
+
|
|
76
|
+
### Step 4 — Enable the features you need
|
|
40
77
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
grid.sortMode = 'multi' // Enable multi-column sorting
|
|
53
|
-
</script>
|
|
78
|
+
Turn on whatever the page calls for. Everything is off by default:
|
|
79
|
+
|
|
80
|
+
```javascript
|
|
81
|
+
grid.isStriped = true // alternating row backgrounds
|
|
82
|
+
grid.isHoverable = true // hover highlight
|
|
83
|
+
grid.isRowNumbersVisible = true // leftmost # column
|
|
84
|
+
grid.sortMode = 'multi' // click headers to sort, Ctrl+click to add
|
|
85
|
+
grid.isPageable = true
|
|
86
|
+
grid.pageSize = 25
|
|
87
|
+
grid.isEditable = true
|
|
88
|
+
grid.editTrigger = 'navigate' // Excel-like: type to edit the focused cell
|
|
54
89
|
```
|
|
55
90
|
|
|
56
|
-
###
|
|
91
|
+
### Essential Properties
|
|
92
|
+
|
|
93
|
+
| Property | Type | Purpose |
|
|
94
|
+
|----------|------|---------|
|
|
95
|
+
| `items` | `T[]` | Row data — the only required "content" property |
|
|
96
|
+
| `columns` | `Column<T>[]` | Column definitions with at least a `field` each |
|
|
97
|
+
| `isStriped` / `isHoverable` / `isRowNumbersVisible` | `boolean` | Cosmetic toggles |
|
|
98
|
+
| `sortMode` | `'none' \| 'single' \| 'multi'` | Column sort behavior |
|
|
99
|
+
| `isPageable` + `pageSize` | `boolean` + `number` | Pagination |
|
|
100
|
+
| `isEditable` + `editTrigger` | `boolean` + `EditTrigger` | Enable inline editing and how it starts |
|
|
101
|
+
| `isFilterable` | `boolean` | Per-column filter row under the headers |
|
|
102
|
+
| `mode` | `'read-only' \| 'excel' \| 'input-matrix'` | Presets that set several of the above together |
|
|
103
|
+
|
|
104
|
+
## Common Configurations
|
|
105
|
+
|
|
106
|
+
Short recipes for common setups. Each sets only what's necessary on top of the Step 3 minimum.
|
|
107
|
+
|
|
108
|
+
### Sortable grid
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
grid.sortMode = 'multi' // or 'single'
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Paginated grid with top + bottom pager
|
|
115
|
+
|
|
116
|
+
```javascript
|
|
117
|
+
grid.isPageable = true
|
|
118
|
+
grid.pageSize = 25
|
|
119
|
+
grid.paginationPosition = 'top-center|bottom-center'
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Editable grid (Excel-like navigation)
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
grid.mode = 'excel' // isEditable + editTrigger='navigate' + cellSelectionMode='click'
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Or opt in manually for finer control:
|
|
129
|
+
|
|
130
|
+
```javascript
|
|
131
|
+
grid.isEditable = true
|
|
132
|
+
grid.editTrigger = 'navigate'
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Per-column editors
|
|
136
|
+
|
|
137
|
+
```javascript
|
|
138
|
+
grid.columns = [
|
|
139
|
+
{ field: 'name', title: 'Name', editor: 'text' },
|
|
140
|
+
{ field: 'salary', title: 'Salary', editor: 'number', editorOptions: { min: 0, step: 1000 } },
|
|
141
|
+
{ field: 'department', title: 'Dept', editor: 'select',
|
|
142
|
+
editorOptions: {
|
|
143
|
+
options: [
|
|
144
|
+
{ value: 'eng', label: 'Engineering' },
|
|
145
|
+
{ value: 'sal', label: 'Sales' }
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Height modes
|
|
153
|
+
|
|
154
|
+
The grid's shadow DOM uses `max-height: inherit`, so setting `max-height` on the host controls its internal scroll container:
|
|
57
155
|
|
|
58
156
|
```html
|
|
59
|
-
|
|
60
|
-
<web-grid
|
|
157
|
+
<!-- Container: grid caps at 400px, scrolls internally -->
|
|
158
|
+
<web-grid style="max-height: 400px"></web-grid>
|
|
159
|
+
|
|
160
|
+
<!-- Full height: grid expands with content, page handles scrolling -->
|
|
161
|
+
<web-grid style="height: 100%"></web-grid>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
For full-height mode, also set `tableBorderOnly = true` so the grid doesn't capture wheel events:
|
|
165
|
+
|
|
166
|
+
```javascript
|
|
167
|
+
grid.tableBorderOnly = true
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Header context menu with column hide + visibility submenu
|
|
171
|
+
|
|
172
|
+
```javascript
|
|
173
|
+
grid.headerContextMenu = [
|
|
174
|
+
'sortAsc', 'sortDesc', 'clearSort',
|
|
175
|
+
{ dividerBefore: true },
|
|
176
|
+
'hideColumn', // hide the right-clicked column
|
|
177
|
+
'columnVisibility' // submenu with a toggle per column
|
|
178
|
+
]
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Hide a column programmatically
|
|
182
|
+
|
|
183
|
+
```javascript
|
|
184
|
+
grid.columns.find(c => c.field === 'email').isHidden = true
|
|
185
|
+
grid.columns = [...grid.columns] // reassign to trigger re-render
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Row toolbar
|
|
189
|
+
|
|
190
|
+
```javascript
|
|
191
|
+
grid.isRowToolbarVisible = true
|
|
192
|
+
grid.rowToolbar = ['add', 'delete', 'duplicate', 'moveUp', 'moveDown']
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Master/detail — react to row focus
|
|
196
|
+
|
|
197
|
+
```javascript
|
|
198
|
+
grid.onrowfocus = ({ row, rowIndex }) => {
|
|
199
|
+
showDetailsFor(row)
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Validate a cell before commit
|
|
204
|
+
|
|
205
|
+
```javascript
|
|
206
|
+
grid.columns = [{
|
|
207
|
+
field: 'email',
|
|
208
|
+
title: 'Email',
|
|
209
|
+
editor: 'text',
|
|
210
|
+
beforeCommitCallback: ({ value }) => {
|
|
211
|
+
if (!/^[^@]+@[^@]+$/.test(String(value))) {
|
|
212
|
+
return { valid: false, message: 'Invalid email address' }
|
|
213
|
+
}
|
|
214
|
+
return { valid: true }
|
|
215
|
+
}
|
|
216
|
+
}]
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### TypeScript
|
|
220
|
+
|
|
221
|
+
Full type definitions ship with the package. Import types from the root:
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
import '@keenmate/web-grid'
|
|
225
|
+
import type { Column, RowChangeDetail } from '@keenmate/web-grid'
|
|
226
|
+
|
|
227
|
+
interface Employee {
|
|
228
|
+
id: number
|
|
229
|
+
name: string
|
|
230
|
+
salary: number
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const columns: Column<Employee>[] = [
|
|
234
|
+
{ field: 'id', title: 'ID', width: '60px' },
|
|
235
|
+
{ field: 'name', title: 'Name', width: '200px' },
|
|
236
|
+
{ field: 'salary', title: 'Salary', editor: 'number' }
|
|
237
|
+
]
|
|
61
238
|
```
|
|
62
239
|
|
|
63
240
|
## Features
|