@keenmate/web-grid 1.0.0-rc02 → 1.0.0-rc05

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
@@ -27,9 +27,10 @@ npm install @keenmate/web-grid
27
27
  ]
28
28
  grid.columns = [
29
29
  { field: 'id', title: 'ID', width: '60px' },
30
- { field: 'name', title: 'Name', sortable: true },
31
- { field: 'age', title: 'Age', sortable: true }
30
+ { field: 'name', title: 'Name' },
31
+ { field: 'age', title: 'Age' }
32
32
  ]
33
+ grid.sortMode = 'multi' // Enable multi-column sorting
33
34
  </script>
34
35
  ```
35
36
 
@@ -42,7 +43,7 @@ npm install @keenmate/web-grid
42
43
 
43
44
  ## Features
44
45
 
45
- - **Sorting** - Click column headers to sort ascending/descending
46
+ - **Sorting** - Single or multi-column sorting with `sortMode` property
46
47
  - **Filtering** - Per-column text input filters
47
48
  - **Pagination** - Configurable page size with navigation
48
49
  - **Inline Editing** - 7 editor types with validation support
@@ -59,18 +60,23 @@ npm install @keenmate/web-grid
59
60
  |----------|------|---------|-------------|
60
61
  | `items` | `Array` | `[]` | Data array to display |
61
62
  | `columns` | `Array<Column>` | `[]` | Column definitions |
62
- | `sortable` | `boolean` | `false` | Enable column sorting |
63
+ | `sortMode` | `string` | `'none'` | Sort mode: `'none'`, `'single'`, `'multi'` |
63
64
  | `filterable` | `boolean` | `false` | Enable column filtering |
64
65
  | `pageable` | `boolean` | `false` | Enable pagination |
65
66
  | `pageSize` | `number` | `10` | Rows per page |
66
67
  | `editable` | `boolean` | `false` | Enable cell editing |
67
68
  | `editTrigger` | `string` | `'dblclick'` | Edit trigger: `'click'`, `'dblclick'`, `'navigate'` |
69
+ | `editStartSelection` | `string` | `'mousePosition'` | Cursor position when entering edit: `'mousePosition'`, `'selectAll'`, `'cursorAtStart'`, `'cursorAtEnd'` |
68
70
  | `striped` | `boolean` | `false` | Alternate row colors |
69
71
  | `hoverable` | `boolean` | `false` | Highlight row on hover |
70
72
  | `showRowToolbar` | `boolean` | `false` | Show row action toolbar |
71
73
  | `rowToolbar` | `Array` | `[]` | Toolbar items configuration |
72
- | `toolbarTrigger` | `string` | `'hover'` | Toolbar trigger: `'hover'`, `'button'` |
74
+ | `toolbarTrigger` | `string` | `'hover'` | Toolbar trigger: `'hover'`, `'click'`, `'button'` |
75
+ | `toolbarPosition` | `string` | `'auto'` | Toolbar position: `'auto'`, `'left'`, `'right'`, `'top'` |
76
+ | `toolbarAlign` | `string` | `'center'` | Vertical alignment for left/right: `'center'`, `'top'` |
77
+ | `toolbarTopPosition` | `string` | `'center'` | Horizontal position for top: `'start'`, `'center'`, `'end'`, `'cursor'` |
73
78
  | `contextMenu` | `Array` | `[]` | Context menu items |
79
+ | `validationTooltipCallback` | `Function` | `undefined` | Custom HTML tooltip for validation errors: `({ field, error, value, row, rowIndex }) => htmlString` |
74
80
 
75
81
  ## Column Definition
76
82
 
@@ -83,7 +89,7 @@ npm install @keenmate/web-grid
83
89
  maxWidth: '300px', // Maximum width
84
90
  align: 'left', // 'left', 'center', 'right'
85
91
  textOverflow: 'wrap', // 'wrap' or 'ellipsis'
86
- sortable: true, // Enable sorting
92
+ sortable: false, // Disable sorting for this column (when grid has sortMode enabled)
87
93
  filterable: true, // Enable filtering
88
94
  editable: true, // Enable editing
89
95
  editor: 'text', // Editor type
@@ -91,7 +97,8 @@ npm install @keenmate/web-grid
91
97
  formatCallback: (value, row) => '', // Value formatter
92
98
  templateCallback: (row, column) => '', // Custom cell HTML
93
99
  cellClassCallback: (value, row) => '', // Dynamic CSS class
94
- beforeCommitCallback: (ctx) => true // Validation
100
+ beforeCommitCallback: (ctx) => true, // Validation
101
+ validationTooltipCallback: (ctx) => '' // Custom HTML for validation error tooltip
95
102
  }
96
103
  ```
97
104
 
@@ -124,6 +131,11 @@ grid.rowToolbar = [
124
131
  onclick: ({ row, rowIndex }) => { /* ... */ }
125
132
  }
126
133
  ]
134
+
135
+ // Positioning
136
+ grid.toolbarPosition = 'left' // Prefer left side (falls back if no space)
137
+ grid.toolbarAlign = 'top' // Align to top of row (for left/right position)
138
+ grid.toolbarTopPosition = 'cursor' // Position at cursor (for top position)
127
139
  ```
128
140
 
129
141
  ## Context Menu
@@ -10,10 +10,11 @@
10
10
  { "name": "base-text-color-1", "required": true, "usage": "Primary cell and header text" },
11
11
  { "name": "base-text-color-2", "required": false, "usage": "Secondary text, subtitles" },
12
12
  { "name": "base-text-color-3", "required": false, "usage": "Placeholder, disabled, empty state text" },
13
- { "name": "base-text-on-accent", "required": false, "usage": "Text on accent backgrounds" },
14
- { "name": "base-surface-1", "required": true, "usage": "Table background, cell background, inputs" },
15
- { "name": "base-surface-2", "required": true, "usage": "Header background, striped rows, pagination buttons" },
16
- { "name": "base-surface-3", "required": false, "usage": "Hover states, sorted header, active buttons" },
13
+ { "name": "base-text-color-on-accent", "required": false, "usage": "Text on accent backgrounds" },
14
+ { "name": "base-main-bg", "required": true, "usage": "Table background, cell background, inputs" },
15
+ { "name": "base-elevated-bg", "required": true, "usage": "Header background, striped rows, pagination buttons" },
16
+ { "name": "base-hover-bg", "required": false, "usage": "Hover states, sorted header, active buttons" },
17
+ { "name": "base-disabled-bg", "required": false, "usage": "Readonly/disabled cell backgrounds" },
17
18
  { "name": "base-dropdown-bg", "required": false, "usage": "Toolbar, context menu, floating surfaces" },
18
19
  { "name": "base-border-color", "required": true, "usage": "Table, cell, header, toolbar borders" },
19
20
  { "name": "base-input-bg", "required": false, "usage": "Filter input, editor backgrounds" },
package/dist/grid.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Column, CellValidationState, RowToolbarConfig, ContextMenuItem, RowChangeDetail, ToolbarClickDetail, RowActionClickDetail, ContextMenuContext, EditTrigger, EditingCell, FocusedCell, SortState, DataRequestDetail, DataRequestTrigger, BeforeCommitResult, GridMode, ToggleVisibility, PaginationLabelsCallback, SummaryContentCallback } from './types.js';
1
+ import type { Column, CellValidationState, RowToolbarConfig, ContextMenuItem, RowChangeDetail, ToolbarClickDetail, RowActionClickDetail, ContextMenuContext, EditTrigger, EditStartSelection, EditingCell, FocusedCell, SortMode, SortState, DataRequestDetail, DataRequestTrigger, BeforeCommitResult, GridMode, ToggleVisibility, PaginationLabelsCallback, SummaryContentCallback, ValidationTooltipContext } from './types.js';
2
2
  /**
3
3
  * WebGrid - Core logic class for the data grid
4
4
  *
@@ -8,7 +8,7 @@ import type { Column, CellValidationState, RowToolbarConfig, ContextMenuItem, Ro
8
8
  export declare class WebGrid<T = unknown> {
9
9
  protected _items: T[];
10
10
  protected _columns: Column<T>[];
11
- protected _sortable: boolean;
11
+ protected _sortMode: SortMode;
12
12
  protected _filterable: boolean;
13
13
  protected _pageable: boolean;
14
14
  protected _pageSize: number;
@@ -17,6 +17,7 @@ export declare class WebGrid<T = unknown> {
17
17
  protected _hoverable: boolean;
18
18
  protected _editable: boolean;
19
19
  protected _editTrigger: EditTrigger;
20
+ protected _editStartSelection: EditStartSelection;
20
21
  protected _mode: GridMode;
21
22
  protected _dropdownToggleVisibility: ToggleVisibility;
22
23
  protected _dropdownShowOnFocus: boolean;
@@ -29,6 +30,7 @@ export declare class WebGrid<T = unknown> {
29
30
  protected _toolbarAlign: 'center' | 'top';
30
31
  protected _toolbarTopPosition: 'start' | 'center' | 'end' | 'cursor';
31
32
  protected _toolbarTrigger: 'hover' | 'click' | 'button';
33
+ protected _toolbarPosition: 'auto' | 'left' | 'right' | 'top';
32
34
  protected _contextMenu: ContextMenuItem<T>[] | undefined;
33
35
  protected _onrowchange: ((detail: RowChangeDetail<T>) => void) | undefined;
34
36
  protected _onroweditstart: ((detail: {
@@ -47,6 +49,7 @@ export declare class WebGrid<T = unknown> {
47
49
  field: string;
48
50
  error: string;
49
51
  }) => void) | undefined;
52
+ protected _validationTooltipCallback: ((context: ValidationTooltipContext<T>) => string | null) | undefined;
50
53
  protected _ontoolbarclick: ((detail: ToolbarClickDetail<T>) => void) | undefined;
51
54
  protected _onrowaction: ((detail: RowActionClickDetail<T>) => void) | undefined;
52
55
  protected _oncontextmenuopen: ((context: ContextMenuContext<T>) => void) | undefined;
@@ -88,6 +91,9 @@ export declare class WebGrid<T = unknown> {
88
91
  set items(value: T[]);
89
92
  get columns(): Column<T>[];
90
93
  set columns(value: Column<T>[]);
94
+ get sortMode(): SortMode;
95
+ set sortMode(value: SortMode);
96
+ /** @deprecated Use sortMode instead. sortable=true maps to sortMode="multi", sortable=false maps to sortMode="none" */
91
97
  get sortable(): boolean;
92
98
  set sortable(value: boolean);
93
99
  get filterable(): boolean;
@@ -106,6 +112,8 @@ export declare class WebGrid<T = unknown> {
106
112
  set editable(value: boolean);
107
113
  get editTrigger(): EditTrigger;
108
114
  set editTrigger(value: EditTrigger);
115
+ get editStartSelection(): EditStartSelection;
116
+ set editStartSelection(value: EditStartSelection);
109
117
  get mode(): GridMode;
110
118
  set mode(value: GridMode);
111
119
  get dropdownToggleVisibility(): ToggleVisibility;
@@ -141,6 +149,8 @@ export declare class WebGrid<T = unknown> {
141
149
  set toolbarTopPosition(value: 'start' | 'center' | 'end' | 'cursor');
142
150
  get toolbarTrigger(): 'hover' | 'click' | 'button';
143
151
  set toolbarTrigger(value: 'hover' | 'click' | 'button');
152
+ get toolbarPosition(): 'auto' | 'left' | 'right' | 'top';
153
+ set toolbarPosition(value: 'auto' | 'left' | 'right' | 'top');
144
154
  get contextMenu(): ContextMenuItem<T>[] | undefined;
145
155
  set contextMenu(value: ContextMenuItem<T>[] | undefined);
146
156
  get sort(): SortState[];
@@ -210,6 +220,8 @@ export declare class WebGrid<T = unknown> {
210
220
  field: string;
211
221
  error: string;
212
222
  }) => void) | undefined);
223
+ get validationTooltipCallback(): ((context: ValidationTooltipContext<T>) => string | null) | undefined;
224
+ set validationTooltipCallback(value: ((context: ValidationTooltipContext<T>) => string | null) | undefined);
213
225
  get ontoolbarclick(): ((detail: ToolbarClickDetail<T>) => void) | undefined;
214
226
  set ontoolbarclick(value: ((detail: ToolbarClickDetail<T>) => void) | undefined);
215
227
  set onrowaction(value: ((detail: RowActionClickDetail<T>) => void) | undefined);
@@ -47,6 +47,7 @@ export declare function getConnectorState(): ConnectorState;
47
47
  /**
48
48
  * Update connector path after row has moved
49
49
  * Call this after a moveUp/moveDown action to draw the bracket-shaped connector
50
+ * The connector is clipped at grid container boundaries
50
51
  */
51
52
  export declare function updateConnector<T>(ctx: GridContext<T>, displayItems: T[]): void;
52
53
  /**
@@ -2,7 +2,7 @@ import type { GridContext } from '../types.js';
2
2
  /**
3
3
  * Show tooltip for an element
4
4
  */
5
- export declare function showTooltip<T>(ctx: GridContext<T>, anchor: HTMLElement, text: string, delay?: number): void;
5
+ export declare function showTooltip<T>(ctx: GridContext<T>, anchor: HTMLElement, text: string, delay?: number, isHtml?: boolean): void;
6
6
  /**
7
7
  * Hide tooltip
8
8
  */
@@ -10,4 +10,4 @@ export declare function hideTooltip<T>(ctx: GridContext<T>, delay?: number): voi
10
10
  /**
11
11
  * Create and position tooltip element
12
12
  */
13
- export declare function createTooltip<T>(ctx: GridContext<T>, anchor: HTMLElement, text: string): void;
13
+ export declare function createTooltip<T>(ctx: GridContext<T>, anchor: HTMLElement, content: string, isHtml?: boolean): void;
package/dist/types.d.ts CHANGED
@@ -4,7 +4,7 @@ export type GridMode = "read-only" | "excel" | "input-matrix";
4
4
  export type ToggleVisibility = "always" | "on-focus";
5
5
  export type OptionsLoadTrigger = "immediate" | "oneditstart" | "ondropdownopen";
6
6
  export type DateOutputFormat = "date" | "iso" | "timestamp";
7
- export type EditStartSelection = "selectAll" | "cursorAtStart" | "cursorAtEnd";
7
+ export type EditStartSelection = "mousePosition" | "selectAll" | "cursorAtStart" | "cursorAtEnd";
8
8
  export type EditorOption = {
9
9
  value: string | number | boolean;
10
10
  label: string;
@@ -118,6 +118,14 @@ export type Column<T> = {
118
118
  tooltipCallback?: (value: unknown, row: T) => string | null;
119
119
  beforeCopyCallback?: (value: unknown, row: T) => string;
120
120
  beforePasteCallback?: (value: string, row: T) => unknown;
121
+ validationTooltipCallback?: (context: ValidationTooltipContext<T>) => string | null;
122
+ };
123
+ export type ValidationTooltipContext<T> = {
124
+ field: string;
125
+ error: string;
126
+ value: unknown;
127
+ row: T;
128
+ rowIndex: number;
121
129
  };
122
130
  export type RowChangeDetail<T> = {
123
131
  row: T;
@@ -178,6 +186,7 @@ export type ContextMenuItem<T> = {
178
186
  export type QuickGridProps<T> = {
179
187
  items: T[];
180
188
  columns: Column<T>[];
189
+ /** @deprecated Use sortMode instead */
181
190
  sortable?: boolean;
182
191
  filterable?: boolean;
183
192
  pageable?: boolean;
@@ -190,6 +199,7 @@ export type QuickGridProps<T> = {
190
199
  customStylesCallback?: () => string;
191
200
  rowClassCallback?: (row: T, rowIndex: number) => string | null;
192
201
  sort?: SortState[];
202
+ sortMode?: SortMode;
193
203
  currentPage?: number;
194
204
  totalItems?: number;
195
205
  showPagination?: boolean | 'auto';
@@ -202,6 +212,7 @@ export type QuickGridProps<T> = {
202
212
  summaryInline?: boolean;
203
213
  editable?: boolean;
204
214
  editTrigger?: EditTrigger;
215
+ editStartSelection?: EditStartSelection;
205
216
  mode?: GridMode;
206
217
  dropdownToggleVisibility?: ToggleVisibility;
207
218
  dropdownShowOnFocus?: boolean;
@@ -213,6 +224,7 @@ export type QuickGridProps<T> = {
213
224
  toolbarAlign?: 'center' | 'top';
214
225
  toolbarTopPosition?: 'start' | 'center' | 'end' | 'cursor';
215
226
  toolbarTrigger?: 'hover' | 'click' | 'button';
227
+ toolbarPosition?: 'auto' | 'left' | 'right' | 'top';
216
228
  showRowActions?: boolean;
217
229
  rowActions?: RowToolbarConfig<T>[];
218
230
  contextMenu?: ContextMenuItem<T>[];
@@ -241,6 +253,7 @@ export type QuickGridProps<T> = {
241
253
  field: string;
242
254
  error: string;
243
255
  }) => void;
256
+ validationTooltipCallback?: (context: ValidationTooltipContext<T>) => string | null;
244
257
  ontoolbarclick?: (detail: ToolbarClickDetail<T>) => void;
245
258
  onrowaction?: (detail: RowActionClickDetail<T>) => void;
246
259
  ondatarequest?: (detail: DataRequestDetail) => void;
@@ -260,6 +273,7 @@ export type FocusedCell = {
260
273
  colIndex: number;
261
274
  } | null;
262
275
  export type SortDirection = "asc" | "desc";
276
+ export type SortMode = "none" | "single" | "multi";
263
277
  export type ToolbarRowGroup<T> = {
264
278
  rowNum: number;
265
279
  groups: {
@@ -1,5 +1,5 @@
1
1
  import { WebGrid } from './grid.js';
2
- import type { Column, CellValidationState, RowToolbarConfig, ContextMenuItem, RowChangeDetail, ToolbarClickDetail, RowActionClickDetail, ContextMenuContext, EditTrigger, EditorOption, EditorOptions, GridMode, ToggleVisibility, DataRequestDetail, SortState, PaginationLabelsCallback, SummaryContentCallback } from './types.js';
2
+ import type { Column, CellValidationState, RowToolbarConfig, ContextMenuItem, RowChangeDetail, ToolbarClickDetail, RowActionClickDetail, ContextMenuContext, EditTrigger, EditStartSelection, EditorOption, EditorOptions, GridMode, ToggleVisibility, DataRequestDetail, SortState, SortMode, PaginationLabelsCallback, SummaryContentCallback, ValidationTooltipContext } from './types.js';
3
3
  import type { GridContext } from './modules/types.js';
4
4
  /**
5
5
  * GridElement - Custom HTML Element for WebGrid
@@ -83,6 +83,8 @@ export declare class GridElement<T = unknown> extends HTMLElement implements Gri
83
83
  set editable(value: boolean);
84
84
  get editTrigger(): EditTrigger;
85
85
  set editTrigger(value: EditTrigger);
86
+ get editStartSelection(): EditStartSelection;
87
+ set editStartSelection(value: EditStartSelection);
86
88
  get mode(): GridMode;
87
89
  set mode(value: GridMode);
88
90
  get dropdownToggleVisibility(): ToggleVisibility;
@@ -107,6 +109,8 @@ export declare class GridElement<T = unknown> extends HTMLElement implements Gri
107
109
  set toolbarTopPosition(value: 'start' | 'center' | 'end' | 'cursor');
108
110
  get toolbarTrigger(): 'hover' | 'click' | 'button';
109
111
  set toolbarTrigger(value: 'hover' | 'click' | 'button');
112
+ get toolbarPosition(): 'auto' | 'left' | 'right' | 'top';
113
+ set toolbarPosition(value: 'auto' | 'left' | 'right' | 'top');
110
114
  get contextMenu(): ContextMenuItem<T>[] | undefined;
111
115
  set contextMenu(value: ContextMenuItem<T>[] | undefined);
112
116
  get showRowActions(): boolean;
@@ -130,6 +134,8 @@ export declare class GridElement<T = unknown> extends HTMLElement implements Gri
130
134
  field: string;
131
135
  error: string;
132
136
  }) => void) | undefined);
137
+ get validationTooltipCallback(): ((context: ValidationTooltipContext<T>) => string | null) | undefined;
138
+ set validationTooltipCallback(value: ((context: ValidationTooltipContext<T>) => string | null) | undefined);
133
139
  set ontoolbarclick(value: ((detail: ToolbarClickDetail<T>) => void) | undefined);
134
140
  set onrowaction(value: ((detail: RowActionClickDetail<T>) => void) | undefined);
135
141
  set oncontextmenuopen(value: ((context: ContextMenuContext<T>) => void) | undefined);
@@ -145,6 +151,8 @@ export declare class GridElement<T = unknown> extends HTMLElement implements Gri
145
151
  }) => void) | undefined);
146
152
  get sort(): SortState[];
147
153
  set sort(value: SortState[]);
154
+ get sortMode(): SortMode;
155
+ set sortMode(value: SortMode);
148
156
  get currentPage(): number;
149
157
  set currentPage(value: number);
150
158
  get totalItems(): number | null;