@keenmate/web-grid 1.2.0-rc01 → 1.2.0-rc02

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 (40) hide show
  1. package/README.md +16 -11
  2. package/ai/fill-handle.txt +1 -1
  3. package/ai/frozen-columns.txt +2 -2
  4. package/ai/row-locking.txt +1 -1
  5. package/ai/styling-theming.txt +13 -12
  6. package/component-variables.manifest.json +8 -7
  7. package/dist/grid.d.ts +3 -0
  8. package/dist/types.d.ts +1 -0
  9. package/dist/web-component.d.ts +10 -0
  10. package/dist/web-grid.js +99 -26
  11. package/dist/web-grid.umd.js +16 -16
  12. package/package.json +1 -1
  13. package/src/css/animations.css +14 -0
  14. package/src/css/{_cells.css → cells.css} +1 -1
  15. package/src/css/controls.css +3 -0
  16. package/src/css/dark-mode.css +67 -0
  17. package/src/css/{_dialogs.css → dialogs.css} +9 -68
  18. package/src/css/{_dirty-indicator.css → dirty-indicator.css} +37 -37
  19. package/src/css/{_dropdown.css → dropdown.css} +1 -1
  20. package/src/css/{_editors.css → editors.css} +14 -8
  21. package/src/css/floating.css +71 -0
  22. package/src/css/{_freeze.css → freeze.css} +5 -5
  23. package/src/css/{_header.css → header.css} +1 -1
  24. package/src/css/main.css +53 -48
  25. package/src/css/{_navigation.css → navigation.css} +3 -3
  26. package/src/css/{_resize.css → resize.css} +1 -1
  27. package/src/css/{_selection.css → selection.css} +1 -1
  28. package/src/css/{_shortcuts.css → shortcuts.css} +4 -4
  29. package/src/css/{_modifiers.css → states.css} +8 -2
  30. package/src/css/{_tree.css → tree.css} +71 -71
  31. package/src/css/{_variables.css → variables.css} +55 -42
  32. package/src/css/_dark-mode.css +0 -93
  33. /package/src/css/{_cell-selection.css → cell-selection.css} +0 -0
  34. /package/src/css/{_fill-handle.css → fill-handle.css} +0 -0
  35. /package/src/css/{_pagination.css → pagination.css} +0 -0
  36. /package/src/css/{_reorder.css → reorder.css} +0 -0
  37. /package/src/css/{_row-locking.css → row-locking.css} +0 -0
  38. /package/src/css/{_table.css → table.css} +0 -0
  39. /package/src/css/{_toolbar.css → toolbar.css} +0 -0
  40. /package/src/css/{_virtual-scroll.css → virtual-scroll.css} +0 -0
package/README.md CHANGED
@@ -2,6 +2,17 @@
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.2.0-rc02
6
+
7
+ - **Excel-like commit-on-click-away** — new `shouldCommitOnClickAway` property (defaults to `true`). Clicking a different cell while editing now commits the in-progress value through `beforeCommitCallback` / `validateCallback` instead of silently discarding it. Set to `false` to keep the legacy discard behavior. Companion fix: row focus (`.wg__row--focused`) now applies on the first cell click — previously it only landed on the second.
8
+ - **CSS surface taxonomy aligned with pure-admin's `--base-*` names** — `--wg-surface-1/2/3` renamed to `--wg-main-bg` / `--wg-elevated-bg`, `--wg-surface-floating` → `--wg-dropdown-bg` (`--wg-surface-3` merged into `--wg-hover-bg`). Consumer overrides of the old names need to migrate; see the CHANGELOG mapping table.
9
+ - **Dark mode reworked to respect consumer themes** — the dark-mode override blocks used to set `--wg-*` to hardcoded literals, silently overriding pure-admin / theme-designer values. They now just flip `color-scheme` and let `light-dark()` in `variables.css` do the work. The consumer's `--base-*` chain stays the source of truth.
10
+ - **OS-aware dark mode via `light-dark()` fallbacks** — every hardcoded fallback in `variables.css` is wrapped in `light-dark(<light>, <dark>)`. A consumer who only sets `body { color-scheme: dark }` (no overrides, no framework class) now gets a sensible dark palette automatically.
11
+ - **CSS architecture refactor: `@layer` cascade + canonical file set** — `main.css` now declares `@layer variables, component, overrides;` so consumer rules beat library defaults without `!important`. CSS filenames dropped the underscore prefix (pure-CSS doesn't use SASS-partial convention). New canonical Tier-2 files (`controls.css` / `floating.css` / `states.css` / `animations.css`) match the cross-component pattern.
12
+ - **`--base-active-bg` + `--base-inverse-bg`** — two new cross-component theming hooks. `--base-active-bg` distinguishes pressed from hover; `--base-inverse-bg` covers tooltip and future inverse UI surfaces. Both are optional and additive.
13
+ - **Context menu was leaking through stale `--base-*` names** — was referencing `--base-layer-01` / `--base-stroke-default` / `--base-error-color` (all long-removed in pure-admin). Now uses the canonical names; consumers loading a pure-admin theme finally get themed context menus instead of silent fallbacks.
14
+ - **WCAG contrast e2e suite** — 18 assertions check header / body / hover / focused / selected-row / editing-cell contrast against the 3:1 threshold (WCAG AA for non-text UI). Catches theme regressions invisible to visual smoke tests.
15
+
5
16
  ## What's New in v1.2.0-rc01
6
17
 
7
18
  - **Tree mode polish**: The column marked `isTree: true` is now read-only by default (editing it conflicts with the toggle); Tab / Shift-Tab in heterogeneous trees skip rows where every cell is read-only, and the next editable cell auto-opens its editor after a Tab commit; `'expand-all'`, `'collapse-all'`, `'expand-tree'`, `'collapse-tree'` are now usable as predefined context-menu items via string shorthand or `{ type: ... }` object form. Tree chevron is a single rotating glyph (120 ms transition) on an inline-flex layout. CSS class `wg__tree-cell-content` renamed to `wg__tree-cell-body`.
@@ -10,14 +21,6 @@ A feature-rich, framework-agnostic data grid web component built with TypeScript
10
21
  - **Datepicker no longer closes when you click its own chrome**: previously, clicking the chevrons / month/year header / disabled days appeared as "outside the grid" to two internal listeners and silently tore the picker down. Now both listeners recognize our `document.body`-hosted popovers (datepicker + cell/header context menus) as part of the grid's logical scope. Same fix protects the cell and header context menus from the same class of bug.
11
22
  - **Datepicker `outputFormat` is honored from the action pipeline**: a column declaring `editorOptions.outputFormat: 'timestamp'` (or `'date'`) now actually emits a number (or `Date`) instead of an ISO string when commit goes through the modern pipeline executor (`editTrigger='always'` and keyboard-driven select).
12
23
 
13
- ## What's New in v1.1.0
14
-
15
- - **Tree / hierarchy mode**: Render tree-structured data using ltree-style path strings (`"1.2.3"`, `"/a/b/c"`, `"C:\\Win\\Sys"` — separator auto-detected). Mark one column with `isTree: true` to add depth-based indentation and an expand/collapse chevron. Sort is sibling-aware, filter auto-expands ancestors of matches, pagination operates on visible rows. New props: `treePathMember`, `treeLevelMember`, `treeParentMember`, `treeSeparator`, `treeDataSorted`, `expandedPaths`, `defaultExpandDepth`. Methods: `toggleExpandedPath`, `expandAll`, `collapseAll`, `getRowTreeInfo`. Event: `onexpandedpathschange`.
16
- - **Custom chevron icons via `treeChevronCallback`**: Receives `{ expanded, hasChildren, row, level, path }`, returns HTML for the chevron's inner content. Result is cached per `(row, expanded, hasChildren)` so the callback fires at most a handful of times per row. Use it for file/folder icons, status indicators, anything per-row. Static fallbacks: `treeExpandedGlyph` / `treeCollapsedGlyph`.
17
- - **Double-click to expand/collapse**: New `treeDoubleClickBehavior: 'none' | 'toggle'`. When set to `'toggle'`, double-clicking anywhere in the tree column expands/collapses the node — works reliably even when the cell DOM is re-rendered between clicks (uses `MouseEvent.detail`, not the unreliable native `dblclick`).
18
- - **No more spurious `onrowchange` events**: Entering edit mode and exiting via arrow keys without typing no longer fires phantom "X → X" change events. `commitEdit` now only fires `onrowchange` when the value actually changed (or validation failed).
19
- - **Pathological filler-cell width fix**: Removed `min-width: max-content` from `.wg__table` — it was redundant with `table-layout: fixed` and triggered intrinsic-size computation that ballooned the filler to hundreds of thousands of pixels in some browsers (Firefox especially) when cells contained absolutely-positioned editors.
20
-
21
24
  ## Installation
22
25
 
23
26
  ```bash
@@ -930,7 +933,7 @@ web-grid {
930
933
  /* Or set base variables for all KeenMate components */
931
934
  :root {
932
935
  --base-accent-color: #10b981;
933
- --base-layer-1: #ffffff;
936
+ --base-main-bg: #ffffff;
934
937
  }
935
938
  ```
936
939
 
@@ -953,8 +956,10 @@ This means:
953
956
  |----------|-------------|
954
957
  | `--wg-accent-color` | Primary accent color |
955
958
  | `--wg-text-color-1` | Primary text color |
956
- | `--wg-surface-1` | Background color |
957
- | `--wg-surface-2` | Alternate row/header background |
959
+ | `--wg-main-bg` | Background color (table body, cells) |
960
+ | `--wg-elevated-bg` | Alternate row/header background |
961
+ | `--wg-hover-bg` | Hover background (rows, buttons) |
962
+ | `--wg-dropdown-bg` | Floating surfaces (toolbar, context menu, dropdowns) |
958
963
  | `--wg-border-color` | Border color |
959
964
 
960
965
  ### Component Variables Manifest
@@ -113,7 +113,7 @@ prevents accidental fills from clicks). During the drag:
113
113
 
114
114
  CSS variables for the fill handle visual:
115
115
  --wg-fill-handle-size Default: 8px
116
- --wg-fill-handle-bg Default: var(--wg-surface-1)
116
+ --wg-fill-handle-bg Default: var(--wg-main-bg)
117
117
  --wg-fill-handle-border-color Default: var(--wg-accent-color)
118
118
  --wg-fill-handle-border-width Default: 2px
119
119
  --wg-fill-range-bg Default: color-mix(accent 15%, transparent)
@@ -74,7 +74,7 @@ color against the opaque frozen column base color instead of transparent:
74
74
 
75
75
  .wg__row--selected > .wg__cell--frozen {
76
76
  background: color-mix(in srgb, var(--wg-accent-color) 15%,
77
- var(--wg-frozen-column-bg, var(--wg-surface-1))) !important;
77
+ var(--wg-frozen-column-bg, var(--wg-main-bg))) !important;
78
78
  }
79
79
 
80
80
 
@@ -105,7 +105,7 @@ The shadow only appears when the wg--scrolled-horizontal class is present
105
105
  on the container (set when scrollLeft > 0).
106
106
 
107
107
  Other frozen column CSS variables:
108
- --wg-frozen-column-bg Default: var(--wg-surface-1)
108
+ --wg-frozen-column-bg Default: var(--wg-main-bg)
109
109
  --wg-frozen-header-bg Default: color-mix(in srgb, accent 8%, header-bg)
110
110
  --wg-frozen-column-border Default: 2px solid var(--wg-border-color)
111
111
  --wg-cell-splitter-color Border color for frozen column separator
@@ -148,7 +148,7 @@ Locked rows receive the following visual treatment:
148
148
  - Lock icon has cursor: help and full opacity (overrides row opacity)
149
149
 
150
150
  CSS variables:
151
- --wg-row-locked-bg Default: var(--base-disabled-bg, var(--wg-surface-2))
151
+ --wg-row-locked-bg Default: var(--base-disabled-bg, var(--wg-elevated-bg))
152
152
  --wg-row-locked-opacity Default: 0.7
153
153
 
154
154
 
@@ -9,7 +9,7 @@ Each --wg-* variable falls back to a --base-* variable, then to a hardcoded defa
9
9
 
10
10
  :host {
11
11
  --wg-accent-color: var(--base-accent-color, #0078d4);
12
- --wg-surface-1: var(--base-main-bg, #ffffff);
12
+ --wg-main-bg: var(--base-main-bg, #ffffff);
13
13
  --wg-font-size-base: calc(var(--base-font-size-sm, 1.4) * var(--wg-rem));
14
14
  }
15
15
 
@@ -23,7 +23,7 @@ Example -- theme all KeenMate components at once:
23
23
 
24
24
  :root {
25
25
  --base-accent-color: #10b981;
26
- --base-layer-1: #ffffff;
26
+ --base-main-bg: #ffffff;
27
27
  --base-font-family: 'Inter', sans-serif;
28
28
  }
29
29
 
@@ -54,16 +54,17 @@ Colors:
54
54
  Falls back to: --base-text-color-1, default: #242424
55
55
  --wg-text-color-2 Secondary text (row numbers, labels)
56
56
  --wg-text-color-3 Muted text (placeholders, empty states)
57
- --wg-surface-1 Main background (table body, cells)
57
+ --wg-main-bg Main background (table body, cells)
58
58
  Falls back to: --base-main-bg, default: #ffffff
59
- --wg-surface-2 Elevated background (headers, striped rows)
59
+ --wg-elevated-bg Elevated background (headers, striped rows)
60
60
  Falls back to: --base-elevated-bg, default: #f5f5f5
61
- --wg-surface-3 Hover background (row hover, button hover)
61
+ --wg-hover-bg Hover background (row hover, button hover)
62
+ Falls back to: --base-hover-bg, default: color-mix derived
62
63
  --wg-border-color All borders (table, cells, header separators)
63
64
  Falls back to: --base-border-color, default: #e0e0e0
64
65
 
65
66
  Header:
66
- --wg-header-bg Header row background (defaults to --wg-surface-2)
67
+ --wg-header-bg Header row background (defaults to --wg-elevated-bg)
67
68
  --wg-header-bg-hover Sortable header on hover
68
69
  --wg-header-color Header text color
69
70
  --wg-header-border Bottom border below header (2px solid)
@@ -71,8 +72,8 @@ Header:
71
72
  --wg-header-font-weight Header text weight (semibold)
72
73
 
73
74
  Rows:
74
- --wg-row-bg-hover Row hover when isHoverable=true (defaults to --wg-surface-3)
75
- --wg-row-bg-even Striped even rows when isStriped=true (defaults to --wg-surface-2)
75
+ --wg-row-bg-hover Row hover when isHoverable=true (defaults to --wg-hover-bg)
76
+ --wg-row-bg-even Striped even rows when isStriped=true (defaults to --wg-elevated-bg)
76
77
  --wg-row-border Border between rows
77
78
 
78
79
  Typography:
@@ -104,15 +105,15 @@ Dark mode activates automatically. No configuration needed. Detection methods:
104
105
 
105
106
  All four methods apply the same dark palette overrides:
106
107
 
107
- --wg-surface-1: #1f1f1f
108
- --wg-surface-2: #2b2b2b
109
- --wg-surface-3: #333333
108
+ --wg-main-bg: #1f1f1f
109
+ --wg-elevated-bg: #2b2b2b
110
+ --wg-hover-bg: #3a3a3a
110
111
  --wg-text-color-1: #e0e0e0
111
112
  --wg-text-color-2: #c0c0c0
112
113
  --wg-text-color-3: #a0a0a0
113
114
  --wg-border-color: #3d3d3d
114
115
  --wg-input-bg: #1f1f1f
115
- --wg-hover-bg: #3a3a3a
116
+ --wg-active-bg: #4a4a4a
116
117
  --wg-danger-color: #f87c86
117
118
  --wg-danger-bg-light: #442726
118
119
  --wg-dirty-indicator-color: #ffa940
@@ -13,10 +13,12 @@
13
13
  { "name": "base-text-color-on-accent", "required": false, "usage": "Text color on accent-colored backgrounds" },
14
14
  { "name": "base-text-inverted", "required": false, "usage": "Text on dark backgrounds (selected row numbers)" },
15
15
  { "name": "base-main-bg", "required": true, "usage": "Table body background, cell backgrounds, input fields" },
16
- { "name": "base-elevated-bg", "required": true, "usage": "Header row, striped even rows, pagination bar" },
17
- { "name": "base-hover-bg", "required": false, "usage": "Row hover, sorted column header, button hover states" },
16
+ { "name": "base-elevated-bg", "required": true, "usage": "Header row, striped even rows, pagination bar; also secondary fallback for base-dropdown-bg" },
17
+ { "name": "base-hover-bg", "required": false, "usage": "Row hover, sorted column header, button hover background (primary lookup; falls back to text/main color-mix)" },
18
+ { "name": "base-active-bg", "required": false, "usage": "Pressed/active button background, selected option background (primary lookup; falls back to text/main color-mix)" },
18
19
  { "name": "base-disabled-bg", "required": false, "usage": "Read-only and disabled cell backgrounds, locked row backgrounds" },
19
- { "name": "base-dropdown-bg", "required": false, "usage": "Floating toolbar, context menu, dropdown panels" },
20
+ { "name": "base-dropdown-bg", "required": false, "usage": "Floating toolbar, context menu, dropdown panels (primary lookup; chains through base-elevated-bg)" },
21
+ { "name": "base-inverse-bg", "required": false, "usage": "Secondary fallback for tooltip background (inverse-colored surface — dark in light mode, light in dark mode)" },
20
22
  { "name": "base-border-color", "required": true, "usage": "Table border, cell borders, header separators" },
21
23
  { "name": "base-input-bg", "required": false, "usage": "Filter input fields, editor text inputs" },
22
24
  { "name": "base-input-color", "required": false, "usage": "Text color in filter and editor inputs" },
@@ -54,10 +56,9 @@
54
56
  { "name": "wg-text-color-3", "category": "text", "usage": "Placeholder text, disabled text, empty state message, date trigger" },
55
57
  { "name": "wg-text-on-accent", "category": "text", "usage": "Text on accent backgrounds (Go button, active pagination)" },
56
58
 
57
- { "name": "wg-surface-1", "category": "surface", "usage": "Table body, cell backgrounds, filter input background" },
58
- { "name": "wg-surface-2", "category": "surface", "usage": "Header row, striped even rows, read-only cells, shortcut key badges" },
59
- { "name": "wg-surface-3", "category": "surface", "usage": "Row hover background, sorted header, pagination button hover" },
60
- { "name": "wg-surface-floating", "category": "surface", "usage": "Floating toolbar background, context menu, dropdown panels" },
59
+ { "name": "wg-main-bg", "category": "surface", "usage": "Table body, cell backgrounds, filter input background" },
60
+ { "name": "wg-elevated-bg", "category": "surface", "usage": "Header row, striped even rows, read-only cells, shortcut key badges" },
61
+ { "name": "wg-dropdown-bg", "category": "surface", "usage": "Floating toolbar background, context menu, dropdown panels" },
61
62
 
62
63
  { "name": "wg-border-color", "category": "border", "usage": "Table border, cell borders, header bottom, toolbar dividers" },
63
64
  { "name": "wg-border-color-hover", "category": "border", "usage": "Pagination button border on hover" },
package/dist/grid.d.ts CHANGED
@@ -32,6 +32,7 @@ export declare class WebGrid<T = unknown> {
32
32
  protected _isRowEditable: boolean | ((row: T) => boolean) | undefined;
33
33
  protected _editTrigger: EditTrigger;
34
34
  protected _editStartSelection: EditStartSelection;
35
+ protected _shouldCommitOnClickAway: boolean;
35
36
  protected _mode: GridMode;
36
37
  protected _dropdownToggleVisibility: ToggleVisibility;
37
38
  protected _shouldShowDropdownOnFocus: boolean;
@@ -221,6 +222,8 @@ export declare class WebGrid<T = unknown> {
221
222
  set editTrigger(value: EditTrigger);
222
223
  get editStartSelection(): EditStartSelection;
223
224
  set editStartSelection(value: EditStartSelection);
225
+ get shouldCommitOnClickAway(): boolean;
226
+ set shouldCommitOnClickAway(value: boolean);
224
227
  get mode(): GridMode;
225
228
  set mode(value: GridMode);
226
229
  get dropdownToggleVisibility(): ToggleVisibility;
package/dist/types.d.ts CHANGED
@@ -339,6 +339,7 @@ export type QuickGridProps<T> = {
339
339
  isRowEditable?: boolean | ((row: T) => boolean);
340
340
  editTrigger?: EditTrigger;
341
341
  editStartSelection?: EditStartSelection;
342
+ shouldCommitOnClickAway?: boolean;
342
343
  mode?: GridMode;
343
344
  dropdownToggleVisibility?: ToggleVisibility;
344
345
  shouldShowDropdownOnFocus?: boolean;
@@ -110,6 +110,8 @@ export declare class GridElement<T = unknown> extends HTMLElement implements Gri
110
110
  set editTrigger(value: EditTrigger);
111
111
  get editStartSelection(): EditStartSelection;
112
112
  set editStartSelection(value: EditStartSelection);
113
+ get shouldCommitOnClickAway(): boolean;
114
+ set shouldCommitOnClickAway(value: boolean);
113
115
  get mode(): GridMode;
114
116
  set mode(value: GridMode);
115
117
  get dropdownToggleVisibility(): ToggleVisibility;
@@ -452,6 +454,14 @@ export declare class GridElement<T = unknown> extends HTMLElement implements Gri
452
454
  * Clear all selections (cell range, row, column) and their visual borders
453
455
  */
454
456
  private clearAllSelections;
457
+ /**
458
+ * Called from cell-transition click handlers in place of grid.cancelEdit().
459
+ * Reads the in-progress editor value and commits it (Excel-like) when
460
+ * shouldCommitOnClickAway is true; falls back to cancel when false or when
461
+ * the editor DOM can't be read. Must be called BEFORE renderCell wipes
462
+ * the editor element.
463
+ */
464
+ private commitOrCancelEditOnTransition;
455
465
  /**
456
466
  * Surgically update row focus visual (add/remove wg__row--focused class)
457
467
  * Avoids full re-render to preserve cell focus