@alaarab/ogrid-js 2.0.0-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/esm/OGrid.js +654 -0
  2. package/dist/esm/components/ColumnChooser.js +68 -0
  3. package/dist/esm/components/ContextMenu.js +122 -0
  4. package/dist/esm/components/HeaderFilter.js +281 -0
  5. package/dist/esm/components/InlineCellEditor.js +278 -0
  6. package/dist/esm/components/MarchingAntsOverlay.js +170 -0
  7. package/dist/esm/components/PaginationControls.js +85 -0
  8. package/dist/esm/components/SideBar.js +353 -0
  9. package/dist/esm/components/StatusBar.js +34 -0
  10. package/dist/esm/index.js +26 -0
  11. package/dist/esm/renderer/TableRenderer.js +414 -0
  12. package/dist/esm/state/ClipboardState.js +171 -0
  13. package/dist/esm/state/ColumnPinningState.js +78 -0
  14. package/dist/esm/state/ColumnResizeState.js +55 -0
  15. package/dist/esm/state/EventEmitter.js +27 -0
  16. package/dist/esm/state/FillHandleState.js +218 -0
  17. package/dist/esm/state/GridState.js +261 -0
  18. package/dist/esm/state/HeaderFilterState.js +205 -0
  19. package/dist/esm/state/KeyboardNavState.js +374 -0
  20. package/dist/esm/state/RowSelectionState.js +81 -0
  21. package/dist/esm/state/SelectionState.js +102 -0
  22. package/dist/esm/state/SideBarState.js +41 -0
  23. package/dist/esm/state/TableLayoutState.js +95 -0
  24. package/dist/esm/state/UndoRedoState.js +82 -0
  25. package/dist/esm/types/columnTypes.js +1 -0
  26. package/dist/esm/types/gridTypes.js +1 -0
  27. package/dist/esm/types/index.js +2 -0
  28. package/dist/types/OGrid.d.ts +60 -0
  29. package/dist/types/components/ColumnChooser.d.ts +14 -0
  30. package/dist/types/components/ContextMenu.d.ts +17 -0
  31. package/dist/types/components/HeaderFilter.d.ts +24 -0
  32. package/dist/types/components/InlineCellEditor.d.ts +24 -0
  33. package/dist/types/components/MarchingAntsOverlay.d.ts +25 -0
  34. package/dist/types/components/PaginationControls.d.ts +9 -0
  35. package/dist/types/components/SideBar.d.ts +35 -0
  36. package/dist/types/components/StatusBar.d.ts +8 -0
  37. package/dist/types/index.d.ts +26 -0
  38. package/dist/types/renderer/TableRenderer.d.ts +59 -0
  39. package/dist/types/state/ClipboardState.d.ts +35 -0
  40. package/dist/types/state/ColumnPinningState.d.ts +36 -0
  41. package/dist/types/state/ColumnResizeState.d.ts +23 -0
  42. package/dist/types/state/EventEmitter.d.ts +9 -0
  43. package/dist/types/state/FillHandleState.d.ts +51 -0
  44. package/dist/types/state/GridState.d.ts +68 -0
  45. package/dist/types/state/HeaderFilterState.d.ts +64 -0
  46. package/dist/types/state/KeyboardNavState.d.ts +29 -0
  47. package/dist/types/state/RowSelectionState.d.ts +23 -0
  48. package/dist/types/state/SelectionState.d.ts +37 -0
  49. package/dist/types/state/SideBarState.d.ts +19 -0
  50. package/dist/types/state/TableLayoutState.d.ts +33 -0
  51. package/dist/types/state/UndoRedoState.d.ts +28 -0
  52. package/dist/types/types/columnTypes.d.ts +28 -0
  53. package/dist/types/types/gridTypes.d.ts +69 -0
  54. package/dist/types/types/index.d.ts +2 -0
  55. package/package.json +29 -0
@@ -0,0 +1,102 @@
1
+ import { EventEmitter } from './EventEmitter';
2
+ export class SelectionState {
3
+ constructor() {
4
+ this.emitter = new EventEmitter();
5
+ this._activeCell = null;
6
+ this._selectionRange = null;
7
+ this._selectedRowIds = new Set();
8
+ this._isDragging = false;
9
+ this.dragStartCell = null;
10
+ this.rafHandle = null;
11
+ this.pendingRange = null;
12
+ }
13
+ get activeCell() {
14
+ return this._activeCell;
15
+ }
16
+ get selectionRange() {
17
+ return this._selectionRange;
18
+ }
19
+ get selectedRowIds() {
20
+ return this._selectedRowIds;
21
+ }
22
+ get isDragging() {
23
+ return this._isDragging;
24
+ }
25
+ /** Get the current drag range (used during drag for DOM attribute updates). */
26
+ getDragRange() {
27
+ return this.pendingRange;
28
+ }
29
+ setActiveCell(cell) {
30
+ this._activeCell = cell;
31
+ this._selectionRange = cell != null
32
+ ? { startRow: cell.rowIndex, startCol: cell.columnIndex, endRow: cell.rowIndex, endCol: cell.columnIndex }
33
+ : null;
34
+ this.emitter.emit('selectionChange', { activeCell: cell, selectionRange: this._selectionRange });
35
+ }
36
+ setSelectionRange(range) {
37
+ this._selectionRange = range;
38
+ this.emitter.emit('selectionChange', { activeCell: this._activeCell, selectionRange: range });
39
+ }
40
+ clearSelection() {
41
+ this._activeCell = null;
42
+ this._selectionRange = null;
43
+ this.emitter.emit('selectionChange', { activeCell: null, selectionRange: null });
44
+ }
45
+ startDrag(rowIndex, colIndex) {
46
+ this._isDragging = true;
47
+ this.dragStartCell = { rowIndex, columnIndex: colIndex };
48
+ this._activeCell = { rowIndex, columnIndex: colIndex };
49
+ this._selectionRange = { startRow: rowIndex, startCol: colIndex, endRow: rowIndex, endCol: colIndex };
50
+ }
51
+ updateDrag(rowIndex, colIndex, applyFn) {
52
+ if (!this._isDragging || !this.dragStartCell)
53
+ return;
54
+ const newRange = {
55
+ startRow: this.dragStartCell.rowIndex,
56
+ startCol: this.dragStartCell.columnIndex,
57
+ endRow: rowIndex,
58
+ endCol: colIndex,
59
+ };
60
+ this.pendingRange = newRange;
61
+ if (this.rafHandle === null) {
62
+ this.rafHandle = requestAnimationFrame(() => {
63
+ if (this.pendingRange) {
64
+ applyFn(this.pendingRange);
65
+ }
66
+ this.rafHandle = null;
67
+ });
68
+ }
69
+ }
70
+ endDrag() {
71
+ if (this.rafHandle !== null) {
72
+ // Flush pending RAF synchronously before ending drag (critical for jsdom tests)
73
+ cancelAnimationFrame(this.rafHandle);
74
+ this.rafHandle = null;
75
+ }
76
+ if (this.pendingRange) {
77
+ this._selectionRange = this.pendingRange;
78
+ this.pendingRange = null;
79
+ this.emitter.emit('selectionChange', { activeCell: this._activeCell, selectionRange: this._selectionRange });
80
+ }
81
+ this._isDragging = false;
82
+ this.dragStartCell = null;
83
+ }
84
+ setSelectedRowIds(ids) {
85
+ this._selectedRowIds = ids;
86
+ this.emitter.emit('rowSelectionChange', { selectedRowIds: ids });
87
+ }
88
+ onSelectionChange(handler) {
89
+ this.emitter.on('selectionChange', handler);
90
+ return () => this.emitter.off('selectionChange', handler);
91
+ }
92
+ onRowSelectionChange(handler) {
93
+ this.emitter.on('rowSelectionChange', handler);
94
+ return () => this.emitter.off('rowSelectionChange', handler);
95
+ }
96
+ destroy() {
97
+ if (this.rafHandle !== null) {
98
+ cancelAnimationFrame(this.rafHandle);
99
+ }
100
+ this.emitter.removeAllListeners();
101
+ }
102
+ }
@@ -0,0 +1,41 @@
1
+ import { EventEmitter } from './EventEmitter';
2
+ const DEFAULT_PANELS = ['columns', 'filters'];
3
+ export class SideBarState {
4
+ constructor(config) {
5
+ this.emitter = new EventEmitter();
6
+ this._isEnabled = config != null && config !== false;
7
+ if (!this._isEnabled || config === true) {
8
+ this._panels = DEFAULT_PANELS;
9
+ this._position = 'right';
10
+ this._activePanel = null;
11
+ }
12
+ else {
13
+ const def = config;
14
+ this._panels = def.panels ?? DEFAULT_PANELS;
15
+ this._position = def.position ?? 'right';
16
+ this._activePanel = def.defaultPanel ?? null;
17
+ }
18
+ }
19
+ get isEnabled() { return this._isEnabled; }
20
+ get panels() { return this._panels; }
21
+ get position() { return this._position; }
22
+ get activePanel() { return this._activePanel; }
23
+ get isOpen() { return this._activePanel !== null; }
24
+ setActivePanel(panel) {
25
+ this._activePanel = panel;
26
+ this.emitter.emit('change', undefined);
27
+ }
28
+ toggle(panel) {
29
+ this.setActivePanel(this._activePanel === panel ? null : panel);
30
+ }
31
+ close() {
32
+ this.setActivePanel(null);
33
+ }
34
+ onChange(handler) {
35
+ this.emitter.on('change', handler);
36
+ return () => this.emitter.off('change', handler);
37
+ }
38
+ destroy() {
39
+ this.emitter.removeAllListeners();
40
+ }
41
+ }
@@ -0,0 +1,95 @@
1
+ import { DEFAULT_MIN_COLUMN_WIDTH, CELL_PADDING, CHECKBOX_COLUMN_WIDTH } from '@alaarab/ogrid-core';
2
+ import { EventEmitter } from './EventEmitter';
3
+ export class TableLayoutState {
4
+ constructor() {
5
+ this.emitter = new EventEmitter();
6
+ this._containerWidth = 0;
7
+ this._columnSizingOverrides = {};
8
+ this._ro = null;
9
+ }
10
+ /** Start observing a container element for resize. */
11
+ observeContainer(el) {
12
+ this.disconnectObserver();
13
+ // ResizeObserver may not be available in jsdom test environments
14
+ if (typeof ResizeObserver !== 'undefined') {
15
+ this._ro = new ResizeObserver((entries) => {
16
+ for (const entry of entries) {
17
+ const rect = entry.contentRect;
18
+ this._containerWidth = rect.width;
19
+ this.emitter.emit('layoutChange', { type: 'containerResize' });
20
+ }
21
+ });
22
+ this._ro.observe(el);
23
+ }
24
+ // Measure initial size
25
+ this._containerWidth = el.clientWidth;
26
+ }
27
+ disconnectObserver() {
28
+ if (this._ro) {
29
+ this._ro.disconnect();
30
+ this._ro = null;
31
+ }
32
+ }
33
+ get containerWidth() {
34
+ return this._containerWidth;
35
+ }
36
+ get columnSizingOverrides() {
37
+ return this._columnSizingOverrides;
38
+ }
39
+ /** Set a column width override (from resize drag). */
40
+ setColumnOverride(columnId, widthPx) {
41
+ this._columnSizingOverrides = { ...this._columnSizingOverrides, [columnId]: widthPx };
42
+ this.emitter.emit('layoutChange', { type: 'columnOverride' });
43
+ }
44
+ /** Compute minimum table width from visible columns. */
45
+ computeMinTableWidth(visibleColumnCount, hasCheckboxColumn) {
46
+ const checkboxWidth = hasCheckboxColumn ? CHECKBOX_COLUMN_WIDTH : 0;
47
+ return checkboxWidth + visibleColumnCount * (DEFAULT_MIN_COLUMN_WIDTH + CELL_PADDING);
48
+ }
49
+ /** Compute desired table width respecting overrides. */
50
+ computeDesiredTableWidth(visibleColumns, hasCheckboxColumn) {
51
+ const checkboxWidth = hasCheckboxColumn ? CHECKBOX_COLUMN_WIDTH : 0;
52
+ let total = checkboxWidth;
53
+ for (const col of visibleColumns) {
54
+ const override = this._columnSizingOverrides[col.columnId];
55
+ if (override) {
56
+ total += override + CELL_PADDING;
57
+ }
58
+ else {
59
+ total += (col.width ?? col.minWidth ?? DEFAULT_MIN_COLUMN_WIDTH) + CELL_PADDING;
60
+ }
61
+ }
62
+ return total;
63
+ }
64
+ /** Get all column widths (overrides only — non-overridden columns use CSS defaults). */
65
+ getAllColumnWidths() {
66
+ return { ...this._columnSizingOverrides };
67
+ }
68
+ /** Remove overrides for columns that no longer exist. */
69
+ cleanupOverrides(validColumnIds) {
70
+ let changed = false;
71
+ const next = { ...this._columnSizingOverrides };
72
+ for (const key of Object.keys(next)) {
73
+ if (!validColumnIds.has(key)) {
74
+ delete next[key];
75
+ changed = true;
76
+ }
77
+ }
78
+ if (changed) {
79
+ this._columnSizingOverrides = next;
80
+ this.emitter.emit('layoutChange', { type: 'columnOverride' });
81
+ }
82
+ }
83
+ /** Apply initial column widths from options. */
84
+ applyInitialWidths(initialWidths) {
85
+ this._columnSizingOverrides = { ...initialWidths };
86
+ }
87
+ onLayoutChange(handler) {
88
+ this.emitter.on('layoutChange', handler);
89
+ return () => this.emitter.off('layoutChange', handler);
90
+ }
91
+ destroy() {
92
+ this.disconnectObserver();
93
+ this.emitter.removeAllListeners();
94
+ }
95
+ }
@@ -0,0 +1,82 @@
1
+ import { EventEmitter } from './EventEmitter';
2
+ export class UndoRedoState {
3
+ constructor(onCellValueChanged, maxUndoDepth = 100) {
4
+ this.onCellValueChanged = onCellValueChanged;
5
+ this.emitter = new EventEmitter();
6
+ this.historyStack = [];
7
+ this.redoStack = [];
8
+ this.batch = null;
9
+ this.maxUndoDepth = maxUndoDepth;
10
+ if (onCellValueChanged) {
11
+ this.wrappedCallback = (event) => {
12
+ if (this.batch !== null) {
13
+ this.batch.push(event);
14
+ }
15
+ else {
16
+ this.historyStack = [...this.historyStack, [event]].slice(-this.maxUndoDepth);
17
+ this.redoStack = [];
18
+ this.emitStackChange();
19
+ }
20
+ onCellValueChanged(event);
21
+ };
22
+ }
23
+ }
24
+ get canUndo() {
25
+ return this.historyStack.length > 0;
26
+ }
27
+ get canRedo() {
28
+ return this.redoStack.length > 0;
29
+ }
30
+ getWrappedCallback() {
31
+ return this.wrappedCallback;
32
+ }
33
+ beginBatch() {
34
+ this.batch = [];
35
+ }
36
+ endBatch() {
37
+ const currentBatch = this.batch;
38
+ this.batch = null;
39
+ if (!currentBatch || currentBatch.length === 0)
40
+ return;
41
+ this.historyStack = [...this.historyStack, currentBatch].slice(-this.maxUndoDepth);
42
+ this.redoStack = [];
43
+ this.emitStackChange();
44
+ }
45
+ undo() {
46
+ if (!this.onCellValueChanged || this.historyStack.length === 0)
47
+ return;
48
+ const lastBatch = this.historyStack[this.historyStack.length - 1];
49
+ this.historyStack = this.historyStack.slice(0, -1);
50
+ this.redoStack = [...this.redoStack, lastBatch];
51
+ this.emitStackChange();
52
+ for (let i = lastBatch.length - 1; i >= 0; i--) {
53
+ const ev = lastBatch[i];
54
+ this.onCellValueChanged({
55
+ ...ev,
56
+ oldValue: ev.newValue,
57
+ newValue: ev.oldValue,
58
+ });
59
+ }
60
+ }
61
+ redo() {
62
+ if (!this.onCellValueChanged || this.redoStack.length === 0)
63
+ return;
64
+ const nextBatch = this.redoStack[this.redoStack.length - 1];
65
+ this.redoStack = this.redoStack.slice(0, -1);
66
+ this.historyStack = [...this.historyStack, nextBatch];
67
+ this.emitStackChange();
68
+ for (const ev of nextBatch) {
69
+ this.onCellValueChanged(ev);
70
+ }
71
+ }
72
+ emitStackChange() {
73
+ this.emitter.emit('stackChange', { canUndo: this.canUndo, canRedo: this.canRedo });
74
+ }
75
+ onStackChange(handler) {
76
+ this.emitter.on('stackChange', handler);
77
+ return () => this.emitter.off('stackChange', handler);
78
+ }
79
+ destroy() {
80
+ this.emitter.removeAllListeners();
81
+ }
82
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export * from './columnTypes';
2
+ export * from './gridTypes';
@@ -0,0 +1,60 @@
1
+ import type { OGridOptions, OGridEvents, IJsOGridApi } from './types/gridTypes';
2
+ export declare class OGrid<T> {
3
+ private state;
4
+ private renderer;
5
+ private pagination;
6
+ private statusBar;
7
+ private columnChooser;
8
+ private sideBarState;
9
+ private sideBarComponent;
10
+ private sideBarContainer;
11
+ private headerFilterState;
12
+ private headerFilterComponent;
13
+ private filterConfigs;
14
+ private loadingOverlay;
15
+ private bodyArea;
16
+ private selectionState;
17
+ private keyboardNavState;
18
+ private clipboardState;
19
+ private undoRedoState;
20
+ private resizeState;
21
+ private fillHandleState;
22
+ private rowSelectionState;
23
+ private pinningState;
24
+ private marchingAnts;
25
+ private cellEditor;
26
+ private contextMenu;
27
+ private layoutState;
28
+ private events;
29
+ private unsubscribes;
30
+ private containerEl;
31
+ private tableContainer;
32
+ private toolbarEl;
33
+ private paginationContainer;
34
+ private statusBarContainer;
35
+ private options;
36
+ /** The imperative grid API (extends React's IOGridApi with JS-specific methods). */
37
+ readonly api: IJsOGridApi<T>;
38
+ constructor(container: HTMLElement, options: OGridOptions<T>);
39
+ private initializeInteraction;
40
+ private attachGlobalHandlers;
41
+ private updateRendererInteractionState;
42
+ private updateDragAttributes;
43
+ private handleCellClick;
44
+ private handleCellMouseDown;
45
+ private handleCellContextMenu;
46
+ private showContextMenu;
47
+ private startCellEdit;
48
+ private buildFilterConfigs;
49
+ private handleFilterIconClick;
50
+ private renderHeaderFilterPopover;
51
+ private renderSideBar;
52
+ private renderLoadingOverlay;
53
+ private renderAll;
54
+ /** Subscribe to grid events. */
55
+ on<K extends keyof OGridEvents<T>>(event: K, handler: (data: OGridEvents<T>[K]) => void): void;
56
+ /** Unsubscribe from grid events. */
57
+ off<K extends keyof OGridEvents<T>>(event: K, handler: (data: OGridEvents<T>[K]) => void): void;
58
+ /** Clean up all event listeners and DOM. */
59
+ destroy(): void;
60
+ }
@@ -0,0 +1,14 @@
1
+ import type { GridState } from '../state/GridState';
2
+ export declare class ColumnChooser<T> {
3
+ private container;
4
+ private state;
5
+ private el;
6
+ private dropdown;
7
+ private isOpen;
8
+ constructor(container: HTMLElement, state: GridState<T>);
9
+ render(): void;
10
+ private toggle;
11
+ private open;
12
+ private close;
13
+ destroy(): void;
14
+ }
@@ -0,0 +1,17 @@
1
+ import type { ISelectionRange } from '@alaarab/ogrid-core';
2
+ export interface ContextMenuHandlers {
3
+ onCopy: () => void;
4
+ onCut: () => void;
5
+ onPaste: () => void;
6
+ onSelectAll: () => void;
7
+ onUndo: () => void;
8
+ onRedo: () => void;
9
+ }
10
+ export declare class ContextMenu {
11
+ private menu;
12
+ private handlers;
13
+ show(x: number, y: number, handlers: ContextMenuHandlers, canUndo: boolean, canRedo: boolean, selectionRange: ISelectionRange | null): void;
14
+ close(): void;
15
+ private handleItemClick;
16
+ destroy(): void;
17
+ }
@@ -0,0 +1,24 @@
1
+ import type { HeaderFilterState, HeaderFilterConfig } from '../state/HeaderFilterState';
2
+ /**
3
+ * Renders header filter popover (dropdown) in DOM.
4
+ * Instantiated by OGrid, reads state from HeaderFilterState.
5
+ */
6
+ export declare class HeaderFilter {
7
+ private state;
8
+ private popoverEl;
9
+ constructor(state: HeaderFilterState);
10
+ /**
11
+ * Render the popover for the currently open filter.
12
+ * Call this whenever HeaderFilterState changes.
13
+ */
14
+ render(config: HeaderFilterConfig | null): void;
15
+ private renderTextFilter;
16
+ private renderMultiSelectFilter;
17
+ private updateCheckboxList;
18
+ private renderDateFilter;
19
+ private applyInputStyle;
20
+ private applyButtonStyle;
21
+ private applySmallButtonStyle;
22
+ cleanup(): void;
23
+ destroy(): void;
24
+ }
@@ -0,0 +1,24 @@
1
+ import type { IColumnDef } from '../types/columnTypes';
2
+ import type { RowId } from '@alaarab/ogrid-core';
3
+ export declare class InlineCellEditor<T> {
4
+ private container;
5
+ private editor;
6
+ private editingCell;
7
+ private onCommit;
8
+ private onCancel;
9
+ constructor(container: HTMLElement);
10
+ startEdit(rowId: RowId, columnId: string, item: T, column: IColumnDef<T>, cell: HTMLTableCellElement, onCommit: (rowId: RowId, columnId: string, value: unknown) => void, onCancel: () => void): void;
11
+ /** Returns the cell currently being edited, or null if no editor is open. */
12
+ getEditingCell(): {
13
+ rowId: RowId;
14
+ columnId: string;
15
+ } | null;
16
+ closeEditor(): void;
17
+ private createEditor;
18
+ private createTextEditor;
19
+ private createCheckboxEditor;
20
+ private createDateEditor;
21
+ private createSelectEditor;
22
+ private createRichSelectEditor;
23
+ destroy(): void;
24
+ }
@@ -0,0 +1,25 @@
1
+ import type { ISelectionRange } from '@alaarab/ogrid-core';
2
+ /**
3
+ * MarchingAntsOverlay — renders SVG overlays on top of the grid:
4
+ * 1. Selection range: solid green border
5
+ * 2. Copy/Cut range: animated dashed border (marching ants)
6
+ *
7
+ * Vanilla JS equivalent of React's MarchingAntsOverlay component.
8
+ */
9
+ export declare class MarchingAntsOverlay {
10
+ private container;
11
+ private colOffset;
12
+ private selSvg;
13
+ private clipSvg;
14
+ private selectionRange;
15
+ private copyRange;
16
+ private cutRange;
17
+ private rafHandle;
18
+ constructor(container: HTMLElement, colOffset?: number);
19
+ update(selectionRange: ISelectionRange | null, copyRange: ISelectionRange | null, cutRange: ISelectionRange | null): void;
20
+ private render;
21
+ private createSvg;
22
+ private positionSvg;
23
+ private removeSvg;
24
+ destroy(): void;
25
+ }
@@ -0,0 +1,9 @@
1
+ import type { GridState } from '../state/GridState';
2
+ export declare class PaginationControls<T> {
3
+ private container;
4
+ private state;
5
+ private el;
6
+ constructor(container: HTMLElement, state: GridState<T>);
7
+ render(totalCount: number): void;
8
+ destroy(): void;
9
+ }
@@ -0,0 +1,35 @@
1
+ import type { IColumnDefinition, IFilters, FilterValue } from '@alaarab/ogrid-core';
2
+ import type { SideBarState } from '../state/SideBarState';
3
+ export interface SideBarFilterColumn {
4
+ columnId: string;
5
+ name: string;
6
+ filterField: string;
7
+ filterType: 'text' | 'multiSelect' | 'people' | 'date';
8
+ }
9
+ export interface SideBarRenderConfig {
10
+ columns: IColumnDefinition[];
11
+ visibleColumns: Set<string>;
12
+ onVisibilityChange: (columnKey: string, visible: boolean) => void;
13
+ onSetVisibleColumns: (columns: Set<string>) => void;
14
+ filterableColumns: SideBarFilterColumn[];
15
+ filters: IFilters;
16
+ onFilterChange: (key: string, value: FilterValue | undefined) => void;
17
+ filterOptions: Record<string, string[]>;
18
+ }
19
+ export declare class SideBar {
20
+ private container;
21
+ private state;
22
+ private el;
23
+ private config;
24
+ constructor(container: HTMLElement, state: SideBarState);
25
+ setConfig(config: SideBarRenderConfig): void;
26
+ render(): void;
27
+ private createTabStrip;
28
+ private createPanel;
29
+ private renderColumnsPanel;
30
+ private renderFiltersPanel;
31
+ private applyActionButtonStyle;
32
+ private applyTextInputStyle;
33
+ private applyDateInputStyle;
34
+ destroy(): void;
35
+ }
@@ -0,0 +1,8 @@
1
+ import type { IStatusBarProps } from '@alaarab/ogrid-core';
2
+ export declare class StatusBar {
3
+ private container;
4
+ private el;
5
+ constructor(container: HTMLElement);
6
+ render(props: IStatusBarProps): void;
7
+ destroy(): void;
8
+ }
@@ -0,0 +1,26 @@
1
+ export * from '@alaarab/ogrid-core';
2
+ export type { IColumnDef, IColumnGroupDef, ICellEditorContext } from './types/columnTypes';
3
+ export type { OGridOptions, OGridEvents, IJsOGridApi } from './types/gridTypes';
4
+ export { OGrid } from './OGrid';
5
+ export { GridState } from './state/GridState';
6
+ export { EventEmitter } from './state/EventEmitter';
7
+ export { SelectionState } from './state/SelectionState';
8
+ export { KeyboardNavState } from './state/KeyboardNavState';
9
+ export { ClipboardState } from './state/ClipboardState';
10
+ export { UndoRedoState } from './state/UndoRedoState';
11
+ export { ColumnResizeState } from './state/ColumnResizeState';
12
+ export { TableLayoutState } from './state/TableLayoutState';
13
+ export { TableRenderer } from './renderer/TableRenderer';
14
+ export { PaginationControls } from './components/PaginationControls';
15
+ export { StatusBar } from './components/StatusBar';
16
+ export { ColumnChooser } from './components/ColumnChooser';
17
+ export { InlineCellEditor } from './components/InlineCellEditor';
18
+ export { ContextMenu } from './components/ContextMenu';
19
+ export { FillHandleState } from './state/FillHandleState';
20
+ export { RowSelectionState } from './state/RowSelectionState';
21
+ export { ColumnPinningState } from './state/ColumnPinningState';
22
+ export { MarchingAntsOverlay } from './components/MarchingAntsOverlay';
23
+ export { SideBarState } from './state/SideBarState';
24
+ export { HeaderFilterState } from './state/HeaderFilterState';
25
+ export { SideBar } from './components/SideBar';
26
+ export { HeaderFilter } from './components/HeaderFilter';
@@ -0,0 +1,59 @@
1
+ import type { RowId } from '../types/gridTypes';
2
+ import type { IActiveCell, ISelectionRange } from '@alaarab/ogrid-core';
3
+ import type { GridState } from '../state/GridState';
4
+ import type { HeaderFilterState, HeaderFilterConfig } from '../state/HeaderFilterState';
5
+ export interface TableRendererInteractionState {
6
+ activeCell: IActiveCell | null;
7
+ selectionRange: ISelectionRange | null;
8
+ copyRange: ISelectionRange | null;
9
+ cutRange: ISelectionRange | null;
10
+ editingCell: {
11
+ rowId: RowId;
12
+ columnId: string;
13
+ } | null;
14
+ columnWidths: Record<string, number>;
15
+ onCellClick?: (rowIndex: number, colIndex: number, e: MouseEvent) => void;
16
+ onCellMouseDown?: (rowIndex: number, colIndex: number, e: MouseEvent) => void;
17
+ onCellDoubleClick?: (rowIndex: number, colIndex: number, rowId: RowId, columnId: string) => void;
18
+ onCellContextMenu?: (rowIndex: number, colIndex: number, e: MouseEvent) => void;
19
+ onResizeStart?: (columnId: string, clientX: number, currentWidth: number) => void;
20
+ onFillHandleMouseDown?: (e: MouseEvent) => void;
21
+ rowSelectionMode?: 'single' | 'multiple' | 'none';
22
+ selectedRowIds?: Set<RowId>;
23
+ onRowCheckboxChange?: (rowId: RowId, checked: boolean, rowIndex: number, shiftKey: boolean) => void;
24
+ onSelectAll?: (checked: boolean) => void;
25
+ allSelected?: boolean;
26
+ someSelected?: boolean;
27
+ pinnedColumns?: Record<string, 'left' | 'right'>;
28
+ leftOffsets?: Record<string, number>;
29
+ rightOffsets?: Record<string, number>;
30
+ }
31
+ export declare class TableRenderer<T> {
32
+ private container;
33
+ private state;
34
+ private table;
35
+ private thead;
36
+ private tbody;
37
+ private interactionState;
38
+ private wrapperEl;
39
+ private headerFilterState;
40
+ private filterConfigs;
41
+ private onFilterIconClick;
42
+ constructor(container: HTMLElement, state: GridState<T>);
43
+ setHeaderFilterState(state: HeaderFilterState, configs: Map<string, HeaderFilterConfig>): void;
44
+ setOnFilterIconClick(handler: (columnId: string, headerEl: HTMLElement) => void): void;
45
+ setInteractionState(state: TableRendererInteractionState | null): void;
46
+ getWrapperElement(): HTMLDivElement | null;
47
+ /** Full render — creates the table structure from scratch. */
48
+ render(): void;
49
+ /** Re-render body rows and header (after sort/filter/page change). */
50
+ update(): void;
51
+ private hasCheckboxColumn;
52
+ /** The column index offset for data columns (1 if checkbox column present, else 0). */
53
+ getColOffset(): number;
54
+ private applyPinningStyles;
55
+ private renderHeader;
56
+ private appendSelectAllCheckbox;
57
+ private renderBody;
58
+ destroy(): void;
59
+ }