@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 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
- ### v1.0.3
18
+ ## Installation
11
19
 
12
- - **`onrowfocus` fixes**: No longer fires during cell range selection (drag/shift+click). Mouse-triggered row focus now defers to click (mouseup) instead of mousedown; keyboard navigation still fires immediately.
13
- - **Cell selection visual fix**: Focused cell outline no longer persists during cell range drag.
14
- - **Toolbar fixes**: Tooltip hides when toolbar moves/closes. Selections cleared on toolbar action click. `triggerElement` in `ontoolbarclick` detail stays alive (no longer detached by synchronous re-render).
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
- ### v1.0.2
24
+ Or via CDN (no bundler):
18
25
 
19
- - **Tooltip positioning in transformed containers**: Fixed tooltips appearing at grid's top-left when ancestor has CSS `transform`. Switched to `position: absolute` with `:host` as positioning context.
20
- - **HTML tooltips**: New `isTooltipHtml` column option for rich tooltip content.
21
- - **`ontoolbarclick` detail**: Now includes `event` (MouseEvent) and `triggerElement` (HTMLElement) for anchoring popovers to toolbar buttons inside shadow DOM.
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
- ## Installation
30
+ ## Getting Started
25
31
 
26
- ```bash
27
- npm install @keenmate/web-grid
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
- ## Quick Start
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
- ### ES Module (recommended)
46
+ ### Step 2 — Drop the element into your markup
33
47
 
34
48
  ```html
35
- <script type="module">
36
- import '@keenmate/web-grid'
37
- </script>
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
- <web-grid id="grid"></web-grid>
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
- <script type="module">
42
- const grid = document.getElementById('grid')
43
- grid.items = [
44
- { id: 1, name: 'Alice', age: 28 },
45
- { id: 2, name: 'Bob', age: 34 }
46
- ]
47
- grid.columns = [
48
- { field: 'id', title: 'ID', width: '60px' },
49
- { field: 'name', title: 'Name' },
50
- { field: 'age', title: 'Age' }
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
- ### UMD (Script Tag)
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
- <script src="https://unpkg.com/@keenmate/web-grid"></script>
60
- <web-grid id="grid"></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