@alaarab/ogrid-core 2.0.6 → 2.0.8

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.
@@ -0,0 +1,3 @@
1
+ export * from './layout';
2
+ export * from './timing';
3
+ export * from './zIndex';
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Core OGrid constants — magic numbers centralized for consistency and maintainability.
2
+ * Layout and sizing constants for OGrid components.
3
3
  */
4
4
  /** Width of the row selection checkbox column in pixels. */
5
5
  export const CHECKBOX_COLUMN_WIDTH = 48;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Timing constants used across OGrid.
3
+ * Centralizes magic numbers for consistency and easier tuning.
4
+ */
5
+ /** Debounce delay for people/user search inputs (milliseconds) */
6
+ export const PEOPLE_SEARCH_DEBOUNCE_MS = 300;
7
+ /** Default debounce delay for generic inputs (milliseconds) */
8
+ export const DEFAULT_DEBOUNCE_MS = 300;
9
+ /** Sidebar panel transition duration (milliseconds) */
10
+ export const SIDEBAR_TRANSITION_MS = 300;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Z-index constants for layering OGrid UI elements.
3
+ * Ensures consistent stacking order across all packages.
4
+ */
5
+ export const Z_INDEX = {
6
+ /** Selection range overlay (marching ants) */
7
+ SELECTION_OVERLAY: 4,
8
+ /** Clipboard overlay (copy/cut animation) */
9
+ CLIPBOARD_OVERLAY: 5,
10
+ /** Dropdown menus (column chooser, pagination size select) */
11
+ DROPDOWN: 1000,
12
+ /** Modal dialogs */
13
+ MODAL: 2000,
14
+ /** Context menus (right-click grid menu) */
15
+ CONTEXT_MENU: 9999,
16
+ };
@@ -1,5 +1,10 @@
1
1
  import { getCellValue } from './cellValue';
2
2
  import { getFilterField } from './ogridHelpers';
3
+ /**
4
+ * Cached column map to avoid rebuilding on every call.
5
+ * WeakMap keyed by columns array reference.
6
+ */
7
+ const columnMapCache = new WeakMap();
3
8
  /**
4
9
  * Apply client-side filtering and sorting to data.
5
10
  * Extracted from useOGrid for testability and reuse.
@@ -12,10 +17,14 @@ import { getFilterField } from './ogridHelpers';
12
17
  * @returns Filtered and sorted array
13
18
  */
14
19
  export function processClientSideData(data, columns, filters, sortBy, sortDirection) {
15
- // Build column lookup map for O(1) access by columnId
16
- const columnMap = new Map();
17
- for (let i = 0; i < columns.length; i++) {
18
- columnMap.set(columns[i].columnId, columns[i]);
20
+ // Get or build column lookup map (cached via WeakMap)
21
+ let columnMap = columnMapCache.get(columns);
22
+ if (!columnMap) {
23
+ columnMap = new Map();
24
+ for (let i = 0; i < columns.length; i++) {
25
+ columnMap.set(columns[i].columnId, columns[i]);
26
+ }
27
+ columnMapCache.set(columns, columnMap);
19
28
  }
20
29
  // --- Filtering (single-pass: build predicates, then one .filter()) ---
21
30
  const predicates = [];
@@ -0,0 +1,208 @@
1
+ /**
2
+ * View model helpers for DataGridTable.
3
+ * Pure TypeScript — no framework dependencies (React, Angular, Vue).
4
+ * Framework packages re-export these and may add thin framework-specific wrappers.
5
+ */
6
+ import { getCellValue } from './cellValue';
7
+ import { isInSelectionRange } from '../types/dataGridTypes';
8
+ /**
9
+ * Returns ColumnHeaderFilter props from column def and grid filter/sort state.
10
+ */
11
+ export function getHeaderFilterConfig(col, input) {
12
+ const filterable = col.filterable && typeof col.filterable === 'object' ? col.filterable : null;
13
+ const filterType = (filterable?.type ?? 'none');
14
+ const filterField = filterable?.filterField ?? col.columnId;
15
+ const sortable = col.sortable !== false;
16
+ const filterValue = input.filters[filterField];
17
+ const base = {
18
+ columnKey: col.columnId,
19
+ columnName: col.name,
20
+ filterType,
21
+ isSorted: input.sortBy === col.columnId,
22
+ isSortedDescending: input.sortBy === col.columnId && input.sortDirection === 'desc',
23
+ onSort: sortable ? () => input.onColumnSort(col.columnId) : undefined,
24
+ };
25
+ if (filterType === 'text') {
26
+ return {
27
+ ...base,
28
+ textValue: filterValue?.type === 'text' ? filterValue.value : '',
29
+ onTextChange: (v) => input.onFilterChange(filterField, v.trim() ? { type: 'text', value: v } : undefined),
30
+ };
31
+ }
32
+ if (filterType === 'people') {
33
+ return {
34
+ ...base,
35
+ selectedUser: filterValue?.type === 'people' ? filterValue.value : undefined,
36
+ onUserChange: (u) => input.onFilterChange(filterField, u ? { type: 'people', value: u } : undefined),
37
+ peopleSearch: input.peopleSearch,
38
+ };
39
+ }
40
+ if (filterType === 'multiSelect') {
41
+ return {
42
+ ...base,
43
+ options: input.filterOptions[filterField] ?? [],
44
+ isLoadingOptions: input.loadingFilterOptions[filterField] ?? false,
45
+ selectedValues: filterValue?.type === 'multiSelect' ? filterValue.value : [],
46
+ onFilterChange: (values) => input.onFilterChange(filterField, values.length ? { type: 'multiSelect', value: values } : undefined),
47
+ };
48
+ }
49
+ if (filterType === 'date') {
50
+ return {
51
+ ...base,
52
+ dateValue: filterValue?.type === 'date' ? filterValue.value : undefined,
53
+ onDateChange: (v) => input.onFilterChange(filterField, v ? { type: 'date', value: v } : undefined),
54
+ };
55
+ }
56
+ return base;
57
+ }
58
+ /**
59
+ * Returns a descriptor for rendering a cell. UI uses this to decide editing-inline vs editing-popover vs display
60
+ * and to apply isActive, isInRange, etc. without duplicating the boolean logic.
61
+ */
62
+ export function getCellRenderDescriptor(item, col, rowIndex, colIdx, input) {
63
+ const rowId = input.getRowId(item);
64
+ const globalColIndex = colIdx + input.colOffset;
65
+ const colEditable = col.editable === true ||
66
+ (typeof col.editable === 'function' && col.editable(item));
67
+ const canEditInline = input.editable !== false &&
68
+ !!colEditable &&
69
+ !!input.onCellValueChanged &&
70
+ typeof col.cellEditor !== 'function';
71
+ const canEditPopup = input.editable !== false &&
72
+ !!colEditable &&
73
+ !!input.onCellValueChanged &&
74
+ typeof col.cellEditor === 'function' &&
75
+ col.cellEditorPopup !== false;
76
+ const canEditAny = canEditInline || canEditPopup;
77
+ const isEditing = input.editingCell?.rowId === rowId &&
78
+ input.editingCell?.columnId === col.columnId;
79
+ const isActive = input.activeCell?.rowIndex === rowIndex &&
80
+ input.activeCell?.columnIndex === globalColIndex;
81
+ const isInRange = input.selectionRange != null &&
82
+ isInSelectionRange(input.selectionRange, rowIndex, colIdx);
83
+ const isInCutRange = input.cutRange != null &&
84
+ isInSelectionRange(input.cutRange, rowIndex, colIdx);
85
+ const isInCopyRange = input.copyRange != null &&
86
+ isInSelectionRange(input.copyRange, rowIndex, colIdx);
87
+ const isSelectionEndCell = !input.isDragging &&
88
+ input.copyRange == null &&
89
+ input.cutRange == null &&
90
+ input.selectionRange != null &&
91
+ rowIndex === input.selectionRange.endRow &&
92
+ colIdx === input.selectionRange.endCol;
93
+ const isPinned = col.pinned != null;
94
+ const pinnedSide = col.pinned ?? undefined;
95
+ let mode = 'display';
96
+ let editorType;
97
+ let value;
98
+ if (isEditing && canEditInline) {
99
+ mode = 'editing-inline';
100
+ if (col.cellEditor === 'text' ||
101
+ col.cellEditor === 'select' ||
102
+ col.cellEditor === 'checkbox' ||
103
+ col.cellEditor === 'richSelect' ||
104
+ col.cellEditor === 'date') {
105
+ editorType = col.cellEditor;
106
+ }
107
+ else if (col.type === 'date') {
108
+ editorType = 'date';
109
+ }
110
+ else if (col.type === 'boolean') {
111
+ editorType = 'checkbox';
112
+ }
113
+ else {
114
+ editorType = 'text';
115
+ }
116
+ value = getCellValue(item, col);
117
+ }
118
+ else if (isEditing && canEditPopup && typeof col.cellEditor === 'function') {
119
+ mode = 'editing-popover';
120
+ value = getCellValue(item, col);
121
+ }
122
+ else {
123
+ value = getCellValue(item, col);
124
+ }
125
+ return {
126
+ mode,
127
+ editorType,
128
+ value,
129
+ isActive,
130
+ isInRange,
131
+ isInCutRange,
132
+ isInCopyRange,
133
+ isSelectionEndCell,
134
+ canEditAny,
135
+ isPinned,
136
+ pinnedSide,
137
+ globalColIndex,
138
+ rowId,
139
+ rowIndex,
140
+ displayValue: value,
141
+ };
142
+ }
143
+ /**
144
+ * Resolves display content for a cell in display mode.
145
+ * Handles the renderCell -> valueFormatter -> String() fallback chain.
146
+ * Returns `unknown` — framework packages may narrow to their own node type.
147
+ */
148
+ export function resolveCellDisplayContent(col, item, displayValue) {
149
+ const c = col;
150
+ if (c.renderCell && typeof c.renderCell === 'function') {
151
+ return c.renderCell(item);
152
+ }
153
+ if (col.valueFormatter)
154
+ return col.valueFormatter(displayValue, item);
155
+ if (displayValue == null)
156
+ return null;
157
+ if (col.type === 'date') {
158
+ const d = new Date(String(displayValue));
159
+ if (!Number.isNaN(d.getTime()))
160
+ return d.toLocaleDateString();
161
+ }
162
+ if (col.type === 'boolean') {
163
+ return displayValue ? 'True' : 'False';
164
+ }
165
+ return String(displayValue);
166
+ }
167
+ /**
168
+ * Resolves the cellStyle from a column def, handling both function and static values.
169
+ */
170
+ export function resolveCellStyle(col, item) {
171
+ const c = col;
172
+ if (!c.cellStyle)
173
+ return undefined;
174
+ return typeof c.cellStyle === 'function' ? c.cellStyle(item) : c.cellStyle;
175
+ }
176
+ /**
177
+ * Builds props for InlineCellEditor. Shared across all UI packages.
178
+ */
179
+ export function buildInlineEditorProps(item, col, descriptor, callbacks) {
180
+ return {
181
+ value: descriptor.value,
182
+ item,
183
+ column: col,
184
+ rowIndex: descriptor.rowIndex,
185
+ editorType: (descriptor.editorType ?? 'text'),
186
+ onCommit: (newValue) => callbacks.commitCellEdit(item, col.columnId, descriptor.value, newValue, descriptor.rowIndex, descriptor.globalColIndex),
187
+ onCancel: () => callbacks.setEditingCell(null),
188
+ };
189
+ }
190
+ /**
191
+ * Builds ICellEditorProps for custom popover editors. Shared across all UI packages.
192
+ */
193
+ export function buildPopoverEditorProps(item, col, descriptor, pendingEditorValue, callbacks) {
194
+ const oldValue = descriptor.value;
195
+ const displayValue = pendingEditorValue !== undefined ? pendingEditorValue : oldValue;
196
+ return {
197
+ value: displayValue,
198
+ onValueChange: callbacks.setPendingEditorValue,
199
+ onCommit: () => {
200
+ const newValue = pendingEditorValue !== undefined ? pendingEditorValue : oldValue;
201
+ callbacks.commitCellEdit(item, col.columnId, oldValue, newValue, descriptor.rowIndex, descriptor.globalColIndex);
202
+ },
203
+ onCancel: callbacks.cancelPopoverEdit,
204
+ item,
205
+ column: col,
206
+ cellEditorParams: col.cellEditorParams,
207
+ };
208
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Debounces a function call, delaying execution until after `delayMs` milliseconds
3
+ * have elapsed since the last invocation.
4
+ *
5
+ * @param fn - The function to debounce
6
+ * @param delayMs - Delay in milliseconds
7
+ * @returns Debounced function with a `cancel` method
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const search = debounce((query: string) => {
12
+ * console.log('Searching:', query);
13
+ * }, 300);
14
+ *
15
+ * search('a');
16
+ * search('ab');
17
+ * search('abc'); // Only this will execute after 300ms
18
+ *
19
+ * search.cancel(); // Cancel pending execution
20
+ * ```
21
+ */
22
+ export function debounce(fn, delayMs) {
23
+ let timeoutId = null;
24
+ const debounced = ((...args) => {
25
+ if (timeoutId !== null) {
26
+ clearTimeout(timeoutId);
27
+ }
28
+ timeoutId = setTimeout(() => {
29
+ fn(...args);
30
+ timeoutId = null;
31
+ }, delayMs);
32
+ });
33
+ debounced.cancel = () => {
34
+ if (timeoutId !== null) {
35
+ clearTimeout(timeoutId);
36
+ timeoutId = null;
37
+ }
38
+ };
39
+ return debounced;
40
+ }
@@ -12,3 +12,5 @@ export { processClientSideData } from './clientSideData';
12
12
  export { areGridRowPropsEqual, isRowInRange } from './gridRowComparator';
13
13
  export { getPinStateForColumn, reorderColumnArray, calculateDropTarget, } from './columnReorder';
14
14
  export { computeVisibleRange, computeTotalHeight, getScrollTopForRow, } from './virtualScroll';
15
+ export { getHeaderFilterConfig, getCellRenderDescriptor, resolveCellDisplayContent, resolveCellStyle, buildInlineEditorProps, buildPopoverEditorProps, } from './dataGridViewModel';
16
+ export { debounce } from './debounce';
@@ -0,0 +1,3 @@
1
+ export * from './layout';
2
+ export * from './timing';
3
+ export * from './zIndex';
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Core OGrid constants — magic numbers centralized for consistency and maintainability.
2
+ * Layout and sizing constants for OGrid components.
3
3
  */
4
4
  /** Width of the row selection checkbox column in pixels. */
5
5
  export declare const CHECKBOX_COLUMN_WIDTH = 48;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Timing constants used across OGrid.
3
+ * Centralizes magic numbers for consistency and easier tuning.
4
+ */
5
+ /** Debounce delay for people/user search inputs (milliseconds) */
6
+ export declare const PEOPLE_SEARCH_DEBOUNCE_MS = 300;
7
+ /** Default debounce delay for generic inputs (milliseconds) */
8
+ export declare const DEFAULT_DEBOUNCE_MS = 300;
9
+ /** Sidebar panel transition duration (milliseconds) */
10
+ export declare const SIDEBAR_TRANSITION_MS = 300;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Z-index constants for layering OGrid UI elements.
3
+ * Ensures consistent stacking order across all packages.
4
+ */
5
+ export declare const Z_INDEX: {
6
+ /** Selection range overlay (marching ants) */
7
+ readonly SELECTION_OVERLAY: 4;
8
+ /** Clipboard overlay (copy/cut animation) */
9
+ readonly CLIPBOARD_OVERLAY: 5;
10
+ /** Dropdown menus (column chooser, pagination size select) */
11
+ readonly DROPDOWN: 1000;
12
+ /** Modal dialogs */
13
+ readonly MODAL: 2000;
14
+ /** Context menus (right-click grid menu) */
15
+ readonly CONTEXT_MENU: 9999;
16
+ };
17
+ /** Type helper for z-index keys */
18
+ export type ZIndexKey = keyof typeof Z_INDEX;
@@ -0,0 +1,134 @@
1
+ /**
2
+ * View model helpers for DataGridTable.
3
+ * Pure TypeScript — no framework dependencies (React, Angular, Vue).
4
+ * Framework packages re-export these and may add thin framework-specific wrappers.
5
+ */
6
+ import type { ColumnFilterType, IDateFilterValue, ICellEditorProps } from '../types/columnTypes';
7
+ import type { IColumnDef } from '../types/columnTypes';
8
+ import type { RowId, UserLike, IFilters, FilterValue } from '../types/dataGridTypes';
9
+ export interface HeaderFilterConfigInput {
10
+ sortBy?: string;
11
+ sortDirection: 'asc' | 'desc';
12
+ onColumnSort: (columnKey: string) => void;
13
+ filters: IFilters;
14
+ onFilterChange: (key: string, value: FilterValue | undefined) => void;
15
+ filterOptions: Record<string, string[]>;
16
+ loadingFilterOptions: Record<string, boolean>;
17
+ peopleSearch?: (query: string) => Promise<UserLike[]>;
18
+ }
19
+ /** Props to pass to ColumnHeaderFilter. Matches IColumnHeaderFilterProps. */
20
+ export interface HeaderFilterConfig {
21
+ columnKey: string;
22
+ columnName: string;
23
+ filterType: ColumnFilterType;
24
+ isSorted?: boolean;
25
+ isSortedDescending?: boolean;
26
+ onSort?: () => void;
27
+ selectedValues?: string[];
28
+ onFilterChange?: (values: string[]) => void;
29
+ options?: string[];
30
+ isLoadingOptions?: boolean;
31
+ textValue?: string;
32
+ onTextChange?: (value: string) => void;
33
+ selectedUser?: UserLike;
34
+ onUserChange?: (user: UserLike | undefined) => void;
35
+ peopleSearch?: (query: string) => Promise<UserLike[]>;
36
+ dateValue?: IDateFilterValue;
37
+ onDateChange?: (value: IDateFilterValue | undefined) => void;
38
+ }
39
+ /**
40
+ * Returns ColumnHeaderFilter props from column def and grid filter/sort state.
41
+ */
42
+ export declare function getHeaderFilterConfig<T>(col: IColumnDef<T>, input: HeaderFilterConfigInput): HeaderFilterConfig;
43
+ export type CellRenderMode = 'editing-inline' | 'editing-popover' | 'display';
44
+ export interface CellRenderDescriptorInput<T> {
45
+ editingCell: {
46
+ rowId: RowId;
47
+ columnId: string;
48
+ } | null;
49
+ activeCell: {
50
+ rowIndex: number;
51
+ columnIndex: number;
52
+ } | null;
53
+ selectionRange: {
54
+ startRow: number;
55
+ startCol: number;
56
+ endRow: number;
57
+ endCol: number;
58
+ } | null;
59
+ cutRange: {
60
+ startRow: number;
61
+ startCol: number;
62
+ endRow: number;
63
+ endCol: number;
64
+ } | null;
65
+ copyRange: {
66
+ startRow: number;
67
+ startCol: number;
68
+ endRow: number;
69
+ endCol: number;
70
+ } | null;
71
+ colOffset: number;
72
+ itemsLength?: number;
73
+ getRowId: (item: T) => RowId;
74
+ editable?: boolean;
75
+ onCellValueChanged?: unknown;
76
+ /** True while user is drag-selecting cells — hides fill handle during drag. */
77
+ isDragging?: boolean;
78
+ }
79
+ export interface CellRenderDescriptor {
80
+ mode: CellRenderMode;
81
+ editorType?: 'text' | 'select' | 'checkbox' | 'richSelect' | 'date';
82
+ value?: unknown;
83
+ isActive: boolean;
84
+ isInRange: boolean;
85
+ isInCutRange: boolean;
86
+ isInCopyRange: boolean;
87
+ isSelectionEndCell: boolean;
88
+ canEditAny: boolean;
89
+ isPinned: boolean;
90
+ pinnedSide?: 'left' | 'right';
91
+ globalColIndex: number;
92
+ rowId: RowId;
93
+ rowIndex: number;
94
+ /** Raw value for display (when mode === 'display'). UI uses col.renderCell or col.valueFormatter. */
95
+ displayValue?: unknown;
96
+ }
97
+ /**
98
+ * Returns a descriptor for rendering a cell. UI uses this to decide editing-inline vs editing-popover vs display
99
+ * and to apply isActive, isInRange, etc. without duplicating the boolean logic.
100
+ */
101
+ export declare function getCellRenderDescriptor<T>(item: T, col: IColumnDef<T>, rowIndex: number, colIdx: number, input: CellRenderDescriptorInput<T>): CellRenderDescriptor;
102
+ /**
103
+ * Resolves display content for a cell in display mode.
104
+ * Handles the renderCell -> valueFormatter -> String() fallback chain.
105
+ * Returns `unknown` — framework packages may narrow to their own node type.
106
+ */
107
+ export declare function resolveCellDisplayContent<T>(col: IColumnDef<T>, item: T, displayValue: unknown): unknown;
108
+ /**
109
+ * Resolves the cellStyle from a column def, handling both function and static values.
110
+ */
111
+ export declare function resolveCellStyle<T>(col: IColumnDef<T>, item: T): Record<string, string> | undefined;
112
+ /**
113
+ * Builds props for InlineCellEditor. Shared across all UI packages.
114
+ */
115
+ export declare function buildInlineEditorProps<T>(item: T, col: IColumnDef<T>, descriptor: CellRenderDescriptor, callbacks: {
116
+ commitCellEdit: (item: T, columnId: string, oldValue: unknown, newValue: unknown, rowIndex: number, globalColIndex: number) => void;
117
+ setEditingCell: (cell: null) => void;
118
+ }): {
119
+ value: unknown;
120
+ item: T;
121
+ column: IColumnDef<T>;
122
+ rowIndex: number;
123
+ editorType: "text" | "select" | "checkbox" | "richSelect" | "date";
124
+ onCommit: (newValue: unknown) => void;
125
+ onCancel: () => void;
126
+ };
127
+ /**
128
+ * Builds ICellEditorProps for custom popover editors. Shared across all UI packages.
129
+ */
130
+ export declare function buildPopoverEditorProps<T>(item: T, col: IColumnDef<T>, descriptor: CellRenderDescriptor, pendingEditorValue: unknown, callbacks: {
131
+ setPendingEditorValue: (value: unknown) => void;
132
+ commitCellEdit: (item: T, columnId: string, oldValue: unknown, newValue: unknown, rowIndex: number, globalColIndex: number) => void;
133
+ cancelPopoverEdit: () => void;
134
+ }): ICellEditorProps<T>;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Debounces a function call, delaying execution until after `delayMs` milliseconds
3
+ * have elapsed since the last invocation.
4
+ *
5
+ * @param fn - The function to debounce
6
+ * @param delayMs - Delay in milliseconds
7
+ * @returns Debounced function with a `cancel` method
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const search = debounce((query: string) => {
12
+ * console.log('Searching:', query);
13
+ * }, 300);
14
+ *
15
+ * search('a');
16
+ * search('ab');
17
+ * search('abc'); // Only this will execute after 300ms
18
+ *
19
+ * search.cancel(); // Cancel pending execution
20
+ * ```
21
+ */
22
+ export declare function debounce<T extends (...args: unknown[]) => void>(fn: T, delayMs: number): T & {
23
+ cancel: () => void;
24
+ };
@@ -21,3 +21,6 @@ export { getPinStateForColumn, reorderColumnArray, calculateDropTarget, } from '
21
21
  export type { ColumnPinState, IDropTarget } from './columnReorder';
22
22
  export { computeVisibleRange, computeTotalHeight, getScrollTopForRow, } from './virtualScroll';
23
23
  export type { IVisibleRange } from './virtualScroll';
24
+ export { getHeaderFilterConfig, getCellRenderDescriptor, resolveCellDisplayContent, resolveCellStyle, buildInlineEditorProps, buildPopoverEditorProps, } from './dataGridViewModel';
25
+ export type { HeaderFilterConfigInput, HeaderFilterConfig, CellRenderDescriptorInput, CellRenderDescriptor, CellRenderMode, } from './dataGridViewModel';
26
+ export { debounce } from './debounce';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alaarab/ogrid-core",
3
- "version": "2.0.6",
3
+ "version": "2.0.8",
4
4
  "description": "OGrid core – framework-agnostic types, algorithms, and utilities for OGrid data grids.",
5
5
  "main": "dist/esm/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -16,11 +16,25 @@
16
16
  "build": "rimraf dist && tsc -p tsconfig.build.json",
17
17
  "test": "jest"
18
18
  },
19
- "keywords": ["ogrid", "datatable", "typescript", "grid", "core"],
19
+ "keywords": [
20
+ "ogrid",
21
+ "datatable",
22
+ "typescript",
23
+ "grid",
24
+ "core"
25
+ ],
20
26
  "author": "Ala Arab",
21
27
  "license": "MIT",
22
- "files": ["dist", "README.md", "LICENSE"],
23
- "engines": { "node": ">=18" },
28
+ "files": [
29
+ "dist",
30
+ "README.md",
31
+ "LICENSE"
32
+ ],
33
+ "engines": {
34
+ "node": ">=18"
35
+ },
24
36
  "sideEffects": false,
25
- "publishConfig": { "access": "public" }
37
+ "publishConfig": {
38
+ "access": "public"
39
+ }
26
40
  }