@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 +8 -8
- package/dist/grid.d.ts +95 -11
- package/dist/logger.d.ts +1 -0
- package/dist/modules/click-events/index.d.ts +5 -1
- package/dist/modules/contextmenu/index.d.ts +10 -1
- package/dist/modules/datepicker/datepicker.d.ts +2 -0
- package/dist/modules/rendering/tree-render.d.ts +8 -0
- package/dist/perf.d.ts +15 -0
- package/dist/types.d.ts +14 -4
- package/dist/web-component.d.ts +21 -3
- package/dist/web-grid.js +2922 -2397
- package/dist/web-grid.umd.js +100 -105
- package/package.json +9 -3
- package/src/css/_navigation.css +7 -2
- package/src/css/_tree.css +29 -31
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,
|
|
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:
|
|
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():
|
|
289
|
-
set contextMenu(value:
|
|
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
|
-
|
|
702
|
-
|
|
703
|
-
*
|
|
704
|
-
|
|
705
|
-
|
|
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
|
-
|
|
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
|
|
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?:
|
|
360
|
+
contextMenu?: ContextMenuConfig<T>[];
|
|
351
361
|
contextMenuXOffset?: number;
|
|
352
362
|
contextMenuYOffset?: number;
|
|
353
363
|
oncontextmenuopen?: (context: ContextMenuContext<T>) => void;
|
package/dist/web-component.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WebGrid } from './grid.js';
|
|
2
|
-
import type { Column, CellValidationState, RowToolbarConfig,
|
|
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():
|
|
155
|
-
set contextMenu(value:
|
|
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;
|