@alaarab/ogrid-js 2.0.3 → 2.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/OGrid.js +37 -5
- package/dist/esm/components/InlineCellEditor.js +1 -0
- package/dist/esm/renderer/TableRenderer.js +34 -3
- package/dist/esm/state/ColumnPinningState.js +7 -2
- package/dist/esm/state/SelectionState.js +3 -0
- package/dist/styles/ogrid.css +4 -0
- package/dist/types/renderer/TableRenderer.d.ts +3 -1
- package/dist/types/state/ColumnPinningState.d.ts +1 -1
- package/dist/types/state/SelectionState.d.ts +1 -0
- package/dist/types/types/gridTypes.d.ts +2 -0
- package/package.json +2 -2
package/dist/esm/OGrid.js
CHANGED
|
@@ -341,7 +341,7 @@ export class OGrid {
|
|
|
341
341
|
const visibleCols = this.state.visibleColumnDefs;
|
|
342
342
|
// Compute pinning offsets
|
|
343
343
|
const columnWidths = this.layoutState.getAllColumnWidths();
|
|
344
|
-
const leftOffsets = this.pinningState?.computeLeftOffsets(visibleCols, columnWidths, 120, !!this.rowSelectionState, 40) ?? {};
|
|
344
|
+
const leftOffsets = this.pinningState?.computeLeftOffsets(visibleCols, columnWidths, 120, !!this.rowSelectionState, 40, !!this.options.showRowNumbers) ?? {};
|
|
345
345
|
const rightOffsets = this.pinningState?.computeRightOffsets(visibleCols, columnWidths, 120) ?? {};
|
|
346
346
|
this.renderer.setInteractionState({
|
|
347
347
|
activeCell: this.selectionState.activeCell,
|
|
@@ -368,6 +368,8 @@ export class OGrid {
|
|
|
368
368
|
},
|
|
369
369
|
allSelected: this.rowSelectionState?.isAllSelected(items),
|
|
370
370
|
someSelected: this.rowSelectionState?.isSomeSelected(items),
|
|
371
|
+
// Row numbers
|
|
372
|
+
showRowNumbers: this.options.showRowNumbers,
|
|
371
373
|
// Column pinning
|
|
372
374
|
pinnedColumns: this.pinningState?.pinnedColumns,
|
|
373
375
|
leftOffsets,
|
|
@@ -392,15 +394,43 @@ export class OGrid {
|
|
|
392
394
|
if (!range)
|
|
393
395
|
return;
|
|
394
396
|
const norm = normalizeSelectionRange(range);
|
|
397
|
+
const anchor = this.selectionState.dragAnchor;
|
|
398
|
+
const minR = norm.startRow;
|
|
399
|
+
const maxR = norm.endRow;
|
|
400
|
+
const minC = norm.startCol;
|
|
401
|
+
const maxC = norm.endCol;
|
|
395
402
|
const cells = wrapper.querySelectorAll('td[data-row-index][data-col-index]');
|
|
396
403
|
for (const cell of Array.from(cells)) {
|
|
397
|
-
const
|
|
398
|
-
const
|
|
404
|
+
const el = cell;
|
|
405
|
+
const rowIndex = parseInt(el.getAttribute('data-row-index') ?? '-1', 10);
|
|
406
|
+
const colIndex = parseInt(el.getAttribute('data-col-index') ?? '-1', 10);
|
|
399
407
|
if (isInSelectionRange(norm, rowIndex, colIndex)) {
|
|
400
|
-
|
|
408
|
+
el.setAttribute('data-drag-range', 'true');
|
|
409
|
+
// Anchor cell (white background)
|
|
410
|
+
const isAnchor = anchor && rowIndex === anchor.rowIndex && colIndex === anchor.columnIndex;
|
|
411
|
+
if (isAnchor) {
|
|
412
|
+
el.setAttribute('data-drag-anchor', '');
|
|
413
|
+
}
|
|
414
|
+
else {
|
|
415
|
+
el.removeAttribute('data-drag-anchor');
|
|
416
|
+
}
|
|
417
|
+
// Edge borders via inset box-shadow
|
|
418
|
+
const shadows = [];
|
|
419
|
+
if (rowIndex === minR)
|
|
420
|
+
shadows.push('inset 0 2px 0 0 var(--ogrid-selection, #217346)');
|
|
421
|
+
if (rowIndex === maxR)
|
|
422
|
+
shadows.push('inset 0 -2px 0 0 var(--ogrid-selection, #217346)');
|
|
423
|
+
if (colIndex === minC)
|
|
424
|
+
shadows.push('inset 2px 0 0 0 var(--ogrid-selection, #217346)');
|
|
425
|
+
if (colIndex === maxC)
|
|
426
|
+
shadows.push('inset -2px 0 0 0 var(--ogrid-selection, #217346)');
|
|
427
|
+
el.style.boxShadow = shadows.length > 0 ? shadows.join(', ') : '';
|
|
401
428
|
}
|
|
402
429
|
else {
|
|
403
|
-
|
|
430
|
+
el.removeAttribute('data-drag-range');
|
|
431
|
+
el.removeAttribute('data-drag-anchor');
|
|
432
|
+
if (el.style.boxShadow)
|
|
433
|
+
el.style.boxShadow = '';
|
|
404
434
|
}
|
|
405
435
|
}
|
|
406
436
|
}
|
|
@@ -416,6 +446,8 @@ export class OGrid {
|
|
|
416
446
|
return;
|
|
417
447
|
e.preventDefault();
|
|
418
448
|
this.selectionState.startDrag(rowIndex, colIndex);
|
|
449
|
+
// Apply drag attributes immediately for instant visual feedback on the initial cell
|
|
450
|
+
setTimeout(() => this.updateDragAttributes(), 0);
|
|
419
451
|
}
|
|
420
452
|
handleCellContextMenu(rowIndex, colIndex, e) {
|
|
421
453
|
e.preventDefault();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getCellValue, buildHeaderRows, isInSelectionRange } from '@alaarab/ogrid-core';
|
|
1
|
+
import { getCellValue, buildHeaderRows, isInSelectionRange, ROW_NUMBER_COLUMN_WIDTH } from '@alaarab/ogrid-core';
|
|
2
2
|
const CHECKBOX_COL_WIDTH = 40;
|
|
3
3
|
export class TableRenderer {
|
|
4
4
|
constructor(container, state) {
|
|
@@ -80,9 +80,17 @@ export class TableRenderer {
|
|
|
80
80
|
const mode = this.interactionState?.rowSelectionMode;
|
|
81
81
|
return mode === 'single' || mode === 'multiple';
|
|
82
82
|
}
|
|
83
|
-
|
|
83
|
+
hasRowNumbersColumn() {
|
|
84
|
+
return !!this.interactionState?.showRowNumbers;
|
|
85
|
+
}
|
|
86
|
+
/** The column index offset for data columns (checkbox + row numbers if present). */
|
|
84
87
|
getColOffset() {
|
|
85
|
-
|
|
88
|
+
let offset = 0;
|
|
89
|
+
if (this.hasCheckboxColumn())
|
|
90
|
+
offset++;
|
|
91
|
+
if (this.hasRowNumbersColumn())
|
|
92
|
+
offset++;
|
|
93
|
+
return offset;
|
|
86
94
|
}
|
|
87
95
|
applyPinningStyles(el, columnId, isHeader) {
|
|
88
96
|
const is = this.interactionState;
|
|
@@ -182,6 +190,15 @@ export class TableRenderer {
|
|
|
182
190
|
this.appendSelectAllCheckbox(th);
|
|
183
191
|
tr.appendChild(th);
|
|
184
192
|
}
|
|
193
|
+
// Row numbers header
|
|
194
|
+
if (this.hasRowNumbersColumn()) {
|
|
195
|
+
const th = document.createElement('th');
|
|
196
|
+
th.className = 'ogrid-header-cell ogrid-row-number-header';
|
|
197
|
+
th.style.width = `${ROW_NUMBER_COLUMN_WIDTH}px`;
|
|
198
|
+
th.style.textAlign = 'center';
|
|
199
|
+
th.textContent = '#';
|
|
200
|
+
tr.appendChild(th);
|
|
201
|
+
}
|
|
185
202
|
for (let colIdx = 0; colIdx < visibleCols.length; colIdx++) {
|
|
186
203
|
const col = visibleCols[colIdx];
|
|
187
204
|
const th = document.createElement('th');
|
|
@@ -294,8 +311,11 @@ export class TableRenderer {
|
|
|
294
311
|
const visibleCols = this.state.visibleColumnDefs;
|
|
295
312
|
const { items } = this.state.getProcessedItems();
|
|
296
313
|
const hasCheckbox = this.hasCheckboxColumn();
|
|
314
|
+
const hasRowNumbers = this.hasRowNumbersColumn();
|
|
297
315
|
const colOffset = this.getColOffset();
|
|
298
316
|
const totalColSpan = visibleCols.length + colOffset;
|
|
317
|
+
// Calculate row number offset for pagination
|
|
318
|
+
const rowNumberOffset = hasRowNumbers ? (this.state.page - 1) * this.state.pageSize : 0;
|
|
299
319
|
if (items.length === 0 && !this.state.isLoading) {
|
|
300
320
|
const tr = document.createElement('tr');
|
|
301
321
|
const td = document.createElement('td');
|
|
@@ -359,6 +379,17 @@ export class TableRenderer {
|
|
|
359
379
|
td.appendChild(checkbox);
|
|
360
380
|
tr.appendChild(td);
|
|
361
381
|
}
|
|
382
|
+
// Row numbers column
|
|
383
|
+
if (hasRowNumbers) {
|
|
384
|
+
const td = document.createElement('td');
|
|
385
|
+
td.className = 'ogrid-cell ogrid-row-number-cell';
|
|
386
|
+
td.style.width = `${ROW_NUMBER_COLUMN_WIDTH}px`;
|
|
387
|
+
td.style.textAlign = 'center';
|
|
388
|
+
td.style.color = 'var(--ogrid-fg-muted, #666)';
|
|
389
|
+
td.style.fontSize = '0.9em';
|
|
390
|
+
td.textContent = String(rowNumberOffset + rowIndex + 1);
|
|
391
|
+
tr.appendChild(td);
|
|
392
|
+
}
|
|
362
393
|
for (let colIndex = 0; colIndex < visibleCols.length; colIndex++) {
|
|
363
394
|
const col = visibleCols[colIndex];
|
|
364
395
|
const globalColIndex = colIndex + colOffset;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ROW_NUMBER_COLUMN_WIDTH } from '@alaarab/ogrid-core';
|
|
1
2
|
import { EventEmitter } from './EventEmitter';
|
|
2
3
|
/**
|
|
3
4
|
* Manages column pinning state — tracks which columns are pinned left/right.
|
|
@@ -40,9 +41,13 @@ export class ColumnPinningState {
|
|
|
40
41
|
* Compute sticky left offsets for left-pinned columns.
|
|
41
42
|
* Returns a map of columnId -> left offset in pixels.
|
|
42
43
|
*/
|
|
43
|
-
computeLeftOffsets(visibleCols, columnWidths, defaultWidth, hasCheckboxColumn, checkboxColumnWidth) {
|
|
44
|
+
computeLeftOffsets(visibleCols, columnWidths, defaultWidth, hasCheckboxColumn, checkboxColumnWidth, hasRowNumbersColumn) {
|
|
44
45
|
const offsets = {};
|
|
45
|
-
let left =
|
|
46
|
+
let left = 0;
|
|
47
|
+
if (hasCheckboxColumn)
|
|
48
|
+
left += checkboxColumnWidth;
|
|
49
|
+
if (hasRowNumbersColumn)
|
|
50
|
+
left += ROW_NUMBER_COLUMN_WIDTH;
|
|
46
51
|
for (const col of visibleCols) {
|
|
47
52
|
if (this._pinnedColumns[col.columnId] === 'left') {
|
|
48
53
|
offsets[col.columnId] = left;
|
package/dist/styles/ogrid.css
CHANGED
|
@@ -25,6 +25,7 @@ export interface TableRendererInteractionState {
|
|
|
25
25
|
onSelectAll?: (checked: boolean) => void;
|
|
26
26
|
allSelected?: boolean;
|
|
27
27
|
someSelected?: boolean;
|
|
28
|
+
showRowNumbers?: boolean;
|
|
28
29
|
pinnedColumns?: Record<string, 'left' | 'right'>;
|
|
29
30
|
leftOffsets?: Record<string, number>;
|
|
30
31
|
rightOffsets?: Record<string, number>;
|
|
@@ -54,7 +55,8 @@ export declare class TableRenderer<T> {
|
|
|
54
55
|
/** Re-render body rows and header (after sort/filter/page change). */
|
|
55
56
|
update(): void;
|
|
56
57
|
private hasCheckboxColumn;
|
|
57
|
-
|
|
58
|
+
private hasRowNumbersColumn;
|
|
59
|
+
/** The column index offset for data columns (checkbox + row numbers if present). */
|
|
58
60
|
getColOffset(): number;
|
|
59
61
|
private applyPinningStyles;
|
|
60
62
|
private renderHeader;
|
|
@@ -22,7 +22,7 @@ export declare class ColumnPinningState {
|
|
|
22
22
|
*/
|
|
23
23
|
computeLeftOffsets(visibleCols: {
|
|
24
24
|
columnId: string;
|
|
25
|
-
}[], columnWidths: Record<string, number>, defaultWidth: number, hasCheckboxColumn: boolean, checkboxColumnWidth: number): Record<string, number>;
|
|
25
|
+
}[], columnWidths: Record<string, number>, defaultWidth: number, hasCheckboxColumn: boolean, checkboxColumnWidth: number, hasRowNumbersColumn?: boolean): Record<string, number>;
|
|
26
26
|
/**
|
|
27
27
|
* Compute sticky right offsets for right-pinned columns.
|
|
28
28
|
* Returns a map of columnId -> right offset in pixels.
|
|
@@ -18,6 +18,7 @@ export declare class SelectionState {
|
|
|
18
18
|
private rafHandle;
|
|
19
19
|
private pendingRange;
|
|
20
20
|
get activeCell(): IActiveCell | null;
|
|
21
|
+
get dragAnchor(): IActiveCell | null;
|
|
21
22
|
get selectionRange(): ISelectionRange | null;
|
|
22
23
|
get selectedRowIds(): Set<RowId>;
|
|
23
24
|
get isDragging(): boolean;
|
|
@@ -39,6 +39,8 @@ export interface OGridOptions<T> {
|
|
|
39
39
|
cellSelection?: boolean;
|
|
40
40
|
/** Callback fired when a cell value is changed via editing. */
|
|
41
41
|
onCellValueChanged?: (event: ICellValueChangedEvent<T>) => void;
|
|
42
|
+
/** Show row numbers column. Default: false. */
|
|
43
|
+
showRowNumbers?: boolean;
|
|
42
44
|
rowSelection?: RowSelectionMode;
|
|
43
45
|
/** Callback fired when row selection changes. */
|
|
44
46
|
onSelectionChange?: (event: IRowSelectionChangeEvent<T>) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alaarab/ogrid-js",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.5",
|
|
4
4
|
"description": "OGrid vanilla JS – framework-free data grid with sorting, filtering, pagination, and spreadsheet-style editing.",
|
|
5
5
|
"main": "dist/esm/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"files": ["dist", "README.md", "LICENSE"],
|
|
24
24
|
"engines": { "node": ">=18" },
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@alaarab/ogrid-core": "2.0.
|
|
26
|
+
"@alaarab/ogrid-core": "2.0.5"
|
|
27
27
|
},
|
|
28
28
|
"publishConfig": { "access": "public" }
|
|
29
29
|
}
|