@keenmate/web-grid 1.1.0 → 1.2.0-rc01

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,6 +2,14 @@
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-rc01
6
+
7
+ - **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`.
8
+ - **Tree-row expand is ~40× faster**: Memoized the data pipeline (`displayItems` / `paginatedItems`) and added a surgical render path that replaces only inner contents instead of rebuilding the table. Expanding a 700-row tree drops from ~700 ms to ~16 ms. Render timings surface via the new `GRID:PERF` logger category.
9
+ - **Paste API is first-class on `<web-grid>`**: `onpaste`, `onbeforepaste`, `pasteMode`, and `shouldValidateOnPaste` are now reachable directly on the GridElement instead of requiring `el.grid.*`. `onpaste` shadows the native HTMLElement property and delivers a `PasteDetail`, not a raw `ClipboardEvent`. TypeScript consumers should cast on assignment or use `el.grid.onpaste = fn` for full type fidelity; JS consumers have no friction.
10
+ - **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
+ - **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
+
5
13
  ## What's New in v1.1.0
6
14
 
7
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`.
@@ -10,14 +18,6 @@ A feature-rich, framework-agnostic data grid web component built with TypeScript
10
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).
11
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.
12
20
 
13
- ## What's New in v1.0.5
14
-
15
- - **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.
16
- - **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.
17
- - **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.
18
- - **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-*`.
19
- - **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.
20
-
21
21
  ## Installation
22
22
 
23
23
  ```bash
package/dist/grid.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Column, CellValidationState, RowToolbarConfig, ContextMenuItem, RowShortcut, RowChangeDetail, ToolbarClickDetail, RowActionClickDetail, ContextMenuContext, HeaderMenuConfig, HeaderMenuContext, EditTrigger, EditStartSelection, EditingCell, FocusedCell, SortMode, SortState, DataRequestDetail, DataRequestTrigger, BeforeCommitResult, GridMode, ToggleVisibility, PaginationLabelsCallback, SummaryContentCallback, ValidationTooltipContext, ToolbarPosition, GridLabels, RowLockInfo, RowLockingOptions, RowLockChangeDetail, ColumnWidthState, ColumnResizeDetail, ColumnOrderState, ColumnReorderDetail, FillDragDetail, FillDirection, RangeShortcut, CellSelectionMode, CellRange, CellSelectionChangeDetail, RowFocusDetail, PasteMode, BeforePasteDetail, PasteDetail, CreateRowCallback, NewRowPosition, TreeExpandedChangeDetail, TreeChevronCallback, TreeDoubleClickBehavior } from './types.js';
1
+ import type { Column, CellValidationState, RowToolbarConfig, ContextMenuConfig, RowShortcut, RowChangeDetail, ToolbarClickDetail, RowActionClickDetail, ContextMenuContext, HeaderMenuConfig, HeaderMenuContext, EditTrigger, EditStartSelection, EditingCell, FocusedCell, SortMode, SortState, DataRequestDetail, DataRequestTrigger, BeforeCommitResult, GridMode, ToggleVisibility, PaginationLabelsCallback, SummaryContentCallback, ValidationTooltipContext, ToolbarPosition, GridLabels, RowLockInfo, RowLockingOptions, RowLockChangeDetail, ColumnWidthState, ColumnResizeDetail, ColumnOrderState, ColumnReorderDetail, FillDragDetail, FillDirection, RangeShortcut, CellSelectionMode, CellRange, CellSelectionChangeDetail, RowFocusDetail, PasteMode, BeforePasteDetail, PasteDetail, CreateRowCallback, NewRowPosition, TreeExpandedChangeDetail, TreeChevronCallback, TreeDoubleClickBehavior } from './types.js';
2
2
  type TreeNode = {
3
3
  path: string;
4
4
  parent: string | null;
@@ -29,6 +29,7 @@ export declare class WebGrid<T = unknown> {
29
29
  protected _isStriped: boolean;
30
30
  protected _isHoverable: boolean;
31
31
  protected _isEditable: boolean;
32
+ protected _isRowEditable: boolean | ((row: T) => boolean) | undefined;
32
33
  protected _editTrigger: EditTrigger;
33
34
  protected _editStartSelection: EditStartSelection;
34
35
  protected _mode: GridMode;
@@ -53,7 +54,7 @@ export declare class WebGrid<T = unknown> {
53
54
  protected _cellToolbarOffset: number | string;
54
55
  protected _toolbarBtnMinWidth: string | undefined;
55
56
  protected _inlineActionsTitle: string;
56
- protected _contextMenu: ContextMenuItem<T>[] | undefined;
57
+ protected _contextMenu: ContextMenuConfig<T>[] | undefined;
57
58
  protected _contextMenuXOffset: number;
58
59
  protected _contextMenuYOffset: number;
59
60
  protected _headerContextMenu: HeaderMenuConfig<T>[] | undefined;
@@ -105,6 +106,8 @@ export declare class WebGrid<T = unknown> {
105
106
  }) => void) | undefined;
106
107
  protected _sort: SortState[];
107
108
  protected _filters: Record<string, string>;
109
+ protected _onfilterchange: ((filters: Record<string, string>) => void) | undefined;
110
+ protected _columnMinWidth: string | undefined;
108
111
  protected _currentPage: number;
109
112
  protected _totalItems: number | null;
110
113
  protected _showPagination: boolean | 'auto';
@@ -170,6 +173,8 @@ export declare class WebGrid<T = unknown> {
170
173
  protected _treePathMember: string | null;
171
174
  protected _treeLevelMember: string | null;
172
175
  protected _treeParentMember: string | null;
176
+ protected _idMember: string | null;
177
+ protected _hasWarnedAboutMissingRowId: boolean;
173
178
  protected _treeSeparator: string | null;
174
179
  protected _treeDataSorted: boolean;
175
180
  protected _expandedPaths: Set<string>;
@@ -182,6 +187,8 @@ export declare class WebGrid<T = unknown> {
182
187
  protected _treeCollapsedGlyph: string;
183
188
  protected _treeChevronCallback: TreeChevronCallback<T> | undefined;
184
189
  protected _treeChevronCache: WeakMap<object, Map<string, string>>;
190
+ protected _paginatedItemsCache: T[] | null;
191
+ protected _displayItemsCache: T[] | null;
185
192
  get items(): T[];
186
193
  set items(value: T[]);
187
194
  get columns(): Column<T>[];
@@ -190,6 +197,10 @@ export declare class WebGrid<T = unknown> {
190
197
  set sortMode(value: SortMode);
191
198
  get isFilterable(): boolean;
192
199
  set isFilterable(value: boolean);
200
+ get onfilterchange(): ((filters: Record<string, string>) => void) | undefined;
201
+ set onfilterchange(value: ((filters: Record<string, string>) => void) | undefined);
202
+ get columnMinWidth(): string | undefined;
203
+ set columnMinWidth(value: string | undefined);
193
204
  get isPageable(): boolean;
194
205
  set isPageable(value: boolean);
195
206
  get pageSize(): number;
@@ -204,6 +215,8 @@ export declare class WebGrid<T = unknown> {
204
215
  set isHoverable(value: boolean);
205
216
  get isEditable(): boolean;
206
217
  set isEditable(value: boolean);
218
+ get isRowEditable(): boolean | ((row: T) => boolean) | undefined;
219
+ set isRowEditable(value: boolean | ((row: T) => boolean) | undefined);
207
220
  get editTrigger(): EditTrigger;
208
221
  set editTrigger(value: EditTrigger);
209
222
  get editStartSelection(): EditStartSelection;
@@ -285,8 +298,8 @@ export declare class WebGrid<T = unknown> {
285
298
  set toolbarBtnMinWidth(value: string | undefined);
286
299
  get inlineActionsTitle(): string;
287
300
  set inlineActionsTitle(value: string);
288
- get contextMenu(): ContextMenuItem<T>[] | undefined;
289
- set contextMenu(value: ContextMenuItem<T>[] | undefined);
301
+ get contextMenu(): ContextMenuConfig<T>[] | undefined;
302
+ set contextMenu(value: ContextMenuConfig<T>[] | undefined);
290
303
  get contextMenuXOffset(): number;
291
304
  set contextMenuXOffset(value: number);
292
305
  get contextMenuYOffset(): number;
@@ -377,6 +390,7 @@ export declare class WebGrid<T = unknown> {
377
390
  get ontoolbarclick(): ((detail: ToolbarClickDetail<T>) => void) | undefined;
378
391
  set ontoolbarclick(value: ((detail: ToolbarClickDetail<T>) => void) | undefined);
379
392
  set onrowaction(value: ((detail: RowActionClickDetail<T>) => void) | undefined);
393
+ get oncontextmenuopen(): ((context: ContextMenuContext<T>) => void) | undefined;
380
394
  set oncontextmenuopen(value: ((context: ContextMenuContext<T>) => void) | undefined);
381
395
  get onheadercontextmenuopen(): ((context: HeaderMenuContext<T>) => void) | undefined;
382
396
  set onheadercontextmenuopen(value: ((context: HeaderMenuContext<T>) => void) | undefined);
@@ -467,6 +481,17 @@ export declare class WebGrid<T = unknown> {
467
481
  set newRowIndicator(value: string);
468
482
  get createEmptyRowCallback(): (() => T | Promise<T>) | undefined;
469
483
  set createEmptyRowCallback(value: (() => T | Promise<T>) | undefined);
484
+ get idMember(): string | null;
485
+ set idMember(value: string | null);
486
+ /**
487
+ * Return a stable string key for a row. Coalesce order: idMember value → treePathMember
488
+ * value → displayed-index string fallback. Used to key drafts and invalid-cell markers
489
+ * so they don't drift when the displayed order changes (sort, filter, page, tree toggle).
490
+ *
491
+ * Distinct from `getRowId` which is the row-locking identifier (any type).
492
+ */
493
+ getStableRowKey(item: T, displayedIndex: number): string;
494
+ private maybeWarnAboutRowIdentity;
470
495
  get treePathMember(): string | null;
471
496
  set treePathMember(value: string | null);
472
497
  get treeLevelMember(): string | null;
@@ -488,6 +513,22 @@ export declare class WebGrid<T = unknown> {
488
513
  toggleExpandedPath(path: string): void;
489
514
  expandAll(): void;
490
515
  collapseAll(): void;
516
+ /**
517
+ * Expand a path's entire subtree (the path itself + all descendants).
518
+ * Used by the per-row "expand all" context-menu action — file-explorer convention
519
+ * is "expand everything *under here*", not the entire dataset.
520
+ */
521
+ expandSubtree(path: string): void;
522
+ /**
523
+ * Collapse a path's entire subtree (the path itself + all descendants).
524
+ */
525
+ collapseSubtree(path: string): void;
526
+ /**
527
+ * Walk up the path's ancestor chain looking for the nearest expanded ancestor.
528
+ * Used by Ctrl+ArrowLeft: when the focused row has no expanded children to collapse,
529
+ * step up to the closest ancestor that is expanded so the user gets meaningful action.
530
+ */
531
+ findNearestExpandedAncestor(path: string): string | null;
491
532
  /** Returns tree info for a row (used by rendering) */
492
533
  getRowTreeInfo(item: T): {
493
534
  path: string;
@@ -575,6 +616,15 @@ export declare class WebGrid<T = unknown> {
575
616
  copyCellSelectionToClipboard(): Promise<boolean>;
576
617
  get isNavigateMode(): boolean;
577
618
  get filteredItems(): T[];
619
+ /**
620
+ * Returns the set of fields whose current filter input is "incomplete" (column.filter
621
+ * returned null when probed against the first row). Renderers can use this to mark the
622
+ * input visually (red border) without excluding all rows.
623
+ */
624
+ getInvalidFilterFields(): Set<string>;
625
+ get filters(): Record<string, string>;
626
+ set filters(value: Record<string, string>);
627
+ setFilter(field: string, value: string): void;
578
628
  get sortedItems(): T[];
579
629
  get paginatedItems(): T[];
580
630
  get totalPages(): number;
@@ -630,6 +680,12 @@ export declare class WebGrid<T = unknown> {
630
680
  */
631
681
  protected checkToolbarConflicts(): void;
632
682
  protected requestUpdate(): void;
683
+ /**
684
+ * Drop memoized pipeline output. The web-component's requestUpdate override
685
+ * calls this on every state mutation, so callers don't need to invoke it
686
+ * directly — but it's safe to call any time the cache might be stale.
687
+ */
688
+ invalidateDisplayCache(): void;
633
689
  getRowDraft(rowIndex: number): T | undefined;
634
690
  hasRowDraft(rowIndex: number): boolean;
635
691
  /**
@@ -650,6 +706,8 @@ export declare class WebGrid<T = unknown> {
650
706
  discardAllDrafts(): void;
651
707
  getCellRawValue(item: T, rowIndex: number, field: string): unknown;
652
708
  getCellValue(item: T, column: Column<T>, rowIndex?: number): string;
709
+ /** Compute the stable rowKey for a displayed-row index, or null if no row at that index. */
710
+ private rowKeyForIndex;
653
711
  isCellInvalid(rowIndex: number, field: string): boolean;
654
712
  getCellValidationError(rowIndex: number, field: string): string | null;
655
713
  addInvalidCell(rowIndex: number, field: string, error: string): void;
@@ -696,16 +754,42 @@ export declare class WebGrid<T = unknown> {
696
754
  */
697
755
  updateDraftValue(rowIndex: number, field: string, newValue: unknown): void;
698
756
  /**
699
- * Check if a column's cells can be edited
700
- */
701
- isCellEditable(column: Column<T>): boolean;
702
- /**
703
- * Get all editable columns with their indices
704
- */
705
- getEditableColumns(): {
757
+ * Check if a column's cells can be edited.
758
+ * `row` is required to evaluate function-form predicates; pass it for per-row checks,
759
+ * omit it for static column-level checks (e.g. building toolbar UI). When omitted and a
760
+ * predicate exists, conservatively returns true so the column isn't hidden.
761
+ *
762
+ * Resolution order:
763
+ * 0. tree column in tree mode → not editable (the tree column displays hierarchy, not data)
764
+ * 1. column.isEditable === false → not editable (hard veto)
765
+ * 2. column.isEditable === function with row → must return true to continue
766
+ * 3. grid.isRowEditable with row → must pass to continue
767
+ * 4. column.isEditable === true → editable (overrides grid-level)
768
+ * 5. else → defer to grid-level isEditable
769
+ */
770
+ isCellEditable(column: Column<T>, row?: T): boolean;
771
+ /**
772
+ * Get all editable columns with their indices.
773
+ * Pass `row` to evaluate per-row predicates (function-form `isEditable`, `isRowEditable`).
774
+ * Without `row`, returns columns that are *potentially* editable (any row could pass).
775
+ */
776
+ getEditableColumns(row?: T): {
706
777
  index: number;
707
778
  column: Column<T>;
708
779
  }[];
780
+ /**
781
+ * Walk rows in `direction` looking for the next row that has at least one editable
782
+ * column at or beyond `fromColEditableIndex` (or beyond the last when going forward
783
+ * past the row's editable list). Used by Tab traversal in heterogeneous trees so the
784
+ * cursor skips read-only rows (e.g. team rows) entirely instead of landing on a cell
785
+ * with no tabindex and silently losing focus.
786
+ *
787
+ * Returns null if no editable cell exists in the requested direction.
788
+ */
789
+ findNextEditableCell(fromRowIndex: number, fromColEditableIndex: number, direction: 'forward' | 'backward'): {
790
+ rowIndex: number;
791
+ colIndex: number;
792
+ } | null;
709
793
  /**
710
794
  * Check if a specific cell is currently focused
711
795
  */
package/dist/logger.d.ts CHANGED
@@ -28,6 +28,7 @@ export declare const initLogger: any;
28
28
  export declare const dataLogger: any;
29
29
  export declare const uiLogger: any;
30
30
  export declare const interactionLogger: any;
31
+ export declare const perfLogger: any;
31
32
  export default log;
32
33
  /**
33
34
  * List of all logging categories for introspection
@@ -22,8 +22,12 @@ export interface ClickEventManager {
22
22
  * Initialize click listeners
23
23
  * @param container - The grid container element (.wg)
24
24
  * @param hostElement - The custom element host (<web-grid>) for outside detection
25
+ * @param isPathInOwnedScope - Optional predicate; when it returns true for a
26
+ * click's composed path, the click is treated as inside the grid (used for
27
+ * document.body-hosted popovers like the datepicker and context menus
28
+ * that need to extend the grid's "inside" scope beyond the host element).
25
29
  */
26
- init(container: HTMLElement, hostElement: HTMLElement): void;
30
+ init(container: HTMLElement, hostElement: HTMLElement, isPathInOwnedScope?: (path: EventTarget[]) => boolean): void;
27
31
  /**
28
32
  * Remove all listeners and subscriptions (called in disconnectedCallback)
29
33
  */
@@ -1,5 +1,14 @@
1
- import type { ContextMenuItem, ContextMenuContext, HeaderMenuConfig, HeaderMenuItem, HeaderMenuContext } from '../../types.js';
1
+ import type { ContextMenuItem, ContextMenuConfig, ContextMenuContext, HeaderMenuConfig, HeaderMenuItem, HeaderMenuContext } from '../../types.js';
2
2
  import type { GridContext } from '../types.js';
3
+ /**
4
+ * Normalize a ContextMenuConfig list (which may contain string shorthand and/or items
5
+ * with `type` set) into a flat list of fully-defined ContextMenuItem objects.
6
+ * Predefined types get default labels, icons, visibility predicates, and onclick handlers.
7
+ *
8
+ * The grid is needed at click time for `expand-all` etc. to call `expandSubtree(path)`,
9
+ * so we close over it rather than passing it through later.
10
+ */
11
+ export declare function normalizeContextMenu<T>(config: ContextMenuConfig<T>[], grid: GridContext<T>['grid']): ContextMenuItem<T>[];
3
12
  /**
4
13
  * Open context menu at position
5
14
  */
@@ -11,6 +11,8 @@ export declare class DatePicker {
11
11
  private anchor;
12
12
  private input;
13
13
  private cleanupAutoUpdate;
14
+ /** The picker's outer container (mounted in document.body), or null when closed. */
15
+ getElement(): HTMLElement | null;
14
16
  private previousInputValue;
15
17
  private boundHandleClickOutside;
16
18
  private boundHandleKeyDown;
@@ -4,6 +4,14 @@ import type { GridContext } from '../types.js';
4
4
  * Wrap cell content with tree indent + chevron when column is the tree column.
5
5
  * Returns the original innerHtml unchanged when tree mode is off or column isn't isTree.
6
6
  *
7
+ * Layout: inline-flex wrapper with `padding-inline-start: level * --wg-tree-indent`.
8
+ * Inside the wrapper sits either a chevron <button> (branch) or an empty
9
+ * <span class="wg__tree-leaf-spacer"> (leaf, keeps alignment with branches).
10
+ *
11
+ * Chevron rotation: when treeExpandedGlyph === treeCollapsedGlyph (the default
12
+ * setup) we add `.wg__tree-chevron--expanded` and CSS rotates the glyph 90°.
13
+ * When the glyphs differ, the glyph is swapped on state change instead.
14
+ *
7
15
  * Used by both the full-table render (table.ts) and the surgical single-cell
8
16
  * render (cell.ts), so both paths keep the chevron after focus/edit transitions.
9
17
  */
package/dist/perf.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ export declare const gridPerf: {
2
+ counters: {
3
+ displayItems: number;
4
+ displayItemsMs: number;
5
+ paginatedItems: number;
6
+ paginatedItemsMs: number;
7
+ treeSorted: number;
8
+ treeSortedMs: number;
9
+ treeVisible: number;
10
+ treeVisibleMs: number;
11
+ cellDisplayItemsLookup: number;
12
+ };
13
+ reset(): void;
14
+ summary(): string;
15
+ };
package/dist/types.d.ts CHANGED
@@ -75,7 +75,7 @@ export type CustomEditorContext<T> = {
75
75
  cancel: () => void;
76
76
  };
77
77
  export type CellValidationState = {
78
- rowIndex: number;
78
+ rowKey: string;
79
79
  field: string;
80
80
  error: string;
81
81
  };
@@ -104,6 +104,8 @@ export type Column<T> = {
104
104
  maxWidth?: string;
105
105
  textOverflow?: 'wrap' | 'ellipsis';
106
106
  maxLines?: number;
107
+ nowrap?: boolean;
108
+ filter?: (filterValue: string, row: T) => boolean | null;
107
109
  horizontalAlign?: "left" | "center" | "right" | "justify";
108
110
  verticalAlign?: "top" | "middle" | "bottom";
109
111
  headerHorizontalAlign?: "left" | "center" | "right" | "justify";
@@ -113,7 +115,7 @@ export type Column<T> = {
113
115
  formatCallback?: (value: unknown, row: T) => string;
114
116
  templateCallback?: (row: T) => string;
115
117
  renderCallback?: CellRenderCallback<T>;
116
- isEditable?: boolean;
118
+ isEditable?: boolean | ((row: T) => boolean);
117
119
  editor?: EditorType;
118
120
  editTrigger?: EditTrigger;
119
121
  dropdownToggleVisibility?: ToggleVisibility;
@@ -214,23 +216,27 @@ export type ContextMenuContext<T> = {
214
216
  column: Column<T>;
215
217
  cellValue: unknown;
216
218
  };
219
+ export type PredefinedContextMenuItemType = 'expand-all' | 'collapse-all' | 'expand-tree' | 'collapse-tree';
217
220
  export type ContextMenuItem<T> = {
218
221
  id: string;
219
- label: string | ((context: ContextMenuContext<T>) => string);
222
+ label?: string | ((context: ContextMenuContext<T>) => string);
220
223
  icon?: string | ((context: ContextMenuContext<T>) => string);
221
224
  shortcut?: string;
222
225
  disabled?: boolean | ((context: ContextMenuContext<T>) => boolean);
223
226
  visible?: boolean | ((context: ContextMenuContext<T>) => boolean);
224
227
  danger?: boolean;
225
228
  dividerBefore?: boolean;
229
+ type?: PredefinedContextMenuItemType;
226
230
  onclick?: (context: ContextMenuContext<T>) => void | Promise<void>;
227
231
  };
232
+ export type ContextMenuConfig<T> = PredefinedContextMenuItemType | ContextMenuItem<T>;
228
233
  export type HeaderMenuContext<T> = {
229
234
  column: Column<T>;
230
235
  field: string;
231
236
  columnIndex: number;
232
237
  sortDirection: 'asc' | 'desc' | null;
233
238
  isFrozen: boolean;
239
+ isTreeMode: boolean;
234
240
  allColumns: Column<T>[];
235
241
  labels: GridLabels;
236
242
  };
@@ -301,6 +307,8 @@ export type QuickGridProps<T> = {
301
307
  items: T[];
302
308
  columns: Column<T>[];
303
309
  isFilterable?: boolean;
310
+ columnMinWidth?: string;
311
+ onfilterchange?: (filters: Record<string, string>) => void;
304
312
  isPageable?: boolean;
305
313
  pageSize?: number;
306
314
  isStriped?: boolean;
@@ -313,6 +321,7 @@ export type QuickGridProps<T> = {
313
321
  style?: string;
314
322
  customStylesCallback?: () => string;
315
323
  rowClassCallback?: (row: T, rowIndex: number) => string | null;
324
+ idMember?: keyof T | string;
316
325
  sort?: SortState[];
317
326
  sortMode?: SortMode;
318
327
  currentPage?: number;
@@ -327,6 +336,7 @@ export type QuickGridProps<T> = {
327
336
  summaryContentCallback?: SummaryContentCallback<T>;
328
337
  isSummaryInline?: boolean;
329
338
  isEditable?: boolean;
339
+ isRowEditable?: boolean | ((row: T) => boolean);
330
340
  editTrigger?: EditTrigger;
331
341
  editStartSelection?: EditStartSelection;
332
342
  mode?: GridMode;
@@ -347,7 +357,7 @@ export type QuickGridProps<T> = {
347
357
  cellToolbarOffset?: number | string;
348
358
  toolbarBtnMinWidth?: string;
349
359
  inlineActionsTitle?: string;
350
- contextMenu?: ContextMenuItem<T>[];
360
+ contextMenu?: ContextMenuConfig<T>[];
351
361
  contextMenuXOffset?: number;
352
362
  contextMenuYOffset?: number;
353
363
  oncontextmenuopen?: (context: ContextMenuContext<T>) => void;
@@ -1,5 +1,5 @@
1
1
  import { WebGrid } from './grid.js';
2
- import type { Column, CellValidationState, RowToolbarConfig, ContextMenuItem, RowShortcut, RowChangeDetail, ToolbarClickDetail, RowActionClickDetail, ContextMenuContext, HeaderMenuConfig, HeaderMenuContext, EditTrigger, EditStartSelection, EditorOption, EditorOptions, GridMode, ToggleVisibility, DataRequestDetail, SortState, SortMode, PaginationLabelsCallback, SummaryContentCallback, ValidationTooltipContext, ToolbarPosition, GridLabels, RowLockInfo, RowLockingOptions, RowLockChangeDetail, ColumnResizeDetail, ColumnWidthState, ColumnReorderDetail, ColumnOrderState, FillDragDetail, RangeShortcut, RowFocusDetail } from './types.js';
2
+ import type { Column, CellValidationState, RowToolbarConfig, ContextMenuConfig, RowShortcut, RowChangeDetail, ToolbarClickDetail, RowActionClickDetail, ContextMenuContext, HeaderMenuConfig, HeaderMenuContext, EditTrigger, EditStartSelection, EditorOption, EditorOptions, GridMode, ToggleVisibility, DataRequestDetail, SortState, SortMode, PaginationLabelsCallback, SummaryContentCallback, ValidationTooltipContext, ToolbarPosition, GridLabels, RowLockInfo, RowLockingOptions, RowLockChangeDetail, ColumnResizeDetail, ColumnWidthState, ColumnReorderDetail, ColumnOrderState, FillDragDetail, RangeShortcut, RowFocusDetail, PasteMode, BeforePasteDetail } from './types.js';
3
3
  import { DatePicker } from './modules/datepicker/index.js';
4
4
  import { type ScrollEventManager } from './modules/scroll-events/index.js';
5
5
  import { type FocusEventManager } from './modules/focus-events/index.js';
@@ -83,6 +83,13 @@ export declare class GridElement<T = unknown> extends HTMLElement implements Gri
83
83
  set columns(value: Column<T>[]);
84
84
  get isFilterable(): boolean;
85
85
  set isFilterable(value: boolean);
86
+ get onfilterchange(): ((filters: Record<string, string>) => void) | undefined;
87
+ set onfilterchange(value: ((filters: Record<string, string>) => void) | undefined);
88
+ get columnMinWidth(): string | undefined;
89
+ set columnMinWidth(value: string | undefined);
90
+ get filters(): Record<string, string>;
91
+ set filters(value: Record<string, string>);
92
+ setFilter(field: string, value: string): void;
86
93
  get isPageable(): boolean;
87
94
  set isPageable(value: boolean);
88
95
  get pageSize(): number;
@@ -97,6 +104,8 @@ export declare class GridElement<T = unknown> extends HTMLElement implements Gri
97
104
  set isHoverable(value: boolean);
98
105
  get isEditable(): boolean;
99
106
  set isEditable(value: boolean);
107
+ get isRowEditable(): boolean | ((row: T) => boolean) | undefined;
108
+ set isRowEditable(value: boolean | ((row: T) => boolean) | undefined);
100
109
  get editTrigger(): EditTrigger;
101
110
  set editTrigger(value: EditTrigger);
102
111
  get editStartSelection(): EditStartSelection;
@@ -151,8 +160,8 @@ export declare class GridElement<T = unknown> extends HTMLElement implements Gri
151
160
  set toolbarBtnMinWidth(value: string | undefined);
152
161
  get inlineActionsTitle(): string;
153
162
  set inlineActionsTitle(value: string);
154
- get contextMenu(): ContextMenuItem<T>[] | undefined;
155
- set contextMenu(value: ContextMenuItem<T>[] | undefined);
163
+ get contextMenu(): ContextMenuConfig<T>[] | undefined;
164
+ set contextMenu(value: ContextMenuConfig<T>[] | undefined);
156
165
  get contextMenuXOffset(): number;
157
166
  set contextMenuXOffset(value: number);
158
167
  get contextMenuYOffset(): number;
@@ -196,6 +205,8 @@ export declare class GridElement<T = unknown> extends HTMLElement implements Gri
196
205
  set newRowIndicator(value: string);
197
206
  get createEmptyRowCallback(): () => T | Promise<T>;
198
207
  set createEmptyRowCallback(value: () => T | Promise<T>);
208
+ get idMember(): string | null;
209
+ set idMember(value: string | null);
199
210
  get treePathMember(): string | null;
200
211
  set treePathMember(value: string | null);
201
212
  get treeLevelMember(): string | null;
@@ -251,6 +262,7 @@ export declare class GridElement<T = unknown> extends HTMLElement implements Gri
251
262
  set validationTooltipCallback(value: ((context: ValidationTooltipContext<T>) => string | null) | undefined);
252
263
  set ontoolbarclick(value: ((detail: ToolbarClickDetail<T>) => void) | undefined);
253
264
  set onrowaction(value: ((detail: RowActionClickDetail<T>) => void) | undefined);
265
+ get oncontextmenuopen(): ((context: ContextMenuContext<T>) => void) | undefined;
254
266
  set oncontextmenuopen(value: ((context: ContextMenuContext<T>) => void) | undefined);
255
267
  get ondatarequest(): ((detail: DataRequestDetail) => void) | undefined;
256
268
  set ondatarequest(value: ((detail: DataRequestDetail) => void) | undefined);
@@ -343,6 +355,12 @@ export declare class GridElement<T = unknown> extends HTMLElement implements Gri
343
355
  set infiniteScrollThreshold(value: number);
344
356
  get hasMoreItems(): boolean;
345
357
  set hasMoreItems(value: boolean);
358
+ get onbeforepaste(): ((detail: BeforePasteDetail<T>) => void) | undefined;
359
+ set onbeforepaste(value: ((detail: BeforePasteDetail<T>) => void) | undefined);
360
+ get pasteMode(): PasteMode;
361
+ set pasteMode(value: PasteMode);
362
+ get shouldValidateOnPaste(): boolean;
363
+ set shouldValidateOnPaste(value: boolean);
346
364
  get displayItems(): T[];
347
365
  get totalPages(): number;
348
366
  get isNavigateMode(): boolean;