persian-data-grid 0.5.0

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,2487 @@
1
+ import * as React from 'react';
2
+ import React__default, { ReactNode } from 'react';
3
+
4
+ type AuditEvent = {
5
+ message: string;
6
+ payload?: unknown;
7
+ type: 'INFORMATION' | 'ERROR' | 'FORBIDDEN' | 'CELL_CHANGED' | 'CELL_DISPLAY_CHANGED' | 'ROW_ADDED' | 'NEW_ROW_ADDED' | 'ROW_DELETED' | 'ROW_RESTORED' | 'ROW_REORDERED' | 'COLUMN_REORDERED' | 'UNIT_COLUMN_ADDED' | 'PAGE_CHANGED' | 'PAGE_SIZE_CHANGED' | 'TABLE_DELETED' | 'TABLE_RESET' | 'ROWS_LOADED' | 'DYNAMIC_DATA_REQUESTED' | 'VALIDATION_FAILED' | 'ROW_NOT_FOUND' | 'PAGE_NOT_CHANGED' | 'COLUMN_NOT_FOUND' | 'CELL_NOT_FOUND' | 'NOT_EDITABLE' | 'FORBIDDEN' | 'INVALID_VALUE' | 'DUPLICATE_ROW' | 'INVARIANT_VIOLATION' | 'ROW_NOT_EXPANDED' | 'ACTIVE_COLLECTION_CHANGED' | 'DRAG_OR_DROP_ROW_NOT_FOUND';
8
+ };
9
+ interface AuditLogger {
10
+ log(event: AuditEvent): void;
11
+ error(event: AuditEvent): void;
12
+ warn(event: AuditEvent): void;
13
+ info(event: AuditEvent): void;
14
+ }
15
+
16
+ interface RemoteApi {
17
+ request<TResponse = any>(input: {
18
+ endpoint: string;
19
+ params?: Record<string, any>;
20
+ method?: 'GET' | 'POST';
21
+ }): Promise<TResponse>;
22
+ }
23
+
24
+ type Actor$1 = {
25
+ userId: string;
26
+ roles: string[];
27
+ };
28
+ interface PermissionPolicy {
29
+ canChangeCell(input: {
30
+ actor: Actor$1;
31
+ rowId: number;
32
+ columnId: string;
33
+ }): boolean;
34
+ canEdit?: (input: {
35
+ actor: Actor$1;
36
+ rowId: number;
37
+ columnId: string;
38
+ }) => boolean;
39
+ canAddRow?: (input: {
40
+ actor: Actor$1;
41
+ }) => boolean;
42
+ canCopyRow?: (input: {
43
+ actor: Actor$1;
44
+ rowId: number;
45
+ }) => boolean;
46
+ canDeleteRow?: (input: {
47
+ actor: Actor$1;
48
+ rowId: number;
49
+ }) => boolean;
50
+ canReorderRow?: (input: {
51
+ actor: Actor$1;
52
+ rowId: number;
53
+ }) => boolean;
54
+ }
55
+
56
+ /**
57
+ * View-state value object for virtual scrolling.
58
+ * Lives in Domain types but is NOT an accounting invariant — Adapters drive it.
59
+ */
60
+ declare class Viewport {
61
+ /** Vertical scroll offset in pixels. */
62
+ readonly scrollOffset: number;
63
+ /** Visible viewport height in pixels. */
64
+ readonly viewportSize: number;
65
+ /** Fixed row height in pixels (variable-height later). */
66
+ readonly rowHeight: number;
67
+ /** Extra rows rendered above/below the window. */
68
+ readonly overscan: number;
69
+ constructor(
70
+ /** Vertical scroll offset in pixels. */
71
+ scrollOffset: number,
72
+ /** Visible viewport height in pixels. */
73
+ viewportSize: number,
74
+ /** Fixed row height in pixels (variable-height later). */
75
+ rowHeight: number,
76
+ /** Extra rows rendered above/below the window. */
77
+ overscan?: number);
78
+ equals(other: Viewport): boolean;
79
+ withScrollOffset(scrollOffset: number): Viewport;
80
+ withViewportSize(viewportSize: number): Viewport;
81
+ toJSON(): {
82
+ scrollOffset: number;
83
+ viewportSize: number;
84
+ rowHeight: number;
85
+ overscan: number;
86
+ };
87
+ }
88
+ /** Inclusive start, exclusive end — indices into the ordered row list. */
89
+ type VisibleRange = {
90
+ readonly startIndex: number;
91
+ readonly endIndex: number;
92
+ readonly startOffset: number;
93
+ readonly endOffset: number;
94
+ readonly totalHeight: number;
95
+ readonly visibleCount: number;
96
+ };
97
+
98
+ declare class CellValue {
99
+ readonly value: unknown;
100
+ constructor(value: unknown);
101
+ equals(other: CellValue): boolean;
102
+ }
103
+ declare class CellDisplay {
104
+ readonly value: unknown;
105
+ constructor(value: unknown);
106
+ equals(other: CellDisplay): boolean;
107
+ }
108
+ declare class ColumnId {
109
+ readonly value: string;
110
+ constructor(value: string);
111
+ equals(other: ColumnId): boolean;
112
+ }
113
+ type KeyValue = {
114
+ key: string;
115
+ value: unknown;
116
+ display: unknown;
117
+ };
118
+ type IRule = {
119
+ type?: string | 'array' | 'object' | 'enum' | 'date' | 'number' | 'integer' | 'float' | 'boolean' | 'email' | 'url' | 'hex' | RegExp;
120
+ required?: boolean;
121
+ whitespace?: boolean;
122
+ message?: string;
123
+ transform?: (value: any) => any;
124
+ pattern?: string | RegExp;
125
+ min?: number;
126
+ max?: number;
127
+ len?: number;
128
+ enum?: any[];
129
+ validator?: (rule: IRule, value: any, callback: (error?: string[]) => void) => void | Promise<void>;
130
+ asyncValidator?: (rule: IRule, value: any) => Promise<void>;
131
+ warningOnly?: boolean;
132
+ validateTrigger?: string | string[];
133
+ };
134
+ declare class RowId {
135
+ value: number;
136
+ constructor(value: number);
137
+ equals(other: RowId): boolean;
138
+ set(id: RowId): void;
139
+ }
140
+ declare class RowState {
141
+ value: RowStateEnum;
142
+ constructor(value: RowStateEnum);
143
+ equals(other: RowStateEnum): boolean;
144
+ set(rowState: RowStateEnum): void;
145
+ }
146
+ declare enum RowStateEnum {
147
+ Added = "Add",
148
+ Modified = "Update",
149
+ Deleted = "Delete",
150
+ Unchanged = "None"
151
+ }
152
+ type TableActions = "copy" | "cut" | "paste" | "pasteInsert" | null;
153
+
154
+ declare class Pagination {
155
+ readonly page: number;
156
+ readonly pageSize: number;
157
+ readonly totalRows: number;
158
+ readonly totalPages: number;
159
+ readonly canPrev: boolean;
160
+ readonly canNext: boolean;
161
+ constructor(page: number, pageSize: number, totalRows: number);
162
+ changePage(page: number): Pagination;
163
+ changePageSize(size: number): Pagination;
164
+ toJSON(): {
165
+ page: number;
166
+ pageSize: number;
167
+ totalRows: number;
168
+ totalPages: number;
169
+ canPrev: boolean;
170
+ canNext: boolean;
171
+ };
172
+ }
173
+
174
+ declare class CellChanged {
175
+ readonly rowId: RowId;
176
+ readonly columnId: ColumnId;
177
+ readonly newValue: unknown;
178
+ readonly previousValue: unknown;
179
+ readonly type = "CELL_CHANGED";
180
+ constructor(rowId: RowId, columnId: ColumnId, newValue: unknown, previousValue: unknown);
181
+ }
182
+ declare class DisplayChanged {
183
+ readonly rowId: RowId;
184
+ readonly columnId: ColumnId;
185
+ readonly newValue: unknown;
186
+ readonly type = "DISPLAY_CHANGED";
187
+ constructor(rowId: RowId, columnId: ColumnId, newValue: unknown);
188
+ }
189
+ declare class DescriptionSaved {
190
+ readonly rowId: RowId;
191
+ readonly flag: boolean;
192
+ readonly type = "DESCRIPTION_SAVED";
193
+ constructor(rowId: RowId, flag: boolean);
194
+ }
195
+ declare class ColumnReordered {
196
+ readonly sourceIndex: number;
197
+ readonly destIndex: number;
198
+ readonly type = "COLUMN_REORDERED";
199
+ constructor(sourceIndex: number, destIndex: number);
200
+ }
201
+ declare class RowAdded {
202
+ readonly rowId: RowId;
203
+ readonly type = "ROW_ADDED";
204
+ constructor(rowId: RowId);
205
+ }
206
+ declare class RowDeleted {
207
+ readonly rowId: RowId;
208
+ readonly type = "ROW_DELETED";
209
+ constructor(rowId: RowId);
210
+ }
211
+ declare class RowRemoved {
212
+ readonly rowId: RowId;
213
+ readonly type = "NEW_ROW_REMOVED";
214
+ constructor(rowId: RowId);
215
+ }
216
+ declare class MinimumRowConstraintViolated {
217
+ readonly rowId: RowId;
218
+ readonly type = "NEW_AND_FIRST_ROW_CAN_NOT_BE_REMOVE";
219
+ constructor(rowId: RowId);
220
+ }
221
+ declare class RowRestored {
222
+ readonly rowId: RowId;
223
+ readonly type = "ROW_RESTORED";
224
+ constructor(rowId: RowId);
225
+ }
226
+ declare class RowReordered {
227
+ readonly draggedRowNum: number;
228
+ readonly droppedRowNum: number;
229
+ readonly type = "ROW_REORDERED";
230
+ constructor(draggedRowNum: number, droppedRowNum: number);
231
+ }
232
+
233
+ declare class Cell {
234
+ readonly rowId: RowId;
235
+ readonly columnId: ColumnId;
236
+ private value;
237
+ private originalValue;
238
+ private display;
239
+ constructor(rowId: RowId, columnId: ColumnId, value: CellValue, originalValue: CellValue, display: CellDisplay);
240
+ changeValue(newValue: unknown): CellChanged | null;
241
+ changeDisplay(newValue: unknown): DisplayChanged | null;
242
+ changeOriginalValue(newValue: unknown): CellChanged | null;
243
+ getValue(): unknown;
244
+ getValueObject(): CellValue;
245
+ getDisplay(): unknown;
246
+ getDisplayObject(): CellDisplay;
247
+ getOriginalValue(): CellValue;
248
+ clone(): Cell;
249
+ }
250
+
251
+ declare class Row {
252
+ id: RowId;
253
+ cells: Map<string, Cell>;
254
+ rowState: RowState;
255
+ changeFields: Set<string>;
256
+ visibilityCondition: Record<string, boolean>;
257
+ collection: string;
258
+ isSaveDescription: boolean;
259
+ constructor(id: RowId, cells: Map<string, Cell>, rowState: RowState, changeFields: Set<string> | undefined, visibilityCondition: Record<string, boolean>, collection: string | undefined, isSaveDescription: boolean);
260
+ updateChangeFields(columnId: ColumnId): void;
261
+ getCollection(): string;
262
+ setCollection(collection: string): void;
263
+ getChangeFields(): readonly string[];
264
+ getSnapshotChangeFields(): readonly string[];
265
+ changeCell(columnId: ColumnId, value: unknown): CellChanged | null;
266
+ saveDescription(flag: boolean): DescriptionSaved;
267
+ changeDisplay(columnId: ColumnId, value: unknown): DisplayChanged | null;
268
+ getCells(): ReadonlyMap<string, Cell>;
269
+ getCell(columnId: string): Cell | undefined;
270
+ ensureCell(columnId: ColumnId, defaultValue: CellValue, displayValue: CellDisplay): void;
271
+ setRowId(rowId: RowId): void;
272
+ setVisibilityCondition(Condition: Record<string, boolean>): void;
273
+ getVisibilityCondition(): Record<string, boolean>;
274
+ removeCell(columnId: ColumnId): void;
275
+ clone(): Row;
276
+ }
277
+
278
+ type FieldType = 'index' | 'text' | 'number' | 'price' | 'select' | 'selectOption' | 'date' | 'static' | 'description' | 'checkbox';
279
+ type ColumnVisibilityRule = {
280
+ kind: 'always';
281
+ } | {
282
+ kind: 'never';
283
+ } | {
284
+ kind: 'showUnitLevelConditionally';
285
+ fieldName: string;
286
+ } | {
287
+ kind: 'whenFieldTruthy';
288
+ fieldName: string;
289
+ } | {
290
+ kind: 'whenRemoteFlag';
291
+ sourceFieldName: string;
292
+ flag: string;
293
+ } | {
294
+ kind: 'whenCollection';
295
+ collection: string;
296
+ } | {
297
+ kind: 'whenTableType';
298
+ tableType: string;
299
+ };
300
+ interface ResolveOnConfig<K = unknown, TResponse = unknown> {
301
+ endpoint: string;
302
+ fieldName: string;
303
+ buildParams: (row: Record<string, unknown>) => Record<string, unknown>;
304
+ getResponse?: (response: TResponse, row: Row) => unknown;
305
+ mapFlags?: (response: TResponse) => Record<string, boolean>;
306
+ }
307
+ type ColumnAccessControl = {
308
+ allowRoles?: string[];
309
+ denyRoles?: string[];
310
+ rule?: (ctx: {
311
+ actor: Actor$1;
312
+ row: Row;
313
+ table: Table;
314
+ }) => boolean;
315
+ };
316
+ interface IDependOn {
317
+ fieldName: string;
318
+ value: any;
319
+ }
320
+ type DefaultOptionType = {
321
+ value?: string | number;
322
+ label?: any;
323
+ title?: string;
324
+ [key: string]: unknown;
325
+ };
326
+ interface ColumnSchema<T = unknown, K = unknown> {
327
+ fieldName: string;
328
+ fieldCaption: string;
329
+ fieldType: FieldType;
330
+ fieldCollection?: string;
331
+ order?: number;
332
+ rules?: IRule[];
333
+ options?: DefaultOptionType[];
334
+ editable?: boolean;
335
+ isUnique?: boolean;
336
+ noCache?: boolean;
337
+ expandable?: boolean;
338
+ returnValue?: (values: T, colId: string) => unknown;
339
+ returnDisplayValue?: (values: T, colId: string) => unknown;
340
+ enableDeleteButton?: boolean;
341
+ enableExpandButton?: boolean;
342
+ enableMoveButton?: boolean;
343
+ enableOptionsButton?: boolean;
344
+ disable?: boolean;
345
+ colAccess?: ColumnAccessControl;
346
+ dynamicSource?: {
347
+ endpoint: string;
348
+ dependsOn?: string[];
349
+ dependOn?: IDependOn | IDependOn[];
350
+ params?: Record<string, string>;
351
+ [key: string]: unknown;
352
+ };
353
+ hidden?: boolean;
354
+ className?: string;
355
+ visibility: ColumnVisibilityRule;
356
+ resolveOn?: ResolveOnConfig<K>;
357
+ computed?: {
358
+ dependsOn: readonly string[];
359
+ compute: (row: Record<string, unknown>, remoteApi: RemoteApi) => Promise<unknown>;
360
+ children?: [] | undefined;
361
+ };
362
+ selectOptions?: {
363
+ label: string;
364
+ value: string | number;
365
+ }[];
366
+ indexOptions?: (...args: any[]) => any[];
367
+ onChange?: (...args: any[]) => void;
368
+ displayFormat?: (value: unknown) => unknown;
369
+ minWidth?: number;
370
+ style?: any;
371
+ popUpWidth?: number;
372
+ dynamicSelectFilterOption?: (inputValue: string, option: any) => boolean;
373
+ labelValue?: 'selectDisplay' | 'selectValue';
374
+ }
375
+
376
+ declare class Collection {
377
+ name: string;
378
+ private rows;
379
+ private columns;
380
+ constructor(name: string | undefined, rows: Map<number, Row>, columns: Map<string, ColumnSchema>);
381
+ setCollectionName(name: string): void;
382
+ getCollectionName(): string;
383
+ getRows(): Map<number, Row>;
384
+ setRows(rows: Map<number, Row>): void;
385
+ getColumns(): Map<string, ColumnSchema>;
386
+ }
387
+
388
+ type CollectionScope = 'active' | 'all' | string[];
389
+ declare class Table {
390
+ readonly id: string;
391
+ private collection;
392
+ private pagination;
393
+ private action;
394
+ private activeCollection;
395
+ constructor(id: string, collection: Map<string, Collection>, pagination: Pagination, action: TableActions, activeCollection?: string);
396
+ private getActiveCollection;
397
+ private getCollection;
398
+ /** Finds which Collection currently owns a given column id (if any). */
399
+ private findCollectionForColumn;
400
+ getCollections(): Map<string, Collection>;
401
+ getColumnSchema(columnId: ColumnId): ColumnSchema | undefined;
402
+ getActiveCollectionName(): string;
403
+ setActiveCollection(activeCollection: string): void;
404
+ getRowCollection(rowId: number): string | undefined;
405
+ setRowCollection(rowId: number, collection: string): void;
406
+ setColumnSchema(columnId: ColumnId, DetailColumnConfig: ColumnSchema): ColumnSchema | undefined;
407
+ getColumns(): ColumnSchema[];
408
+ getActiveCollectionColumns(): ColumnSchema[];
409
+ getColumnsForCollectionScope(collectionScope?: CollectionScope): ColumnSchema[];
410
+ getColumnValues(colId: string): unknown[];
411
+ setColumns(newColumns: ColumnSchema[]): void;
412
+ changeCell(rowId: RowId, columnId: ColumnId, value: unknown): CellChanged | null;
413
+ changeDisplay(rowId: RowId, columnId: ColumnId, value: unknown): DisplayChanged | null;
414
+ saveDescription(rowId: RowId, flag: boolean): DescriptionSaved | null;
415
+ duplicateRow(rowId: RowId): RowAdded;
416
+ addRow(targetRowId: number, placedRowId?: number): RowAdded;
417
+ addNewRow(data?: KeyValue[]): RowAdded;
418
+ addNewRows(cmd: {
419
+ rows: KeyValue[][];
420
+ detailFieldKey: string;
421
+ }): RowAdded[];
422
+ addColumns(newColumns: ColumnSchema[]): {
423
+ added: ColumnId[];
424
+ };
425
+ removeColumns(columnIds: ColumnId[]): {
426
+ removed: ColumnId[];
427
+ };
428
+ getRows(collectionScope?: CollectionScope): Row[];
429
+ getCollectionsRows(collections: string[]): Row[];
430
+ getRow(rowId: number): Row | undefined;
431
+ addRows(newRows: Row[]): void;
432
+ getPagination(): Pagination;
433
+ setPagination(pagination: Pagination): void;
434
+ changePage(page: number): void;
435
+ changePageSize(size: number): void;
436
+ getVisibleRows(): Row[];
437
+ setTableAction(action: TableActions): void;
438
+ getTableAction(): TableActions;
439
+ /**
440
+ * Re-inserts a previously Added row after hard-remove (undo of ADD → redo).
441
+ * Preserves rowId and cell values; no-ops if the id already exists.
442
+ */
443
+ restoreAddedRow(params: {
444
+ rowId: number;
445
+ cells: Readonly<Record<string, {
446
+ readonly value: unknown;
447
+ readonly display?: unknown;
448
+ readonly originalValue?: unknown;
449
+ }>>;
450
+ collection?: string;
451
+ isSaveDescription?: boolean;
452
+ }): RowAdded;
453
+ deleteRow(rowId: RowId): RowDeleted | RowRestored | RowRemoved | MinimumRowConstraintViolated | null;
454
+ reorderRows(draggedRowNum: number, droppedRowNum: number, position?: 'before' | 'after'): RowReordered;
455
+ reorderColumns(sourceIndex: number, destIndex: number): ColumnReordered;
456
+ clone(): Table;
457
+ }
458
+
459
+ interface TableRepository {
460
+ getById(store: string, tableKey: string): Promise<Table>;
461
+ save(store: string, table: Table): Promise<void>;
462
+ delete(store: string, tableKey: string): Promise<void>;
463
+ resetTable(store: string, tableKey: string): Promise<void>;
464
+ exists(store: string, tableKey: string): Promise<boolean>;
465
+ getFromDbById?(store: string, tableKey: string): Promise<Table>;
466
+ }
467
+
468
+ /**
469
+ * Host-agnostic request config shape used by UI multi-select bindings.
470
+ * Host apps may narrow this to their own IRequestConfig.
471
+ */
472
+ type IRequestConfig = {
473
+ endpoint?: string;
474
+ params?: Record<string, unknown>;
475
+ method?: 'GET' | 'POST';
476
+ [key: string]: unknown;
477
+ };
478
+
479
+ interface UIRow {
480
+ id: number;
481
+ cells: Record<string, TCell>;
482
+ rowState: RowStateEnum;
483
+ isExpanded: boolean;
484
+ changeFields: readonly string[];
485
+ visibilityCondition: Record<string, boolean>;
486
+ }
487
+ type MultiSelectDependOn = {
488
+ fieldName: string;
489
+ value: unknown;
490
+ };
491
+ interface IMultiSelectConfig {
492
+ dynamicValue: IRequestConfig & {
493
+ dependsOn?: string[];
494
+ dependOn?: MultiSelectDependOn | MultiSelectDependOn[];
495
+ };
496
+ fieldKey: string;
497
+ detailFieldKey: string;
498
+ onAdd: (e: any) => void;
499
+ ListConfig: {
500
+ fieldName: string;
501
+ fieldCaption: string;
502
+ fieldType: FieldType;
503
+ hidden?: boolean;
504
+ returnValue?: (row: Record<string, unknown>[], colId: string) => unknown;
505
+ returnDisplayValue?: (row: Record<string, unknown>[], colId: string) => unknown;
506
+ }[];
507
+ }
508
+
509
+ type GridSearchMatch = {
510
+ rowId: number;
511
+ columnId: string;
512
+ };
513
+ type GridSearchState = {
514
+ columnId: string;
515
+ query: string;
516
+ matches: GridSearchMatch[];
517
+ currentIndex: number;
518
+ } | null;
519
+ type MobileEditorState = {
520
+ mode: 'add' | 'edit';
521
+ rowId: number;
522
+ } | null;
523
+ type TableViewState = {
524
+ activeCell: ActiveCell;
525
+ selectedRows: Record<number, true>;
526
+ rows: UIRow[];
527
+ deletedRows: Array<{
528
+ id: string;
529
+ cells: Record<string, unknown>;
530
+ isExpanded: boolean;
531
+ }>;
532
+ columns: ColumnSchema[];
533
+ activeCollectionColumn: ColumnSchema[];
534
+ pagination: {
535
+ page: number;
536
+ pageSize: number;
537
+ totalRows: number;
538
+ totalPages: number;
539
+ canPrev: boolean;
540
+ canNext: boolean;
541
+ };
542
+ action: TableActions;
543
+ gridSearch: GridSearchState;
544
+ mobileEditor: MobileEditorState;
545
+ };
546
+ type MobileTableViewState = {
547
+ rows: UIRow[];
548
+ columns: ColumnSchema[];
549
+ totalRows: number;
550
+ visibleCount: number;
551
+ hasMore: boolean;
552
+ pageSize: number;
553
+ mobileEditor: MobileEditorState;
554
+ };
555
+ type TableSnapShot = {
556
+ rows: Array<{
557
+ id: number;
558
+ cells: Record<string, unknown>;
559
+ rowState: RowStateEnum;
560
+ collection: string;
561
+ rowType?: string;
562
+ changeFields: readonly string[];
563
+ isSaveDescription: boolean;
564
+ }>;
565
+ };
566
+ type ActiveCell = {
567
+ rowId: number;
568
+ columnId: string;
569
+ } | null;
570
+ type ValidCell = {
571
+ isValid: boolean;
572
+ cellError: CellError;
573
+ };
574
+ type TableState = {
575
+ table: Table;
576
+ expandedRows: Record<string, boolean>;
577
+ selectedRows: Record<number, true>;
578
+ activeRowId: number | undefined;
579
+ activeCell: ActiveCell | undefined;
580
+ rangeAnchorRowId: number | undefined;
581
+ gridSearch: GridSearchState;
582
+ mobileEditor: MobileEditorState;
583
+ };
584
+ type TCell = {
585
+ value: unknown;
586
+ originalValue: unknown;
587
+ display: unknown;
588
+ };
589
+ type ItemType = {
590
+ type?: 'submenu' | 'item' | 'group' | 'divider';
591
+ label?: React.ReactNode;
592
+ children?: ItemType[];
593
+ disabled?: boolean;
594
+ ref?: React.Ref<HTMLLIElement | null>;
595
+ style?: React.CSSProperties;
596
+ className?: string;
597
+ isSelected?: boolean;
598
+ isOpen?: boolean;
599
+ isSubMenu?: boolean;
600
+ danger?: boolean;
601
+ icon?: React.ReactNode;
602
+ title?: string;
603
+ key: string;
604
+ theme?: 'dark' | 'light';
605
+ dashed?: boolean;
606
+ rootClassName?: string;
607
+ itemIcon?: React.ReactNode;
608
+ expandIcon?: React.ReactNode;
609
+ popupClassName?: string;
610
+ popupOffset?: number[];
611
+ popupStyle?: React.CSSProperties;
612
+ onClick?: () => void;
613
+ extra?: React.ReactNode;
614
+ };
615
+ type ValidationCallback = (result: ValidationCallbackResult) => void;
616
+ type ValidationCallbackResult = {
617
+ valid: boolean;
618
+ errors?: Map<string, CellError>;
619
+ data?: any;
620
+ };
621
+ interface CellError {
622
+ rowId: number;
623
+ caption: string;
624
+ message: string;
625
+ }
626
+
627
+ interface BaseTableCommand {
628
+ readonly store: string;
629
+ readonly tableKey: string;
630
+ /** When set, undoable events from separate executes merge into one undo unit. */
631
+ readonly correlationId?: string;
632
+ }
633
+ type Actor = {
634
+ readonly userId: string;
635
+ readonly roles: string[];
636
+ };
637
+ /**
638
+ * Base invariant:
639
+ * هر Command دقیقاً متعلق به یک Table است
640
+ */
641
+ interface MoveActiveCellCommand {
642
+ readonly type: 'MOVE_ACTIVE_CELL';
643
+ readonly store: string;
644
+ readonly tableKey: string;
645
+ readonly rowId: number;
646
+ readonly columnId: string;
647
+ readonly direction: 'next' | 'prev';
648
+ }
649
+ interface MoveActiveCellVerticalCommand {
650
+ readonly type: 'MOVE_ACTIVE_CELL_VERTICAL';
651
+ readonly store: string;
652
+ readonly tableKey: string;
653
+ readonly rowId: number;
654
+ readonly columnId: string;
655
+ readonly direction: 'up' | 'down';
656
+ }
657
+ interface MoveVerticalSelectedRows {
658
+ readonly type: 'MOVE_VERTICAL_SELECTED_ROWS';
659
+ readonly tableKey: string;
660
+ readonly direction: 'up' | 'down';
661
+ }
662
+ interface MoveVerticalActiveRow {
663
+ readonly type: 'MOVE_VERTICAL_ACTIVE_ROW';
664
+ readonly tableKey: string;
665
+ readonly direction: 'up' | 'down';
666
+ }
667
+ interface ActiveCellCommand {
668
+ readonly type: 'ACTIVE_CELL';
669
+ readonly tableKey: string;
670
+ readonly rowId: number;
671
+ readonly columnId: string;
672
+ }
673
+ interface ActiveRowCommand extends BaseTableCommand {
674
+ readonly type: 'ACTIVE_ROW';
675
+ readonly tableKey: string;
676
+ readonly rowId: number;
677
+ }
678
+ interface ActiveFirstCellCommand {
679
+ readonly type: 'ACTIVATE_FIRST_CELL';
680
+ readonly tableKey: string;
681
+ readonly rowId: number;
682
+ }
683
+ interface ChangeCellValueCommand extends BaseTableCommand {
684
+ readonly type: 'CHANGE_CELL_VALUE';
685
+ readonly rowId: number;
686
+ readonly columnId: string;
687
+ readonly newValue: unknown;
688
+ }
689
+ interface SaveDescriptionCommand extends BaseTableCommand {
690
+ readonly type: 'SAVE_DESCRIPTION';
691
+ readonly rowId: number;
692
+ readonly flag: boolean;
693
+ }
694
+ interface ChangeCellDisplayValueCommand extends BaseTableCommand {
695
+ readonly type: 'CHANGE_CELL_DISPLAY_VALUE';
696
+ readonly rowId: number;
697
+ readonly columnId: string;
698
+ readonly newValue: string;
699
+ }
700
+ interface AddEmptyRowCommand extends BaseTableCommand {
701
+ readonly type: 'ADD_EMPTY_ROW';
702
+ readonly autoActivate: boolean;
703
+ }
704
+ interface AddNewRowsCommand extends BaseTableCommand {
705
+ readonly type: 'ADD_NEW_ROWS';
706
+ readonly detailFieldKey: string;
707
+ readonly rows: {
708
+ key: string;
709
+ value: unknown;
710
+ display: unknown;
711
+ }[][];
712
+ readonly autoActivate?: boolean;
713
+ }
714
+ interface DuplicateRowCommand extends BaseTableCommand {
715
+ readonly type: 'DUPLICATE_ROW';
716
+ readonly rowId: number;
717
+ }
718
+ /**
719
+ * Clone one source row (clipboard paste). Engine batches these with a shared
720
+ * correlationId so undo reverses the whole paste unit.
721
+ */
722
+ interface PasteRowCommand extends BaseTableCommand {
723
+ readonly type: 'PASTE_ROW';
724
+ readonly sourceRowId: number;
725
+ /** When set (pasteInsert), place the clone relative to this row. */
726
+ readonly placeAtRowId?: number;
727
+ }
728
+ interface DeleteRowCommand extends BaseTableCommand {
729
+ readonly type: 'ROW_DELETED';
730
+ readonly rowId: number;
731
+ }
732
+ /** Undo-stack redo: re-insert a previously added row with original identity/values. */
733
+ interface RestoreAddedRowCommand extends BaseTableCommand {
734
+ readonly type: 'RESTORE_ADDED_ROW';
735
+ readonly rowId: number;
736
+ readonly cells: Readonly<Record<string, {
737
+ readonly value: unknown;
738
+ readonly display?: unknown;
739
+ readonly originalValue?: unknown;
740
+ }>>;
741
+ readonly collection?: string;
742
+ readonly isSaveDescription?: boolean;
743
+ }
744
+ interface DeleteRowsCommand extends BaseTableCommand {
745
+ readonly type: 'ROWS_DELETED';
746
+ }
747
+ interface ExpandRowCommand {
748
+ readonly type: 'ROW_EXPANDED';
749
+ readonly tableKey: string;
750
+ readonly rowId: number;
751
+ readonly value: boolean;
752
+ }
753
+ interface SelectRowCommand {
754
+ readonly type: 'ROW_SELECTED';
755
+ readonly tableKey: string;
756
+ readonly rowId: number;
757
+ }
758
+ interface ToggleRowSelectionCommand {
759
+ readonly type: "ROW_SELECTION_TOGGLED";
760
+ readonly tableKey: string;
761
+ readonly rowId: number;
762
+ }
763
+ interface ToggleRowExpandCommand {
764
+ readonly type: 'ROW_EXPAND_TOGGLED';
765
+ readonly tableKey: string;
766
+ readonly rowId: number;
767
+ }
768
+ interface SelectRangeCommand {
769
+ readonly type: "ROW_RANGE_SELECTED";
770
+ readonly tableKey: string;
771
+ readonly rowId: number;
772
+ }
773
+ interface SelectActiveRowToLastCommand {
774
+ readonly type: "SELECT_FROM_ACTIVE_TO_LAST";
775
+ readonly tableKey: string;
776
+ readonly anchorRowId: number;
777
+ }
778
+ interface RowReorderedCommand extends BaseTableCommand {
779
+ readonly type: 'ROW_REORDERED';
780
+ readonly draggedRowId: number;
781
+ readonly droppedRowId: number;
782
+ readonly position: 'before' | 'after';
783
+ }
784
+ interface SelectAllRowsCommand {
785
+ readonly type: 'TOGGLE_SELECT_ALL_ROWS';
786
+ readonly tableKey: string;
787
+ }
788
+ interface SelectPageRowsCommand {
789
+ readonly type: 'TOGGLE_SELECT_PAGE_ROWS';
790
+ readonly tableKey: string;
791
+ }
792
+ interface CollapseAllRowsCommand {
793
+ readonly type: 'COLLAPSE_ALL_ROWS';
794
+ readonly tableKey: string;
795
+ }
796
+ interface ColumnReorderedCommand extends BaseTableCommand {
797
+ readonly type: 'COLUMN_REORDERED';
798
+ readonly sourceIndex: number;
799
+ readonly destIndex: number;
800
+ }
801
+ interface DeleteTableCommand extends BaseTableCommand {
802
+ readonly type: 'TABLE_DELETED';
803
+ }
804
+ interface SetActiveCollectionCommand extends BaseTableCommand {
805
+ readonly type: 'SET_ACTIVE_COLLECTION';
806
+ readonly activeCollection: string;
807
+ }
808
+ interface ResetTableCommand extends BaseTableCommand {
809
+ readonly type: 'TABLE_RESET';
810
+ readonly rowId: string;
811
+ }
812
+ interface RegisterTableCommand extends BaseTableCommand {
813
+ readonly type: 'TABLE_REGISTERED';
814
+ readonly store: string;
815
+ readonly table: Table;
816
+ }
817
+ interface DisposeTableCommand extends BaseTableCommand {
818
+ readonly type: 'TABLE_DISPOSED';
819
+ }
820
+ interface ChangeTableActionCommand extends BaseTableCommand {
821
+ readonly type: 'SET_TABLE_ACTION';
822
+ action: TableActions;
823
+ }
824
+ interface ChangePageCommand extends BaseTableCommand {
825
+ readonly type: 'CHANGE_PAGE';
826
+ readonly page: number;
827
+ }
828
+ interface ChangePageSizeCommand extends BaseTableCommand {
829
+ readonly type: 'CHANGE_PAGE_SIZE';
830
+ readonly pageSize: number;
831
+ }
832
+ interface ChangeUnitLevelCommand extends BaseTableCommand {
833
+ readonly type: 'SET_UNIT_LEVEL';
834
+ readonly level: number;
835
+ }
836
+ interface ApplyDynamicProjectionCommand extends BaseTableCommand {
837
+ readonly type: 'APPLY_DYNAMIC_PROJECTION';
838
+ readonly tableKey: string;
839
+ readonly rowId: number;
840
+ readonly columnId: string;
841
+ }
842
+ interface SetGridSearchCommand {
843
+ readonly type: 'SET_GRID_SEARCH';
844
+ readonly tableKey: string;
845
+ readonly search: GridSearchState;
846
+ }
847
+ interface SetMobileEditorCommand {
848
+ readonly type: 'SET_MOBILE_EDITOR';
849
+ readonly tableKey: string;
850
+ readonly editor: MobileEditorState;
851
+ }
852
+ type EngineTableCommand = SelectActiveRowToLastCommand | SelectRangeCommand | ToggleRowExpandCommand | SelectRowCommand | ColumnReorderedCommand | CollapseAllRowsCommand | RegisterTableCommand | DisposeTableCommand | DeleteRowsCommand | ToggleRowSelectionCommand | SelectAllRowsCommand | SelectPageRowsCommand | ActiveCellCommand | ActiveRowCommand | MoveActiveCellCommand | MoveActiveCellVerticalCommand | MoveVerticalSelectedRows | MoveVerticalActiveRow | ActiveFirstCellCommand | ExpandRowCommand | ChangeTableActionCommand | SetGridSearchCommand | SetMobileEditorCommand;
853
+ type ApplicationTableCommand = ChangeCellValueCommand | SaveDescriptionCommand | ChangeCellDisplayValueCommand | AddEmptyRowCommand | AddNewRowsCommand | DuplicateRowCommand | PasteRowCommand | DeleteRowCommand | RestoreAddedRowCommand | DeleteTableCommand | SetActiveCollectionCommand | ResetTableCommand | RowReorderedCommand | ChangePageCommand | ChangePageSizeCommand | ApplyDynamicProjectionCommand | ChangeUnitLevelCommand;
854
+ type TableCommand = EngineTableCommand | ApplicationTableCommand;
855
+
856
+ interface BaseTableEvent {
857
+ readonly tableId: string;
858
+ readonly type: string;
859
+ }
860
+ interface CellChangedEvent extends BaseTableEvent {
861
+ type: 'CELL_CHANGED';
862
+ rowId: number;
863
+ columnId: string;
864
+ newValue: unknown;
865
+ previousValue: unknown;
866
+ }
867
+ interface DynamicProjectionEvent extends BaseTableEvent {
868
+ type: 'DYNAMIC_PROJECTION_DONE';
869
+ rowId: number;
870
+ columnId: string;
871
+ }
872
+ interface CellDisplayChangedEvent extends BaseTableEvent {
873
+ type: 'CELL_DISPLAY_CHANGED';
874
+ rowId: number;
875
+ columnId: string;
876
+ newValue: unknown;
877
+ }
878
+ interface RowAddedEvent extends BaseTableEvent {
879
+ type: 'ROW_ADDED';
880
+ rowId: string;
881
+ }
882
+ interface NewRowAddedEvent extends BaseTableEvent {
883
+ type: 'NEW_ROW_ADDED';
884
+ rowId: string;
885
+ }
886
+ interface RowDeletedEvent extends BaseTableEvent {
887
+ type: 'ROW_DELETED';
888
+ rowId: string;
889
+ }
890
+ interface NewRowRemovedEvent extends BaseTableEvent {
891
+ type: 'NEW_ROW_REMOVED';
892
+ rowId: string;
893
+ }
894
+ interface RowRestoredEvent extends BaseTableEvent {
895
+ type: 'ROW_RESTORED';
896
+ rowId: string;
897
+ }
898
+ interface RowReorderedEvent extends BaseTableEvent {
899
+ type: 'ROW_REORDERED';
900
+ sourceIndex: number;
901
+ destIndex: number;
902
+ }
903
+ interface RowDescriptionSaved extends BaseTableEvent {
904
+ type: 'ROW_DESCRIPTION_SAVED';
905
+ rowId: number;
906
+ description: boolean;
907
+ }
908
+ interface ColumnReorderedEvent extends BaseTableEvent {
909
+ type: 'COLUMN_REORDERED';
910
+ sourceIndex: number;
911
+ destIndex: number;
912
+ }
913
+ interface UnitColumnAddedEvent extends BaseTableEvent {
914
+ type: 'UNIT_COLUMN_ADDED';
915
+ reason: string;
916
+ details?: unknown;
917
+ }
918
+ interface PageChangedEvent extends BaseTableEvent {
919
+ type: 'PAGE_CHANGED';
920
+ page: number;
921
+ }
922
+ interface PageSizeChangedEvent extends BaseTableEvent {
923
+ type: 'PAGE_SIZE_CHANGED';
924
+ tableId: string;
925
+ pageSize: number;
926
+ }
927
+ interface TableDeletedEvent extends BaseTableEvent {
928
+ type: 'TABLE_DELETED';
929
+ tableId: string;
930
+ }
931
+ interface TableResetEvent extends BaseTableEvent {
932
+ type: 'TABLE_RESET';
933
+ tableId: string;
934
+ }
935
+ interface ActiveCollectionChangedEvent extends BaseTableEvent {
936
+ type: 'ACTIVE_COLLECTION_CHANGED';
937
+ tableId: string;
938
+ }
939
+ interface RowsLoadedEvent extends BaseTableEvent {
940
+ type: 'ROWS_LOADED';
941
+ count: number;
942
+ }
943
+ interface DynamicDataRequestedEvent extends BaseTableEvent {
944
+ type: 'DYNAMIC_DATA_REQUESTED';
945
+ requestId: string;
946
+ sourceColumn: string;
947
+ value: unknown;
948
+ }
949
+ interface ValidationFailedEvent extends BaseTableEvent {
950
+ type: 'VALIDATION_FAILED';
951
+ reason: string;
952
+ details?: unknown;
953
+ }
954
+ type TableEvent = CellChangedEvent | DynamicProjectionEvent | CellDisplayChangedEvent | RowAddedEvent | NewRowAddedEvent | RowDeletedEvent | NewRowRemovedEvent | RowRestoredEvent | RowReorderedEvent | RowDescriptionSaved | ColumnReorderedEvent | UnitColumnAddedEvent | PageChangedEvent | PageSizeChangedEvent | RowsLoadedEvent | DynamicDataRequestedEvent | ValidationFailedEvent | TableDeletedEvent | ActiveCollectionChangedEvent | TableResetEvent;
955
+
956
+ type DynamicConfig = {
957
+ columnMeta: Map<string, ColumnSchema>;
958
+ remoteApi: RemoteApi;
959
+ };
960
+ declare class ChangeCellValueHandler {
961
+ private readonly repo;
962
+ private readonly audit;
963
+ private readonly permissionPolicy;
964
+ private readonly dynamic?;
965
+ constructor(repo: TableRepository, audit: AuditLogger, permissionPolicy: PermissionPolicy, dynamic?: DynamicConfig | undefined);
966
+ execute(command: ChangeCellValueCommand, actor: Actor$1): Promise<TableEvent[]>;
967
+ private applyRemoteVisibilityRules;
968
+ private applyComputedColumns;
969
+ private validateCellValue;
970
+ private applyDynamicProjection;
971
+ }
972
+ declare class ChangeCellDisplayValueHandler {
973
+ private readonly repo;
974
+ private readonly audit;
975
+ private readonly permissionPolicy;
976
+ constructor(repo: TableRepository, audit: AuditLogger, permissionPolicy: PermissionPolicy);
977
+ execute(command: ChangeCellDisplayValueCommand, actor: Actor$1): Promise<TableEvent[]>;
978
+ }
979
+ declare class SaveDescriptionHandler {
980
+ private readonly repo;
981
+ private readonly audit;
982
+ private readonly permissionPolicy;
983
+ constructor(repo: TableRepository, audit: AuditLogger, permissionPolicy: PermissionPolicy);
984
+ execute(command: SaveDescriptionCommand, actor: Actor$1): Promise<TableEvent[]>;
985
+ }
986
+ declare class ApplyDynamicProjectionHandler {
987
+ private readonly repo;
988
+ private readonly audit;
989
+ private readonly permissionPolicy;
990
+ private readonly dynamic?;
991
+ constructor(repo: TableRepository, audit: AuditLogger, permissionPolicy: PermissionPolicy, dynamic?: DynamicConfig | undefined);
992
+ execute(command: ApplyDynamicProjectionCommand, actor: Actor$1): Promise<TableEvent[]>;
993
+ private applyRemoteVisibilityRules;
994
+ private applyComputedColumns;
995
+ private validateCellValue;
996
+ private applyDynamicProjection;
997
+ }
998
+
999
+ declare class AddNewRowCommandHandler {
1000
+ private readonly repo;
1001
+ private readonly audit;
1002
+ private readonly permission;
1003
+ constructor(repo: TableRepository, audit: AuditLogger, permission: PermissionPolicy);
1004
+ execute(command: AddEmptyRowCommand, actor: Actor$1): Promise<RowAdded | null>;
1005
+ }
1006
+ declare class AddNewRowsCommandHandler {
1007
+ private readonly repo;
1008
+ private readonly audit;
1009
+ private readonly permission;
1010
+ constructor(repo: TableRepository, audit: AuditLogger, permission: PermissionPolicy);
1011
+ execute(command: AddNewRowsCommand, actor: Actor$1): Promise<RowAdded[] | null>;
1012
+ }
1013
+ declare class PasteRowCommandHandler {
1014
+ private readonly repo;
1015
+ private readonly audit;
1016
+ private readonly permission;
1017
+ constructor(repo: TableRepository, audit: AuditLogger, permission: PermissionPolicy);
1018
+ execute(command: PasteRowCommand, actor: Actor$1): Promise<RowAdded | null>;
1019
+ }
1020
+ declare class DuplicateRowCommandHandler {
1021
+ private readonly repo;
1022
+ private readonly audit;
1023
+ private readonly permission;
1024
+ constructor(repo: TableRepository, audit: AuditLogger, permission: PermissionPolicy);
1025
+ execute(command: DuplicateRowCommand, actor: Actor$1): Promise<RowAdded | null>;
1026
+ }
1027
+ declare class DeleteRowCommandHandler {
1028
+ private readonly repo;
1029
+ private readonly audit;
1030
+ private readonly permission;
1031
+ constructor(repo: TableRepository, audit: AuditLogger, permission: PermissionPolicy);
1032
+ execute(command: DeleteRowCommand, actor: Actor$1): Promise<RowDeleted | RowRemoved | MinimumRowConstraintViolated | RowRestored | null>;
1033
+ }
1034
+ declare class RestoreAddedRowCommandHandler {
1035
+ private readonly repo;
1036
+ private readonly audit;
1037
+ private readonly permission;
1038
+ constructor(repo: TableRepository, audit: AuditLogger, permission: PermissionPolicy);
1039
+ execute(command: RestoreAddedRowCommand, actor: Actor$1): Promise<RowAdded | null>;
1040
+ }
1041
+ declare class ReorderRowCommandHandler {
1042
+ private readonly repo;
1043
+ private readonly audit;
1044
+ private readonly permission;
1045
+ constructor(repo: TableRepository, audit: AuditLogger, permission: PermissionPolicy);
1046
+ execute(command: RowReorderedCommand, actor: Actor$1): Promise<RowReordered | null>;
1047
+ }
1048
+
1049
+ declare class ChangeUnitLevelHandler {
1050
+ private readonly repo;
1051
+ private readonly audit;
1052
+ constructor(repo: TableRepository, audit: AuditLogger);
1053
+ execute(command: ChangeUnitLevelCommand, actor: Actor$1): Promise<TableEvent[]>;
1054
+ }
1055
+ declare class ChangePageCommandHandler {
1056
+ private readonly repo;
1057
+ private readonly audit;
1058
+ constructor(repo: TableRepository, audit: AuditLogger);
1059
+ execute(command: ChangePageCommand, actor: Actor$1): Promise<TableEvent[]>;
1060
+ }
1061
+ declare class ChangePageSizeCommandHandler {
1062
+ private readonly repo;
1063
+ private readonly audit;
1064
+ constructor(repo: TableRepository, audit: AuditLogger);
1065
+ execute(command: ChangePageSizeCommand, actor: Actor$1): Promise<TableEvent[]>;
1066
+ }
1067
+ declare class DeleteTableCommandHandler {
1068
+ private readonly repo;
1069
+ private readonly audit;
1070
+ private readonly permissionPolicy;
1071
+ constructor(repo: TableRepository, audit: AuditLogger, permissionPolicy: PermissionPolicy);
1072
+ execute(command: DeleteTableCommand, actor: Actor$1): Promise<TableEvent[]>;
1073
+ }
1074
+ declare class ResetTableCommandHandler {
1075
+ private readonly repo;
1076
+ private readonly audit;
1077
+ private readonly permissionPolicy;
1078
+ constructor(repo: TableRepository, audit: AuditLogger, permissionPolicy: PermissionPolicy);
1079
+ execute(command: ResetTableCommand, actor: Actor$1): Promise<TableEvent[]>;
1080
+ }
1081
+ declare class SetActiveCollectionCommandHandler {
1082
+ private readonly repo;
1083
+ private readonly audit;
1084
+ constructor(repo: TableRepository, audit: AuditLogger);
1085
+ private applyVisibility;
1086
+ execute(command: SetActiveCollectionCommand, actor: Actor$1): Promise<TableEvent[]>;
1087
+ }
1088
+
1089
+ interface GridEvent<TType extends string = string, TPayload = unknown> {
1090
+ readonly eventId: string;
1091
+ readonly type: TType;
1092
+ readonly tableId: string;
1093
+ readonly streamId: string;
1094
+ readonly version: number;
1095
+ readonly occurredAt: number;
1096
+ readonly actorId: string;
1097
+ readonly payload: TPayload;
1098
+ readonly correlationId?: string;
1099
+ readonly causationId?: string;
1100
+ }
1101
+ interface ExportRequestedPayload {
1102
+ readonly format: 'xlsx' | 'pdf';
1103
+ readonly collectionScope: 'active' | 'all' | string[];
1104
+ readonly fileName?: string;
1105
+ readonly sheetName?: string;
1106
+ readonly direction?: 'rtl' | 'ltr';
1107
+ }
1108
+ interface ImportRequestedPayload {
1109
+ readonly format: 'xlsx';
1110
+ readonly collectionScope: 'active' | 'all' | string[];
1111
+ readonly sheetName?: string;
1112
+ readonly byteLength?: number;
1113
+ }
1114
+
1115
+ type AppendResult = {
1116
+ ok: true;
1117
+ version: number;
1118
+ } | {
1119
+ ok: false;
1120
+ conflict: {
1121
+ expectedVersion: number;
1122
+ actualVersion: number;
1123
+ };
1124
+ };
1125
+ type Unsubscribe = () => void;
1126
+ interface EventStore {
1127
+ append(streamId: string, events: GridEvent[], expectedVersion: number): Promise<AppendResult>;
1128
+ read(streamId: string, fromVersion?: number): Promise<GridEvent[]>;
1129
+ /** Ordered global stream for catch-up of cross-stream projections. */
1130
+ readAll(fromPosition?: number): Promise<GridEvent[]>;
1131
+ subscribe(streamId: string, onEvent: (event: GridEvent) => void): Unsubscribe;
1132
+ subscribeAll(onEvent: (event: GridEvent) => void): Unsubscribe;
1133
+ }
1134
+
1135
+ interface CellUndoEntry {
1136
+ readonly kind: 'CELL_CHANGED';
1137
+ readonly tableId: string;
1138
+ readonly rowId: number;
1139
+ readonly columnId: string;
1140
+ readonly newValue: unknown;
1141
+ readonly previousValue: unknown;
1142
+ }
1143
+ type RowCellSnapshot = {
1144
+ readonly value: unknown;
1145
+ readonly display?: unknown;
1146
+ readonly originalValue?: unknown;
1147
+ };
1148
+ interface RowAddedUndoEntry {
1149
+ readonly kind: 'ROW_ADDED';
1150
+ readonly tableId: string;
1151
+ readonly rowId: number;
1152
+ /** Captured at record time so redo can restore identity + values. */
1153
+ readonly cells: Readonly<Record<string, RowCellSnapshot>>;
1154
+ readonly collection?: string;
1155
+ readonly isSaveDescription?: boolean;
1156
+ }
1157
+ /**
1158
+ * Compensating entry for a delete:
1159
+ * - soft: Unchanged→Deleted (undo/redo = toggle ROW_DELETED)
1160
+ * - hard: Added row removed from map (undo = RESTORE_ADDED_ROW)
1161
+ */
1162
+ interface RowDeletedUndoEntry {
1163
+ readonly kind: 'ROW_DELETED';
1164
+ readonly tableId: string;
1165
+ readonly rowId: number;
1166
+ readonly mode: 'soft' | 'hard';
1167
+ readonly cells: Readonly<Record<string, RowCellSnapshot>>;
1168
+ readonly collection?: string;
1169
+ readonly isSaveDescription?: boolean;
1170
+ }
1171
+ type AtomicUndoEntry = CellUndoEntry | RowAddedUndoEntry | RowDeletedUndoEntry;
1172
+ type UndoDispatchCommand = {
1173
+ type: 'CHANGE_CELL_VALUE';
1174
+ store: string;
1175
+ tableKey: string;
1176
+ rowId: number;
1177
+ columnId: string;
1178
+ newValue: unknown;
1179
+ } | {
1180
+ type: 'ROW_DELETED';
1181
+ store: string;
1182
+ tableKey: string;
1183
+ rowId: number;
1184
+ } | {
1185
+ type: 'RESTORE_ADDED_ROW';
1186
+ store: string;
1187
+ tableKey: string;
1188
+ rowId: number;
1189
+ cells: Readonly<Record<string, RowCellSnapshot>>;
1190
+ collection?: string;
1191
+ isSaveDescription?: boolean;
1192
+ };
1193
+ type CellUndoDispatch = (command: UndoDispatchCommand) => Promise<void>;
1194
+ /**
1195
+ * Compensating undo/redo stack for domain edits.
1196
+ * - CELL_CHANGED: restore previousValue / re-apply newValue
1197
+ * - ROW_ADDED: delete on undo; RESTORE_ADDED_ROW on redo
1198
+ * - ROW_DELETED soft: toggle ROW_DELETED; hard: RESTORE_ADDED_ROW / ROW_DELETED
1199
+ * - Same correlationId merges into one undo unit (paste / cut+paste)
1200
+ */
1201
+ declare class CellUndoStack {
1202
+ private undoEntries;
1203
+ private redoEntries;
1204
+ private applying;
1205
+ record(event: CellChangedEvent, correlationId?: string): void;
1206
+ recordRowAdded(event: {
1207
+ tableId: string;
1208
+ rowId: number;
1209
+ cells?: Readonly<Record<string, RowCellSnapshot>>;
1210
+ collection?: string;
1211
+ isSaveDescription?: boolean;
1212
+ }, correlationId?: string): void;
1213
+ recordRowDeleted(event: {
1214
+ tableId: string;
1215
+ rowId: number;
1216
+ mode: 'soft' | 'hard';
1217
+ cells?: Readonly<Record<string, RowCellSnapshot>>;
1218
+ collection?: string;
1219
+ isSaveDescription?: boolean;
1220
+ }, correlationId?: string): void;
1221
+ recordMany(entries: AtomicUndoEntry[], correlationId?: string): void;
1222
+ canUndo(): boolean;
1223
+ canRedo(): boolean;
1224
+ undoDepth(): number;
1225
+ redoDepth(): number;
1226
+ undo(store: string, dispatch: CellUndoDispatch): Promise<boolean>;
1227
+ redo(store: string, dispatch: CellUndoDispatch): Promise<boolean>;
1228
+ clear(): void;
1229
+ private pushAtomic;
1230
+ private applyCompensating;
1231
+ private applyForward;
1232
+ }
1233
+
1234
+ declare class TableAppService {
1235
+ private readonly changeCellValue;
1236
+ private readonly changeCellDisplayValue;
1237
+ private readonly saveDescription;
1238
+ private readonly addEmptyRow;
1239
+ private readonly addNewRows;
1240
+ private readonly duplicateRow;
1241
+ private readonly deleteRow;
1242
+ private readonly reorderRow;
1243
+ private readonly setUnitLevel;
1244
+ private readonly setPageSize;
1245
+ private readonly setPage;
1246
+ private readonly setActiveCollection;
1247
+ private readonly deleteTable;
1248
+ private readonly resetTable;
1249
+ private readonly applyDynamicProjection;
1250
+ private readonly restoreAddedRow?;
1251
+ private readonly pasteRow?;
1252
+ private eventStore?;
1253
+ private undoStack?;
1254
+ private repo?;
1255
+ constructor(changeCellValue: ChangeCellValueHandler, changeCellDisplayValue: ChangeCellDisplayValueHandler, saveDescription: SaveDescriptionHandler, addEmptyRow: AddNewRowCommandHandler, addNewRows: AddNewRowsCommandHandler, duplicateRow: DuplicateRowCommandHandler, deleteRow: DeleteRowCommandHandler, reorderRow: ReorderRowCommandHandler, setUnitLevel: ChangeUnitLevelHandler, setPageSize: ChangePageSizeCommandHandler, setPage: ChangePageCommandHandler, setActiveCollection: SetActiveCollectionCommandHandler, deleteTable: DeleteTableCommandHandler, resetTable: ResetTableCommandHandler, applyDynamicProjection: ApplyDynamicProjectionHandler, restoreAddedRow?: RestoreAddedRowCommandHandler | undefined, pasteRow?: PasteRowCommandHandler | undefined);
1256
+ setEventStore(eventStore: EventStore): void;
1257
+ setUndoStack(undoStack: CellUndoStack): void;
1258
+ setRepository(repo: TableRepository): void;
1259
+ execute(command: ApplicationTableCommand, actor: Actor): Promise<RowAdded | RowDeleted | RowRemoved | MinimumRowConstraintViolated | RowRestored | RowReordered | RowAdded[] | TableEvent[] | null>;
1260
+ private dispatch;
1261
+ private recordUndoableEvents;
1262
+ private captureRowSnapshot;
1263
+ private appendToEventStore;
1264
+ private normalizeResult;
1265
+ private resolveRowId;
1266
+ private toGridPayload;
1267
+ private createCorrelationId;
1268
+ }
1269
+
1270
+ declare class ConsoleAuditLogger implements AuditLogger {
1271
+ log(event: unknown): void;
1272
+ error(event: unknown): void;
1273
+ warn(event: unknown): void;
1274
+ info(event: unknown): void;
1275
+ }
1276
+
1277
+ declare class TableEngine {
1278
+ private readonly app;
1279
+ private readonly repo;
1280
+ private readonly actor;
1281
+ private tableStore?;
1282
+ private tableKey?;
1283
+ readonly errors: Map<string, CellError>;
1284
+ readonly searchResult: Map<string, CellError>;
1285
+ private readonly errHandler;
1286
+ private readonly selection;
1287
+ private readonly rowMgr;
1288
+ private readonly nav;
1289
+ private readonly viewBuilder;
1290
+ constructor(app: TableAppService, repo: TableRepository, actor: Actor, audit: ConsoleAuditLogger);
1291
+ private registerTable;
1292
+ private deleteTable;
1293
+ private disposeTable;
1294
+ private resetTable;
1295
+ private getStore;
1296
+ /**
1297
+ * Default case در dispatch:
1298
+ * command را به AppService می‌دهد و سپس repo را reload می‌کند.
1299
+ */
1300
+ private executeAppCommand;
1301
+ /**
1302
+ * Paste goes through AppService (PASTE_ROW + optional ROW_DELETED for cut)
1303
+ * with one correlationId so undo reverses the whole unit.
1304
+ */
1305
+ private executePasteAction;
1306
+ dispatch(command: TableCommand): Promise<void>;
1307
+ private setGridSearch;
1308
+ private setMobileEditor;
1309
+ getViewState(): TableViewState | undefined;
1310
+ getAllRows(): Row[] | null;
1311
+ getAllUIRows(): UIRow[] | null;
1312
+ getMobileViewState(): MobileTableViewState | undefined;
1313
+ getRowView(rowId: number): UIRow | null;
1314
+ getSnapShot(collectionScope: CollectionScope): TableSnapShot | null;
1315
+ getExpandedRowData(rowId: number): Record<string, unknown> | null;
1316
+ getActiveCell(): TableState['activeCell'] | null;
1317
+ getActiveRow(): number | null;
1318
+ getSelectedRows(): Record<number, boolean> | undefined;
1319
+ getCell(rowId: number, columnId: string): Cell | undefined;
1320
+ getMobileEditor(): TableState['mobileEditor'] | undefined;
1321
+ isActiveCell(rowId: number, columnId: string): boolean;
1322
+ isSelectedRow(rowId: number): boolean;
1323
+ isCutRow(rowId: number): boolean;
1324
+ isActiveRow(rowId: number): boolean;
1325
+ private validateCell;
1326
+ validation(cb: ValidationCallback): void;
1327
+ isValidCell(rowId: number, caption: string): ValidCell;
1328
+ subscribe(cb: () => void): (() => void) | null;
1329
+ /**
1330
+ * Selector-based subscription over engine-derived view data.
1331
+ * `selector` closes over engine getters (snapshot, activeCell, …).
1332
+ */
1333
+ subscribeSelected<TSelected>(selector: () => TSelected, listener: (selected: TSelected) => void, isEqual?: (a: TSelected, b: TSelected) => boolean): (() => void) | null;
1334
+ subscribeColumn<T = unknown>(columnId: string, collections: CollectionScope, cb: (items: Array<{
1335
+ id: number;
1336
+ rowNum: unknown;
1337
+ value: T;
1338
+ }>) => void): (() => void) | null;
1339
+ }
1340
+
1341
+ interface ChangelogEntry {
1342
+ readonly eventId: string;
1343
+ readonly type: string;
1344
+ readonly tableId: string;
1345
+ readonly occurredAt: number;
1346
+ readonly actorId: string;
1347
+ readonly payload: unknown;
1348
+ }
1349
+ interface ChangelogQuery {
1350
+ tableId?: string;
1351
+ rowId?: number | string;
1352
+ columnId?: string;
1353
+ type?: string;
1354
+ since?: number;
1355
+ limit?: number;
1356
+ }
1357
+ declare class ChangelogProjection {
1358
+ private readonly eventStore;
1359
+ private entries;
1360
+ private unsubscribe;
1361
+ private subscribers;
1362
+ private seenEventIds;
1363
+ private started;
1364
+ constructor(eventStore: EventStore);
1365
+ /**
1366
+ * Catch up via readAll, then subscribe for live events.
1367
+ * Dedupes by eventId so subscribe-before-replay races are safe.
1368
+ */
1369
+ start(): Promise<void>;
1370
+ stop(): void;
1371
+ query(filter?: ChangelogQuery): ChangelogEntry[];
1372
+ count(filter?: ChangelogQuery): number;
1373
+ subscribe(notify: (entries: ChangelogEntry[]) => void, filter?: ChangelogQuery): Unsubscribe;
1374
+ clear(): void;
1375
+ private project;
1376
+ private notifySubscribers;
1377
+ }
1378
+
1379
+ type HistorySeverity = 'info' | 'warning' | 'error';
1380
+ type HistoryCategory = 'data' | 'structure' | 'view' | 'system';
1381
+ interface HistoryQuery extends ChangelogQuery {
1382
+ severity?: HistorySeverity;
1383
+ category?: HistoryCategory;
1384
+ }
1385
+ interface HistoryItem {
1386
+ readonly id: string;
1387
+ readonly type: string;
1388
+ readonly title: string;
1389
+ readonly description: string;
1390
+ readonly occurredAt: number;
1391
+ readonly tableId: string;
1392
+ readonly actorId: string;
1393
+ readonly severity: HistorySeverity;
1394
+ readonly category: HistoryCategory;
1395
+ readonly raw: ChangelogEntry;
1396
+ }
1397
+ declare class HistoryPanelViewModel {
1398
+ private readonly changelogProjection;
1399
+ constructor(changelogProjection: ChangelogProjection);
1400
+ query(filter?: HistoryQuery): HistoryItem[];
1401
+ count(filter?: HistoryQuery): number;
1402
+ subscribe(cb: (items: HistoryItem[]) => void, filter?: HistoryQuery): Unsubscribe;
1403
+ private toHistoryItem;
1404
+ }
1405
+
1406
+ /**
1407
+ * Session-centric view / keyboard intents.
1408
+ * These are not domain commands; GridSession maps them to engine dispatches.
1409
+ */
1410
+ type ViewIntent = {
1411
+ type: 'ADD_EMPTY_ROW';
1412
+ autoActivate?: boolean;
1413
+ } | {
1414
+ type: 'DUPLICATE_ROW';
1415
+ rowId: number;
1416
+ } | {
1417
+ type: 'DELETE_ROW';
1418
+ rowId: number;
1419
+ } | {
1420
+ type: 'TOGGLE_ROW_SELECTION';
1421
+ rowId: number;
1422
+ } | {
1423
+ type: 'SELECT_FROM_ACTIVE_TO_LAST';
1424
+ anchorRowId: number;
1425
+ } | {
1426
+ type: 'ACTIVATE_FIRST_CELL';
1427
+ rowId: number;
1428
+ } | {
1429
+ type: 'MOVE_ACTIVE_CELL';
1430
+ rowId: number;
1431
+ columnId: string;
1432
+ direction: 'next' | 'prev';
1433
+ } | {
1434
+ type: 'MOVE_ACTIVE_CELL_VERTICAL';
1435
+ rowId: number;
1436
+ columnId: string;
1437
+ direction: 'up' | 'down';
1438
+ } | {
1439
+ type: 'MOVE_VERTICAL_SELECTED_ROWS';
1440
+ direction: 'up' | 'down';
1441
+ } | {
1442
+ type: 'MOVE_VERTICAL_ACTIVE_ROW';
1443
+ direction: 'up' | 'down';
1444
+ } | {
1445
+ type: 'COLLAPSE_ALL_ROWS';
1446
+ } | {
1447
+ type: 'CHANGE_PAGE';
1448
+ page: number;
1449
+ } | {
1450
+ type: 'CHANGE_PAGE_SIZE';
1451
+ pageSize: number;
1452
+ } | {
1453
+ type: 'SET_TABLE_ACTION';
1454
+ action: TableActions;
1455
+ } | {
1456
+ type: 'SET_GRID_SEARCH';
1457
+ search: GridSearchState;
1458
+ } | {
1459
+ type: 'SET_MOBILE_EDITOR';
1460
+ editor: MobileEditorState;
1461
+ } | {
1462
+ type: 'CHANGE_VIEWPORT';
1463
+ scrollOffset: number;
1464
+ viewportSize?: number;
1465
+ rowHeight?: number;
1466
+ overscan?: number;
1467
+ } | {
1468
+ type: 'UNDO';
1469
+ } | {
1470
+ type: 'REDO';
1471
+ };
1472
+ type ViewIntentDispatcher = (intent: ViewIntent) => Promise<void>;
1473
+
1474
+ type GridSessionSubscribeSelected = <TSelected>(selector: () => TSelected, listener: (selected: TSelected) => void, isEqual?: (a: TSelected, b: TSelected) => boolean) => () => void;
1475
+ /**
1476
+ * Framework-agnostic session facade (target shape of useGrid / createGrid).
1477
+ * Adapters should prefer this over raw Engine.
1478
+ */
1479
+ interface GridSession {
1480
+ readonly store: string;
1481
+ readonly tableKey: string;
1482
+ dispatchViewIntent: ViewIntentDispatcher;
1483
+ handleKeydown(event: KeyboardEvent, ctx: {
1484
+ activeRowId: number | null;
1485
+ activeColumnId: string | null;
1486
+ }): Promise<void>;
1487
+ getSnapShot(collectionScope?: CollectionScope): TableSnapShot | null;
1488
+ getViewState(): ReturnType<TableEngine['getViewState']>;
1489
+ subscribe(cb: () => void): () => void;
1490
+ subscribeSelected: GridSessionSubscribeSelected;
1491
+ canUndo(): boolean;
1492
+ canRedo(): boolean;
1493
+ undo(): Promise<boolean>;
1494
+ redo(): Promise<boolean>;
1495
+ getChangelog(filter?: Omit<ChangelogQuery, 'tableId'>): ChangelogEntry[];
1496
+ getChangelogCount(filter?: Omit<ChangelogQuery, 'tableId'>): number;
1497
+ subscribeChangelog(cb: (entries: ChangelogEntry[]) => void, filter?: Omit<ChangelogQuery, 'tableId'>): () => void;
1498
+ getHistoryItems(filter?: Omit<HistoryQuery, 'tableId'>): HistoryItem[];
1499
+ getHistoryItemCount(filter?: Omit<HistoryQuery, 'tableId'>): number;
1500
+ subscribeHistoryItems(cb: (items: HistoryItem[]) => void, filter?: Omit<HistoryQuery, 'tableId'>): () => void;
1501
+ getEngine(): TableEngine;
1502
+ /** Current virtual-scroll viewport (view state; not domain). */
1503
+ getViewport(): Viewport;
1504
+ getVisibleRange(totalRows?: number): VisibleRange;
1505
+ projectVisibleRows<T>(rows: readonly T[], totalRows?: number): T[];
1506
+ }
1507
+
1508
+ interface UICommandBase {
1509
+ readonly type: string;
1510
+ }
1511
+ interface UICellChangeEvent extends UICommandBase {
1512
+ readonly type: 'UI_CELL_CHANGE';
1513
+ readonly rowId: number;
1514
+ readonly columnId: string;
1515
+ readonly value: unknown;
1516
+ }
1517
+ interface UIDescriptionSaveEvent extends UICommandBase {
1518
+ readonly type: 'UI_DESCRIPTION_SAVE';
1519
+ readonly rowId: number;
1520
+ readonly flag: boolean;
1521
+ }
1522
+ interface UICellChangeDisplayEvent extends UICommandBase {
1523
+ readonly type: 'UI_CELL_CHANGE_DISPLAY';
1524
+ readonly rowId: number;
1525
+ readonly columnId: string;
1526
+ readonly value: string;
1527
+ }
1528
+ interface UIMoveActiveCellEvent extends UICommandBase {
1529
+ readonly type: 'UI_MOVE_ACTIVE_CELL';
1530
+ readonly rowId: number;
1531
+ readonly columnId: string;
1532
+ readonly direction: "next" | "prev";
1533
+ }
1534
+ interface UIMoveActiveVerticalCellEvent extends UICommandBase {
1535
+ readonly type: 'UI_MOVE_ACTIVE_CELL_VERTICAL';
1536
+ readonly rowId: number;
1537
+ readonly columnId: string;
1538
+ readonly direction: 'up' | 'down';
1539
+ }
1540
+ interface UIActiveFirstCellEvent extends UICommandBase {
1541
+ readonly type: 'UI_ACTIVE_FIRST_CELL';
1542
+ readonly rowId: number;
1543
+ }
1544
+ interface UIActiveCellEvent extends UICommandBase {
1545
+ readonly type: 'UI_ACTIVE_CELL';
1546
+ readonly rowId: number;
1547
+ readonly columnId: string;
1548
+ }
1549
+ interface ChangePageSizeUiCommand extends UICommandBase {
1550
+ readonly type: 'CHANGE_PAGE_SIZE';
1551
+ readonly pageSize: number;
1552
+ }
1553
+ interface ChangePageUiCommand extends UICommandBase {
1554
+ readonly type: 'CHANGE_PAGE';
1555
+ readonly page: number;
1556
+ }
1557
+ interface ActiveRowUiCommand extends UICommandBase {
1558
+ readonly type: 'UI_ACTIVE_ROW';
1559
+ readonly rowId: number;
1560
+ }
1561
+ interface AddEmptyRowUiCommand extends UICommandBase {
1562
+ readonly type: 'ADD_EMPTY_ROW';
1563
+ }
1564
+ interface AddNewRowsUiCommand extends UICommandBase {
1565
+ readonly type: 'ADD_NEW_ROWS';
1566
+ readonly detailFieldKey: string;
1567
+ readonly rows: {
1568
+ key: string;
1569
+ value: unknown;
1570
+ display: unknown;
1571
+ }[][];
1572
+ }
1573
+ interface DuplicateRowUiCommand extends UICommandBase {
1574
+ readonly type: 'DUPLICATE_ROW';
1575
+ readonly rowId: number;
1576
+ }
1577
+ interface DeleteRowUiCommand extends UICommandBase {
1578
+ readonly type: 'ROW_DELETED';
1579
+ readonly rowId: number;
1580
+ }
1581
+ interface DeleteSelectedRowsUiCommand extends UICommandBase {
1582
+ readonly type: 'UI_DELETE_SELECTED_ROW';
1583
+ }
1584
+ interface DeleteTableUiCommand extends UICommandBase {
1585
+ readonly type: 'TABLE_DELETED';
1586
+ }
1587
+ interface RegisterTableUiCommand extends UICommandBase {
1588
+ readonly type: 'TABLE_REGISTERED';
1589
+ readonly storeName: string;
1590
+ readonly table: Table;
1591
+ }
1592
+ interface ToggleRowExpandedUiCommand extends UICommandBase {
1593
+ readonly type: 'TOGGLE_ROW_EXPANDED';
1594
+ readonly rowId: number;
1595
+ }
1596
+ interface ReorderRowUiCommand extends UICommandBase {
1597
+ readonly type: 'ROW_REORDERED';
1598
+ readonly draggedRowId: number;
1599
+ readonly droppedRowId: number;
1600
+ readonly position: 'before' | 'after';
1601
+ }
1602
+ interface ToggleRowSelectedUiCommand extends UICommandBase {
1603
+ readonly type: 'TOGGLE_ROW_SELECTED';
1604
+ }
1605
+ interface TogglePageRowSelectedUiCommand extends UICommandBase {
1606
+ readonly type: 'TOGGLE_PAGE_ROW_SELECTED';
1607
+ }
1608
+ interface RowSelectedUiCommand extends UICommandBase {
1609
+ readonly type: 'ROW_SELECTED';
1610
+ readonly rowId: number;
1611
+ }
1612
+ interface ActionTableUiCommand extends UICommandBase {
1613
+ readonly type: 'UI_ACTION_TABLE';
1614
+ readonly action: TableActions;
1615
+ }
1616
+ interface ActiveCollectionUiCommand extends UICommandBase {
1617
+ readonly type: 'UI_CHANGE_ACTIVE_COLLECTION';
1618
+ readonly activeCollection: string;
1619
+ }
1620
+ interface KeyDownUiCommand extends UICommandBase {
1621
+ readonly type: 'KEY_DOWN';
1622
+ readonly event: KeyboardEvent;
1623
+ readonly ctx: {
1624
+ tableKey: string;
1625
+ activeRowId: number | null;
1626
+ activeColumnId: string | null;
1627
+ };
1628
+ }
1629
+ interface SetGridSearchUiCommand extends UICommandBase {
1630
+ readonly type: 'UI_SET_GRID_SEARCH';
1631
+ readonly search: GridSearchState;
1632
+ }
1633
+ interface ClearGridSearchUiCommand extends UICommandBase {
1634
+ readonly type: 'UI_CLEAR_GRID_SEARCH';
1635
+ }
1636
+ interface OpenMobileAddUiCommand extends UICommandBase {
1637
+ readonly type: 'UI_OPEN_MOBILE_ADD';
1638
+ }
1639
+ interface OpenMobileEditUiCommand extends UICommandBase {
1640
+ readonly type: 'UI_OPEN_MOBILE_EDIT';
1641
+ readonly rowId: number;
1642
+ }
1643
+ interface CloseMobileEditorUiCommand extends UICommandBase {
1644
+ readonly type: 'UI_CLOSE_MOBILE_EDITOR';
1645
+ }
1646
+ type UITableCommand = ActiveRowUiCommand | ToggleRowSelectedUiCommand | TogglePageRowSelectedUiCommand | RowSelectedUiCommand | UIMoveActiveVerticalCellEvent | UIMoveActiveCellEvent | UIActiveCellEvent | UIActiveFirstCellEvent | UICellChangeEvent | UIDescriptionSaveEvent | UICellChangeDisplayEvent | ChangePageSizeUiCommand | ChangePageUiCommand | AddEmptyRowUiCommand | AddNewRowsUiCommand | DuplicateRowUiCommand | DeleteRowUiCommand | DeleteTableUiCommand | RegisterTableUiCommand | ToggleRowExpandedUiCommand | ReorderRowUiCommand | ActionTableUiCommand | ActiveCollectionUiCommand | DeleteSelectedRowsUiCommand | KeyDownUiCommand | SetGridSearchUiCommand | ClearGridSearchUiCommand | OpenMobileAddUiCommand | OpenMobileEditUiCommand | CloseMobileEditorUiCommand;
1647
+
1648
+ declare class UITableController {
1649
+ private readonly engine;
1650
+ private readonly store;
1651
+ private readonly tableKey;
1652
+ private readonly audit;
1653
+ private readonly changelogProjection?;
1654
+ private readonly historyPanelViewModel?;
1655
+ private readonly cellUndoStack?;
1656
+ private readonly session?;
1657
+ private readonly remoteApi?;
1658
+ private disposed;
1659
+ constructor(engine: TableEngine, store: string, tableKey: string, audit: AuditLogger, changelogProjection?: ChangelogProjection | undefined, historyPanelViewModel?: HistoryPanelViewModel | undefined, cellUndoStack?: CellUndoStack | undefined, session?: GridSession | undefined, remoteApi?: RemoteApi | undefined);
1660
+ getRemoteApi(): RemoteApi | undefined;
1661
+ private safe;
1662
+ private changePageSize;
1663
+ private changePage;
1664
+ private onCellChange;
1665
+ private onDescriptionSave;
1666
+ private onCellDisplayChange;
1667
+ private setActiveCell;
1668
+ private setActiveRow;
1669
+ private moveActiveCellVertical;
1670
+ private reorderRow;
1671
+ private addEmptyRow;
1672
+ private openMobileAddEditor;
1673
+ private addNewRows;
1674
+ private duplicateRow;
1675
+ private deleteRow;
1676
+ private deleteRows;
1677
+ private deleteTable;
1678
+ private registerTable;
1679
+ private toggleRowExpanded;
1680
+ private toggleRowSelect;
1681
+ private togglePageRowSelect;
1682
+ private selectFromActiveToLast;
1683
+ private activateFirstEditableCell;
1684
+ private moveToNextCell;
1685
+ private setTableAction;
1686
+ private setActiveCollection;
1687
+ private setGridSearch;
1688
+ private setMobileEditor;
1689
+ getViewState(): TableViewState | null | undefined;
1690
+ getMobileViewState(): MobileTableViewState | null | undefined;
1691
+ getRowView(rowId: number): UIRow | null;
1692
+ getAllRows(): Row[] | null;
1693
+ getAllUIRows(): UIRow[] | null;
1694
+ getSnapShot(collectionScope?: CollectionScope): TableSnapShot | null;
1695
+ getCell(rowId: number, columnId: string): Cell | null | undefined;
1696
+ getChangelog(filter?: Omit<ChangelogQuery, 'tableId'>): ChangelogEntry[];
1697
+ getChangelogCount(filter?: Omit<ChangelogQuery, 'tableId'>): number;
1698
+ subscribeChangelog(cb: (entries: ChangelogEntry[]) => void, filter?: Omit<ChangelogQuery, 'tableId'>): () => void;
1699
+ getHistoryItems(filter?: Omit<HistoryQuery, 'tableId'>): HistoryItem[];
1700
+ getHistoryItemCount(filter?: Omit<HistoryQuery, 'tableId'>): number;
1701
+ subscribeHistoryItems(cb: (items: HistoryItem[]) => void, filter?: Omit<HistoryQuery, 'tableId'>): () => void;
1702
+ canUndo(): boolean;
1703
+ canRedo(): boolean;
1704
+ undo(): Promise<boolean>;
1705
+ redo(): Promise<boolean>;
1706
+ getActiveRow(): number | null;
1707
+ getSelectedRows(): Record<number, boolean> | null | undefined;
1708
+ getActiveCell(): ActiveCell | undefined;
1709
+ getMobileEditor(): MobileEditorState | undefined;
1710
+ resetMobileVisibleRows(size?: number): void;
1711
+ loadMoreMobileRows(step?: number): void;
1712
+ revealAllMobileRows(minSize?: number): void;
1713
+ isActiveCell(rowId: number, columnId: string): boolean | null;
1714
+ isActiveRow(rowId: number): boolean | null;
1715
+ isSelectedRow(rowId: number): boolean | null;
1716
+ isCutRow(rowId: number): boolean | null;
1717
+ subscribe(cb: () => void): (() => void) | null;
1718
+ subscribeSelected<TSelected>(selector: () => TSelected, listener: (selected: TSelected) => void, isEqual?: (a: TSelected, b: TSelected) => boolean): () => void;
1719
+ getSession(): GridSession | undefined;
1720
+ getTableKey(): string;
1721
+ subscribeColumn<T>(columnId: string, collections: CollectionScope, cb: (values: T[]) => void): (() => void) | null;
1722
+ validation: () => (callback: (result: ValidationCallbackResult) => void) => void;
1723
+ isValidCell(rowId: number, columnId: string): ValidCell | null;
1724
+ onRowClick(rowId: number, modifiers: {
1725
+ ctrlKey: boolean;
1726
+ shiftKey: boolean;
1727
+ }): void;
1728
+ onRowSelect(rowId: number): void;
1729
+ dispose(): void;
1730
+ dispatch(command: UITableCommand): Promise<void>;
1731
+ private dispatchInternal;
1732
+ }
1733
+
1734
+ type ExportColumnDef = {
1735
+ readonly fieldName: string;
1736
+ readonly fieldCaption?: string;
1737
+ readonly fieldType?: string;
1738
+ readonly order?: number;
1739
+ };
1740
+ type ExportCellSource = {
1741
+ readonly value: unknown;
1742
+ readonly display?: unknown;
1743
+ };
1744
+ type ExportRowSource = {
1745
+ readonly id: number;
1746
+ readonly rowState: string;
1747
+ readonly cells: Readonly<Record<string, ExportCellSource>>;
1748
+ };
1749
+ type ExportSource = {
1750
+ readonly columns: readonly ExportColumnDef[];
1751
+ readonly rows: readonly ExportRowSource[];
1752
+ };
1753
+ /**
1754
+ * Read-only query surface for plugins (never mutates aggregates).
1755
+ */
1756
+ interface GridQueryPort {
1757
+ getSnapShot(collectionScope?: CollectionScope): TableSnapShot | null;
1758
+ getExportSource(collectionScope?: CollectionScope): ExportSource | null;
1759
+ }
1760
+ type PluginEventBus = {
1761
+ subscribeAll(onEvent: (event: GridEvent) => void): Unsubscribe;
1762
+ publish(event: GridEvent): Promise<void>;
1763
+ };
1764
+ interface GridPluginContext {
1765
+ readonly tableId: string;
1766
+ readonly bus: PluginEventBus;
1767
+ readonly session: GridSession;
1768
+ readonly query: GridQueryPort;
1769
+ readonly eventStore: EventStore;
1770
+ /**
1771
+ * Out-of-band binary for IMPORT_REQUESTED (not stored on the event bus /
1772
+ * IndexedDB payload — only correlationId is published).
1773
+ */
1774
+ resolveImportData?: (correlationId: string) => Uint8Array | undefined;
1775
+ }
1776
+ interface GridPlugin {
1777
+ readonly name: string;
1778
+ register(ctx: GridPluginContext): void;
1779
+ dispose?(): void;
1780
+ }
1781
+
1782
+ type RequestExportOptions = {
1783
+ format: 'xlsx' | 'pdf';
1784
+ collectionScope?: ExportRequestedPayload['collectionScope'];
1785
+ correlationId?: string;
1786
+ fileName?: string;
1787
+ sheetName?: string;
1788
+ direction?: 'rtl' | 'ltr';
1789
+ };
1790
+ type RequestImportOptions = {
1791
+ format: 'xlsx';
1792
+ data: Blob | ArrayBuffer | Uint8Array;
1793
+ collectionScope?: ImportRequestedPayload['collectionScope'];
1794
+ correlationId?: string;
1795
+ sheetName?: string;
1796
+ };
1797
+ type PluginHostDeps = {
1798
+ tableId: string;
1799
+ actorId: string;
1800
+ eventStore: EventStore;
1801
+ session: GridSession;
1802
+ query: GridQueryPort;
1803
+ };
1804
+ /**
1805
+ * Registers plugins and publishes plugin/view-stream events (e.g. EXPORT_REQUESTED).
1806
+ */
1807
+ declare class PluginHost {
1808
+ private readonly deps;
1809
+ private readonly plugins;
1810
+ private readonly disposers;
1811
+ private readonly importPayloads;
1812
+ private version;
1813
+ constructor(deps: PluginHostDeps);
1814
+ private takeImportPayload;
1815
+ private createBus;
1816
+ register(plugins: readonly GridPlugin[]): void;
1817
+ list(): readonly GridPlugin[];
1818
+ requestExport(options: RequestExportOptions): Promise<void>;
1819
+ requestImport(options: RequestImportOptions): Promise<void>;
1820
+ dispose(): void;
1821
+ }
1822
+
1823
+ /**
1824
+ * Core column definition without React/DOM bindings.
1825
+ * Host adapters attach renderers via ColumnViewBinding.
1826
+ */
1827
+ interface ColumnDefinition {
1828
+ readonly fieldName: string;
1829
+ readonly fieldCaption: string;
1830
+ readonly fieldType: FieldType;
1831
+ readonly fieldCollection?: string;
1832
+ readonly order?: number;
1833
+ readonly editable?: boolean;
1834
+ readonly isUnique?: boolean;
1835
+ readonly hidden?: boolean;
1836
+ readonly disable?: boolean;
1837
+ readonly noCache?: boolean;
1838
+ readonly expandable?: boolean;
1839
+ readonly rules?: IRule[];
1840
+ readonly options?: ReadonlyArray<{
1841
+ label?: string;
1842
+ value?: string | number;
1843
+ title?: string;
1844
+ }>;
1845
+ readonly visibility: ColumnVisibilityRule;
1846
+ readonly dynamicSource?: {
1847
+ endpoint: string;
1848
+ dependsOn?: string[];
1849
+ dependOn?: IDependOn | IDependOn[];
1850
+ params?: Record<string, string>;
1851
+ };
1852
+ readonly computed?: {
1853
+ dependsOn: readonly string[];
1854
+ };
1855
+ readonly selectOptions?: ReadonlyArray<{
1856
+ label: string;
1857
+ value: string | number;
1858
+ }>;
1859
+ readonly minWidth?: number;
1860
+ readonly labelValue?: 'selectDisplay' | 'selectValue';
1861
+ }
1862
+ /**
1863
+ * Presentation binding kept outside Domain (Adapter / Host).
1864
+ * `render` is intentionally untyped here to avoid React import in core.
1865
+ */
1866
+ interface ColumnViewBinding {
1867
+ readonly fieldName: string;
1868
+ readonly className?: string;
1869
+ readonly minWidth?: number;
1870
+ readonly style?: unknown;
1871
+ readonly render?: (...args: unknown[]) => unknown;
1872
+ readonly displayFormat?: (value: unknown) => unknown;
1873
+ readonly onChange?: (...args: unknown[]) => void;
1874
+ readonly indexOptions?: (...args: unknown[]) => unknown[];
1875
+ readonly popUpWidth?: number;
1876
+ readonly dynamicSelectFilterOption?: (inputValue: string, option: unknown) => boolean;
1877
+ }
1878
+
1879
+ type CollectionRowMap = Record<string, object>;
1880
+ type RowInput = {
1881
+ id: number;
1882
+ values?: Record<string, unknown>;
1883
+ collection?: string;
1884
+ rowType?: string;
1885
+ };
1886
+ type RowAccessControl = {
1887
+ allowRoles?: string[];
1888
+ denyRoles?: string[];
1889
+ rule?: (ctx: {
1890
+ actor: Actor$1;
1891
+ table: Table;
1892
+ row?: Row;
1893
+ }) => boolean;
1894
+ };
1895
+ type CreateERPTableConfig = {
1896
+ store: string;
1897
+ tableKey: string;
1898
+ activeCollection?: string;
1899
+ tableType?: string;
1900
+ actor: Actor$1;
1901
+ rowAccess?: RowAccessControl;
1902
+ columns: ColumnSchema[];
1903
+ rows: RowInput[];
1904
+ repo?: TableRepository;
1905
+ audit?: AuditLogger;
1906
+ permissionPolicy?: PermissionPolicy;
1907
+ tableHeight?: number;
1908
+ recordPerPage?: number;
1909
+ remoteApi?: RemoteApi;
1910
+ /**
1911
+ * Override event store. Default: IndexedDbEventStore in the browser,
1912
+ * InMemoryEventStore in Node/tests.
1913
+ */
1914
+ eventStore?: EventStore;
1915
+ /** Optional plugins (Excel/PDF export+import, …) registered at composition root. */
1916
+ plugins?: readonly GridPlugin[];
1917
+ };
1918
+ type CreateERPTableResult = {
1919
+ engine: TableEngine;
1920
+ controller: UITableController;
1921
+ session: GridSession;
1922
+ table: Table;
1923
+ tableKey: string;
1924
+ columnMeta: Map<string, ColumnSchema>;
1925
+ columnDefinitions: ColumnDefinition[];
1926
+ columnBindings: ColumnViewBinding[];
1927
+ eventStore: EventStore;
1928
+ changelogProjection: ChangelogProjection;
1929
+ historyPanelViewModel: HistoryPanelViewModel;
1930
+ cellUndoStack: CellUndoStack;
1931
+ pluginHost: PluginHost;
1932
+ };
1933
+
1934
+ type ERPTableLocale = 'fa' | 'en';
1935
+ type ERPTableMessages = Record<string, string>;
1936
+
1937
+ type ERPTableToastKind = 'success' | 'error';
1938
+ type ERPTableHostValue = {
1939
+ locale: ERPTableLocale;
1940
+ direction: 'rtl' | 'ltr';
1941
+ remoteApi?: RemoteApi;
1942
+ messages?: Partial<ERPTableMessages>;
1943
+ onToast?: (kind: ERPTableToastKind, message: string, detail?: unknown) => void;
1944
+ };
1945
+ declare function ERPTableHostProvider({ children, locale, direction, remoteApi, messages, onToast, }: ERPTableHostValue & {
1946
+ children: ReactNode;
1947
+ }): React__default.JSX.Element;
1948
+
1949
+ interface ERPTableProps extends CreateERPTableConfig {
1950
+ onReady?: (controller: UITableController) => void;
1951
+ tableTitle?: ReactNode;
1952
+ header?: ReactNode;
1953
+ footer?: boolean | ReactNode;
1954
+ activeCollection?: string;
1955
+ tableHeight?: number;
1956
+ multiSelectConfig: IMultiSelectConfig;
1957
+ moreDetailComponent?: React__default.ComponentType<{
1958
+ data: unknown;
1959
+ }>;
1960
+ /**
1961
+ * Desktop virtual scroll. Default **false** to match ERP pagination.
1962
+ * Pass true to enable GridSession virtualization.
1963
+ */
1964
+ virtualization?: boolean;
1965
+ locale?: ERPTableLocale;
1966
+ direction?: 'rtl' | 'ltr';
1967
+ messages?: Partial<ERPTableMessages>;
1968
+ onToast?: (kind: ERPTableToastKind, message: string, detail?: unknown) => void;
1969
+ }
1970
+ declare function ERPTable(props: ERPTableProps): React__default.JSX.Element | null;
1971
+
1972
+ interface CellRendererProps {
1973
+ tableKey: string;
1974
+ row: UIRow;
1975
+ columnId: string;
1976
+ idx: number;
1977
+ meta?: ColumnSchema;
1978
+ controller: UITableController;
1979
+ tabIndex: number;
1980
+ mode?: "view" | "cell" | "form";
1981
+ }
1982
+ declare const CellRenderer: React__default.FC<CellRendererProps>;
1983
+
1984
+ type UseERPTableResult = {
1985
+ ready: false;
1986
+ } | {
1987
+ ready: true;
1988
+ controller: UITableController;
1989
+ session: GridSession;
1990
+ rows: TableSnapShot;
1991
+ changelog: ChangelogEntry[];
1992
+ changelogCount: number;
1993
+ historyItems: HistoryItem[];
1994
+ historyItemCount: number;
1995
+ canUndo: boolean;
1996
+ canRedo: boolean;
1997
+ getChangelog: (filter?: Omit<ChangelogQuery, 'tableId'>) => ChangelogEntry[];
1998
+ getHistoryItems: (filter?: Omit<HistoryQuery, 'tableId'>) => HistoryItem[];
1999
+ subscribeChangelog: (cb: (entries: ChangelogEntry[]) => void, filter?: Omit<ChangelogQuery, 'tableId'>) => () => void;
2000
+ subscribeHistoryItems: (cb: (items: HistoryItem[]) => void, filter?: Omit<HistoryQuery, 'tableId'>) => () => void;
2001
+ subscribeSelected: GridSession['subscribeSelected'];
2002
+ getViewport: GridSession['getViewport'];
2003
+ getVisibleRange: GridSession['getVisibleRange'];
2004
+ projectVisibleRows: GridSession['projectVisibleRows'];
2005
+ changeViewport: (input: {
2006
+ scrollOffset: number;
2007
+ viewportSize?: number;
2008
+ rowHeight?: number;
2009
+ overscan?: number;
2010
+ }) => Promise<void>;
2011
+ undo: () => Promise<boolean>;
2012
+ redo: () => Promise<boolean>;
2013
+ };
2014
+ declare function useERPTable(config: CreateERPTableConfig): UseERPTableResult;
2015
+
2016
+ declare function createERPTable(config: CreateERPTableConfig): Promise<CreateERPTableResult>;
2017
+
2018
+ /**
2019
+ * Maps host/legacy ColumnSchema into core ColumnDefinition + view bindings.
2020
+ * Domain/runtime should prefer ColumnDefinition; React renderers stay in bindings.
2021
+ */
2022
+ declare function toColumnDefinition(schema: ColumnSchema): ColumnDefinition;
2023
+ declare function toColumnViewBinding(schema: ColumnSchema): ColumnViewBinding;
2024
+ declare function mapColumnSchemas(schemas: ColumnSchema[]): {
2025
+ definitions: ColumnDefinition[];
2026
+ bindings: ColumnViewBinding[];
2027
+ };
2028
+
2029
+ type Listener$1 = (event: GridEvent) => void;
2030
+ declare class InMemoryEventStore implements EventStore {
2031
+ private streams;
2032
+ private globalLog;
2033
+ private listeners;
2034
+ private globalListeners;
2035
+ append(streamId: string, events: GridEvent[], expectedVersion: number): Promise<AppendResult>;
2036
+ read(streamId: string, fromVersion?: number): Promise<GridEvent[]>;
2037
+ readAll(fromPosition?: number): Promise<GridEvent[]>;
2038
+ subscribe(streamId: string, onEvent: Listener$1): Unsubscribe;
2039
+ subscribeAll(onEvent: Listener$1): Unsubscribe;
2040
+ getStreamVersion(streamId: string): number;
2041
+ getGlobalPosition(): number;
2042
+ }
2043
+
2044
+ /**
2045
+ * Minimal async key-value backend so IndexedDbEventStore can run in Node tests
2046
+ * without a real IndexedDB, and in browsers via an IDB adapter.
2047
+ */
2048
+ interface KvStore {
2049
+ get<T = unknown>(key: string): Promise<T | undefined>;
2050
+ put(key: string, value: unknown): Promise<void>;
2051
+ delete(key: string): Promise<void>;
2052
+ getAllKeys(): Promise<string[]>;
2053
+ getAll<T = unknown>(): Promise<T[]>;
2054
+ clear(): Promise<void>;
2055
+ }
2056
+ interface KvDatabase {
2057
+ objectStore(name: string): KvStore;
2058
+ }
2059
+ declare class MemoryKvDatabase implements KvDatabase {
2060
+ private stores;
2061
+ objectStore(name: string): KvStore;
2062
+ }
2063
+ /**
2064
+ * Browser IndexedDB adapter. Opens (or creates) a DB with the given object stores.
2065
+ * Falls back callers should use MemoryKvDatabase in Node/tests.
2066
+ */
2067
+ declare function openIndexedDbDatabase(dbName: string, storeNames: string[], version?: number): Promise<KvDatabase>;
2068
+
2069
+ type Listener = (event: GridEvent) => void;
2070
+ /**
2071
+ * Durable EventStore backed by IndexedDB (or any KvDatabase).
2072
+ * Same OCC contract as InMemoryEventStore.
2073
+ */
2074
+ declare class IndexedDbEventStore implements EventStore {
2075
+ private readonly db;
2076
+ private listeners;
2077
+ private globalListeners;
2078
+ private ready;
2079
+ constructor(db: KvDatabase);
2080
+ static open(dbName?: string): Promise<IndexedDbEventStore>;
2081
+ /** Test / Node helper — durable API with in-memory persistence backend. */
2082
+ static inMemory(): IndexedDbEventStore;
2083
+ append(streamId: string, events: GridEvent[], expectedVersion: number): Promise<AppendResult>;
2084
+ read(streamId: string, fromVersion?: number): Promise<GridEvent[]>;
2085
+ readAll(fromPosition?: number): Promise<GridEvent[]>;
2086
+ subscribe(streamId: string, onEvent: Listener): Unsubscribe;
2087
+ subscribeAll(onEvent: Listener): Unsubscribe;
2088
+ }
2089
+
2090
+ /**
2091
+ * Aggregate snapshot for fast reload: lastSnapshot + events after version.
2092
+ */
2093
+ interface AggregateSnapshot<TPayload = unknown> {
2094
+ readonly tableId: string;
2095
+ readonly streamId: string;
2096
+ readonly version: number;
2097
+ readonly takenAt: number;
2098
+ readonly payload: TPayload;
2099
+ }
2100
+ interface SnapshotStore<TPayload = unknown> {
2101
+ save(snapshot: AggregateSnapshot<TPayload>): Promise<void>;
2102
+ loadLatest(streamId: string): Promise<AggregateSnapshot<TPayload> | null>;
2103
+ clear(streamId: string): Promise<void>;
2104
+ }
2105
+
2106
+ type SnapshotStrategyOptions = {
2107
+ /** Take a snapshot every N appended domain events (default 200). */
2108
+ readonly everyNEvents?: number;
2109
+ };
2110
+ /**
2111
+ * After appends, periodically persists a snapshot of the selected payload.
2112
+ * load(stream) = latest snapshot + events with version > snapshot.version
2113
+ */
2114
+ declare class SnapshotStrategy<TPayload = unknown> {
2115
+ private readonly snapshots;
2116
+ private readonly eventStore;
2117
+ private readonly capture;
2118
+ private readonly everyN;
2119
+ private counts;
2120
+ constructor(snapshots: SnapshotStore<TPayload>, eventStore: EventStore, capture: (streamId: string) => Promise<TPayload> | TPayload, options?: SnapshotStrategyOptions);
2121
+ /** Call after a successful EventStore.append for the stream. */
2122
+ onAppend(streamId: string, tableId: string, appendedCount: number): Promise<void>;
2123
+ loadWithCatchUp(streamId: string): Promise<{
2124
+ snapshot: AggregateSnapshot<TPayload> | null;
2125
+ eventsAfter: GridEvent[];
2126
+ }>;
2127
+ }
2128
+
2129
+ declare class InMemorySnapshotStore<TPayload = unknown> implements SnapshotStore<TPayload> {
2130
+ private byStream;
2131
+ save(snapshot: AggregateSnapshot<TPayload>): Promise<void>;
2132
+ loadLatest(streamId: string): Promise<AggregateSnapshot<TPayload> | null>;
2133
+ clear(streamId: string): Promise<void>;
2134
+ }
2135
+
2136
+ /** Default RemoteApi for Node/tests/package builds — host injects a real adapter. */
2137
+ declare class NoopRemoteApi implements RemoteApi {
2138
+ request<TResponse = unknown>(): Promise<TResponse>;
2139
+ }
2140
+
2141
+ declare class EngineErrorHandler {
2142
+ private readonly audit;
2143
+ constructor(audit: ConsoleAuditLogger);
2144
+ /**
2145
+ * همه‌ی خطاها — چه DomainError چه runtime error — از اینجا رد می‌شن
2146
+ * و از طریق ConsoleAuditLogger لاگ می‌شن.
2147
+ */
2148
+ handle(error: unknown, context?: string): void;
2149
+ /** برای جاهایی که store یا table پیدا نشد */
2150
+ notFound(entity: string, key: string, context?: string): void;
2151
+ }
2152
+
2153
+ /**
2154
+ * Browser RemoteApi used by ERP after npm install.
2155
+ * Reads auth cookie `_auth` and redux-persist `persist:arianERP` the same way
2156
+ * the ERP FetchRemoteApi did, then POSTs JSON (relative URLs work on the ERP host).
2157
+ */
2158
+ declare class FetchRemoteApi implements RemoteApi {
2159
+ private readonly err?;
2160
+ private readonly options;
2161
+ constructor(err?: EngineErrorHandler | undefined, options?: {
2162
+ baseUrl?: string;
2163
+ });
2164
+ request<TResponse = any>(input: {
2165
+ endpoint: string;
2166
+ params?: Record<string, any>;
2167
+ method?: 'GET' | 'POST';
2168
+ }): Promise<TResponse>;
2169
+ }
2170
+
2171
+ /**
2172
+ * Plugin-facing event catalog (stable type tokens for subscribe / export plugins).
2173
+ * Keep in sync with `application/events` and `domain/types/GridEvent`.
2174
+ */
2175
+ type EventCatalogEntry = {
2176
+ readonly type: string;
2177
+ readonly category: 'cell' | 'row' | 'column' | 'table' | 'view' | 'dynamic' | 'error' | 'plugin';
2178
+ readonly undoable: boolean;
2179
+ readonly description: string;
2180
+ };
2181
+ declare const EVENT_CATALOG: readonly EventCatalogEntry[];
2182
+ declare function getEventCatalogEntry(type: string): EventCatalogEntry | undefined;
2183
+ declare function listUndoableEventTypes(): string[];
2184
+
2185
+ type BenchmarkSample = {
2186
+ readonly name: string;
2187
+ readonly iterations: number;
2188
+ readonly totalMs: number;
2189
+ readonly avgMs: number;
2190
+ readonly maxMs: number;
2191
+ };
2192
+ type PerformanceBudget = {
2193
+ readonly name: string;
2194
+ /** Maximum allowed average milliseconds per iteration. */
2195
+ readonly maxAvgMs: number;
2196
+ /** Maximum allowed single-iteration milliseconds. */
2197
+ readonly maxMaxMs?: number;
2198
+ };
2199
+ type BenchmarkResult = {
2200
+ readonly sample: BenchmarkSample;
2201
+ readonly budget: PerformanceBudget;
2202
+ readonly ok: boolean;
2203
+ readonly reasons: string[];
2204
+ };
2205
+ /**
2206
+ * Tiny synchronous/async micro-benchmark helper for core hot paths.
2207
+ * Not a substitute for browser profiling — guards CI regressions.
2208
+ */
2209
+ declare function runBenchmark(name: string, iterations: number, fn: () => void | Promise<void>): Promise<BenchmarkSample>;
2210
+ declare function checkBudget(sample: BenchmarkSample, budget: PerformanceBudget): BenchmarkResult;
2211
+ /** Default budgets for Phase 4 CI guards (generous for CI variance). */
2212
+ declare const DEFAULT_PERFORMANCE_BUDGETS: {
2213
+ readonly inMemoryAppend100: {
2214
+ readonly name: "inMemoryAppend100";
2215
+ readonly maxAvgMs: 25;
2216
+ readonly maxMaxMs: 80;
2217
+ };
2218
+ readonly indexedDbAppend100: {
2219
+ readonly name: "indexedDbAppend100";
2220
+ readonly maxAvgMs: 80;
2221
+ readonly maxMaxMs: 200;
2222
+ };
2223
+ readonly selectorNotifyNoop: {
2224
+ readonly name: "selectorNotifyNoop";
2225
+ readonly maxAvgMs: 5;
2226
+ readonly maxMaxMs: 20;
2227
+ };
2228
+ };
2229
+
2230
+ /**
2231
+ * Pure virtual-window calculator — no DOM / window / document.
2232
+ * Input: totalRows + Viewport → VisibleRange for Adapter rendering.
2233
+ */
2234
+ declare class ViewportCalculator {
2235
+ static calculate(totalRows: number, viewport: Viewport): VisibleRange;
2236
+ /** Contiguous index list for the visible window. */
2237
+ static indices(range: VisibleRange): number[];
2238
+ /** Slice a dense array by VisibleRange (O(window), not O(n)). */
2239
+ static projectRows<T>(rows: readonly T[], range: VisibleRange): T[];
2240
+ /**
2241
+ * Project from sparse structure: ordered id list + Map by id.
2242
+ * Suitable for 100k+ tables without materializing full UI rows.
2243
+ */
2244
+ static projectByIndex<T>(orderedIds: readonly number[], byId: ReadonlyMap<number, T>, range: VisibleRange): T[];
2245
+ }
2246
+
2247
+ /**
2248
+ * Sparse ordered index for large tables: O(1) id lookup + O(window) projection.
2249
+ * Keeps full row payloads in a Map; visible window never walks all rows.
2250
+ */
2251
+ declare class SparseRowIndex<T> {
2252
+ private readonly byId;
2253
+ private orderedIds;
2254
+ constructor(entries?: Iterable<readonly [number, T]>);
2255
+ get size(): number;
2256
+ getOrderedIds(): readonly number[];
2257
+ getById(id: number): T | undefined;
2258
+ set(id: number, value: T): void;
2259
+ /** Replace order without rebuilding payloads (e.g. after sort). */
2260
+ setOrder(orderedIds: readonly number[]): void;
2261
+ clear(): void;
2262
+ /** Project only the visible window — O(window), not O(n). */
2263
+ projectVisible(range: {
2264
+ startIndex: number;
2265
+ endIndex: number;
2266
+ }): T[];
2267
+ }
2268
+
2269
+ type VirtualListProps<T> = {
2270
+ session: GridSession;
2271
+ items: readonly T[];
2272
+ /** Scrollport height in pixels. */
2273
+ height: number;
2274
+ rowHeight?: number;
2275
+ overscan?: number;
2276
+ className?: string;
2277
+ style?: React__default.CSSProperties;
2278
+ getItemKey?: (item: T, absoluteIndex: number) => string | number;
2279
+ renderItem: (item: T, absoluteIndex: number) => React__default.ReactNode;
2280
+ };
2281
+ /**
2282
+ * Thin React adapter for Core ViewportCalculator.
2283
+ * Renders spacers + absolute-positioned visible rows only.
2284
+ */
2285
+ declare function VirtualList<T>({ session, items, height, rowHeight, overscan, className, style, getItemKey, renderItem, }: VirtualListProps<T>): React__default.JSX.Element;
2286
+
2287
+ type VirtualWindowModel<T> = {
2288
+ readonly range: VisibleRange;
2289
+ readonly visibleItems: readonly T[];
2290
+ /** Absolute row indices matching visibleItems. */
2291
+ readonly absoluteIndices: readonly number[];
2292
+ readonly spacerTop: number;
2293
+ readonly spacerBottom: number;
2294
+ readonly totalHeight: number;
2295
+ };
2296
+ /**
2297
+ * Pure adapter helper: map items + viewport → render window.
2298
+ * No React / DOM — unit-testable in Node.
2299
+ */
2300
+ declare function buildVirtualWindow<T>(items: readonly T[], viewport: Viewport): VirtualWindowModel<T>;
2301
+
2302
+ type UseVirtualWindowResult<T> = VirtualWindowModel<T> & {
2303
+ readonly onScroll: (scrollTop: number, clientHeight?: number) => void;
2304
+ };
2305
+ /**
2306
+ * Syncs GridSession viewport with a scrollable container and returns
2307
+ * only the visible item window for rendering.
2308
+ */
2309
+ declare function useVirtualWindow<T>(session: GridSession | null | undefined, items: readonly T[], options?: {
2310
+ rowHeight?: number;
2311
+ overscan?: number;
2312
+ initialViewportSize?: number;
2313
+ }): UseVirtualWindowResult<T>;
2314
+
2315
+ /**
2316
+ * Adapter: TableEngine → GridQueryPort for export plugins.
2317
+ */
2318
+ declare function createEngineGridQuery(engine: TableEngine): GridQueryPort;
2319
+
2320
+ /**
2321
+ * Port so PDF libraries (jsPDF, etc.) stay out of Core.
2322
+ * Host or plugin package injects a concrete renderer.
2323
+ */
2324
+ interface PdfRenderer {
2325
+ render(source: ExportSource, options?: {
2326
+ title?: string;
2327
+ direction?: 'rtl' | 'ltr';
2328
+ }): Promise<Blob>;
2329
+ }
2330
+
2331
+ type ExcelExportPluginOptions = {
2332
+ /** Skip browser download (useful in tests / Node). */
2333
+ download?: boolean;
2334
+ onBlob?: (blob: Blob, meta: {
2335
+ fileName: string;
2336
+ rowCount: number;
2337
+ columnCount: number;
2338
+ }) => void;
2339
+ };
2340
+ /**
2341
+ * Subscribes to EXPORT_REQUESTED (format=xlsx); never mutates Domain.
2342
+ */
2343
+ declare class ExcelExportPlugin implements GridPlugin {
2344
+ private readonly options;
2345
+ readonly name = "excel-export";
2346
+ private unsub;
2347
+ constructor(options?: ExcelExportPluginOptions);
2348
+ register(ctx: GridPluginContext): void;
2349
+ dispose(): void;
2350
+ private onEvent;
2351
+ }
2352
+
2353
+ type ExcelImportPluginOptions = {
2354
+ onImported?: (meta: {
2355
+ rowCount: number;
2356
+ columnCount: number;
2357
+ }) => void;
2358
+ };
2359
+ /**
2360
+ * Subscribes to IMPORT_REQUESTED (format=xlsx); mutates domain only via
2361
+ * session/engine commands (never touches Entity directly).
2362
+ */
2363
+ declare class ExcelImportPlugin implements GridPlugin {
2364
+ private readonly options;
2365
+ readonly name = "excel-import";
2366
+ private unsub;
2367
+ constructor(options?: ExcelImportPluginOptions);
2368
+ register(ctx: GridPluginContext): void;
2369
+ dispose(): void;
2370
+ private onEvent;
2371
+ }
2372
+
2373
+ type ExportActiveCollectionResult = {
2374
+ rowCount: number;
2375
+ columnCount: number;
2376
+ };
2377
+ type ExportActiveCollectionOptions = {
2378
+ fileName?: string;
2379
+ sheetName?: string;
2380
+ direction?: 'rtl' | 'ltr';
2381
+ rowHeaderLabel?: string;
2382
+ /** When false, skip browser download (tests). */
2383
+ download?: boolean;
2384
+ };
2385
+ /**
2386
+ * Imperative facade used by ERP toolbar buttons.
2387
+ * Prefer PluginHost.requestExport + ExcelExportPlugin for event-driven hosts.
2388
+ */
2389
+ declare function exportActiveCollectionToExcel(controller: UITableController, options?: ExportActiveCollectionOptions): Promise<ExportActiveCollectionResult>;
2390
+
2391
+ type ExportTable = {
2392
+ columns: Array<{
2393
+ fieldName: string;
2394
+ caption: string;
2395
+ }>;
2396
+ /** Parallel to columns; already stringified cell text */
2397
+ rows: string[][];
2398
+ };
2399
+ /**
2400
+ * Builds a dense string matrix from ExportSource (plugin query port).
2401
+ */
2402
+ declare function buildExportTable(source: ExportSource): ExportTable;
2403
+
2404
+ type BuildXlsxOptions = {
2405
+ sheetName?: string;
2406
+ direction?: 'rtl' | 'ltr';
2407
+ rowHeaderLabel?: string;
2408
+ };
2409
+ declare function buildXlsxBlob(table: ExportTable, options?: BuildXlsxOptions): Blob;
2410
+
2411
+ type ParsedXlsxSheet = {
2412
+ /** First row cells (header captions / field names). */
2413
+ headers: string[];
2414
+ /** Body rows; each row length matches headers (padded with ''). */
2415
+ rows: string[][];
2416
+ };
2417
+ /**
2418
+ * Parses a minimal OOXML .xlsx (store or deflate) into a string matrix.
2419
+ * Supports shared strings and inlineStr (as produced by buildXlsxBlob).
2420
+ */
2421
+ declare function parseXlsxBlob(data: Blob | ArrayBuffer | Uint8Array, options?: {
2422
+ sheetName?: string;
2423
+ }): Promise<ParsedXlsxSheet>;
2424
+
2425
+ type ImportCellKv = {
2426
+ key: string;
2427
+ value: unknown;
2428
+ display: unknown;
2429
+ };
2430
+ type MappedImportRows = {
2431
+ columns: Array<{
2432
+ fieldName: string;
2433
+ fieldType?: string;
2434
+ }>;
2435
+ /** One KeyValue[] per data row (no index column). */
2436
+ rows: ImportCellKv[][];
2437
+ };
2438
+ /**
2439
+ * Maps sheet headers to export/query columns by caption or fieldName.
2440
+ * Skips index/static columns.
2441
+ */
2442
+ declare function mapImportedSheet(sheet: ParsedXlsxSheet, columns: readonly ExportColumnDef[]): MappedImportRows;
2443
+
2444
+ type ApplyImportedRowsResult = {
2445
+ rowCount: number;
2446
+ };
2447
+ /**
2448
+ * Applies imported cell matrices through the engine (ADD_NEW_ROWS) so
2449
+ * CachedTableRepository / IndexedDB persistence stays on the normal path.
2450
+ *
2451
+ * Uses a synthetic unique `index` token only for dedupe in Table.addNewRows;
2452
+ * addNewRow still auto-assigns the real index cell.
2453
+ */
2454
+ declare function applyImportedRows(session: GridSession, rows: ImportCellKv[][]): Promise<ApplyImportedRowsResult>;
2455
+
2456
+ type PdfExportPluginOptions = {
2457
+ renderer?: PdfRenderer;
2458
+ download?: boolean;
2459
+ onBlob?: (blob: Blob, meta: {
2460
+ fileName: string;
2461
+ rowCount: number;
2462
+ }) => void;
2463
+ };
2464
+ /**
2465
+ * Subscribes to EXPORT_REQUESTED (format=pdf); Domain stays untouched.
2466
+ */
2467
+ declare class PdfExportPlugin implements GridPlugin {
2468
+ private readonly options;
2469
+ readonly name = "pdf-export";
2470
+ private unsub;
2471
+ private readonly renderer;
2472
+ constructor(options?: PdfExportPluginOptions);
2473
+ register(ctx: GridPluginContext): void;
2474
+ dispose(): void;
2475
+ private onEvent;
2476
+ }
2477
+
2478
+ /**
2479
+ * Minimal text PDF (no external lib) — Host can swap for jsPDF via PdfRenderer.
2480
+ */
2481
+ declare class TextPdfRenderer implements PdfRenderer {
2482
+ render(source: ExportSource, options?: {
2483
+ title?: string;
2484
+ }): Promise<Blob>;
2485
+ }
2486
+
2487
+ export { type AggregateSnapshot, type AppendResult, type BenchmarkResult, type BenchmarkSample, CellRenderer, type CollectionRowMap, type ColumnDefinition, type ColumnSchema, type ColumnViewBinding, type CreateERPTableConfig, type CreateERPTableResult, DEFAULT_PERFORMANCE_BUDGETS, ERPTable, ERPTableHostProvider, type ERPTableHostValue, type ERPTableLocale, type ERPTableMessages, type ERPTableProps, EVENT_CATALOG, type EventCatalogEntry, type EventStore, ExcelExportPlugin, ExcelImportPlugin, type ExportSource, FetchRemoteApi, type FieldType, type GridPlugin, type GridPluginContext, type GridQueryPort, type GridSession, type IMultiSelectConfig, InMemoryEventStore, InMemorySnapshotStore, IndexedDbEventStore, type ItemType, type KvDatabase, type KvStore, MemoryKvDatabase, NoopRemoteApi, PdfExportPlugin, type PdfRenderer, type PerformanceBudget, PluginHost, type RemoteApi, type RequestExportOptions, type RequestImportOptions, type RowInput, RowStateEnum, type SnapshotStore, SnapshotStrategy, SparseRowIndex, TableEngine, type TableSnapShot, type TableViewState, TextPdfRenderer, type UIRow, UITableController, type UseERPTableResult, type UseVirtualWindowResult, type ValidCell, type ViewIntent, Viewport, ViewportCalculator, VirtualList, type VirtualListProps, type VirtualWindowModel, type VisibleRange, applyImportedRows, buildExportTable, buildVirtualWindow, buildXlsxBlob, checkBudget, createERPTable, createEngineGridQuery, exportActiveCollectionToExcel, getEventCatalogEntry, listUndoableEventTypes, mapColumnSchemas, mapImportedSheet, openIndexedDbDatabase, parseXlsxBlob, runBenchmark, toColumnDefinition, toColumnViewBinding, useERPTable, useVirtualWindow };