persian-data-grid 0.5.0 → 0.6.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.
- package/OFL.txt +93 -0
- package/README.md +179 -22
- package/dist/ERPTableGroupRow-J5Z2LRC5.cjs +131 -0
- package/dist/ERPTableGroupRow-J5Z2LRC5.cjs.map +1 -0
- package/dist/ERPTableGroupRow-PSAPAHGL.js +125 -0
- package/dist/ERPTableGroupRow-PSAPAHGL.js.map +1 -0
- package/dist/GridPlugin-CJCaYnlw.d.ts +57 -0
- package/dist/GridPlugin-oxhq8AsM.d.cts +57 -0
- package/dist/GridPresenceService-GEH6535Q.js +3 -0
- package/dist/GridPresenceService-GEH6535Q.js.map +1 -0
- package/dist/GridPresenceService-RDN5FXHQ.cjs +12 -0
- package/dist/GridPresenceService-RDN5FXHQ.cjs.map +1 -0
- package/dist/GridSession-B-9lLcoB.d.cts +2492 -0
- package/dist/GridSession-Bc7UIawO.d.ts +2492 -0
- package/dist/GridSyncService-KTLB4KP3.js +3 -0
- package/dist/GridSyncService-KTLB4KP3.js.map +1 -0
- package/dist/GridSyncService-TAPAHABV.cjs +12 -0
- package/dist/GridSyncService-TAPAHABV.cjs.map +1 -0
- package/dist/PdfRenderer-1HFh6UeR.d.ts +22 -0
- package/dist/PdfRenderer-CBg7hWNS.d.cts +22 -0
- package/dist/RemoteApi-CCQxiSf1.d.cts +28 -0
- package/dist/RemoteApi-CCQxiSf1.d.ts +28 -0
- package/dist/SelectImpl-NM4O4IGW.js +447 -0
- package/dist/SelectImpl-NM4O4IGW.js.map +1 -0
- package/dist/SelectImpl-W2EI4T7O.cjs +453 -0
- package/dist/SelectImpl-W2EI4T7O.cjs.map +1 -0
- package/dist/UITableController-Cuwq481K.d.cts +632 -0
- package/dist/UITableController-DU8RopUM.d.ts +632 -0
- package/dist/VazirmatnPdfRenderer-BCMpC1zy.d.cts +96 -0
- package/dist/VazirmatnPdfRenderer-Dz_G-m3c.d.ts +96 -0
- package/dist/adapters/arian-erp.cjs +77 -0
- package/dist/adapters/arian-erp.cjs.map +1 -0
- package/dist/adapters/arian-erp.d.cts +60 -0
- package/dist/adapters/arian-erp.d.ts +60 -0
- package/dist/adapters/arian-erp.js +71 -0
- package/dist/adapters/arian-erp.js.map +1 -0
- package/dist/appendAtEnd-RHIQRG2W.cjs +35 -0
- package/dist/appendAtEnd-RHIQRG2W.cjs.map +1 -0
- package/dist/appendAtEnd-TJEABLGD.js +33 -0
- package/dist/appendAtEnd-TJEABLGD.js.map +1 -0
- package/dist/applyImportedRows-BO6yxoAN.d.cts +135 -0
- package/dist/applyImportedRows-D4zVY8uD.d.ts +135 -0
- package/dist/applyRowVisibilityHandler-KS6TMCBN.js +83 -0
- package/dist/applyRowVisibilityHandler-KS6TMCBN.js.map +1 -0
- package/dist/applyRowVisibilityHandler-LXCOGESZ.cjs +85 -0
- package/dist/applyRowVisibilityHandler-LXCOGESZ.cjs.map +1 -0
- package/dist/broadcastChannelTransport-FHUMV76O.cjs +12 -0
- package/dist/broadcastChannelTransport-FHUMV76O.cjs.map +1 -0
- package/dist/broadcastChannelTransport-MIH53VNZ.js +3 -0
- package/dist/broadcastChannelTransport-MIH53VNZ.js.map +1 -0
- package/dist/callbackRemoteApi-BlXO5NJz.d.ts +30 -0
- package/dist/callbackRemoteApi-DgnXH-i0.d.cts +30 -0
- package/dist/cellRenderContext-DB7V_mlu.d.ts +42 -0
- package/dist/cellRenderContext-DG5BOlxK.d.cts +42 -0
- package/dist/chunk-2BJCRYOS.cjs +936 -0
- package/dist/chunk-2BJCRYOS.cjs.map +1 -0
- package/dist/chunk-3Y3KKGEC.js +3 -0
- package/dist/chunk-3Y3KKGEC.js.map +1 -0
- package/dist/chunk-5ALMNLUR.cjs +1408 -0
- package/dist/chunk-5ALMNLUR.cjs.map +1 -0
- package/dist/chunk-5HKVMPBD.js +937 -0
- package/dist/chunk-5HKVMPBD.js.map +1 -0
- package/dist/chunk-633KP74Z.js +189 -0
- package/dist/chunk-633KP74Z.js.map +1 -0
- package/dist/chunk-6XBXZPBW.js +298 -0
- package/dist/chunk-6XBXZPBW.js.map +1 -0
- package/dist/chunk-77UXAJII.js +112 -0
- package/dist/chunk-77UXAJII.js.map +1 -0
- package/dist/chunk-ASPTRYRD.cjs +21 -0
- package/dist/chunk-ASPTRYRD.cjs.map +1 -0
- package/dist/chunk-AU3RDJYQ.js +243 -0
- package/dist/chunk-AU3RDJYQ.js.map +1 -0
- package/dist/chunk-BHDRUZH5.cjs +33 -0
- package/dist/chunk-BHDRUZH5.cjs.map +1 -0
- package/dist/chunk-BLYVOV3G.cjs +191 -0
- package/dist/chunk-BLYVOV3G.cjs.map +1 -0
- package/dist/chunk-CILNIWYW.cjs +100 -0
- package/dist/chunk-CILNIWYW.cjs.map +1 -0
- package/dist/chunk-DFFP7SJ6.cjs +257 -0
- package/dist/chunk-DFFP7SJ6.cjs.map +1 -0
- package/dist/chunk-DXRCYW42.cjs +568 -0
- package/dist/chunk-DXRCYW42.cjs.map +1 -0
- package/dist/chunk-EBV6HGZB.cjs +33 -0
- package/dist/chunk-EBV6HGZB.cjs.map +1 -0
- package/dist/chunk-EHHHC5JV.js +832 -0
- package/dist/chunk-EHHHC5JV.js.map +1 -0
- package/dist/chunk-F4PYOYHR.js +112 -0
- package/dist/chunk-F4PYOYHR.js.map +1 -0
- package/dist/chunk-GQEDLUMB.js +168 -0
- package/dist/chunk-GQEDLUMB.js.map +1 -0
- package/dist/chunk-H2LESGMX.cjs +319 -0
- package/dist/chunk-H2LESGMX.cjs.map +1 -0
- package/dist/chunk-HTNJT2QU.js +11674 -0
- package/dist/chunk-HTNJT2QU.js.map +1 -0
- package/dist/chunk-IIISFUW4.cjs +11786 -0
- package/dist/chunk-IIISFUW4.cjs.map +1 -0
- package/dist/chunk-IMPCRWYP.cjs +251 -0
- package/dist/chunk-IMPCRWYP.cjs.map +1 -0
- package/dist/chunk-IPPIXOVQ.js +317 -0
- package/dist/chunk-IPPIXOVQ.js.map +1 -0
- package/dist/chunk-J4XJ4UBC.js +1404 -0
- package/dist/chunk-J4XJ4UBC.js.map +1 -0
- package/dist/chunk-J7CPPFXT.cjs +89 -0
- package/dist/chunk-J7CPPFXT.cjs.map +1 -0
- package/dist/chunk-JOICD47Q.cjs +41 -0
- package/dist/chunk-JOICD47Q.cjs.map +1 -0
- package/dist/chunk-KHMG6EI2.js +13 -0
- package/dist/chunk-KHMG6EI2.js.map +1 -0
- package/dist/chunk-KMRURD5J.cjs +15 -0
- package/dist/chunk-KMRURD5J.cjs.map +1 -0
- package/dist/chunk-KRJG3KMP.cjs +174 -0
- package/dist/chunk-KRJG3KMP.cjs.map +1 -0
- package/dist/chunk-KUBVDIF7.cjs +653 -0
- package/dist/chunk-KUBVDIF7.cjs.map +1 -0
- package/dist/chunk-KYAOSBQN.js +31 -0
- package/dist/chunk-KYAOSBQN.js.map +1 -0
- package/dist/chunk-LJ7LMEXO.js +36 -0
- package/dist/chunk-LJ7LMEXO.js.map +1 -0
- package/dist/chunk-MT3KLB2Q.cjs +944 -0
- package/dist/chunk-MT3KLB2Q.cjs.map +1 -0
- package/dist/chunk-MU3RY46O.js +932 -0
- package/dist/chunk-MU3RY46O.js.map +1 -0
- package/dist/chunk-MUQQKPWR.js +84 -0
- package/dist/chunk-MUQQKPWR.js.map +1 -0
- package/dist/chunk-N7SJTINL.cjs +4 -0
- package/dist/chunk-N7SJTINL.cjs.map +1 -0
- package/dist/chunk-NTV2UUAJ.cjs +149 -0
- package/dist/chunk-NTV2UUAJ.cjs.map +1 -0
- package/dist/chunk-PJQWHF6T.js +31 -0
- package/dist/chunk-PJQWHF6T.js.map +1 -0
- package/dist/chunk-PQY54EL5.js +248 -0
- package/dist/chunk-PQY54EL5.js.map +1 -0
- package/dist/chunk-PXCHPZTP.cjs +839 -0
- package/dist/chunk-PXCHPZTP.cjs.map +1 -0
- package/dist/chunk-Q7TBBUTX.cjs +110 -0
- package/dist/chunk-Q7TBBUTX.cjs.map +1 -0
- package/dist/chunk-QQMU44KJ.js +612 -0
- package/dist/chunk-QQMU44KJ.js.map +1 -0
- package/dist/chunk-QZN7R2WP.cjs +114 -0
- package/dist/chunk-QZN7R2WP.cjs.map +1 -0
- package/dist/chunk-RKVSJU46.js +35 -0
- package/dist/chunk-RKVSJU46.js.map +1 -0
- package/dist/chunk-RM6ZWNT3.js +561 -0
- package/dist/chunk-RM6ZWNT3.js.map +1 -0
- package/dist/chunk-SX4VQXAA.cjs +114 -0
- package/dist/chunk-SX4VQXAA.cjs.map +1 -0
- package/dist/chunk-SZ7BLAY3.js +92 -0
- package/dist/chunk-SZ7BLAY3.js.map +1 -0
- package/dist/chunk-TN4MG6FY.js +112 -0
- package/dist/chunk-TN4MG6FY.js.map +1 -0
- package/dist/chunk-UC7PHDM6.cjs +331 -0
- package/dist/chunk-UC7PHDM6.cjs.map +1 -0
- package/dist/chunk-UXVLYUUW.js +108 -0
- package/dist/chunk-UXVLYUUW.js.map +1 -0
- package/dist/chunk-VVGYRZ7S.cjs +38 -0
- package/dist/chunk-VVGYRZ7S.cjs.map +1 -0
- package/dist/chunk-W5256BJ4.js +56 -0
- package/dist/chunk-W5256BJ4.js.map +1 -0
- package/dist/chunk-WUMOSOEK.cjs +62 -0
- package/dist/chunk-WUMOSOEK.cjs.map +1 -0
- package/dist/chunk-XLRE2J25.js +140 -0
- package/dist/chunk-XLRE2J25.js.map +1 -0
- package/dist/chunk-Y6W5V2CI.js +19 -0
- package/dist/chunk-Y6W5V2CI.js.map +1 -0
- package/dist/chunk-Z4QPZ3Z3.cjs +114 -0
- package/dist/chunk-Z4QPZ3Z3.cjs.map +1 -0
- package/dist/createEngineGridQuery-Dmq3i5v3.d.cts +884 -0
- package/dist/createEngineGridQuery-Mt1hc33m.d.ts +884 -0
- package/dist/date-picker-jalali.cjs +263 -0
- package/dist/date-picker-jalali.cjs.map +1 -0
- package/dist/date-picker-jalali.d.cts +62 -0
- package/dist/date-picker-jalali.d.ts +62 -0
- package/dist/date-picker-jalali.js +256 -0
- package/dist/date-picker-jalali.js.map +1 -0
- package/dist/finance.cjs +205 -0
- package/dist/finance.cjs.map +1 -0
- package/dist/finance.d.cts +90 -0
- package/dist/finance.d.ts +90 -0
- package/dist/finance.js +157 -0
- package/dist/finance.js.map +1 -0
- package/dist/foldedColumn-IHDT4ARZ.cjs +66 -0
- package/dist/foldedColumn-IHDT4ARZ.cjs.map +1 -0
- package/dist/foldedColumn-TFURUKFG.js +64 -0
- package/dist/foldedColumn-TFURUKFG.js.map +1 -0
- package/dist/headless.cjs +729 -0
- package/dist/headless.cjs.map +1 -0
- package/dist/headless.d.cts +504 -0
- package/dist/headless.d.ts +504 -0
- package/dist/headless.js +226 -0
- package/dist/headless.js.map +1 -0
- package/dist/index-DN8M8Jkq.d.cts +14 -0
- package/dist/index-DmzL-F_o.d.ts +14 -0
- package/dist/index.cjs +8002 -11409
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +437 -2305
- package/dist/index.d.ts +437 -2305
- package/dist/index.js +7244 -11083
- package/dist/index.js.map +1 -1
- package/dist/locales/ar.cjs +12 -0
- package/dist/locales/ar.cjs.map +1 -0
- package/dist/locales/ar.d.cts +6 -0
- package/dist/locales/ar.d.ts +6 -0
- package/dist/locales/ar.js +3 -0
- package/dist/locales/ar.js.map +1 -0
- package/dist/locales/en.cjs +12 -0
- package/dist/locales/en.cjs.map +1 -0
- package/dist/locales/en.d.cts +6 -0
- package/dist/locales/en.d.ts +6 -0
- package/dist/locales/en.js +3 -0
- package/dist/locales/en.js.map +1 -0
- package/dist/locales/fa.cjs +12 -0
- package/dist/locales/fa.cjs.map +1 -0
- package/dist/locales/fa.d.cts +6 -0
- package/dist/locales/fa.d.ts +6 -0
- package/dist/locales/fa.js +3 -0
- package/dist/locales/fa.js.map +1 -0
- package/dist/locales/index.cjs +51 -0
- package/dist/locales/index.cjs.map +1 -0
- package/dist/locales/index.d.cts +5 -0
- package/dist/locales/index.d.ts +5 -0
- package/dist/locales/index.js +6 -0
- package/dist/locales/index.js.map +1 -0
- package/dist/memoryRecords-AWDKUJ2F.cjs +50 -0
- package/dist/memoryRecords-AWDKUJ2F.cjs.map +1 -0
- package/dist/memoryRecords-OJTGXLRH.js +47 -0
- package/dist/memoryRecords-OJTGXLRH.js.map +1 -0
- package/dist/pagedFooterTotals-DXCGDO6F.cjs +27 -0
- package/dist/pagedFooterTotals-DXCGDO6F.cjs.map +1 -0
- package/dist/pagedFooterTotals-ORWKUNE7.js +25 -0
- package/dist/pagedFooterTotals-ORWKUNE7.js.map +1 -0
- package/dist/pagedKit-MFGAJFSK.cjs +134 -0
- package/dist/pagedKit-MFGAJFSK.cjs.map +1 -0
- package/dist/pagedKit-WYWY4LRV.js +127 -0
- package/dist/pagedKit-WYWY4LRV.js.map +1 -0
- package/dist/pagedSearch-HCPJW7VM.js +38 -0
- package/dist/pagedSearch-HCPJW7VM.js.map +1 -0
- package/dist/pagedSearch-U3WCG4GN.cjs +42 -0
- package/dist/pagedSearch-U3WCG4GN.cjs.map +1 -0
- package/dist/plugins/csv.cjs +124 -0
- package/dist/plugins/csv.cjs.map +1 -0
- package/dist/plugins/csv.d.cts +44 -0
- package/dist/plugins/csv.d.ts +44 -0
- package/dist/plugins/csv.js +120 -0
- package/dist/plugins/csv.js.map +1 -0
- package/dist/plugins/excel.cjs +52 -0
- package/dist/plugins/excel.cjs.map +1 -0
- package/dist/plugins/excel.d.cts +14 -0
- package/dist/plugins/excel.d.ts +14 -0
- package/dist/plugins/excel.js +7 -0
- package/dist/plugins/excel.js.map +1 -0
- package/dist/plugins/pdf/fonts/vazirmatn.cjs +50 -0
- package/dist/plugins/pdf/fonts/vazirmatn.cjs.map +1 -0
- package/dist/plugins/pdf/fonts/vazirmatn.d.cts +24 -0
- package/dist/plugins/pdf/fonts/vazirmatn.d.ts +24 -0
- package/dist/plugins/pdf/fonts/vazirmatn.js +39 -0
- package/dist/plugins/pdf/fonts/vazirmatn.js.map +1 -0
- package/dist/plugins/pdf.cjs +24 -0
- package/dist/plugins/pdf.cjs.map +1 -0
- package/dist/plugins/pdf.d.cts +21 -0
- package/dist/plugins/pdf.d.ts +21 -0
- package/dist/plugins/pdf.js +7 -0
- package/dist/plugins/pdf.js.map +1 -0
- package/dist/presence.cjs +56 -0
- package/dist/presence.cjs.map +1 -0
- package/dist/presence.d.cts +17 -0
- package/dist/presence.d.ts +17 -0
- package/dist/presence.js +54 -0
- package/dist/presence.js.map +1 -0
- package/dist/rebuildRowVisibility-66EAZ356.cjs +21 -0
- package/dist/rebuildRowVisibility-66EAZ356.cjs.map +1 -0
- package/dist/rebuildRowVisibility-6TYM5BP2.js +19 -0
- package/dist/rebuildRowVisibility-6TYM5BP2.js.map +1 -0
- package/dist/styles.css +1440 -0
- package/dist/sync.cjs +148 -0
- package/dist/sync.cjs.map +1 -0
- package/dist/sync.d.cts +17 -0
- package/dist/sync.d.ts +17 -0
- package/dist/sync.js +146 -0
- package/dist/sync.js.map +1 -0
- package/dist/types-D__47BKv.d.cts +23 -0
- package/dist/types-D__47BKv.d.ts +23 -0
- package/package.json +184 -28
|
@@ -0,0 +1,2492 @@
|
|
|
1
|
+
import { R as RemoteApi, A as AuditLogger, C as ConsoleAuditLogger } from './RemoteApi-CCQxiSf1.cjs';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Pure cell-range selection model (PR-104).
|
|
6
|
+
* No React/DOM — keyboard/UI wiring lands in PR-105+.
|
|
7
|
+
*/
|
|
8
|
+
type CellAddress = {
|
|
9
|
+
/** 0-based index in the visible/sorted row list. */
|
|
10
|
+
rowIndex: number;
|
|
11
|
+
colId: string;
|
|
12
|
+
};
|
|
13
|
+
/** Inclusive rectangular range in UI row/column space. */
|
|
14
|
+
type CellRange = {
|
|
15
|
+
startRow: number;
|
|
16
|
+
endRow: number;
|
|
17
|
+
/** Column ids in document order (inclusive span). */
|
|
18
|
+
colIds: readonly string[];
|
|
19
|
+
};
|
|
20
|
+
type CellRangeSelection = {
|
|
21
|
+
ranges: readonly CellRange[];
|
|
22
|
+
anchor: CellAddress | null;
|
|
23
|
+
focus: CellAddress | null;
|
|
24
|
+
};
|
|
25
|
+
type CellRangeBounds = {
|
|
26
|
+
rowCount: number;
|
|
27
|
+
/** Visible/selectable columns in document order. */
|
|
28
|
+
columnOrder: readonly string[];
|
|
29
|
+
};
|
|
30
|
+
type ArrowDirection = 'up' | 'down' | 'left' | 'right';
|
|
31
|
+
declare function createEmptyCellRangeSelection(): CellRangeSelection;
|
|
32
|
+
declare function colIndex(colId: string, columnOrder: readonly string[]): number;
|
|
33
|
+
declare function clampRowIndex(rowIndex: number, rowCount: number): number;
|
|
34
|
+
declare function clampColIndex(colIndex: number, colCount: number): number;
|
|
35
|
+
/**
|
|
36
|
+
* Clamp rows/columns to bounds and sort `colIds` by `columnOrder`.
|
|
37
|
+
*/
|
|
38
|
+
declare function normalizeCellRange(range: CellRange, bounds: CellRangeBounds): CellRange;
|
|
39
|
+
declare function rangeFromAnchorFocus(anchor: CellAddress, focus: CellAddress, bounds: CellRangeBounds): CellRange;
|
|
40
|
+
declare function isCellInRange(cell: CellAddress, range: CellRange): boolean;
|
|
41
|
+
declare function rangesOverlap(a: CellRange, b: CellRange): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Merge overlapping/adjacent rectangles into a minimal set.
|
|
44
|
+
*/
|
|
45
|
+
declare function mergeCellRanges(ranges: readonly CellRange[], columnOrder: readonly string[]): CellRange[];
|
|
46
|
+
declare function moveCellAddress(cell: CellAddress, direction: ArrowDirection, bounds: CellRangeBounds): CellAddress;
|
|
47
|
+
/** Plain click — single 1×1 range. */
|
|
48
|
+
declare function clickCell(selection: CellRangeSelection, cell: CellAddress, bounds: CellRangeBounds): CellRangeSelection;
|
|
49
|
+
/** Shift+Click — extend from anchor to clicked cell (replace primary range). */
|
|
50
|
+
declare function shiftClickCell(selection: CellRangeSelection, cell: CellAddress, bounds: CellRangeBounds): CellRangeSelection;
|
|
51
|
+
/** Ctrl+Click — add a new 1×1 range; anchor/focus move to the new cell. */
|
|
52
|
+
declare function ctrlClickCell(selection: CellRangeSelection, cell: CellAddress, bounds: CellRangeBounds): CellRangeSelection;
|
|
53
|
+
/** Shift+Arrow — extend primary range from anchor to moved focus. */
|
|
54
|
+
declare function shiftArrowCell(selection: CellRangeSelection, direction: ArrowDirection, bounds: CellRangeBounds): CellRangeSelection;
|
|
55
|
+
/** Ctrl+A — one range over the full grid body. */
|
|
56
|
+
declare function selectAllCellRanges(bounds: CellRangeBounds): CellRangeSelection;
|
|
57
|
+
|
|
58
|
+
type Actor$1 = {
|
|
59
|
+
userId: string;
|
|
60
|
+
roles: string[];
|
|
61
|
+
};
|
|
62
|
+
interface PermissionPolicy {
|
|
63
|
+
canChangeCell(input: {
|
|
64
|
+
actor: Actor$1;
|
|
65
|
+
rowId: number;
|
|
66
|
+
columnId: string;
|
|
67
|
+
}): boolean;
|
|
68
|
+
canEdit?: (input: {
|
|
69
|
+
actor: Actor$1;
|
|
70
|
+
rowId: number;
|
|
71
|
+
columnId: string;
|
|
72
|
+
}) => boolean;
|
|
73
|
+
canAddRow?: (input: {
|
|
74
|
+
actor: Actor$1;
|
|
75
|
+
}) => boolean;
|
|
76
|
+
canCopyRow?: (input: {
|
|
77
|
+
actor: Actor$1;
|
|
78
|
+
rowId: number;
|
|
79
|
+
}) => boolean;
|
|
80
|
+
canDeleteRow?: (input: {
|
|
81
|
+
actor: Actor$1;
|
|
82
|
+
rowId: number;
|
|
83
|
+
}) => boolean;
|
|
84
|
+
canReorderRow?: (input: {
|
|
85
|
+
actor: Actor$1;
|
|
86
|
+
rowId: number;
|
|
87
|
+
}) => boolean;
|
|
88
|
+
canReorderColumn?: (input: {
|
|
89
|
+
actor: Actor$1;
|
|
90
|
+
}) => boolean;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* View-state value object for virtual scrolling.
|
|
95
|
+
* Lives in Domain types but is NOT an accounting invariant — Adapters drive it.
|
|
96
|
+
*/
|
|
97
|
+
declare class Viewport {
|
|
98
|
+
/** Vertical scroll offset in pixels. */
|
|
99
|
+
readonly scrollOffset: number;
|
|
100
|
+
/** Visible viewport height in pixels. */
|
|
101
|
+
readonly viewportSize: number;
|
|
102
|
+
/** Fixed row height in pixels (variable-height later). */
|
|
103
|
+
readonly rowHeight: number;
|
|
104
|
+
/** Extra rows rendered above/below the window. */
|
|
105
|
+
readonly overscan: number;
|
|
106
|
+
constructor(
|
|
107
|
+
/** Vertical scroll offset in pixels. */
|
|
108
|
+
scrollOffset: number,
|
|
109
|
+
/** Visible viewport height in pixels. */
|
|
110
|
+
viewportSize: number,
|
|
111
|
+
/** Fixed row height in pixels (variable-height later). */
|
|
112
|
+
rowHeight: number,
|
|
113
|
+
/** Extra rows rendered above/below the window. */
|
|
114
|
+
overscan?: number);
|
|
115
|
+
equals(other: Viewport): boolean;
|
|
116
|
+
withScrollOffset(scrollOffset: number): Viewport;
|
|
117
|
+
withViewportSize(viewportSize: number): Viewport;
|
|
118
|
+
toJSON(): {
|
|
119
|
+
scrollOffset: number;
|
|
120
|
+
viewportSize: number;
|
|
121
|
+
rowHeight: number;
|
|
122
|
+
overscan: number;
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/** Inclusive start, exclusive end — indices into the ordered row list. */
|
|
126
|
+
type VisibleRange = {
|
|
127
|
+
readonly startIndex: number;
|
|
128
|
+
readonly endIndex: number;
|
|
129
|
+
readonly startOffset: number;
|
|
130
|
+
readonly endOffset: number;
|
|
131
|
+
readonly totalHeight: number;
|
|
132
|
+
readonly visibleCount: number;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
declare class CellValue {
|
|
136
|
+
readonly value: unknown;
|
|
137
|
+
constructor(value: unknown);
|
|
138
|
+
equals(other: CellValue): boolean;
|
|
139
|
+
}
|
|
140
|
+
declare class CellDisplay {
|
|
141
|
+
readonly value: unknown;
|
|
142
|
+
constructor(value: unknown);
|
|
143
|
+
equals(other: CellDisplay): boolean;
|
|
144
|
+
}
|
|
145
|
+
declare class ColumnId {
|
|
146
|
+
readonly value: string;
|
|
147
|
+
private static readonly interned;
|
|
148
|
+
constructor(value: string);
|
|
149
|
+
/** Shared instance per field name (PR-101) — avoids 100k×cols ColumnId objects. */
|
|
150
|
+
static for(value: string): ColumnId;
|
|
151
|
+
equals(other: ColumnId): boolean;
|
|
152
|
+
}
|
|
153
|
+
type KeyValue = {
|
|
154
|
+
key: string;
|
|
155
|
+
value: unknown;
|
|
156
|
+
display: unknown;
|
|
157
|
+
};
|
|
158
|
+
type IRule = {
|
|
159
|
+
type?: string | "array" | "object" | "enum" | "date" | "number" | "integer" | "float" | "boolean" | "email" | "url" | "hex" | RegExp;
|
|
160
|
+
required?: boolean;
|
|
161
|
+
requiredIf?: () => boolean;
|
|
162
|
+
whitespace?: boolean;
|
|
163
|
+
message?: string;
|
|
164
|
+
transform?: (value: unknown) => unknown;
|
|
165
|
+
pattern?: string | RegExp;
|
|
166
|
+
min?: number;
|
|
167
|
+
max?: number;
|
|
168
|
+
len?: number;
|
|
169
|
+
enum?: unknown[];
|
|
170
|
+
validator?: (rule: IRule, value: unknown, callback: (error?: string[]) => void) => void | Promise<void>;
|
|
171
|
+
asyncValidator?: (rule: IRule, value: unknown) => Promise<void>;
|
|
172
|
+
warningOnly?: boolean;
|
|
173
|
+
validateTrigger?: string | string[];
|
|
174
|
+
};
|
|
175
|
+
declare class RowId {
|
|
176
|
+
value: number;
|
|
177
|
+
constructor(value: number);
|
|
178
|
+
equals(other: RowId): boolean;
|
|
179
|
+
set(id: RowId): void;
|
|
180
|
+
}
|
|
181
|
+
declare class RowState {
|
|
182
|
+
value: RowStateEnum;
|
|
183
|
+
constructor(value: RowStateEnum);
|
|
184
|
+
equals(other: RowStateEnum): boolean;
|
|
185
|
+
set(rowState: RowStateEnum): void;
|
|
186
|
+
}
|
|
187
|
+
declare enum RowStateEnum {
|
|
188
|
+
Added = "Add",
|
|
189
|
+
Modified = "Update",
|
|
190
|
+
Deleted = "Delete",
|
|
191
|
+
Unchanged = "None"
|
|
192
|
+
}
|
|
193
|
+
type TableActions = "copy" | "cut" | "paste" | "pasteInsert" | null;
|
|
194
|
+
|
|
195
|
+
declare class Pagination {
|
|
196
|
+
readonly page: number;
|
|
197
|
+
readonly pageSize: number;
|
|
198
|
+
readonly totalRows: number;
|
|
199
|
+
readonly totalPages: number;
|
|
200
|
+
readonly canPrev: boolean;
|
|
201
|
+
readonly canNext: boolean;
|
|
202
|
+
constructor(page: number, pageSize: number, totalRows: number);
|
|
203
|
+
changePage(page: number): Pagination;
|
|
204
|
+
changePageSize(size: number): Pagination;
|
|
205
|
+
toJSON(): {
|
|
206
|
+
page: number;
|
|
207
|
+
pageSize: number;
|
|
208
|
+
totalRows: number;
|
|
209
|
+
totalPages: number;
|
|
210
|
+
canPrev: boolean;
|
|
211
|
+
canNext: boolean;
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
declare class CellChanged {
|
|
216
|
+
readonly rowId: RowId;
|
|
217
|
+
readonly columnId: ColumnId;
|
|
218
|
+
readonly newValue: unknown;
|
|
219
|
+
readonly previousValue: unknown;
|
|
220
|
+
readonly type = "CELL_CHANGED";
|
|
221
|
+
constructor(rowId: RowId, columnId: ColumnId, newValue: unknown, previousValue: unknown);
|
|
222
|
+
}
|
|
223
|
+
declare class DisplayChanged {
|
|
224
|
+
readonly rowId: RowId;
|
|
225
|
+
readonly columnId: ColumnId;
|
|
226
|
+
readonly newValue: unknown;
|
|
227
|
+
readonly type = "DISPLAY_CHANGED";
|
|
228
|
+
constructor(rowId: RowId, columnId: ColumnId, newValue: unknown);
|
|
229
|
+
}
|
|
230
|
+
declare class DescriptionSaved {
|
|
231
|
+
readonly rowId: RowId;
|
|
232
|
+
readonly flag: boolean;
|
|
233
|
+
readonly type = "DESCRIPTION_SAVED";
|
|
234
|
+
constructor(rowId: RowId, flag: boolean);
|
|
235
|
+
}
|
|
236
|
+
declare class ColumnReordered {
|
|
237
|
+
readonly sourceIndex: number;
|
|
238
|
+
readonly destIndex: number;
|
|
239
|
+
readonly type = "COLUMN_REORDERED";
|
|
240
|
+
constructor(sourceIndex: number, destIndex: number);
|
|
241
|
+
}
|
|
242
|
+
declare class RowAdded {
|
|
243
|
+
readonly rowId: RowId;
|
|
244
|
+
readonly type = "ROW_ADDED";
|
|
245
|
+
constructor(rowId: RowId);
|
|
246
|
+
}
|
|
247
|
+
declare class RowDeleted {
|
|
248
|
+
readonly rowId: RowId;
|
|
249
|
+
readonly type = "ROW_DELETED";
|
|
250
|
+
constructor(rowId: RowId);
|
|
251
|
+
}
|
|
252
|
+
declare class RowRemoved {
|
|
253
|
+
readonly rowId: RowId;
|
|
254
|
+
readonly type = "NEW_ROW_REMOVED";
|
|
255
|
+
constructor(rowId: RowId);
|
|
256
|
+
}
|
|
257
|
+
declare class MinimumRowConstraintViolated {
|
|
258
|
+
readonly rowId: RowId;
|
|
259
|
+
readonly type = "NEW_AND_FIRST_ROW_CAN_NOT_BE_REMOVE";
|
|
260
|
+
constructor(rowId: RowId);
|
|
261
|
+
}
|
|
262
|
+
declare class RowRestored {
|
|
263
|
+
readonly rowId: RowId;
|
|
264
|
+
readonly type = "ROW_RESTORED";
|
|
265
|
+
constructor(rowId: RowId);
|
|
266
|
+
}
|
|
267
|
+
declare class RowReordered {
|
|
268
|
+
readonly draggedRowNum: number;
|
|
269
|
+
readonly droppedRowNum: number;
|
|
270
|
+
readonly type = "ROW_REORDERED";
|
|
271
|
+
constructor(draggedRowNum: number, droppedRowNum: number);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Domain cell. Stores primitives (PR-101) — `CellValue` / `CellDisplay`
|
|
276
|
+
* wrappers are allocated only when callers ask for value objects.
|
|
277
|
+
*/
|
|
278
|
+
declare class Cell {
|
|
279
|
+
readonly rowId: RowId;
|
|
280
|
+
readonly columnId: ColumnId;
|
|
281
|
+
private value;
|
|
282
|
+
private originalValue;
|
|
283
|
+
private display;
|
|
284
|
+
constructor(rowId: RowId, columnId: ColumnId, value: unknown, originalValue: unknown, display: unknown);
|
|
285
|
+
changeValue(newValue: unknown): CellChanged | null;
|
|
286
|
+
changeDisplay(newValue: unknown): DisplayChanged | null;
|
|
287
|
+
changeOriginalValue(newValue: unknown): CellChanged | null;
|
|
288
|
+
getValue(): unknown;
|
|
289
|
+
getValueObject(): CellValue;
|
|
290
|
+
getDisplay(): unknown;
|
|
291
|
+
getDisplayObject(): CellDisplay;
|
|
292
|
+
getOriginalValue(): CellValue;
|
|
293
|
+
clone(): Cell;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
declare class Row {
|
|
297
|
+
id: RowId;
|
|
298
|
+
cells: Map<string, Cell>;
|
|
299
|
+
rowState: RowState;
|
|
300
|
+
changeFields: Set<string>;
|
|
301
|
+
visibilityCondition: Record<string, boolean>;
|
|
302
|
+
collection: string;
|
|
303
|
+
isSaveDescription: boolean;
|
|
304
|
+
/**
|
|
305
|
+
* Host object for `rowData` (PR-82). Same reference — never deep-cloned —
|
|
306
|
+
* so `ColumnDef.valueGetter` can read the original `TRow`.
|
|
307
|
+
*/
|
|
308
|
+
data?: unknown | undefined;
|
|
309
|
+
/** Stable host id from `getRowId` (string). */
|
|
310
|
+
sourceId?: string | undefined;
|
|
311
|
+
constructor(id: RowId, cells: Map<string, Cell>, rowState: RowState, changeFields: Set<string> | undefined, visibilityCondition: Record<string, boolean>, collection: string | undefined, isSaveDescription: boolean,
|
|
312
|
+
/**
|
|
313
|
+
* Host object for `rowData` (PR-82). Same reference — never deep-cloned —
|
|
314
|
+
* so `ColumnDef.valueGetter` can read the original `TRow`.
|
|
315
|
+
*/
|
|
316
|
+
data?: unknown | undefined,
|
|
317
|
+
/** Stable host id from `getRowId` (string). */
|
|
318
|
+
sourceId?: string | undefined);
|
|
319
|
+
updateChangeFields(columnId: ColumnId): void;
|
|
320
|
+
getCollection(): string;
|
|
321
|
+
setCollection(collection: string): void;
|
|
322
|
+
getChangeFields(): readonly string[];
|
|
323
|
+
getSnapshotChangeFields(): readonly string[];
|
|
324
|
+
changeCell(columnId: ColumnId, value: unknown): CellChanged | null;
|
|
325
|
+
saveDescription(flag: boolean): DescriptionSaved;
|
|
326
|
+
changeDisplay(columnId: ColumnId, value: unknown): DisplayChanged | null;
|
|
327
|
+
getCells(): ReadonlyMap<string, Cell>;
|
|
328
|
+
/**
|
|
329
|
+
* Return a cell without materializing from host `data` (PR-101).
|
|
330
|
+
*/
|
|
331
|
+
peekCell(columnId: string): Cell | undefined;
|
|
332
|
+
/**
|
|
333
|
+
* Lazy host cells (PR-101): when `rowData` left values on `data`, materialize
|
|
334
|
+
* a Cell on first read and cache it.
|
|
335
|
+
*/
|
|
336
|
+
getCell(columnId: string): Cell | undefined;
|
|
337
|
+
/**
|
|
338
|
+
* Read a cell value without allocating a Cell when the host object still
|
|
339
|
+
* holds the canonical value (PR-101 hot path for sort/filter/quick filter).
|
|
340
|
+
*/
|
|
341
|
+
readValue(columnId: string): unknown;
|
|
342
|
+
readDisplay(columnId: string): unknown;
|
|
343
|
+
ensureCell(columnId: ColumnId, defaultValue: CellValue, displayValue: CellDisplay): void;
|
|
344
|
+
setRowId(rowId: RowId): void;
|
|
345
|
+
setVisibilityCondition(Condition: Record<string, boolean>): void;
|
|
346
|
+
getVisibilityCondition(): Record<string, boolean>;
|
|
347
|
+
removeCell(columnId: ColumnId): void;
|
|
348
|
+
setData(data: unknown): void;
|
|
349
|
+
getData(): unknown;
|
|
350
|
+
clone(): Row;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
declare class Collection {
|
|
354
|
+
name: string;
|
|
355
|
+
private rows;
|
|
356
|
+
private columns;
|
|
357
|
+
constructor(name: string | undefined, rows: Map<number, Row>, columns: Map<string, ColumnSchema>);
|
|
358
|
+
setCollectionName(name: string): void;
|
|
359
|
+
getCollectionName(): string;
|
|
360
|
+
getRows(): Map<number, Row>;
|
|
361
|
+
setRows(rows: Map<number, Row>): void;
|
|
362
|
+
getColumns(): Map<string, ColumnSchema>;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
type CollectionScope = 'active' | 'all' | string[];
|
|
366
|
+
declare class Table {
|
|
367
|
+
readonly id: string;
|
|
368
|
+
private collection;
|
|
369
|
+
private pagination;
|
|
370
|
+
private action;
|
|
371
|
+
private activeCollection;
|
|
372
|
+
constructor(id: string, collection: Map<string, Collection>, pagination: Pagination, action: TableActions, activeCollection?: string);
|
|
373
|
+
/**
|
|
374
|
+
* Page-window mode (persistence 'paged-idb'): the Collection row Maps hold
|
|
375
|
+
* ONLY the current page; Pagination.totalRows is the source of truth for
|
|
376
|
+
* totals. In the default mode the Maps hold every row and pagination slices.
|
|
377
|
+
*/
|
|
378
|
+
private pageWindow;
|
|
379
|
+
isPageWindow(): boolean;
|
|
380
|
+
setPageWindow(enabled: boolean): this;
|
|
381
|
+
private getActiveCollection;
|
|
382
|
+
private getCollection;
|
|
383
|
+
/** Finds which Collection currently owns a given column id (if any). */
|
|
384
|
+
private findCollectionForColumn;
|
|
385
|
+
getCollections(): Map<string, Collection>;
|
|
386
|
+
getColumnSchema(columnId: ColumnId): ColumnSchema | undefined;
|
|
387
|
+
getActiveCollectionName(): string;
|
|
388
|
+
setActiveCollection(activeCollection: string): void;
|
|
389
|
+
getRowCollection(rowId: number): string | undefined;
|
|
390
|
+
setRowCollection(rowId: number, collection: string): void;
|
|
391
|
+
setColumnSchema(columnId: ColumnId, DetailColumnConfig: ColumnSchema): ColumnSchema | undefined;
|
|
392
|
+
getColumns(): ColumnSchema[];
|
|
393
|
+
getActiveCollectionColumns(): ColumnSchema[];
|
|
394
|
+
getColumnsForCollectionScope(collectionScope?: CollectionScope): ColumnSchema[];
|
|
395
|
+
getColumnValues(colId: string): unknown[];
|
|
396
|
+
setColumns(newColumns: ColumnSchema[]): void;
|
|
397
|
+
changeCell(rowId: RowId, columnId: ColumnId, value: unknown): CellChanged | null;
|
|
398
|
+
changeDisplay(rowId: RowId, columnId: ColumnId, value: unknown): DisplayChanged | null;
|
|
399
|
+
saveDescription(rowId: RowId, flag: boolean): DescriptionSaved | null;
|
|
400
|
+
duplicateRow(rowId: RowId): RowAdded;
|
|
401
|
+
addRow(targetRowId: number, placedRowId?: number): RowAdded;
|
|
402
|
+
addNewRow(data?: KeyValue[], nextIndex?: number): RowAdded;
|
|
403
|
+
addNewRows(cmd: {
|
|
404
|
+
rows: KeyValue[][];
|
|
405
|
+
detailFieldKey: string;
|
|
406
|
+
}): RowAdded[];
|
|
407
|
+
addColumns(newColumns: ColumnSchema[]): {
|
|
408
|
+
added: ColumnId[];
|
|
409
|
+
};
|
|
410
|
+
setColumnHidden(columnId: string, hidden: boolean): boolean;
|
|
411
|
+
/** Runtime pin on `columnDef.pinned` (PR-114). Index column is not mutable. */
|
|
412
|
+
setColumnPinned(columnId: string, pinned: 'start' | 'end' | null): boolean;
|
|
413
|
+
removeColumns(columnIds: ColumnId[]): {
|
|
414
|
+
removed: ColumnId[];
|
|
415
|
+
};
|
|
416
|
+
getRows(collectionScope?: CollectionScope): Row[];
|
|
417
|
+
getCollectionsRows(collections: string[]): Row[];
|
|
418
|
+
getRow(rowId: number): Row | undefined;
|
|
419
|
+
/** Host `rowData` sync (PR-82) — put without going through add/undo. */
|
|
420
|
+
hostPutRow(row: Row): void;
|
|
421
|
+
/** Host `rowData` sync (PR-82) — drop to match the host array. */
|
|
422
|
+
hostRemoveRow(rowId: number): void;
|
|
423
|
+
addRows(newRows: Row[]): void;
|
|
424
|
+
getPagination(): Pagination;
|
|
425
|
+
setPagination(pagination: Pagination): void;
|
|
426
|
+
changePage(page: number): void;
|
|
427
|
+
changePageSize(size: number): void;
|
|
428
|
+
/**
|
|
429
|
+
* Rows currently held in RAM for the active collection.
|
|
430
|
+
* With page-window storage the Collection Map already contains only the
|
|
431
|
+
* current page — do not slice by pagination offsets.
|
|
432
|
+
*/
|
|
433
|
+
getVisibleRows(): Row[];
|
|
434
|
+
setTableAction(action: TableActions): void;
|
|
435
|
+
getTableAction(): TableActions;
|
|
436
|
+
/**
|
|
437
|
+
* Re-inserts a previously Added row after hard-remove (undo of ADD → redo).
|
|
438
|
+
* Preserves rowId and cell values; no-ops if the id already exists.
|
|
439
|
+
*/
|
|
440
|
+
restoreAddedRow(params: {
|
|
441
|
+
rowId: number;
|
|
442
|
+
cells: Readonly<Record<string, {
|
|
443
|
+
readonly value: unknown;
|
|
444
|
+
readonly display?: unknown;
|
|
445
|
+
readonly originalValue?: unknown;
|
|
446
|
+
}>>;
|
|
447
|
+
collection?: string;
|
|
448
|
+
isSaveDescription?: boolean;
|
|
449
|
+
}): RowAdded;
|
|
450
|
+
/**
|
|
451
|
+
* Delete semantics:
|
|
452
|
+
* - `Added` → hard-remove from the table (physically gone).
|
|
453
|
+
* - `Deleted` → restore (قابل برگرداندن).
|
|
454
|
+
* - otherwise (`Unchanged` / `Modified`) → soft-delete (`rowState = Deleted`).
|
|
455
|
+
*/
|
|
456
|
+
deleteRow(rowId: RowId): RowDeleted | RowRestored | RowRemoved | MinimumRowConstraintViolated | null;
|
|
457
|
+
reorderRows(draggedRowNum: number, droppedRowNum: number, position?: 'before' | 'after'): RowReordered;
|
|
458
|
+
reorderColumns(sourceIndex: number, destIndex: number): ColumnReordered;
|
|
459
|
+
clone(): Table;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Multi-level column group (PR-113).
|
|
464
|
+
* Nested groups are supported via `children` containing more groups.
|
|
465
|
+
*/
|
|
466
|
+
interface ColumnGroupDef<TRow = unknown> {
|
|
467
|
+
groupId?: string;
|
|
468
|
+
headerName: string;
|
|
469
|
+
children: readonly ColDefOrGroup<TRow>[];
|
|
470
|
+
/** When true, hiding one child hides siblings in the same group (AG Grid parity). */
|
|
471
|
+
marryChildren?: boolean;
|
|
472
|
+
}
|
|
473
|
+
type ColDefOrGroup<TRow = unknown> = ColumnDef<TRow> | ColumnGroupDef<TRow>;
|
|
474
|
+
declare function isColumnGroupDef<TRow>(item: ColDefOrGroup<TRow>): item is ColumnGroupDef<TRow>;
|
|
475
|
+
/** Persisted on leaf `ColumnSchema` for header rendering and group reorder. */
|
|
476
|
+
type ColumnGroupPathEntry = {
|
|
477
|
+
groupId: string;
|
|
478
|
+
headerName: string;
|
|
479
|
+
marryChildren?: boolean;
|
|
480
|
+
};
|
|
481
|
+
type ColumnGroupMeta = {
|
|
482
|
+
/** Immediate parent group id. */
|
|
483
|
+
groupId: string;
|
|
484
|
+
/** Root → parent chain. */
|
|
485
|
+
path: readonly ColumnGroupPathEntry[];
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
type FieldType = 'index' | 'text' | 'textArea' | 'number' | 'price' | 'select' | 'selectOption' | 'date' | 'static' | 'description' | 'checkbox';
|
|
489
|
+
type ColumnVisibilityRule = {
|
|
490
|
+
kind: 'always';
|
|
491
|
+
} | {
|
|
492
|
+
kind: 'never';
|
|
493
|
+
} | {
|
|
494
|
+
kind: 'showUnitLevelConditionally';
|
|
495
|
+
fieldName: string;
|
|
496
|
+
} | {
|
|
497
|
+
kind: 'whenFieldTruthy';
|
|
498
|
+
fieldName: string;
|
|
499
|
+
} | {
|
|
500
|
+
kind: 'whenRemoteFlag';
|
|
501
|
+
sourceFieldName: string;
|
|
502
|
+
flag: string;
|
|
503
|
+
} | {
|
|
504
|
+
kind: 'whenCollection';
|
|
505
|
+
collection: string;
|
|
506
|
+
} | {
|
|
507
|
+
kind: 'whenTableType';
|
|
508
|
+
tableType: string;
|
|
509
|
+
};
|
|
510
|
+
interface ResolveOnConfig<K = unknown, TResponse = unknown> {
|
|
511
|
+
endpoint: string;
|
|
512
|
+
fieldName: string;
|
|
513
|
+
buildParams: (row: Record<string, unknown>) => Record<string, unknown>;
|
|
514
|
+
getResponse?: (response: TResponse, row: Row) => unknown;
|
|
515
|
+
mapFlags?: (response: TResponse) => Record<string, boolean>;
|
|
516
|
+
}
|
|
517
|
+
type ColumnAccessControl = {
|
|
518
|
+
allowRoles?: string[];
|
|
519
|
+
denyRoles?: string[];
|
|
520
|
+
rule?: (ctx: {
|
|
521
|
+
actor: Actor$1;
|
|
522
|
+
row: Row;
|
|
523
|
+
table: Table;
|
|
524
|
+
}) => boolean;
|
|
525
|
+
};
|
|
526
|
+
interface IDependOn {
|
|
527
|
+
fieldName: string;
|
|
528
|
+
value: unknown;
|
|
529
|
+
}
|
|
530
|
+
type DefaultOptionType = {
|
|
531
|
+
value?: string | number;
|
|
532
|
+
label?: string;
|
|
533
|
+
title?: string;
|
|
534
|
+
[key: string]: unknown;
|
|
535
|
+
};
|
|
536
|
+
interface ColumnSchema<T = unknown, K = unknown> {
|
|
537
|
+
fieldName: string;
|
|
538
|
+
fieldCaption: string;
|
|
539
|
+
fieldType: FieldType;
|
|
540
|
+
fieldCollection?: string;
|
|
541
|
+
order?: number;
|
|
542
|
+
rules?: IRule[];
|
|
543
|
+
options?: DefaultOptionType[];
|
|
544
|
+
editable?: boolean;
|
|
545
|
+
isUnique?: boolean;
|
|
546
|
+
noCache?: boolean;
|
|
547
|
+
expandable?: boolean;
|
|
548
|
+
returnValue?: (values: T, colId: string) => unknown;
|
|
549
|
+
returnDisplayValue?: (values: T, colId: string) => unknown;
|
|
550
|
+
/**
|
|
551
|
+
* Custom cell renderer (PR-54). `CellRenderer` calls this before the FieldType
|
|
552
|
+
* switch. Not the same as `returnDisplayValue` (engine display string).
|
|
553
|
+
*/
|
|
554
|
+
render?: (ctx: unknown) => unknown;
|
|
555
|
+
enableDeleteButton?: boolean;
|
|
556
|
+
enableExpandButton?: boolean;
|
|
557
|
+
enableMoveButton?: boolean;
|
|
558
|
+
enableOptionsButton?: boolean;
|
|
559
|
+
disable?: boolean;
|
|
560
|
+
colAccess?: ColumnAccessControl;
|
|
561
|
+
dynamicSource?: {
|
|
562
|
+
endpoint: string;
|
|
563
|
+
dependsOn?: string[];
|
|
564
|
+
dependOn?: IDependOn | IDependOn[];
|
|
565
|
+
params?: Record<string, string>;
|
|
566
|
+
[key: string]: unknown;
|
|
567
|
+
};
|
|
568
|
+
hidden?: boolean;
|
|
569
|
+
className?: string;
|
|
570
|
+
visibility: ColumnVisibilityRule;
|
|
571
|
+
resolveOn?: ResolveOnConfig<K>;
|
|
572
|
+
computed?: {
|
|
573
|
+
dependsOn: readonly string[];
|
|
574
|
+
compute: (row: Record<string, unknown>, remoteApi: RemoteApi) => Promise<unknown>;
|
|
575
|
+
children?: [] | undefined;
|
|
576
|
+
};
|
|
577
|
+
selectOptions?: {
|
|
578
|
+
label: string;
|
|
579
|
+
value: string | number;
|
|
580
|
+
}[];
|
|
581
|
+
indexOptions?: (...args: unknown[]) => unknown[];
|
|
582
|
+
onChange?: (...args: unknown[]) => void;
|
|
583
|
+
displayFormat?: (value: unknown) => unknown;
|
|
584
|
+
minWidth?: number;
|
|
585
|
+
style?: Record<string, string | number>;
|
|
586
|
+
popUpWidth?: number;
|
|
587
|
+
dynamicSelectFilterOption?: (inputValue: string, option: unknown) => boolean;
|
|
588
|
+
labelValue?: 'selectDisplay' | 'selectValue';
|
|
589
|
+
/**
|
|
590
|
+
* ColumnDef-only fields restored by `toColumnDef` (PR-81).
|
|
591
|
+
* ERP hosts can ignore this.
|
|
592
|
+
*/
|
|
593
|
+
columnDef?: ColumnDefBridge;
|
|
594
|
+
/** Leaf column group ancestry (PR-113). */
|
|
595
|
+
columnGroup?: ColumnGroupMeta;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Filter descriptor on `ColumnDef`. Consumed in Phase 18 (PR-92+).
|
|
600
|
+
* Built-in names, a custom registry key (PR-95), or `{ type, params }`.
|
|
601
|
+
*/
|
|
602
|
+
type FilterDef = 'text' | 'number' | 'date' | 'set' | (string & {}) | {
|
|
603
|
+
type: string;
|
|
604
|
+
params?: Record<string, unknown>;
|
|
605
|
+
};
|
|
606
|
+
type ColumnPinned = 'start' | 'end' | null;
|
|
607
|
+
/** Built-in footer / group aggregates (PR-118 / RFC-002). */
|
|
608
|
+
type AggFuncName = 'sum' | 'avg' | 'min' | 'max' | 'count' | 'first' | 'last';
|
|
609
|
+
type AggFunc<TValue = unknown> = AggFuncName | ((values: readonly TValue[]) => unknown);
|
|
610
|
+
/**
|
|
611
|
+
* `field` is an unconstrained string until `TRow` is specified; then it is a key of `TRow`.
|
|
612
|
+
* `keyof unknown` is `never`, so untyped `ColumnDef[]` stays usable (PR-88).
|
|
613
|
+
*/
|
|
614
|
+
type ColumnField<TRow> = keyof TRow extends never ? string : Extract<keyof TRow, string>;
|
|
615
|
+
/**
|
|
616
|
+
* Cell renderer slot on `ColumnDef`. Same runtime as `ColumnSchema.render`.
|
|
617
|
+
* UI `CellComponent` is the React-side shape — domain does not import React (PR-81).
|
|
618
|
+
*/
|
|
619
|
+
type ColumnCellRenderer = (ctx: unknown) => unknown;
|
|
620
|
+
/**
|
|
621
|
+
* Public, generic column definition (PR-81 / D14).
|
|
622
|
+
* `ColumnSchema` remains the ERP host / domain persistence shape; use
|
|
623
|
+
* `toColumnSchema` / `toColumnDef` in `infrastructure/columns/` to convert.
|
|
624
|
+
*/
|
|
625
|
+
interface ColumnDef<TRow = unknown, TValue = unknown> {
|
|
626
|
+
colId?: string;
|
|
627
|
+
field?: ColumnField<TRow>;
|
|
628
|
+
headerName?: string;
|
|
629
|
+
type?: FieldType;
|
|
630
|
+
valueGetter?: (p: {
|
|
631
|
+
data: TRow;
|
|
632
|
+
}) => TValue;
|
|
633
|
+
valueSetter?: (p: {
|
|
634
|
+
data: TRow;
|
|
635
|
+
newValue: TValue;
|
|
636
|
+
}) => boolean;
|
|
637
|
+
valueFormatter?: (p: {
|
|
638
|
+
value: TValue;
|
|
639
|
+
data: TRow;
|
|
640
|
+
}) => string;
|
|
641
|
+
/** Consumed in Phase 18 (PR-89). */
|
|
642
|
+
comparator?: (a: TValue, b: TValue) => number;
|
|
643
|
+
editable?: boolean | ((p: {
|
|
644
|
+
data: TRow;
|
|
645
|
+
}) => boolean);
|
|
646
|
+
width?: number;
|
|
647
|
+
minWidth?: number;
|
|
648
|
+
flex?: number;
|
|
649
|
+
hide?: boolean;
|
|
650
|
+
pinned?: ColumnPinned;
|
|
651
|
+
sortable?: boolean;
|
|
652
|
+
filter?: FilterDef | false;
|
|
653
|
+
cellRenderer?: ColumnCellRenderer;
|
|
654
|
+
/**
|
|
655
|
+
* Footer / group aggregate (PR-118 / RFC-002).
|
|
656
|
+
* Built-ins are incremental; money uses integer minor units.
|
|
657
|
+
*/
|
|
658
|
+
aggFunc?: AggFunc<TValue>;
|
|
659
|
+
/**
|
|
660
|
+
* Display unit for `type: 'price'` (PR-140).
|
|
661
|
+
* Stored values remain integer **rials**; `toman` only affects default formatting
|
|
662
|
+
* (÷10). Prefer `valueFormatter` / `valueGetter` for edit UX in تومان.
|
|
663
|
+
*/
|
|
664
|
+
currencyUnit?: 'rial' | 'toman';
|
|
665
|
+
/**
|
|
666
|
+
* Source `ColumnSchema` when this def was produced by `toColumnDef`.
|
|
667
|
+
* `toColumnSchema` copies ERP-only fields (visibility, resolveOn, …) from it.
|
|
668
|
+
*/
|
|
669
|
+
columnSchema?: ColumnSchema;
|
|
670
|
+
/** Stamped by `flattenColDefOrGroup` before `toColumnSchema` (PR-113). */
|
|
671
|
+
columnGroup?: ColumnGroupMeta;
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* ColumnDef fields that have no native `ColumnSchema` equivalent.
|
|
675
|
+
* Stashed on `ColumnSchema.columnDef` so the mapper round-trips.
|
|
676
|
+
*/
|
|
677
|
+
interface ColumnDefBridge {
|
|
678
|
+
field?: string;
|
|
679
|
+
colId?: string;
|
|
680
|
+
valueGetter?: (p: {
|
|
681
|
+
data: unknown;
|
|
682
|
+
}) => unknown;
|
|
683
|
+
valueSetter?: (p: {
|
|
684
|
+
data: unknown;
|
|
685
|
+
newValue: unknown;
|
|
686
|
+
}) => boolean;
|
|
687
|
+
valueFormatter?: (p: {
|
|
688
|
+
value: unknown;
|
|
689
|
+
data: unknown;
|
|
690
|
+
}) => string;
|
|
691
|
+
comparator?: (a: unknown, b: unknown) => number;
|
|
692
|
+
editableWhen?: (p: {
|
|
693
|
+
data: unknown;
|
|
694
|
+
}) => boolean;
|
|
695
|
+
width?: number;
|
|
696
|
+
flex?: number;
|
|
697
|
+
pinned?: ColumnPinned;
|
|
698
|
+
sortable?: boolean;
|
|
699
|
+
filter?: FilterDef | false;
|
|
700
|
+
aggFunc?: AggFunc;
|
|
701
|
+
currencyUnit?: 'rial' | 'toman';
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* Single-level row grouping (PR-120 / RFC-002). Pure — no React/DOM.
|
|
706
|
+
* Produces a flat presentation list: group nodes + leaf row ids.
|
|
707
|
+
*/
|
|
708
|
+
|
|
709
|
+
type FlatGroupNode = {
|
|
710
|
+
kind: 'group';
|
|
711
|
+
/** Negative sentinel id (not a domain RowId). */
|
|
712
|
+
id: number;
|
|
713
|
+
field: string;
|
|
714
|
+
key: string;
|
|
715
|
+
childRowIds: readonly number[];
|
|
716
|
+
aggregates: Record<string, unknown>;
|
|
717
|
+
};
|
|
718
|
+
type FlatLeafNode = {
|
|
719
|
+
kind: 'leaf';
|
|
720
|
+
id: number;
|
|
721
|
+
};
|
|
722
|
+
type FlatUiNode = FlatGroupNode | FlatLeafNode;
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* Column filter model (PR-92). Wired to the row index in PR-94.
|
|
726
|
+
* Keys are `colId` / field names. Empty model ⇒ all rows pass.
|
|
727
|
+
*/
|
|
728
|
+
type FilterModel = Readonly<Record<string, ColumnFilter>>;
|
|
729
|
+
type FilterJoin = 'AND' | 'OR';
|
|
730
|
+
type TextFilterOp = 'contains' | 'notContains' | 'equals' | 'startsWith' | 'endsWith' | 'blank' | 'notBlank';
|
|
731
|
+
/** Number ops: = ≠ < ≤ > ≥ inRange blank */
|
|
732
|
+
type NumberFilterOp = 'equals' | 'notEqual' | '=' | '≠' | '!=' | 'lessThan' | '<' | 'lessThanOrEqual' | '≤' | '<=' | 'greaterThan' | '>' | 'greaterThanOrEqual' | '≥' | '>=' | 'inRange' | 'blank';
|
|
733
|
+
type DateFilterOp = 'equals' | 'before' | 'after' | 'inRange' | 'blank';
|
|
734
|
+
type SetFilterOp = 'in' | 'notIn';
|
|
735
|
+
type BooleanFilterOp = 'true' | 'false' | 'any';
|
|
736
|
+
type TextColumnFilter = {
|
|
737
|
+
filterType: 'text';
|
|
738
|
+
type: TextFilterOp;
|
|
739
|
+
filter?: string | number | null;
|
|
740
|
+
};
|
|
741
|
+
type NumberColumnFilter = {
|
|
742
|
+
filterType: 'number';
|
|
743
|
+
type: NumberFilterOp;
|
|
744
|
+
filter?: number | string | null;
|
|
745
|
+
filterTo?: number | string | null;
|
|
746
|
+
};
|
|
747
|
+
type DateColumnFilter = {
|
|
748
|
+
filterType: 'date';
|
|
749
|
+
type: DateFilterOp;
|
|
750
|
+
/** Inclusive lower / equals bound (Date, epoch ms, or date string). */
|
|
751
|
+
dateFrom?: unknown;
|
|
752
|
+
dateTo?: unknown;
|
|
753
|
+
filter?: unknown;
|
|
754
|
+
filterTo?: unknown;
|
|
755
|
+
};
|
|
756
|
+
type SetColumnFilter = {
|
|
757
|
+
filterType: 'set';
|
|
758
|
+
type?: SetFilterOp;
|
|
759
|
+
values: readonly unknown[];
|
|
760
|
+
};
|
|
761
|
+
type BooleanColumnFilter = {
|
|
762
|
+
filterType: 'boolean';
|
|
763
|
+
type: BooleanFilterOp;
|
|
764
|
+
};
|
|
765
|
+
/**
|
|
766
|
+
* Host / ColumnDef custom predicate. `rowId` is the engine row id;
|
|
767
|
+
* hosts that need the row object look it up themselves.
|
|
768
|
+
*/
|
|
769
|
+
type CustomFilterFn = (value: unknown, rowId: number) => boolean;
|
|
770
|
+
type CustomColumnFilter = {
|
|
771
|
+
filterType: 'custom';
|
|
772
|
+
/** Registry key when applied from a FilterComponent (PR-95). */
|
|
773
|
+
type?: string;
|
|
774
|
+
params?: Record<string, unknown>;
|
|
775
|
+
customFilter: CustomFilterFn;
|
|
776
|
+
};
|
|
777
|
+
type SimpleColumnFilter = TextColumnFilter | NumberColumnFilter | DateColumnFilter | SetColumnFilter | BooleanColumnFilter | CustomColumnFilter;
|
|
778
|
+
/** AND / OR of simple conditions on one column (PR-92). */
|
|
779
|
+
type CombinedColumnFilter = {
|
|
780
|
+
operator: FilterJoin;
|
|
781
|
+
conditions: readonly SimpleColumnFilter[];
|
|
782
|
+
};
|
|
783
|
+
type ColumnFilter = SimpleColumnFilter | CombinedColumnFilter;
|
|
784
|
+
type FilterAccessor = {
|
|
785
|
+
getValue: (rowId: number, colId: string) => unknown;
|
|
786
|
+
/**
|
|
787
|
+
* Optional per-column custom filter when the model uses
|
|
788
|
+
* `{ filterType: 'custom' }` without an inline `customFilter`.
|
|
789
|
+
*/
|
|
790
|
+
getCustomFilter?: (colId: string) => CustomFilterFn | undefined;
|
|
791
|
+
};
|
|
792
|
+
/** Digits + Arabic ي/ك → Latin digits + Persian ی/ک for text compare. */
|
|
793
|
+
declare function normalizeFilterText(value: string): string;
|
|
794
|
+
/**
|
|
795
|
+
* Unique display values for a set-filter menu (PR-92 helper; UI in PR-94).
|
|
796
|
+
* Order is first-seen in `rowIds`.
|
|
797
|
+
*/
|
|
798
|
+
declare function collectUniqueFilterValues(rowIds: readonly number[], colId: string, accessor: FilterAccessor): unknown[];
|
|
799
|
+
/**
|
|
800
|
+
* Pure multi-column filter (PR-92). Does not mutate `rowIds`.
|
|
801
|
+
* Columns in the model are combined with AND. Per-column conditions
|
|
802
|
+
* may use AND / OR. Empty / invalid model returns a shallow copy.
|
|
803
|
+
*/
|
|
804
|
+
declare function applyFilter(rowIds: readonly number[], filterModel: FilterModel | null | undefined, accessor: FilterAccessor): number[];
|
|
805
|
+
/** True when the column has a non-empty filter entry (PR-94 active indicator). */
|
|
806
|
+
declare function isColumnFilterActive(filterModel: FilterModel | null | undefined, colId: string): boolean;
|
|
807
|
+
type BuiltinFilterKind = 'text' | 'number' | 'date' | 'set' | 'boolean';
|
|
808
|
+
/**
|
|
809
|
+
* Resolve which built-in filter UI to show for a column (PR-94).
|
|
810
|
+
* Custom registry filters return `null` — use {@link resolveFilterUi}.
|
|
811
|
+
*/
|
|
812
|
+
declare function resolveBuiltinFilterKind(col: {
|
|
813
|
+
fieldName: string;
|
|
814
|
+
fieldType?: string;
|
|
815
|
+
columnDef?: {
|
|
816
|
+
filter?: unknown;
|
|
817
|
+
} | null;
|
|
818
|
+
}): BuiltinFilterKind | null;
|
|
819
|
+
|
|
820
|
+
/** Document-order column used as the final tie-breaker (PR-89). */
|
|
821
|
+
declare const INDEX_COL_ID = "index";
|
|
822
|
+
type SortDirection = 'asc' | 'desc';
|
|
823
|
+
type SortModelItem = {
|
|
824
|
+
colId: string;
|
|
825
|
+
sort: SortDirection;
|
|
826
|
+
};
|
|
827
|
+
type SortModel = readonly SortModelItem[];
|
|
828
|
+
type SortValueComparator = (a: unknown, b: unknown) => number;
|
|
829
|
+
type SortAccessor = {
|
|
830
|
+
getValue: (rowId: number, colId: string) => unknown;
|
|
831
|
+
getFieldType?: (colId: string) => FieldType | undefined;
|
|
832
|
+
getComparator?: (colId: string) => SortValueComparator | undefined;
|
|
833
|
+
};
|
|
834
|
+
declare function normalizeDigits(value: string): string;
|
|
835
|
+
declare function isBlankSortValue(value: unknown): boolean;
|
|
836
|
+
/**
|
|
837
|
+
* Ascending compare for a FieldType. Blank handling is done by `compareSortValues`.
|
|
838
|
+
*/
|
|
839
|
+
declare function compareTypedValues(a: unknown, b: unknown, fieldType: FieldType | undefined): number;
|
|
840
|
+
declare function compareSortValues(a: unknown, b: unknown, fieldType: FieldType | undefined, comparator: SortValueComparator | undefined): number;
|
|
841
|
+
/**
|
|
842
|
+
* Pure multi-sort (PR-89). Does not mutate `rowIds`.
|
|
843
|
+
* Null/blank values sort last in both directions. `index` is the last
|
|
844
|
+
* tie-breaker so document order is preserved when sort keys match.
|
|
845
|
+
*/
|
|
846
|
+
declare function applySort(rowIds: readonly number[], sortModel: SortModel, accessor: SortAccessor): number[];
|
|
847
|
+
/** Max pointer movement (px) that still counts as a header sort click (PR-91). */
|
|
848
|
+
declare const HEADER_SORT_CLICK_MAX_MOVE_PX = 5;
|
|
849
|
+
/**
|
|
850
|
+
* True when pointer travel is below the drag threshold so a header click
|
|
851
|
+
* should change sort (not a column reorder gesture).
|
|
852
|
+
*/
|
|
853
|
+
declare function shouldCommitHeaderSortClick(movedPx: number): boolean;
|
|
854
|
+
type CycleSortModelOptions = {
|
|
855
|
+
/** Shift+Click: keep other columns; otherwise replace with this column. */
|
|
856
|
+
multi?: boolean;
|
|
857
|
+
};
|
|
858
|
+
/**
|
|
859
|
+
* Header click cycle (PR-91): none → asc → desc → none.
|
|
860
|
+
* Without `multi`, the model becomes a single column (or empty).
|
|
861
|
+
* With `multi`, the column is appended / toggled / removed in place.
|
|
862
|
+
*/
|
|
863
|
+
declare function cycleSortModel(current: SortModel, colId: string, options?: CycleSortModelOptions): SortModel;
|
|
864
|
+
type AriaSortValue = 'ascending' | 'descending' | 'none';
|
|
865
|
+
declare function ariaSortForColumn(sortModel: SortModel, colId: string): AriaSortValue;
|
|
866
|
+
/** 1-based priority for multi-sort badge; undefined when column is unsorted. */
|
|
867
|
+
declare function sortPriorityForColumn(sortModel: SortModel, colId: string): number | undefined;
|
|
868
|
+
/** Index column and `sortable: false` are never header-sortable. */
|
|
869
|
+
declare function isHeaderColumnSortable(col: {
|
|
870
|
+
fieldName: string;
|
|
871
|
+
fieldType?: string;
|
|
872
|
+
columnDef?: {
|
|
873
|
+
sortable?: boolean;
|
|
874
|
+
} | null;
|
|
875
|
+
}): boolean;
|
|
876
|
+
|
|
877
|
+
/**
|
|
878
|
+
* Row model mode (PR-96).
|
|
879
|
+
* - `clientSide` — local sort / filter / quick filter.
|
|
880
|
+
* - `infinite` / `serverSide` — models are for the host datasource; skip local apply*.
|
|
881
|
+
*/
|
|
882
|
+
type RowModelType = 'clientSide' | 'infinite' | 'serverSide';
|
|
883
|
+
declare function isServerRowModel(rowModelType: RowModelType | undefined | null): boolean;
|
|
884
|
+
/** Half-open page window `[startRow, endRow)`. */
|
|
885
|
+
declare function pageWindow(page: number, pageSize: number): {
|
|
886
|
+
startRow: number;
|
|
887
|
+
endRow: number;
|
|
888
|
+
};
|
|
889
|
+
|
|
890
|
+
/**
|
|
891
|
+
* Session-only cell edit draft (PR-126). Not EventStore.
|
|
892
|
+
* Typing updates drafts; Commit writes; Cancel discards.
|
|
893
|
+
*/
|
|
894
|
+
type CellEditType = 'cell' | 'fullRow';
|
|
895
|
+
type CellEditValue = {
|
|
896
|
+
value: unknown;
|
|
897
|
+
display: unknown;
|
|
898
|
+
};
|
|
899
|
+
type CellEditSession = {
|
|
900
|
+
rowId: number;
|
|
901
|
+
/** Focused column while editing. */
|
|
902
|
+
columnId: string;
|
|
903
|
+
editType: CellEditType;
|
|
904
|
+
/** Values at edit start — restored on cancel. */
|
|
905
|
+
baseline: Readonly<Record<string, CellEditValue>>;
|
|
906
|
+
/** Working copies. */
|
|
907
|
+
drafts: Record<string, CellEditValue>;
|
|
908
|
+
};
|
|
909
|
+
type CellEditOptions = {
|
|
910
|
+
/** Default true — activate cell starts edit. False ⇒ need Enter / double-click / api.startEditingCell. */
|
|
911
|
+
singleClickEdit: boolean;
|
|
912
|
+
/** Default true — leaving the grid / clearActiveCell commits the draft. */
|
|
913
|
+
stopEditingWhenCellsLoseFocus: boolean;
|
|
914
|
+
/** Default `cell`. `fullRow` edits every editable column on the row. */
|
|
915
|
+
editType: CellEditType;
|
|
916
|
+
};
|
|
917
|
+
|
|
918
|
+
/**
|
|
919
|
+
* Host-agnostic request config shape used by UI multi-select bindings.
|
|
920
|
+
* Host apps may narrow this to their own IRequestConfig.
|
|
921
|
+
*/
|
|
922
|
+
type IRequestConfig = {
|
|
923
|
+
endpoint?: string;
|
|
924
|
+
params?: Record<string, unknown>;
|
|
925
|
+
method?: 'GET' | 'POST';
|
|
926
|
+
[key: string]: unknown;
|
|
927
|
+
};
|
|
928
|
+
|
|
929
|
+
interface UIRow {
|
|
930
|
+
id: number;
|
|
931
|
+
cells: Record<string, TCell>;
|
|
932
|
+
rowState: RowStateEnum;
|
|
933
|
+
isExpanded: boolean;
|
|
934
|
+
changeFields: readonly string[];
|
|
935
|
+
visibilityCondition: Record<string, boolean>;
|
|
936
|
+
/** Infinite/server placeholder row (PR-103 skeleton). */
|
|
937
|
+
loading?: boolean;
|
|
938
|
+
/** Synthetic group row (PR-120). Absent / `'leaf'` = normal data row. */
|
|
939
|
+
rowKind?: 'group' | 'leaf';
|
|
940
|
+
groupField?: string;
|
|
941
|
+
groupKey?: string;
|
|
942
|
+
groupChildCount?: number;
|
|
943
|
+
groupExpanded?: boolean;
|
|
944
|
+
}
|
|
945
|
+
type MultiSelectDependOn = {
|
|
946
|
+
fieldName: string;
|
|
947
|
+
value: unknown;
|
|
948
|
+
};
|
|
949
|
+
interface IMultiSelectConfig {
|
|
950
|
+
/**
|
|
951
|
+
* Resolve `dynamicValue.dependOn` values through the host's
|
|
952
|
+
* `useDependOn` hook (e.g. header-form fields) instead of the static
|
|
953
|
+
* values carried by the items.
|
|
954
|
+
*/
|
|
955
|
+
dependOnFromHost?: boolean;
|
|
956
|
+
dynamicValue: IRequestConfig & {
|
|
957
|
+
dependsOn?: string[];
|
|
958
|
+
dependOn?: MultiSelectDependOn | MultiSelectDependOn[];
|
|
959
|
+
};
|
|
960
|
+
fieldKey: string;
|
|
961
|
+
detailFieldKey: string;
|
|
962
|
+
onAdd: (rows: Record<string, unknown>[]) => void;
|
|
963
|
+
ListConfig: {
|
|
964
|
+
fieldName: string;
|
|
965
|
+
fieldCaption: string;
|
|
966
|
+
fieldType: FieldType;
|
|
967
|
+
hidden?: boolean;
|
|
968
|
+
returnValue?: (row: Record<string, unknown>, colId: string) => unknown;
|
|
969
|
+
returnDisplayValue?: (row: Record<string, unknown>, colId: string) => unknown;
|
|
970
|
+
}[];
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
type GridSearchMatch = {
|
|
974
|
+
rowId: number;
|
|
975
|
+
columnId: string;
|
|
976
|
+
};
|
|
977
|
+
type GridSearchState = {
|
|
978
|
+
columnId: string;
|
|
979
|
+
query: string;
|
|
980
|
+
matches: GridSearchMatch[];
|
|
981
|
+
currentIndex: number;
|
|
982
|
+
} | null;
|
|
983
|
+
type MobileEditorState = {
|
|
984
|
+
mode: 'add' | 'edit';
|
|
985
|
+
rowId: number;
|
|
986
|
+
} | null;
|
|
987
|
+
type TableViewState = {
|
|
988
|
+
activeCell: ActiveCell;
|
|
989
|
+
selectedRows: Record<number, true>;
|
|
990
|
+
rows: UIRow[];
|
|
991
|
+
deletedRows: Array<{
|
|
992
|
+
id: string;
|
|
993
|
+
cells: Record<string, unknown>;
|
|
994
|
+
isExpanded: boolean;
|
|
995
|
+
}>;
|
|
996
|
+
columns: ColumnSchema[];
|
|
997
|
+
activeCollectionColumn: ColumnSchema[];
|
|
998
|
+
pagination: {
|
|
999
|
+
page: number;
|
|
1000
|
+
pageSize: number;
|
|
1001
|
+
totalRows: number;
|
|
1002
|
+
totalPages: number;
|
|
1003
|
+
canPrev: boolean;
|
|
1004
|
+
canNext: boolean;
|
|
1005
|
+
};
|
|
1006
|
+
action: TableActions;
|
|
1007
|
+
gridSearch: GridSearchState;
|
|
1008
|
+
mobileEditor: MobileEditorState;
|
|
1009
|
+
/** Session-only column widths (px). Not EventStore. */
|
|
1010
|
+
columnWidths: Record<string, number>;
|
|
1011
|
+
/** Session-only sort (PR-90). Empty ⇒ document `index` order. Not EventStore. */
|
|
1012
|
+
sortModel: SortModel;
|
|
1013
|
+
/**
|
|
1014
|
+
* Session-only quick filter (PR-93). Hides non-matching rows (unlike
|
|
1015
|
+
* `gridSearch` find-and-navigate). Not EventStore.
|
|
1016
|
+
*/
|
|
1017
|
+
quickFilterText: string;
|
|
1018
|
+
/** Session-only column filters (PR-94). Not EventStore. */
|
|
1019
|
+
filterModel: FilterModel;
|
|
1020
|
+
/** Cell-range selection (PR-105). Session-only. */
|
|
1021
|
+
cellRanges: readonly CellRange[];
|
|
1022
|
+
/** Collapsed column group ids (PR-113). */
|
|
1023
|
+
collapsedColumnGroups: Record<string, true>;
|
|
1024
|
+
/** Active row-group columns (PR-120). */
|
|
1025
|
+
rowGroupColumns: string[];
|
|
1026
|
+
groupDefaultExpanded: boolean;
|
|
1027
|
+
/** Session-only cell edit draft (PR-126). */
|
|
1028
|
+
cellEdit: CellEditSession | null;
|
|
1029
|
+
};
|
|
1030
|
+
type MobileTableViewState = {
|
|
1031
|
+
rows: UIRow[];
|
|
1032
|
+
columns: ColumnSchema[];
|
|
1033
|
+
totalRows: number;
|
|
1034
|
+
visibleCount: number;
|
|
1035
|
+
hasMore: boolean;
|
|
1036
|
+
pageSize: number;
|
|
1037
|
+
mobileEditor: MobileEditorState;
|
|
1038
|
+
};
|
|
1039
|
+
type TableSnapShot = {
|
|
1040
|
+
rows: Array<{
|
|
1041
|
+
id: number;
|
|
1042
|
+
cells: Record<string, unknown>;
|
|
1043
|
+
rowState: RowStateEnum;
|
|
1044
|
+
collection: string;
|
|
1045
|
+
rowType?: string;
|
|
1046
|
+
changeFields: readonly string[];
|
|
1047
|
+
isSaveDescription: boolean;
|
|
1048
|
+
}>;
|
|
1049
|
+
};
|
|
1050
|
+
type ActiveCell = {
|
|
1051
|
+
rowId: number;
|
|
1052
|
+
columnId: string;
|
|
1053
|
+
} | null;
|
|
1054
|
+
type ValidCell = {
|
|
1055
|
+
isValid: boolean;
|
|
1056
|
+
cellError: CellError;
|
|
1057
|
+
};
|
|
1058
|
+
type TableState = {
|
|
1059
|
+
table: Table;
|
|
1060
|
+
expandedRows: Record<string, boolean>;
|
|
1061
|
+
selectedRows: Record<number, true>;
|
|
1062
|
+
activeRowId: number | undefined;
|
|
1063
|
+
activeCell: ActiveCell | undefined;
|
|
1064
|
+
rangeAnchorRowId: number | undefined;
|
|
1065
|
+
gridSearch: GridSearchState;
|
|
1066
|
+
mobileEditor: MobileEditorState;
|
|
1067
|
+
columnWidths: Record<string, number>;
|
|
1068
|
+
/** Session-only sort model (PR-90). Not EventStore. */
|
|
1069
|
+
sortModel: SortModel;
|
|
1070
|
+
/** Session-only quick filter text (PR-93). Not EventStore. */
|
|
1071
|
+
quickFilterText: string;
|
|
1072
|
+
/** Session-only column filter model (PR-94). Not EventStore. */
|
|
1073
|
+
filterModel: FilterModel;
|
|
1074
|
+
/**
|
|
1075
|
+
* Row model mode (PR-96). Default `clientSide`.
|
|
1076
|
+
* When `infinite` / `serverSide`, local sort/filter are skipped.
|
|
1077
|
+
*/
|
|
1078
|
+
rowModelType: RowModelType;
|
|
1079
|
+
/**
|
|
1080
|
+
* Total rows from the last `GridDatasource.getRows().lastRow` (PR-96).
|
|
1081
|
+
* `null` = unknown / use loaded row count.
|
|
1082
|
+
*/
|
|
1083
|
+
serverRowCount: number | null;
|
|
1084
|
+
/** Cell-range selection state (PR-105). Session-only. */
|
|
1085
|
+
cellRangeSelection: CellRangeSelection;
|
|
1086
|
+
/** Collapsed column group ids (PR-113). Session-only. */
|
|
1087
|
+
collapsedColumnGroups: Record<string, true>;
|
|
1088
|
+
/**
|
|
1089
|
+
* Row group column ids (PR-120). Only the first is active in 0.12.0.
|
|
1090
|
+
* Session-only — not EventStore (RFC-002).
|
|
1091
|
+
*/
|
|
1092
|
+
rowGroupColumns: string[];
|
|
1093
|
+
/** Default expand state for row groups (PR-120). */
|
|
1094
|
+
groupDefaultExpanded: boolean;
|
|
1095
|
+
/** Per-group expand overrides keyed by normalizeGroupKey (PR-120). */
|
|
1096
|
+
rowGroupExpanded: Record<string, boolean>;
|
|
1097
|
+
/** Session-only cell edit draft (PR-126). Not EventStore. */
|
|
1098
|
+
cellEdit: CellEditSession | null;
|
|
1099
|
+
};
|
|
1100
|
+
type TCell = {
|
|
1101
|
+
value: unknown;
|
|
1102
|
+
originalValue: unknown;
|
|
1103
|
+
display: unknown;
|
|
1104
|
+
};
|
|
1105
|
+
type ItemType = {
|
|
1106
|
+
type?: 'submenu' | 'item' | 'group' | 'divider';
|
|
1107
|
+
label?: React.ReactNode;
|
|
1108
|
+
children?: ItemType[];
|
|
1109
|
+
disabled?: boolean;
|
|
1110
|
+
ref?: React.Ref<HTMLLIElement | null>;
|
|
1111
|
+
style?: React.CSSProperties;
|
|
1112
|
+
className?: string;
|
|
1113
|
+
isSelected?: boolean;
|
|
1114
|
+
isOpen?: boolean;
|
|
1115
|
+
isSubMenu?: boolean;
|
|
1116
|
+
danger?: boolean;
|
|
1117
|
+
icon?: React.ReactNode;
|
|
1118
|
+
title?: string;
|
|
1119
|
+
key: string;
|
|
1120
|
+
theme?: 'dark' | 'light';
|
|
1121
|
+
dashed?: boolean;
|
|
1122
|
+
rootClassName?: string;
|
|
1123
|
+
itemIcon?: React.ReactNode;
|
|
1124
|
+
expandIcon?: React.ReactNode;
|
|
1125
|
+
popupClassName?: string;
|
|
1126
|
+
popupOffset?: number[];
|
|
1127
|
+
popupStyle?: React.CSSProperties;
|
|
1128
|
+
onClick?: () => void;
|
|
1129
|
+
extra?: React.ReactNode;
|
|
1130
|
+
};
|
|
1131
|
+
type ValidationCallback = (result: ValidationCallbackResult) => void;
|
|
1132
|
+
type ValidationCallbackResult = {
|
|
1133
|
+
valid: boolean;
|
|
1134
|
+
errors?: Map<string, CellError>;
|
|
1135
|
+
data?: unknown;
|
|
1136
|
+
};
|
|
1137
|
+
interface CellError {
|
|
1138
|
+
rowId: number;
|
|
1139
|
+
caption: string;
|
|
1140
|
+
message: string;
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
interface BaseTableCommand {
|
|
1144
|
+
readonly store: string;
|
|
1145
|
+
readonly tableKey: string;
|
|
1146
|
+
/** When set, undoable events from separate executes merge into one undo unit. */
|
|
1147
|
+
readonly correlationId?: string;
|
|
1148
|
+
}
|
|
1149
|
+
type Actor = {
|
|
1150
|
+
readonly userId: string;
|
|
1151
|
+
readonly roles: string[];
|
|
1152
|
+
};
|
|
1153
|
+
/**
|
|
1154
|
+
* Base invariant:
|
|
1155
|
+
* هر Command دقیقاً متعلق به یک Table است
|
|
1156
|
+
*/
|
|
1157
|
+
interface MoveActiveCellCommand {
|
|
1158
|
+
readonly type: 'MOVE_ACTIVE_CELL';
|
|
1159
|
+
readonly store: string;
|
|
1160
|
+
readonly tableKey: string;
|
|
1161
|
+
readonly rowId: number;
|
|
1162
|
+
readonly columnId: string;
|
|
1163
|
+
readonly direction: 'next' | 'prev';
|
|
1164
|
+
}
|
|
1165
|
+
interface MoveActiveCellVerticalCommand {
|
|
1166
|
+
readonly type: 'MOVE_ACTIVE_CELL_VERTICAL';
|
|
1167
|
+
readonly store: string;
|
|
1168
|
+
readonly tableKey: string;
|
|
1169
|
+
readonly rowId: number;
|
|
1170
|
+
readonly columnId: string;
|
|
1171
|
+
readonly direction: 'up' | 'down';
|
|
1172
|
+
}
|
|
1173
|
+
interface MoveVerticalSelectedRows {
|
|
1174
|
+
readonly type: 'MOVE_VERTICAL_SELECTED_ROWS';
|
|
1175
|
+
readonly tableKey: string;
|
|
1176
|
+
readonly direction: 'up' | 'down';
|
|
1177
|
+
}
|
|
1178
|
+
interface MoveVerticalActiveRow {
|
|
1179
|
+
readonly type: 'MOVE_VERTICAL_ACTIVE_ROW';
|
|
1180
|
+
readonly tableKey: string;
|
|
1181
|
+
readonly direction: 'up' | 'down';
|
|
1182
|
+
}
|
|
1183
|
+
interface ActiveCellCommand {
|
|
1184
|
+
readonly type: 'ACTIVE_CELL';
|
|
1185
|
+
readonly tableKey: string;
|
|
1186
|
+
readonly rowId: number;
|
|
1187
|
+
readonly columnId: string;
|
|
1188
|
+
}
|
|
1189
|
+
interface ActiveRowCommand extends BaseTableCommand {
|
|
1190
|
+
readonly type: 'ACTIVE_ROW';
|
|
1191
|
+
readonly tableKey: string;
|
|
1192
|
+
readonly rowId: number;
|
|
1193
|
+
}
|
|
1194
|
+
interface ActiveFirstCellCommand {
|
|
1195
|
+
readonly type: 'ACTIVATE_FIRST_CELL';
|
|
1196
|
+
readonly tableKey: string;
|
|
1197
|
+
readonly rowId: number;
|
|
1198
|
+
}
|
|
1199
|
+
interface ChangeCellValueCommand extends BaseTableCommand {
|
|
1200
|
+
readonly type: 'CHANGE_CELL_VALUE';
|
|
1201
|
+
readonly rowId: number;
|
|
1202
|
+
readonly columnId: string;
|
|
1203
|
+
readonly newValue: unknown;
|
|
1204
|
+
}
|
|
1205
|
+
interface SaveDescriptionCommand extends BaseTableCommand {
|
|
1206
|
+
readonly type: 'SAVE_DESCRIPTION';
|
|
1207
|
+
readonly rowId: number;
|
|
1208
|
+
readonly flag: boolean;
|
|
1209
|
+
}
|
|
1210
|
+
interface ChangeCellDisplayValueCommand extends BaseTableCommand {
|
|
1211
|
+
readonly type: 'CHANGE_CELL_DISPLAY_VALUE';
|
|
1212
|
+
readonly rowId: number;
|
|
1213
|
+
readonly columnId: string;
|
|
1214
|
+
readonly newValue: string;
|
|
1215
|
+
}
|
|
1216
|
+
interface AddEmptyRowCommand extends BaseTableCommand {
|
|
1217
|
+
readonly type: 'ADD_EMPTY_ROW';
|
|
1218
|
+
readonly autoActivate: boolean;
|
|
1219
|
+
}
|
|
1220
|
+
interface AddNewRowsCommand extends BaseTableCommand {
|
|
1221
|
+
readonly type: 'ADD_NEW_ROWS';
|
|
1222
|
+
readonly detailFieldKey: string;
|
|
1223
|
+
readonly rows: {
|
|
1224
|
+
key: string;
|
|
1225
|
+
value: unknown;
|
|
1226
|
+
display: unknown;
|
|
1227
|
+
}[][];
|
|
1228
|
+
readonly autoActivate?: boolean;
|
|
1229
|
+
}
|
|
1230
|
+
interface DuplicateRowCommand extends BaseTableCommand {
|
|
1231
|
+
readonly type: 'DUPLICATE_ROW';
|
|
1232
|
+
readonly rowId: number;
|
|
1233
|
+
}
|
|
1234
|
+
/**
|
|
1235
|
+
* Clone one source row (clipboard paste). Engine batches these with a shared
|
|
1236
|
+
* correlationId so undo reverses the whole paste unit.
|
|
1237
|
+
*/
|
|
1238
|
+
interface PasteCellsCommand extends BaseTableCommand {
|
|
1239
|
+
readonly type: 'PASTE_CELLS';
|
|
1240
|
+
readonly updates: readonly {
|
|
1241
|
+
rowId: number;
|
|
1242
|
+
columnId: string;
|
|
1243
|
+
rawText: string;
|
|
1244
|
+
}[];
|
|
1245
|
+
}
|
|
1246
|
+
interface PasteRowCommand extends BaseTableCommand {
|
|
1247
|
+
readonly type: 'PASTE_ROW';
|
|
1248
|
+
readonly sourceRowId: number;
|
|
1249
|
+
/** When set (pasteInsert), place the clone relative to this row. */
|
|
1250
|
+
readonly placeAtRowId?: number;
|
|
1251
|
+
}
|
|
1252
|
+
interface DeleteRowCommand extends BaseTableCommand {
|
|
1253
|
+
readonly type: 'ROW_DELETED';
|
|
1254
|
+
readonly rowId: number;
|
|
1255
|
+
}
|
|
1256
|
+
/** Undo-stack redo: re-insert a previously added row with original identity/values. */
|
|
1257
|
+
interface RestoreAddedRowCommand extends BaseTableCommand {
|
|
1258
|
+
readonly type: 'RESTORE_ADDED_ROW';
|
|
1259
|
+
readonly rowId: number;
|
|
1260
|
+
readonly cells: Readonly<Record<string, {
|
|
1261
|
+
readonly value: unknown;
|
|
1262
|
+
readonly display?: unknown;
|
|
1263
|
+
readonly originalValue?: unknown;
|
|
1264
|
+
}>>;
|
|
1265
|
+
readonly collection?: string;
|
|
1266
|
+
readonly isSaveDescription?: boolean;
|
|
1267
|
+
}
|
|
1268
|
+
interface DeleteRowsCommand extends BaseTableCommand {
|
|
1269
|
+
readonly type: 'ROWS_DELETED';
|
|
1270
|
+
/** Selected row ids (may include rows not in the RAM page window). Filled by engine if omitted. */
|
|
1271
|
+
readonly rowIds?: number[];
|
|
1272
|
+
}
|
|
1273
|
+
interface ExpandRowCommand {
|
|
1274
|
+
readonly type: 'ROW_EXPANDED';
|
|
1275
|
+
readonly tableKey: string;
|
|
1276
|
+
readonly rowId: number;
|
|
1277
|
+
readonly value: boolean;
|
|
1278
|
+
}
|
|
1279
|
+
interface SelectRowCommand {
|
|
1280
|
+
readonly type: 'ROW_SELECTED';
|
|
1281
|
+
readonly tableKey: string;
|
|
1282
|
+
readonly rowId: number;
|
|
1283
|
+
}
|
|
1284
|
+
interface ToggleRowSelectionCommand {
|
|
1285
|
+
readonly type: "ROW_SELECTION_TOGGLED";
|
|
1286
|
+
readonly tableKey: string;
|
|
1287
|
+
readonly rowId: number;
|
|
1288
|
+
}
|
|
1289
|
+
interface ToggleRowExpandCommand {
|
|
1290
|
+
readonly type: 'ROW_EXPAND_TOGGLED';
|
|
1291
|
+
readonly tableKey: string;
|
|
1292
|
+
readonly rowId: number;
|
|
1293
|
+
}
|
|
1294
|
+
interface SelectRangeCommand {
|
|
1295
|
+
readonly type: "ROW_RANGE_SELECTED";
|
|
1296
|
+
readonly tableKey: string;
|
|
1297
|
+
readonly rowId: number;
|
|
1298
|
+
}
|
|
1299
|
+
interface SelectActiveRowToLastCommand {
|
|
1300
|
+
readonly type: "SELECT_FROM_ACTIVE_TO_LAST";
|
|
1301
|
+
readonly tableKey: string;
|
|
1302
|
+
readonly anchorRowId: number;
|
|
1303
|
+
}
|
|
1304
|
+
interface RowReorderedCommand extends BaseTableCommand {
|
|
1305
|
+
readonly type: 'ROW_REORDERED';
|
|
1306
|
+
readonly draggedRowId: number;
|
|
1307
|
+
readonly droppedRowId: number;
|
|
1308
|
+
readonly position: 'before' | 'after';
|
|
1309
|
+
}
|
|
1310
|
+
interface SelectAllRowsCommand {
|
|
1311
|
+
readonly type: 'TOGGLE_SELECT_ALL_ROWS';
|
|
1312
|
+
readonly store: string;
|
|
1313
|
+
readonly tableKey: string;
|
|
1314
|
+
}
|
|
1315
|
+
interface SelectPageRowsCommand {
|
|
1316
|
+
readonly type: 'TOGGLE_SELECT_PAGE_ROWS';
|
|
1317
|
+
readonly tableKey: string;
|
|
1318
|
+
}
|
|
1319
|
+
interface ClearRowSelectionCommand {
|
|
1320
|
+
readonly type: 'CLEAR_ROW_SELECTION';
|
|
1321
|
+
readonly tableKey: string;
|
|
1322
|
+
}
|
|
1323
|
+
interface CollapseAllRowsCommand {
|
|
1324
|
+
readonly type: 'COLLAPSE_ALL_ROWS';
|
|
1325
|
+
readonly tableKey: string;
|
|
1326
|
+
}
|
|
1327
|
+
interface ColumnReorderedCommand extends BaseTableCommand {
|
|
1328
|
+
readonly type: 'COLUMN_REORDERED';
|
|
1329
|
+
readonly sourceIndex: number;
|
|
1330
|
+
readonly destIndex: number;
|
|
1331
|
+
}
|
|
1332
|
+
interface DeleteTableCommand extends BaseTableCommand {
|
|
1333
|
+
readonly type: 'TABLE_DELETED';
|
|
1334
|
+
}
|
|
1335
|
+
interface SetActiveCollectionCommand extends BaseTableCommand {
|
|
1336
|
+
readonly type: 'SET_ACTIVE_COLLECTION';
|
|
1337
|
+
readonly activeCollection: string;
|
|
1338
|
+
}
|
|
1339
|
+
interface ResetTableCommand extends BaseTableCommand {
|
|
1340
|
+
readonly type: 'TABLE_RESET';
|
|
1341
|
+
readonly rowId: string;
|
|
1342
|
+
}
|
|
1343
|
+
interface RegisterTableCommand extends BaseTableCommand {
|
|
1344
|
+
readonly type: 'TABLE_REGISTERED';
|
|
1345
|
+
readonly store: string;
|
|
1346
|
+
readonly table: Table;
|
|
1347
|
+
}
|
|
1348
|
+
interface DisposeTableCommand extends BaseTableCommand {
|
|
1349
|
+
readonly type: 'TABLE_DISPOSED';
|
|
1350
|
+
}
|
|
1351
|
+
interface ChangeTableActionCommand extends BaseTableCommand {
|
|
1352
|
+
readonly type: 'SET_TABLE_ACTION';
|
|
1353
|
+
action: TableActions;
|
|
1354
|
+
}
|
|
1355
|
+
interface ChangePageCommand extends BaseTableCommand {
|
|
1356
|
+
readonly type: 'CHANGE_PAGE';
|
|
1357
|
+
readonly page: number;
|
|
1358
|
+
}
|
|
1359
|
+
interface ChangePageSizeCommand extends BaseTableCommand {
|
|
1360
|
+
readonly type: 'CHANGE_PAGE_SIZE';
|
|
1361
|
+
readonly pageSize: number;
|
|
1362
|
+
}
|
|
1363
|
+
interface ApplyDynamicProjectionCommand extends BaseTableCommand {
|
|
1364
|
+
readonly type: 'APPLY_DYNAMIC_PROJECTION';
|
|
1365
|
+
readonly tableKey: string;
|
|
1366
|
+
readonly rowId: number;
|
|
1367
|
+
readonly columnId: string;
|
|
1368
|
+
}
|
|
1369
|
+
/**
|
|
1370
|
+
* اعمال مجدد شروط visibility ریموت برای یک سطر مشخص (مثلاً هنگام active شدن سطر
|
|
1371
|
+
* در حالت ویرایش) بدون تغییر RowState یا پاککردن سلولهای وابسته.
|
|
1372
|
+
*/
|
|
1373
|
+
interface ApplyRowVisibilityCommand extends BaseTableCommand {
|
|
1374
|
+
readonly type: 'APPLY_ROW_VISIBILITY';
|
|
1375
|
+
readonly tableKey: string;
|
|
1376
|
+
readonly rowId: number;
|
|
1377
|
+
}
|
|
1378
|
+
interface SetGridSearchCommand {
|
|
1379
|
+
readonly type: 'SET_GRID_SEARCH';
|
|
1380
|
+
readonly tableKey: string;
|
|
1381
|
+
readonly search: GridSearchState;
|
|
1382
|
+
}
|
|
1383
|
+
interface SetMobileEditorCommand {
|
|
1384
|
+
readonly type: 'SET_MOBILE_EDITOR';
|
|
1385
|
+
readonly tableKey: string;
|
|
1386
|
+
readonly editor: MobileEditorState;
|
|
1387
|
+
}
|
|
1388
|
+
interface ResizeColumnCommand {
|
|
1389
|
+
readonly type: 'RESIZE_COLUMN';
|
|
1390
|
+
readonly tableKey: string;
|
|
1391
|
+
readonly columnId: string;
|
|
1392
|
+
readonly width: number;
|
|
1393
|
+
}
|
|
1394
|
+
interface SetColumnVisibleCommand {
|
|
1395
|
+
readonly type: 'SET_COLUMN_VISIBLE';
|
|
1396
|
+
readonly tableKey: string;
|
|
1397
|
+
readonly columnId: string;
|
|
1398
|
+
readonly visible: boolean;
|
|
1399
|
+
}
|
|
1400
|
+
interface ToggleColumnGroupCommand {
|
|
1401
|
+
readonly type: 'TOGGLE_COLUMN_GROUP';
|
|
1402
|
+
readonly tableKey: string;
|
|
1403
|
+
readonly groupId: string;
|
|
1404
|
+
}
|
|
1405
|
+
interface SetColumnPinnedCommand {
|
|
1406
|
+
readonly type: 'SET_COLUMN_PIN';
|
|
1407
|
+
readonly tableKey: string;
|
|
1408
|
+
readonly columnId: string;
|
|
1409
|
+
readonly pinned: 'start' | 'end' | null;
|
|
1410
|
+
}
|
|
1411
|
+
interface SetSortModelCommand {
|
|
1412
|
+
readonly type: 'SET_SORT_MODEL';
|
|
1413
|
+
readonly tableKey: string;
|
|
1414
|
+
/** Empty / omit fields cleared by host ⇒ document `index` order. */
|
|
1415
|
+
readonly sortModel: readonly {
|
|
1416
|
+
readonly colId: string;
|
|
1417
|
+
readonly sort: 'asc' | 'desc';
|
|
1418
|
+
}[];
|
|
1419
|
+
}
|
|
1420
|
+
interface SetQuickFilterTextCommand {
|
|
1421
|
+
readonly type: 'SET_QUICK_FILTER_TEXT';
|
|
1422
|
+
readonly tableKey: string;
|
|
1423
|
+
/** Empty string clears the filter (all rows visible). */
|
|
1424
|
+
readonly quickFilterText: string;
|
|
1425
|
+
}
|
|
1426
|
+
interface SetFilterModelCommand {
|
|
1427
|
+
readonly type: 'SET_FILTER_MODEL';
|
|
1428
|
+
readonly tableKey: string;
|
|
1429
|
+
/** Empty object clears all column filters. */
|
|
1430
|
+
readonly filterModel: FilterModel;
|
|
1431
|
+
}
|
|
1432
|
+
interface SetRowGroupColumnsCommand {
|
|
1433
|
+
readonly type: 'SET_ROW_GROUP_COLUMNS';
|
|
1434
|
+
readonly tableKey: string;
|
|
1435
|
+
/** Only the first entry is active in 0.12.0 (RFC-002). */
|
|
1436
|
+
readonly columns: readonly string[];
|
|
1437
|
+
}
|
|
1438
|
+
interface SetGroupDefaultExpandedCommand {
|
|
1439
|
+
readonly type: 'SET_GROUP_DEFAULT_EXPANDED';
|
|
1440
|
+
readonly tableKey: string;
|
|
1441
|
+
readonly expanded: boolean;
|
|
1442
|
+
}
|
|
1443
|
+
interface ToggleRowGroupCommand {
|
|
1444
|
+
readonly type: 'TOGGLE_ROW_GROUP';
|
|
1445
|
+
readonly tableKey: string;
|
|
1446
|
+
/** `normalizeGroupKey` of the group. */
|
|
1447
|
+
readonly groupKey: string;
|
|
1448
|
+
}
|
|
1449
|
+
type EngineTableCommand = SelectActiveRowToLastCommand | SelectRangeCommand | ToggleRowExpandCommand | SelectRowCommand | CollapseAllRowsCommand | RegisterTableCommand | DisposeTableCommand | DeleteRowsCommand | ToggleRowSelectionCommand | SelectAllRowsCommand | SelectPageRowsCommand | ClearRowSelectionCommand | ActiveCellCommand | ActiveRowCommand | MoveActiveCellCommand | MoveActiveCellVerticalCommand | MoveVerticalSelectedRows | MoveVerticalActiveRow | ActiveFirstCellCommand | ExpandRowCommand | ChangeTableActionCommand | SetGridSearchCommand | SetMobileEditorCommand | ResizeColumnCommand | SetColumnVisibleCommand | ToggleColumnGroupCommand | SetColumnPinnedCommand | SetSortModelCommand | SetQuickFilterTextCommand | SetFilterModelCommand | SetRowGroupColumnsCommand | SetGroupDefaultExpandedCommand | ToggleRowGroupCommand;
|
|
1450
|
+
type ApplicationTableCommand = ChangeCellValueCommand | SaveDescriptionCommand | ChangeCellDisplayValueCommand | AddEmptyRowCommand | AddNewRowsCommand | DuplicateRowCommand | PasteCellsCommand | PasteRowCommand | DeleteRowCommand | RestoreAddedRowCommand | DeleteTableCommand | SetActiveCollectionCommand | ResetTableCommand | RowReorderedCommand | ColumnReorderedCommand | ChangePageCommand | ChangePageSizeCommand | ApplyDynamicProjectionCommand | ApplyRowVisibilityCommand | DeleteRowsCommand;
|
|
1451
|
+
type TableCommand = EngineTableCommand | ApplicationTableCommand;
|
|
1452
|
+
|
|
1453
|
+
interface TableRepository {
|
|
1454
|
+
getById(store: string, tableKey: string): Promise<Table>;
|
|
1455
|
+
save(store: string, table: Table): Promise<void>;
|
|
1456
|
+
delete(store: string, tableKey: string): Promise<void>;
|
|
1457
|
+
resetTable(store: string, tableKey: string): Promise<void>;
|
|
1458
|
+
exists(store: string, tableKey: string): Promise<boolean>;
|
|
1459
|
+
getFromDbById?(store: string, tableKey: string): Promise<Table>;
|
|
1460
|
+
}
|
|
1461
|
+
/** Plain serialized row as streamed from IndexedDB (no domain objects). */
|
|
1462
|
+
interface PersistedRowRecord {
|
|
1463
|
+
rowId: number;
|
|
1464
|
+
collection: string;
|
|
1465
|
+
sortIndex: number;
|
|
1466
|
+
rowState: string;
|
|
1467
|
+
/** colId → { value, originalValue, display } — plain, no domain objects */
|
|
1468
|
+
cells: Record<string, {
|
|
1469
|
+
value: unknown;
|
|
1470
|
+
originalValue: unknown;
|
|
1471
|
+
display: unknown;
|
|
1472
|
+
}>;
|
|
1473
|
+
}
|
|
1474
|
+
/**
|
|
1475
|
+
* Page-window repository ("paged IndexedDB" persistence mode).
|
|
1476
|
+
*
|
|
1477
|
+
* IndexedDB is the single source of truth for ALL rows; RAM holds exactly one
|
|
1478
|
+
* page window (Memory Iron Rule: heap is O(batch), never O(total rows)).
|
|
1479
|
+
* Opt-in via `persistence: 'paged-idb'`; the default event-sourced
|
|
1480
|
+
* repositories do NOT implement these methods.
|
|
1481
|
+
*/
|
|
1482
|
+
interface WindowedTableRepository extends TableRepository {
|
|
1483
|
+
/**
|
|
1484
|
+
* Persist metadata + upsert rows currently held in the Table (page window).
|
|
1485
|
+
* Must NOT delete other pages' rows in IndexedDB.
|
|
1486
|
+
*/
|
|
1487
|
+
save(store: string, table: Table): Promise<void>;
|
|
1488
|
+
/**
|
|
1489
|
+
* Replace IndexedDB source of truth with every row on `table`, then callers
|
|
1490
|
+
* should `loadPage` so RAM only keeps one page.
|
|
1491
|
+
*/
|
|
1492
|
+
replaceAll(store: string, table: Table): Promise<void>;
|
|
1493
|
+
/** Flush pending IDB writes, load one page into RAM, return that window. */
|
|
1494
|
+
loadPage(store: string, tableKey: string, page: number, pageSize?: number): Promise<Table | null>;
|
|
1495
|
+
/**
|
|
1496
|
+
* Switch the persisted active collection (page resets to 1) and return a
|
|
1497
|
+
* Table whose RAM window holds page 1 of the NEW collection only.
|
|
1498
|
+
* Rows of other collections must remain untouched in IndexedDB.
|
|
1499
|
+
*/
|
|
1500
|
+
setActiveCollection(store: string, tableKey: string, collection: string): Promise<Table | null>;
|
|
1501
|
+
/**
|
|
1502
|
+
* @deprecated Legacy: hydrates the whole dataset. Use `iterateRowRecords`.
|
|
1503
|
+
* All rows from IndexedDB (source of truth).
|
|
1504
|
+
*/
|
|
1505
|
+
getAllRows(store: string, tableKey: string, collectionScope?: CollectionScope): Promise<Row[]>;
|
|
1506
|
+
/**
|
|
1507
|
+
* All row ids from IndexedDB (source of truth), without hydrating cells.
|
|
1508
|
+
* Used for select-all across the full dataset (not just the RAM page window).
|
|
1509
|
+
*/
|
|
1510
|
+
getAllRowIds(store: string, tableKey: string, collectionScope?: CollectionScope): Promise<number[]>;
|
|
1511
|
+
/**
|
|
1512
|
+
* Stream serialized row records from IndexedDB in bounded batches via a
|
|
1513
|
+
* cursor over the byTableCollectionSort index (ordered, no full load).
|
|
1514
|
+
* The heap at any moment holds one batch — never the whole dataset.
|
|
1515
|
+
* Return false from onBatch to stop early.
|
|
1516
|
+
*/
|
|
1517
|
+
iterateRowRecords(store: string, tableKey: string, collectionScope: CollectionScope, onBatch: (records: PersistedRowRecord[],
|
|
1518
|
+
/** Ordinal (0-based, collection-sorted position) of the batch's first record */
|
|
1519
|
+
ordinalBase: number) => Promise<boolean | void>, batchSize?: number): Promise<void>;
|
|
1520
|
+
/** Physically remove row records from IndexedDB (hard delete). */
|
|
1521
|
+
removeRows(store: string, tableKey: string, rowIds: number[]): Promise<void>;
|
|
1522
|
+
/**
|
|
1523
|
+
* Bulk soft/hard delete applied directly to persisted row records
|
|
1524
|
+
* (cursor-based — heap stays O(1)):
|
|
1525
|
+
* - `Added` rows are hard-removed from the store
|
|
1526
|
+
* - others get rowState = Deleted written on the record (cursor.update)
|
|
1527
|
+
* - already-Deleted rows are left untouched (no restore on bulk delete)
|
|
1528
|
+
*/
|
|
1529
|
+
softDeleteRows(store: string, tableKey: string, rowIds: number[]): Promise<{
|
|
1530
|
+
softDeleted: number;
|
|
1531
|
+
hardRemoved: number;
|
|
1532
|
+
/** Non-deleted rows remaining in the active collection after the delete. */
|
|
1533
|
+
remaining: number;
|
|
1534
|
+
}>;
|
|
1535
|
+
/** Drop RAM window only; IndexedDB untouched. */
|
|
1536
|
+
clearLocal(store: string, tableKey: string): void;
|
|
1537
|
+
/** Await queued IndexedDB writes for this table. */
|
|
1538
|
+
flush(store: string, tableKey: string): Promise<void>;
|
|
1539
|
+
}
|
|
1540
|
+
/** Type guard: true only for page-window repositories (`persistence: 'paged-idb'`). */
|
|
1541
|
+
declare function isWindowedRepository(repo: TableRepository): repo is WindowedTableRepository;
|
|
1542
|
+
|
|
1543
|
+
interface BaseTableEvent {
|
|
1544
|
+
readonly tableId: string;
|
|
1545
|
+
readonly type: string;
|
|
1546
|
+
}
|
|
1547
|
+
interface CellChangedEvent extends BaseTableEvent {
|
|
1548
|
+
type: 'CELL_CHANGED';
|
|
1549
|
+
rowId: number;
|
|
1550
|
+
columnId: string;
|
|
1551
|
+
newValue: unknown;
|
|
1552
|
+
previousValue: unknown;
|
|
1553
|
+
}
|
|
1554
|
+
interface DynamicProjectionEvent extends BaseTableEvent {
|
|
1555
|
+
type: 'DYNAMIC_PROJECTION_DONE';
|
|
1556
|
+
rowId: number;
|
|
1557
|
+
columnId: string;
|
|
1558
|
+
}
|
|
1559
|
+
interface CellDisplayChangedEvent extends BaseTableEvent {
|
|
1560
|
+
type: 'CELL_DISPLAY_CHANGED';
|
|
1561
|
+
rowId: number;
|
|
1562
|
+
columnId: string;
|
|
1563
|
+
newValue: unknown;
|
|
1564
|
+
}
|
|
1565
|
+
interface RowAddedEvent extends BaseTableEvent {
|
|
1566
|
+
type: 'ROW_ADDED';
|
|
1567
|
+
rowId: string;
|
|
1568
|
+
}
|
|
1569
|
+
interface NewRowAddedEvent extends BaseTableEvent {
|
|
1570
|
+
type: 'NEW_ROW_ADDED';
|
|
1571
|
+
rowId: string;
|
|
1572
|
+
}
|
|
1573
|
+
interface RowDeletedEvent extends BaseTableEvent {
|
|
1574
|
+
type: 'ROW_DELETED';
|
|
1575
|
+
rowId: string;
|
|
1576
|
+
}
|
|
1577
|
+
interface NewRowRemovedEvent extends BaseTableEvent {
|
|
1578
|
+
type: 'NEW_ROW_REMOVED';
|
|
1579
|
+
rowId: string;
|
|
1580
|
+
}
|
|
1581
|
+
interface RowRestoredEvent extends BaseTableEvent {
|
|
1582
|
+
type: 'ROW_RESTORED';
|
|
1583
|
+
rowId: string;
|
|
1584
|
+
}
|
|
1585
|
+
interface RowReorderedEvent extends BaseTableEvent {
|
|
1586
|
+
type: 'ROW_REORDERED';
|
|
1587
|
+
sourceIndex: number;
|
|
1588
|
+
destIndex: number;
|
|
1589
|
+
}
|
|
1590
|
+
interface RowDescriptionSaved extends BaseTableEvent {
|
|
1591
|
+
type: 'ROW_DESCRIPTION_SAVED';
|
|
1592
|
+
rowId: number;
|
|
1593
|
+
description: boolean;
|
|
1594
|
+
}
|
|
1595
|
+
interface ColumnReorderedEvent extends BaseTableEvent {
|
|
1596
|
+
type: 'COLUMN_REORDERED';
|
|
1597
|
+
sourceIndex: number;
|
|
1598
|
+
destIndex: number;
|
|
1599
|
+
}
|
|
1600
|
+
interface UnitColumnAddedEvent extends BaseTableEvent {
|
|
1601
|
+
type: 'UNIT_COLUMN_ADDED';
|
|
1602
|
+
reason: string;
|
|
1603
|
+
details?: unknown;
|
|
1604
|
+
}
|
|
1605
|
+
interface PageChangedEvent extends BaseTableEvent {
|
|
1606
|
+
type: 'PAGE_CHANGED';
|
|
1607
|
+
page: number;
|
|
1608
|
+
}
|
|
1609
|
+
interface PageSizeChangedEvent extends BaseTableEvent {
|
|
1610
|
+
type: 'PAGE_SIZE_CHANGED';
|
|
1611
|
+
tableId: string;
|
|
1612
|
+
pageSize: number;
|
|
1613
|
+
}
|
|
1614
|
+
interface TableDeletedEvent extends BaseTableEvent {
|
|
1615
|
+
type: 'TABLE_DELETED';
|
|
1616
|
+
tableId: string;
|
|
1617
|
+
}
|
|
1618
|
+
interface TableResetEvent extends BaseTableEvent {
|
|
1619
|
+
type: 'TABLE_RESET';
|
|
1620
|
+
tableId: string;
|
|
1621
|
+
}
|
|
1622
|
+
interface ActiveCollectionChangedEvent extends BaseTableEvent {
|
|
1623
|
+
type: 'ACTIVE_COLLECTION_CHANGED';
|
|
1624
|
+
tableId: string;
|
|
1625
|
+
}
|
|
1626
|
+
interface RowsLoadedEvent extends BaseTableEvent {
|
|
1627
|
+
type: 'ROWS_LOADED';
|
|
1628
|
+
count: number;
|
|
1629
|
+
}
|
|
1630
|
+
interface DynamicDataRequestedEvent extends BaseTableEvent {
|
|
1631
|
+
type: 'DYNAMIC_DATA_REQUESTED';
|
|
1632
|
+
requestId: string;
|
|
1633
|
+
sourceColumn: string;
|
|
1634
|
+
value: unknown;
|
|
1635
|
+
}
|
|
1636
|
+
interface ValidationFailedEvent extends BaseTableEvent {
|
|
1637
|
+
type: 'VALIDATION_FAILED';
|
|
1638
|
+
reason: string;
|
|
1639
|
+
details?: unknown;
|
|
1640
|
+
}
|
|
1641
|
+
type TableEvent = CellChangedEvent | DynamicProjectionEvent | CellDisplayChangedEvent | RowAddedEvent | NewRowAddedEvent | RowDeletedEvent | NewRowRemovedEvent | RowRestoredEvent | RowReorderedEvent | RowDescriptionSaved | ColumnReorderedEvent | UnitColumnAddedEvent | PageChangedEvent | PageSizeChangedEvent | RowsLoadedEvent | DynamicDataRequestedEvent | ValidationFailedEvent | TableDeletedEvent | ActiveCollectionChangedEvent | TableResetEvent;
|
|
1642
|
+
|
|
1643
|
+
type DynamicConfig = {
|
|
1644
|
+
columnMeta: Map<string, ColumnSchema>;
|
|
1645
|
+
remoteApi: RemoteApi;
|
|
1646
|
+
};
|
|
1647
|
+
declare class ChangeCellValueHandler {
|
|
1648
|
+
private readonly repo;
|
|
1649
|
+
private readonly audit;
|
|
1650
|
+
private readonly permissionPolicy;
|
|
1651
|
+
private readonly dynamic?;
|
|
1652
|
+
constructor(repo: TableRepository, audit: AuditLogger, permissionPolicy: PermissionPolicy, dynamic?: DynamicConfig | undefined);
|
|
1653
|
+
execute(command: ChangeCellValueCommand, actor: Actor$1): Promise<TableEvent[]>;
|
|
1654
|
+
private applyRemoteVisibilityRules;
|
|
1655
|
+
private applyComputedColumns;
|
|
1656
|
+
private validateCellValue;
|
|
1657
|
+
private applyDynamicProjection;
|
|
1658
|
+
}
|
|
1659
|
+
declare class ChangeCellDisplayValueHandler {
|
|
1660
|
+
private readonly repo;
|
|
1661
|
+
private readonly audit;
|
|
1662
|
+
private readonly permissionPolicy;
|
|
1663
|
+
constructor(repo: TableRepository, audit: AuditLogger, permissionPolicy: PermissionPolicy);
|
|
1664
|
+
execute(command: ChangeCellDisplayValueCommand, actor: Actor$1): Promise<TableEvent[]>;
|
|
1665
|
+
}
|
|
1666
|
+
declare class SaveDescriptionHandler {
|
|
1667
|
+
private readonly repo;
|
|
1668
|
+
private readonly audit;
|
|
1669
|
+
private readonly permissionPolicy;
|
|
1670
|
+
constructor(repo: TableRepository, audit: AuditLogger, permissionPolicy: PermissionPolicy);
|
|
1671
|
+
execute(command: SaveDescriptionCommand, actor: Actor$1): Promise<TableEvent[]>;
|
|
1672
|
+
}
|
|
1673
|
+
declare class ApplyDynamicProjectionHandler {
|
|
1674
|
+
private readonly repo;
|
|
1675
|
+
private readonly audit;
|
|
1676
|
+
private readonly permissionPolicy;
|
|
1677
|
+
private readonly dynamic?;
|
|
1678
|
+
constructor(repo: TableRepository, audit: AuditLogger, permissionPolicy: PermissionPolicy, dynamic?: DynamicConfig | undefined);
|
|
1679
|
+
execute(command: ApplyDynamicProjectionCommand, actor: Actor$1): Promise<TableEvent[]>;
|
|
1680
|
+
private applyRemoteVisibilityRules;
|
|
1681
|
+
private applyComputedColumns;
|
|
1682
|
+
private validateCellValue;
|
|
1683
|
+
private applyDynamicProjection;
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
declare class DeleteRowsCommandHandler {
|
|
1687
|
+
private readonly repo;
|
|
1688
|
+
private readonly audit;
|
|
1689
|
+
private readonly permission;
|
|
1690
|
+
constructor(repo: WindowedTableRepository, audit: AuditLogger, permission: PermissionPolicy);
|
|
1691
|
+
/**
|
|
1692
|
+
* Bulk delete — never toggles restore:
|
|
1693
|
+
* - `Added` → hard-remove from IndexedDB
|
|
1694
|
+
* - otherwise → `rowState = Deleted` (soft; قابل برگرداندن با حذف تکی)
|
|
1695
|
+
* Already-`Deleted` rows stay deleted.
|
|
1696
|
+
*/
|
|
1697
|
+
execute(command: DeleteRowsCommand, actor: Actor$1): Promise<{
|
|
1698
|
+
removed: number;
|
|
1699
|
+
softDeleted: number;
|
|
1700
|
+
remaining: number;
|
|
1701
|
+
} | null>;
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
/**
|
|
1705
|
+
* هنگام فعالشدن (active) شدن یک سطر اجرا میشود:
|
|
1706
|
+
* برای هر ستون دارای resolveOn که سلولش مقدار دارد، applyRemoteVisibilityRules
|
|
1707
|
+
* را (بدون پاککردن سلولهای وابسته) صدا میزند تا visibilityCondition سطر فعال
|
|
1708
|
+
* از سرویس ریموت بهروز شود. مقدار RowState سطر را تغییر نمیدهد.
|
|
1709
|
+
*/
|
|
1710
|
+
declare class ApplyRowVisibilityHandler {
|
|
1711
|
+
private readonly repo;
|
|
1712
|
+
private readonly audit;
|
|
1713
|
+
private readonly permissionPolicy;
|
|
1714
|
+
private readonly dynamic?;
|
|
1715
|
+
/**
|
|
1716
|
+
* Dedupe guard: آخرین امضای (row + کالکشن + مقادیر ستونهای resolveOn) که
|
|
1717
|
+
* برایش سر ریموت صدا زده شد. بدون این، دو مسیر مستقل (کلیک سطر →
|
|
1718
|
+
* setActiveRow و کلیک سلول → setActiveCell) و رفرشهای متوالی، همان API را
|
|
1719
|
+
* چند بار صدا میزدند. وقتی مقادیر عوض شود امضای جدید است و API دوباره
|
|
1720
|
+
* صدا زده میشود.
|
|
1721
|
+
*/
|
|
1722
|
+
private lastSignature;
|
|
1723
|
+
constructor(repo: TableRepository, audit: AuditLogger, permissionPolicy: PermissionPolicy, dynamic?: DynamicConfig | undefined);
|
|
1724
|
+
execute(command: ApplyRowVisibilityCommand, actor: Actor$1): Promise<TableEvent[]>;
|
|
1725
|
+
private applyRemoteVisibilityRules;
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
/**
|
|
1729
|
+
* Batch clipboard paste (PR-107): one repo save, many CELL_CHANGED events.
|
|
1730
|
+
*/
|
|
1731
|
+
declare class PasteCellsCommandHandler {
|
|
1732
|
+
private readonly repo;
|
|
1733
|
+
private readonly audit;
|
|
1734
|
+
private readonly permissionPolicy;
|
|
1735
|
+
constructor(repo: TableRepository, audit: AuditLogger, permissionPolicy: PermissionPolicy);
|
|
1736
|
+
execute(command: PasteCellsCommand, actor: Actor$1): Promise<TableEvent[]>;
|
|
1737
|
+
private validateCellValue;
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
declare class AddNewRowCommandHandler {
|
|
1741
|
+
private readonly repo;
|
|
1742
|
+
private readonly audit;
|
|
1743
|
+
private readonly permission;
|
|
1744
|
+
constructor(repo: TableRepository, audit: AuditLogger, permission: PermissionPolicy);
|
|
1745
|
+
execute(command: AddEmptyRowCommand, actor: Actor$1): Promise<RowAdded | null>;
|
|
1746
|
+
}
|
|
1747
|
+
declare class AddNewRowsCommandHandler {
|
|
1748
|
+
private readonly repo;
|
|
1749
|
+
private readonly audit;
|
|
1750
|
+
private readonly permission;
|
|
1751
|
+
constructor(repo: TableRepository, audit: AuditLogger, permission: PermissionPolicy);
|
|
1752
|
+
execute(command: AddNewRowsCommand, actor: Actor$1): Promise<RowAdded[] | null>;
|
|
1753
|
+
}
|
|
1754
|
+
declare class PasteRowCommandHandler {
|
|
1755
|
+
private readonly repo;
|
|
1756
|
+
private readonly audit;
|
|
1757
|
+
private readonly permission;
|
|
1758
|
+
constructor(repo: TableRepository, audit: AuditLogger, permission: PermissionPolicy);
|
|
1759
|
+
execute(command: PasteRowCommand, actor: Actor$1): Promise<RowAdded | null>;
|
|
1760
|
+
}
|
|
1761
|
+
declare class DuplicateRowCommandHandler {
|
|
1762
|
+
private readonly repo;
|
|
1763
|
+
private readonly audit;
|
|
1764
|
+
private readonly permission;
|
|
1765
|
+
constructor(repo: TableRepository, audit: AuditLogger, permission: PermissionPolicy);
|
|
1766
|
+
execute(command: DuplicateRowCommand, actor: Actor$1): Promise<RowAdded | null>;
|
|
1767
|
+
}
|
|
1768
|
+
declare class DeleteRowCommandHandler {
|
|
1769
|
+
private readonly repo;
|
|
1770
|
+
private readonly audit;
|
|
1771
|
+
private readonly permission;
|
|
1772
|
+
constructor(repo: TableRepository, audit: AuditLogger, permission: PermissionPolicy);
|
|
1773
|
+
execute(command: DeleteRowCommand, actor: Actor$1): Promise<RowDeleted | RowRemoved | MinimumRowConstraintViolated | RowRestored | null>;
|
|
1774
|
+
}
|
|
1775
|
+
declare class RestoreAddedRowCommandHandler {
|
|
1776
|
+
private readonly repo;
|
|
1777
|
+
private readonly audit;
|
|
1778
|
+
private readonly permission;
|
|
1779
|
+
constructor(repo: TableRepository, audit: AuditLogger, permission: PermissionPolicy);
|
|
1780
|
+
execute(command: RestoreAddedRowCommand, actor: Actor$1): Promise<RowAdded | null>;
|
|
1781
|
+
}
|
|
1782
|
+
declare class ReorderRowCommandHandler {
|
|
1783
|
+
private readonly repo;
|
|
1784
|
+
private readonly audit;
|
|
1785
|
+
private readonly permission;
|
|
1786
|
+
constructor(repo: TableRepository, audit: AuditLogger, permission: PermissionPolicy);
|
|
1787
|
+
execute(command: RowReorderedCommand, actor: Actor$1): Promise<RowReordered | null>;
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
declare class ChangePageCommandHandler {
|
|
1791
|
+
private readonly repo;
|
|
1792
|
+
private readonly audit;
|
|
1793
|
+
constructor(repo: TableRepository, audit: AuditLogger);
|
|
1794
|
+
execute(command: ChangePageCommand, actor: Actor$1): Promise<TableEvent[]>;
|
|
1795
|
+
}
|
|
1796
|
+
declare class ChangePageSizeCommandHandler {
|
|
1797
|
+
private readonly repo;
|
|
1798
|
+
private readonly audit;
|
|
1799
|
+
constructor(repo: TableRepository, audit: AuditLogger);
|
|
1800
|
+
execute(command: ChangePageSizeCommand, actor: Actor$1): Promise<TableEvent[]>;
|
|
1801
|
+
}
|
|
1802
|
+
declare class DeleteTableCommandHandler {
|
|
1803
|
+
private readonly repo;
|
|
1804
|
+
private readonly audit;
|
|
1805
|
+
private readonly permissionPolicy;
|
|
1806
|
+
constructor(repo: TableRepository, audit: AuditLogger, permissionPolicy: PermissionPolicy);
|
|
1807
|
+
execute(command: DeleteTableCommand, actor: Actor$1): Promise<TableEvent[]>;
|
|
1808
|
+
}
|
|
1809
|
+
declare class ResetTableCommandHandler {
|
|
1810
|
+
private readonly repo;
|
|
1811
|
+
private readonly audit;
|
|
1812
|
+
private readonly permissionPolicy;
|
|
1813
|
+
constructor(repo: TableRepository, audit: AuditLogger, permissionPolicy: PermissionPolicy);
|
|
1814
|
+
execute(command: ResetTableCommand, actor: Actor$1): Promise<TableEvent[]>;
|
|
1815
|
+
}
|
|
1816
|
+
declare class SetActiveCollectionCommandHandler {
|
|
1817
|
+
private readonly repo;
|
|
1818
|
+
private readonly audit;
|
|
1819
|
+
constructor(repo: TableRepository, audit: AuditLogger);
|
|
1820
|
+
private applyVisibility;
|
|
1821
|
+
execute(command: SetActiveCollectionCommand, actor: Actor$1): Promise<TableEvent[]>;
|
|
1822
|
+
private handleSetActiveError;
|
|
1823
|
+
}
|
|
1824
|
+
declare class ReorderColumnCommandHandler {
|
|
1825
|
+
private readonly repo;
|
|
1826
|
+
private readonly audit;
|
|
1827
|
+
private readonly permission;
|
|
1828
|
+
constructor(repo: TableRepository, audit: AuditLogger, permission: PermissionPolicy);
|
|
1829
|
+
execute(command: ColumnReorderedCommand, actor: Actor$1): Promise<TableEvent[]>;
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
interface GridEvent<TType extends string = string, TPayload = unknown> {
|
|
1833
|
+
readonly eventId: string;
|
|
1834
|
+
readonly type: TType;
|
|
1835
|
+
readonly tableId: string;
|
|
1836
|
+
readonly streamId: string;
|
|
1837
|
+
readonly version: number;
|
|
1838
|
+
readonly occurredAt: number;
|
|
1839
|
+
readonly actorId: string;
|
|
1840
|
+
readonly payload: TPayload;
|
|
1841
|
+
readonly correlationId?: string;
|
|
1842
|
+
readonly causationId?: string;
|
|
1843
|
+
}
|
|
1844
|
+
interface ExportRequestedPayload {
|
|
1845
|
+
readonly format: 'xlsx' | 'pdf' | 'csv';
|
|
1846
|
+
readonly collectionScope: 'active' | 'all' | string[];
|
|
1847
|
+
readonly fileName?: string;
|
|
1848
|
+
readonly sheetName?: string;
|
|
1849
|
+
readonly direction?: 'rtl' | 'ltr';
|
|
1850
|
+
}
|
|
1851
|
+
interface ImportRequestedPayload {
|
|
1852
|
+
readonly format: 'xlsx';
|
|
1853
|
+
readonly collectionScope: 'active' | 'all' | string[];
|
|
1854
|
+
readonly sheetName?: string;
|
|
1855
|
+
readonly byteLength?: number;
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
type AppendResult = {
|
|
1859
|
+
ok: true;
|
|
1860
|
+
version: number;
|
|
1861
|
+
} | {
|
|
1862
|
+
ok: false;
|
|
1863
|
+
conflict: {
|
|
1864
|
+
expectedVersion: number;
|
|
1865
|
+
actualVersion: number;
|
|
1866
|
+
};
|
|
1867
|
+
};
|
|
1868
|
+
type Unsubscribe = () => void;
|
|
1869
|
+
interface EventStore {
|
|
1870
|
+
append(streamId: string, events: GridEvent[], expectedVersion: number): Promise<AppendResult>;
|
|
1871
|
+
read(streamId: string, fromVersion?: number): Promise<GridEvent[]>;
|
|
1872
|
+
/** Ordered global stream for catch-up of cross-stream projections. */
|
|
1873
|
+
readAll(fromPosition?: number): Promise<GridEvent[]>;
|
|
1874
|
+
subscribe(streamId: string, onEvent: (event: GridEvent) => void): Unsubscribe;
|
|
1875
|
+
subscribeAll(onEvent: (event: GridEvent) => void): Unsubscribe;
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
interface CellUndoEntry {
|
|
1879
|
+
readonly kind: 'CELL_CHANGED';
|
|
1880
|
+
readonly tableId: string;
|
|
1881
|
+
readonly rowId: number;
|
|
1882
|
+
readonly columnId: string;
|
|
1883
|
+
readonly newValue: unknown;
|
|
1884
|
+
readonly previousValue: unknown;
|
|
1885
|
+
}
|
|
1886
|
+
type RowCellSnapshot = {
|
|
1887
|
+
readonly value: unknown;
|
|
1888
|
+
readonly display?: unknown;
|
|
1889
|
+
readonly originalValue?: unknown;
|
|
1890
|
+
};
|
|
1891
|
+
interface RowAddedUndoEntry {
|
|
1892
|
+
readonly kind: 'ROW_ADDED';
|
|
1893
|
+
readonly tableId: string;
|
|
1894
|
+
readonly rowId: number;
|
|
1895
|
+
/** Captured at record time so redo can restore identity + values. */
|
|
1896
|
+
readonly cells: Readonly<Record<string, RowCellSnapshot>>;
|
|
1897
|
+
readonly collection?: string;
|
|
1898
|
+
readonly isSaveDescription?: boolean;
|
|
1899
|
+
}
|
|
1900
|
+
/**
|
|
1901
|
+
* Compensating entry for a delete:
|
|
1902
|
+
* - soft: Unchanged→Deleted (undo/redo = toggle ROW_DELETED)
|
|
1903
|
+
* - hard: Added row removed from map (undo = RESTORE_ADDED_ROW)
|
|
1904
|
+
*/
|
|
1905
|
+
interface RowDeletedUndoEntry {
|
|
1906
|
+
readonly kind: 'ROW_DELETED';
|
|
1907
|
+
readonly tableId: string;
|
|
1908
|
+
readonly rowId: number;
|
|
1909
|
+
readonly mode: 'soft' | 'hard';
|
|
1910
|
+
readonly cells: Readonly<Record<string, RowCellSnapshot>>;
|
|
1911
|
+
readonly collection?: string;
|
|
1912
|
+
readonly isSaveDescription?: boolean;
|
|
1913
|
+
}
|
|
1914
|
+
type AtomicUndoEntry = CellUndoEntry | RowAddedUndoEntry | RowDeletedUndoEntry;
|
|
1915
|
+
type UndoDispatchCommand = {
|
|
1916
|
+
type: 'CHANGE_CELL_VALUE';
|
|
1917
|
+
store: string;
|
|
1918
|
+
tableKey: string;
|
|
1919
|
+
rowId: number;
|
|
1920
|
+
columnId: string;
|
|
1921
|
+
newValue: unknown;
|
|
1922
|
+
} | {
|
|
1923
|
+
type: 'ROW_DELETED';
|
|
1924
|
+
store: string;
|
|
1925
|
+
tableKey: string;
|
|
1926
|
+
rowId: number;
|
|
1927
|
+
} | {
|
|
1928
|
+
type: 'RESTORE_ADDED_ROW';
|
|
1929
|
+
store: string;
|
|
1930
|
+
tableKey: string;
|
|
1931
|
+
rowId: number;
|
|
1932
|
+
cells: Readonly<Record<string, RowCellSnapshot>>;
|
|
1933
|
+
collection?: string;
|
|
1934
|
+
isSaveDescription?: boolean;
|
|
1935
|
+
};
|
|
1936
|
+
type CellUndoDispatch = (command: UndoDispatchCommand) => Promise<void>;
|
|
1937
|
+
/**
|
|
1938
|
+
* Compensating undo/redo stack for domain edits.
|
|
1939
|
+
* - CELL_CHANGED: restore previousValue / re-apply newValue
|
|
1940
|
+
* - ROW_ADDED: delete on undo; RESTORE_ADDED_ROW on redo
|
|
1941
|
+
* - ROW_DELETED soft: toggle ROW_DELETED; hard: RESTORE_ADDED_ROW / ROW_DELETED
|
|
1942
|
+
* - Same correlationId merges into one undo unit (paste / cut+paste)
|
|
1943
|
+
*/
|
|
1944
|
+
declare class CellUndoStack {
|
|
1945
|
+
private undoEntries;
|
|
1946
|
+
private redoEntries;
|
|
1947
|
+
private applying;
|
|
1948
|
+
record(event: CellChangedEvent, correlationId?: string): void;
|
|
1949
|
+
recordRowAdded(event: {
|
|
1950
|
+
tableId: string;
|
|
1951
|
+
rowId: number;
|
|
1952
|
+
cells?: Readonly<Record<string, RowCellSnapshot>>;
|
|
1953
|
+
collection?: string;
|
|
1954
|
+
isSaveDescription?: boolean;
|
|
1955
|
+
}, correlationId?: string): void;
|
|
1956
|
+
recordRowDeleted(event: {
|
|
1957
|
+
tableId: string;
|
|
1958
|
+
rowId: number;
|
|
1959
|
+
mode: 'soft' | 'hard';
|
|
1960
|
+
cells?: Readonly<Record<string, RowCellSnapshot>>;
|
|
1961
|
+
collection?: string;
|
|
1962
|
+
isSaveDescription?: boolean;
|
|
1963
|
+
}, correlationId?: string): void;
|
|
1964
|
+
recordMany(entries: AtomicUndoEntry[], correlationId?: string): void;
|
|
1965
|
+
canUndo(): boolean;
|
|
1966
|
+
canRedo(): boolean;
|
|
1967
|
+
undoDepth(): number;
|
|
1968
|
+
redoDepth(): number;
|
|
1969
|
+
undo(store: string, dispatch: CellUndoDispatch): Promise<boolean>;
|
|
1970
|
+
redo(store: string, dispatch: CellUndoDispatch): Promise<boolean>;
|
|
1971
|
+
clear(): void;
|
|
1972
|
+
private pushAtomic;
|
|
1973
|
+
private applyCompensating;
|
|
1974
|
+
private applyForward;
|
|
1975
|
+
}
|
|
1976
|
+
|
|
1977
|
+
declare class TableAppService {
|
|
1978
|
+
private readonly changeCellValue;
|
|
1979
|
+
private readonly changeCellDisplayValue;
|
|
1980
|
+
private readonly saveDescription;
|
|
1981
|
+
private readonly addEmptyRow;
|
|
1982
|
+
private readonly addNewRows;
|
|
1983
|
+
private readonly duplicateRow;
|
|
1984
|
+
private readonly deleteRow;
|
|
1985
|
+
private readonly reorderRow;
|
|
1986
|
+
private readonly setPageSize;
|
|
1987
|
+
private readonly setPage;
|
|
1988
|
+
private readonly setActiveCollection;
|
|
1989
|
+
private readonly deleteTable;
|
|
1990
|
+
private readonly resetTable;
|
|
1991
|
+
private readonly applyDynamicProjection;
|
|
1992
|
+
private readonly pasteCells;
|
|
1993
|
+
private readonly restoreAddedRow?;
|
|
1994
|
+
private readonly pasteRow?;
|
|
1995
|
+
private readonly reorderColumn?;
|
|
1996
|
+
/** Page-window (paged-idb) mode only. */
|
|
1997
|
+
/** Lazy loader (module is fetched on first row activation with `resolveOn`). */
|
|
1998
|
+
private readonly applyRowVisibility?;
|
|
1999
|
+
private eventStore?;
|
|
2000
|
+
private undoStack?;
|
|
2001
|
+
private repo?;
|
|
2002
|
+
private snapshotStrategy?;
|
|
2003
|
+
constructor(changeCellValue: ChangeCellValueHandler, changeCellDisplayValue: ChangeCellDisplayValueHandler, saveDescription: SaveDescriptionHandler, addEmptyRow: AddNewRowCommandHandler, addNewRows: AddNewRowsCommandHandler, duplicateRow: DuplicateRowCommandHandler, deleteRow: DeleteRowCommandHandler, reorderRow: ReorderRowCommandHandler, setPageSize: ChangePageSizeCommandHandler, setPage: ChangePageCommandHandler, setActiveCollection: SetActiveCollectionCommandHandler, deleteTable: DeleteTableCommandHandler, resetTable: ResetTableCommandHandler, applyDynamicProjection: ApplyDynamicProjectionHandler, pasteCells: PasteCellsCommandHandler, restoreAddedRow?: RestoreAddedRowCommandHandler | undefined, pasteRow?: PasteRowCommandHandler | undefined, reorderColumn?: ReorderColumnCommandHandler | undefined,
|
|
2004
|
+
/** Page-window (paged-idb) mode only. */
|
|
2005
|
+
/** Lazy loader (module is fetched on first row activation with `resolveOn`). */
|
|
2006
|
+
applyRowVisibility?: (() => Promise<ApplyRowVisibilityHandler>) | undefined);
|
|
2007
|
+
private deleteRows?;
|
|
2008
|
+
/** Page-window mode only (lazy module): bulk delete of the selected rows. */
|
|
2009
|
+
setDeleteRowsHandler(handler: DeleteRowsCommandHandler): void;
|
|
2010
|
+
setEventStore(eventStore: EventStore): void;
|
|
2011
|
+
setSnapshotStrategy(strategy: {
|
|
2012
|
+
onAppend(streamId: string, tableId: string, appendedCount: number): Promise<void>;
|
|
2013
|
+
}): void;
|
|
2014
|
+
setUndoStack(undoStack: CellUndoStack): void;
|
|
2015
|
+
setRepository(repo: TableRepository): void;
|
|
2016
|
+
execute(command: ApplicationTableCommand, actor: Actor): Promise<RowAdded | RowDeleted | RowRemoved | MinimumRowConstraintViolated | RowRestored | RowReordered | RowAdded[] | TableEvent[] | {
|
|
2017
|
+
removed: number;
|
|
2018
|
+
softDeleted: number;
|
|
2019
|
+
remaining: number;
|
|
2020
|
+
} | null>;
|
|
2021
|
+
private dispatch;
|
|
2022
|
+
private recordUndoableEvents;
|
|
2023
|
+
private captureRowSnapshot;
|
|
2024
|
+
private appendToEventStore;
|
|
2025
|
+
private recordSnapshot;
|
|
2026
|
+
private normalizeResult;
|
|
2027
|
+
private resolveRowId;
|
|
2028
|
+
private toGridPayload;
|
|
2029
|
+
private createCorrelationId;
|
|
2030
|
+
}
|
|
2031
|
+
|
|
2032
|
+
/**
|
|
2033
|
+
* Sparse ordered index for large tables: O(1) id lookup + O(window) projection.
|
|
2034
|
+
* Position map enables O(1) neighbor for keyboard nav (PR-99).
|
|
2035
|
+
*/
|
|
2036
|
+
declare class SparseRowIndex<T> {
|
|
2037
|
+
private readonly byId;
|
|
2038
|
+
private orderedIds;
|
|
2039
|
+
/** id → position in `orderedIds` (PR-99). */
|
|
2040
|
+
private readonly posById;
|
|
2041
|
+
constructor(entries?: Iterable<readonly [number, T]>);
|
|
2042
|
+
get size(): number;
|
|
2043
|
+
getOrderedIds(): readonly number[];
|
|
2044
|
+
getById(id: number): T | undefined;
|
|
2045
|
+
/** O(1) position of `id`, or `-1`. */
|
|
2046
|
+
indexOf(id: number): number;
|
|
2047
|
+
/** O(1) neighbor id along the ordered index, or `undefined`. */
|
|
2048
|
+
neighbor(id: number, delta: 1 | -1): number | undefined;
|
|
2049
|
+
set(id: number, value: T): void;
|
|
2050
|
+
/** Insert `id` at `pos` (0…size). Shifts later positions — O(n-pos). */
|
|
2051
|
+
insertAt(pos: number, id: number, value: T): void;
|
|
2052
|
+
remove(id: number): boolean;
|
|
2053
|
+
/** Replace order without rebuilding payloads (e.g. after sort). */
|
|
2054
|
+
setOrder(orderedIds: readonly number[]): void;
|
|
2055
|
+
/** Full replace of ids + values in one pass (PR-99 rebuild). */
|
|
2056
|
+
replaceAll(orderedIds: readonly number[], valueFor: (id: number) => T): void;
|
|
2057
|
+
clear(): void;
|
|
2058
|
+
/** Project only the visible window — O(window), not O(n). */
|
|
2059
|
+
projectVisible(range: {
|
|
2060
|
+
startIndex: number;
|
|
2061
|
+
endIndex: number;
|
|
2062
|
+
}): T[];
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2065
|
+
type GetRowId<TRow = unknown> = (row: TRow, index: number) => string;
|
|
2066
|
+
/** Default `getRowId`: array index. Hosts with a stable key should pass one. */
|
|
2067
|
+
declare function defaultGetRowId<TRow>(_row: TRow, index: number): string;
|
|
2068
|
+
/**
|
|
2069
|
+
* Domain sort/pagination still keys off an `index` cell. When the host omits
|
|
2070
|
+
* one, synthesize a hidden `#` column so order stays stable.
|
|
2071
|
+
*/
|
|
2072
|
+
declare function ensureIndexColumnDef<TRow>(defs: ColDefOrGroup<TRow>[]): ColDefOrGroup<TRow>[];
|
|
2073
|
+
type MappedRowInput = {
|
|
2074
|
+
id: number;
|
|
2075
|
+
values: Record<string, unknown>;
|
|
2076
|
+
data: unknown;
|
|
2077
|
+
sourceId: string;
|
|
2078
|
+
collection: 'default';
|
|
2079
|
+
};
|
|
2080
|
+
declare function mapRowDataToRowInputs<TRow>(rowData: readonly TRow[], columnDefs: ColumnDef<TRow>[], getRowId?: GetRowId<TRow>): MappedRowInput[];
|
|
2081
|
+
type HostRowDataDiffResult = {
|
|
2082
|
+
added: number;
|
|
2083
|
+
updated: number;
|
|
2084
|
+
removed: number;
|
|
2085
|
+
kept: number;
|
|
2086
|
+
structureChanged: boolean;
|
|
2087
|
+
removedIds: number[];
|
|
2088
|
+
/** Domain `Row` instances whose cells were not rewritten. */
|
|
2089
|
+
unchangedRows: Row[];
|
|
2090
|
+
};
|
|
2091
|
+
/**
|
|
2092
|
+
* Align table rows with a new `rowData` array without rebuilding the table.
|
|
2093
|
+
* Unchanged rows keep the same `Row` instance (no deep clone of `data`).
|
|
2094
|
+
*/
|
|
2095
|
+
declare function applyHostRowDataToTable<TRow>(table: Table, rowData: readonly TRow[], columnDefs: ColumnDef<TRow>[], getRowId?: GetRowId<TRow>): HostRowDataDiffResult;
|
|
2096
|
+
|
|
2097
|
+
declare class TableEngine {
|
|
2098
|
+
private readonly app;
|
|
2099
|
+
private readonly repo;
|
|
2100
|
+
private readonly actor;
|
|
2101
|
+
/**
|
|
2102
|
+
* متای زندهٔ ستونها از کانفیگ (دارای resolveOn / dynamicSource که در
|
|
2103
|
+
* IndexedDB serialize نمیشوند). NavigationManager برای تشخیص ستونهای
|
|
2104
|
+
* شرطیِ فعالشدن سطر (APPLY_ROW_VISIBILITY) به آن نیاز دارد.
|
|
2105
|
+
*/
|
|
2106
|
+
private readonly columnMeta?;
|
|
2107
|
+
private tableStore?;
|
|
2108
|
+
private tableKey?;
|
|
2109
|
+
/** Durable command store id (for CHANGE_CELL_* on edit commit). */
|
|
2110
|
+
private commandStore?;
|
|
2111
|
+
private cellEditOptions;
|
|
2112
|
+
readonly errors: Map<string, CellError>;
|
|
2113
|
+
readonly searchResult: Map<string, CellError>;
|
|
2114
|
+
private readonly asyncCellCache;
|
|
2115
|
+
private readonly asyncCellSeq;
|
|
2116
|
+
private readonly errHandler;
|
|
2117
|
+
private readonly selection;
|
|
2118
|
+
private readonly cellRange;
|
|
2119
|
+
private readonly rowMgr;
|
|
2120
|
+
private readonly nav;
|
|
2121
|
+
private readonly viewBuilder;
|
|
2122
|
+
/** Notifies host server/infinite row model after sort/filter/page (PR-96). */
|
|
2123
|
+
private viewQueryListener?;
|
|
2124
|
+
constructor(app: TableAppService, repo: TableRepository, actor: Actor, audit: ConsoleAuditLogger,
|
|
2125
|
+
/**
|
|
2126
|
+
* متای زندهٔ ستونها از کانفیگ (دارای resolveOn / dynamicSource که در
|
|
2127
|
+
* IndexedDB serialize نمیشوند). NavigationManager برای تشخیص ستونهای
|
|
2128
|
+
* شرطیِ فعالشدن سطر (APPLY_ROW_VISIBILITY) به آن نیاز دارد.
|
|
2129
|
+
*/
|
|
2130
|
+
columnMeta?: Map<string, ColumnSchema> | undefined);
|
|
2131
|
+
private registerTable;
|
|
2132
|
+
private deleteTable;
|
|
2133
|
+
private disposeTable;
|
|
2134
|
+
private resetTable;
|
|
2135
|
+
private shouldInvalidateUiRowIndex;
|
|
2136
|
+
private getStore;
|
|
2137
|
+
/**
|
|
2138
|
+
* Default case در dispatch:
|
|
2139
|
+
* command را به AppService میدهد و سپس repo را reload میکند.
|
|
2140
|
+
*/
|
|
2141
|
+
private executeAppCommand;
|
|
2142
|
+
/**
|
|
2143
|
+
* Paste goes through AppService (PASTE_ROW + optional ROW_DELETED for cut)
|
|
2144
|
+
* with one correlationId so undo reverses the whole unit.
|
|
2145
|
+
*/
|
|
2146
|
+
private executePasteAction;
|
|
2147
|
+
dispatch(command: TableCommand): Promise<void>;
|
|
2148
|
+
private setGridSearch;
|
|
2149
|
+
private setMobileEditor;
|
|
2150
|
+
private resizeColumn;
|
|
2151
|
+
private setColumnPinned;
|
|
2152
|
+
private toggleColumnGroup;
|
|
2153
|
+
private setColumnVisible;
|
|
2154
|
+
private setSortModel;
|
|
2155
|
+
private setQuickFilterText;
|
|
2156
|
+
private setFilterModel;
|
|
2157
|
+
private setRowGroupColumns;
|
|
2158
|
+
private setGroupDefaultExpanded;
|
|
2159
|
+
private toggleRowGroup;
|
|
2160
|
+
/**
|
|
2161
|
+
* Server/infinite row model hooks (PR-96).
|
|
2162
|
+
* Listener runs after sort / filter / page changes.
|
|
2163
|
+
*/
|
|
2164
|
+
bindViewQueryListener(listener: (() => void) | undefined): void;
|
|
2165
|
+
setRowModelType(rowModelType: RowModelType): void;
|
|
2166
|
+
setServerRowCount(count: number | null): void;
|
|
2167
|
+
private notifyViewQueryChanged;
|
|
2168
|
+
getViewState(): TableViewState | undefined;
|
|
2169
|
+
/**
|
|
2170
|
+
* Diff `rowData` onto the live table without resetting it (PR-82).
|
|
2171
|
+
* Unchanged domain rows keep identity so UI `React.memo` can skip them.
|
|
2172
|
+
*/
|
|
2173
|
+
applyHostRowData<TRow>(rowData: readonly TRow[], columnDefs?: ColumnDef<TRow>[], getRowId?: GetRowId<TRow>): void;
|
|
2174
|
+
getAllRows(): Row[] | null;
|
|
2175
|
+
getAllUIRows(): UIRow[] | null;
|
|
2176
|
+
/** Flat group/leaf nodes (PR-120). */
|
|
2177
|
+
getFlatUiNodes(): readonly FlatUiNode[];
|
|
2178
|
+
getGroupNode(rowId: number): FlatGroupNode | undefined;
|
|
2179
|
+
/** Expand/collapse group for the active synthetic row (PR-121). */
|
|
2180
|
+
toggleRowGroupById(rowId: number): boolean;
|
|
2181
|
+
getUiRowIndex(): SparseRowIndex<number>;
|
|
2182
|
+
/** Absolute 0-based position in the filter/sort UI order (PR-99). */
|
|
2183
|
+
getUiRowAbsoluteIndex(rowId: number): number;
|
|
2184
|
+
getCellRanges(): readonly CellRange[];
|
|
2185
|
+
addCellRange(range: CellRange): void;
|
|
2186
|
+
handleCellRangePointer(rowId: number, colId: string, modifiers: {
|
|
2187
|
+
shiftKey: boolean;
|
|
2188
|
+
ctrlKey: boolean;
|
|
2189
|
+
}): void;
|
|
2190
|
+
extendCellRangeArrow(direction: ArrowDirection): void;
|
|
2191
|
+
extendCellRangeToEdge(direction: ArrowDirection): void;
|
|
2192
|
+
jumpActiveCellRowEdge(edge: 'start' | 'end'): void;
|
|
2193
|
+
jumpActiveCellGridCorner(corner: 'first' | 'last'): void;
|
|
2194
|
+
private syncActiveCellToRangeFocus;
|
|
2195
|
+
selectAllCells(): void;
|
|
2196
|
+
syncCellRangeToActiveCell(): void;
|
|
2197
|
+
private getCellRangeBounds;
|
|
2198
|
+
findColumnSearchMatches(columnId: string, query: string): Array<{
|
|
2199
|
+
rowId: number;
|
|
2200
|
+
columnId: string;
|
|
2201
|
+
}>;
|
|
2202
|
+
getColumnTotals(): Record<string, number>;
|
|
2203
|
+
getColumnAggs(): Record<string, unknown>;
|
|
2204
|
+
getColumnAggValue(columnId: string, overrideAgg?: AggFunc): unknown;
|
|
2205
|
+
subscribeColumnTotals(cb: (totals: Record<string, number>) => void): (() => void) | null;
|
|
2206
|
+
subscribeColumnAggs(cb: (aggs: Record<string, unknown>) => void): (() => void) | null;
|
|
2207
|
+
getUiRowCount(): number;
|
|
2208
|
+
projectVisibleUiRows(range: {
|
|
2209
|
+
startIndex: number;
|
|
2210
|
+
endIndex: number;
|
|
2211
|
+
}): UIRow[];
|
|
2212
|
+
getMobileViewState(): MobileTableViewState | undefined;
|
|
2213
|
+
getRowView(rowId: number): UIRow | null;
|
|
2214
|
+
getSnapShot(collectionScope: CollectionScope): TableSnapShot | null;
|
|
2215
|
+
/**
|
|
2216
|
+
* Full dataset snapshot from IndexedDB (source of truth).
|
|
2217
|
+
* Use for server save / export — not the RAM page window.
|
|
2218
|
+
*/
|
|
2219
|
+
getFullSnapShot(store: string, collectionScope?: CollectionScope): Promise<TableSnapShot | null>;
|
|
2220
|
+
/**
|
|
2221
|
+
* Stream serialized row records from IndexedDB in bounded batches.
|
|
2222
|
+
* Heap holds one batch at a time — never the whole dataset.
|
|
2223
|
+
* Return false from onBatch to stop early.
|
|
2224
|
+
*/
|
|
2225
|
+
iterateRowsFromDb(store: string, collectionScope: CollectionScope, onBatch: (records: PersistedRowRecord[], ordinalBase: number) => Promise<boolean | void>, batchSize?: number): Promise<void>;
|
|
2226
|
+
/** True in persistence 'paged-idb' mode (RAM holds one page window). */
|
|
2227
|
+
isPagedWindow(): boolean;
|
|
2228
|
+
/** Windowed: IndexedDB (SoT). Default mode: the in-memory table. */
|
|
2229
|
+
private loadAllRows;
|
|
2230
|
+
getExpandedRowData(rowId: number): Record<string, unknown> | null;
|
|
2231
|
+
getActiveCell(): TableState['activeCell'] | null;
|
|
2232
|
+
/** Force a view-store tick so bound React rows re-read cells (PR-86). */
|
|
2233
|
+
refreshView(): void;
|
|
2234
|
+
setCellEditOptions(partial: Partial<CellEditOptions>): void;
|
|
2235
|
+
getCellEditOptions(): CellEditOptions;
|
|
2236
|
+
getCellEdit(): CellEditSession | null;
|
|
2237
|
+
getEditDraft(rowId: number, columnId: string): CellEditValue | null;
|
|
2238
|
+
isEditingCell(rowId: number, columnId: string): boolean;
|
|
2239
|
+
/**
|
|
2240
|
+
* Begin a session-only draft for the cell (or full row). Does not touch EventStore.
|
|
2241
|
+
*/
|
|
2242
|
+
startCellEdit(rowId: number, columnId: string): void;
|
|
2243
|
+
patchCellEdit(rowId: number, columnId: string, patch: Partial<CellEditValue>): void;
|
|
2244
|
+
/** Discard drafts; restore UI to domain values. No EventStore write. */
|
|
2245
|
+
cancelCellEdit(): void;
|
|
2246
|
+
/**
|
|
2247
|
+
* Write dirty drafts via CHANGE_CELL_* then clear the session.
|
|
2248
|
+
* @returns number of value-change commands dispatched
|
|
2249
|
+
*/
|
|
2250
|
+
commitCellEdit(): Promise<number>;
|
|
2251
|
+
private transitionActiveCell;
|
|
2252
|
+
private maybeStartEditForActiveCell;
|
|
2253
|
+
/** Leave cell-edit / focus. Commits when stopEditingWhenCellsLoseFocus. */
|
|
2254
|
+
clearActiveCell(options?: {
|
|
2255
|
+
cancel?: boolean;
|
|
2256
|
+
}): Promise<void>;
|
|
2257
|
+
getActiveRow(): number | null;
|
|
2258
|
+
getSelectedRows(): Record<number, boolean> | undefined;
|
|
2259
|
+
getCell(rowId: number, columnId: string): Cell | undefined;
|
|
2260
|
+
getMobileEditor(): TableState['mobileEditor'] | undefined;
|
|
2261
|
+
isActiveCell(rowId: number, columnId: string): boolean;
|
|
2262
|
+
isSelectedRow(rowId: number): boolean;
|
|
2263
|
+
isCutRow(rowId: number): boolean;
|
|
2264
|
+
isActiveRow(rowId: number): boolean;
|
|
2265
|
+
private validateCell;
|
|
2266
|
+
private schemaHasAsyncValidator;
|
|
2267
|
+
private tableHasAsyncValidators;
|
|
2268
|
+
private cellValueKey;
|
|
2269
|
+
private errorFromAsyncFailure;
|
|
2270
|
+
private applyAsyncValidators;
|
|
2271
|
+
private validateCellFull;
|
|
2272
|
+
private finishValidation;
|
|
2273
|
+
private collectValidationJobs;
|
|
2274
|
+
private applyValidationErrors;
|
|
2275
|
+
private runValidationSync;
|
|
2276
|
+
private runValidationAsync;
|
|
2277
|
+
private scheduleAsyncCellCheck;
|
|
2278
|
+
validation(cb: ValidationCallback): void;
|
|
2279
|
+
isValidCell(rowId: number, caption: string): ValidCell;
|
|
2280
|
+
subscribe(cb: () => void): (() => void) | null;
|
|
2281
|
+
/**
|
|
2282
|
+
* Selector-based subscription over engine-derived view data.
|
|
2283
|
+
* `selector` closes over engine getters (snapshot, activeCell, …).
|
|
2284
|
+
*/
|
|
2285
|
+
subscribeSelected<TSelected>(selector: () => TSelected, listener: (selected: TSelected) => void, isEqual?: (a: TSelected, b: TSelected) => boolean): (() => void) | null;
|
|
2286
|
+
/**
|
|
2287
|
+
* Streamed column subscription (Memory Iron Rule compliant).
|
|
2288
|
+
* Consumes the dataset through `iterateRowRecords` in bounded batches and
|
|
2289
|
+
* folds every non-deleted item into a small caller-owned accumulator via
|
|
2290
|
+
* `reducer` — never materializes rows with getAllRows and never
|
|
2291
|
+
* JSON.stringify's the whole dataset. Heap = one batch + the accumulator
|
|
2292
|
+
* (O(batch) in RAM, independent of total row count).
|
|
2293
|
+
* Change detection uses an incrementally-maintained double-hash signature
|
|
2294
|
+
* (O(1) heap) instead of a full JSON signature.
|
|
2295
|
+
* `cb` fires with the folded accumulator on the initial emit and afterwards
|
|
2296
|
+
* only when the column's data actually changed. Reads are async.
|
|
2297
|
+
*/
|
|
2298
|
+
subscribeColumn<T = unknown>(columnId: string, collections: CollectionScope, reducer: (acc: T, item: {
|
|
2299
|
+
id: number;
|
|
2300
|
+
rowNum: unknown;
|
|
2301
|
+
value: unknown;
|
|
2302
|
+
}) => T, seed: T, cb: (acc: T) => void, store?: string): (() => void) | null;
|
|
2303
|
+
}
|
|
2304
|
+
|
|
2305
|
+
interface ChangelogEntry {
|
|
2306
|
+
readonly eventId: string;
|
|
2307
|
+
readonly type: string;
|
|
2308
|
+
readonly tableId: string;
|
|
2309
|
+
readonly occurredAt: number;
|
|
2310
|
+
readonly actorId: string;
|
|
2311
|
+
readonly payload: unknown;
|
|
2312
|
+
}
|
|
2313
|
+
interface ChangelogQuery {
|
|
2314
|
+
tableId?: string;
|
|
2315
|
+
rowId?: number | string;
|
|
2316
|
+
columnId?: string;
|
|
2317
|
+
type?: string;
|
|
2318
|
+
since?: number;
|
|
2319
|
+
limit?: number;
|
|
2320
|
+
}
|
|
2321
|
+
declare class ChangelogProjection {
|
|
2322
|
+
private readonly eventStore;
|
|
2323
|
+
private entries;
|
|
2324
|
+
private unsubscribe;
|
|
2325
|
+
private subscribers;
|
|
2326
|
+
private seenEventIds;
|
|
2327
|
+
private started;
|
|
2328
|
+
constructor(eventStore: EventStore);
|
|
2329
|
+
/**
|
|
2330
|
+
* Catch up via readAll, then subscribe for live events.
|
|
2331
|
+
* Dedupes by eventId so subscribe-before-replay races are safe.
|
|
2332
|
+
*/
|
|
2333
|
+
start(): Promise<void>;
|
|
2334
|
+
stop(): void;
|
|
2335
|
+
query(filter?: ChangelogQuery): ChangelogEntry[];
|
|
2336
|
+
count(filter?: ChangelogQuery): number;
|
|
2337
|
+
subscribe(notify: (entries: ChangelogEntry[]) => void, filter?: ChangelogQuery): Unsubscribe;
|
|
2338
|
+
clear(): void;
|
|
2339
|
+
private project;
|
|
2340
|
+
private notifySubscribers;
|
|
2341
|
+
}
|
|
2342
|
+
|
|
2343
|
+
type HistorySeverity = 'info' | 'warning' | 'error';
|
|
2344
|
+
type HistoryCategory = 'data' | 'structure' | 'view' | 'system';
|
|
2345
|
+
interface HistoryQuery extends ChangelogQuery {
|
|
2346
|
+
severity?: HistorySeverity;
|
|
2347
|
+
category?: HistoryCategory;
|
|
2348
|
+
}
|
|
2349
|
+
interface HistoryItem {
|
|
2350
|
+
readonly id: string;
|
|
2351
|
+
readonly type: string;
|
|
2352
|
+
readonly title: string;
|
|
2353
|
+
readonly description: string;
|
|
2354
|
+
readonly occurredAt: number;
|
|
2355
|
+
readonly tableId: string;
|
|
2356
|
+
readonly actorId: string;
|
|
2357
|
+
readonly severity: HistorySeverity;
|
|
2358
|
+
readonly category: HistoryCategory;
|
|
2359
|
+
readonly raw: ChangelogEntry;
|
|
2360
|
+
}
|
|
2361
|
+
declare class HistoryPanelViewModel {
|
|
2362
|
+
private readonly changelogProjection;
|
|
2363
|
+
constructor(changelogProjection: ChangelogProjection);
|
|
2364
|
+
query(filter?: HistoryQuery): HistoryItem[];
|
|
2365
|
+
count(filter?: HistoryQuery): number;
|
|
2366
|
+
subscribe(cb: (items: HistoryItem[]) => void, filter?: HistoryQuery): Unsubscribe;
|
|
2367
|
+
private toHistoryItem;
|
|
2368
|
+
}
|
|
2369
|
+
|
|
2370
|
+
/**
|
|
2371
|
+
* Session-centric view / keyboard intents.
|
|
2372
|
+
* These are not domain commands; GridSession maps them to engine dispatches.
|
|
2373
|
+
*/
|
|
2374
|
+
type ViewIntent = {
|
|
2375
|
+
type: 'ADD_EMPTY_ROW';
|
|
2376
|
+
autoActivate?: boolean;
|
|
2377
|
+
} | {
|
|
2378
|
+
type: 'DUPLICATE_ROW';
|
|
2379
|
+
rowId: number;
|
|
2380
|
+
} | {
|
|
2381
|
+
type: 'DELETE_ROW';
|
|
2382
|
+
rowId: number;
|
|
2383
|
+
} | {
|
|
2384
|
+
type: 'TOGGLE_ROW_SELECTION';
|
|
2385
|
+
rowId: number;
|
|
2386
|
+
} | {
|
|
2387
|
+
type: 'SELECT_FROM_ACTIVE_TO_LAST';
|
|
2388
|
+
anchorRowId: number;
|
|
2389
|
+
} | {
|
|
2390
|
+
type: 'ACTIVATE_FIRST_CELL';
|
|
2391
|
+
rowId: number;
|
|
2392
|
+
} | {
|
|
2393
|
+
type: 'MOVE_ACTIVE_CELL';
|
|
2394
|
+
rowId: number;
|
|
2395
|
+
columnId: string;
|
|
2396
|
+
direction: 'next' | 'prev';
|
|
2397
|
+
} | {
|
|
2398
|
+
type: 'MOVE_ACTIVE_CELL_VERTICAL';
|
|
2399
|
+
rowId: number;
|
|
2400
|
+
columnId: string;
|
|
2401
|
+
direction: 'up' | 'down';
|
|
2402
|
+
} | {
|
|
2403
|
+
type: 'MOVE_VERTICAL_SELECTED_ROWS';
|
|
2404
|
+
direction: 'up' | 'down';
|
|
2405
|
+
} | {
|
|
2406
|
+
type: 'MOVE_VERTICAL_ACTIVE_ROW';
|
|
2407
|
+
direction: 'up' | 'down';
|
|
2408
|
+
} | {
|
|
2409
|
+
type: 'COLLAPSE_ALL_ROWS';
|
|
2410
|
+
} | {
|
|
2411
|
+
type: 'CHANGE_PAGE';
|
|
2412
|
+
page: number;
|
|
2413
|
+
} | {
|
|
2414
|
+
type: 'CHANGE_PAGE_SIZE';
|
|
2415
|
+
pageSize: number;
|
|
2416
|
+
} | {
|
|
2417
|
+
type: 'SET_TABLE_ACTION';
|
|
2418
|
+
action: TableActions;
|
|
2419
|
+
} | {
|
|
2420
|
+
type: 'SET_GRID_SEARCH';
|
|
2421
|
+
search: GridSearchState;
|
|
2422
|
+
} | {
|
|
2423
|
+
type: 'SET_MOBILE_EDITOR';
|
|
2424
|
+
editor: MobileEditorState;
|
|
2425
|
+
} | {
|
|
2426
|
+
type: 'CHANGE_VIEWPORT';
|
|
2427
|
+
scrollOffset: number;
|
|
2428
|
+
viewportSize?: number;
|
|
2429
|
+
rowHeight?: number;
|
|
2430
|
+
overscan?: number;
|
|
2431
|
+
} | {
|
|
2432
|
+
type: 'UNDO';
|
|
2433
|
+
} | {
|
|
2434
|
+
type: 'REDO';
|
|
2435
|
+
} | {
|
|
2436
|
+
type: 'EXTEND_CELL_RANGE';
|
|
2437
|
+
direction: ArrowDirection;
|
|
2438
|
+
} | {
|
|
2439
|
+
type: 'EXTEND_CELL_RANGE_TO_EDGE';
|
|
2440
|
+
direction: ArrowDirection;
|
|
2441
|
+
} | {
|
|
2442
|
+
type: 'JUMP_ACTIVE_CELL_ROW_EDGE';
|
|
2443
|
+
edge: 'start' | 'end';
|
|
2444
|
+
} | {
|
|
2445
|
+
type: 'JUMP_ACTIVE_CELL_GRID';
|
|
2446
|
+
corner: 'first' | 'last';
|
|
2447
|
+
} | {
|
|
2448
|
+
type: 'SELECT_ALL_CELLS';
|
|
2449
|
+
};
|
|
2450
|
+
type ViewIntentDispatcher = (intent: ViewIntent) => Promise<void>;
|
|
2451
|
+
|
|
2452
|
+
type GridSessionSubscribeSelected = <TSelected>(selector: () => TSelected, listener: (selected: TSelected) => void, isEqual?: (a: TSelected, b: TSelected) => boolean) => () => void;
|
|
2453
|
+
/**
|
|
2454
|
+
* Framework-agnostic session facade (target shape of useGrid / createGrid).
|
|
2455
|
+
* Adapters should prefer this over raw Engine.
|
|
2456
|
+
*/
|
|
2457
|
+
interface GridSession {
|
|
2458
|
+
readonly store: string;
|
|
2459
|
+
readonly tableKey: string;
|
|
2460
|
+
dispatchViewIntent: ViewIntentDispatcher;
|
|
2461
|
+
handleKeydown(event: KeyboardEvent, ctx: {
|
|
2462
|
+
activeRowId: number | null;
|
|
2463
|
+
activeColumnId: string | null;
|
|
2464
|
+
}): Promise<void>;
|
|
2465
|
+
getSnapShot(collectionScope?: CollectionScope): TableSnapShot | null;
|
|
2466
|
+
getViewState(): ReturnType<TableEngine['getViewState']>;
|
|
2467
|
+
subscribe(cb: () => void): () => void;
|
|
2468
|
+
subscribeSelected: GridSessionSubscribeSelected;
|
|
2469
|
+
canUndo(): boolean;
|
|
2470
|
+
canRedo(): boolean;
|
|
2471
|
+
undo(): Promise<boolean>;
|
|
2472
|
+
redo(): Promise<boolean>;
|
|
2473
|
+
getChangelog(filter?: Omit<ChangelogQuery, 'tableId'>): ChangelogEntry[];
|
|
2474
|
+
getChangelogCount(filter?: Omit<ChangelogQuery, 'tableId'>): number;
|
|
2475
|
+
subscribeChangelog(cb: (entries: ChangelogEntry[]) => void, filter?: Omit<ChangelogQuery, 'tableId'>): () => void;
|
|
2476
|
+
getHistoryItems(filter?: Omit<HistoryQuery, 'tableId'>): HistoryItem[];
|
|
2477
|
+
getHistoryItemCount(filter?: Omit<HistoryQuery, 'tableId'>): number;
|
|
2478
|
+
subscribeHistoryItems(cb: (items: HistoryItem[]) => void, filter?: Omit<HistoryQuery, 'tableId'>): () => void;
|
|
2479
|
+
getEngine(): TableEngine;
|
|
2480
|
+
/** Current virtual-scroll viewport (view state; not domain). */
|
|
2481
|
+
getViewport(): Viewport;
|
|
2482
|
+
getVisibleRange(totalRows?: number): VisibleRange;
|
|
2483
|
+
projectVisibleRows<T>(rows: readonly T[], totalRows?: number): T[];
|
|
2484
|
+
/** Active-collection row count from the sparse UI index (order = `index` column). */
|
|
2485
|
+
getUiRowCount(): number;
|
|
2486
|
+
/** Visible UI rows for the current viewport — O(window), not O(n). */
|
|
2487
|
+
projectVisibleUiRows(): NonNullable<ReturnType<TableEngine['getRowView']>>[];
|
|
2488
|
+
/** Notify when virtual viewport scroll/size changes (PR-102 block fetch). */
|
|
2489
|
+
subscribeViewport(listener: () => void): () => void;
|
|
2490
|
+
}
|
|
2491
|
+
|
|
2492
|
+
export { type CycleSortModelOptions as $, type AggFunc as A, type AriaSortValue as B, type ColumnSchema as C, type DefaultOptionType as D, type EventStore as E, type FilterModel as F, type GridEvent as G, HistoryPanelViewModel as H, type ArrowDirection as I, type BooleanColumnFilter as J, type BooleanFilterOp as K, type BuiltinFilterKind as L, type MobileTableViewState as M, type CellRangeBounds as N, type CellRangeSelection as O, type ColumnDefBridge as P, type ColumnField as Q, Row as R, type ColumnFilter as S, type TableSnapShot as T, type UIRow as U, type ValidCell as V, type WindowedTableRepository as W, type ColumnPinned as X, type CombinedColumnFilter as Y, type CustomColumnFilter as Z, type CustomFilterFn as _, type Unsubscribe as a, sortPriorityForColumn as a$, type DateColumnFilter as a0, type DateFilterOp as a1, type FilterAccessor as a2, type FilterDef as a3, type FilterJoin as a4, HEADER_SORT_CLICK_MAX_MOVE_PX as a5, INDEX_COL_ID as a6, type ItemType as a7, type NumberColumnFilter as a8, type NumberFilterOp as a9, compareSortValues as aA, compareTypedValues as aB, createEmptyCellRangeSelection as aC, ctrlClickCell as aD, cycleSortModel as aE, defaultGetRowId as aF, ensureIndexColumnDef as aG, isBlankSortValue as aH, isCellInRange as aI, isColumnFilterActive as aJ, isHeaderColumnSortable as aK, isServerRowModel as aL, isWindowedRepository as aM, mapRowDataToRowInputs as aN, mergeCellRanges as aO, moveCellAddress as aP, normalizeCellRange as aQ, normalizeDigits as aR, normalizeFilterText as aS, pageWindow as aT, rangeFromAnchorFocus as aU, rangesOverlap as aV, resolveBuiltinFilterKind as aW, selectAllCellRanges as aX, shiftArrowCell as aY, shiftClickCell as aZ, shouldCommitHeaderSortClick as a_, type PersistedRowRecord as aa, type RowModelType as ab, RowStateEnum as ac, type SetColumnFilter as ad, type SetFilterOp as ae, type SimpleColumnFilter as af, type SortAccessor as ag, type SortDirection as ah, type SortModel as ai, type SortModelItem as aj, type SortValueComparator as ak, SparseRowIndex as al, type TextColumnFilter as am, type TextFilterOp as an, type ViewIntent as ao, Viewport as ap, type VisibleRange as aq, applyFilter as ar, applyHostRowDataToTable as as, applySort as at, ariaSortForColumn as au, clampColIndex as av, clampRowIndex as aw, clickCell as ax, colIndex as ay, collectUniqueFilterValues as az, type GridSession as b, type ExportRequestedPayload as b0, type ImportRequestedPayload as b1, type IRule as b2, type ColumnVisibilityRule as b3, type IDependOn as b4, type Actor$1 as b5, type ColDefOrGroup as b6, type TableRepository as b7, type PermissionPolicy as b8, type CellEditType as b9, type IMultiSelectConfig as ba, type ColumnGroupDef as bb, type ColumnGroupMeta as bc, type ColumnGroupPathEntry as bd, isColumnGroupDef as be, type CollectionScope as c, type CellRange as d, TableEngine as e, Table as f, type TableActions as g, type GridSearchState as h, ChangelogProjection as i, CellUndoStack as j, type TableViewState as k, type ColumnDef as l, type GetRowId as m, Cell as n, type ChangelogQuery as o, type ChangelogEntry as p, type HistoryQuery as q, type HistoryItem as r, type ActiveCell as s, type CellEditValue as t, type MobileEditorState as u, type ValidationCallbackResult as v, type CellAddress as w, type FieldType as x, type AggFuncName as y, type AppendResult as z };
|