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,331 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// engine/columnWidth.ts
|
|
4
|
+
var DEFAULT_COLUMN_MIN_WIDTH = 144;
|
|
5
|
+
var INDEX_COLUMN_DEFAULT_WIDTH = 168;
|
|
6
|
+
function isIndexColumn(column) {
|
|
7
|
+
return column.fieldType === "index" || column.fieldName === "index";
|
|
8
|
+
}
|
|
9
|
+
function columnWidthFloor(column) {
|
|
10
|
+
const schemaMin = column?.minWidth ?? 0;
|
|
11
|
+
if (column && isIndexColumn(column)) {
|
|
12
|
+
return Math.max(INDEX_COLUMN_DEFAULT_WIDTH, schemaMin);
|
|
13
|
+
}
|
|
14
|
+
return Math.max(DEFAULT_COLUMN_MIN_WIDTH, schemaMin);
|
|
15
|
+
}
|
|
16
|
+
function clampColumnWidth(width, column) {
|
|
17
|
+
const floor = columnWidthFloor(column);
|
|
18
|
+
if (!Number.isFinite(width)) return floor;
|
|
19
|
+
return Math.max(floor, Math.round(width));
|
|
20
|
+
}
|
|
21
|
+
function resolveColumnWidth(column, columnWidths) {
|
|
22
|
+
const stored = columnWidths?.[column.fieldName];
|
|
23
|
+
if (typeof stored === "number" && Number.isFinite(stored)) {
|
|
24
|
+
return clampColumnWidth(stored, column);
|
|
25
|
+
}
|
|
26
|
+
if (isIndexColumn(column)) {
|
|
27
|
+
return INDEX_COLUMN_DEFAULT_WIDTH;
|
|
28
|
+
}
|
|
29
|
+
return column.minWidth ?? DEFAULT_COLUMN_MIN_WIDTH;
|
|
30
|
+
}
|
|
31
|
+
function columnSizeStyle(column, columnWidths, layoutWidths) {
|
|
32
|
+
const width = layoutWidths?.[column.fieldName] ?? resolveColumnWidth(column, columnWidths);
|
|
33
|
+
return { width, minWidth: width };
|
|
34
|
+
}
|
|
35
|
+
function overlayStoredColumnWidth(column, columnWidths, base) {
|
|
36
|
+
const stored = columnWidths?.[column.fieldName];
|
|
37
|
+
if (typeof stored !== "number" || !Number.isFinite(stored)) {
|
|
38
|
+
return base;
|
|
39
|
+
}
|
|
40
|
+
const width = clampColumnWidth(stored, column);
|
|
41
|
+
return { width, minWidth: width };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// engine/ColumnViewport.ts
|
|
45
|
+
function buildCumulativeWidths(widths) {
|
|
46
|
+
const cum = new Array(widths.length + 1);
|
|
47
|
+
cum[0] = 0;
|
|
48
|
+
for (let i = 0; i < widths.length; i += 1) {
|
|
49
|
+
const w = widths[i] ?? 0;
|
|
50
|
+
cum[i + 1] = cum[i] + (Number.isFinite(w) && w > 0 ? w : 0);
|
|
51
|
+
}
|
|
52
|
+
return cum;
|
|
53
|
+
}
|
|
54
|
+
function upperBoundCumulative(cum, value) {
|
|
55
|
+
let lo = 0;
|
|
56
|
+
let hi = cum.length;
|
|
57
|
+
while (lo < hi) {
|
|
58
|
+
const mid = lo + hi >> 1;
|
|
59
|
+
if ((cum[mid] ?? 0) > value) hi = mid;
|
|
60
|
+
else lo = mid + 1;
|
|
61
|
+
}
|
|
62
|
+
return lo;
|
|
63
|
+
}
|
|
64
|
+
function findStartColumnIndex(cum, viewStartInScrollable) {
|
|
65
|
+
if (cum.length <= 1) return 0;
|
|
66
|
+
const idx = upperBoundCumulative(cum, viewStartInScrollable) - 1;
|
|
67
|
+
return Math.max(0, Math.min(cum.length - 2, idx));
|
|
68
|
+
}
|
|
69
|
+
function findEndColumnIndex(cum, viewEndInScrollable) {
|
|
70
|
+
if (cum.length <= 1) return 0;
|
|
71
|
+
upperBoundCumulative(cum, viewEndInScrollable - Number.EPSILON);
|
|
72
|
+
let lo = 0;
|
|
73
|
+
let hi = cum.length - 1;
|
|
74
|
+
while (lo < hi) {
|
|
75
|
+
const mid = lo + hi >> 1;
|
|
76
|
+
if ((cum[mid] ?? 0) >= viewEndInScrollable) hi = mid;
|
|
77
|
+
else lo = mid + 1;
|
|
78
|
+
}
|
|
79
|
+
return Math.max(0, Math.min(cum.length - 1, lo));
|
|
80
|
+
}
|
|
81
|
+
function calculateColumnViewport(scrollableWidths, scrollOffset, viewportSize, pinnedStartWidth = 0, overscan = 1, pinnedEndWidth = 0) {
|
|
82
|
+
const cum = buildCumulativeWidths(scrollableWidths);
|
|
83
|
+
const totalScrollableWidth = cum[cum.length - 1] ?? 0;
|
|
84
|
+
const n = scrollableWidths.length;
|
|
85
|
+
if (n === 0 || viewportSize <= 0) {
|
|
86
|
+
return {
|
|
87
|
+
startIndex: 0,
|
|
88
|
+
endIndex: 0,
|
|
89
|
+
spacerStart: 0,
|
|
90
|
+
spacerEnd: 0,
|
|
91
|
+
totalScrollableWidth,
|
|
92
|
+
visibleCount: 0
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const maxScroll = Math.max(
|
|
96
|
+
0,
|
|
97
|
+
pinnedStartWidth + totalScrollableWidth + pinnedEndWidth - viewportSize
|
|
98
|
+
);
|
|
99
|
+
const clampedScroll = Math.min(Math.max(0, scrollOffset), maxScroll);
|
|
100
|
+
const scrollableViewport = Math.max(
|
|
101
|
+
0,
|
|
102
|
+
viewportSize - pinnedStartWidth - pinnedEndWidth
|
|
103
|
+
);
|
|
104
|
+
const relStart = Math.max(0, clampedScroll - pinnedStartWidth);
|
|
105
|
+
const relEnd = relStart + scrollableViewport;
|
|
106
|
+
let startIndex = findStartColumnIndex(cum, relStart);
|
|
107
|
+
let endIndex = findEndColumnIndex(cum, relEnd);
|
|
108
|
+
startIndex = Math.max(0, startIndex - overscan);
|
|
109
|
+
endIndex = Math.min(n, endIndex + overscan);
|
|
110
|
+
if (endIndex < startIndex) endIndex = startIndex;
|
|
111
|
+
const spacerStart = cum[startIndex] ?? 0;
|
|
112
|
+
const spacerEnd = Math.max(0, totalScrollableWidth - (cum[endIndex] ?? 0));
|
|
113
|
+
return {
|
|
114
|
+
startIndex,
|
|
115
|
+
endIndex,
|
|
116
|
+
spacerStart,
|
|
117
|
+
spacerEnd,
|
|
118
|
+
totalScrollableWidth,
|
|
119
|
+
visibleCount: Math.max(0, endIndex - startIndex)
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function projectColumnSlice(items, range) {
|
|
123
|
+
return items.slice(range.startIndex, range.endIndex);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// engine/ViewportCalculator.ts
|
|
127
|
+
var ViewportCalculator = class {
|
|
128
|
+
static calculate(totalRows, viewport) {
|
|
129
|
+
const safeTotal = Math.max(0, Math.floor(totalRows));
|
|
130
|
+
const { scrollOffset, viewportSize, rowHeight, overscan } = viewport;
|
|
131
|
+
const totalHeight = safeTotal * rowHeight;
|
|
132
|
+
if (safeTotal === 0) {
|
|
133
|
+
return {
|
|
134
|
+
startIndex: 0,
|
|
135
|
+
endIndex: 0,
|
|
136
|
+
startOffset: 0,
|
|
137
|
+
endOffset: 0,
|
|
138
|
+
totalHeight: 0,
|
|
139
|
+
visibleCount: 0
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
const maxOffset = Math.max(0, totalHeight - viewportSize);
|
|
143
|
+
const clampedScroll = Math.min(scrollOffset, maxOffset);
|
|
144
|
+
const rawStart = Math.floor(clampedScroll / rowHeight);
|
|
145
|
+
const rawEnd = Math.ceil((clampedScroll + viewportSize) / rowHeight);
|
|
146
|
+
const startIndex = Math.max(0, rawStart - overscan);
|
|
147
|
+
const endIndex = Math.min(safeTotal, rawEnd + overscan);
|
|
148
|
+
return {
|
|
149
|
+
startIndex,
|
|
150
|
+
endIndex,
|
|
151
|
+
startOffset: startIndex * rowHeight,
|
|
152
|
+
endOffset: Math.max(0, totalHeight - endIndex * rowHeight),
|
|
153
|
+
totalHeight,
|
|
154
|
+
visibleCount: Math.max(0, endIndex - startIndex)
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/** Contiguous index list for the visible window. */
|
|
158
|
+
static indices(range) {
|
|
159
|
+
const out = [];
|
|
160
|
+
for (let i = range.startIndex; i < range.endIndex; i += 1) {
|
|
161
|
+
out.push(i);
|
|
162
|
+
}
|
|
163
|
+
return out;
|
|
164
|
+
}
|
|
165
|
+
/** Slice a dense array by VisibleRange (O(window), not O(n)). */
|
|
166
|
+
static projectRows(rows, range) {
|
|
167
|
+
return rows.slice(range.startIndex, range.endIndex);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Project from sparse structure: ordered id list + Map by id.
|
|
171
|
+
* Suitable for 100k+ tables without materializing full UI rows.
|
|
172
|
+
*/
|
|
173
|
+
static projectByIndex(orderedIds, byId, range) {
|
|
174
|
+
const out = [];
|
|
175
|
+
const end = Math.min(range.endIndex, orderedIds.length);
|
|
176
|
+
for (let i = range.startIndex; i < end; i += 1) {
|
|
177
|
+
const id = orderedIds[i];
|
|
178
|
+
const row = byId.get(id);
|
|
179
|
+
if (row !== void 0) out.push(row);
|
|
180
|
+
}
|
|
181
|
+
return out;
|
|
182
|
+
}
|
|
183
|
+
/** Horizontal column window (PR-98). */
|
|
184
|
+
static calculateColumns(scrollableWidths, scrollOffset, viewportSize, pinnedStartWidth = 0, overscan = 1, pinnedEndWidth = 0) {
|
|
185
|
+
return calculateColumnViewport(
|
|
186
|
+
scrollableWidths,
|
|
187
|
+
scrollOffset,
|
|
188
|
+
viewportSize,
|
|
189
|
+
pinnedStartWidth,
|
|
190
|
+
overscan,
|
|
191
|
+
pinnedEndWidth
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
static projectColumns(items, range) {
|
|
195
|
+
return projectColumnSlice(items, range);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// engine/dataOps/columnPin.ts
|
|
200
|
+
function resolveColumnPinned(column) {
|
|
201
|
+
if (isIndexColumn(column)) return "start";
|
|
202
|
+
const pinned = column.columnDef?.pinned;
|
|
203
|
+
if (pinned === "start" || pinned === "end") return pinned;
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
function partitionColumnsByPin(columns) {
|
|
207
|
+
const pinnedStart = [];
|
|
208
|
+
const scrollable = [];
|
|
209
|
+
const pinnedEnd = [];
|
|
210
|
+
const pinnedStartAbs = [];
|
|
211
|
+
const scrollableAbs = [];
|
|
212
|
+
const pinnedEndAbs = [];
|
|
213
|
+
columns.forEach((col, abs) => {
|
|
214
|
+
const pin = resolveColumnPinned(col);
|
|
215
|
+
if (pin === "start") {
|
|
216
|
+
pinnedStart.push(col);
|
|
217
|
+
pinnedStartAbs.push(abs);
|
|
218
|
+
} else if (pin === "end") {
|
|
219
|
+
pinnedEnd.push(col);
|
|
220
|
+
pinnedEndAbs.push(abs);
|
|
221
|
+
} else {
|
|
222
|
+
scrollable.push(col);
|
|
223
|
+
scrollableAbs.push(abs);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
return {
|
|
227
|
+
pinnedStart,
|
|
228
|
+
scrollable,
|
|
229
|
+
pinnedEnd,
|
|
230
|
+
pinnedStartAbs,
|
|
231
|
+
scrollableAbs,
|
|
232
|
+
pinnedEndAbs
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
function sumColumnWidths(columns, resolveWidth) {
|
|
236
|
+
return columns.reduce((sum, col) => sum + resolveWidth(col), 0);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// engine/dataOps/columnLayout.ts
|
|
240
|
+
function getColumnFlex(column) {
|
|
241
|
+
const flex = column.columnDef?.flex;
|
|
242
|
+
if (typeof flex === "number" && flex > 0 && Number.isFinite(flex)) return flex;
|
|
243
|
+
return 0;
|
|
244
|
+
}
|
|
245
|
+
function isFlexColumn(column, columnWidths) {
|
|
246
|
+
if (getColumnFlex(column) <= 0) return false;
|
|
247
|
+
const stored = columnWidths?.[column.fieldName];
|
|
248
|
+
return !(typeof stored === "number" && Number.isFinite(stored));
|
|
249
|
+
}
|
|
250
|
+
function computeLayoutColumnWidths(columns, columnWidths, containerWidth) {
|
|
251
|
+
const visible = columns.filter((c) => !("hidden" in c && c.hidden));
|
|
252
|
+
if (visible.length === 0) return {};
|
|
253
|
+
const entries = visible.map((col) => ({
|
|
254
|
+
col,
|
|
255
|
+
fieldName: col.fieldName,
|
|
256
|
+
flex: isFlexColumn(col, columnWidths) ? getColumnFlex(col) : 0,
|
|
257
|
+
baseWidth: resolveColumnWidth(col, columnWidths),
|
|
258
|
+
floor: columnWidthFloor(col)
|
|
259
|
+
}));
|
|
260
|
+
const out = {};
|
|
261
|
+
const hasFlex = entries.some((e) => e.flex > 0);
|
|
262
|
+
if (!hasFlex || containerWidth <= 0) {
|
|
263
|
+
for (const e of entries) out[e.fieldName] = e.baseWidth;
|
|
264
|
+
return out;
|
|
265
|
+
}
|
|
266
|
+
let fixedSum = 0;
|
|
267
|
+
let flexMinSum = 0;
|
|
268
|
+
let totalFlex = 0;
|
|
269
|
+
for (const e of entries) {
|
|
270
|
+
if (e.flex > 0) {
|
|
271
|
+
flexMinSum += e.floor;
|
|
272
|
+
totalFlex += e.flex;
|
|
273
|
+
} else {
|
|
274
|
+
fixedSum += e.baseWidth;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
const remaining = containerWidth - fixedSum - flexMinSum;
|
|
278
|
+
for (const e of entries) {
|
|
279
|
+
if (e.flex <= 0) {
|
|
280
|
+
out[e.fieldName] = e.baseWidth;
|
|
281
|
+
} else if (remaining <= 0 || totalFlex <= 0) {
|
|
282
|
+
out[e.fieldName] = e.floor;
|
|
283
|
+
} else {
|
|
284
|
+
const share = remaining * (e.flex / totalFlex);
|
|
285
|
+
out[e.fieldName] = clampColumnWidth(e.floor + share, e.col);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return out;
|
|
289
|
+
}
|
|
290
|
+
function sizeColumnsToFitWidths(columns, columnWidths, containerWidth) {
|
|
291
|
+
const visible = columns.filter((c) => !("hidden" in c && c.hidden));
|
|
292
|
+
if (visible.length === 0 || containerWidth <= 0) return {};
|
|
293
|
+
const current = visible.map((col) => ({
|
|
294
|
+
col,
|
|
295
|
+
colId: col.fieldName,
|
|
296
|
+
width: resolveColumnWidth(col, columnWidths)
|
|
297
|
+
}));
|
|
298
|
+
const total = current.reduce((sum2, c) => sum2 + c.width, 0);
|
|
299
|
+
if (total <= 0) return {};
|
|
300
|
+
const scale = containerWidth / total;
|
|
301
|
+
const out = {};
|
|
302
|
+
for (const c of current) {
|
|
303
|
+
out[c.colId] = clampColumnWidth(c.width * scale, c.col);
|
|
304
|
+
}
|
|
305
|
+
const sum = Object.values(out).reduce((a, b) => a + b, 0);
|
|
306
|
+
const delta = containerWidth - sum;
|
|
307
|
+
if (delta !== 0 && visible.length > 0) {
|
|
308
|
+
const last = visible[visible.length - 1];
|
|
309
|
+
out[last.fieldName] = clampColumnWidth(
|
|
310
|
+
(out[last.fieldName] ?? 0) + delta,
|
|
311
|
+
last
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
return out;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
exports.ViewportCalculator = ViewportCalculator;
|
|
318
|
+
exports.buildCumulativeWidths = buildCumulativeWidths;
|
|
319
|
+
exports.calculateColumnViewport = calculateColumnViewport;
|
|
320
|
+
exports.clampColumnWidth = clampColumnWidth;
|
|
321
|
+
exports.columnSizeStyle = columnSizeStyle;
|
|
322
|
+
exports.computeLayoutColumnWidths = computeLayoutColumnWidths;
|
|
323
|
+
exports.isIndexColumn = isIndexColumn;
|
|
324
|
+
exports.overlayStoredColumnWidth = overlayStoredColumnWidth;
|
|
325
|
+
exports.partitionColumnsByPin = partitionColumnsByPin;
|
|
326
|
+
exports.resolveColumnPinned = resolveColumnPinned;
|
|
327
|
+
exports.resolveColumnWidth = resolveColumnWidth;
|
|
328
|
+
exports.sizeColumnsToFitWidths = sizeColumnsToFitWidths;
|
|
329
|
+
exports.sumColumnWidths = sumColumnWidths;
|
|
330
|
+
//# sourceMappingURL=chunk-UC7PHDM6.cjs.map
|
|
331
|
+
//# sourceMappingURL=chunk-UC7PHDM6.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../engine/columnWidth.ts","../engine/ColumnViewport.ts","../engine/ViewportCalculator.ts","../engine/dataOps/columnPin.ts","../engine/dataOps/columnLayout.ts"],"names":["sum"],"mappings":"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","file":"chunk-UC7PHDM6.cjs","sourcesContent":["export const DEFAULT_COLUMN_MIN_WIDTH = 144;\r\nexport const INDEX_COLUMN_DEFAULT_WIDTH = 168;\r\n\r\nexport type ColumnWidthHint = {\r\n fieldName?: string;\r\n fieldType?: string;\r\n minWidth?: number;\r\n};\r\n\r\nexport function isIndexColumn(column: ColumnWidthHint): boolean {\r\n return column.fieldType === 'index' || column.fieldName === 'index';\r\n}\r\n\r\nexport function columnWidthFloor(column?: ColumnWidthHint): number {\r\n const schemaMin = column?.minWidth ?? 0;\r\n if (column && isIndexColumn(column)) {\r\n return Math.max(INDEX_COLUMN_DEFAULT_WIDTH, schemaMin);\r\n }\r\n return Math.max(DEFAULT_COLUMN_MIN_WIDTH, schemaMin);\r\n}\r\n\r\nexport function clampColumnWidth(\r\n width: number,\r\n column?: ColumnWidthHint,\r\n): number {\r\n const floor = columnWidthFloor(column);\r\n if (!Number.isFinite(width)) return floor;\r\n return Math.max(floor, Math.round(width));\r\n}\r\n\r\nexport function resolveColumnWidth(\r\n column: ColumnWidthHint & { fieldName: string },\r\n columnWidths: Record<string, number> | undefined,\r\n): number {\r\n const stored = columnWidths?.[column.fieldName];\r\n if (typeof stored === 'number' && Number.isFinite(stored)) {\r\n return clampColumnWidth(stored, column);\r\n }\r\n if (isIndexColumn(column)) {\r\n return INDEX_COLUMN_DEFAULT_WIDTH;\r\n }\r\n return column.minWidth ?? DEFAULT_COLUMN_MIN_WIDTH;\r\n}\r\n\r\nexport function columnSizeStyle(\r\n column: ColumnWidthHint & { fieldName: string },\r\n columnWidths: Record<string, number> | undefined,\r\n layoutWidths?: Record<string, number>,\r\n): { width: number; minWidth: number } {\r\n const width =\r\n layoutWidths?.[column.fieldName] ??\r\n resolveColumnWidth(column, columnWidths);\r\n return { width, minWidth: width };\r\n}\r\n\r\n/** Apply a stored session width on top of a surface-specific fallback (mobile). */\r\nexport function overlayStoredColumnWidth(\r\n column: ColumnWidthHint & { fieldName: string },\r\n columnWidths: Record<string, number> | undefined,\r\n base: { width?: number; minWidth?: number; maxWidth?: number },\r\n): { width?: number; minWidth?: number; maxWidth?: number } {\r\n const stored = columnWidths?.[column.fieldName];\r\n if (typeof stored !== 'number' || !Number.isFinite(stored)) {\r\n return base;\r\n }\r\n const width = clampColumnWidth(stored, column);\r\n return { width, minWidth: width };\r\n}\r\n","/**\r\n * Horizontal column window (PR-98).\r\n * Variable-width columns via cumulative widths + binary search.\r\n * Pinned columns are excluded from the scrollable slice (always rendered by the host).\r\n */\r\n\r\nexport type ColumnVisibleRange = {\r\n /** Inclusive start into the scrollable-widths array. */\r\n startIndex: number;\r\n /** Exclusive end into the scrollable-widths array. */\r\n endIndex: number;\r\n /** px before the first visible scrollable column. */\r\n spacerStart: number;\r\n /** px after the last visible scrollable column. */\r\n spacerEnd: number;\r\n totalScrollableWidth: number;\r\n visibleCount: number;\r\n};\r\n\r\n/** Prefix sums: `cum[i]` = sum(widths[0..i)). Length = widths.length + 1. */\r\nexport function buildCumulativeWidths(widths: readonly number[]): number[] {\r\n const cum = new Array<number>(widths.length + 1);\r\n cum[0] = 0;\r\n for (let i = 0; i < widths.length; i += 1) {\r\n const w = widths[i] ?? 0;\r\n cum[i + 1] = cum[i]! + (Number.isFinite(w) && w > 0 ? w : 0);\r\n }\r\n return cum;\r\n}\r\n\r\n/** First index `i` where `cum[i] > value` (cum is non-decreasing). */\r\nexport function upperBoundCumulative(cum: readonly number[], value: number): number {\r\n let lo = 0;\r\n let hi = cum.length;\r\n while (lo < hi) {\r\n const mid = (lo + hi) >> 1;\r\n if ((cum[mid] ?? 0) > value) hi = mid;\r\n else lo = mid + 1;\r\n }\r\n return lo;\r\n}\r\n\r\n/**\r\n * First scrollable column whose end exceeds `viewStart` (absolute px from table start).\r\n * `cum` is relative to the scrollable region (starts at 0).\r\n */\r\nexport function findStartColumnIndex(\r\n cum: readonly number[],\r\n viewStartInScrollable: number,\r\n): number {\r\n if (cum.length <= 1) return 0;\r\n // first i where cum[i+1] > viewStart ⇔ upperBound(cum, viewStart) - 1, clamped\r\n const idx = upperBoundCumulative(cum, viewStartInScrollable) - 1;\r\n return Math.max(0, Math.min(cum.length - 2, idx));\r\n}\r\n\r\n/** First column index whose start is >= viewEnd (exclusive end). */\r\nexport function findEndColumnIndex(\r\n cum: readonly number[],\r\n viewEndInScrollable: number,\r\n): number {\r\n if (cum.length <= 1) return 0;\r\n const idx = upperBoundCumulative(cum, viewEndInScrollable - Number.EPSILON);\r\n // upperBound returns first cum[i] > viewEnd-ε; we want first start >= viewEnd\r\n // If cum[i] is start of column i, first i with cum[i] >= viewEnd:\r\n let lo = 0;\r\n let hi = cum.length - 1;\r\n while (lo < hi) {\r\n const mid = (lo + hi) >> 1;\r\n if ((cum[mid] ?? 0) >= viewEndInScrollable) hi = mid;\r\n else lo = mid + 1;\r\n }\r\n return Math.max(0, Math.min(cum.length - 1, lo));\r\n}\r\n\r\n/**\r\n * @param scrollableWidths widths of non-pinned columns in document order\r\n * @param scrollOffset absolute scroll from table inline-start (px)\r\n * @param viewportSize visible width of the scrollport (px)\r\n * @param pinnedStartWidth total width of inline-start pinned columns (px)\r\n * @param overscan extra columns on each side\r\n * @param pinnedEndWidth total width of inline-end pinned columns (px)\r\n */\r\nexport function calculateColumnViewport(\r\n scrollableWidths: readonly number[],\r\n scrollOffset: number,\r\n viewportSize: number,\r\n pinnedStartWidth = 0,\r\n overscan = 1,\r\n pinnedEndWidth = 0,\r\n): ColumnVisibleRange {\r\n const cum = buildCumulativeWidths(scrollableWidths);\r\n const totalScrollableWidth = cum[cum.length - 1] ?? 0;\r\n const n = scrollableWidths.length;\r\n\r\n if (n === 0 || viewportSize <= 0) {\r\n return {\r\n startIndex: 0,\r\n endIndex: 0,\r\n spacerStart: 0,\r\n spacerEnd: 0,\r\n totalScrollableWidth,\r\n visibleCount: 0,\r\n };\r\n }\r\n\r\n const maxScroll = Math.max(\r\n 0,\r\n pinnedStartWidth + totalScrollableWidth + pinnedEndWidth - viewportSize,\r\n );\r\n const clampedScroll = Math.min(Math.max(0, scrollOffset), maxScroll);\r\n const scrollableViewport = Math.max(\r\n 0,\r\n viewportSize - pinnedStartWidth - pinnedEndWidth,\r\n );\r\n\r\n const relStart = Math.max(0, clampedScroll - pinnedStartWidth);\r\n const relEnd = relStart + scrollableViewport;\r\n\r\n let startIndex = findStartColumnIndex(cum, relStart);\r\n let endIndex = findEndColumnIndex(cum, relEnd);\r\n\r\n startIndex = Math.max(0, startIndex - overscan);\r\n endIndex = Math.min(n, endIndex + overscan);\r\n if (endIndex < startIndex) endIndex = startIndex;\r\n\r\n const spacerStart = cum[startIndex] ?? 0;\r\n const spacerEnd = Math.max(0, totalScrollableWidth - (cum[endIndex] ?? 0));\r\n\r\n return {\r\n startIndex,\r\n endIndex,\r\n spacerStart,\r\n spacerEnd,\r\n totalScrollableWidth,\r\n visibleCount: Math.max(0, endIndex - startIndex),\r\n };\r\n}\r\n\r\nexport function projectColumnSlice<T>(\r\n items: readonly T[],\r\n range: ColumnVisibleRange,\r\n): T[] {\r\n return items.slice(range.startIndex, range.endIndex);\r\n}\r\n","import { Viewport, type VisibleRange } from '../domain/value-objects/Viewport';\r\nimport {\r\n calculateColumnViewport,\r\n projectColumnSlice,\r\n type ColumnVisibleRange,\r\n} from './ColumnViewport';\r\n\r\nexport type { ColumnVisibleRange } from './ColumnViewport';\r\nexport {\r\n buildCumulativeWidths,\r\n calculateColumnViewport,\r\n projectColumnSlice,\r\n} from './ColumnViewport';\r\n\r\n/**\r\n * Pure virtual-window calculator — no DOM / window / document.\r\n * Vertical: totalRows + Viewport → VisibleRange.\r\n * Horizontal (PR-98): scrollable widths + scroll → ColumnVisibleRange.\r\n */\r\nexport class ViewportCalculator {\r\n static calculate(totalRows: number, viewport: Viewport): VisibleRange {\r\n const safeTotal = Math.max(0, Math.floor(totalRows));\r\n const { scrollOffset, viewportSize, rowHeight, overscan } = viewport;\r\n const totalHeight = safeTotal * rowHeight;\r\n\r\n if (safeTotal === 0) {\r\n return {\r\n startIndex: 0,\r\n endIndex: 0,\r\n startOffset: 0,\r\n endOffset: 0,\r\n totalHeight: 0,\r\n visibleCount: 0,\r\n };\r\n }\r\n\r\n const maxOffset = Math.max(0, totalHeight - viewportSize);\r\n const clampedScroll = Math.min(scrollOffset, maxOffset);\r\n\r\n const rawStart = Math.floor(clampedScroll / rowHeight);\r\n const rawEnd = Math.ceil((clampedScroll + viewportSize) / rowHeight);\r\n\r\n const startIndex = Math.max(0, rawStart - overscan);\r\n const endIndex = Math.min(safeTotal, rawEnd + overscan);\r\n\r\n return {\r\n startIndex,\r\n endIndex,\r\n startOffset: startIndex * rowHeight,\r\n endOffset: Math.max(0, totalHeight - endIndex * rowHeight),\r\n totalHeight,\r\n visibleCount: Math.max(0, endIndex - startIndex),\r\n };\r\n }\r\n\r\n /** Contiguous index list for the visible window. */\r\n static indices(range: VisibleRange): number[] {\r\n const out: number[] = [];\r\n for (let i = range.startIndex; i < range.endIndex; i += 1) {\r\n out.push(i);\r\n }\r\n return out;\r\n }\r\n\r\n /** Slice a dense array by VisibleRange (O(window), not O(n)). */\r\n static projectRows<T>(rows: readonly T[], range: VisibleRange): T[] {\r\n return rows.slice(range.startIndex, range.endIndex);\r\n }\r\n\r\n /**\r\n * Project from sparse structure: ordered id list + Map by id.\r\n * Suitable for 100k+ tables without materializing full UI rows.\r\n */\r\n static projectByIndex<T>(\r\n orderedIds: readonly number[],\r\n byId: ReadonlyMap<number, T>,\r\n range: VisibleRange,\r\n ): T[] {\r\n const out: T[] = [];\r\n const end = Math.min(range.endIndex, orderedIds.length);\r\n for (let i = range.startIndex; i < end; i += 1) {\r\n const id = orderedIds[i];\r\n const row = byId.get(id);\r\n if (row !== undefined) out.push(row);\r\n }\r\n return out;\r\n }\r\n\r\n /** Horizontal column window (PR-98). */\r\n static calculateColumns(\r\n scrollableWidths: readonly number[],\r\n scrollOffset: number,\r\n viewportSize: number,\r\n pinnedStartWidth = 0,\r\n overscan = 1,\r\n pinnedEndWidth = 0,\r\n ): ColumnVisibleRange {\r\n return calculateColumnViewport(\r\n scrollableWidths,\r\n scrollOffset,\r\n viewportSize,\r\n pinnedStartWidth,\r\n overscan,\r\n pinnedEndWidth,\r\n );\r\n }\r\n\r\n static projectColumns<T>(\r\n items: readonly T[],\r\n range: ColumnVisibleRange,\r\n ): T[] {\r\n return projectColumnSlice(items, range);\r\n }\r\n}\r\n","/**\r\n * Column pin partitioning (PR-110 / D19).\r\n * Pure — no React/DOM.\r\n */\r\n\r\nimport type { ColumnPinned } from '../../domain/types/ColumnDef';\r\nimport type { ColumnSchema } from '../../domain/types/ColumnSchema';\r\nimport { isIndexColumn } from '../columnWidth';\r\n\r\nexport type ColumnPinSide = 'start' | 'end';\r\n\r\nexport type ColumnPinPartition = {\r\n pinnedStart: ColumnSchema[];\r\n scrollable: ColumnSchema[];\r\n pinnedEnd: ColumnSchema[];\r\n /** Absolute index in the full visible list for each entry. */\r\n pinnedStartAbs: number[];\r\n scrollableAbs: number[];\r\n pinnedEndAbs: number[];\r\n};\r\n\r\n/** Index column is always pinned at inline-start (D19 supersedes D10). */\r\nexport function resolveColumnPinned(\r\n column: ColumnSchema,\r\n): ColumnPinned {\r\n if (isIndexColumn(column)) return 'start';\r\n const pinned = column.columnDef?.pinned;\r\n if (pinned === 'start' || pinned === 'end') return pinned;\r\n return null;\r\n}\r\n\r\nexport function isPinnedColumn(column: ColumnSchema): boolean {\r\n return resolveColumnPinned(column) != null;\r\n}\r\n\r\nexport function partitionColumnsByPin(\r\n columns: readonly ColumnSchema[],\r\n): ColumnPinPartition {\r\n const pinnedStart: ColumnSchema[] = [];\r\n const scrollable: ColumnSchema[] = [];\r\n const pinnedEnd: ColumnSchema[] = [];\r\n const pinnedStartAbs: number[] = [];\r\n const scrollableAbs: number[] = [];\r\n const pinnedEndAbs: number[] = [];\r\n\r\n columns.forEach((col, abs) => {\r\n const pin = resolveColumnPinned(col);\r\n if (pin === 'start') {\r\n pinnedStart.push(col);\r\n pinnedStartAbs.push(abs);\r\n } else if (pin === 'end') {\r\n pinnedEnd.push(col);\r\n pinnedEndAbs.push(abs);\r\n } else {\r\n scrollable.push(col);\r\n scrollableAbs.push(abs);\r\n }\r\n });\r\n\r\n return {\r\n pinnedStart,\r\n scrollable,\r\n pinnedEnd,\r\n pinnedStartAbs,\r\n scrollableAbs,\r\n pinnedEndAbs,\r\n };\r\n}\r\n\r\nexport function computePinOffsets(\r\n columns: readonly ColumnSchema[],\r\n resolveWidth: (col: ColumnSchema) => number,\r\n): Record<string, number> {\r\n const offsets: Record<string, number> = {};\r\n let cursor = 0;\r\n for (const col of columns) {\r\n offsets[col.fieldName] = cursor;\r\n cursor += resolveWidth(col);\r\n }\r\n return offsets;\r\n}\r\n\r\nexport function computeEndPinOffsets(\r\n columns: readonly ColumnSchema[],\r\n resolveWidth: (col: ColumnSchema) => number,\r\n): Record<string, number> {\r\n const offsets: Record<string, number> = {};\r\n let cursor = 0;\r\n for (let i = columns.length - 1; i >= 0; i -= 1) {\r\n const col = columns[i]!;\r\n offsets[col.fieldName] = cursor;\r\n cursor += resolveWidth(col);\r\n }\r\n return offsets;\r\n}\r\n\r\nexport function sumColumnWidths(\r\n columns: readonly ColumnSchema[],\r\n resolveWidth: (col: ColumnSchema) => number,\r\n): number {\r\n return columns.reduce((sum, col) => sum + resolveWidth(col), 0);\r\n}\r\n","import {\r\n clampColumnWidth,\r\n columnWidthFloor,\r\n resolveColumnWidth,\r\n type ColumnWidthHint,\r\n} from '../columnWidth';\r\n\r\nexport type ColumnFlexHint = ColumnWidthHint & {\r\n fieldName: string;\r\n columnDef?: { flex?: number };\r\n};\r\n\r\n/** Flex weight from `ColumnDef.flex` (via `columnDef` bridge). */\r\nexport function getColumnFlex(column: ColumnFlexHint): number {\r\n const flex = column.columnDef?.flex;\r\n if (typeof flex === 'number' && flex > 0 && Number.isFinite(flex)) return flex;\r\n return 0;\r\n}\r\n\r\n/** Flex applies only when the column has flex and no explicit session width. */\r\nexport function isFlexColumn(\r\n column: ColumnFlexHint,\r\n columnWidths: Record<string, number> | undefined,\r\n): boolean {\r\n if (getColumnFlex(column) <= 0) return false;\r\n const stored = columnWidths?.[column.fieldName];\r\n return !(typeof stored === 'number' && Number.isFinite(stored));\r\n}\r\n\r\n/**\r\n * Distribute remaining container width to flex columns (PR-112).\r\n * Fixed columns keep `resolveColumnWidth`; flex columns grow from their floor.\r\n */\r\nexport function computeLayoutColumnWidths(\r\n columns: readonly ColumnFlexHint[],\r\n columnWidths: Record<string, number> | undefined,\r\n containerWidth: number,\r\n): Record<string, number> {\r\n const visible = columns.filter((c) => !('hidden' in c && c.hidden));\r\n if (visible.length === 0) return {};\r\n\r\n const entries = visible.map((col) => ({\r\n col,\r\n fieldName: col.fieldName,\r\n flex: isFlexColumn(col, columnWidths) ? getColumnFlex(col) : 0,\r\n baseWidth: resolveColumnWidth(col, columnWidths),\r\n floor: columnWidthFloor(col),\r\n }));\r\n\r\n const out: Record<string, number> = {};\r\n const hasFlex = entries.some((e) => e.flex > 0);\r\n\r\n if (!hasFlex || containerWidth <= 0) {\r\n for (const e of entries) out[e.fieldName] = e.baseWidth;\r\n return out;\r\n }\r\n\r\n let fixedSum = 0;\r\n let flexMinSum = 0;\r\n let totalFlex = 0;\r\n for (const e of entries) {\r\n if (e.flex > 0) {\r\n flexMinSum += e.floor;\r\n totalFlex += e.flex;\r\n } else {\r\n fixedSum += e.baseWidth;\r\n }\r\n }\r\n\r\n const remaining = containerWidth - fixedSum - flexMinSum;\r\n\r\n for (const e of entries) {\r\n if (e.flex <= 0) {\r\n out[e.fieldName] = e.baseWidth;\r\n } else if (remaining <= 0 || totalFlex <= 0) {\r\n out[e.fieldName] = e.floor;\r\n } else {\r\n const share = remaining * (e.flex / totalFlex);\r\n out[e.fieldName] = clampColumnWidth(e.floor + share, e.col);\r\n }\r\n }\r\n\r\n return out;\r\n}\r\n\r\n/**\r\n * Scale visible column widths proportionally to fit `containerWidth` (PR-112).\r\n */\r\nexport function sizeColumnsToFitWidths(\r\n columns: readonly ColumnFlexHint[],\r\n columnWidths: Record<string, number> | undefined,\r\n containerWidth: number,\r\n): Record<string, number> {\r\n const visible = columns.filter((c) => !('hidden' in c && c.hidden));\r\n if (visible.length === 0 || containerWidth <= 0) return {};\r\n\r\n const current = visible.map((col) => ({\r\n col,\r\n colId: col.fieldName,\r\n width: resolveColumnWidth(col, columnWidths),\r\n }));\r\n\r\n const total = current.reduce((sum, c) => sum + c.width, 0);\r\n if (total <= 0) return {};\r\n\r\n const scale = containerWidth / total;\r\n const out: Record<string, number> = {};\r\n for (const c of current) {\r\n out[c.colId] = clampColumnWidth(c.width * scale, c.col);\r\n }\r\n\r\n const sum = Object.values(out).reduce((a, b) => a + b, 0);\r\n const delta = containerWidth - sum;\r\n if (delta !== 0 && visible.length > 0) {\r\n const last = visible[visible.length - 1]!;\r\n out[last.fieldName] = clampColumnWidth(\r\n (out[last.fieldName] ?? 0) + delta,\r\n last,\r\n );\r\n }\r\n\r\n return out;\r\n}\r\n"]}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// application/presence/GridPresenceService.ts
|
|
2
|
+
var PEER_COLORS = [
|
|
3
|
+
"#0ea5e9",
|
|
4
|
+
"#f59e0b",
|
|
5
|
+
"#10b981",
|
|
6
|
+
"#ef4444",
|
|
7
|
+
"#8b5cf6",
|
|
8
|
+
"#ec4899"
|
|
9
|
+
];
|
|
10
|
+
function hashColor(id) {
|
|
11
|
+
let h = 0;
|
|
12
|
+
for (let i = 0; i < id.length; i += 1) {
|
|
13
|
+
h = h * 31 + id.charCodeAt(i) >>> 0;
|
|
14
|
+
}
|
|
15
|
+
return PEER_COLORS[h % PEER_COLORS.length];
|
|
16
|
+
}
|
|
17
|
+
var GridPresenceService = class {
|
|
18
|
+
constructor(options) {
|
|
19
|
+
this.options = options;
|
|
20
|
+
this.peers = /* @__PURE__ */ new Map();
|
|
21
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
22
|
+
this.unsub = null;
|
|
23
|
+
this.disposed = false;
|
|
24
|
+
const peerId = options.peerId ?? `peer:${options.actorId}:${Math.random().toString(36).slice(2, 9)}`;
|
|
25
|
+
this.local = {
|
|
26
|
+
peerId,
|
|
27
|
+
actorId: options.actorId,
|
|
28
|
+
label: options.label ?? options.actorId,
|
|
29
|
+
color: options.color ?? hashColor(peerId),
|
|
30
|
+
rowId: null,
|
|
31
|
+
columnId: null
|
|
32
|
+
};
|
|
33
|
+
this.staleMs = options.staleMs ?? 15e3;
|
|
34
|
+
this.unsub = options.transport.subscribe((message) => {
|
|
35
|
+
this.onMessage(message);
|
|
36
|
+
});
|
|
37
|
+
this.broadcast();
|
|
38
|
+
}
|
|
39
|
+
getLocal() {
|
|
40
|
+
return { ...this.local };
|
|
41
|
+
}
|
|
42
|
+
getPeers() {
|
|
43
|
+
this.pruneStale();
|
|
44
|
+
return [...this.peers.values()].filter(
|
|
45
|
+
(p) => p.peerId !== this.local.peerId
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
setActiveCell(rowId, columnId) {
|
|
49
|
+
if (this.disposed) return;
|
|
50
|
+
this.local.rowId = rowId;
|
|
51
|
+
this.local.columnId = columnId;
|
|
52
|
+
this.broadcast();
|
|
53
|
+
}
|
|
54
|
+
dispose() {
|
|
55
|
+
if (this.disposed) return;
|
|
56
|
+
this.disposed = true;
|
|
57
|
+
this.options.transport.publish({
|
|
58
|
+
kind: "leave",
|
|
59
|
+
peerId: this.local.peerId
|
|
60
|
+
});
|
|
61
|
+
this.unsub?.();
|
|
62
|
+
this.unsub = null;
|
|
63
|
+
this.peers.clear();
|
|
64
|
+
this.emit();
|
|
65
|
+
}
|
|
66
|
+
subscribe(listener) {
|
|
67
|
+
this.listeners.add(listener);
|
|
68
|
+
listener(this.getPeers());
|
|
69
|
+
return () => this.listeners.delete(listener);
|
|
70
|
+
}
|
|
71
|
+
broadcast() {
|
|
72
|
+
const peer = {
|
|
73
|
+
peerId: this.local.peerId,
|
|
74
|
+
actorId: this.local.actorId,
|
|
75
|
+
label: this.local.label,
|
|
76
|
+
color: this.local.color,
|
|
77
|
+
rowId: this.local.rowId,
|
|
78
|
+
columnId: this.local.columnId,
|
|
79
|
+
updatedAt: Date.now()
|
|
80
|
+
};
|
|
81
|
+
this.options.transport.publish({ kind: "presence", peer });
|
|
82
|
+
}
|
|
83
|
+
onMessage(message) {
|
|
84
|
+
if (message.kind === "leave") {
|
|
85
|
+
if (message.peerId === this.local.peerId) return;
|
|
86
|
+
this.peers.delete(message.peerId);
|
|
87
|
+
this.emit();
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (message.peer.peerId === this.local.peerId) return;
|
|
91
|
+
this.peers.set(message.peer.peerId, message.peer);
|
|
92
|
+
this.emit();
|
|
93
|
+
}
|
|
94
|
+
pruneStale() {
|
|
95
|
+
const cutoff = Date.now() - this.staleMs;
|
|
96
|
+
for (const [id, peer] of this.peers) {
|
|
97
|
+
if (peer.updatedAt < cutoff) this.peers.delete(id);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
emit() {
|
|
101
|
+
const snapshot = this.getPeers();
|
|
102
|
+
for (const listener of this.listeners) listener(snapshot);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export { GridPresenceService };
|
|
107
|
+
//# sourceMappingURL=chunk-UXVLYUUW.js.map
|
|
108
|
+
//# sourceMappingURL=chunk-UXVLYUUW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../application/presence/GridPresenceService.ts"],"names":[],"mappings":"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","file":"chunk-UXVLYUUW.js","sourcesContent":["import type {\r\n PresenceLocalState,\r\n PresenceMessage,\r\n PresencePeer,\r\n PresencePort,\r\n PresenceTransport,\r\n} from '../ports/PresencePort';\r\n\r\nconst PEER_COLORS = [\r\n '#0ea5e9',\r\n '#f59e0b',\r\n '#10b981',\r\n '#ef4444',\r\n '#8b5cf6',\r\n '#ec4899',\r\n];\r\n\r\nexport type GridPresenceServiceOptions = {\r\n readonly tableId: string;\r\n readonly actorId: string;\r\n readonly label?: string;\r\n readonly transport: PresenceTransport;\r\n readonly peerId?: string;\r\n readonly color?: string;\r\n /** Drop peers quieter than this (ms). Default 15s. */\r\n readonly staleMs?: number;\r\n};\r\n\r\nfunction hashColor(id: string): string {\r\n let h = 0;\r\n for (let i = 0; i < id.length; i += 1) {\r\n h = (h * 31 + id.charCodeAt(i)) >>> 0;\r\n }\r\n return PEER_COLORS[h % PEER_COLORS.length]!;\r\n}\r\n\r\n/**\r\n * PresencePort: broadcast local cursor/selection; track remote peers (PR-139).\r\n * Does not merge cell values — editing different cells stays conflict-free.\r\n */\r\nexport class GridPresenceService implements PresencePort {\r\n private readonly local: PresenceLocalState;\r\n private peers = new Map<string, PresencePeer>();\r\n private readonly listeners = new Set<\r\n (peers: readonly PresencePeer[]) => void\r\n >();\r\n private unsub: (() => void) | null = null;\r\n private disposed = false;\r\n private readonly staleMs: number;\r\n\r\n constructor(private readonly options: GridPresenceServiceOptions) {\r\n const peerId =\r\n options.peerId ??\r\n `peer:${options.actorId}:${Math.random().toString(36).slice(2, 9)}`;\r\n this.local = {\r\n peerId,\r\n actorId: options.actorId,\r\n label: options.label ?? options.actorId,\r\n color: options.color ?? hashColor(peerId),\r\n rowId: null,\r\n columnId: null,\r\n };\r\n this.staleMs = options.staleMs ?? 15_000;\r\n this.unsub = options.transport.subscribe((message) => {\r\n this.onMessage(message);\r\n });\r\n this.broadcast();\r\n }\r\n\r\n getLocal(): PresenceLocalState {\r\n return { ...this.local };\r\n }\r\n\r\n getPeers(): readonly PresencePeer[] {\r\n this.pruneStale();\r\n return [...this.peers.values()].filter(\r\n (p) => p.peerId !== this.local.peerId,\r\n );\r\n }\r\n\r\n setActiveCell(rowId: number | null, columnId: string | null): void {\r\n if (this.disposed) return;\r\n this.local.rowId = rowId;\r\n this.local.columnId = columnId;\r\n this.broadcast();\r\n }\r\n\r\n dispose(): void {\r\n if (this.disposed) return;\r\n this.disposed = true;\r\n this.options.transport.publish({\r\n kind: 'leave',\r\n peerId: this.local.peerId,\r\n });\r\n this.unsub?.();\r\n this.unsub = null;\r\n this.peers.clear();\r\n this.emit();\r\n }\r\n\r\n subscribe(listener: (peers: readonly PresencePeer[]) => void): () => void {\r\n this.listeners.add(listener);\r\n listener(this.getPeers());\r\n return () => this.listeners.delete(listener);\r\n }\r\n\r\n private broadcast(): void {\r\n const peer: PresencePeer = {\r\n peerId: this.local.peerId,\r\n actorId: this.local.actorId,\r\n label: this.local.label,\r\n color: this.local.color,\r\n rowId: this.local.rowId,\r\n columnId: this.local.columnId,\r\n updatedAt: Date.now(),\r\n };\r\n this.options.transport.publish({ kind: 'presence', peer });\r\n }\r\n\r\n private onMessage(message: PresenceMessage): void {\r\n if (message.kind === 'leave') {\r\n if (message.peerId === this.local.peerId) return;\r\n this.peers.delete(message.peerId);\r\n this.emit();\r\n return;\r\n }\r\n if (message.peer.peerId === this.local.peerId) return;\r\n this.peers.set(message.peer.peerId, message.peer);\r\n this.emit();\r\n }\r\n\r\n private pruneStale(): void {\r\n const cutoff = Date.now() - this.staleMs;\r\n for (const [id, peer] of this.peers) {\r\n if (peer.updatedAt < cutoff) this.peers.delete(id);\r\n }\r\n }\r\n\r\n private emit(): void {\r\n const snapshot = this.getPeers();\r\n for (const listener of this.listeners) listener(snapshot);\r\n }\r\n}\r\n"]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkBHDRUZH5_cjs = require('./chunk-BHDRUZH5.cjs');
|
|
4
|
+
|
|
5
|
+
// packages/plugins/excel/src/buildExportTable.ts
|
|
6
|
+
var EMPTY_PLACEHOLDERS = /* @__PURE__ */ new Set(["\u0627\u0646\u062A\u062E\u0627\u0628 \u06A9\u0646\u06CC\u062F", "select", "Select"]);
|
|
7
|
+
var hasMeaningfulValue = (value) => value !== void 0 && value !== null && value !== "";
|
|
8
|
+
function cellText(source, column) {
|
|
9
|
+
const cell = source.cells[column.fieldName];
|
|
10
|
+
if (!cell) return "";
|
|
11
|
+
const raw = hasMeaningfulValue(cell.display) ? cell.display : cell.value;
|
|
12
|
+
if (!hasMeaningfulValue(raw)) return "";
|
|
13
|
+
const text = chunkBHDRUZH5_cjs.formatExportValue(raw, column.fieldType).trim();
|
|
14
|
+
if (!text || EMPTY_PLACEHOLDERS.has(text)) return "";
|
|
15
|
+
return text;
|
|
16
|
+
}
|
|
17
|
+
function buildExportTable(source) {
|
|
18
|
+
const columnsWithData = source.columns.filter(
|
|
19
|
+
(column) => source.rows.some((row) => cellText(row, column) !== "")
|
|
20
|
+
);
|
|
21
|
+
return {
|
|
22
|
+
columns: columnsWithData.map((c) => ({
|
|
23
|
+
fieldName: c.fieldName,
|
|
24
|
+
caption: c.fieldCaption ?? c.fieldName
|
|
25
|
+
})),
|
|
26
|
+
rows: source.rows.map(
|
|
27
|
+
(row) => columnsWithData.map((col) => cellText(row, col))
|
|
28
|
+
),
|
|
29
|
+
rowKinds: source.rows.map((row) => row.kind ?? "leaf"),
|
|
30
|
+
outlineLevels: source.rows.map(
|
|
31
|
+
(row) => typeof row.outlineLevel === "number" ? row.outlineLevel : 0
|
|
32
|
+
)
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
exports.buildExportTable = buildExportTable;
|
|
37
|
+
//# sourceMappingURL=chunk-VVGYRZ7S.cjs.map
|
|
38
|
+
//# sourceMappingURL=chunk-VVGYRZ7S.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../packages/plugins/excel/src/buildExportTable.ts"],"names":["formatExportValue"],"mappings":";;;;;AAMA,IAAM,qCAAqB,IAAI,GAAA,CAAI,CAAC,+DAAA,EAAe,QAAA,EAAU,QAAQ,CAAC,CAAA;AAYtE,IAAM,qBAAqB,CAAC,KAAA,KAC1B,UAAU,MAAA,IAAa,KAAA,KAAU,QAAQ,KAAA,KAAU,EAAA;AAErD,SAAS,QAAA,CACP,QACA,MAAA,EACQ;AACR,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,SAAS,CAAA;AAC1C,EAAA,IAAI,CAAC,MAAM,OAAO,EAAA;AAElB,EAAA,MAAM,MAAM,kBAAA,CAAmB,IAAA,CAAK,OAAO,CAAA,GAAI,IAAA,CAAK,UAAU,IAAA,CAAK,KAAA;AACnE,EAAA,IAAI,CAAC,kBAAA,CAAmB,GAAG,CAAA,EAAG,OAAO,EAAA;AAErC,EAAA,MAAM,OAAOA,mCAAA,CAAkB,GAAA,EAAK,MAAA,CAAO,SAAS,EAAE,IAAA,EAAK;AAC3D,EAAA,IAAI,CAAC,IAAA,IAAQ,kBAAA,CAAmB,GAAA,CAAI,IAAI,GAAG,OAAO,EAAA;AAClD,EAAA,OAAO,IAAA;AACT;AAKO,SAAS,iBAAiB,MAAA,EAAmC;AAClE,EAAA,MAAM,eAAA,GAAkB,OAAO,OAAA,CAAQ,MAAA;AAAA,IAAO,CAAC,MAAA,KAC7C,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,CAAC,GAAA,KAAQ,QAAA,CAAS,GAAA,EAAK,MAAM,CAAA,KAAM,EAAE;AAAA,GACxD;AAEA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,eAAA,CAAgB,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MACnC,WAAW,CAAA,CAAE,SAAA;AAAA,MACb,OAAA,EAAS,CAAA,CAAE,YAAA,IAAgB,CAAA,CAAE;AAAA,KAC/B,CAAE,CAAA;AAAA,IACF,IAAA,EAAM,OAAO,IAAA,CAAK,GAAA;AAAA,MAAI,CAAC,QACrB,eAAA,CAAgB,GAAA,CAAI,CAAC,GAAA,KAAQ,QAAA,CAAS,GAAA,EAAK,GAAG,CAAC;AAAA,KACjD;AAAA,IACA,QAAA,EAAU,OAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,KAAQ,GAAA,CAAI,QAAQ,MAAM,CAAA;AAAA,IACrD,aAAA,EAAe,OAAO,IAAA,CAAK,GAAA;AAAA,MAAI,CAAC,GAAA,KAC9B,OAAO,IAAI,YAAA,KAAiB,QAAA,GAAW,IAAI,YAAA,GAAe;AAAA;AAC5D,GACF;AACF","file":"chunk-VVGYRZ7S.cjs","sourcesContent":["import type {\r\n ExportColumnDef,\r\n ExportSource,\r\n} from '../../../../application/plugins/GridPlugin';\r\nimport { formatExportValue } from './formatExportValue';\r\n\r\nconst EMPTY_PLACEHOLDERS = new Set(['انتخاب کنید', 'select', 'Select']);\r\n\r\nexport type ExportTable = {\r\n columns: Array<{ fieldName: string; caption: string }>;\r\n /** Parallel to columns; already stringified cell text */\r\n rows: string[][];\r\n /** Parallel to rows (PR-122). Absent ⇒ all leaf. */\r\n rowKinds?: Array<'group' | 'leaf' | 'total'>;\r\n /** Excel outlineLevel per data row (PR-122). */\r\n outlineLevels?: number[];\r\n};\r\n\r\nconst hasMeaningfulValue = (value: unknown) =>\r\n value !== undefined && value !== null && value !== '';\r\n\r\nfunction cellText(\r\n source: ExportSource['rows'][number],\r\n column: ExportColumnDef,\r\n): string {\r\n const cell = source.cells[column.fieldName];\r\n if (!cell) return '';\r\n\r\n const raw = hasMeaningfulValue(cell.display) ? cell.display : cell.value;\r\n if (!hasMeaningfulValue(raw)) return '';\r\n\r\n const text = formatExportValue(raw, column.fieldType).trim();\r\n if (!text || EMPTY_PLACEHOLDERS.has(text)) return '';\r\n return text;\r\n}\r\n\r\n/**\r\n * Builds a dense string matrix from ExportSource (plugin query port).\r\n */\r\nexport function buildExportTable(source: ExportSource): ExportTable {\r\n const columnsWithData = source.columns.filter((column) =>\r\n source.rows.some((row) => cellText(row, column) !== ''),\r\n );\r\n\r\n return {\r\n columns: columnsWithData.map((c) => ({\r\n fieldName: c.fieldName,\r\n caption: c.fieldCaption ?? c.fieldName,\r\n })),\r\n rows: source.rows.map((row) =>\r\n columnsWithData.map((col) => cellText(row, col)),\r\n ),\r\n rowKinds: source.rows.map((row) => row.kind ?? 'leaf'),\r\n outlineLevels: source.rows.map((row) =>\r\n typeof row.outlineLevel === 'number' ? row.outlineLevel : 0,\r\n ),\r\n };\r\n}\r\n"]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { jalaliToGregorianDate, gregorianDateToJalali, jalaliAdapter } from './chunk-GQEDLUMB.js';
|
|
2
|
+
|
|
3
|
+
// infrastructure/finance/holidays.ts
|
|
4
|
+
var IRAN_FIXED_HOLIDAYS = [
|
|
5
|
+
{ jm: 1, jd: 1, title: "\u0646\u0648\u0631\u0648\u0632" },
|
|
6
|
+
{ jm: 1, jd: 2, title: "\u0639\u06CC\u062F \u0646\u0648\u0631\u0648\u0632" },
|
|
7
|
+
{ jm: 1, jd: 3, title: "\u0639\u06CC\u062F \u0646\u0648\u0631\u0648\u0632" },
|
|
8
|
+
{ jm: 1, jd: 4, title: "\u0639\u06CC\u062F \u0646\u0648\u0631\u0648\u0632" },
|
|
9
|
+
{ jm: 1, jd: 12, title: "\u0631\u0648\u0632 \u062C\u0645\u0647\u0648\u0631\u06CC \u0627\u0633\u0644\u0627\u0645\u06CC" },
|
|
10
|
+
{ jm: 1, jd: 13, title: "\u0633\u06CC\u0632\u062F\u0647\u200C\u0628\u0647\u200C\u062F\u0631" },
|
|
11
|
+
{ jm: 3, jd: 14, title: "\u0631\u062D\u0644\u062A \u0627\u0645\u0627\u0645 \u062E\u0645\u06CC\u0646\u06CC" },
|
|
12
|
+
{ jm: 3, jd: 15, title: "\u0642\u06CC\u0627\u0645 \u06F1\u06F5 \u062E\u0631\u062F\u0627\u062F" },
|
|
13
|
+
{ jm: 11, jd: 22, title: "\u067E\u06CC\u0631\u0648\u0632\u06CC \u0627\u0646\u0642\u0644\u0627\u0628 \u0627\u0633\u0644\u0627\u0645\u06CC" },
|
|
14
|
+
{ jm: 12, jd: 29, title: "\u0645\u0644\u06CC \u0634\u062F\u0646 \u0635\u0646\u0639\u062A \u0646\u0641\u062A" }
|
|
15
|
+
];
|
|
16
|
+
function utcDay(date) {
|
|
17
|
+
return new Date(
|
|
18
|
+
Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 12)
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
function iranHolidaysForYear(jalaliYear, extra = []) {
|
|
22
|
+
const combined = [...IRAN_FIXED_HOLIDAYS, ...extra].filter(
|
|
23
|
+
(h) => h.jy == null || h.jy === jalaliYear
|
|
24
|
+
);
|
|
25
|
+
return combined.map((h) => ({
|
|
26
|
+
...h,
|
|
27
|
+
jy: jalaliYear,
|
|
28
|
+
date: jalaliToGregorianDate(jalaliYear, h.jm, h.jd)
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
31
|
+
function isIranHoliday(date, extra = []) {
|
|
32
|
+
const { jy, jm, jd } = gregorianDateToJalali(utcDay(date));
|
|
33
|
+
return iranHolidaysForYear(jy, extra).some(
|
|
34
|
+
(h) => h.jm === jm && h.jd === jd
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
function holidayTitle(date, extra = []) {
|
|
38
|
+
const { jy, jm, jd } = gregorianDateToJalali(utcDay(date));
|
|
39
|
+
const hit = iranHolidaysForYear(jy, extra).find(
|
|
40
|
+
(h) => h.jm === jm && h.jd === jd
|
|
41
|
+
);
|
|
42
|
+
return hit?.title ?? null;
|
|
43
|
+
}
|
|
44
|
+
function nextBusinessDay(date, extra = []) {
|
|
45
|
+
let cursor = jalaliAdapter.addDays(utcDay(date), 1);
|
|
46
|
+
for (let i = 0; i < 366; i += 1) {
|
|
47
|
+
const dow = cursor.getUTCDay();
|
|
48
|
+
if (dow !== 5 && !isIranHoliday(cursor, extra)) return cursor;
|
|
49
|
+
cursor = jalaliAdapter.addDays(cursor, 1);
|
|
50
|
+
}
|
|
51
|
+
return cursor;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { IRAN_FIXED_HOLIDAYS, holidayTitle, iranHolidaysForYear, isIranHoliday, nextBusinessDay };
|
|
55
|
+
//# sourceMappingURL=chunk-W5256BJ4.js.map
|
|
56
|
+
//# sourceMappingURL=chunk-W5256BJ4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../infrastructure/finance/holidays.ts"],"names":[],"mappings":"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","file":"chunk-W5256BJ4.js","sourcesContent":["/**\r\n * Iranian official holidays (Jalali fixed dates) (PR-140).\r\n * Lunar/Islamic moveable holidays can be merged via `extra`.\r\n */\r\n\r\nimport {\r\n gregorianDateToJalali,\r\n jalaliToGregorianDate,\r\n} from '../date/jalaliMath';\r\nimport { jalaliAdapter } from '../date/jalaliAdapter';\r\n\r\nexport type IranHoliday = {\r\n /** Jalali month 1–12 */\r\n jm: number;\r\n /** Jalali day */\r\n jd: number;\r\n title: string;\r\n /** When set, holiday applies only to that Jalali year */\r\n jy?: number;\r\n};\r\n\r\n/** Civil / solar fixed holidays observed every Jalali year. */\r\nexport const IRAN_FIXED_HOLIDAYS: readonly IranHoliday[] = [\r\n { jm: 1, jd: 1, title: 'نوروز' },\r\n { jm: 1, jd: 2, title: 'عید نوروز' },\r\n { jm: 1, jd: 3, title: 'عید نوروز' },\r\n { jm: 1, jd: 4, title: 'عید نوروز' },\r\n { jm: 1, jd: 12, title: 'روز جمهوری اسلامی' },\r\n { jm: 1, jd: 13, title: 'سیزدهبهدر' },\r\n { jm: 3, jd: 14, title: 'رحلت امام خمینی' },\r\n { jm: 3, jd: 15, title: 'قیام ۱۵ خرداد' },\r\n { jm: 11, jd: 22, title: 'پیروزی انقلاب اسلامی' },\r\n { jm: 12, jd: 29, title: 'ملی شدن صنعت نفت' },\r\n];\r\n\r\nfunction utcDay(date: Date): Date {\r\n return new Date(\r\n Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 12),\r\n );\r\n}\r\n\r\nexport function iranHolidaysForYear(\r\n jalaliYear: number,\r\n extra: readonly IranHoliday[] = [],\r\n): Array<IranHoliday & { date: Date }> {\r\n const combined = [...IRAN_FIXED_HOLIDAYS, ...extra].filter(\r\n (h) => h.jy == null || h.jy === jalaliYear,\r\n );\r\n return combined.map((h) => ({\r\n ...h,\r\n jy: jalaliYear,\r\n date: jalaliToGregorianDate(jalaliYear, h.jm, h.jd),\r\n }));\r\n}\r\n\r\nexport function isIranHoliday(\r\n date: Date,\r\n extra: readonly IranHoliday[] = [],\r\n): boolean {\r\n const { jy, jm, jd } = gregorianDateToJalali(utcDay(date));\r\n return iranHolidaysForYear(jy, extra).some(\r\n (h) => h.jm === jm && h.jd === jd,\r\n );\r\n}\r\n\r\nexport function holidayTitle(\r\n date: Date,\r\n extra: readonly IranHoliday[] = [],\r\n): string | null {\r\n const { jy, jm, jd } = gregorianDateToJalali(utcDay(date));\r\n const hit = iranHolidaysForYear(jy, extra).find(\r\n (h) => h.jm === jm && h.jd === jd,\r\n );\r\n return hit?.title ?? null;\r\n}\r\n\r\n/** Skip Fridays (Iran weekend) and holidays; returns next open day. */\r\nexport function nextBusinessDay(\r\n date: Date,\r\n extra: readonly IranHoliday[] = [],\r\n): Date {\r\n let cursor = jalaliAdapter.addDays(utcDay(date), 1);\r\n for (let i = 0; i < 366; i += 1) {\r\n const dow = cursor.getUTCDay(); // 5 = Friday\r\n if (dow !== 5 && !isIranHoliday(cursor, extra)) return cursor;\r\n cursor = jalaliAdapter.addDays(cursor, 1);\r\n }\r\n return cursor;\r\n}\r\n"]}
|