@ai-matrx/design-system 0.22.0 → 0.26.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/CHANGELOG.md +227 -0
- package/dist/data-table/cell-undo.cjs +98 -0
- package/dist/data-table/cell-undo.cjs.map +1 -0
- package/dist/data-table/cell-undo.d.cts +85 -0
- package/dist/data-table/cell-undo.d.ts +85 -0
- package/dist/data-table/cell-undo.js +78 -0
- package/dist/data-table/cell-undo.js.map +1 -0
- package/dist/data-table/copy-helpers.d.cts +7 -2
- package/dist/data-table/copy-helpers.d.ts +7 -2
- package/dist/data-table/coverage.cjs +116 -0
- package/dist/data-table/coverage.cjs.map +1 -0
- package/dist/data-table/coverage.d.cts +65 -0
- package/dist/data-table/coverage.d.ts +65 -0
- package/dist/data-table/coverage.js +96 -0
- package/dist/data-table/coverage.js.map +1 -0
- package/dist/data-table/data-row-inspector.cjs.map +1 -1
- package/dist/data-table/data-row-inspector.js.map +1 -1
- package/dist/data-table/data-row-window.cjs.map +1 -1
- package/dist/data-table/data-row-window.js.map +1 -1
- package/dist/data-table/facets.cjs +118 -0
- package/dist/data-table/facets.cjs.map +1 -0
- package/dist/data-table/facets.d.cts +100 -0
- package/dist/data-table/facets.d.ts +100 -0
- package/dist/data-table/facets.js +98 -0
- package/dist/data-table/facets.js.map +1 -0
- package/dist/data-table/fill.cjs +299 -0
- package/dist/data-table/fill.cjs.map +1 -0
- package/dist/data-table/fill.d.cts +129 -0
- package/dist/data-table/fill.d.ts +129 -0
- package/dist/data-table/fill.js +277 -0
- package/dist/data-table/fill.js.map +1 -0
- package/dist/data-table/filter-engine.d.cts +7 -2
- package/dist/data-table/filter-engine.d.ts +7 -2
- package/dist/data-table/grid-clipboard.cjs +165 -0
- package/dist/data-table/grid-clipboard.cjs.map +1 -0
- package/dist/data-table/grid-clipboard.d.cts +85 -0
- package/dist/data-table/grid-clipboard.d.ts +85 -0
- package/dist/data-table/grid-clipboard.js +145 -0
- package/dist/data-table/grid-clipboard.js.map +1 -0
- package/dist/data-table/grid-selection.cjs +258 -0
- package/dist/data-table/grid-selection.cjs.map +1 -0
- package/dist/data-table/grid-selection.d.cts +166 -0
- package/dist/data-table/grid-selection.d.ts +166 -0
- package/dist/data-table/grid-selection.js +238 -0
- package/dist/data-table/grid-selection.js.map +1 -0
- package/dist/data-table/grouping.cjs +302 -0
- package/dist/data-table/grouping.cjs.map +1 -0
- package/dist/data-table/grouping.d.cts +119 -0
- package/dist/data-table/grouping.d.ts +119 -0
- package/dist/data-table/grouping.js +282 -0
- package/dist/data-table/grouping.js.map +1 -0
- package/dist/data-table/host.cjs.map +1 -1
- package/dist/data-table/host.d.cts +18 -4
- package/dist/data-table/host.d.ts +18 -4
- package/dist/data-table/host.js.map +1 -1
- package/dist/data-table/index.cjs +3173 -451
- package/dist/data-table/index.cjs.map +1 -1
- package/dist/data-table/index.d.cts +13 -3
- package/dist/data-table/index.d.ts +13 -3
- package/dist/data-table/index.js +3174 -451
- package/dist/data-table/index.js.map +1 -1
- package/dist/data-table/infer-filter.d.cts +7 -2
- package/dist/data-table/infer-filter.d.ts +7 -2
- package/dist/data-table/layered-filters.d.cts +7 -2
- package/dist/data-table/layered-filters.d.ts +7 -2
- package/dist/data-table/menu-targets.cjs +77 -0
- package/dist/data-table/menu-targets.cjs.map +1 -0
- package/dist/data-table/menu-targets.d.cts +108 -0
- package/dist/data-table/menu-targets.d.ts +108 -0
- package/dist/data-table/menu-targets.js +57 -0
- package/dist/data-table/menu-targets.js.map +1 -0
- package/dist/data-table/pagination.cjs.map +1 -1
- package/dist/data-table/pagination.js.map +1 -1
- package/dist/data-table/query-control.d.cts +7 -2
- package/dist/data-table/query-control.d.ts +7 -2
- package/dist/data-table/spreadsheet.cjs +1062 -0
- package/dist/data-table/spreadsheet.cjs.map +1 -0
- package/dist/data-table/spreadsheet.d.cts +153 -0
- package/dist/data-table/spreadsheet.d.ts +153 -0
- package/dist/data-table/spreadsheet.js +1042 -0
- package/dist/data-table/spreadsheet.js.map +1 -0
- package/dist/data-table/types.cjs.map +1 -1
- package/dist/data-table/types.d.cts +7 -2
- package/dist/data-table/types.d.ts +7 -2
- package/dist/data-table/url-state.d.cts +7 -2
- package/dist/data-table/url-state.d.ts +7 -2
- package/dist/data-table/uuid-cell.cjs.map +1 -1
- package/dist/data-table/uuid-cell.js.map +1 -1
- package/dist/data-table/validation.cjs +229 -0
- package/dist/data-table/validation.cjs.map +1 -0
- package/dist/data-table/validation.d.cts +125 -0
- package/dist/data-table/validation.d.ts +125 -0
- package/dist/data-table/validation.js +209 -0
- package/dist/data-table/validation.js.map +1 -0
- package/dist/data-table/virtual-window.cjs +203 -0
- package/dist/data-table/virtual-window.cjs.map +1 -0
- package/dist/data-table/virtual-window.d.cts +84 -0
- package/dist/data-table/virtual-window.d.ts +84 -0
- package/dist/data-table/virtual-window.js +183 -0
- package/dist/data-table/virtual-window.js.map +1 -0
- package/dist/data-table/xlsx.d.cts +7 -2
- package/dist/data-table/xlsx.d.ts +7 -2
- package/dist/field-formats/index.d.cts +2 -2
- package/dist/field-formats/index.d.ts +2 -2
- package/dist/formulas/index.cjs +1041 -0
- package/dist/formulas/index.cjs.map +1 -0
- package/dist/formulas/index.d.cts +389 -0
- package/dist/formulas/index.d.ts +389 -0
- package/dist/formulas/index.js +1019 -0
- package/dist/formulas/index.js.map +1 -0
- package/dist/{types-BdbvlF9-.d.cts → types-CJWU1Gae.d.cts} +1 -1
- package/dist/{types-BdbvlF9-.d.ts → types-CJWU1Gae.d.ts} +1 -1
- package/dist/{types-D-flTpK0.d.ts → types-Cu5_eUG1.d.ts} +268 -4
- package/dist/{types-Sn249eoy.d.cts → types-DrJXAAoD.d.cts} +268 -4
- package/package.json +129 -2
|
@@ -35,8 +35,11 @@ __export(data_table_exports, {
|
|
|
35
35
|
CELL_TINT_CLASS: () => CELL_TINT_CLASS,
|
|
36
36
|
COLOR_RULE_OPS: () => COLOR_RULE_OPS,
|
|
37
37
|
COLOR_RULE_OP_LABELS: () => COLOR_RULE_OP_LABELS,
|
|
38
|
+
DEFAULT_OVERSCAN: () => DEFAULT_OVERSCAN,
|
|
39
|
+
DEFAULT_UNDO_DEPTH: () => DEFAULT_UNDO_DEPTH,
|
|
38
40
|
DataRowInspector: () => DataRowInspector,
|
|
39
41
|
DataRowWindow: () => DataRowWindow,
|
|
42
|
+
EMPTY_GROUP_KEY: () => EMPTY_GROUP_KEY,
|
|
40
43
|
EMPTY_TABLE_STYLE: () => EMPTY_TABLE_STYLE,
|
|
41
44
|
FORMAT_MISMATCH_CLASS: () => FORMAT_MISMATCH_CLASS,
|
|
42
45
|
FormattedCell: () => FormattedCell,
|
|
@@ -47,6 +50,7 @@ __export(data_table_exports, {
|
|
|
47
50
|
MatrxUuidCell: () => MatrxUuidCell,
|
|
48
51
|
NO_FROZEN_COLUMNS: () => NO_FROZEN_COLUMNS,
|
|
49
52
|
OPS_WITH_VALUE: () => OPS_WITH_VALUE,
|
|
53
|
+
PARTIAL_BADGE: () => PARTIAL_BADGE,
|
|
50
54
|
ROW_TINT_CLASS: () => ROW_TINT_CLASS,
|
|
51
55
|
STYLE_COLORS: () => STYLE_COLORS,
|
|
52
56
|
STYLE_COLOR_LABELS: () => STYLE_COLOR_LABELS,
|
|
@@ -56,22 +60,62 @@ __export(data_table_exports, {
|
|
|
56
60
|
TABLE_STYLE_VERSION: () => TABLE_STYLE_VERSION,
|
|
57
61
|
TableTitleRow: () => TableTitleRow,
|
|
58
62
|
TableViewTabs: () => TableViewTabs,
|
|
63
|
+
UNKNOWN_TOTAL_BADGE: () => UNKNOWN_TOTAL_BADGE,
|
|
59
64
|
alignForFormat: () => alignForFormat,
|
|
65
|
+
allRange: () => allRange,
|
|
60
66
|
applyStylePath: () => applyStylePath,
|
|
67
|
+
boundsContain: () => boundsContain,
|
|
61
68
|
buildRowAgentInput: () => buildRowAgentInput,
|
|
62
69
|
buildViewAgentInput: () => buildViewAgentInput,
|
|
63
70
|
buildViewHuman: () => buildViewHuman,
|
|
71
|
+
canRedo: () => canRedo,
|
|
72
|
+
canUndo: () => canUndo,
|
|
73
|
+
cellClipboardText: () => cellClipboardText,
|
|
74
|
+
cellDomKey: () => cellDomKey,
|
|
75
|
+
cellsInRange: () => cellsInRange,
|
|
76
|
+
classifyGridKey: () => classifyGridKey,
|
|
77
|
+
coerceGroupNumber: () => coerceGroupNumber,
|
|
64
78
|
collectSelectOptions: () => collectSelectOptions,
|
|
65
79
|
colorForChoice: () => colorForChoice,
|
|
80
|
+
columnRange: () => columnRange,
|
|
81
|
+
computeVariableWindow: () => computeVariableWindow,
|
|
82
|
+
computeWindow: () => computeWindow,
|
|
83
|
+
createUndoStack: () => createUndoStack,
|
|
84
|
+
describeCoverage: () => describeCoverage,
|
|
85
|
+
detectSeries: () => detectSeries,
|
|
86
|
+
directClickKinds: () => directClickKinds,
|
|
66
87
|
downloadTableAsXlsx: () => downloadTableAsXlsx,
|
|
67
88
|
evaluateRule: () => evaluateRule,
|
|
89
|
+
fillDown: () => fillDown,
|
|
90
|
+
fillRange: () => fillRange,
|
|
91
|
+
fillTargetFor: () => fillTargetFor,
|
|
68
92
|
filterKindLabel: () => filterKindLabel,
|
|
93
|
+
flattenGroups: () => flattenGroups,
|
|
69
94
|
formatColumnValue: () => formatColumnValue,
|
|
95
|
+
formatGroupNumber: () => formatGroupNumber,
|
|
96
|
+
gridToTsv: () => gridToTsv,
|
|
97
|
+
groupKeyOf: () => groupKeyOf,
|
|
98
|
+
groupRows: () => groupRows,
|
|
99
|
+
groupSummary: () => groupSummary,
|
|
70
100
|
inferTableSearchRole: () => inferTableSearchRole,
|
|
101
|
+
isBlankGroupValue: () => isBlankGroupValue,
|
|
102
|
+
isDirectClickEditor: () => isDirectClickEditor,
|
|
103
|
+
isGroupCollapsed: () => isGroupCollapsed,
|
|
104
|
+
isSingleCell: () => isSingleCell,
|
|
105
|
+
isSingleCellRange: () => isSingleCellRange,
|
|
71
106
|
isStyleColor: () => isStyleColor,
|
|
107
|
+
moveSelection: () => moveSelection,
|
|
108
|
+
parseClipboardGrid: () => parseClipboardGrid,
|
|
72
109
|
parseTableStyle: () => parseTableStyle,
|
|
73
110
|
parseTableViewSnapshot: () => parseTableViewSnapshot,
|
|
74
111
|
pixelWidth: () => pixelWidth,
|
|
112
|
+
planPaste: () => planPaste,
|
|
113
|
+
popRedo: () => popRedo,
|
|
114
|
+
popUndo: () => popUndo,
|
|
115
|
+
pushUndo: () => pushUndo,
|
|
116
|
+
rangeBounds: () => rangeBounds,
|
|
117
|
+
rangeRows: () => rangeRows,
|
|
118
|
+
rangeSize: () => rangeSize,
|
|
75
119
|
rankTableSearchRows: () => rankTableSearchRows,
|
|
76
120
|
resolveCellColor: () => resolveCellColor,
|
|
77
121
|
resolveColumnMarker: () => resolveColumnMarker,
|
|
@@ -79,23 +123,31 @@ __export(data_table_exports, {
|
|
|
79
123
|
resolveFrozenColumns: () => resolveFrozenColumns,
|
|
80
124
|
resolveRowColor: () => resolveRowColor,
|
|
81
125
|
resolveTableSearchScopes: () => resolveTableSearchScopes,
|
|
126
|
+
rowRange: () => rowRange,
|
|
82
127
|
rowsToCsvFromColumns: () => rowsToCsvFromColumns,
|
|
83
128
|
rowsToMarkdownTable: () => rowsToMarkdownTable,
|
|
84
129
|
rowsToRecordsFromColumns: () => rowsToRecordsFromColumns,
|
|
130
|
+
sameCell: () => sameCell,
|
|
131
|
+
scrollOffsetForIndex: () => scrollOffsetForIndex,
|
|
85
132
|
shortUuid: () => shortUuid,
|
|
133
|
+
storedValuesEqual: () => storedValuesEqual,
|
|
86
134
|
stylePath: () => stylePath,
|
|
87
135
|
tableStyleFromMetadata: () => tableStyleFromMetadata,
|
|
88
136
|
tableStyleIsEmpty: () => tableStyleIsEmpty,
|
|
89
137
|
tableUrlParamPrefix: () => tableUrlParamPrefix,
|
|
138
|
+
tileIndex: () => tileIndex,
|
|
139
|
+
toggleGroupCollapsed: () => toggleGroupCollapsed,
|
|
140
|
+
undoEntryFor: () => undoEntryFor,
|
|
90
141
|
useMatrxDataTableHost: () => useMatrxDataTableHost,
|
|
91
142
|
useMatrxTableRowAlchemy: () => useMatrxTableRowAlchemy,
|
|
92
143
|
useScrollPagination: () => useScrollPagination,
|
|
144
|
+
useSpreadsheetGrid: () => useSpreadsheetGrid,
|
|
93
145
|
useTableUrlState: () => useTableUrlState
|
|
94
146
|
});
|
|
95
147
|
module.exports = __toCommonJS(data_table_exports);
|
|
96
148
|
|
|
97
149
|
// src/data-table/MatrxDataTable.tsx
|
|
98
|
-
var
|
|
150
|
+
var import_react21 = require("react");
|
|
99
151
|
var import_core3 = require("@dnd-kit/core");
|
|
100
152
|
|
|
101
153
|
// src/data-table/icons.tsx
|
|
@@ -5175,10 +5227,10 @@ function passesColumnFilter(value, filter) {
|
|
|
5175
5227
|
if (raw === "") return false;
|
|
5176
5228
|
const normalized = raw.replace(/[^0-9.-]/g, "");
|
|
5177
5229
|
if (normalized === "") return false;
|
|
5178
|
-
const
|
|
5179
|
-
if (!Number.isFinite(
|
|
5180
|
-
if (filter.min !== void 0 &&
|
|
5181
|
-
if (filter.max !== void 0 &&
|
|
5230
|
+
const n2 = typeof value === "number" ? value : Number(normalized);
|
|
5231
|
+
if (!Number.isFinite(n2)) return false;
|
|
5232
|
+
if (filter.min !== void 0 && n2 < filter.min) return false;
|
|
5233
|
+
if (filter.max !== void 0 && n2 > filter.max) return false;
|
|
5182
5234
|
return true;
|
|
5183
5235
|
}
|
|
5184
5236
|
}
|
|
@@ -5241,26 +5293,26 @@ function filterAndSortRows(rows, columns, columnFilters, sort, globalSearch, any
|
|
|
5241
5293
|
return result;
|
|
5242
5294
|
}
|
|
5243
5295
|
function countActiveColumnFilters(filters) {
|
|
5244
|
-
let
|
|
5296
|
+
let n2 = 0;
|
|
5245
5297
|
for (const f of Object.values(filters)) {
|
|
5246
5298
|
if (!f) continue;
|
|
5247
5299
|
switch (f.kind) {
|
|
5248
5300
|
case "text":
|
|
5249
|
-
if (f.value.trim() || f.mode && f.mode !== "contains")
|
|
5301
|
+
if (f.value.trim() || f.mode && f.mode !== "contains") n2 += 1;
|
|
5250
5302
|
break;
|
|
5251
5303
|
case "select":
|
|
5252
5304
|
if (f.values !== void 0 || f.value && f.value !== "__all__")
|
|
5253
|
-
|
|
5305
|
+
n2 += 1;
|
|
5254
5306
|
break;
|
|
5255
5307
|
case "boolean":
|
|
5256
|
-
|
|
5308
|
+
n2 += 1;
|
|
5257
5309
|
break;
|
|
5258
5310
|
case "number":
|
|
5259
|
-
if (f.min !== void 0 || f.max !== void 0)
|
|
5311
|
+
if (f.min !== void 0 || f.max !== void 0) n2 += 1;
|
|
5260
5312
|
break;
|
|
5261
5313
|
}
|
|
5262
5314
|
}
|
|
5263
|
-
return
|
|
5315
|
+
return n2;
|
|
5264
5316
|
}
|
|
5265
5317
|
function isColumnFilterActive(filter) {
|
|
5266
5318
|
if (!filter) return false;
|
|
@@ -5512,11 +5564,11 @@ var import_react11 = require("react");
|
|
|
5512
5564
|
var import_url_state = require("@ai-matrx/kit/url-state");
|
|
5513
5565
|
function parseSort(raw) {
|
|
5514
5566
|
if (!raw) return null;
|
|
5515
|
-
const
|
|
5516
|
-
if (
|
|
5517
|
-
const direction = raw.slice(
|
|
5567
|
+
const at2 = raw.lastIndexOf(".");
|
|
5568
|
+
if (at2 <= 0) return null;
|
|
5569
|
+
const direction = raw.slice(at2 + 1);
|
|
5518
5570
|
if (direction !== "asc" && direction !== "desc") return null;
|
|
5519
|
-
return { id: raw.slice(0,
|
|
5571
|
+
return { id: raw.slice(0, at2), direction };
|
|
5520
5572
|
}
|
|
5521
5573
|
function parseObject(raw, fallback) {
|
|
5522
5574
|
if (!raw) return fallback;
|
|
@@ -5539,8 +5591,8 @@ function parseLayeredFilters(raw) {
|
|
|
5539
5591
|
}
|
|
5540
5592
|
}
|
|
5541
5593
|
function positiveInt(raw, fallback) {
|
|
5542
|
-
const
|
|
5543
|
-
return Number.isFinite(
|
|
5594
|
+
const n2 = raw ? Number.parseInt(raw, 10) : Number.NaN;
|
|
5595
|
+
return Number.isFinite(n2) && n2 > 0 ? n2 : fallback;
|
|
5544
5596
|
}
|
|
5545
5597
|
function tableUrlParamPrefix(tableId) {
|
|
5546
5598
|
if (!/^[a-z][a-z0-9-]{0,63}$/.test(tableId)) {
|
|
@@ -5879,6 +5931,95 @@ var CommandShortcut = ({
|
|
|
5879
5931
|
};
|
|
5880
5932
|
CommandShortcut.displayName = "CommandShortcut";
|
|
5881
5933
|
|
|
5934
|
+
// src/data-table/facets.ts
|
|
5935
|
+
var MAX_LISTABLE_FACET_LENGTH = 300;
|
|
5936
|
+
var DEFAULT_FACET_LIMIT = 200;
|
|
5937
|
+
var MAX_FACET_LIMIT = 500;
|
|
5938
|
+
function facetText(raw) {
|
|
5939
|
+
if (raw === null || raw === void 0) return "";
|
|
5940
|
+
if (typeof raw === "object") {
|
|
5941
|
+
try {
|
|
5942
|
+
return JSON.stringify(raw);
|
|
5943
|
+
} catch {
|
|
5944
|
+
return String(raw);
|
|
5945
|
+
}
|
|
5946
|
+
}
|
|
5947
|
+
return String(raw);
|
|
5948
|
+
}
|
|
5949
|
+
function computeColumnFacets(args) {
|
|
5950
|
+
const { columnId: columnId2, rows, readValue: readValue2 } = args;
|
|
5951
|
+
const limit = Math.min(Math.max(args.limit ?? DEFAULT_FACET_LIMIT, 1), MAX_FACET_LIMIT);
|
|
5952
|
+
const counts = /* @__PURE__ */ new Map();
|
|
5953
|
+
const longValues = /* @__PURE__ */ new Set();
|
|
5954
|
+
let blank = 0;
|
|
5955
|
+
let maxLength = 0;
|
|
5956
|
+
for (const row of rows) {
|
|
5957
|
+
let raw;
|
|
5958
|
+
try {
|
|
5959
|
+
raw = readValue2(row, columnId2);
|
|
5960
|
+
} catch {
|
|
5961
|
+
raw = void 0;
|
|
5962
|
+
}
|
|
5963
|
+
const trimmed = facetText(raw).trim();
|
|
5964
|
+
if (trimmed === "") {
|
|
5965
|
+
blank += 1;
|
|
5966
|
+
continue;
|
|
5967
|
+
}
|
|
5968
|
+
if (trimmed.length > maxLength) maxLength = trimmed.length;
|
|
5969
|
+
if (trimmed.length > MAX_LISTABLE_FACET_LENGTH) {
|
|
5970
|
+
longValues.add(trimmed);
|
|
5971
|
+
continue;
|
|
5972
|
+
}
|
|
5973
|
+
counts.set(trimmed, (counts.get(trimmed) ?? 0) + 1);
|
|
5974
|
+
}
|
|
5975
|
+
const values = [...counts.entries()].map(([value, count]) => ({ value, count })).sort((a, b) => b.count - a.count || a.value.localeCompare(b.value)).slice(0, limit);
|
|
5976
|
+
return {
|
|
5977
|
+
columnId: columnId2,
|
|
5978
|
+
totalRows: rows.length,
|
|
5979
|
+
filled: rows.length - blank,
|
|
5980
|
+
blank,
|
|
5981
|
+
distinctCount: counts.size + longValues.size,
|
|
5982
|
+
maxLength,
|
|
5983
|
+
unlistable: longValues.size,
|
|
5984
|
+
limit,
|
|
5985
|
+
truncated: counts.size > limit,
|
|
5986
|
+
values,
|
|
5987
|
+
answeredBy: "local",
|
|
5988
|
+
complete: args.complete ?? true
|
|
5989
|
+
};
|
|
5990
|
+
}
|
|
5991
|
+
function localFacetsAreComplete(loadedRowCount, total) {
|
|
5992
|
+
if (total === void 0 || !Number.isFinite(total) || total < 0) return false;
|
|
5993
|
+
return loadedRowCount >= total;
|
|
5994
|
+
}
|
|
5995
|
+
var NUMBERS = new Intl.NumberFormat("en-US");
|
|
5996
|
+
function n(value) {
|
|
5997
|
+
try {
|
|
5998
|
+
return NUMBERS.format(value);
|
|
5999
|
+
} catch {
|
|
6000
|
+
return String(value);
|
|
6001
|
+
}
|
|
6002
|
+
}
|
|
6003
|
+
function describeFacetSource(facets, noun = "row") {
|
|
6004
|
+
if (!facets) return "";
|
|
6005
|
+
const plural2 = `${noun}s`;
|
|
6006
|
+
if (!facets.complete) {
|
|
6007
|
+
return `These counts cover the ${n(facets.totalRows)} ${plural2} loaded here, not the whole table.`;
|
|
6008
|
+
}
|
|
6009
|
+
if (facets.truncated) {
|
|
6010
|
+
return `Showing the ${n(facets.values.length)} most common of ${n(facets.distinctCount)} values.`;
|
|
6011
|
+
}
|
|
6012
|
+
if (facets.unlistable > 0) {
|
|
6013
|
+
return `${n(facets.unlistable)} ${facets.unlistable === 1 ? "value is" : "values are"} too long to list. Match text instead to reach ${facets.unlistable === 1 ? "it" : "them"}.`;
|
|
6014
|
+
}
|
|
6015
|
+
return "";
|
|
6016
|
+
}
|
|
6017
|
+
var FACETS_LOADING_NOTICE = "Counting values\u2026";
|
|
6018
|
+
function describeFacetFailure(error) {
|
|
6019
|
+
const detail = error instanceof Error ? error.message : String(error ?? "");
|
|
6020
|
+
return detail ? `The values in this column could not be counted: ${detail} Match text instead.` : "The values in this column could not be counted. Match text instead.";
|
|
6021
|
+
}
|
|
6022
|
+
|
|
5882
6023
|
// src/data-table/column-marker.ts
|
|
5883
6024
|
var MARKER_ACCESSORS = {
|
|
5884
6025
|
favorite: "favorite",
|
|
@@ -5946,6 +6087,10 @@ function ColumnHeaderCell({
|
|
|
5946
6087
|
filterFooterHint,
|
|
5947
6088
|
allowNegation = false,
|
|
5948
6089
|
allowNullModes = false,
|
|
6090
|
+
facets,
|
|
6091
|
+
facetsLoading = false,
|
|
6092
|
+
facetsError,
|
|
6093
|
+
onFilterOpen,
|
|
5949
6094
|
reorderColumn
|
|
5950
6095
|
}) {
|
|
5951
6096
|
const reorderEnabled = reorderColumn !== void 0;
|
|
@@ -5980,6 +6125,11 @@ function ColumnHeaderCell({
|
|
|
5980
6125
|
setPendingNegation(filterValue?.negated ?? false);
|
|
5981
6126
|
}
|
|
5982
6127
|
}, [filterOpen, filterValue]);
|
|
6128
|
+
const notifyOpen = (0, import_react13.useRef)(onFilterOpen);
|
|
6129
|
+
notifyOpen.current = onFilterOpen;
|
|
6130
|
+
(0, import_react13.useEffect)(() => {
|
|
6131
|
+
if (filterOpen) notifyOpen.current?.();
|
|
6132
|
+
}, [filterOpen]);
|
|
5983
6133
|
const applyFilter = () => {
|
|
5984
6134
|
onFilterChange(draftFilter);
|
|
5985
6135
|
setFilterOpen(false);
|
|
@@ -6074,6 +6224,9 @@ function ColumnHeaderCell({
|
|
|
6074
6224
|
selectOptions,
|
|
6075
6225
|
selectSingle,
|
|
6076
6226
|
selectAllowCustom,
|
|
6227
|
+
facets: facets ?? null,
|
|
6228
|
+
facetsLoading,
|
|
6229
|
+
...facetsError === void 0 ? {} : { facetsError },
|
|
6077
6230
|
...markerLabels ? {
|
|
6078
6231
|
booleanLabels: {
|
|
6079
6232
|
all: "All",
|
|
@@ -6298,8 +6451,43 @@ function FilterBody({
|
|
|
6298
6451
|
selectSingle = false,
|
|
6299
6452
|
selectAllowCustom = false,
|
|
6300
6453
|
allowNullModes = false,
|
|
6301
|
-
booleanLabels
|
|
6454
|
+
booleanLabels,
|
|
6455
|
+
facets = null,
|
|
6456
|
+
facetsLoading = false,
|
|
6457
|
+
facetsError
|
|
6302
6458
|
}) {
|
|
6459
|
+
const checklist = facetsLoading || facetsError || facets && (facets.values.length > 0 || facets.blank > 0) ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6460
|
+
FacetChecklist,
|
|
6461
|
+
{
|
|
6462
|
+
facets,
|
|
6463
|
+
loading: facetsLoading,
|
|
6464
|
+
...facetsError === void 0 ? {} : { error: facetsError },
|
|
6465
|
+
value,
|
|
6466
|
+
onChange
|
|
6467
|
+
}
|
|
6468
|
+
) : null;
|
|
6469
|
+
if (checklist && kind === "select" && facets && facets.values.length > 0) {
|
|
6470
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "space-y-2", children: checklist });
|
|
6471
|
+
}
|
|
6472
|
+
if (checklist) {
|
|
6473
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "space-y-2", children: [
|
|
6474
|
+
checklist,
|
|
6475
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "h-px bg-border" }),
|
|
6476
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6477
|
+
FilterBody,
|
|
6478
|
+
{
|
|
6479
|
+
kind,
|
|
6480
|
+
value,
|
|
6481
|
+
onChange,
|
|
6482
|
+
selectOptions,
|
|
6483
|
+
selectSingle,
|
|
6484
|
+
selectAllowCustom,
|
|
6485
|
+
allowNullModes,
|
|
6486
|
+
...booleanLabels === void 0 ? {} : { booleanLabels }
|
|
6487
|
+
}
|
|
6488
|
+
)
|
|
6489
|
+
] });
|
|
6490
|
+
}
|
|
6303
6491
|
if (kind === "text") {
|
|
6304
6492
|
const text = value?.kind === "text" ? value.value : "";
|
|
6305
6493
|
const mode = (value?.kind === "text" ? value.mode : void 0) ?? "contains";
|
|
@@ -6410,6 +6598,112 @@ function FilterBody({
|
|
|
6410
6598
|
}
|
|
6411
6599
|
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(NumberFilterBody, { value, onChange });
|
|
6412
6600
|
}
|
|
6601
|
+
function FacetChecklist({
|
|
6602
|
+
facets,
|
|
6603
|
+
loading,
|
|
6604
|
+
error,
|
|
6605
|
+
value,
|
|
6606
|
+
onChange
|
|
6607
|
+
}) {
|
|
6608
|
+
const [query, setQuery] = (0, import_react13.useState)("");
|
|
6609
|
+
const selected = value?.kind === "select" ? value.values ?? (value.value && value.value !== "__all__" ? [value.value] : []) : [];
|
|
6610
|
+
const selectedSet = new Set(selected);
|
|
6611
|
+
const rows = (0, import_react13.useMemo)(() => {
|
|
6612
|
+
if (!facets) return [];
|
|
6613
|
+
const listed = facets.values.map((entry) => ({
|
|
6614
|
+
value: entry.value,
|
|
6615
|
+
label: entry.value,
|
|
6616
|
+
count: entry.count
|
|
6617
|
+
}));
|
|
6618
|
+
const withBlank = facets.blank > 0 ? [{ value: "", label: "(empty)", count: facets.blank }, ...listed] : listed;
|
|
6619
|
+
const q = query.trim().toLowerCase();
|
|
6620
|
+
if (!q) return withBlank;
|
|
6621
|
+
return withBlank.filter((row) => row.label.toLowerCase().includes(q));
|
|
6622
|
+
}, [facets, query]);
|
|
6623
|
+
const toggle = (candidate) => {
|
|
6624
|
+
const next = new Set(selectedSet);
|
|
6625
|
+
if (next.has(candidate)) next.delete(candidate);
|
|
6626
|
+
else next.add(candidate);
|
|
6627
|
+
const values = [...next];
|
|
6628
|
+
onChange(
|
|
6629
|
+
values.length === 0 ? void 0 : { kind: "select", value: values[0] ?? "", values }
|
|
6630
|
+
);
|
|
6631
|
+
};
|
|
6632
|
+
const notice = error ?? (loading ? FACETS_LOADING_NOTICE : describeFacetSource(facets));
|
|
6633
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "space-y-1.5", children: [
|
|
6634
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "px-1 text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: "Values" }),
|
|
6635
|
+
facets && facets.values.length + (facets.blank > 0 ? 1 : 0) > 8 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6636
|
+
Input,
|
|
6637
|
+
{
|
|
6638
|
+
"data-matrx-filter-autofocus": true,
|
|
6639
|
+
value: query,
|
|
6640
|
+
onChange: (event) => setQuery(event.target.value),
|
|
6641
|
+
placeholder: "Find a value\u2026",
|
|
6642
|
+
className: "h-7 text-sm",
|
|
6643
|
+
style: { fontSize: "16px" }
|
|
6644
|
+
}
|
|
6645
|
+
) : null,
|
|
6646
|
+
rows.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("ul", { className: "max-h-56 space-y-0.5 overflow-y-auto", "data-matrx-facet-list": "true", children: rows.map((row) => {
|
|
6647
|
+
const checked = selectedSet.has(row.value);
|
|
6648
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
6649
|
+
"button",
|
|
6650
|
+
{
|
|
6651
|
+
type: "button",
|
|
6652
|
+
role: "checkbox",
|
|
6653
|
+
"aria-checked": checked,
|
|
6654
|
+
"data-matrx-facet-value": row.value === "" ? "__blank__" : row.value,
|
|
6655
|
+
onClick: () => toggle(row.value),
|
|
6656
|
+
className: cn(
|
|
6657
|
+
"flex w-full items-center gap-2 rounded px-1.5 py-1 text-left text-xs hover:bg-muted",
|
|
6658
|
+
checked && "bg-primary/10"
|
|
6659
|
+
),
|
|
6660
|
+
children: [
|
|
6661
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6662
|
+
"span",
|
|
6663
|
+
{
|
|
6664
|
+
"aria-hidden": true,
|
|
6665
|
+
className: cn(
|
|
6666
|
+
"flex h-3.5 w-3.5 shrink-0 items-center justify-center rounded-[3px] border",
|
|
6667
|
+
checked ? "border-primary bg-primary text-primary-foreground" : "border-border"
|
|
6668
|
+
),
|
|
6669
|
+
children: checked ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Check, { className: "h-2.5 w-2.5" }) : null
|
|
6670
|
+
}
|
|
6671
|
+
),
|
|
6672
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: cn("min-w-0 flex-1 truncate", row.value === "" && "italic text-muted-foreground"), children: row.label }),
|
|
6673
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6674
|
+
"span",
|
|
6675
|
+
{
|
|
6676
|
+
"data-matrx-facet-count": String(row.count),
|
|
6677
|
+
className: "shrink-0 tabular-nums text-[11px] text-muted-foreground",
|
|
6678
|
+
children: row.count.toLocaleString("en-US")
|
|
6679
|
+
}
|
|
6680
|
+
)
|
|
6681
|
+
]
|
|
6682
|
+
}
|
|
6683
|
+
) }, row.value === "" ? "__blank__" : row.value);
|
|
6684
|
+
}) }) : loading ? null : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "px-1 text-[11px] text-muted-foreground", children: query.trim() ? "No value matches that." : "This column has no values yet." }),
|
|
6685
|
+
notice ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6686
|
+
"p",
|
|
6687
|
+
{
|
|
6688
|
+
"data-matrx-facet-notice": "true",
|
|
6689
|
+
className: cn(
|
|
6690
|
+
"px-1 text-[11px] leading-snug",
|
|
6691
|
+
error ? "text-amber-700 dark:text-amber-400" : "text-muted-foreground"
|
|
6692
|
+
),
|
|
6693
|
+
children: notice
|
|
6694
|
+
}
|
|
6695
|
+
) : null,
|
|
6696
|
+
selected.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6697
|
+
"button",
|
|
6698
|
+
{
|
|
6699
|
+
type: "button",
|
|
6700
|
+
onClick: () => onChange(void 0),
|
|
6701
|
+
className: "px-1 text-[11px] text-muted-foreground underline-offset-2 hover:underline",
|
|
6702
|
+
children: "Clear selection"
|
|
6703
|
+
}
|
|
6704
|
+
) : null
|
|
6705
|
+
] });
|
|
6706
|
+
}
|
|
6413
6707
|
function SearchableSelectFilter({
|
|
6414
6708
|
selected,
|
|
6415
6709
|
options,
|
|
@@ -6596,8 +6890,8 @@ function NumberFilterBody({
|
|
|
6596
6890
|
}
|
|
6597
6891
|
function parseOptionalNumber(raw) {
|
|
6598
6892
|
if (raw.trim() === "") return void 0;
|
|
6599
|
-
const
|
|
6600
|
-
return Number.isFinite(
|
|
6893
|
+
const n2 = Number(raw.replace(/[^0-9.-]/g, ""));
|
|
6894
|
+
return Number.isFinite(n2) ? n2 : void 0;
|
|
6601
6895
|
}
|
|
6602
6896
|
|
|
6603
6897
|
// src/data-table/ColumnResizeHandle.tsx
|
|
@@ -6790,115 +7084,1768 @@ function projectColumnDragOrder(orderedIds, preview2) {
|
|
|
6790
7084
|
return order;
|
|
6791
7085
|
}
|
|
6792
7086
|
|
|
6793
|
-
// src/data-table/
|
|
6794
|
-
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
if (/^(description|summary|details|notes|blurb)$/.test(key) || key.endsWith("_description")) return "description";
|
|
6799
|
-
return "other";
|
|
7087
|
+
// src/data-table/grouping.ts
|
|
7088
|
+
var EMPTY_GROUP_KEY = "empty";
|
|
7089
|
+
var DEFAULT_EMPTY_LABEL = "(empty)";
|
|
7090
|
+
function isBlankGroupValue(value) {
|
|
7091
|
+
return value === null || value === void 0 || value === "";
|
|
6800
7092
|
}
|
|
6801
|
-
function
|
|
6802
|
-
|
|
6803
|
-
|
|
6804
|
-
|
|
7093
|
+
function groupKeyOf(value) {
|
|
7094
|
+
if (isBlankGroupValue(value)) return EMPTY_GROUP_KEY;
|
|
7095
|
+
switch (typeof value) {
|
|
7096
|
+
case "string":
|
|
7097
|
+
return `s:${value}`;
|
|
7098
|
+
case "number":
|
|
7099
|
+
return `n:${String(value)}`;
|
|
7100
|
+
case "boolean":
|
|
7101
|
+
return `b:${value ? "true" : "false"}`;
|
|
7102
|
+
case "bigint":
|
|
7103
|
+
return `i:${String(value)}`;
|
|
7104
|
+
case "symbol":
|
|
7105
|
+
return `y:${String(value)}`;
|
|
7106
|
+
case "function":
|
|
7107
|
+
return `f:${safeString(value)}`;
|
|
7108
|
+
default:
|
|
7109
|
+
break;
|
|
6805
7110
|
}
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
}
|
|
7111
|
+
if (value instanceof Date) {
|
|
7112
|
+
const time = value.getTime();
|
|
7113
|
+
return `d:${Number.isFinite(time) ? value.toISOString() : "invalid"}`;
|
|
6810
7114
|
}
|
|
6811
|
-
return
|
|
7115
|
+
return `o:${safeJson(value)}`;
|
|
6812
7116
|
}
|
|
6813
|
-
function
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
for (const [id, label] of [["id", "ID"], ["name", "Name"], ["description", "Description"]]) {
|
|
6819
|
-
if (roles.has(id)) scopes.push({ id, label });
|
|
7117
|
+
function safeString(value) {
|
|
7118
|
+
try {
|
|
7119
|
+
return String(value);
|
|
7120
|
+
} catch {
|
|
7121
|
+
return "[unreadable]";
|
|
6820
7122
|
}
|
|
6821
|
-
for (const scope of options.scopes ?? []) if (!scopes.some((s) => s.id === scope.id) && scope.fields?.length) scopes.push(scope);
|
|
6822
|
-
return scopes;
|
|
6823
7123
|
}
|
|
6824
|
-
function
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
7124
|
+
function safeJson(value) {
|
|
7125
|
+
try {
|
|
7126
|
+
const json = JSON.stringify(value);
|
|
7127
|
+
return typeof json === "string" ? json : safeString(value);
|
|
7128
|
+
} catch {
|
|
7129
|
+
return safeString(value);
|
|
7130
|
+
}
|
|
7131
|
+
}
|
|
7132
|
+
var CURRENCY_AND_SPACE = /[\s,$£€¥]/g;
|
|
7133
|
+
function coerceGroupNumber(value) {
|
|
7134
|
+
if (isBlankGroupValue(value)) return null;
|
|
7135
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
7136
|
+
if (typeof value === "boolean") return value ? 1 : 0;
|
|
7137
|
+
if (typeof value === "bigint") {
|
|
7138
|
+
const asNumber = Number(value);
|
|
7139
|
+
return Number.isFinite(asNumber) ? asNumber : null;
|
|
7140
|
+
}
|
|
7141
|
+
if (typeof value !== "string") return null;
|
|
7142
|
+
const cleaned = value.replace(CURRENCY_AND_SPACE, "");
|
|
7143
|
+
if (cleaned === "" || cleaned === "-" || cleaned === "+") return null;
|
|
7144
|
+
const parsed = Number(cleaned);
|
|
7145
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
7146
|
+
}
|
|
7147
|
+
var NUMBER_FORMAT = new Intl.NumberFormat("en-US", { maximumFractionDigits: 2 });
|
|
7148
|
+
function formatGroupNumber(value) {
|
|
7149
|
+
if (!Number.isFinite(value)) return "\u2014";
|
|
7150
|
+
try {
|
|
7151
|
+
return NUMBER_FORMAT.format(value);
|
|
7152
|
+
} catch {
|
|
7153
|
+
return String(value);
|
|
7154
|
+
}
|
|
7155
|
+
}
|
|
7156
|
+
function defaultLabelOf(value, emptyLabel) {
|
|
7157
|
+
if (isBlankGroupValue(value)) return emptyLabel;
|
|
7158
|
+
if (typeof value === "string") return value;
|
|
7159
|
+
if (typeof value === "number") return formatGroupNumber(value);
|
|
7160
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
7161
|
+
if (value instanceof Date) {
|
|
7162
|
+
const time = value.getTime();
|
|
7163
|
+
return Number.isFinite(time) ? value.toISOString() : "Invalid Date";
|
|
7164
|
+
}
|
|
7165
|
+
if (typeof value === "object") return safeJson(value);
|
|
7166
|
+
return safeString(value);
|
|
7167
|
+
}
|
|
7168
|
+
var AGGREGATE_NAMES = {
|
|
7169
|
+
count: { name: "Count", position: "before" },
|
|
7170
|
+
sum: { name: "Sum", position: "before" },
|
|
7171
|
+
average: { name: "Average", position: "before" },
|
|
7172
|
+
min: { name: "Min", position: "before" },
|
|
7173
|
+
max: { name: "Max", position: "before" },
|
|
7174
|
+
empty: { name: "empty", position: "after" },
|
|
7175
|
+
filled: { name: "filled", position: "after" },
|
|
7176
|
+
unique: { name: "unique", position: "after" },
|
|
7177
|
+
checked: { name: "checked", position: "after" },
|
|
7178
|
+
unchecked: { name: "unchecked", position: "after" },
|
|
7179
|
+
percentFilled: { name: "filled", position: "after" }
|
|
7180
|
+
};
|
|
7181
|
+
function aggregateLabel(kind, value, override) {
|
|
7182
|
+
const naming = AGGREGATE_NAMES[kind] ?? { name: kind, position: "before" };
|
|
7183
|
+
const name = override && override.trim() !== "" ? override : naming.name;
|
|
7184
|
+
const shown = value === null ? "\u2014" : kind === "percentFilled" ? `${formatGroupNumber(value)}%` : formatGroupNumber(value);
|
|
7185
|
+
return naming.position === "before" ? `${name} ${shown}` : `${shown} ${name}`;
|
|
7186
|
+
}
|
|
7187
|
+
function readValue(row, reader) {
|
|
7188
|
+
try {
|
|
7189
|
+
return reader(row);
|
|
7190
|
+
} catch {
|
|
7191
|
+
return null;
|
|
7192
|
+
}
|
|
7193
|
+
}
|
|
7194
|
+
function computeAggregate(rows, column) {
|
|
7195
|
+
const kind = column.spec.kind;
|
|
7196
|
+
const raw = rows.map((row) => readValue(row, column.readCell));
|
|
7197
|
+
const total = raw.length;
|
|
7198
|
+
const filled = raw.filter((value2) => !isBlankGroupValue(value2));
|
|
7199
|
+
const numbers = filled.map((value2) => coerceGroupNumber(value2)).filter((value2) => value2 !== null);
|
|
7200
|
+
let value;
|
|
7201
|
+
switch (kind) {
|
|
7202
|
+
case "count":
|
|
7203
|
+
value = total;
|
|
7204
|
+
break;
|
|
7205
|
+
case "sum":
|
|
7206
|
+
value = numbers.length === 0 ? null : numbers.reduce((acc, n2) => acc + n2, 0);
|
|
7207
|
+
break;
|
|
7208
|
+
case "average":
|
|
7209
|
+
value = numbers.length === 0 ? null : numbers.reduce((acc, n2) => acc + n2, 0) / numbers.length;
|
|
7210
|
+
break;
|
|
7211
|
+
case "min":
|
|
7212
|
+
value = numbers.length === 0 ? null : numbers.reduce((acc, n2) => n2 < acc ? n2 : acc);
|
|
7213
|
+
break;
|
|
7214
|
+
case "max":
|
|
7215
|
+
value = numbers.length === 0 ? null : numbers.reduce((acc, n2) => n2 > acc ? n2 : acc);
|
|
7216
|
+
break;
|
|
7217
|
+
case "empty":
|
|
7218
|
+
value = total - filled.length;
|
|
7219
|
+
break;
|
|
7220
|
+
case "filled":
|
|
7221
|
+
value = filled.length;
|
|
7222
|
+
break;
|
|
7223
|
+
case "unique": {
|
|
7224
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7225
|
+
for (const entry of filled) seen.add(groupKeyOf(entry));
|
|
7226
|
+
value = seen.size;
|
|
7227
|
+
break;
|
|
6847
7228
|
}
|
|
6848
|
-
|
|
6849
|
-
|
|
7229
|
+
case "checked":
|
|
7230
|
+
value = filled.filter((entry) => entry === true).length;
|
|
7231
|
+
break;
|
|
7232
|
+
case "unchecked":
|
|
7233
|
+
value = filled.filter((entry) => entry === false).length;
|
|
7234
|
+
break;
|
|
7235
|
+
case "percentFilled":
|
|
7236
|
+
value = total === 0 ? null : filled.length / total * 100;
|
|
7237
|
+
break;
|
|
7238
|
+
default:
|
|
7239
|
+
value = null;
|
|
7240
|
+
break;
|
|
7241
|
+
}
|
|
7242
|
+
return { kind, value, label: aggregateLabel(kind, value, column.spec.label) };
|
|
7243
|
+
}
|
|
7244
|
+
function compareLabels(a, b) {
|
|
7245
|
+
if (a === b) return 0;
|
|
7246
|
+
return a < b ? -1 : 1;
|
|
7247
|
+
}
|
|
7248
|
+
function compareValues2(a, b) {
|
|
7249
|
+
const aNumber = typeof a.value === "number" ? a.value : null;
|
|
7250
|
+
const bNumber = typeof b.value === "number" ? b.value : null;
|
|
7251
|
+
if (aNumber !== null && bNumber !== null && aNumber !== bNumber) return aNumber < bNumber ? -1 : 1;
|
|
7252
|
+
if (typeof a.value === "boolean" && typeof b.value === "boolean" && a.value !== b.value) {
|
|
7253
|
+
return a.value ? 1 : -1;
|
|
7254
|
+
}
|
|
7255
|
+
return compareLabels(a.label, b.label);
|
|
7256
|
+
}
|
|
7257
|
+
function groupRows(options) {
|
|
7258
|
+
const rows = Array.isArray(options.rows) ? options.rows : [];
|
|
7259
|
+
const emptyLabel = options.emptyLabel ?? DEFAULT_EMPTY_LABEL;
|
|
7260
|
+
const order = options.order ?? "value-asc";
|
|
7261
|
+
const aggregates = options.aggregates ?? {};
|
|
7262
|
+
const labelFor = (value) => {
|
|
7263
|
+
if (!options.labelOf) return defaultLabelOf(value, emptyLabel);
|
|
7264
|
+
if (isBlankGroupValue(value)) {
|
|
7265
|
+
try {
|
|
7266
|
+
const custom = options.labelOf(value);
|
|
7267
|
+
return typeof custom === "string" && custom !== "" ? custom : emptyLabel;
|
|
7268
|
+
} catch {
|
|
7269
|
+
return emptyLabel;
|
|
7270
|
+
}
|
|
7271
|
+
}
|
|
7272
|
+
try {
|
|
7273
|
+
const custom = options.labelOf(value);
|
|
7274
|
+
return typeof custom === "string" ? custom : defaultLabelOf(value, emptyLabel);
|
|
7275
|
+
} catch {
|
|
7276
|
+
return defaultLabelOf(value, emptyLabel);
|
|
7277
|
+
}
|
|
7278
|
+
};
|
|
7279
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
7280
|
+
for (const row of rows) {
|
|
7281
|
+
const raw = readValue(row, options.readCell);
|
|
7282
|
+
const blank = isBlankGroupValue(raw);
|
|
7283
|
+
const value = blank ? null : raw;
|
|
7284
|
+
const key = groupKeyOf(value);
|
|
7285
|
+
let bucket = buckets.get(key);
|
|
7286
|
+
if (!bucket) {
|
|
7287
|
+
bucket = { key, value, label: labelFor(value), rows: [], seen: buckets.size };
|
|
7288
|
+
buckets.set(key, bucket);
|
|
7289
|
+
}
|
|
7290
|
+
bucket.rows.push(row);
|
|
7291
|
+
}
|
|
7292
|
+
const ordered = [...buckets.values()].sort((a, b) => {
|
|
7293
|
+
const aBlank = a.key === EMPTY_GROUP_KEY;
|
|
7294
|
+
const bBlank = b.key === EMPTY_GROUP_KEY;
|
|
7295
|
+
if (aBlank !== bBlank) return aBlank ? 1 : -1;
|
|
7296
|
+
if (aBlank && bBlank) return 0;
|
|
7297
|
+
switch (order) {
|
|
7298
|
+
case "value-asc":
|
|
7299
|
+
return compareValues2(a, b) || a.seen - b.seen;
|
|
7300
|
+
case "value-desc":
|
|
7301
|
+
return -compareValues2(a, b) || a.seen - b.seen;
|
|
7302
|
+
case "count-desc":
|
|
7303
|
+
return b.rows.length - a.rows.length || a.seen - b.seen;
|
|
7304
|
+
case "first-seen":
|
|
7305
|
+
default:
|
|
7306
|
+
return a.seen - b.seen;
|
|
7307
|
+
}
|
|
7308
|
+
});
|
|
7309
|
+
const aggregateEntries = Object.entries(aggregates);
|
|
7310
|
+
return ordered.map((bucket, index) => {
|
|
7311
|
+
const results = {};
|
|
7312
|
+
for (const [columnId2, column] of aggregateEntries) {
|
|
7313
|
+
if (!column || typeof column.readCell !== "function" || !column.spec) continue;
|
|
7314
|
+
results[columnId2] = computeAggregate(bucket.rows, column);
|
|
7315
|
+
}
|
|
7316
|
+
return {
|
|
7317
|
+
key: bucket.key,
|
|
7318
|
+
value: bucket.value,
|
|
7319
|
+
label: bucket.label,
|
|
7320
|
+
rows: bucket.rows,
|
|
7321
|
+
aggregates: results,
|
|
7322
|
+
index
|
|
7323
|
+
};
|
|
7324
|
+
});
|
|
7325
|
+
}
|
|
7326
|
+
function toggleGroupCollapsed(collapsed, key) {
|
|
7327
|
+
const list = Array.isArray(collapsed) ? collapsed : [];
|
|
7328
|
+
return list.includes(key) ? list.filter((entry) => entry !== key) : [...list, key];
|
|
7329
|
+
}
|
|
7330
|
+
function isGroupCollapsed(collapsed, key) {
|
|
7331
|
+
return Array.isArray(collapsed) ? collapsed.includes(key) : false;
|
|
7332
|
+
}
|
|
7333
|
+
function flattenGroups(groups, collapsed) {
|
|
7334
|
+
const out = [];
|
|
7335
|
+
let dataIndex = 0;
|
|
7336
|
+
for (const group of Array.isArray(groups) ? groups : []) {
|
|
7337
|
+
out.push({ kind: "group", group });
|
|
7338
|
+
if (isGroupCollapsed(collapsed, group.key)) continue;
|
|
7339
|
+
for (const row of group.rows) {
|
|
7340
|
+
out.push({ kind: "row", group, row, dataIndex });
|
|
7341
|
+
dataIndex += 1;
|
|
7342
|
+
}
|
|
7343
|
+
}
|
|
7344
|
+
return out;
|
|
7345
|
+
}
|
|
7346
|
+
function groupSummary(group, rowNoun = "row") {
|
|
7347
|
+
const count = group?.rows?.length ?? 0;
|
|
7348
|
+
const noun = count === 1 ? rowNoun : `${rowNoun}s`;
|
|
7349
|
+
const parts = [`${formatGroupNumber(count)} ${noun}`];
|
|
7350
|
+
for (const result of Object.values(group?.aggregates ?? {})) {
|
|
7351
|
+
if (result?.label) parts.push(result.label);
|
|
7352
|
+
}
|
|
7353
|
+
return parts.join(" \xB7 ");
|
|
6850
7354
|
}
|
|
6851
7355
|
|
|
6852
|
-
// src/data-table/
|
|
6853
|
-
var
|
|
6854
|
-
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
7356
|
+
// src/data-table/virtual-window.ts
|
|
7357
|
+
var DEFAULT_OVERSCAN = 6;
|
|
7358
|
+
function isNum(value) {
|
|
7359
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
7360
|
+
}
|
|
7361
|
+
function toCount(value) {
|
|
7362
|
+
return isNum(value) && value > 0 ? Math.floor(value) : 0;
|
|
7363
|
+
}
|
|
7364
|
+
function toLength(value) {
|
|
7365
|
+
return isNum(value) && value > 0 ? value : 0;
|
|
7366
|
+
}
|
|
7367
|
+
function toOverscan(value) {
|
|
7368
|
+
if (!isNum(value)) return DEFAULT_OVERSCAN;
|
|
7369
|
+
return value > 0 ? Math.floor(value) : 0;
|
|
7370
|
+
}
|
|
7371
|
+
function toPinned(value, count) {
|
|
7372
|
+
if (!isNum(value) || value <= 0) return 0;
|
|
7373
|
+
return Math.min(Math.floor(value), count);
|
|
7374
|
+
}
|
|
7375
|
+
function assemble(args) {
|
|
7376
|
+
const { pinnedCount, start, end, padStart, body, total } = args;
|
|
7377
|
+
let padEnd = total - (padStart + body);
|
|
7378
|
+
if (!Number.isFinite(padEnd)) padEnd = 0;
|
|
7379
|
+
const sum = padStart + body + padEnd;
|
|
7380
|
+
if (sum !== total) padEnd = padEnd + (total - sum);
|
|
7381
|
+
const pinned = [];
|
|
7382
|
+
for (let i = 0; i < pinnedCount; i += 1) pinned.push(i);
|
|
7383
|
+
return { start, end, padStart, padEnd, total, pinned };
|
|
7384
|
+
}
|
|
7385
|
+
function emptyWindow(pinnedCount) {
|
|
7386
|
+
const pinned = [];
|
|
7387
|
+
for (let i = 0; i < pinnedCount; i += 1) pinned.push(i);
|
|
7388
|
+
return { start: pinnedCount, end: pinnedCount, padStart: 0, padEnd: 0, total: 0, pinned };
|
|
7389
|
+
}
|
|
7390
|
+
function band(firstVisible, lastVisible, scrollCount, overscan) {
|
|
7391
|
+
let first = firstVisible;
|
|
7392
|
+
if (first > scrollCount - 1) first = scrollCount - 1;
|
|
7393
|
+
if (first < 0) first = 0;
|
|
7394
|
+
let last = lastVisible;
|
|
7395
|
+
if (last < first + 1) last = first + 1;
|
|
7396
|
+
if (last > scrollCount) last = scrollCount;
|
|
7397
|
+
const start = Math.max(0, first - overscan);
|
|
7398
|
+
let end = Math.min(scrollCount, last + overscan);
|
|
7399
|
+
if (end < start) end = start;
|
|
7400
|
+
return { start, end };
|
|
7401
|
+
}
|
|
7402
|
+
function computeWindow(input) {
|
|
7403
|
+
const count = toCount(input?.count);
|
|
7404
|
+
const pinnedCount = toPinned(input?.pinnedStart, count);
|
|
7405
|
+
if (count <= 0) return emptyWindow(0);
|
|
7406
|
+
const itemSize = toLength(input?.itemSize);
|
|
7407
|
+
const viewport = toLength(input?.viewport);
|
|
7408
|
+
const overscan = toOverscan(input?.overscan);
|
|
7409
|
+
const scrollCount = count - pinnedCount;
|
|
7410
|
+
if (scrollCount <= 0) return emptyWindow(pinnedCount);
|
|
7411
|
+
if (itemSize <= 0) {
|
|
7412
|
+
return assemble({ pinnedCount, start: pinnedCount, end: count, padStart: 0, body: 0, total: 0 });
|
|
7413
|
+
}
|
|
7414
|
+
const total = scrollCount * itemSize;
|
|
7415
|
+
const maxOffset = Math.max(0, total - viewport);
|
|
7416
|
+
const offset = Math.min(toLength(input?.offset), maxOffset);
|
|
7417
|
+
const { start: relStart, end: relEnd } = band(
|
|
7418
|
+
Math.floor(offset / itemSize),
|
|
7419
|
+
Math.ceil((offset + viewport) / itemSize),
|
|
7420
|
+
scrollCount,
|
|
7421
|
+
overscan
|
|
6867
7422
|
);
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
7423
|
+
return assemble({
|
|
7424
|
+
pinnedCount,
|
|
7425
|
+
start: pinnedCount + relStart,
|
|
7426
|
+
end: pinnedCount + relEnd,
|
|
7427
|
+
padStart: relStart * itemSize,
|
|
7428
|
+
body: (relEnd - relStart) * itemSize,
|
|
7429
|
+
total
|
|
7430
|
+
});
|
|
7431
|
+
}
|
|
7432
|
+
var PREFIX_CACHE = /* @__PURE__ */ new WeakMap();
|
|
7433
|
+
function prefixFor(sizeAt, count) {
|
|
7434
|
+
let byCount = PREFIX_CACHE.get(sizeAt);
|
|
7435
|
+
if (!byCount) {
|
|
7436
|
+
byCount = /* @__PURE__ */ new Map();
|
|
7437
|
+
PREFIX_CACHE.set(sizeAt, byCount);
|
|
7438
|
+
}
|
|
7439
|
+
const cached = byCount.get(count);
|
|
7440
|
+
if (cached) return cached;
|
|
7441
|
+
const prefix = new Float64Array(count + 1);
|
|
7442
|
+
let running = 0;
|
|
7443
|
+
for (let i = 0; i < count; i += 1) {
|
|
7444
|
+
let size = 0;
|
|
7445
|
+
try {
|
|
7446
|
+
size = sizeAt(i);
|
|
7447
|
+
} catch {
|
|
7448
|
+
size = 0;
|
|
7449
|
+
}
|
|
7450
|
+
running += isNum(size) && size > 0 ? size : 0;
|
|
7451
|
+
prefix[i + 1] = running;
|
|
7452
|
+
}
|
|
7453
|
+
byCount.set(count, prefix);
|
|
7454
|
+
return prefix;
|
|
7455
|
+
}
|
|
7456
|
+
function at(prefix, index) {
|
|
7457
|
+
return prefix[index] ?? 0;
|
|
7458
|
+
}
|
|
7459
|
+
function lastAtOrBefore(prefix, lo, hi, target) {
|
|
7460
|
+
let a = lo;
|
|
7461
|
+
let b = hi;
|
|
7462
|
+
while (a < b) {
|
|
7463
|
+
const mid = a + Math.ceil((b - a) / 2);
|
|
7464
|
+
if (at(prefix, mid) <= target) a = mid;
|
|
7465
|
+
else b = mid - 1;
|
|
7466
|
+
}
|
|
7467
|
+
return a;
|
|
7468
|
+
}
|
|
7469
|
+
function firstAtOrAfter(prefix, lo, hi, target) {
|
|
7470
|
+
let a = lo;
|
|
7471
|
+
let b = hi;
|
|
7472
|
+
while (a < b) {
|
|
7473
|
+
const mid = a + Math.floor((b - a) / 2);
|
|
7474
|
+
if (at(prefix, mid) >= target) b = mid;
|
|
7475
|
+
else a = mid + 1;
|
|
7476
|
+
}
|
|
7477
|
+
return a;
|
|
7478
|
+
}
|
|
7479
|
+
function computeVariableWindow(input) {
|
|
7480
|
+
const count = toCount(input?.count);
|
|
7481
|
+
const pinnedCount = toPinned(input?.pinnedStart, count);
|
|
7482
|
+
if (count <= 0) return emptyWindow(0);
|
|
7483
|
+
const sizeAt = typeof input?.sizeAt === "function" ? input.sizeAt : () => 0;
|
|
7484
|
+
const viewport = toLength(input?.viewport);
|
|
7485
|
+
const overscan = toOverscan(input?.overscan);
|
|
7486
|
+
const scrollCount = count - pinnedCount;
|
|
7487
|
+
if (scrollCount <= 0) return emptyWindow(pinnedCount);
|
|
7488
|
+
const prefix = prefixFor(sizeAt, count);
|
|
7489
|
+
const pinnedLength = at(prefix, pinnedCount);
|
|
7490
|
+
const total = at(prefix, count) - pinnedLength;
|
|
7491
|
+
if (total <= 0) {
|
|
7492
|
+
return assemble({ pinnedCount, start: pinnedCount, end: count, padStart: 0, body: 0, total: total > 0 ? total : 0 });
|
|
7493
|
+
}
|
|
7494
|
+
const maxOffset = Math.max(0, total - viewport);
|
|
7495
|
+
const offset = Math.min(toLength(input?.offset), maxOffset);
|
|
7496
|
+
const firstVisible = lastAtOrBefore(prefix, pinnedCount, count, pinnedLength + offset) - pinnedCount;
|
|
7497
|
+
const lastVisible = firstAtOrAfter(prefix, pinnedCount, count, pinnedLength + offset + viewport) - pinnedCount;
|
|
7498
|
+
const { start: relStart, end: relEnd } = band(firstVisible, lastVisible, scrollCount, overscan);
|
|
7499
|
+
const absStart = pinnedCount + relStart;
|
|
7500
|
+
const absEnd = pinnedCount + relEnd;
|
|
7501
|
+
return assemble({
|
|
7502
|
+
pinnedCount,
|
|
7503
|
+
start: absStart,
|
|
7504
|
+
end: absEnd,
|
|
7505
|
+
padStart: at(prefix, absStart) - pinnedLength,
|
|
7506
|
+
body: at(prefix, absEnd) - at(prefix, absStart),
|
|
7507
|
+
total
|
|
7508
|
+
});
|
|
7509
|
+
}
|
|
7510
|
+
function scrollOffsetForIndex(input) {
|
|
7511
|
+
const count = toCount(input?.count);
|
|
7512
|
+
if (count <= 0) return null;
|
|
7513
|
+
const pinnedCount = toPinned(input?.pinnedStart, count);
|
|
7514
|
+
const itemSize = toLength(input?.itemSize);
|
|
7515
|
+
const viewport = toLength(input?.viewport);
|
|
7516
|
+
const scrollCount = count - pinnedCount;
|
|
7517
|
+
if (scrollCount <= 0 || itemSize <= 0) return null;
|
|
7518
|
+
const rawIndex = isNum(input?.index) ? Math.floor(input.index) : 0;
|
|
7519
|
+
const index = Math.min(Math.max(rawIndex, 0), count - 1);
|
|
7520
|
+
if (index < pinnedCount) return null;
|
|
7521
|
+
const total = scrollCount * itemSize;
|
|
7522
|
+
const maxOffset = Math.max(0, total - viewport);
|
|
7523
|
+
const offset = Math.min(toLength(input?.offset), maxOffset);
|
|
7524
|
+
const itemStart = (index - pinnedCount) * itemSize;
|
|
7525
|
+
const itemEnd = itemStart + itemSize;
|
|
7526
|
+
if (itemStart >= offset && itemEnd <= offset + viewport) return null;
|
|
7527
|
+
const next = itemStart < offset ? itemStart : itemEnd - viewport;
|
|
7528
|
+
const clamped = Math.min(Math.max(next, 0), maxOffset);
|
|
7529
|
+
return clamped === offset ? null : clamped;
|
|
7530
|
+
}
|
|
7531
|
+
|
|
7532
|
+
// src/data-table/useSpreadsheetGrid.ts
|
|
7533
|
+
var import_react15 = require("react");
|
|
7534
|
+
|
|
7535
|
+
// src/data-table/grid-selection.ts
|
|
7536
|
+
function rangeBounds(range, rowIds, fieldNames) {
|
|
7537
|
+
const ra = rowIds.indexOf(range.anchor.rowId);
|
|
7538
|
+
const rf = rowIds.indexOf(range.focus.rowId);
|
|
7539
|
+
const ca = fieldNames.indexOf(range.anchor.fieldName);
|
|
7540
|
+
const cf = fieldNames.indexOf(range.focus.fieldName);
|
|
7541
|
+
if (ra === -1 || rf === -1 || ca === -1 || cf === -1) return null;
|
|
7542
|
+
return {
|
|
7543
|
+
r0: Math.min(ra, rf),
|
|
7544
|
+
r1: Math.max(ra, rf),
|
|
7545
|
+
c0: Math.min(ca, cf),
|
|
7546
|
+
c1: Math.max(ca, cf)
|
|
7547
|
+
};
|
|
7548
|
+
}
|
|
7549
|
+
function rangeSize(bounds) {
|
|
7550
|
+
const rows = bounds.r1 - bounds.r0 + 1;
|
|
7551
|
+
const cols = bounds.c1 - bounds.c0 + 1;
|
|
7552
|
+
return { rows, cols, cells: rows * cols };
|
|
7553
|
+
}
|
|
7554
|
+
function boundsContain(bounds, rowIndex, colIndex) {
|
|
7555
|
+
return rowIndex >= bounds.r0 && rowIndex <= bounds.r1 && colIndex >= bounds.c0 && colIndex <= bounds.c1;
|
|
7556
|
+
}
|
|
7557
|
+
function cellsInRange(range, rowIds, fieldNames) {
|
|
7558
|
+
const b = rangeBounds(range, rowIds, fieldNames);
|
|
7559
|
+
if (!b) return [];
|
|
7560
|
+
const out = [];
|
|
7561
|
+
for (let r = b.r0; r <= b.r1; r += 1) {
|
|
7562
|
+
const rowId = rowIds[r];
|
|
7563
|
+
if (rowId === void 0) continue;
|
|
7564
|
+
for (let c = b.c0; c <= b.c1; c += 1) {
|
|
7565
|
+
const fieldName = fieldNames[c];
|
|
7566
|
+
if (fieldName === void 0) continue;
|
|
7567
|
+
out.push({ rowId, fieldName });
|
|
7568
|
+
}
|
|
7569
|
+
}
|
|
7570
|
+
return out;
|
|
7571
|
+
}
|
|
7572
|
+
function rangeRows(range, rowIds, fieldNames) {
|
|
7573
|
+
const b = rangeBounds(range, rowIds, fieldNames);
|
|
7574
|
+
if (!b) return [];
|
|
7575
|
+
const rows = [];
|
|
7576
|
+
for (let r = b.r0; r <= b.r1; r += 1) {
|
|
7577
|
+
const rowId = rowIds[r];
|
|
7578
|
+
if (rowId === void 0) continue;
|
|
7579
|
+
const row = [];
|
|
7580
|
+
for (let c = b.c0; c <= b.c1; c += 1) {
|
|
7581
|
+
const fieldName = fieldNames[c];
|
|
7582
|
+
if (fieldName === void 0) continue;
|
|
7583
|
+
row.push({ rowId, fieldName });
|
|
7584
|
+
}
|
|
7585
|
+
rows.push(row);
|
|
7586
|
+
}
|
|
7587
|
+
return rows;
|
|
7588
|
+
}
|
|
7589
|
+
function isSingleCellRange(range) {
|
|
7590
|
+
return sameCell(range.anchor, range.focus);
|
|
7591
|
+
}
|
|
7592
|
+
function rowRange(rowId, fieldNames) {
|
|
7593
|
+
const firstField = fieldNames[0];
|
|
7594
|
+
const lastField = fieldNames[fieldNames.length - 1];
|
|
7595
|
+
if (firstField === void 0 || lastField === void 0) return null;
|
|
7596
|
+
return {
|
|
7597
|
+
anchor: { rowId, fieldName: firstField },
|
|
7598
|
+
focus: { rowId, fieldName: lastField }
|
|
7599
|
+
};
|
|
7600
|
+
}
|
|
7601
|
+
function columnRange(fieldName, rowIds) {
|
|
7602
|
+
const firstRow = rowIds[0];
|
|
7603
|
+
const lastRow = rowIds[rowIds.length - 1];
|
|
7604
|
+
if (firstRow === void 0 || lastRow === void 0) return null;
|
|
7605
|
+
return {
|
|
7606
|
+
anchor: { rowId: firstRow, fieldName },
|
|
7607
|
+
focus: { rowId: lastRow, fieldName }
|
|
7608
|
+
};
|
|
7609
|
+
}
|
|
7610
|
+
function allRange(rowIds, fieldNames) {
|
|
7611
|
+
const firstRow = rowIds[0];
|
|
7612
|
+
const lastRow = rowIds[rowIds.length - 1];
|
|
7613
|
+
const firstField = fieldNames[0];
|
|
7614
|
+
const lastField = fieldNames[fieldNames.length - 1];
|
|
7615
|
+
if (firstRow === void 0 || lastRow === void 0 || firstField === void 0 || lastField === void 0) {
|
|
7616
|
+
return null;
|
|
7617
|
+
}
|
|
7618
|
+
return {
|
|
7619
|
+
anchor: { rowId: firstRow, fieldName: firstField },
|
|
7620
|
+
focus: { rowId: lastRow, fieldName: lastField }
|
|
7621
|
+
};
|
|
7622
|
+
}
|
|
7623
|
+
function sameCell(a, b) {
|
|
7624
|
+
if (!a || !b) return a === b;
|
|
7625
|
+
return a.rowId === b.rowId && a.fieldName === b.fieldName;
|
|
7626
|
+
}
|
|
7627
|
+
function moveSelection(current, move, rowIds, fieldNames) {
|
|
7628
|
+
if (rowIds.length === 0 || fieldNames.length === 0) return null;
|
|
7629
|
+
const firstRowId = rowIds[0];
|
|
7630
|
+
const firstFieldName = fieldNames[0];
|
|
7631
|
+
if (firstRowId === void 0 || firstFieldName === void 0) return null;
|
|
7632
|
+
const first = { rowId: firstRowId, fieldName: firstFieldName };
|
|
7633
|
+
if (!current) return first;
|
|
7634
|
+
let r = rowIds.indexOf(current.rowId);
|
|
7635
|
+
let c = fieldNames.indexOf(current.fieldName);
|
|
7636
|
+
if (r === -1 || c === -1) return first;
|
|
7637
|
+
const lastRow = rowIds.length - 1;
|
|
7638
|
+
const lastCol = fieldNames.length - 1;
|
|
7639
|
+
const clamp = (n2, max) => Math.min(Math.max(n2, 0), max);
|
|
7640
|
+
switch (move) {
|
|
7641
|
+
case "up":
|
|
7642
|
+
r = clamp(r - 1, lastRow);
|
|
7643
|
+
break;
|
|
7644
|
+
case "down":
|
|
7645
|
+
r = clamp(r + 1, lastRow);
|
|
7646
|
+
break;
|
|
7647
|
+
case "left":
|
|
7648
|
+
c = clamp(c - 1, lastCol);
|
|
7649
|
+
break;
|
|
7650
|
+
case "right":
|
|
7651
|
+
c = clamp(c + 1, lastCol);
|
|
7652
|
+
break;
|
|
7653
|
+
case "rowStart":
|
|
7654
|
+
c = 0;
|
|
7655
|
+
break;
|
|
7656
|
+
case "rowEnd":
|
|
7657
|
+
c = lastCol;
|
|
7658
|
+
break;
|
|
7659
|
+
case "gridStart":
|
|
7660
|
+
r = 0;
|
|
7661
|
+
c = 0;
|
|
7662
|
+
break;
|
|
7663
|
+
case "gridEnd":
|
|
7664
|
+
r = lastRow;
|
|
7665
|
+
c = lastCol;
|
|
7666
|
+
break;
|
|
7667
|
+
case "nextCell":
|
|
7668
|
+
if (c < lastCol) c += 1;
|
|
7669
|
+
else if (r < lastRow) {
|
|
7670
|
+
r += 1;
|
|
7671
|
+
c = 0;
|
|
7672
|
+
}
|
|
7673
|
+
break;
|
|
7674
|
+
case "prevCell":
|
|
7675
|
+
if (c > 0) c -= 1;
|
|
7676
|
+
else if (r > 0) {
|
|
7677
|
+
r -= 1;
|
|
7678
|
+
c = lastCol;
|
|
7679
|
+
}
|
|
7680
|
+
break;
|
|
7681
|
+
}
|
|
7682
|
+
const rowId = rowIds[r];
|
|
7683
|
+
const fieldName = fieldNames[c];
|
|
7684
|
+
if (rowId === void 0 || fieldName === void 0) return first;
|
|
7685
|
+
return { rowId, fieldName };
|
|
7686
|
+
}
|
|
7687
|
+
function isTypingKey(e) {
|
|
7688
|
+
if (e.ctrlKey || e.metaKey || e.altKey) return false;
|
|
7689
|
+
return e.key.length === 1 && e.key !== " ";
|
|
7690
|
+
}
|
|
7691
|
+
function classifyGridKey(e) {
|
|
7692
|
+
const mod = e.ctrlKey || e.metaKey;
|
|
7693
|
+
const arrowMove = {
|
|
7694
|
+
ArrowUp: mod ? "gridStart" : "up",
|
|
7695
|
+
ArrowDown: mod ? "gridEnd" : "down",
|
|
7696
|
+
ArrowLeft: mod ? "rowStart" : "left",
|
|
7697
|
+
ArrowRight: mod ? "rowEnd" : "right",
|
|
7698
|
+
Home: mod ? "gridStart" : "rowStart",
|
|
7699
|
+
End: mod ? "gridEnd" : "rowEnd"
|
|
7700
|
+
};
|
|
7701
|
+
const arrow = arrowMove[e.key];
|
|
7702
|
+
if (arrow !== void 0) {
|
|
7703
|
+
return { kind: e.shiftKey ? "extend" : "move", move: arrow };
|
|
7704
|
+
}
|
|
7705
|
+
switch (e.key) {
|
|
7706
|
+
case "Tab":
|
|
7707
|
+
return { kind: "move", move: e.shiftKey ? "prevCell" : "nextCell" };
|
|
7708
|
+
case "Enter":
|
|
7709
|
+
case "F2":
|
|
7710
|
+
return { kind: "edit" };
|
|
7711
|
+
case " ":
|
|
7712
|
+
if (e.shiftKey) return { kind: "selectRow" };
|
|
7713
|
+
if (mod) return { kind: "selectColumn" };
|
|
7714
|
+
return { kind: "edit" };
|
|
7715
|
+
case "a":
|
|
7716
|
+
case "A":
|
|
7717
|
+
if (mod) return { kind: "selectAll" };
|
|
7718
|
+
break;
|
|
7719
|
+
case "d":
|
|
7720
|
+
case "D":
|
|
7721
|
+
if (mod) return { kind: "fillDown" };
|
|
7722
|
+
break;
|
|
7723
|
+
case "Escape":
|
|
7724
|
+
return { kind: "escape" };
|
|
7725
|
+
case "Delete":
|
|
7726
|
+
case "Backspace":
|
|
7727
|
+
return { kind: "clearCell" };
|
|
7728
|
+
case "c":
|
|
7729
|
+
case "C":
|
|
7730
|
+
if (mod) return { kind: "copy" };
|
|
7731
|
+
break;
|
|
7732
|
+
case "x":
|
|
7733
|
+
case "X":
|
|
7734
|
+
if (mod) return { kind: "cut" };
|
|
7735
|
+
break;
|
|
7736
|
+
case "v":
|
|
7737
|
+
case "V":
|
|
7738
|
+
if (mod) return { kind: "paste" };
|
|
7739
|
+
break;
|
|
7740
|
+
}
|
|
7741
|
+
if (isTypingKey(e)) return { kind: "editSeeded", seed: e.key };
|
|
7742
|
+
return null;
|
|
7743
|
+
}
|
|
7744
|
+
function directClickKinds() {
|
|
7745
|
+
return ["checkbox", "rating", "select", "multiselect"];
|
|
7746
|
+
}
|
|
7747
|
+
function isDirectClickEditor(editorKind) {
|
|
7748
|
+
return editorKind !== void 0 && directClickKinds().includes(editorKind);
|
|
7749
|
+
}
|
|
7750
|
+
function cellDomKey(address) {
|
|
7751
|
+
return `${address.rowId}::${address.fieldName}`;
|
|
7752
|
+
}
|
|
7753
|
+
|
|
7754
|
+
// src/data-table/grid-clipboard.ts
|
|
7755
|
+
function cellClipboardText(value) {
|
|
7756
|
+
if (value === null || value === void 0) return "";
|
|
7757
|
+
if (typeof value === "object") return JSON.stringify(value);
|
|
7758
|
+
return String(value);
|
|
7759
|
+
}
|
|
7760
|
+
function tsvCell(text) {
|
|
7761
|
+
return /[\t\r\n"]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
|
|
7762
|
+
}
|
|
7763
|
+
function gridToTsv(block) {
|
|
7764
|
+
return block.map((row) => row.map((cell) => tsvCell(cellClipboardText(cell))).join(" ")).join("\n");
|
|
7765
|
+
}
|
|
7766
|
+
function parseClipboardGrid(text) {
|
|
7767
|
+
const rows = [];
|
|
7768
|
+
let row = [];
|
|
7769
|
+
let cell = "";
|
|
7770
|
+
let i = 0;
|
|
7771
|
+
const n2 = text.length;
|
|
7772
|
+
while (i < n2) {
|
|
7773
|
+
const ch = text[i];
|
|
7774
|
+
if (cell === "" && ch === '"') {
|
|
7775
|
+
let j = i + 1;
|
|
7776
|
+
let out = "";
|
|
7777
|
+
let closed = false;
|
|
7778
|
+
while (j < n2) {
|
|
7779
|
+
const c = text[j];
|
|
7780
|
+
if (c === '"') {
|
|
7781
|
+
if (text[j + 1] === '"') {
|
|
7782
|
+
out += '"';
|
|
7783
|
+
j += 2;
|
|
7784
|
+
continue;
|
|
7785
|
+
}
|
|
7786
|
+
closed = true;
|
|
7787
|
+
j += 1;
|
|
7788
|
+
break;
|
|
7789
|
+
}
|
|
7790
|
+
out += c;
|
|
7791
|
+
j += 1;
|
|
7792
|
+
}
|
|
7793
|
+
if (closed && (j >= n2 || text[j] === " " || text[j] === "\n" || text[j] === "\r")) {
|
|
7794
|
+
cell = out;
|
|
7795
|
+
i = j;
|
|
7796
|
+
if (i >= n2) break;
|
|
7797
|
+
const d = text[i];
|
|
7798
|
+
if (d === " ") {
|
|
7799
|
+
row.push(cell);
|
|
7800
|
+
cell = "";
|
|
7801
|
+
i += 1;
|
|
7802
|
+
continue;
|
|
7803
|
+
}
|
|
7804
|
+
row.push(cell);
|
|
7805
|
+
rows.push(row);
|
|
7806
|
+
row = [];
|
|
7807
|
+
cell = "";
|
|
7808
|
+
i += d === "\r" && text[i + 1] === "\n" ? 2 : 1;
|
|
7809
|
+
continue;
|
|
7810
|
+
}
|
|
7811
|
+
cell += ch;
|
|
7812
|
+
i += 1;
|
|
7813
|
+
continue;
|
|
7814
|
+
}
|
|
7815
|
+
if (ch === " ") {
|
|
7816
|
+
row.push(cell);
|
|
7817
|
+
cell = "";
|
|
7818
|
+
i += 1;
|
|
7819
|
+
continue;
|
|
7820
|
+
}
|
|
7821
|
+
if (ch === "\n" || ch === "\r") {
|
|
7822
|
+
row.push(cell);
|
|
7823
|
+
rows.push(row);
|
|
7824
|
+
row = [];
|
|
7825
|
+
cell = "";
|
|
7826
|
+
i += ch === "\r" && text[i + 1] === "\n" ? 2 : 1;
|
|
7827
|
+
continue;
|
|
7828
|
+
}
|
|
7829
|
+
cell += ch;
|
|
7830
|
+
i += 1;
|
|
7831
|
+
}
|
|
7832
|
+
const endedOnBreak = n2 > 0 && (text[n2 - 1] === "\n" || text[n2 - 1] === "\r");
|
|
7833
|
+
if (!endedOnBreak) {
|
|
7834
|
+
row.push(cell);
|
|
7835
|
+
rows.push(row);
|
|
7836
|
+
} else if (row.length > 0) {
|
|
7837
|
+
row.push(cell);
|
|
7838
|
+
rows.push(row);
|
|
7839
|
+
}
|
|
7840
|
+
return rows.length === 0 ? [[""]] : rows;
|
|
7841
|
+
}
|
|
7842
|
+
function planPaste(anchor, block, rowIds, fieldNames) {
|
|
7843
|
+
const r0 = rowIds.indexOf(anchor.rowId);
|
|
7844
|
+
const c0 = fieldNames.indexOf(anchor.fieldName);
|
|
7845
|
+
if (r0 === -1 || c0 === -1) return null;
|
|
7846
|
+
const width = block.reduce((w, row) => Math.max(w, row.length), 0);
|
|
7847
|
+
const colsAvailable = fieldNames.length - c0;
|
|
7848
|
+
const colsUsed = Math.min(width, colsAvailable);
|
|
7849
|
+
const targetFields = fieldNames.slice(c0, c0 + colsUsed);
|
|
7850
|
+
const cells = [];
|
|
7851
|
+
const overflowRows = [];
|
|
7852
|
+
block.forEach((blockRow, dr) => {
|
|
7853
|
+
const rowId = rowIds[r0 + dr];
|
|
7854
|
+
if (rowId === void 0) {
|
|
7855
|
+
overflowRows.push(targetFields.map((_, dc) => blockRow[dc] ?? ""));
|
|
7856
|
+
return;
|
|
7857
|
+
}
|
|
7858
|
+
targetFields.forEach((fieldName, dc) => {
|
|
7859
|
+
if (dc >= blockRow.length) return;
|
|
7860
|
+
const raw = blockRow[dc];
|
|
7861
|
+
if (raw === void 0) return;
|
|
7862
|
+
cells.push({ rowId, fieldName, raw });
|
|
7863
|
+
});
|
|
7864
|
+
});
|
|
7865
|
+
return {
|
|
7866
|
+
cells,
|
|
7867
|
+
overflowRows,
|
|
7868
|
+
clippedColumns: Math.max(0, width - colsAvailable),
|
|
7869
|
+
fieldNames: targetFields
|
|
7870
|
+
};
|
|
7871
|
+
}
|
|
7872
|
+
function isSingleCell(block) {
|
|
7873
|
+
return block.length === 1 && block[0]?.length === 1;
|
|
7874
|
+
}
|
|
7875
|
+
function storedValuesEqual(a, b) {
|
|
7876
|
+
if (a === b) return true;
|
|
7877
|
+
if (a === null || b === null || a === void 0 || b === void 0) {
|
|
7878
|
+
return (a ?? null) === (b ?? null);
|
|
7879
|
+
}
|
|
7880
|
+
if (typeof a === "object" || typeof b === "object") {
|
|
7881
|
+
try {
|
|
7882
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
7883
|
+
} catch {
|
|
7884
|
+
return false;
|
|
7885
|
+
}
|
|
7886
|
+
}
|
|
7887
|
+
return false;
|
|
7888
|
+
}
|
|
7889
|
+
|
|
7890
|
+
// src/data-table/fill.ts
|
|
7891
|
+
var NO_SERIES = { kind: "none", step: 0 };
|
|
7892
|
+
var MS_PER_DAY = 864e5;
|
|
7893
|
+
function plural(count, one, many) {
|
|
7894
|
+
return `${count} ${count === 1 ? one : many}`;
|
|
7895
|
+
}
|
|
7896
|
+
function isValidRect(rect) {
|
|
7897
|
+
return Number.isInteger(rect.top) && Number.isInteger(rect.left) && Number.isInteger(rect.bottom) && Number.isInteger(rect.right) && rect.top <= rect.bottom && rect.left <= rect.right;
|
|
7898
|
+
}
|
|
7899
|
+
function asBounds(rect) {
|
|
7900
|
+
return { r0: rect.top, r1: rect.bottom, c0: rect.left, c1: rect.right };
|
|
7901
|
+
}
|
|
7902
|
+
function directionOf(source, target) {
|
|
7903
|
+
if (!isValidRect(source) || !isValidRect(target)) return null;
|
|
7904
|
+
if (target.top === source.bottom + 1) return "down";
|
|
7905
|
+
if (target.bottom === source.top - 1) return "up";
|
|
7906
|
+
if (target.left === source.right + 1) return "right";
|
|
7907
|
+
if (target.right === source.left - 1) return "left";
|
|
7908
|
+
return null;
|
|
7909
|
+
}
|
|
7910
|
+
function tileIndex(i, a, b) {
|
|
7911
|
+
const n2 = b - a + 1;
|
|
7912
|
+
if (n2 <= 0) return a;
|
|
7913
|
+
if (i >= a && i <= b) return i;
|
|
7914
|
+
if (i > b) return a + (i - a) % n2;
|
|
7915
|
+
return b - (a - 1 - i) % n2;
|
|
7916
|
+
}
|
|
7917
|
+
function isFiniteNumber(v) {
|
|
7918
|
+
return typeof v === "number" && Number.isFinite(v);
|
|
7919
|
+
}
|
|
7920
|
+
var DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
|
|
7921
|
+
var DATE_ISH = /^\d{4}-\d{2}-\d{2}([T ]|$)/;
|
|
7922
|
+
function dateMs(v) {
|
|
7923
|
+
if (v instanceof Date) {
|
|
7924
|
+
const t = v.getTime();
|
|
7925
|
+
return Number.isFinite(t) ? t : null;
|
|
7926
|
+
}
|
|
7927
|
+
if (typeof v === "string" && DATE_ISH.test(v)) {
|
|
7928
|
+
const t = Date.parse(v);
|
|
7929
|
+
return Number.isFinite(t) ? t : null;
|
|
7930
|
+
}
|
|
7931
|
+
return null;
|
|
7932
|
+
}
|
|
7933
|
+
function detectSeries(values) {
|
|
7934
|
+
if (!Array.isArray(values) || values.length < 2) return NO_SERIES;
|
|
7935
|
+
if (values.every(isFiniteNumber)) {
|
|
7936
|
+
const nums = values;
|
|
7937
|
+
const first = nums[0];
|
|
7938
|
+
const second = nums[1];
|
|
7939
|
+
if (first === void 0 || second === void 0) return NO_SERIES;
|
|
7940
|
+
const step = second - first;
|
|
7941
|
+
for (let i = 1; i < nums.length; i += 1) {
|
|
7942
|
+
const prev = nums[i - 1];
|
|
7943
|
+
const cur = nums[i];
|
|
7944
|
+
if (prev === void 0 || cur === void 0) return NO_SERIES;
|
|
7945
|
+
if (cur - prev !== step) return NO_SERIES;
|
|
7946
|
+
}
|
|
7947
|
+
return { kind: "number", step };
|
|
7948
|
+
}
|
|
7949
|
+
const stamps = values.map(dateMs);
|
|
7950
|
+
if (stamps.every((t) => t !== null)) {
|
|
7951
|
+
const first = stamps[0];
|
|
7952
|
+
const second = stamps[1];
|
|
7953
|
+
if (first === void 0 || second === void 0) return NO_SERIES;
|
|
7954
|
+
const deltaMs = second - first;
|
|
7955
|
+
if (deltaMs % MS_PER_DAY !== 0) return NO_SERIES;
|
|
7956
|
+
for (let i = 1; i < stamps.length; i += 1) {
|
|
7957
|
+
const prev = stamps[i - 1];
|
|
7958
|
+
const cur = stamps[i];
|
|
7959
|
+
if (prev === void 0 || cur === void 0) return NO_SERIES;
|
|
7960
|
+
if (cur - prev !== deltaMs) return NO_SERIES;
|
|
7961
|
+
}
|
|
7962
|
+
return { kind: "date", step: deltaMs / MS_PER_DAY };
|
|
7963
|
+
}
|
|
7964
|
+
return NO_SERIES;
|
|
7965
|
+
}
|
|
7966
|
+
function formatDateLike(ms, sample) {
|
|
7967
|
+
const iso = new Date(ms).toISOString();
|
|
7968
|
+
if (typeof sample === "string" && DATE_ONLY.test(sample)) return iso.slice(0, 10);
|
|
7969
|
+
return iso;
|
|
7970
|
+
}
|
|
7971
|
+
function extrapolate(line, series, k) {
|
|
7972
|
+
const last = line[line.length - 1];
|
|
7973
|
+
if (series.kind === "number" && isFiniteNumber(last)) {
|
|
7974
|
+
return last + k * series.step;
|
|
7975
|
+
}
|
|
7976
|
+
if (series.kind === "date") {
|
|
7977
|
+
const base = dateMs(last);
|
|
7978
|
+
if (base === null) return jsonable(last);
|
|
7979
|
+
return formatDateLike(base + k * series.step * MS_PER_DAY, last);
|
|
7980
|
+
}
|
|
7981
|
+
return jsonable(last);
|
|
7982
|
+
}
|
|
7983
|
+
function jsonable(value) {
|
|
7984
|
+
if (value instanceof Date) {
|
|
7985
|
+
const t = value.getTime();
|
|
7986
|
+
return Number.isFinite(t) ? value.toISOString() : null;
|
|
7987
|
+
}
|
|
7988
|
+
if (value === void 0) return null;
|
|
7989
|
+
return value;
|
|
7990
|
+
}
|
|
7991
|
+
function emptyResult(summary) {
|
|
7992
|
+
return { patches: [], skipped: [], summary };
|
|
7993
|
+
}
|
|
7994
|
+
function fillRange(request) {
|
|
7995
|
+
const { source, target, columnIds, rowIds } = request;
|
|
7996
|
+
const mode = request.mode ?? "series";
|
|
7997
|
+
const isWritable = request.isColumnWritable ?? (() => true);
|
|
7998
|
+
const direction = directionOf(source, target);
|
|
7999
|
+
if (!direction) {
|
|
8000
|
+
return emptyResult(
|
|
8001
|
+
"Filled 0 cells because the fill area does not touch the selection."
|
|
8002
|
+
);
|
|
8003
|
+
}
|
|
8004
|
+
if (rowIds.length === 0 || columnIds.length === 0) {
|
|
8005
|
+
return emptyResult("Filled 0 cells because the table is empty.");
|
|
8006
|
+
}
|
|
8007
|
+
const read = (r, c) => {
|
|
8008
|
+
try {
|
|
8009
|
+
return { ok: true, value: request.valueAt(r, c) };
|
|
8010
|
+
} catch {
|
|
8011
|
+
return { ok: false, value: void 0 };
|
|
8012
|
+
}
|
|
8013
|
+
};
|
|
8014
|
+
const vertical = direction === "down" || direction === "up";
|
|
8015
|
+
const forward = direction === "down" || direction === "right";
|
|
8016
|
+
const fillStart = vertical ? source.top : source.left;
|
|
8017
|
+
const fillEnd = vertical ? source.bottom : source.right;
|
|
8018
|
+
const crossStart = vertical ? source.left : source.top;
|
|
8019
|
+
const crossEnd = vertical ? source.right : source.bottom;
|
|
8020
|
+
const maxFill = (vertical ? rowIds.length : columnIds.length) - 1;
|
|
8021
|
+
const maxCross = (vertical ? columnIds.length : rowIds.length) - 1;
|
|
8022
|
+
const rawFillFrom = vertical ? target.top : target.left;
|
|
8023
|
+
const rawFillTo = vertical ? target.bottom : target.right;
|
|
8024
|
+
const rawCrossFrom = vertical ? target.left : target.top;
|
|
8025
|
+
const rawCrossTo = vertical ? target.right : target.bottom;
|
|
8026
|
+
const fillFrom = Math.max(rawFillFrom, 0);
|
|
8027
|
+
const fillTo = Math.min(rawFillTo, maxFill);
|
|
8028
|
+
const crossFrom = Math.max(rawCrossFrom, 0);
|
|
8029
|
+
const crossTo = Math.min(rawCrossTo, maxCross);
|
|
8030
|
+
const requested = Math.max(rawFillTo - rawFillFrom + 1, 0) * Math.max(rawCrossTo - rawCrossFrom + 1, 0);
|
|
8031
|
+
const inside = Math.max(fillTo - fillFrom + 1, 0) * Math.max(crossTo - crossFrom + 1, 0);
|
|
8032
|
+
const outside = Math.max(requested - inside, 0);
|
|
8033
|
+
const sourceBounds = asBounds(source);
|
|
8034
|
+
const patches = [];
|
|
8035
|
+
const skipped = [];
|
|
8036
|
+
const touchedColumns = /* @__PURE__ */ new Set();
|
|
8037
|
+
const lines = /* @__PURE__ */ new Map();
|
|
8038
|
+
const lineFor = (crossIndex) => {
|
|
8039
|
+
const srcCross = tileIndex(crossIndex, crossStart, crossEnd);
|
|
8040
|
+
const cached = lines.get(srcCross);
|
|
8041
|
+
if (cached) return cached;
|
|
8042
|
+
const values = [];
|
|
8043
|
+
const reads = [];
|
|
8044
|
+
for (let f = fillStart; f <= fillEnd; f += 1) {
|
|
8045
|
+
const r = vertical ? f : srcCross;
|
|
8046
|
+
const c = vertical ? srcCross : f;
|
|
8047
|
+
const got = read(r, c);
|
|
8048
|
+
values.push(got.value);
|
|
8049
|
+
reads.push(got.ok);
|
|
8050
|
+
}
|
|
8051
|
+
const series = mode === "series" ? detectSeries(values) : NO_SERIES;
|
|
8052
|
+
const line = { values, reads, series };
|
|
8053
|
+
lines.set(srcCross, line);
|
|
8054
|
+
return line;
|
|
8055
|
+
};
|
|
8056
|
+
for (let f = fillFrom; f <= fillTo; f += 1) {
|
|
8057
|
+
for (let x = crossFrom; x <= crossTo; x += 1) {
|
|
8058
|
+
const rowIndex = vertical ? f : x;
|
|
8059
|
+
const colIndex = vertical ? x : f;
|
|
8060
|
+
const rowId = rowIds[rowIndex];
|
|
8061
|
+
const columnId2 = columnIds[colIndex];
|
|
8062
|
+
if (rowId === void 0 || columnId2 === void 0) continue;
|
|
8063
|
+
if (boundsContain(sourceBounds, rowIndex, colIndex)) continue;
|
|
8064
|
+
if (!isWritable(columnId2)) {
|
|
8065
|
+
skipped.push({
|
|
8066
|
+
rowId,
|
|
8067
|
+
columnId: columnId2,
|
|
8068
|
+
reason: `${columnId2} cannot be filled because that column is read-only.`
|
|
8069
|
+
});
|
|
8070
|
+
continue;
|
|
8071
|
+
}
|
|
8072
|
+
const line = lineFor(x);
|
|
8073
|
+
if (line.series.kind !== "none") {
|
|
8074
|
+
const k = forward ? f - fillEnd : fillStart - f;
|
|
8075
|
+
patches.push({ rowId, columnId: columnId2, value: jsonable(extrapolate(line.values, line.series, k)) });
|
|
8076
|
+
touchedColumns.add(columnId2);
|
|
8077
|
+
continue;
|
|
8078
|
+
}
|
|
8079
|
+
const srcFill = tileIndex(f, fillStart, fillEnd);
|
|
8080
|
+
const patternIndex = srcFill - fillStart;
|
|
8081
|
+
if (line.reads[patternIndex] !== true) {
|
|
8082
|
+
skipped.push({
|
|
8083
|
+
rowId,
|
|
8084
|
+
columnId: columnId2,
|
|
8085
|
+
reason: `The value to copy into ${columnId2} could not be read, so that cell was left alone.`
|
|
8086
|
+
});
|
|
8087
|
+
continue;
|
|
8088
|
+
}
|
|
8089
|
+
patches.push({ rowId, columnId: columnId2, value: jsonable(line.values[patternIndex]) });
|
|
8090
|
+
touchedColumns.add(columnId2);
|
|
8091
|
+
}
|
|
8092
|
+
}
|
|
8093
|
+
return { patches, skipped, summary: summarize(direction, patches, skipped, touchedColumns, outside) };
|
|
8094
|
+
}
|
|
8095
|
+
function summarize(direction, patches, skipped, touchedColumns, outside) {
|
|
8096
|
+
const parts = [];
|
|
8097
|
+
if (patches.length === 0) {
|
|
8098
|
+
parts.push("Filled 0 cells because there was nothing to fill.");
|
|
8099
|
+
} else if (direction === "down" || direction === "up") {
|
|
8100
|
+
const word = direction === "down" ? "down" : "up";
|
|
8101
|
+
parts.push(
|
|
8102
|
+
`Filled ${plural(patches.length, "cell", "cells")} ${word} ${plural(touchedColumns.size, "column", "columns")}.`
|
|
8103
|
+
);
|
|
8104
|
+
} else {
|
|
8105
|
+
const word = direction === "right" ? "right" : "left";
|
|
8106
|
+
parts.push(
|
|
8107
|
+
`Filled ${plural(patches.length, "cell", "cells")} ${word} across ${plural(touchedColumns.size, "column", "columns")}.`
|
|
8108
|
+
);
|
|
8109
|
+
}
|
|
8110
|
+
if (skipped.length > 0) {
|
|
8111
|
+
parts.push(`Skipped ${plural(skipped.length, "cell", "cells")} that could not be filled.`);
|
|
8112
|
+
}
|
|
8113
|
+
if (outside > 0) {
|
|
8114
|
+
parts.push(`Ignored ${plural(outside, "cell", "cells")} outside the table.`);
|
|
8115
|
+
}
|
|
8116
|
+
return parts.join(" ");
|
|
8117
|
+
}
|
|
8118
|
+
function fillDown(request) {
|
|
8119
|
+
const { range, ...rest } = request;
|
|
8120
|
+
if (!isValidRect(range)) {
|
|
8121
|
+
return emptyResult("Filled 0 cells because the selection is not a rectangle.");
|
|
8122
|
+
}
|
|
8123
|
+
if (range.top === range.bottom) {
|
|
8124
|
+
return emptyResult("Filled 0 cells because the selection is a single row.");
|
|
8125
|
+
}
|
|
8126
|
+
return fillRange({
|
|
8127
|
+
...rest,
|
|
8128
|
+
source: { top: range.top, left: range.left, bottom: range.top, right: range.right },
|
|
8129
|
+
target: { top: range.top + 1, left: range.left, bottom: range.bottom, right: range.right }
|
|
8130
|
+
});
|
|
8131
|
+
}
|
|
8132
|
+
function fillTargetFor(source, toRow, toColumn) {
|
|
8133
|
+
if (!isValidRect(source)) return null;
|
|
8134
|
+
if (!Number.isInteger(toRow) || !Number.isInteger(toColumn)) return null;
|
|
8135
|
+
const below = toRow - source.bottom;
|
|
8136
|
+
const above = source.top - toRow;
|
|
8137
|
+
const rightOf = toColumn - source.right;
|
|
8138
|
+
const leftOf = source.left - toColumn;
|
|
8139
|
+
const vertical = Math.max(below, above, 0);
|
|
8140
|
+
const horizontal = Math.max(rightOf, leftOf, 0);
|
|
8141
|
+
if (vertical === 0 && horizontal === 0) return null;
|
|
8142
|
+
if (vertical >= horizontal) {
|
|
8143
|
+
if (below > 0) {
|
|
8144
|
+
return { top: source.bottom + 1, bottom: toRow, left: source.left, right: source.right };
|
|
8145
|
+
}
|
|
8146
|
+
return { top: toRow, bottom: source.top - 1, left: source.left, right: source.right };
|
|
8147
|
+
}
|
|
8148
|
+
if (rightOf > 0) {
|
|
8149
|
+
return { top: source.top, bottom: source.bottom, left: source.right + 1, right: toColumn };
|
|
8150
|
+
}
|
|
8151
|
+
return { top: source.top, bottom: source.bottom, left: toColumn, right: source.left - 1 };
|
|
8152
|
+
}
|
|
8153
|
+
|
|
8154
|
+
// src/data-table/cell-undo.ts
|
|
8155
|
+
var DEFAULT_UNDO_DEPTH = 100;
|
|
8156
|
+
function createUndoStack(depth = DEFAULT_UNDO_DEPTH) {
|
|
8157
|
+
const bounded = Number.isFinite(depth) && depth > 0 ? Math.floor(depth) : 0;
|
|
8158
|
+
return { past: [], future: [], depth: bounded };
|
|
8159
|
+
}
|
|
8160
|
+
function pushUndo(stack, entry) {
|
|
8161
|
+
if (stack.depth <= 0) {
|
|
8162
|
+
return { past: [], future: [], depth: stack.depth };
|
|
8163
|
+
}
|
|
8164
|
+
const past = [...stack.past, entry];
|
|
8165
|
+
while (past.length > stack.depth) past.shift();
|
|
8166
|
+
return { past, future: [], depth: stack.depth };
|
|
8167
|
+
}
|
|
8168
|
+
function popUndo(stack) {
|
|
8169
|
+
const entry = stack.past[stack.past.length - 1];
|
|
8170
|
+
if (entry === void 0) return { stack, entry: null };
|
|
8171
|
+
return {
|
|
8172
|
+
stack: {
|
|
8173
|
+
past: stack.past.slice(0, -1),
|
|
8174
|
+
future: [...stack.future, entry],
|
|
8175
|
+
depth: stack.depth
|
|
8176
|
+
},
|
|
8177
|
+
entry
|
|
8178
|
+
};
|
|
8179
|
+
}
|
|
8180
|
+
function popRedo(stack) {
|
|
8181
|
+
const entry = stack.future[stack.future.length - 1];
|
|
8182
|
+
if (entry === void 0) return { stack, entry: null };
|
|
8183
|
+
const past = [...stack.past, entry];
|
|
8184
|
+
while (past.length > stack.depth) past.shift();
|
|
8185
|
+
return {
|
|
8186
|
+
stack: { past, future: stack.future.slice(0, -1), depth: stack.depth },
|
|
8187
|
+
entry
|
|
8188
|
+
};
|
|
8189
|
+
}
|
|
8190
|
+
function keyOf(patch) {
|
|
8191
|
+
return JSON.stringify([patch.rowId, patch.columnId]);
|
|
8192
|
+
}
|
|
8193
|
+
function undoEntryFor(before, after, label) {
|
|
8194
|
+
const priors = /* @__PURE__ */ new Map();
|
|
8195
|
+
for (const patch of before) priors.set(keyOf(patch), patch);
|
|
8196
|
+
const undo = after.map((patch) => {
|
|
8197
|
+
const prior = priors.get(keyOf(patch));
|
|
8198
|
+
return {
|
|
8199
|
+
rowId: patch.rowId,
|
|
8200
|
+
columnId: patch.columnId,
|
|
8201
|
+
value: prior ? prior.value : null
|
|
8202
|
+
};
|
|
8203
|
+
});
|
|
8204
|
+
return {
|
|
8205
|
+
label,
|
|
8206
|
+
undo,
|
|
8207
|
+
redo: after.map((patch) => ({
|
|
8208
|
+
rowId: patch.rowId,
|
|
8209
|
+
columnId: patch.columnId,
|
|
8210
|
+
value: patch.value
|
|
8211
|
+
}))
|
|
8212
|
+
};
|
|
8213
|
+
}
|
|
8214
|
+
function canUndo(stack) {
|
|
8215
|
+
return stack.depth > 0 && stack.past.length > 0;
|
|
8216
|
+
}
|
|
8217
|
+
function canRedo(stack) {
|
|
8218
|
+
return stack.depth > 0 && stack.future.length > 0;
|
|
8219
|
+
}
|
|
8220
|
+
|
|
8221
|
+
// src/data-table/useSpreadsheetGrid.ts
|
|
8222
|
+
function targetsAnEditor(target) {
|
|
8223
|
+
const element = target instanceof Element ? target : null;
|
|
8224
|
+
if (!element) return false;
|
|
8225
|
+
return element.closest("input, textarea, select, [contenteditable='true']") !== null;
|
|
8226
|
+
}
|
|
8227
|
+
function useSpreadsheetGrid(options) {
|
|
8228
|
+
const [range, setRange] = (0, import_react15.useState)(null);
|
|
8229
|
+
const [fillTarget, setFillTarget] = (0, import_react15.useState)(null);
|
|
8230
|
+
const [stack, setStack] = (0, import_react15.useState)(() => createUndoStack(options?.undoDepth ?? 100));
|
|
8231
|
+
const draggingRef = (0, import_react15.useRef)(null);
|
|
8232
|
+
const optionsRef = (0, import_react15.useRef)(options);
|
|
8233
|
+
optionsRef.current = options;
|
|
8234
|
+
const rowIds = options?.rowIds ?? [];
|
|
8235
|
+
const columnIds = (0, import_react15.useMemo)(
|
|
8236
|
+
() => options ? options.columnIds.filter((id) => id !== "") : [],
|
|
8237
|
+
[options]
|
|
8238
|
+
);
|
|
8239
|
+
(0, import_react15.useEffect)(() => {
|
|
8240
|
+
if (!range) return;
|
|
8241
|
+
const rowSet = new Set(rowIds);
|
|
8242
|
+
const colSet = new Set(columnIds);
|
|
8243
|
+
const alive = rowSet.has(range.anchor.rowId) && rowSet.has(range.focus.rowId) && colSet.has(range.anchor.fieldName) && colSet.has(range.focus.fieldName);
|
|
8244
|
+
if (!alive) setRange(null);
|
|
8245
|
+
}, [range, rowIds, columnIds]);
|
|
8246
|
+
const bounds = (0, import_react15.useMemo)(
|
|
8247
|
+
() => range ? rangeBounds(range, rowIds, columnIds) : null,
|
|
8248
|
+
[range, rowIds, columnIds]
|
|
8249
|
+
);
|
|
8250
|
+
const rowIndexById = (0, import_react15.useMemo)(() => {
|
|
8251
|
+
const map = /* @__PURE__ */ new Map();
|
|
8252
|
+
for (let i = 0; i < rowIds.length; i += 1) map.set(rowIds[i], i);
|
|
8253
|
+
return map;
|
|
8254
|
+
}, [rowIds]);
|
|
8255
|
+
const columnIndexById = (0, import_react15.useMemo)(() => {
|
|
8256
|
+
const map = /* @__PURE__ */ new Map();
|
|
8257
|
+
for (let i = 0; i < columnIds.length; i += 1) map.set(columnIds[i], i);
|
|
8258
|
+
return map;
|
|
8259
|
+
}, [columnIds]);
|
|
8260
|
+
const screenPatches = (0, import_react15.useCallback)(
|
|
8261
|
+
(patches) => {
|
|
8262
|
+
const validate = optionsRef.current?.validateCell;
|
|
8263
|
+
if (!validate) return { accepted: patches, refusals: [] };
|
|
8264
|
+
const accepted = [];
|
|
8265
|
+
const refusals = [];
|
|
8266
|
+
for (const patch of patches) {
|
|
8267
|
+
let reason;
|
|
8268
|
+
try {
|
|
8269
|
+
reason = validate({ rowId: patch.rowId, columnId: patch.columnId, value: patch.value });
|
|
8270
|
+
} catch {
|
|
8271
|
+
reason = void 0;
|
|
8272
|
+
}
|
|
8273
|
+
if (reason) refusals.push({ columnId: patch.columnId, reason });
|
|
8274
|
+
else accepted.push(patch);
|
|
8275
|
+
}
|
|
8276
|
+
return { accepted, refusals };
|
|
8277
|
+
},
|
|
8278
|
+
[]
|
|
8279
|
+
);
|
|
8280
|
+
const applyPatches = (0, import_react15.useCallback)(
|
|
8281
|
+
async (patches, intent, label) => {
|
|
8282
|
+
const current = optionsRef.current;
|
|
8283
|
+
if (!current || patches.length === 0) return;
|
|
8284
|
+
const depth = current.undoDepth ?? 100;
|
|
8285
|
+
if (depth > 0 && intent !== "undo" && intent !== "redo") {
|
|
8286
|
+
const before = patches.map((patch) => ({
|
|
8287
|
+
rowId: patch.rowId,
|
|
8288
|
+
columnId: patch.columnId,
|
|
8289
|
+
value: current.valueAt(patch.rowId, patch.columnId) ?? null
|
|
8290
|
+
}));
|
|
8291
|
+
setStack((previous) => pushUndo(previous, undoEntryFor(before, patches, label)));
|
|
8292
|
+
}
|
|
8293
|
+
await current.onPatch(patches, intent);
|
|
8294
|
+
},
|
|
8295
|
+
[]
|
|
8296
|
+
);
|
|
8297
|
+
const readValueAt = (0, import_react15.useCallback)((rowIndex, columnIndex) => {
|
|
8298
|
+
const current = optionsRef.current;
|
|
8299
|
+
const rowId = current?.rowIds[rowIndex];
|
|
8300
|
+
const columnId2 = current?.columnIds[columnIndex];
|
|
8301
|
+
if (!current || rowId === void 0 || columnId2 === void 0) return null;
|
|
8302
|
+
return current.valueAt(rowId, columnId2);
|
|
8303
|
+
}, []);
|
|
8304
|
+
const fillRequestBase = (0, import_react15.useCallback)(() => {
|
|
8305
|
+
const current = optionsRef.current;
|
|
8306
|
+
if (!current) return null;
|
|
8307
|
+
return {
|
|
8308
|
+
valueAt: readValueAt,
|
|
8309
|
+
columnIds: [...current.columnIds],
|
|
8310
|
+
rowIds: [...current.rowIds],
|
|
8311
|
+
isColumnWritable: current.isColumnWritable
|
|
8312
|
+
};
|
|
8313
|
+
}, [readValueAt]);
|
|
8314
|
+
const announceSkips = (0, import_react15.useCallback)(
|
|
8315
|
+
(skipped, summary) => {
|
|
8316
|
+
const current = optionsRef.current;
|
|
8317
|
+
if (!current?.notify) return;
|
|
8318
|
+
if (skipped.length === 0) {
|
|
8319
|
+
current.notify(summary);
|
|
8320
|
+
return;
|
|
8321
|
+
}
|
|
8322
|
+
const first = skipped[0];
|
|
8323
|
+
const reason = current.columnRefusal?.(first.columnId) ?? first.reason;
|
|
8324
|
+
const rest = skipped.length > 1 ? ` ${skipped.length - 1} more were left alone.` : "";
|
|
8325
|
+
current.notify(`${summary} ${reason}${rest}`);
|
|
8326
|
+
},
|
|
8327
|
+
[]
|
|
8328
|
+
);
|
|
8329
|
+
const doFillDown = (0, import_react15.useCallback)(async () => {
|
|
8330
|
+
const base = fillRequestBase();
|
|
8331
|
+
if (!base || !bounds) return;
|
|
8332
|
+
const result = fillDown({
|
|
8333
|
+
...base,
|
|
8334
|
+
range: { top: bounds.r0, left: bounds.c0, bottom: bounds.r1, right: bounds.c1 }
|
|
8335
|
+
});
|
|
8336
|
+
const screened = screenPatches(result.patches);
|
|
8337
|
+
await applyPatches(screened.accepted, "fill-down", "Filled down");
|
|
8338
|
+
announceSkips([...result.skipped, ...screened.refusals], result.summary);
|
|
8339
|
+
}, [fillRequestBase, bounds, applyPatches, announceSkips, screenPatches]);
|
|
8340
|
+
const doClear = (0, import_react15.useCallback)(async () => {
|
|
8341
|
+
const current = optionsRef.current;
|
|
8342
|
+
if (!current || !bounds) return;
|
|
8343
|
+
const patches = [];
|
|
8344
|
+
const skipped = [];
|
|
8345
|
+
for (let r = bounds.r0; r <= bounds.r1; r += 1) {
|
|
8346
|
+
for (let c = bounds.c0; c <= bounds.c1; c += 1) {
|
|
8347
|
+
const rowId = current.rowIds[r];
|
|
8348
|
+
const columnId2 = current.columnIds[c];
|
|
8349
|
+
if (rowId === void 0 || columnId2 === void 0) continue;
|
|
8350
|
+
if (!current.isColumnWritable(columnId2)) {
|
|
8351
|
+
skipped.push({
|
|
8352
|
+
columnId: columnId2,
|
|
8353
|
+
reason: current.columnRefusal?.(columnId2) ?? `${columnId2} cannot be cleared.`
|
|
8354
|
+
});
|
|
8355
|
+
continue;
|
|
8356
|
+
}
|
|
8357
|
+
patches.push({ rowId, columnId: columnId2, value: null });
|
|
8358
|
+
}
|
|
8359
|
+
}
|
|
8360
|
+
const screened = screenPatches(patches);
|
|
8361
|
+
await applyPatches(screened.accepted, "clear", "Cleared");
|
|
8362
|
+
announceSkips(
|
|
8363
|
+
[...skipped, ...screened.refusals],
|
|
8364
|
+
`Cleared ${screened.accepted.length} cells.`
|
|
8365
|
+
);
|
|
8366
|
+
}, [bounds, applyPatches, announceSkips, screenPatches]);
|
|
8367
|
+
const doUndo = (0, import_react15.useCallback)(async () => {
|
|
8368
|
+
const taken = popUndo(stack);
|
|
8369
|
+
if (!taken.entry) return;
|
|
8370
|
+
setStack(taken.stack);
|
|
8371
|
+
await applyPatches(taken.entry.undo, "undo", taken.entry.label);
|
|
8372
|
+
optionsRef.current?.notify?.(taken.entry.label);
|
|
8373
|
+
}, [stack, applyPatches]);
|
|
8374
|
+
const doRedo = (0, import_react15.useCallback)(async () => {
|
|
8375
|
+
const taken = popRedo(stack);
|
|
8376
|
+
if (!taken.entry) return;
|
|
8377
|
+
setStack(taken.stack);
|
|
8378
|
+
await applyPatches(taken.entry.redo, "redo", taken.entry.label);
|
|
8379
|
+
}, [stack, applyPatches]);
|
|
8380
|
+
const move = (0, import_react15.useCallback)(
|
|
8381
|
+
(direction, extend) => {
|
|
8382
|
+
setRange((previous) => {
|
|
8383
|
+
const from = previous ? previous.focus : null;
|
|
8384
|
+
const next = moveSelection(from, direction, rowIds, columnIds);
|
|
8385
|
+
if (!next) return previous;
|
|
8386
|
+
if (extend && previous) return { anchor: previous.anchor, focus: next };
|
|
8387
|
+
return { anchor: next, focus: next };
|
|
8388
|
+
});
|
|
8389
|
+
},
|
|
8390
|
+
[rowIds, columnIds]
|
|
8391
|
+
);
|
|
8392
|
+
const onKeyDown = (0, import_react15.useCallback)(
|
|
8393
|
+
(event) => {
|
|
8394
|
+
const current = optionsRef.current;
|
|
8395
|
+
if (!current) return;
|
|
8396
|
+
if (targetsAnEditor(event.target)) return;
|
|
8397
|
+
const accel = event.metaKey || event.ctrlKey;
|
|
8398
|
+
if (accel && (event.key === "z" || event.key === "Z")) {
|
|
8399
|
+
event.preventDefault();
|
|
8400
|
+
if (event.shiftKey) void doRedo();
|
|
8401
|
+
else void doUndo();
|
|
8402
|
+
return;
|
|
8403
|
+
}
|
|
8404
|
+
if (accel && (event.key === "y" || event.key === "Y")) {
|
|
8405
|
+
event.preventDefault();
|
|
8406
|
+
void doRedo();
|
|
8407
|
+
return;
|
|
8408
|
+
}
|
|
8409
|
+
const action = classifyGridKey(event);
|
|
8410
|
+
if (!action) return;
|
|
8411
|
+
switch (action.kind) {
|
|
8412
|
+
case "move":
|
|
8413
|
+
event.preventDefault();
|
|
8414
|
+
move(action.move, false);
|
|
8415
|
+
return;
|
|
8416
|
+
case "extend":
|
|
8417
|
+
event.preventDefault();
|
|
8418
|
+
move(action.move, true);
|
|
8419
|
+
return;
|
|
8420
|
+
case "selectAll": {
|
|
8421
|
+
event.preventDefault();
|
|
8422
|
+
const all = allRange(rowIds, columnIds);
|
|
8423
|
+
if (all) setRange(all);
|
|
8424
|
+
return;
|
|
8425
|
+
}
|
|
8426
|
+
case "selectRow": {
|
|
8427
|
+
event.preventDefault();
|
|
8428
|
+
const focused = range?.focus;
|
|
8429
|
+
const next = focused ? rowRange(focused.rowId, columnIds) : null;
|
|
8430
|
+
if (next) setRange(next);
|
|
8431
|
+
return;
|
|
8432
|
+
}
|
|
8433
|
+
case "selectColumn": {
|
|
8434
|
+
event.preventDefault();
|
|
8435
|
+
const focused = range?.focus;
|
|
8436
|
+
const next = focused ? columnRange(focused.fieldName, rowIds) : null;
|
|
8437
|
+
if (next) setRange(next);
|
|
8438
|
+
return;
|
|
8439
|
+
}
|
|
8440
|
+
case "clearCell":
|
|
8441
|
+
event.preventDefault();
|
|
8442
|
+
void doClear();
|
|
8443
|
+
return;
|
|
8444
|
+
case "fillDown":
|
|
8445
|
+
event.preventDefault();
|
|
8446
|
+
void doFillDown();
|
|
8447
|
+
return;
|
|
8448
|
+
case "escape":
|
|
8449
|
+
setRange(null);
|
|
8450
|
+
return;
|
|
8451
|
+
case "edit":
|
|
8452
|
+
case "editSeeded": {
|
|
8453
|
+
const focused = range?.focus;
|
|
8454
|
+
if (!focused || !current.onEditRequest) return;
|
|
8455
|
+
const seed = action.kind === "editSeeded" ? action.seed : null;
|
|
8456
|
+
if (current.onEditRequest(focused, seed)) event.preventDefault();
|
|
8457
|
+
return;
|
|
8458
|
+
}
|
|
8459
|
+
default:
|
|
8460
|
+
return;
|
|
8461
|
+
}
|
|
8462
|
+
},
|
|
8463
|
+
[move, range, rowIds, columnIds, doClear, doFillDown, doUndo, doRedo]
|
|
8464
|
+
);
|
|
8465
|
+
const selectionAsTsv = (0, import_react15.useCallback)(() => {
|
|
8466
|
+
const current = optionsRef.current;
|
|
8467
|
+
if (!current || !range) return "";
|
|
8468
|
+
const grid = rangeRows(range, rowIds, columnIds).map(
|
|
8469
|
+
(row) => row.map((address) => current.valueAt(address.rowId, address.fieldName))
|
|
8470
|
+
);
|
|
8471
|
+
return gridToTsv(grid);
|
|
8472
|
+
}, [range, rowIds, columnIds]);
|
|
8473
|
+
const selectionAddresses = (0, import_react15.useCallback)(() => {
|
|
8474
|
+
if (!range || !bounds) return { rowIds: [], columnIds: [] };
|
|
8475
|
+
return {
|
|
8476
|
+
rowIds: rowIds.slice(bounds.r0, bounds.r1 + 1),
|
|
8477
|
+
columnIds: columnIds.slice(bounds.c0, bounds.c1 + 1)
|
|
8478
|
+
};
|
|
8479
|
+
}, [range, bounds, rowIds, columnIds]);
|
|
8480
|
+
const onCopy = (0, import_react15.useCallback)(
|
|
8481
|
+
(event) => {
|
|
8482
|
+
if (!optionsRef.current || !range || targetsAnEditor(event.target)) return;
|
|
8483
|
+
const text = selectionAsTsv();
|
|
8484
|
+
if (!text) return;
|
|
8485
|
+
event.preventDefault();
|
|
8486
|
+
event.clipboardData?.setData("text/plain", text);
|
|
8487
|
+
},
|
|
8488
|
+
[range, selectionAsTsv]
|
|
8489
|
+
);
|
|
8490
|
+
const onCut = (0, import_react15.useCallback)(
|
|
8491
|
+
(event) => {
|
|
8492
|
+
if (!optionsRef.current || !range || targetsAnEditor(event.target)) return;
|
|
8493
|
+
const text = selectionAsTsv();
|
|
8494
|
+
if (!text) return;
|
|
8495
|
+
event.preventDefault();
|
|
8496
|
+
event.clipboardData?.setData("text/plain", text);
|
|
8497
|
+
void doClear();
|
|
8498
|
+
},
|
|
8499
|
+
[range, selectionAsTsv, doClear]
|
|
8500
|
+
);
|
|
8501
|
+
const onPaste = (0, import_react15.useCallback)(
|
|
8502
|
+
(event) => {
|
|
8503
|
+
const current = optionsRef.current;
|
|
8504
|
+
if (!current || current.paste === false || !range || targetsAnEditor(event.target)) return;
|
|
8505
|
+
const text = event.clipboardData?.getData("text/plain") ?? "";
|
|
8506
|
+
if (!text) return;
|
|
8507
|
+
event.preventDefault();
|
|
8508
|
+
const block = parseClipboardGrid(text);
|
|
8509
|
+
const start = range.focus;
|
|
8510
|
+
const startRow = rowIds.indexOf(start.rowId);
|
|
8511
|
+
const startCol = columnIds.indexOf(start.fieldName);
|
|
8512
|
+
if (startRow === -1 || startCol === -1) return;
|
|
8513
|
+
const patches = [];
|
|
8514
|
+
const skipped = [];
|
|
8515
|
+
let outside = 0;
|
|
8516
|
+
for (let r = 0; r < block.length; r += 1) {
|
|
8517
|
+
const line = block[r] ?? [];
|
|
8518
|
+
for (let c = 0; c < line.length; c += 1) {
|
|
8519
|
+
const rowId = rowIds[startRow + r];
|
|
8520
|
+
const columnId2 = columnIds[startCol + c];
|
|
8521
|
+
if (rowId === void 0 || columnId2 === void 0) {
|
|
8522
|
+
outside += 1;
|
|
8523
|
+
continue;
|
|
8524
|
+
}
|
|
8525
|
+
if (!current.isColumnWritable(columnId2)) {
|
|
8526
|
+
skipped.push({
|
|
8527
|
+
columnId: columnId2,
|
|
8528
|
+
reason: current.columnRefusal?.(columnId2) ?? `${columnId2} cannot take a pasted value.`
|
|
8529
|
+
});
|
|
8530
|
+
continue;
|
|
8531
|
+
}
|
|
8532
|
+
patches.push({ rowId, columnId: columnId2, value: line[c] ?? null });
|
|
8533
|
+
}
|
|
8534
|
+
}
|
|
8535
|
+
const screened = screenPatches(patches);
|
|
8536
|
+
void applyPatches(screened.accepted, "paste", "Pasted");
|
|
8537
|
+
const tail = outside > 0 ? ` ${outside} landed past the edge of the table and were ignored.` : "";
|
|
8538
|
+
announceSkips([...skipped, ...screened.refusals], `Pasted ${screened.accepted.length} cells.${tail}`);
|
|
8539
|
+
},
|
|
8540
|
+
[range, rowIds, columnIds, applyPatches, announceSkips, screenPatches]
|
|
8541
|
+
);
|
|
8542
|
+
const cellProps = (0, import_react15.useCallback)(
|
|
8543
|
+
(rowId, columnId2) => {
|
|
8544
|
+
const address = { rowId, fieldName: columnId2 };
|
|
8545
|
+
const rowIndex = rowIndexById.get(rowId) ?? -1;
|
|
8546
|
+
const colIndex = columnIndexById.get(columnId2) ?? -1;
|
|
8547
|
+
const selected = bounds !== null && rowIndex >= bounds.r0 && rowIndex <= bounds.r1 && colIndex >= bounds.c0 && colIndex <= bounds.c1;
|
|
8548
|
+
const active = range !== null && sameCell(range.focus, address);
|
|
8549
|
+
const inFillPreview = fillTarget !== null && rowIndex >= fillTarget.top && rowIndex <= fillTarget.bottom && colIndex >= fillTarget.left && colIndex <= fillTarget.right;
|
|
8550
|
+
return {
|
|
8551
|
+
"data-matrx-cell-row": rowId,
|
|
8552
|
+
"data-matrx-cell-col": columnId2,
|
|
8553
|
+
...selected ? { "data-matrx-cell-selected": "true" } : {},
|
|
8554
|
+
...active ? { "data-matrx-cell-active": "true" } : {},
|
|
8555
|
+
...inFillPreview ? { "data-matrx-cell-fill-preview": "true" } : {},
|
|
8556
|
+
onMouseDown: (event) => {
|
|
8557
|
+
if (event.button !== 0) return;
|
|
8558
|
+
event.preventDefault();
|
|
8559
|
+
const origin = event.currentTarget;
|
|
8560
|
+
if (typeof HTMLElement !== "undefined" && origin instanceof HTMLElement) {
|
|
8561
|
+
origin.closest('[data-matrx-table-spreadsheet="true"]')?.focus({ preventScroll: true });
|
|
8562
|
+
}
|
|
8563
|
+
setRange(
|
|
8564
|
+
(previous) => event.shiftKey && previous ? { anchor: previous.anchor, focus: address } : { anchor: address, focus: address }
|
|
8565
|
+
);
|
|
8566
|
+
draggingRef.current = "select";
|
|
8567
|
+
},
|
|
8568
|
+
onMouseEnter: () => {
|
|
8569
|
+
if (draggingRef.current === "select") {
|
|
8570
|
+
setRange((previous) => previous ? { anchor: previous.anchor, focus: address } : previous);
|
|
8571
|
+
return;
|
|
8572
|
+
}
|
|
8573
|
+
if (draggingRef.current === "fill" && bounds) {
|
|
8574
|
+
setFillTarget(
|
|
8575
|
+
fillTargetFor(
|
|
8576
|
+
{ top: bounds.r0, left: bounds.c0, bottom: bounds.r1, right: bounds.c1 },
|
|
8577
|
+
rowIndex,
|
|
8578
|
+
colIndex
|
|
8579
|
+
)
|
|
8580
|
+
);
|
|
8581
|
+
}
|
|
8582
|
+
}
|
|
8583
|
+
};
|
|
8584
|
+
},
|
|
8585
|
+
[rowIndexById, columnIndexById, bounds, range, fillTarget]
|
|
8586
|
+
);
|
|
8587
|
+
const isFillHandleCell = (0, import_react15.useCallback)(
|
|
8588
|
+
(rowId, columnId2) => {
|
|
8589
|
+
const current = optionsRef.current;
|
|
8590
|
+
if (!current || current.fillHandle === false || !bounds) return false;
|
|
8591
|
+
return rowIds[bounds.r1] === rowId && columnIds[bounds.c1] === columnId2;
|
|
8592
|
+
},
|
|
8593
|
+
[bounds, rowIds, columnIds]
|
|
8594
|
+
);
|
|
8595
|
+
const startFillDrag = (0, import_react15.useCallback)(
|
|
8596
|
+
(event) => {
|
|
8597
|
+
event.preventDefault();
|
|
8598
|
+
event.stopPropagation();
|
|
8599
|
+
draggingRef.current = "fill";
|
|
8600
|
+
},
|
|
8601
|
+
[]
|
|
8602
|
+
);
|
|
8603
|
+
const fillTargetRef = (0, import_react15.useRef)(null);
|
|
8604
|
+
fillTargetRef.current = fillTarget;
|
|
8605
|
+
const boundsRef = (0, import_react15.useRef)(null);
|
|
8606
|
+
boundsRef.current = bounds;
|
|
8607
|
+
(0, import_react15.useEffect)(() => {
|
|
8608
|
+
if (!options) return;
|
|
8609
|
+
const commit = () => {
|
|
8610
|
+
const wasDragging = draggingRef.current;
|
|
8611
|
+
draggingRef.current = null;
|
|
8612
|
+
if (wasDragging !== "fill") return;
|
|
8613
|
+
const target = fillTargetRef.current;
|
|
8614
|
+
const source = boundsRef.current;
|
|
8615
|
+
setFillTarget(null);
|
|
8616
|
+
if (!target || !source) return;
|
|
8617
|
+
const base = fillRequestBase();
|
|
8618
|
+
if (!base) return;
|
|
8619
|
+
const result = fillRange({
|
|
8620
|
+
...base,
|
|
8621
|
+
source: { top: source.r0, left: source.c0, bottom: source.r1, right: source.c1 },
|
|
8622
|
+
target
|
|
8623
|
+
});
|
|
8624
|
+
const screened = screenPatches(result.patches);
|
|
8625
|
+
void applyPatches(screened.accepted, "fill", "Filled");
|
|
8626
|
+
announceSkips([...result.skipped, ...screened.refusals], result.summary);
|
|
8627
|
+
};
|
|
8628
|
+
window.addEventListener("mouseup", commit);
|
|
8629
|
+
return () => window.removeEventListener("mouseup", commit);
|
|
8630
|
+
}, [options, fillRequestBase, applyPatches, announceSkips, screenPatches]);
|
|
8631
|
+
return {
|
|
8632
|
+
range,
|
|
8633
|
+
bounds,
|
|
8634
|
+
enabled: options !== null,
|
|
8635
|
+
containerProps: {
|
|
8636
|
+
tabIndex: options ? 0 : -1,
|
|
8637
|
+
onKeyDown,
|
|
8638
|
+
onCopy,
|
|
8639
|
+
onCut,
|
|
8640
|
+
onPaste
|
|
8641
|
+
},
|
|
8642
|
+
cellProps,
|
|
8643
|
+
isFillHandleCell,
|
|
8644
|
+
startFillDrag,
|
|
8645
|
+
canUndo: stack.past.length > 0,
|
|
8646
|
+
canRedo: stack.future.length > 0,
|
|
8647
|
+
selectionTsv: selectionAsTsv,
|
|
8648
|
+
selectionAddresses
|
|
8649
|
+
};
|
|
8650
|
+
}
|
|
8651
|
+
|
|
8652
|
+
// src/data-table/coverage.ts
|
|
8653
|
+
var PARTIAL_BADGE = "Partial";
|
|
8654
|
+
var UNKNOWN_TOTAL_BADGE = "Unknown total";
|
|
8655
|
+
var NUMBERS2 = new Intl.NumberFormat("en-US");
|
|
8656
|
+
function formatNumber(value) {
|
|
8657
|
+
try {
|
|
8658
|
+
return NUMBERS2.format(value);
|
|
8659
|
+
} catch {
|
|
8660
|
+
return String(value);
|
|
8661
|
+
}
|
|
8662
|
+
}
|
|
8663
|
+
function pluralize(noun) {
|
|
8664
|
+
const word = noun.trim();
|
|
8665
|
+
if (!word) return "rows";
|
|
8666
|
+
const lower = word.toLowerCase();
|
|
8667
|
+
if (/[^aeiou]y$/.test(lower)) return `${word.slice(0, -1)}ies`;
|
|
8668
|
+
if (/(s|x|z|ch|sh)$/.test(lower)) return `${word}es`;
|
|
8669
|
+
return `${word}s`;
|
|
8670
|
+
}
|
|
8671
|
+
function quantity(value, noun) {
|
|
8672
|
+
return `${formatNumber(value)} ${value === 1 ? noun.trim() || "row" : pluralize(noun)}`;
|
|
8673
|
+
}
|
|
8674
|
+
function toWhole(value) {
|
|
8675
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
|
|
8676
|
+
}
|
|
8677
|
+
function toOptionalWhole(value) {
|
|
8678
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) return void 0;
|
|
8679
|
+
return Math.floor(value);
|
|
8680
|
+
}
|
|
8681
|
+
function describeCoverage(input) {
|
|
8682
|
+
const safe = input && typeof input === "object" ? input : { loaded: 0, answeredBy: "client" };
|
|
8683
|
+
const loaded = toWhole(safe.loaded);
|
|
8684
|
+
const matched = toOptionalWhole(safe.matched);
|
|
8685
|
+
const total = toOptionalWhole(safe.total);
|
|
8686
|
+
const cap = toOptionalWhole(safe.cap);
|
|
8687
|
+
const answeredBy = safe.answeredBy === "source" ? "source" : "client";
|
|
8688
|
+
const noun = typeof safe.noun === "string" && safe.noun.trim() ? safe.noun.trim() : "row";
|
|
8689
|
+
const reference = matched ?? total;
|
|
8690
|
+
const capReached = cap !== void 0 && cap > 0 && loaded >= cap;
|
|
8691
|
+
if (reference !== void 0 && loaded >= reference) {
|
|
8692
|
+
return {
|
|
8693
|
+
scope: "all",
|
|
8694
|
+
complete: true,
|
|
8695
|
+
count: { value: matched ?? reference, exact: true },
|
|
8696
|
+
notice: "",
|
|
8697
|
+
badge: ""
|
|
8698
|
+
};
|
|
8699
|
+
}
|
|
8700
|
+
if (answeredBy === "source" && matched !== void 0 && !capReached) {
|
|
8701
|
+
return { scope: "all", complete: true, count: { value: matched, exact: true }, notice: "", badge: "" };
|
|
8702
|
+
}
|
|
8703
|
+
if (capReached && cap !== void 0) {
|
|
8704
|
+
const rest = reference !== void 0 ? `${quantity(reference, noun)} in this table; the rest were not looked at.` : "Anything past that was not looked at.";
|
|
8705
|
+
return {
|
|
8706
|
+
scope: "capped",
|
|
8707
|
+
complete: false,
|
|
8708
|
+
count: { value: loaded, exact: false },
|
|
8709
|
+
notice: `This filter searched the first ${quantity(cap, noun)} only. ${rest}`,
|
|
8710
|
+
badge: PARTIAL_BADGE
|
|
8711
|
+
};
|
|
8712
|
+
}
|
|
8713
|
+
if (answeredBy === "client" && reference !== void 0) {
|
|
8714
|
+
return {
|
|
8715
|
+
scope: "loaded",
|
|
8716
|
+
complete: false,
|
|
8717
|
+
count: { value: loaded, exact: false },
|
|
8718
|
+
notice: `Filtering the ${quantity(loaded, noun)} loaded so far, not all ${quantity(reference, noun)} in this table.`,
|
|
8719
|
+
badge: PARTIAL_BADGE
|
|
8720
|
+
};
|
|
8721
|
+
}
|
|
8722
|
+
if (answeredBy === "source" && total !== void 0) {
|
|
8723
|
+
return {
|
|
8724
|
+
scope: "all",
|
|
8725
|
+
complete: false,
|
|
8726
|
+
count: { value: loaded, exact: false },
|
|
8727
|
+
notice: `Showing the ${quantity(loaded, noun)} loaded so far out of ${quantity(total, noun)} in this table.`,
|
|
8728
|
+
badge: PARTIAL_BADGE
|
|
8729
|
+
};
|
|
8730
|
+
}
|
|
8731
|
+
return {
|
|
8732
|
+
scope: answeredBy === "source" ? "all" : "loaded",
|
|
8733
|
+
complete: false,
|
|
8734
|
+
count: { value: loaded, exact: false },
|
|
8735
|
+
notice: `Showing the ${quantity(loaded, noun)} loaded so far. The total number of ${pluralize(noun)} in this table is not known.`,
|
|
8736
|
+
badge: UNKNOWN_TOTAL_BADGE
|
|
8737
|
+
};
|
|
8738
|
+
}
|
|
8739
|
+
|
|
8740
|
+
// src/data-table/ranked-search.ts
|
|
8741
|
+
function inferTableSearchRole(field) {
|
|
8742
|
+
const key = field.replace(/([a-z])([A-Z])/g, "$1_$2").toLowerCase().replace(/[\s-]+/g, "_");
|
|
8743
|
+
if (key === "id" || key === "uuid" || key.endsWith("_id")) return "id";
|
|
8744
|
+
if (/^(name|alias|label|title|key|slug|display_name|common_name|model_name)$/.test(key) || /_(name|label|title)$/.test(key)) return "name";
|
|
8745
|
+
if (/^(description|summary|details|notes|blurb)$/.test(key) || key.endsWith("_description")) return "description";
|
|
8746
|
+
return "other";
|
|
8747
|
+
}
|
|
8748
|
+
function searchableFields(row, columns) {
|
|
8749
|
+
const values = /* @__PURE__ */ new Map();
|
|
8750
|
+
if (row !== null && typeof row === "object") {
|
|
8751
|
+
for (const [key, value] of Object.entries(row)) values.set(key, stringifyCellValue(value));
|
|
8752
|
+
}
|
|
8753
|
+
for (const column of columns) {
|
|
8754
|
+
if (column.accessorKey || column.accessorFn || column.filterValue) {
|
|
8755
|
+
values.set(columnId(column), stringifyCellValue(getFilterValue(row, column)));
|
|
8756
|
+
}
|
|
8757
|
+
}
|
|
8758
|
+
return values;
|
|
8759
|
+
}
|
|
8760
|
+
function resolveTableSearchScopes(rows, columns, options = {}) {
|
|
8761
|
+
const fields = new Set(columns.filter((c) => c.accessorKey || c.accessorFn || c.filterValue).map(columnId));
|
|
8762
|
+
for (const row of rows) if (row !== null && typeof row === "object") Object.keys(row).forEach((key) => fields.add(key));
|
|
8763
|
+
const roles = new Set([...fields].map((key) => options.roles?.[key] ?? inferTableSearchRole(key)));
|
|
8764
|
+
const scopes = [{ id: "all", label: "All" }];
|
|
8765
|
+
for (const [id, label] of [["id", "ID"], ["name", "Name"], ["description", "Description"]]) {
|
|
8766
|
+
if (roles.has(id)) scopes.push({ id, label });
|
|
8767
|
+
}
|
|
8768
|
+
for (const scope of options.scopes ?? []) if (!scopes.some((s) => s.id === scope.id) && scope.fields?.length) scopes.push(scope);
|
|
8769
|
+
return scopes;
|
|
8770
|
+
}
|
|
8771
|
+
function rankTableSearchRows(rows, columns, query, options = {}, extraText) {
|
|
8772
|
+
const q = query.trim().toLocaleLowerCase();
|
|
8773
|
+
if (!q) return [...rows];
|
|
8774
|
+
const scope = options.scope ?? "all";
|
|
8775
|
+
const customScope = options.scopes?.find((s) => s.id === scope);
|
|
8776
|
+
const mode = options.matchMode ?? "contains";
|
|
8777
|
+
return rows.flatMap((row, index) => {
|
|
8778
|
+
const fields = [...searchableFields(row, columns)].filter(([key]) => {
|
|
8779
|
+
if (scope === "all") return true;
|
|
8780
|
+
if (customScope) return customScope.fields?.includes(key) ?? false;
|
|
8781
|
+
return (options.roles?.[key] ?? inferTableSearchRole(key)) === scope;
|
|
8782
|
+
});
|
|
8783
|
+
const extra = scope === "all" ? extraText?.(row) : void 0;
|
|
8784
|
+
const texts = fields.map(([, value]) => value);
|
|
8785
|
+
if (extra) texts.push(extra);
|
|
8786
|
+
const matched = mode === "whole_words" ? matchesTableSearch(texts.join(" "), q, mode) : texts.some((value) => matchesTableSearch(value, q, mode));
|
|
8787
|
+
if (!matched) return [];
|
|
8788
|
+
let rank = 3;
|
|
8789
|
+
for (const [key, value] of fields) {
|
|
8790
|
+
if (!matchesTableSearch(value, q, mode)) continue;
|
|
8791
|
+
const role = options.roles?.[key] ?? inferTableSearchRole(key);
|
|
8792
|
+
if (role === "id" || role === "name") rank = Math.min(rank, value.trim().toLocaleLowerCase() === q ? 0 : 1);
|
|
8793
|
+
else if (role === "description") rank = Math.min(rank, 2);
|
|
8794
|
+
}
|
|
8795
|
+
return [{ row, rank, index }];
|
|
8796
|
+
}).sort((a, b) => a.rank - b.rank || a.index - b.index).map((item) => item.row);
|
|
8797
|
+
}
|
|
8798
|
+
|
|
8799
|
+
// src/data-table/ColumnManager.tsx
|
|
8800
|
+
var import_react16 = require("react");
|
|
8801
|
+
var import_core2 = require("@dnd-kit/core");
|
|
8802
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
8803
|
+
function ColumnManager({
|
|
8804
|
+
open,
|
|
8805
|
+
onOpenChange,
|
|
8806
|
+
columns,
|
|
8807
|
+
order,
|
|
8808
|
+
hidden,
|
|
8809
|
+
onApply
|
|
8810
|
+
}) {
|
|
8811
|
+
const byId = (0, import_react16.useMemo)(
|
|
8812
|
+
() => new Map(columns.map((column) => [columnId(column), column])),
|
|
8813
|
+
[columns]
|
|
8814
|
+
);
|
|
8815
|
+
const [draftOrder, setDraftOrder] = (0, import_react16.useState)(order);
|
|
8816
|
+
const [draftHidden, setDraftHidden] = (0, import_react16.useState)(() => new Set(hidden));
|
|
8817
|
+
const [draggedColumnId, setDraggedColumnId] = (0, import_react16.useState)(null);
|
|
8818
|
+
const [dropTarget, setDropTarget] = (0, import_react16.useState)(null);
|
|
8819
|
+
(0, import_react16.useEffect)(() => {
|
|
8820
|
+
if (!open) return;
|
|
8821
|
+
setDraftOrder(order);
|
|
8822
|
+
setDraftHidden(new Set(hidden));
|
|
8823
|
+
}, [open, order, hidden]);
|
|
8824
|
+
const move = (id, direction) => {
|
|
8825
|
+
setDraftOrder((current) => {
|
|
8826
|
+
const index = current.indexOf(id);
|
|
8827
|
+
const target = index + direction;
|
|
8828
|
+
if (index < 0 || target < 0 || target >= current.length) return current;
|
|
8829
|
+
const next = [...current];
|
|
8830
|
+
const displaced = next[target];
|
|
8831
|
+
if (displaced === void 0) return current;
|
|
8832
|
+
next[target] = id;
|
|
8833
|
+
next[index] = displaced;
|
|
8834
|
+
return next;
|
|
8835
|
+
});
|
|
8836
|
+
};
|
|
8837
|
+
const moveTo = (id, targetId) => {
|
|
8838
|
+
if (id === targetId) return;
|
|
8839
|
+
setDraftOrder((current) => {
|
|
8840
|
+
const from = current.indexOf(id);
|
|
8841
|
+
const target = current.indexOf(targetId);
|
|
8842
|
+
if (from < 0 || target < 0) return current;
|
|
8843
|
+
const next = [...current];
|
|
8844
|
+
next.splice(from, 1);
|
|
8845
|
+
const targetAfterRemoval = next.indexOf(targetId);
|
|
8846
|
+
next.splice(targetAfterRemoval, 0, id);
|
|
8847
|
+
return next;
|
|
8848
|
+
});
|
|
6902
8849
|
};
|
|
6903
8850
|
(0, import_core2.useDndMonitor)({
|
|
6904
8851
|
onDragStart(event) {
|
|
@@ -7399,7 +9346,7 @@ function parseTableViewSnapshot(raw) {
|
|
|
7399
9346
|
}
|
|
7400
9347
|
|
|
7401
9348
|
// src/data-table/MatrxUuidCell.tsx
|
|
7402
|
-
var
|
|
9349
|
+
var import_react17 = require("react");
|
|
7403
9350
|
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
7404
9351
|
var SHORT_LEN = 8;
|
|
7405
9352
|
function shortUuid(id, len = SHORT_LEN) {
|
|
@@ -7439,11 +9386,11 @@ function MatrxUuidCell({
|
|
|
7439
9386
|
}) {
|
|
7440
9387
|
const { resolveEntityDoors, ResourcePeek } = useMatrxDataTableHost();
|
|
7441
9388
|
const { notify, notice } = useTableNotice();
|
|
7442
|
-
const [copied, setCopied] = (0,
|
|
7443
|
-
const [opening, setOpening] = (0,
|
|
7444
|
-
const [peekOpen, setPeekOpen] = (0,
|
|
7445
|
-
const timer = (0,
|
|
7446
|
-
(0,
|
|
9389
|
+
const [copied, setCopied] = (0, import_react17.useState)(false);
|
|
9390
|
+
const [opening, setOpening] = (0, import_react17.useState)(false);
|
|
9391
|
+
const [peekOpen, setPeekOpen] = (0, import_react17.useState)(false);
|
|
9392
|
+
const timer = (0, import_react17.useRef)(null);
|
|
9393
|
+
(0, import_react17.useEffect)(
|
|
7447
9394
|
() => () => {
|
|
7448
9395
|
if (timer.current) clearTimeout(timer.current);
|
|
7449
9396
|
},
|
|
@@ -7738,7 +9685,7 @@ function DataRowInspector({
|
|
|
7738
9685
|
}
|
|
7739
9686
|
|
|
7740
9687
|
// src/data-table/DataRowWindow.tsx
|
|
7741
|
-
var
|
|
9688
|
+
var import_react18 = require("react");
|
|
7742
9689
|
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
7743
9690
|
function DataRowWindow({
|
|
7744
9691
|
isOpen,
|
|
@@ -7759,8 +9706,8 @@ function DataRowWindow({
|
|
|
7759
9706
|
const hasEdit = editContent != null;
|
|
7760
9707
|
const hasTabs = hasEdit && children == null;
|
|
7761
9708
|
const initialTab = defaultTab ?? (hasEdit ? "edit" : "view");
|
|
7762
|
-
const [tab, setTab] = (0,
|
|
7763
|
-
(0,
|
|
9709
|
+
const [tab, setTab] = (0, import_react18.useState)(initialTab);
|
|
9710
|
+
(0, import_react18.useEffect)(() => {
|
|
7764
9711
|
if (!isOpen) return;
|
|
7765
9712
|
setTab(defaultTab ?? (hasEdit ? "edit" : "view"));
|
|
7766
9713
|
}, [isOpen, windowId, hasEdit, defaultTab]);
|
|
@@ -7906,8 +9853,8 @@ function toNumber(value) {
|
|
|
7906
9853
|
if (typeof value === "string") {
|
|
7907
9854
|
const cleaned = value.replace(/[,\s$€£¥%]/g, "");
|
|
7908
9855
|
if (cleaned === "") return null;
|
|
7909
|
-
const
|
|
7910
|
-
return Number.isFinite(
|
|
9856
|
+
const n2 = Number(cleaned);
|
|
9857
|
+
return Number.isFinite(n2) ? n2 : null;
|
|
7911
9858
|
}
|
|
7912
9859
|
return null;
|
|
7913
9860
|
}
|
|
@@ -7945,14 +9892,14 @@ function toList(value) {
|
|
|
7945
9892
|
}
|
|
7946
9893
|
return null;
|
|
7947
9894
|
}
|
|
7948
|
-
function groupedNumber(
|
|
9895
|
+
function groupedNumber(n2, options) {
|
|
7949
9896
|
return new Intl.NumberFormat(void 0, {
|
|
7950
9897
|
useGrouping: options.useGrouping !== false,
|
|
7951
9898
|
...options.precision != null ? {
|
|
7952
9899
|
minimumFractionDigits: options.precision,
|
|
7953
9900
|
maximumFractionDigits: options.precision
|
|
7954
9901
|
} : { maximumFractionDigits: 10 }
|
|
7955
|
-
}).format(
|
|
9902
|
+
}).format(n2);
|
|
7956
9903
|
}
|
|
7957
9904
|
function affix(text, options) {
|
|
7958
9905
|
return `${options.prefix ?? ""}${text}${options.suffix ?? ""}`;
|
|
@@ -8086,8 +10033,8 @@ var DEFS = [
|
|
|
8086
10033
|
numericAlign: true,
|
|
8087
10034
|
optionKeys: ["useGrouping", "precision", "prefix", "suffix"],
|
|
8088
10035
|
format: (v, o) => {
|
|
8089
|
-
const
|
|
8090
|
-
return
|
|
10036
|
+
const n2 = toNumber(v);
|
|
10037
|
+
return n2 === null ? null : affix(groupedNumber(n2, o), o);
|
|
8091
10038
|
},
|
|
8092
10039
|
parse: (raw) => toNumber(raw)
|
|
8093
10040
|
},
|
|
@@ -8102,9 +10049,9 @@ var DEFS = [
|
|
|
8102
10049
|
numericAlign: true,
|
|
8103
10050
|
optionKeys: ["precision", "useGrouping", "prefix", "suffix"],
|
|
8104
10051
|
format: (v, o) => {
|
|
8105
|
-
const
|
|
8106
|
-
if (
|
|
8107
|
-
return affix(groupedNumber(
|
|
10052
|
+
const n2 = toNumber(v);
|
|
10053
|
+
if (n2 === null) return null;
|
|
10054
|
+
return affix(groupedNumber(n2, { ...o, precision: o.precision ?? 2 }), o);
|
|
8108
10055
|
},
|
|
8109
10056
|
parse: (raw) => toNumber(raw)
|
|
8110
10057
|
},
|
|
@@ -8119,8 +10066,8 @@ var DEFS = [
|
|
|
8119
10066
|
numericAlign: true,
|
|
8120
10067
|
optionKeys: ["currency", "precision"],
|
|
8121
10068
|
format: (v, o) => {
|
|
8122
|
-
const
|
|
8123
|
-
if (
|
|
10069
|
+
const n2 = toNumber(v);
|
|
10070
|
+
if (n2 === null) return null;
|
|
8124
10071
|
const currency = (o.currency || "USD").toUpperCase();
|
|
8125
10072
|
try {
|
|
8126
10073
|
return new Intl.NumberFormat(void 0, {
|
|
@@ -8130,9 +10077,9 @@ var DEFS = [
|
|
|
8130
10077
|
minimumFractionDigits: o.precision,
|
|
8131
10078
|
maximumFractionDigits: o.precision
|
|
8132
10079
|
} : {}
|
|
8133
|
-
}).format(
|
|
10080
|
+
}).format(n2);
|
|
8134
10081
|
} catch {
|
|
8135
|
-
return `${groupedNumber(
|
|
10082
|
+
return `${groupedNumber(n2, { precision: o.precision ?? 2 })} ${currency}`;
|
|
8136
10083
|
}
|
|
8137
10084
|
},
|
|
8138
10085
|
parse: (raw) => toNumber(raw)
|
|
@@ -8148,9 +10095,9 @@ var DEFS = [
|
|
|
8148
10095
|
numericAlign: true,
|
|
8149
10096
|
optionKeys: ["percentScale", "precision"],
|
|
8150
10097
|
format: (v, o) => {
|
|
8151
|
-
const
|
|
8152
|
-
if (
|
|
8153
|
-
const shown = o.percentScale === "fraction" ?
|
|
10098
|
+
const n2 = toNumber(v);
|
|
10099
|
+
if (n2 === null) return null;
|
|
10100
|
+
const shown = o.percentScale === "fraction" ? n2 * 100 : n2;
|
|
8154
10101
|
return `${groupedNumber(shown, o.precision === void 0 ? {} : { precision: o.precision })}%`;
|
|
8155
10102
|
},
|
|
8156
10103
|
parse: (raw) => toNumber(raw)
|
|
@@ -8166,9 +10113,9 @@ var DEFS = [
|
|
|
8166
10113
|
numericAlign: true,
|
|
8167
10114
|
optionKeys: ["durationUnit"],
|
|
8168
10115
|
format: (v, o) => {
|
|
8169
|
-
const
|
|
8170
|
-
if (
|
|
8171
|
-
return formatSignedDuration(
|
|
10116
|
+
const n2 = toNumber(v);
|
|
10117
|
+
if (n2 === null) return null;
|
|
10118
|
+
return formatSignedDuration(n2 * DURATION_TO_SECONDS[o.durationUnit ?? "seconds"]);
|
|
8172
10119
|
},
|
|
8173
10120
|
parse: (raw) => toNumber(raw)
|
|
8174
10121
|
},
|
|
@@ -8183,13 +10130,13 @@ var DEFS = [
|
|
|
8183
10130
|
numericAlign: true,
|
|
8184
10131
|
optionKeys: ["useGrouping", "prefix", "suffix"],
|
|
8185
10132
|
format: (v, o) => {
|
|
8186
|
-
const
|
|
8187
|
-
if (
|
|
8188
|
-
return affix(groupedNumber(Math.trunc(
|
|
10133
|
+
const n2 = toNumber(v);
|
|
10134
|
+
if (n2 === null) return null;
|
|
10135
|
+
return affix(groupedNumber(Math.trunc(n2), { ...o, precision: 0 }), o);
|
|
8189
10136
|
},
|
|
8190
10137
|
parse: (raw) => {
|
|
8191
|
-
const
|
|
8192
|
-
return
|
|
10138
|
+
const n2 = toNumber(raw);
|
|
10139
|
+
return n2 === null ? null : Math.trunc(n2);
|
|
8193
10140
|
}
|
|
8194
10141
|
},
|
|
8195
10142
|
{
|
|
@@ -8203,15 +10150,15 @@ var DEFS = [
|
|
|
8203
10150
|
rich: true,
|
|
8204
10151
|
optionKeys: ["ratingMax"],
|
|
8205
10152
|
format: (v, o) => {
|
|
8206
|
-
const
|
|
8207
|
-
if (
|
|
10153
|
+
const n2 = toNumber(v);
|
|
10154
|
+
if (n2 === null) return null;
|
|
8208
10155
|
const max = o.ratingMax ?? 5;
|
|
8209
|
-
if (
|
|
8210
|
-
return `${
|
|
10156
|
+
if (n2 < 0 || n2 > max) return null;
|
|
10157
|
+
return `${n2} / ${max}`;
|
|
8211
10158
|
},
|
|
8212
10159
|
parse: (raw) => {
|
|
8213
|
-
const
|
|
8214
|
-
return
|
|
10160
|
+
const n2 = toNumber(raw);
|
|
10161
|
+
return n2 === null ? null : Math.round(n2);
|
|
8215
10162
|
}
|
|
8216
10163
|
},
|
|
8217
10164
|
{
|
|
@@ -8224,12 +10171,12 @@ var DEFS = [
|
|
|
8224
10171
|
editor: "number",
|
|
8225
10172
|
numericAlign: true,
|
|
8226
10173
|
format: (v) => {
|
|
8227
|
-
const
|
|
8228
|
-
return
|
|
10174
|
+
const n2 = toNumber(v);
|
|
10175
|
+
return n2 === null ? null : (0, import_format3.formatFileSize)(n2);
|
|
8229
10176
|
},
|
|
8230
10177
|
parse: (raw) => {
|
|
8231
|
-
const
|
|
8232
|
-
return
|
|
10178
|
+
const n2 = toNumber(raw);
|
|
10179
|
+
return n2 === null ? null : Math.trunc(n2);
|
|
8233
10180
|
}
|
|
8234
10181
|
},
|
|
8235
10182
|
// ── Choice ────────────────────────────────────────────────────────────────
|
|
@@ -8639,8 +10586,19 @@ function DirtySavePill({
|
|
|
8639
10586
|
}
|
|
8640
10587
|
|
|
8641
10588
|
// src/data-table/EditableTableCell.tsx
|
|
8642
|
-
var
|
|
10589
|
+
var import_react19 = require("react");
|
|
8643
10590
|
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
10591
|
+
function CellRefusal({ reason }) {
|
|
10592
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
10593
|
+
"p",
|
|
10594
|
+
{
|
|
10595
|
+
role: "alert",
|
|
10596
|
+
"data-matrx-cell-refusal": "true",
|
|
10597
|
+
className: "mt-1 text-[11px] leading-snug text-amber-700 dark:text-amber-400",
|
|
10598
|
+
children: reason
|
|
10599
|
+
}
|
|
10600
|
+
);
|
|
10601
|
+
}
|
|
8644
10602
|
function CellEditShell({
|
|
8645
10603
|
href,
|
|
8646
10604
|
display,
|
|
@@ -8687,12 +10645,17 @@ function EditableTableCell({
|
|
|
8687
10645
|
className,
|
|
8688
10646
|
href,
|
|
8689
10647
|
editTrigger = "click",
|
|
8690
|
-
editRequest
|
|
10648
|
+
editRequest,
|
|
10649
|
+
editSeed
|
|
8691
10650
|
}) {
|
|
8692
|
-
const [open, setOpen] = (0,
|
|
8693
|
-
(0,
|
|
10651
|
+
const [open, setOpen] = (0, import_react19.useState)(false);
|
|
10652
|
+
const [refusal, setRefusal] = (0, import_react19.useState)(null);
|
|
10653
|
+
(0, import_react19.useEffect)(() => {
|
|
8694
10654
|
if (editRequest !== void 0) setOpen(true);
|
|
8695
10655
|
}, [editRequest]);
|
|
10656
|
+
(0, import_react19.useEffect)(() => {
|
|
10657
|
+
if (!open) setRefusal(null);
|
|
10658
|
+
}, [open]);
|
|
8696
10659
|
const usePencil = Boolean(href) || editTrigger === "pencil";
|
|
8697
10660
|
if (editType === "string") {
|
|
8698
10661
|
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
@@ -8705,7 +10668,8 @@ function EditableTableCell({
|
|
|
8705
10668
|
...className === void 0 ? {} : { className },
|
|
8706
10669
|
...href === void 0 ? {} : { href },
|
|
8707
10670
|
usePencil,
|
|
8708
|
-
...editRequest === void 0 ? {} : { editRequest }
|
|
10671
|
+
...editRequest === void 0 ? {} : { editRequest },
|
|
10672
|
+
...editSeed === void 0 || editSeed === null ? {} : { editSeed }
|
|
8709
10673
|
}
|
|
8710
10674
|
);
|
|
8711
10675
|
}
|
|
@@ -8750,25 +10714,33 @@ function EditableTableCell({
|
|
|
8750
10714
|
) }) }),
|
|
8751
10715
|
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(TooltipContent, { children: "Edit value" })
|
|
8752
10716
|
] }),
|
|
8753
|
-
/* @__PURE__ */ (0, import_jsx_runtime39.
|
|
10717
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
|
|
8754
10718
|
PopoverContent,
|
|
8755
10719
|
{
|
|
8756
10720
|
align: "start",
|
|
8757
10721
|
className: "w-56 p-2",
|
|
8758
10722
|
onClick: (e) => e.stopPropagation(),
|
|
8759
|
-
children:
|
|
8760
|
-
|
|
8761
|
-
|
|
8762
|
-
|
|
8763
|
-
|
|
8764
|
-
|
|
8765
|
-
|
|
8766
|
-
onCommit(next)
|
|
8767
|
-
|
|
8768
|
-
|
|
8769
|
-
|
|
8770
|
-
|
|
8771
|
-
|
|
10723
|
+
children: [
|
|
10724
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
10725
|
+
TypedEditor,
|
|
10726
|
+
{
|
|
10727
|
+
editType,
|
|
10728
|
+
value,
|
|
10729
|
+
editOptions,
|
|
10730
|
+
onCommit: (next) => {
|
|
10731
|
+
const refused = onCommit(next);
|
|
10732
|
+
if (typeof refused === "string" && refused) {
|
|
10733
|
+
setRefusal(refused);
|
|
10734
|
+
return;
|
|
10735
|
+
}
|
|
10736
|
+
setRefusal(null);
|
|
10737
|
+
setOpen(false);
|
|
10738
|
+
},
|
|
10739
|
+
onCancel: () => setOpen(false)
|
|
10740
|
+
}
|
|
10741
|
+
),
|
|
10742
|
+
refusal ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(CellRefusal, { reason: refusal }) : null
|
|
10743
|
+
]
|
|
8772
10744
|
}
|
|
8773
10745
|
)
|
|
8774
10746
|
] });
|
|
@@ -8781,17 +10753,31 @@ function InlineStringEditor({
|
|
|
8781
10753
|
className,
|
|
8782
10754
|
href,
|
|
8783
10755
|
usePencil,
|
|
8784
|
-
editRequest
|
|
10756
|
+
editRequest,
|
|
10757
|
+
editSeed
|
|
8785
10758
|
}) {
|
|
8786
|
-
const [editing, setEditing] = (0,
|
|
8787
|
-
const [draft, setDraft] = (0,
|
|
8788
|
-
const
|
|
8789
|
-
(0,
|
|
10759
|
+
const [editing, setEditing] = (0, import_react19.useState)(false);
|
|
10760
|
+
const [draft, setDraft] = (0, import_react19.useState)(value);
|
|
10761
|
+
const [refusal, setRefusal] = (0, import_react19.useState)(null);
|
|
10762
|
+
const handledEditRequest = (0, import_react19.useRef)(void 0);
|
|
10763
|
+
const seedRef = (0, import_react19.useRef)(editSeed);
|
|
10764
|
+
seedRef.current = editSeed;
|
|
10765
|
+
(0, import_react19.useEffect)(() => {
|
|
8790
10766
|
if (editRequest === void 0 || handledEditRequest.current === editRequest) return;
|
|
8791
10767
|
handledEditRequest.current = editRequest;
|
|
8792
|
-
setDraft(value);
|
|
10768
|
+
setDraft(seedRef.current ?? value);
|
|
10769
|
+
setRefusal(null);
|
|
8793
10770
|
setEditing(true);
|
|
8794
10771
|
}, [editRequest, value]);
|
|
10772
|
+
const commit = (next) => {
|
|
10773
|
+
const refused = onCommit(next);
|
|
10774
|
+
if (typeof refused === "string" && refused) {
|
|
10775
|
+
setRefusal(refused);
|
|
10776
|
+
return false;
|
|
10777
|
+
}
|
|
10778
|
+
setRefusal(null);
|
|
10779
|
+
return true;
|
|
10780
|
+
};
|
|
8795
10781
|
if (!editing) {
|
|
8796
10782
|
if (usePencil) {
|
|
8797
10783
|
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
@@ -8842,32 +10828,38 @@ function InlineStringEditor({
|
|
|
8842
10828
|
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(TooltipContent, { children: "Click to edit" })
|
|
8843
10829
|
] });
|
|
8844
10830
|
}
|
|
8845
|
-
return /* @__PURE__ */ (0, import_jsx_runtime39.
|
|
8846
|
-
|
|
8847
|
-
|
|
8848
|
-
|
|
8849
|
-
|
|
8850
|
-
|
|
8851
|
-
|
|
8852
|
-
|
|
8853
|
-
|
|
8854
|
-
|
|
8855
|
-
|
|
8856
|
-
|
|
8857
|
-
|
|
8858
|
-
|
|
8859
|
-
|
|
8860
|
-
|
|
8861
|
-
|
|
8862
|
-
|
|
8863
|
-
|
|
8864
|
-
|
|
8865
|
-
|
|
8866
|
-
|
|
8867
|
-
|
|
8868
|
-
|
|
8869
|
-
|
|
8870
|
-
|
|
10831
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "block w-full", children: [
|
|
10832
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
10833
|
+
Input,
|
|
10834
|
+
{
|
|
10835
|
+
autoFocus: true,
|
|
10836
|
+
value: draft,
|
|
10837
|
+
onClick: (e) => e.stopPropagation(),
|
|
10838
|
+
onChange: (e) => {
|
|
10839
|
+
setDraft(e.target.value);
|
|
10840
|
+
if (refusal) setRefusal(null);
|
|
10841
|
+
},
|
|
10842
|
+
onBlur: () => {
|
|
10843
|
+
if (commit(draft)) setEditing(false);
|
|
10844
|
+
},
|
|
10845
|
+
onKeyDown: (e) => {
|
|
10846
|
+
if (e.key === "Enter") {
|
|
10847
|
+
e.preventDefault();
|
|
10848
|
+
if (commit(draft)) setEditing(false);
|
|
10849
|
+
}
|
|
10850
|
+
if (e.key === "Escape") {
|
|
10851
|
+
e.preventDefault();
|
|
10852
|
+
setRefusal(null);
|
|
10853
|
+
setEditing(false);
|
|
10854
|
+
}
|
|
10855
|
+
},
|
|
10856
|
+
"aria-invalid": refusal ? true : void 0,
|
|
10857
|
+
className: cn("h-7 text-sm", refusal && "border-amber-500 focus-visible:ring-amber-500"),
|
|
10858
|
+
style: { fontSize: "16px" }
|
|
10859
|
+
}
|
|
10860
|
+
),
|
|
10861
|
+
refusal ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(CellRefusal, { reason: refusal }) : null
|
|
10862
|
+
] });
|
|
8871
10863
|
}
|
|
8872
10864
|
function TypedEditor({
|
|
8873
10865
|
editType,
|
|
@@ -8942,8 +10934,8 @@ function TagsEditor({
|
|
|
8942
10934
|
onCommit,
|
|
8943
10935
|
onCancel
|
|
8944
10936
|
}) {
|
|
8945
|
-
const [tags, setTags] = (0,
|
|
8946
|
-
const [draft, setDraft] = (0,
|
|
10937
|
+
const [tags, setTags] = (0, import_react19.useState)(value);
|
|
10938
|
+
const [draft, setDraft] = (0, import_react19.useState)("");
|
|
8947
10939
|
const add = (raw) => {
|
|
8948
10940
|
const next = raw.trim();
|
|
8949
10941
|
if (!next || tags.includes(next)) return;
|
|
@@ -9040,7 +11032,7 @@ function NumberEditor({
|
|
|
9040
11032
|
onCommit,
|
|
9041
11033
|
onCancel
|
|
9042
11034
|
}) {
|
|
9043
|
-
const [draft, setDraft] = (0,
|
|
11035
|
+
const [draft, setDraft] = (0, import_react19.useState)(String(value));
|
|
9044
11036
|
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
9045
11037
|
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
9046
11038
|
Input,
|
|
@@ -9052,8 +11044,8 @@ function NumberEditor({
|
|
|
9052
11044
|
style: { fontSize: "16px" },
|
|
9053
11045
|
onKeyDown: (e) => {
|
|
9054
11046
|
if (e.key === "Enter") {
|
|
9055
|
-
const
|
|
9056
|
-
if (Number.isFinite(
|
|
11047
|
+
const n2 = Number(draft);
|
|
11048
|
+
if (Number.isFinite(n2)) onCommit(n2);
|
|
9057
11049
|
}
|
|
9058
11050
|
if (e.key === "Escape") onCancel();
|
|
9059
11051
|
}
|
|
@@ -9080,8 +11072,8 @@ function NumberEditor({
|
|
|
9080
11072
|
className: "h-7",
|
|
9081
11073
|
"aria-label": "Apply value",
|
|
9082
11074
|
onClick: () => {
|
|
9083
|
-
const
|
|
9084
|
-
if (Number.isFinite(
|
|
11075
|
+
const n2 = Number(draft);
|
|
11076
|
+
if (Number.isFinite(n2)) onCommit(n2);
|
|
9085
11077
|
},
|
|
9086
11078
|
children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Check, { className: "h-3.5 w-3.5" })
|
|
9087
11079
|
}
|
|
@@ -9170,7 +11162,7 @@ function resetToolbarFacets(facets) {
|
|
|
9170
11162
|
}
|
|
9171
11163
|
|
|
9172
11164
|
// src/data-table/LayeredFilterBuilder.tsx
|
|
9173
|
-
var
|
|
11165
|
+
var import_react20 = require("react");
|
|
9174
11166
|
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
9175
11167
|
function moveRule(rules, from, to) {
|
|
9176
11168
|
if (from === to || to < 0 || to >= rules.length) return [...rules];
|
|
@@ -9187,8 +11179,8 @@ function LayeredFilterBuilder({
|
|
|
9187
11179
|
maxRules = 20,
|
|
9188
11180
|
label = "Advanced filters"
|
|
9189
11181
|
}) {
|
|
9190
|
-
const [open, setOpen] = (0,
|
|
9191
|
-
const [draggedIndex, setDraggedIndex] = (0,
|
|
11182
|
+
const [open, setOpen] = (0, import_react20.useState)(false);
|
|
11183
|
+
const [draggedIndex, setDraggedIndex] = (0, import_react20.useState)(null);
|
|
9192
11184
|
if (fields.length === 0) return null;
|
|
9193
11185
|
const updateRule = (index, patch) => {
|
|
9194
11186
|
onChange(
|
|
@@ -9669,7 +11661,7 @@ function TableToolbarAction({
|
|
|
9669
11661
|
"aria-busy": busy || void 0,
|
|
9670
11662
|
disabled,
|
|
9671
11663
|
onClick,
|
|
9672
|
-
children: (0,
|
|
11664
|
+
children: (0, import_react21.isValidElement)(children) ? (0, import_react21.cloneElement)(children, { className: cn("h-5 w-5", children.props.className) }) : children
|
|
9673
11665
|
}
|
|
9674
11666
|
) }) }),
|
|
9675
11667
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(TooltipContent, { children: tooltip ?? ariaLabel })
|
|
@@ -9732,7 +11724,7 @@ function MatrxDataTableWithUrlState({
|
|
|
9732
11724
|
...urlState.history === void 0 ? {} : { history: urlState.history },
|
|
9733
11725
|
...urlState.textHistory === void 0 ? {} : { textHistory: urlState.textHistory }
|
|
9734
11726
|
});
|
|
9735
|
-
(0,
|
|
11727
|
+
(0, import_react21.useEffect)(() => {
|
|
9736
11728
|
if (activeUrlTableIds.has(urlState.id)) {
|
|
9737
11729
|
throw new Error(
|
|
9738
11730
|
`Duplicate MatrxDataTable urlState.id "${urlState.id}" on one page. Give every table a unique stable id.`
|
|
@@ -9823,6 +11815,11 @@ function opensRowHref(event) {
|
|
|
9823
11815
|
function TableContextPassthrough({ children }) {
|
|
9824
11816
|
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_jsx_runtime42.Fragment, { children });
|
|
9825
11817
|
}
|
|
11818
|
+
function sameWindow(a, b) {
|
|
11819
|
+
if (a === null || b === null) return a === b;
|
|
11820
|
+
return a.start === b.start && a.end === b.end && a.padStart === b.padStart && a.padEnd === b.padEnd && a.total === b.total && a.pinned.length === b.pinned.length;
|
|
11821
|
+
}
|
|
11822
|
+
var NO_GROUPING_VALUE = "__matrx_no_grouping__";
|
|
9826
11823
|
function MatrxDataTableCore({
|
|
9827
11824
|
data: suppliedData,
|
|
9828
11825
|
columns,
|
|
@@ -9879,11 +11876,17 @@ function MatrxDataTableCore({
|
|
|
9879
11876
|
mobileCardsBreakpoint = "sm",
|
|
9880
11877
|
getRowHref,
|
|
9881
11878
|
onRowOpen,
|
|
9882
|
-
density
|
|
11879
|
+
density,
|
|
11880
|
+
grouping,
|
|
11881
|
+
virtualize,
|
|
11882
|
+
coverage,
|
|
11883
|
+
spreadsheet,
|
|
11884
|
+
facets,
|
|
11885
|
+
rowHeight: explicitRowHeight
|
|
9883
11886
|
}) {
|
|
9884
11887
|
const appendQuery = query?.mode === "controlled-append" ? query : null;
|
|
9885
11888
|
const appendQueryKey = appendQuery?.pagination.queryKey ?? null;
|
|
9886
|
-
const committedAppendQueryKey = (0,
|
|
11889
|
+
const committedAppendQueryKey = (0, import_react21.useRef)(appendQueryKey);
|
|
9887
11890
|
const appendSourceChanged = appendQuery !== null && committedAppendQueryKey.current !== appendQueryKey;
|
|
9888
11891
|
const data = (appendQuery ? appendQuery.pagination.rows : suppliedData) ?? [];
|
|
9889
11892
|
const isLoading = appendQuery ? appendQuery.pagination.loading : suppliedLoading;
|
|
@@ -9895,10 +11898,10 @@ function MatrxDataTableCore({
|
|
|
9895
11898
|
const Link = host.Link ?? DefaultTableLink;
|
|
9896
11899
|
const SidePanelSurface = host.SidePanelSurface ?? DefaultTableSidePanel;
|
|
9897
11900
|
const { notify: toast, notice } = useTableNotice();
|
|
9898
|
-
const [savedViewError, setSavedViewError] = (0,
|
|
9899
|
-
const [toolbarActionError, setToolbarActionError] = (0,
|
|
9900
|
-
const [toolbarActionPending, setToolbarActionPending] = (0,
|
|
9901
|
-
const toolbarActionPendingRef = (0,
|
|
11901
|
+
const [savedViewError, setSavedViewError] = (0, import_react21.useState)(null);
|
|
11902
|
+
const [toolbarActionError, setToolbarActionError] = (0, import_react21.useState)(null);
|
|
11903
|
+
const [toolbarActionPending, setToolbarActionPending] = (0, import_react21.useState)({ refresh: false, add: false });
|
|
11904
|
+
const toolbarActionPendingRef = (0, import_react21.useRef)({ refresh: false, add: false });
|
|
9902
11905
|
const CHECKBOX_TAP_AREA = "h-4 w-4 touch-manipulation";
|
|
9903
11906
|
const mobileCardsClass = mobileCardsBreakpoint === "lg" ? "lg:hidden" : "sm:hidden";
|
|
9904
11907
|
const tableWithCardsClass = mobileCardsBreakpoint === "lg" ? "max-lg:hidden" : "max-sm:hidden";
|
|
@@ -9911,7 +11914,7 @@ function MatrxDataTableCore({
|
|
|
9911
11914
|
const sourceOwnsIntelligentSearch = sourceProcessing?.intelligentSearch === "source";
|
|
9912
11915
|
const sourceOwnsSearch = remoteQuery?.mode === "controlled" || appendQuery !== null && sourceProcessing === void 0 || sourceProcessing?.search === "source" || sourceOwnsIntelligentSearch;
|
|
9913
11916
|
const intelligentSearchEnabled = toolbar?.intelligentSearch !== void 0 && (sourceOwnsIntelligentSearch || remoteQuery === null && !sourceOwnsSearch);
|
|
9914
|
-
const emitControlledQueryChange = (0,
|
|
11917
|
+
const emitControlledQueryChange = (0, import_react21.useCallback)(
|
|
9915
11918
|
(patch, options) => {
|
|
9916
11919
|
if (!controlledQuery) return;
|
|
9917
11920
|
controlledQuery.onStateChange(
|
|
@@ -9920,8 +11923,8 @@ function MatrxDataTableCore({
|
|
|
9920
11923
|
},
|
|
9921
11924
|
[controlledQuery]
|
|
9922
11925
|
);
|
|
9923
|
-
const [internalSearch, setInternalSearch] = (0,
|
|
9924
|
-
const [draggedRowId, setDraggedRowId] = (0,
|
|
11926
|
+
const [internalSearch, setInternalSearch] = (0, import_react21.useState)("");
|
|
11927
|
+
const [draggedRowId, setDraggedRowId] = (0, import_react21.useState)(null);
|
|
9925
11928
|
const hierarchySensors = (0, import_core3.useSensors)(
|
|
9926
11929
|
(0, import_core3.useSensor)(import_core3.PointerSensor, {
|
|
9927
11930
|
activationConstraint: { distance: COLUMN_REORDER_ACTIVATION_DISTANCE }
|
|
@@ -9937,7 +11940,7 @@ function MatrxDataTableCore({
|
|
|
9937
11940
|
}
|
|
9938
11941
|
toolbar?.onSearchChange?.(v);
|
|
9939
11942
|
};
|
|
9940
|
-
const [internalSearchMatchMode, setInternalSearchMatchMode] = (0,
|
|
11943
|
+
const [internalSearchMatchMode, setInternalSearchMatchMode] = (0, import_react21.useState)(
|
|
9941
11944
|
toolbar?.searchMatch?.defaultMode ?? "contains"
|
|
9942
11945
|
);
|
|
9943
11946
|
const searchMatchMode = controlledQuery ? controlledQuery.state.searchMatchMode ?? toolbar?.searchMatch?.defaultMode ?? "contains" : internalSearchMatchMode;
|
|
@@ -9948,7 +11951,7 @@ function MatrxDataTableCore({
|
|
|
9948
11951
|
}
|
|
9949
11952
|
setInternalSearchMatchMode(mode);
|
|
9950
11953
|
};
|
|
9951
|
-
const [internalSearchScope, setInternalSearchScope] = (0,
|
|
11954
|
+
const [internalSearchScope, setInternalSearchScope] = (0, import_react21.useState)("all");
|
|
9952
11955
|
const searchScope = controlledQuery ? controlledQuery.state.searchScope ?? "all" : internalSearchScope;
|
|
9953
11956
|
const setSearchScope = (scope) => {
|
|
9954
11957
|
if (controlledQuery) {
|
|
@@ -9957,7 +11960,7 @@ function MatrxDataTableCore({
|
|
|
9957
11960
|
}
|
|
9958
11961
|
setInternalSearchScope(scope);
|
|
9959
11962
|
};
|
|
9960
|
-
const [internalAnyOf, setInternalAnyOf] = (0,
|
|
11963
|
+
const [internalAnyOf, setInternalAnyOf] = (0, import_react21.useState)("");
|
|
9961
11964
|
const toolbarAnyOfControlled = toolbar?.anyOf?.value !== void 0;
|
|
9962
11965
|
const anyOfValue = controlledQuery ? controlledQuery.state.anyOf : toolbarAnyOfControlled ? toolbar?.anyOf?.value ?? "" : internalAnyOf;
|
|
9963
11966
|
const setAnyOfValue = (v) => {
|
|
@@ -9968,7 +11971,7 @@ function MatrxDataTableCore({
|
|
|
9968
11971
|
}
|
|
9969
11972
|
toolbar?.anyOf?.onChange?.(v);
|
|
9970
11973
|
};
|
|
9971
|
-
const [internalLayeredFilters, setInternalLayeredFilters] = (0,
|
|
11974
|
+
const [internalLayeredFilters, setInternalLayeredFilters] = (0, import_react21.useState)([]);
|
|
9972
11975
|
const layeredFilters = controlledQuery ? controlledQuery.state.layeredFilters ?? [] : internalLayeredFilters;
|
|
9973
11976
|
const setLayeredFilters = (next) => {
|
|
9974
11977
|
if (controlledQuery) {
|
|
@@ -9977,7 +11980,7 @@ function MatrxDataTableCore({
|
|
|
9977
11980
|
}
|
|
9978
11981
|
setInternalLayeredFilters(next);
|
|
9979
11982
|
};
|
|
9980
|
-
const [internalColumnFilters, setInternalColumnFilters] = (0,
|
|
11983
|
+
const [internalColumnFilters, setInternalColumnFilters] = (0, import_react21.useState)({});
|
|
9981
11984
|
const columnFilters = controlledQuery ? controlledQuery.state.columnFilters : internalColumnFilters;
|
|
9982
11985
|
const setColumnFilter = (id, next) => {
|
|
9983
11986
|
const nextFilters = { ...columnFilters, [id]: next };
|
|
@@ -9990,7 +11993,7 @@ function MatrxDataTableCore({
|
|
|
9990
11993
|
}
|
|
9991
11994
|
setInternalColumnFilters(nextFilters);
|
|
9992
11995
|
};
|
|
9993
|
-
const [internalSort, setInternalSort] = (0,
|
|
11996
|
+
const [internalSort, setInternalSort] = (0, import_react21.useState)(defaultSort);
|
|
9994
11997
|
const sort = controlledQuery ? controlledQuery.state.sort : internalSort;
|
|
9995
11998
|
const setSort = (next) => {
|
|
9996
11999
|
if (controlledQuery) {
|
|
@@ -9999,7 +12002,7 @@ function MatrxDataTableCore({
|
|
|
9999
12002
|
}
|
|
10000
12003
|
setInternalSort(next);
|
|
10001
12004
|
};
|
|
10002
|
-
const [internalPage, setInternalPage] = (0,
|
|
12005
|
+
const [internalPage, setInternalPage] = (0, import_react21.useState)(1);
|
|
10003
12006
|
const page = controlledQuery ? controlledQuery.state.page : internalPage;
|
|
10004
12007
|
const setPage = (next) => {
|
|
10005
12008
|
if (controlledQuery) {
|
|
@@ -10008,7 +12011,7 @@ function MatrxDataTableCore({
|
|
|
10008
12011
|
}
|
|
10009
12012
|
setInternalPage(next);
|
|
10010
12013
|
};
|
|
10011
|
-
const [internalPageSize, setInternalPageSize] = (0,
|
|
12014
|
+
const [internalPageSize, setInternalPageSize] = (0, import_react21.useState)(
|
|
10012
12015
|
defaultPageSize
|
|
10013
12016
|
);
|
|
10014
12017
|
const pageSize = controlledQuery ? controlledQuery.state.pageSize : internalPageSize;
|
|
@@ -10019,28 +12022,28 @@ function MatrxDataTableCore({
|
|
|
10019
12022
|
}
|
|
10020
12023
|
setInternalPageSize(next);
|
|
10021
12024
|
};
|
|
10022
|
-
const [uncontrolledSelectedId, setUncontrolledSelectedId] = (0,
|
|
12025
|
+
const [uncontrolledSelectedId, setUncontrolledSelectedId] = (0, import_react21.useState)(null);
|
|
10023
12026
|
const rawSelectedId = controlledSelectedId !== void 0 ? controlledSelectedId : uncontrolledSelectedId;
|
|
10024
12027
|
const selectedId = appendSourceChanged ? null : rawSelectedId;
|
|
10025
12028
|
const setSelectedId = (id) => {
|
|
10026
12029
|
if (controlledSelectedId === void 0) setUncontrolledSelectedId(id);
|
|
10027
12030
|
onSelectedIdChange?.(id);
|
|
10028
12031
|
};
|
|
10029
|
-
const [uncontrolledWindowRowId, setUncontrolledWindowRowId] = (0,
|
|
12032
|
+
const [uncontrolledWindowRowId, setUncontrolledWindowRowId] = (0, import_react21.useState)(null);
|
|
10030
12033
|
const rawWindowRowId = controlledWindowRowId !== void 0 ? controlledWindowRowId : uncontrolledWindowRowId;
|
|
10031
12034
|
const windowRowId = appendSourceChanged ? null : rawWindowRowId;
|
|
10032
12035
|
const setWindowRowId = (id) => {
|
|
10033
12036
|
if (controlledWindowRowId === void 0) setUncontrolledWindowRowId(id);
|
|
10034
12037
|
onWindowRowIdChange?.(id);
|
|
10035
12038
|
};
|
|
10036
|
-
const [windowRowSnapshot, setWindowRowSnapshot] = (0,
|
|
12039
|
+
const [windowRowSnapshot, setWindowRowSnapshot] = (0, import_react21.useState)(null);
|
|
10037
12040
|
const editScopeKey = appendQueryKey === null ? "\0local" : `append:${appendQueryKey}`;
|
|
10038
|
-
const [editsByScope, setEditsByScope] = (0,
|
|
10039
|
-
const editRevisionRef = (0,
|
|
10040
|
-
const [savingByScope, setSavingByScope] = (0,
|
|
10041
|
-
const savingScopesRef = (0,
|
|
10042
|
-
const [editRequest, setEditRequest] = (0,
|
|
10043
|
-
const [confirmForeignDraftDiscard, setConfirmForeignDraftDiscard] = (0,
|
|
12041
|
+
const [editsByScope, setEditsByScope] = (0, import_react21.useState)({});
|
|
12042
|
+
const editRevisionRef = (0, import_react21.useRef)({});
|
|
12043
|
+
const [savingByScope, setSavingByScope] = (0, import_react21.useState)({});
|
|
12044
|
+
const savingScopesRef = (0, import_react21.useRef)(/* @__PURE__ */ new Set());
|
|
12045
|
+
const [editRequest, setEditRequest] = (0, import_react21.useState)(null);
|
|
12046
|
+
const [confirmForeignDraftDiscard, setConfirmForeignDraftDiscard] = (0, import_react21.useState)(false);
|
|
10044
12047
|
const edits = editsByScope[editScopeKey]?.values ?? {};
|
|
10045
12048
|
const saving = (savingByScope[editScopeKey] ?? 0) > 0;
|
|
10046
12049
|
const setEdits = (next) => {
|
|
@@ -10107,7 +12110,7 @@ function MatrxDataTableCore({
|
|
|
10107
12110
|
rows: Object.entries(draft.values).map(([rowId, columns2]) => ({ rowId, columns: columns2 }))
|
|
10108
12111
|
}));
|
|
10109
12112
|
const selection = appendSourceChanged && selectionConfig ? { ...selectionConfig, selectedIds: [] } : selectionConfig;
|
|
10110
|
-
(0,
|
|
12113
|
+
(0, import_react21.useEffect)(() => {
|
|
10111
12114
|
const previous = committedAppendQueryKey.current;
|
|
10112
12115
|
committedAppendQueryKey.current = appendQueryKey;
|
|
10113
12116
|
if (previous === null || appendQueryKey === null || previous === appendQueryKey) {
|
|
@@ -10125,14 +12128,14 @@ function MatrxDataTableCore({
|
|
|
10125
12128
|
onWindowRowIdChange,
|
|
10126
12129
|
selectionConfig
|
|
10127
12130
|
]);
|
|
10128
|
-
const scrollRef = (0,
|
|
10129
|
-
const tableRef = (0,
|
|
10130
|
-
const tableHeaderRef = (0,
|
|
10131
|
-
const cardsScrollRef = (0,
|
|
10132
|
-
const [documentStickyHeader, setDocumentStickyHeader] = (0,
|
|
10133
|
-
const documentStickyHeaderRef = (0,
|
|
10134
|
-
const previousAppendKeyForScrollReset = (0,
|
|
10135
|
-
(0,
|
|
12131
|
+
const scrollRef = (0, import_react21.useRef)(null);
|
|
12132
|
+
const tableRef = (0, import_react21.useRef)(null);
|
|
12133
|
+
const tableHeaderRef = (0, import_react21.useRef)(null);
|
|
12134
|
+
const cardsScrollRef = (0, import_react21.useRef)(null);
|
|
12135
|
+
const [documentStickyHeader, setDocumentStickyHeader] = (0, import_react21.useState)(false);
|
|
12136
|
+
const documentStickyHeaderRef = (0, import_react21.useRef)(false);
|
|
12137
|
+
const previousAppendKeyForScrollReset = (0, import_react21.useRef)(appendQueryKey);
|
|
12138
|
+
(0, import_react21.useLayoutEffect)(() => {
|
|
10136
12139
|
const previous = previousAppendKeyForScrollReset.current;
|
|
10137
12140
|
previousAppendKeyForScrollReset.current = appendQueryKey;
|
|
10138
12141
|
if (previous === null || appendQueryKey === null || previous === appendQueryKey) {
|
|
@@ -10157,13 +12160,13 @@ function MatrxDataTableCore({
|
|
|
10157
12160
|
...appendScrollPolicy?.mode === "scroll" && appendScrollPolicy.thresholdPx !== void 0 ? { thresholdPx: appendScrollPolicy.thresholdPx } : {},
|
|
10158
12161
|
...appendScrollPolicy?.mode === "scroll" && appendScrollPolicy.intentTimeoutMs !== void 0 ? { intentTimeoutMs: appendScrollPolicy.intentTimeoutMs } : {}
|
|
10159
12162
|
});
|
|
10160
|
-
const rootRef = (0,
|
|
12163
|
+
const rootRef = (0, import_react21.useRef)(null);
|
|
10161
12164
|
useClippedContentGuard(rootRef, {
|
|
10162
12165
|
label: typeof copy === "object" && copy.listLabel ? `Table: ${copy.listLabel}` : "MatrxDataTable"
|
|
10163
12166
|
});
|
|
10164
|
-
const [scrollHintRight, setScrollHintRight] = (0,
|
|
10165
|
-
const [scrollHintLeft, setScrollHintLeft] = (0,
|
|
10166
|
-
const updateScrollHint = (0,
|
|
12167
|
+
const [scrollHintRight, setScrollHintRight] = (0, import_react21.useState)(false);
|
|
12168
|
+
const [scrollHintLeft, setScrollHintLeft] = (0, import_react21.useState)(false);
|
|
12169
|
+
const updateScrollHint = (0, import_react21.useCallback)(() => {
|
|
10167
12170
|
const el = scrollRef.current;
|
|
10168
12171
|
if (!el) return;
|
|
10169
12172
|
setScrollHintRight(el.scrollLeft + el.clientWidth < el.scrollWidth - 2);
|
|
@@ -10177,7 +12180,7 @@ function MatrxDataTableCore({
|
|
|
10177
12180
|
behavior: "smooth"
|
|
10178
12181
|
});
|
|
10179
12182
|
};
|
|
10180
|
-
(0,
|
|
12183
|
+
(0, import_react21.useEffect)(() => {
|
|
10181
12184
|
updateScrollHint();
|
|
10182
12185
|
window.addEventListener("resize", updateScrollHint);
|
|
10183
12186
|
const el = scrollRef.current;
|
|
@@ -10192,7 +12195,7 @@ function MatrxDataTableCore({
|
|
|
10192
12195
|
observer?.disconnect();
|
|
10193
12196
|
};
|
|
10194
12197
|
}, [updateScrollHint, data, columns]);
|
|
10195
|
-
(0,
|
|
12198
|
+
(0, import_react21.useLayoutEffect)(() => {
|
|
10196
12199
|
const scroll = scrollRef.current;
|
|
10197
12200
|
const table = tableRef.current;
|
|
10198
12201
|
const header = tableHeaderRef.current;
|
|
@@ -10251,30 +12254,30 @@ function MatrxDataTableCore({
|
|
|
10251
12254
|
window.removeEventListener("resize", requestUpdate);
|
|
10252
12255
|
};
|
|
10253
12256
|
}, [stickyHeader, data, columns]);
|
|
10254
|
-
const [columnOrder, setColumnOrder] = (0,
|
|
10255
|
-
const [hiddenColumnIds, setHiddenColumnIds] = (0,
|
|
12257
|
+
const [columnOrder, setColumnOrder] = (0, import_react21.useState)(() => columnState?.order ?? columns.map(columnId));
|
|
12258
|
+
const [hiddenColumnIds, setHiddenColumnIds] = (0, import_react21.useState)(
|
|
10256
12259
|
() => new Set(columnState?.hidden ?? columns.filter((column) => column.hidden).map(columnId))
|
|
10257
12260
|
);
|
|
10258
|
-
const [columnWidths, setColumnWidths] = (0,
|
|
12261
|
+
const [columnWidths, setColumnWidths] = (0, import_react21.useState)(
|
|
10259
12262
|
() => normalizeColumnWidthsForColumns(columnState?.widths, columns)
|
|
10260
12263
|
);
|
|
10261
|
-
const [fixedTableGeometry, setFixedTableGeometry] = (0,
|
|
10262
|
-
const knownColumnIds = (0,
|
|
10263
|
-
const draggedColumnId = (0,
|
|
10264
|
-
const columnDragActive = (0,
|
|
10265
|
-
const columnDragRaf = (0,
|
|
10266
|
-
const columnDragScrollDirection = (0,
|
|
10267
|
-
const [columnDragPreview, setColumnDragPreview] = (0,
|
|
10268
|
-
const stopColumnDragScroll = (0,
|
|
12264
|
+
const [fixedTableGeometry, setFixedTableGeometry] = (0, import_react21.useState)(null);
|
|
12265
|
+
const knownColumnIds = (0, import_react21.useRef)(new Set(columns.map(columnId)));
|
|
12266
|
+
const draggedColumnId = (0, import_react21.useRef)(null);
|
|
12267
|
+
const columnDragActive = (0, import_react21.useRef)(false);
|
|
12268
|
+
const columnDragRaf = (0, import_react21.useRef)(null);
|
|
12269
|
+
const columnDragScrollDirection = (0, import_react21.useRef)(0);
|
|
12270
|
+
const [columnDragPreview, setColumnDragPreview] = (0, import_react21.useState)(null);
|
|
12271
|
+
const stopColumnDragScroll = (0, import_react21.useCallback)(() => {
|
|
10269
12272
|
if (columnDragRaf.current !== null) cancelAnimationFrame(columnDragRaf.current);
|
|
10270
12273
|
columnDragRaf.current = null;
|
|
10271
12274
|
columnDragScrollDirection.current = 0;
|
|
10272
12275
|
}, []);
|
|
10273
|
-
(0,
|
|
12276
|
+
(0, import_react21.useEffect)(() => () => {
|
|
10274
12277
|
columnDragActive.current = false;
|
|
10275
12278
|
stopColumnDragScroll();
|
|
10276
12279
|
}, [stopColumnDragScroll]);
|
|
10277
|
-
const startColumnDragScroll = (0,
|
|
12280
|
+
const startColumnDragScroll = (0, import_react21.useCallback)(() => {
|
|
10278
12281
|
if (!columnDragActive.current || columnDragRaf.current !== null) return;
|
|
10279
12282
|
const scrollStep = () => {
|
|
10280
12283
|
const scroll = scrollRef.current;
|
|
@@ -10301,25 +12304,25 @@ function MatrxDataTableCore({
|
|
|
10301
12304
|
};
|
|
10302
12305
|
columnDragRaf.current = requestAnimationFrame(scrollStep);
|
|
10303
12306
|
}, []);
|
|
10304
|
-
const commitColumnState = (0,
|
|
12307
|
+
const commitColumnState = (0, import_react21.useCallback)((order, hidden) => {
|
|
10305
12308
|
if (columnState) columnState.onChange({ order, hidden: [...hidden] });
|
|
10306
12309
|
else {
|
|
10307
12310
|
setColumnOrder(order);
|
|
10308
12311
|
setHiddenColumnIds(hidden);
|
|
10309
12312
|
}
|
|
10310
12313
|
}, [columnState]);
|
|
10311
|
-
const [internalColumnManagerOpen, setInternalColumnManagerOpen] = (0,
|
|
12314
|
+
const [internalColumnManagerOpen, setInternalColumnManagerOpen] = (0, import_react21.useState)(false);
|
|
10312
12315
|
const columnManagerOpen = controlledColumnManager?.open ?? internalColumnManagerOpen;
|
|
10313
12316
|
const setColumnManagerOpen = controlledColumnManager?.onOpenChange ?? setInternalColumnManagerOpen;
|
|
10314
|
-
const columnIds = (0,
|
|
10315
|
-
const effectiveColumnOrder = (0,
|
|
10316
|
-
const effectiveHiddenColumnIds = (0,
|
|
10317
|
-
const effectiveColumnWidths = (0,
|
|
12317
|
+
const columnIds = (0, import_react21.useMemo)(() => columns.map(columnId), [columns]);
|
|
12318
|
+
const effectiveColumnOrder = (0, import_react21.useMemo)(() => columnState ? [...columnState.order.filter((id, index, values) => columnIds.includes(id) && values.indexOf(id) === index), ...columnIds.filter((id) => !columnState.order.includes(id))] : columnOrder, [columnIds, columnOrder, columnState]);
|
|
12319
|
+
const effectiveHiddenColumnIds = (0, import_react21.useMemo)(() => columnState ? new Set(columnState.hidden.filter((id) => columnIds.includes(id))) : hiddenColumnIds, [columnIds, columnState, hiddenColumnIds]);
|
|
12320
|
+
const effectiveColumnWidths = (0, import_react21.useMemo)(
|
|
10318
12321
|
() => normalizeColumnWidthsForColumns(columnState?.widths ?? columnWidths, columns),
|
|
10319
12322
|
[columns, columnState?.widths, columnWidths]
|
|
10320
12323
|
);
|
|
10321
|
-
const resizeGestureSnapshotRef = (0,
|
|
10322
|
-
const measureVisibleColumnWidths = (0,
|
|
12324
|
+
const resizeGestureSnapshotRef = (0, import_react21.useRef)(null);
|
|
12325
|
+
const measureVisibleColumnWidths = (0, import_react21.useCallback)(() => {
|
|
10323
12326
|
const measured = {};
|
|
10324
12327
|
const headers = tableRef.current ? Array.from(tableRef.current.querySelectorAll(
|
|
10325
12328
|
"thead th[data-matrx-table-column-id]"
|
|
@@ -10333,7 +12336,7 @@ function MatrxDataTableCore({
|
|
|
10333
12336
|
}
|
|
10334
12337
|
return normalizeColumnWidthsForColumns(measured, columns);
|
|
10335
12338
|
}, [columns]);
|
|
10336
|
-
const measureFixedTableGeometry = (0,
|
|
12339
|
+
const measureFixedTableGeometry = (0, import_react21.useCallback)(() => {
|
|
10337
12340
|
const table = tableRef.current;
|
|
10338
12341
|
const headers = table ? Array.from(table.querySelectorAll("thead th")) : [];
|
|
10339
12342
|
const widthFor = (selector) => {
|
|
@@ -10368,16 +12371,16 @@ function MatrxDataTableCore({
|
|
|
10368
12371
|
...actionsWidth === void 0 ? {} : { actionsWidth }
|
|
10369
12372
|
};
|
|
10370
12373
|
}, [resolvedDensity]);
|
|
10371
|
-
const captureResizeGestureSnapshot = (0,
|
|
12374
|
+
const captureResizeGestureSnapshot = (0, import_react21.useCallback)(() => {
|
|
10372
12375
|
resizeGestureSnapshotRef.current = {
|
|
10373
12376
|
widths: measureVisibleColumnWidths(),
|
|
10374
12377
|
geometry: measureFixedTableGeometry()
|
|
10375
12378
|
};
|
|
10376
12379
|
}, [measureFixedTableGeometry, measureVisibleColumnWidths]);
|
|
10377
|
-
const clearResizeGestureSnapshot = (0,
|
|
12380
|
+
const clearResizeGestureSnapshot = (0, import_react21.useCallback)(() => {
|
|
10378
12381
|
resizeGestureSnapshotRef.current = null;
|
|
10379
12382
|
}, []);
|
|
10380
|
-
const commitColumnWidths = (0,
|
|
12383
|
+
const commitColumnWidths = (0, import_react21.useCallback)((next, captureInitialWidths = false) => {
|
|
10381
12384
|
const gestureSnapshot = captureInitialWidths ? resizeGestureSnapshotRef.current : null;
|
|
10382
12385
|
resizeGestureSnapshotRef.current = null;
|
|
10383
12386
|
const normalized = normalizeColumnWidthsForColumns(
|
|
@@ -10396,7 +12399,7 @@ function MatrxDataTableCore({
|
|
|
10396
12399
|
}
|
|
10397
12400
|
setColumnWidths(normalized);
|
|
10398
12401
|
}, [columnIds, columnState, columns, measureFixedTableGeometry, measureVisibleColumnWidths]);
|
|
10399
|
-
(0,
|
|
12402
|
+
(0, import_react21.useEffect)(() => {
|
|
10400
12403
|
const ids = columns.map(columnId);
|
|
10401
12404
|
if (columnState) return;
|
|
10402
12405
|
const previousIds = knownColumnIds.current;
|
|
@@ -10415,31 +12418,31 @@ function MatrxDataTableCore({
|
|
|
10415
12418
|
setColumnWidths((current) => normalizeColumnWidthsForColumns(current, columns));
|
|
10416
12419
|
knownColumnIds.current = new Set(ids);
|
|
10417
12420
|
}, [columns, columnState]);
|
|
10418
|
-
(0,
|
|
12421
|
+
(0, import_react21.useLayoutEffect)(() => {
|
|
10419
12422
|
for (const id of columnIds) {
|
|
10420
12423
|
tableRef.current?.style.removeProperty(columnResizeCssVar(id));
|
|
10421
12424
|
}
|
|
10422
12425
|
});
|
|
10423
|
-
const previewColumnOrder = (0,
|
|
12426
|
+
const previewColumnOrder = (0, import_react21.useMemo)(
|
|
10424
12427
|
() => projectColumnDragOrder(effectiveColumnOrder, columnDragPreview),
|
|
10425
12428
|
[columnDragPreview, effectiveColumnOrder]
|
|
10426
12429
|
);
|
|
10427
12430
|
useColumnReorderAnimation(tableRef, previewColumnOrder.join("\0"), columnDragPreview !== null);
|
|
10428
|
-
const visibleColumns = (0,
|
|
12431
|
+
const visibleColumns = (0, import_react21.useMemo)(() => {
|
|
10429
12432
|
const byId = new Map(columns.map((column) => [columnId(column), column]));
|
|
10430
12433
|
return previewColumnOrder.map((id) => byId.get(id)).filter(
|
|
10431
12434
|
(column) => column !== void 0 && !effectiveHiddenColumnIds.has(columnId(column))
|
|
10432
12435
|
);
|
|
10433
12436
|
}, [columns, effectiveHiddenColumnIds, previewColumnOrder]);
|
|
10434
12437
|
const usesMeasuredFixedLayout = visibleColumns.length > 0 && visibleColumns.every((column) => effectiveColumnWidths[columnId(column)] !== void 0);
|
|
10435
|
-
(0,
|
|
12438
|
+
(0, import_react21.useLayoutEffect)(() => {
|
|
10436
12439
|
if (!usesMeasuredFixedLayout) {
|
|
10437
12440
|
if (fixedTableGeometry !== null) setFixedTableGeometry(null);
|
|
10438
12441
|
return;
|
|
10439
12442
|
}
|
|
10440
12443
|
if (fixedTableGeometry === null) setFixedTableGeometry(measureFixedTableGeometry());
|
|
10441
12444
|
}, [fixedTableGeometry, measureFixedTableGeometry, usesMeasuredFixedLayout]);
|
|
10442
|
-
(0,
|
|
12445
|
+
(0, import_react21.useLayoutEffect)(() => {
|
|
10443
12446
|
if (!usesMeasuredFixedLayout) return;
|
|
10444
12447
|
const table = tableRef.current;
|
|
10445
12448
|
if (!table) return;
|
|
@@ -10461,7 +12464,7 @@ function MatrxDataTableCore({
|
|
|
10461
12464
|
setFixedTableGeometry(geometry);
|
|
10462
12465
|
}, [resolvedDensity, measureFixedTableGeometry, usesMeasuredFixedLayout]);
|
|
10463
12466
|
const fixedLayoutActive = usesMeasuredFixedLayout && fixedTableGeometry !== null;
|
|
10464
|
-
const frozenColumns = (0,
|
|
12467
|
+
const frozenColumns = (0, import_react21.useMemo)(() => {
|
|
10465
12468
|
if (!visibleColumns.some((column) => column.frozen)) return NO_FROZEN_COLUMNS;
|
|
10466
12469
|
const ids = visibleColumns.map(columnId);
|
|
10467
12470
|
const byId = new Map(visibleColumns.map((column) => [columnId(column), column]));
|
|
@@ -10503,15 +12506,15 @@ function MatrxDataTableCore({
|
|
|
10503
12506
|
);
|
|
10504
12507
|
return color ? CELL_TINT_CLASS[color] : void 0;
|
|
10505
12508
|
};
|
|
10506
|
-
const declaredVisibleCopyColumns = (0,
|
|
12509
|
+
const declaredVisibleCopyColumns = (0, import_react21.useMemo)(
|
|
10507
12510
|
() => visibleColumns.filter((column) => column.accessorFn !== void 0 || column.accessorKey !== void 0),
|
|
10508
12511
|
[visibleColumns]
|
|
10509
12512
|
);
|
|
10510
|
-
const tableCopySourceNamespace = (0,
|
|
10511
|
-
const tableContextMenuInstanceId = (0,
|
|
10512
|
-
const tableDndContextId = (0,
|
|
12513
|
+
const tableCopySourceNamespace = (0, import_react21.useId)();
|
|
12514
|
+
const tableContextMenuInstanceId = (0, import_react21.useId)();
|
|
12515
|
+
const tableDndContextId = (0, import_react21.useId)();
|
|
10513
12516
|
const defaultCopyTitle = toolbar?.title || "Table";
|
|
10514
|
-
const defaultCopy = (0,
|
|
12517
|
+
const defaultCopy = (0, import_react21.useMemo)(() => ({
|
|
10515
12518
|
label: defaultCopyTitle,
|
|
10516
12519
|
listLabel: defaultCopyTitle,
|
|
10517
12520
|
location: defaultCopyTitle,
|
|
@@ -10546,7 +12549,7 @@ function MatrxDataTableCore({
|
|
|
10546
12549
|
serializer: (shaped) => buildViewAgentInput(effectiveCopy, shaped, data, { scope: "custom" })
|
|
10547
12550
|
}))
|
|
10548
12551
|
] : [];
|
|
10549
|
-
const filterMeta = (0,
|
|
12552
|
+
const filterMeta = (0, import_react21.useMemo)(() => {
|
|
10550
12553
|
const meta = /* @__PURE__ */ new Map();
|
|
10551
12554
|
for (const col of visibleColumns) {
|
|
10552
12555
|
const id = columnId(col);
|
|
@@ -10554,14 +12557,14 @@ function MatrxDataTableCore({
|
|
|
10554
12557
|
}
|
|
10555
12558
|
return meta;
|
|
10556
12559
|
}, [visibleColumns, data, remoteQuery]);
|
|
10557
|
-
const intelligentSearchScopes = (0,
|
|
12560
|
+
const intelligentSearchScopes = (0, import_react21.useMemo)(
|
|
10558
12561
|
() => resolveTableSearchScopes(data, columns, {
|
|
10559
12562
|
...toolbar?.intelligentSearch?.roles === void 0 ? {} : { roles: toolbar.intelligentSearch.roles },
|
|
10560
12563
|
...toolbar?.intelligentSearch?.scopes === void 0 ? {} : { scopes: toolbar.intelligentSearch.scopes }
|
|
10561
12564
|
}),
|
|
10562
12565
|
[columns, data, toolbar?.intelligentSearch?.roles, toolbar?.intelligentSearch?.scopes]
|
|
10563
12566
|
);
|
|
10564
|
-
const processed = (0,
|
|
12567
|
+
const processed = (0, import_react21.useMemo)(() => {
|
|
10565
12568
|
if (remoteQuery && !appendUsesLocalProcessing) return data;
|
|
10566
12569
|
if (processLocalRows) {
|
|
10567
12570
|
return processLocalRows(data, {
|
|
@@ -10624,8 +12627,8 @@ function MatrxDataTableCore({
|
|
|
10624
12627
|
intelligentSearchEnabled,
|
|
10625
12628
|
searchScope
|
|
10626
12629
|
]);
|
|
10627
|
-
const lastNotifiedViewRows = (0,
|
|
10628
|
-
(0,
|
|
12630
|
+
const lastNotifiedViewRows = (0, import_react21.useRef)(null);
|
|
12631
|
+
(0, import_react21.useEffect)(() => {
|
|
10629
12632
|
if (!onViewChange) {
|
|
10630
12633
|
lastNotifiedViewRows.current = null;
|
|
10631
12634
|
return;
|
|
@@ -10634,7 +12637,7 @@ function MatrxDataTableCore({
|
|
|
10634
12637
|
lastNotifiedViewRows.current = processed;
|
|
10635
12638
|
if (changed) onViewChange(processed);
|
|
10636
12639
|
}, [processed, onViewChange]);
|
|
10637
|
-
(0,
|
|
12640
|
+
(0, import_react21.useEffect)(() => {
|
|
10638
12641
|
if (controlledQuery) return;
|
|
10639
12642
|
setInternalPage(1);
|
|
10640
12643
|
}, [
|
|
@@ -10678,7 +12681,7 @@ function MatrxDataTableCore({
|
|
|
10678
12681
|
numberedPageHasMore: !hidePagination && !isLoading && !isFetching && processed.length > 0 && safePage < pageCount && (remoteQuery?.mode === "controlled" || !remoteQuery && localPagination?.mode === "numbered"),
|
|
10679
12682
|
onPageAdvance: setPage
|
|
10680
12683
|
});
|
|
10681
|
-
const paginated = (0,
|
|
12684
|
+
const paginated = (0, import_react21.useMemo)(() => {
|
|
10682
12685
|
if (remoteQuery) return processed;
|
|
10683
12686
|
if (hidePagination) return processed;
|
|
10684
12687
|
if (localProgressiveEnabled) return [...progressiveRows.rows];
|
|
@@ -10686,15 +12689,351 @@ function MatrxDataTableCore({
|
|
|
10686
12689
|
const start = (safePage - 1) * effectivePageSize;
|
|
10687
12690
|
return processed.slice(start, start + effectivePageSize);
|
|
10688
12691
|
}, [processed, safePage, effectivePageSize, pageSize, remoteQuery, hidePagination, localProgressiveEnabled, progressiveRows.rows]);
|
|
10689
|
-
|
|
12692
|
+
const groupingColumnId = grouping?.columnId ?? null;
|
|
12693
|
+
const [uncontrolledCollapsed, setUncontrolledCollapsed] = (0, import_react21.useState)([]);
|
|
12694
|
+
const collapsedGroups = grouping?.collapsed ?? uncontrolledCollapsed;
|
|
12695
|
+
const setCollapsedGroups = (0, import_react21.useCallback)(
|
|
12696
|
+
(next) => {
|
|
12697
|
+
if (grouping?.onCollapsedChange) grouping.onCollapsedChange(next);
|
|
12698
|
+
else setUncontrolledCollapsed(next);
|
|
12699
|
+
},
|
|
12700
|
+
[grouping]
|
|
12701
|
+
);
|
|
12702
|
+
const groups = (0, import_react21.useMemo)(() => {
|
|
12703
|
+
if (!grouping || !groupingColumnId) return null;
|
|
12704
|
+
const groupColumn = columns.find((col) => columnId(col) === groupingColumnId);
|
|
12705
|
+
if (!groupColumn) return null;
|
|
12706
|
+
const aggregateColumns = {};
|
|
12707
|
+
for (const [aggColumnId, spec] of Object.entries(grouping.aggregates ?? {})) {
|
|
12708
|
+
const col = columns.find((c) => columnId(c) === aggColumnId);
|
|
12709
|
+
if (!col) continue;
|
|
12710
|
+
aggregateColumns[aggColumnId] = { spec, readCell: (row) => getCellValue(row, col) };
|
|
12711
|
+
}
|
|
12712
|
+
return groupRows({
|
|
12713
|
+
rows: paginated,
|
|
12714
|
+
columnId: groupingColumnId,
|
|
12715
|
+
readCell: (row) => grouping.readCell ? grouping.readCell(row, groupingColumnId) : getCellValue(row, groupColumn),
|
|
12716
|
+
aggregates: aggregateColumns,
|
|
12717
|
+
...grouping.order ? { order: grouping.order } : {},
|
|
12718
|
+
...grouping.emptyLabel ? { emptyLabel: grouping.emptyLabel } : {}
|
|
12719
|
+
});
|
|
12720
|
+
}, [grouping, groupingColumnId, columns, paginated]);
|
|
12721
|
+
const groupableColumns = (0, import_react21.useMemo)(() => {
|
|
12722
|
+
const allowed = grouping?.groupableColumnIds;
|
|
12723
|
+
return visibleColumns.filter((col) => {
|
|
12724
|
+
const id = columnId(col);
|
|
12725
|
+
if (allowed) return allowed.includes(id);
|
|
12726
|
+
return col.accessorKey !== void 0 || col.accessorFn !== void 0;
|
|
12727
|
+
});
|
|
12728
|
+
}, [visibleColumns, grouping?.groupableColumnIds]);
|
|
12729
|
+
const groupedRenderRows = (0, import_react21.useMemo)(
|
|
12730
|
+
() => groups ? flattenGroups(groups, collapsedGroups) : null,
|
|
12731
|
+
[groups, collapsedGroups]
|
|
12732
|
+
);
|
|
12733
|
+
const virtualizeConfig = virtualize === void 0 || virtualize === false ? null : virtualize === true ? {} : virtualize;
|
|
12734
|
+
const virtualRowHeight = explicitRowHeight ?? virtualizeConfig?.rowHeight ?? (resolvedDensity === "condensed" ? 32 : resolvedDensity === "spacious" ? 52 : 40);
|
|
12735
|
+
const virtualThreshold = virtualizeConfig?.threshold ?? 150;
|
|
12736
|
+
const bodyEntryCount = groupedRenderRows ? groupedRenderRows.length : paginated.length;
|
|
12737
|
+
const virtualizeActive = virtualizeConfig !== null && virtualizeConfig.enabled !== false && bodyEntryCount > virtualThreshold && !hierarchy && expandedDetail === void 0;
|
|
12738
|
+
const columnWindowWidth = virtualizeConfig?.columnWidth ?? 160;
|
|
12739
|
+
const frozenRunLength = (0, import_react21.useMemo)(() => {
|
|
12740
|
+
let run = 0;
|
|
12741
|
+
for (const col of visibleColumns) {
|
|
12742
|
+
if (frozenColumns.offsets[columnId(col)] === void 0) break;
|
|
12743
|
+
run += 1;
|
|
12744
|
+
}
|
|
12745
|
+
return run;
|
|
12746
|
+
}, [visibleColumns, frozenColumns]);
|
|
12747
|
+
const columnVirtualizeActive = virtualizeConfig !== null && virtualizeConfig.enabled !== false && virtualizeConfig.columns === true && visibleColumns.length - frozenRunLength > 30 && !hierarchy && mobileCards === void 0;
|
|
12748
|
+
const [rowWindow, setRowWindow] = (0, import_react21.useState)(null);
|
|
12749
|
+
const [columnWindow, setColumnWindow] = (0, import_react21.useState)(null);
|
|
12750
|
+
const windowInputs = (0, import_react21.useRef)({
|
|
12751
|
+
virtualizeActive: false,
|
|
12752
|
+
bodyEntryCount: 0,
|
|
12753
|
+
virtualRowHeight: 40,
|
|
12754
|
+
overscan: 8,
|
|
12755
|
+
columnVirtualizeActive: false,
|
|
12756
|
+
columnCount: 0,
|
|
12757
|
+
columnWindowWidth: 160,
|
|
12758
|
+
frozenRunLength: 0
|
|
12759
|
+
});
|
|
12760
|
+
windowInputs.current = {
|
|
12761
|
+
virtualizeActive,
|
|
12762
|
+
bodyEntryCount,
|
|
12763
|
+
virtualRowHeight,
|
|
12764
|
+
overscan: virtualizeConfig?.overscan ?? 8,
|
|
12765
|
+
columnVirtualizeActive,
|
|
12766
|
+
columnCount: visibleColumns.length,
|
|
12767
|
+
columnWindowWidth,
|
|
12768
|
+
frozenRunLength
|
|
12769
|
+
};
|
|
12770
|
+
const recomputeWindows = (0, import_react21.useCallback)(() => {
|
|
12771
|
+
const el = scrollRef.current;
|
|
12772
|
+
const input = windowInputs.current;
|
|
12773
|
+
const nextRow = input.virtualizeActive ? computeWindow({
|
|
12774
|
+
count: input.bodyEntryCount,
|
|
12775
|
+
itemSize: input.virtualRowHeight,
|
|
12776
|
+
viewport: el?.clientHeight || 600,
|
|
12777
|
+
offset: el?.scrollTop ?? 0,
|
|
12778
|
+
overscan: input.overscan
|
|
12779
|
+
}) : null;
|
|
12780
|
+
const nextColumn = input.columnVirtualizeActive ? computeWindow({
|
|
12781
|
+
count: input.columnCount,
|
|
12782
|
+
itemSize: input.columnWindowWidth,
|
|
12783
|
+
viewport: el?.clientWidth || 1200,
|
|
12784
|
+
offset: el?.scrollLeft ?? 0,
|
|
12785
|
+
overscan: Math.max(2, Math.round(input.overscan / 2)),
|
|
12786
|
+
pinnedStart: input.frozenRunLength
|
|
12787
|
+
}) : null;
|
|
12788
|
+
setRowWindow((prev) => sameWindow(prev, nextRow) ? prev : nextRow);
|
|
12789
|
+
setColumnWindow((prev) => sameWindow(prev, nextColumn) ? prev : nextColumn);
|
|
12790
|
+
}, []);
|
|
12791
|
+
const effectiveRowWindow = (0, import_react21.useMemo)(() => {
|
|
12792
|
+
if (!virtualizeActive) return null;
|
|
12793
|
+
if (rowWindow && rowWindow.end <= bodyEntryCount) return rowWindow;
|
|
12794
|
+
return computeWindow({
|
|
12795
|
+
count: bodyEntryCount,
|
|
12796
|
+
itemSize: virtualRowHeight,
|
|
12797
|
+
viewport: scrollRef.current?.clientHeight || 600,
|
|
12798
|
+
offset: scrollRef.current?.scrollTop ?? 0,
|
|
12799
|
+
overscan: virtualizeConfig?.overscan ?? 8
|
|
12800
|
+
});
|
|
12801
|
+
}, [virtualizeActive, rowWindow, bodyEntryCount, virtualRowHeight, virtualizeConfig?.overscan]);
|
|
12802
|
+
const effectiveColumnWindow = (0, import_react21.useMemo)(() => {
|
|
12803
|
+
if (!columnVirtualizeActive) return null;
|
|
12804
|
+
if (columnWindow && columnWindow.end <= visibleColumns.length) return columnWindow;
|
|
12805
|
+
return computeWindow({
|
|
12806
|
+
count: visibleColumns.length,
|
|
12807
|
+
itemSize: columnWindowWidth,
|
|
12808
|
+
viewport: scrollRef.current?.clientWidth || 1200,
|
|
12809
|
+
offset: scrollRef.current?.scrollLeft ?? 0,
|
|
12810
|
+
overscan: Math.max(2, Math.round((virtualizeConfig?.overscan ?? 8) / 2)),
|
|
12811
|
+
pinnedStart: frozenRunLength
|
|
12812
|
+
});
|
|
12813
|
+
}, [
|
|
12814
|
+
columnVirtualizeActive,
|
|
12815
|
+
columnWindow,
|
|
12816
|
+
visibleColumns.length,
|
|
12817
|
+
columnWindowWidth,
|
|
12818
|
+
virtualizeConfig?.overscan,
|
|
12819
|
+
frozenRunLength
|
|
12820
|
+
]);
|
|
12821
|
+
const metricsWanted = virtualizeActive || columnVirtualizeActive;
|
|
12822
|
+
(0, import_react21.useEffect)(() => {
|
|
12823
|
+
recomputeWindows();
|
|
12824
|
+
}, [
|
|
12825
|
+
recomputeWindows,
|
|
12826
|
+
virtualizeActive,
|
|
12827
|
+
bodyEntryCount,
|
|
12828
|
+
virtualRowHeight,
|
|
12829
|
+
columnVirtualizeActive,
|
|
12830
|
+
visibleColumns.length,
|
|
12831
|
+
columnWindowWidth,
|
|
12832
|
+
frozenRunLength
|
|
12833
|
+
]);
|
|
12834
|
+
(0, import_react21.useEffect)(() => {
|
|
12835
|
+
if (!metricsWanted) return;
|
|
12836
|
+
const el = scrollRef.current;
|
|
12837
|
+
if (!el) return;
|
|
12838
|
+
let frame = 0;
|
|
12839
|
+
const onScroll = () => {
|
|
12840
|
+
if (frame) return;
|
|
12841
|
+
frame = requestAnimationFrame(() => {
|
|
12842
|
+
frame = 0;
|
|
12843
|
+
recomputeWindows();
|
|
12844
|
+
});
|
|
12845
|
+
};
|
|
12846
|
+
el.addEventListener("scroll", onScroll, { passive: true });
|
|
12847
|
+
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(onScroll);
|
|
12848
|
+
observer?.observe(el);
|
|
12849
|
+
return () => {
|
|
12850
|
+
if (frame) cancelAnimationFrame(frame);
|
|
12851
|
+
el.removeEventListener("scroll", onScroll);
|
|
12852
|
+
observer?.disconnect();
|
|
12853
|
+
};
|
|
12854
|
+
}, [metricsWanted, recomputeWindows]);
|
|
12855
|
+
const renderedColumns = (0, import_react21.useMemo)(
|
|
12856
|
+
() => effectiveColumnWindow ? [
|
|
12857
|
+
...visibleColumns.slice(0, frozenRunLength),
|
|
12858
|
+
...visibleColumns.slice(effectiveColumnWindow.start, effectiveColumnWindow.end)
|
|
12859
|
+
] : visibleColumns,
|
|
12860
|
+
[effectiveColumnWindow, visibleColumns, frozenRunLength]
|
|
12861
|
+
);
|
|
12862
|
+
const columnSpacers = effectiveColumnWindow ? { start: effectiveColumnWindow.padStart, end: effectiveColumnWindow.padEnd } : null;
|
|
12863
|
+
const windowedWidthFor = (0, import_react21.useCallback)(
|
|
12864
|
+
(id, declared) => {
|
|
12865
|
+
const resized = effectiveColumnWidths[id];
|
|
12866
|
+
if (!effectiveColumnWindow) return resized;
|
|
12867
|
+
if (frozenColumns.offsets[id] !== void 0) return resized;
|
|
12868
|
+
return resized ?? (typeof declared === "number" ? declared : columnWindowWidth);
|
|
12869
|
+
},
|
|
12870
|
+
[effectiveColumnWindow, effectiveColumnWidths, frozenColumns, columnWindowWidth]
|
|
12871
|
+
);
|
|
12872
|
+
const coverageResult = (0, import_react21.useMemo)(() => {
|
|
12873
|
+
if (!coverage) return null;
|
|
12874
|
+
return describeCoverage({
|
|
12875
|
+
loaded: processed.length,
|
|
12876
|
+
...coverage.matched === void 0 ? {} : { matched: coverage.matched },
|
|
12877
|
+
...coverage.total === void 0 ? {} : { total: coverage.total },
|
|
12878
|
+
...coverage.cap === void 0 ? {} : { cap: coverage.cap },
|
|
12879
|
+
answeredBy: coverage.answeredBy ?? "client",
|
|
12880
|
+
...coverage.noun === void 0 ? {} : { noun: coverage.noun }
|
|
12881
|
+
});
|
|
12882
|
+
}, [coverage, processed.length]);
|
|
12883
|
+
const bodyEntries = (0, import_react21.useMemo)(() => {
|
|
12884
|
+
const from = effectiveRowWindow ? effectiveRowWindow.start : 0;
|
|
12885
|
+
const to = effectiveRowWindow ? effectiveRowWindow.end : void 0;
|
|
12886
|
+
const windowed = groupedRenderRows ? groupedRenderRows.slice(from, to).map(
|
|
12887
|
+
(entry) => entry.kind === "group" ? {
|
|
12888
|
+
kind: "group",
|
|
12889
|
+
group: entry.group,
|
|
12890
|
+
collapsed: isGroupCollapsed(collapsedGroups, entry.group.key)
|
|
12891
|
+
} : { kind: "row", row: entry.row, index: entry.dataIndex ?? 0 }
|
|
12892
|
+
) : paginated.slice(from, to).map((row, offset) => ({ kind: "row", row, index: from + offset }));
|
|
12893
|
+
if (!effectiveRowWindow) return windowed;
|
|
12894
|
+
if (effectiveRowWindow.padStart > 0)
|
|
12895
|
+
windowed.unshift({ kind: "spacer", height: effectiveRowWindow.padStart, place: "start" });
|
|
12896
|
+
if (effectiveRowWindow.padEnd > 0)
|
|
12897
|
+
windowed.push({ kind: "spacer", height: effectiveRowWindow.padEnd, place: "end" });
|
|
12898
|
+
return windowed;
|
|
12899
|
+
}, [groupedRenderRows, collapsedGroups, paginated, effectiveRowWindow]);
|
|
12900
|
+
const getRowIdRef = (0, import_react21.useRef)(getRowId);
|
|
12901
|
+
getRowIdRef.current = getRowId;
|
|
12902
|
+
const spreadsheetRowIds = (0, import_react21.useMemo)(
|
|
12903
|
+
() => paginated.map((row) => getRowIdRef.current(row)),
|
|
12904
|
+
[paginated]
|
|
12905
|
+
);
|
|
12906
|
+
const spreadsheetColumnIds = (0, import_react21.useMemo)(
|
|
12907
|
+
() => visibleColumns.map((col) => columnId(col)),
|
|
12908
|
+
[visibleColumns]
|
|
12909
|
+
);
|
|
12910
|
+
const spreadsheetRowById = (0, import_react21.useMemo)(() => {
|
|
12911
|
+
const map = /* @__PURE__ */ new Map();
|
|
12912
|
+
for (const row of paginated) map.set(getRowIdRef.current(row), row);
|
|
12913
|
+
return map;
|
|
12914
|
+
}, [paginated]);
|
|
12915
|
+
const spreadsheetColumnById = (0, import_react21.useMemo)(() => {
|
|
12916
|
+
const map = /* @__PURE__ */ new Map();
|
|
12917
|
+
for (const col of visibleColumns) map.set(columnId(col), col);
|
|
12918
|
+
return map;
|
|
12919
|
+
}, [visibleColumns]);
|
|
12920
|
+
const spreadsheetEnabled = Boolean(spreadsheet && spreadsheet.enabled !== false);
|
|
12921
|
+
const sheet = useSpreadsheetGrid(
|
|
12922
|
+
spreadsheetEnabled && spreadsheet ? {
|
|
12923
|
+
rowIds: spreadsheetRowIds,
|
|
12924
|
+
columnIds: spreadsheetColumnIds,
|
|
12925
|
+
valueAt: (rowId, colId) => {
|
|
12926
|
+
const row = spreadsheetRowById.get(rowId);
|
|
12927
|
+
const col = spreadsheetColumnById.get(colId);
|
|
12928
|
+
if (row === void 0 || col === void 0) return null;
|
|
12929
|
+
if (spreadsheet.readCell) return spreadsheet.readCell(row, colId);
|
|
12930
|
+
return getCellValue(applyRowEdits(row, edits[rowId]), col);
|
|
12931
|
+
},
|
|
12932
|
+
isColumnWritable: (colId) => {
|
|
12933
|
+
if (spreadsheet.writableColumnIds) return spreadsheet.writableColumnIds.includes(colId);
|
|
12934
|
+
const col = spreadsheetColumnById.get(colId);
|
|
12935
|
+
return Boolean(col && col.editable);
|
|
12936
|
+
},
|
|
12937
|
+
...spreadsheet.columnRefusal ? { columnRefusal: spreadsheet.columnRefusal } : {},
|
|
12938
|
+
onPatch: spreadsheet.onPatch,
|
|
12939
|
+
...spreadsheet.undoDepth === void 0 ? {} : { undoDepth: spreadsheet.undoDepth },
|
|
12940
|
+
...spreadsheet.fillHandle === void 0 ? {} : { fillHandle: spreadsheet.fillHandle },
|
|
12941
|
+
...spreadsheet.paste === void 0 ? {} : { paste: spreadsheet.paste },
|
|
12942
|
+
notify: spreadsheet.notify ?? ((message) => toast.success(message)),
|
|
12943
|
+
onEditRequest: (address, seed) => requestCellEditRef.current(address, seed),
|
|
12944
|
+
...spreadsheet.validateCell ? { validateCell: spreadsheet.validateCell } : {}
|
|
12945
|
+
} : null
|
|
12946
|
+
);
|
|
12947
|
+
const sheetRef = (0, import_react21.useRef)(sheet);
|
|
12948
|
+
sheetRef.current = sheet;
|
|
12949
|
+
const searchValueRef = (0, import_react21.useRef)(searchValue);
|
|
12950
|
+
searchValueRef.current = searchValue;
|
|
12951
|
+
const facetsEnabled = Boolean(facets && facets.enabled !== false);
|
|
12952
|
+
const [facetState, setFacetState] = (0, import_react21.useState)({});
|
|
12953
|
+
const facetReadCell = (0, import_react21.useCallback)(
|
|
12954
|
+
(row, colId) => {
|
|
12955
|
+
if (facets?.readCell) return facets.readCell(row, colId);
|
|
12956
|
+
const col = visibleColumns.find((candidate) => columnId(candidate) === colId);
|
|
12957
|
+
return col ? getFilterValue(row, col) : void 0;
|
|
12958
|
+
},
|
|
12959
|
+
[facets, visibleColumns]
|
|
12960
|
+
);
|
|
12961
|
+
const facetInputsRef = (0, import_react21.useRef)({ data, facets, facetReadCell });
|
|
12962
|
+
facetInputsRef.current = { data, facets, facetReadCell };
|
|
12963
|
+
const facetRequestRef = (0, import_react21.useRef)(/* @__PURE__ */ new Map());
|
|
12964
|
+
const requestFacets = (0, import_react21.useCallback)((colId) => {
|
|
12965
|
+
const { data: rows, facets: config, facetReadCell: readCell } = facetInputsRef.current;
|
|
12966
|
+
if (!config || config.enabled === false) return;
|
|
12967
|
+
const complete = localFacetsAreComplete(rows.length, config.totalRows);
|
|
12968
|
+
const limit = config.limit;
|
|
12969
|
+
if (complete || !config.source) {
|
|
12970
|
+
setFacetState((current) => ({
|
|
12971
|
+
...current,
|
|
12972
|
+
[colId]: {
|
|
12973
|
+
loading: false,
|
|
12974
|
+
data: computeColumnFacets({
|
|
12975
|
+
columnId: colId,
|
|
12976
|
+
rows,
|
|
12977
|
+
readValue: readCell,
|
|
12978
|
+
...limit === void 0 ? {} : { limit },
|
|
12979
|
+
complete
|
|
12980
|
+
})
|
|
12981
|
+
}
|
|
12982
|
+
}));
|
|
12983
|
+
return;
|
|
12984
|
+
}
|
|
12985
|
+
const ticket = (facetRequestRef.current.get(colId) ?? 0) + 1;
|
|
12986
|
+
facetRequestRef.current.set(colId, ticket);
|
|
12987
|
+
setFacetState((current) => ({
|
|
12988
|
+
...current,
|
|
12989
|
+
[colId]: { loading: true, data: current[colId]?.data ?? null }
|
|
12990
|
+
}));
|
|
12991
|
+
void Promise.resolve().then(
|
|
12992
|
+
() => config.source?.({ columnId: colId, search: searchValueRef.current, limit: limit ?? 200 })
|
|
12993
|
+
).then((answer) => {
|
|
12994
|
+
if (facetRequestRef.current.get(colId) !== ticket) return;
|
|
12995
|
+
if (!answer) {
|
|
12996
|
+
setFacetState((current) => ({
|
|
12997
|
+
...current,
|
|
12998
|
+
[colId]: {
|
|
12999
|
+
loading: false,
|
|
13000
|
+
data: computeColumnFacets({
|
|
13001
|
+
columnId: colId,
|
|
13002
|
+
rows: facetInputsRef.current.data,
|
|
13003
|
+
readValue: facetInputsRef.current.facetReadCell,
|
|
13004
|
+
...limit === void 0 ? {} : { limit },
|
|
13005
|
+
complete: false
|
|
13006
|
+
})
|
|
13007
|
+
}
|
|
13008
|
+
}));
|
|
13009
|
+
return;
|
|
13010
|
+
}
|
|
13011
|
+
setFacetState((current) => ({
|
|
13012
|
+
...current,
|
|
13013
|
+
[colId]: { loading: false, data: { ...answer, answeredBy: "source", complete: true } }
|
|
13014
|
+
}));
|
|
13015
|
+
}).catch((error) => {
|
|
13016
|
+
if (facetRequestRef.current.get(colId) !== ticket) return;
|
|
13017
|
+
setFacetState((current) => ({
|
|
13018
|
+
...current,
|
|
13019
|
+
[colId]: { loading: false, data: null, error: describeFacetFailure(error) }
|
|
13020
|
+
}));
|
|
13021
|
+
});
|
|
13022
|
+
}, []);
|
|
13023
|
+
(0, import_react21.useEffect)(() => {
|
|
13024
|
+
if (!facetsEnabled) return;
|
|
13025
|
+
setFacetState({});
|
|
13026
|
+
facetRequestRef.current = /* @__PURE__ */ new Map();
|
|
13027
|
+
}, [facetsEnabled, data, searchValue]);
|
|
13028
|
+
(0, import_react21.useEffect)(() => {
|
|
10690
13029
|
if (!controlledQuery || controlledQuery.state.page === safePage) return;
|
|
10691
13030
|
emitControlledQueryChange({ page: safePage });
|
|
10692
13031
|
}, [controlledQuery, emitControlledQueryChange, safePage]);
|
|
10693
|
-
const selectedRow = (0,
|
|
13032
|
+
const selectedRow = (0, import_react21.useMemo)(() => {
|
|
10694
13033
|
if (!selectedId) return null;
|
|
10695
13034
|
return data.find((r) => getRowId(r) === selectedId) ?? null;
|
|
10696
13035
|
}, [data, selectedId, getRowId]);
|
|
10697
|
-
const windowRow = (0,
|
|
13036
|
+
const windowRow = (0, import_react21.useMemo)(() => {
|
|
10698
13037
|
if (!windowRowId) return null;
|
|
10699
13038
|
return data.find((r) => getRowId(r) === windowRowId) ?? (windowRowSnapshot && windowRowSnapshot.queryKey === appendQueryKey && getRowId(windowRowSnapshot.row) === windowRowId ? windowRowSnapshot.row : null);
|
|
10700
13039
|
}, [data, windowRowId, windowRowSnapshot, getRowId, appendQueryKey]);
|
|
@@ -10729,12 +13068,12 @@ function MatrxDataTableCore({
|
|
|
10729
13068
|
return def !== void 0 && f.value !== def;
|
|
10730
13069
|
});
|
|
10731
13070
|
const hasActiveFilters = activeFilterCount > 0 || Boolean(searchValue.trim()) || intelligentSearchEnabled && searchScope !== "all" || Boolean(anyOfValue.trim()) || completeLayeredFilterRules(layeredFilters).length > 0 || facetActive;
|
|
10732
|
-
const changeCount = (0,
|
|
10733
|
-
let
|
|
13071
|
+
const changeCount = (0, import_react21.useMemo)(() => {
|
|
13072
|
+
let n2 = 0;
|
|
10734
13073
|
for (const fields of Object.values(edits)) {
|
|
10735
|
-
|
|
13074
|
+
n2 += Object.keys(fields).length;
|
|
10736
13075
|
}
|
|
10737
|
-
return
|
|
13076
|
+
return n2;
|
|
10738
13077
|
}, [edits]);
|
|
10739
13078
|
const showSearch = toolbar?.search !== false;
|
|
10740
13079
|
const openDetail = (row) => {
|
|
@@ -10813,6 +13152,23 @@ function MatrxDataTableCore({
|
|
|
10813
13152
|
icon: void 0
|
|
10814
13153
|
} : emptyState;
|
|
10815
13154
|
const commitCell = (rowId, field, next) => {
|
|
13155
|
+
if (edit?.validate) {
|
|
13156
|
+
const row = data.find((candidate) => getRowId(candidate) === rowId);
|
|
13157
|
+
if (row) {
|
|
13158
|
+
let refusal;
|
|
13159
|
+
try {
|
|
13160
|
+
refusal = edit.validate({
|
|
13161
|
+
row: applyRowEdits(row, edits[rowId]),
|
|
13162
|
+
rowId,
|
|
13163
|
+
columnId: field,
|
|
13164
|
+
value: next
|
|
13165
|
+
});
|
|
13166
|
+
} catch {
|
|
13167
|
+
refusal = void 0;
|
|
13168
|
+
}
|
|
13169
|
+
if (refusal) return refusal;
|
|
13170
|
+
}
|
|
13171
|
+
}
|
|
10816
13172
|
const scope = editScopeKey;
|
|
10817
13173
|
const nextEdits = { [rowId]: { [field]: next } };
|
|
10818
13174
|
const revision = setCellEdit(rowId, field, next);
|
|
@@ -10857,9 +13213,29 @@ function MatrxDataTableCore({
|
|
|
10857
13213
|
setEditRequest((current) => ({
|
|
10858
13214
|
rowId: getRowId(row),
|
|
10859
13215
|
field,
|
|
10860
|
-
nonce: (current?.nonce ?? 0) + 1
|
|
13216
|
+
nonce: (current?.nonce ?? 0) + 1,
|
|
13217
|
+
seed: null
|
|
13218
|
+
}));
|
|
13219
|
+
};
|
|
13220
|
+
const requestCellEdit = (address, seed) => {
|
|
13221
|
+
if (!editEnabled) return false;
|
|
13222
|
+
const row = data.find((candidate) => getRowId(candidate) === address.rowId);
|
|
13223
|
+
if (!row) return false;
|
|
13224
|
+
const column = visibleColumns.find(
|
|
13225
|
+
(candidate) => columnId(candidate) === address.fieldName
|
|
13226
|
+
);
|
|
13227
|
+
if (!column?.editable || !(column.editableIf?.(row) ?? true)) return false;
|
|
13228
|
+
const field = column.accessorKey ? String(column.accessorKey) : columnId(column);
|
|
13229
|
+
setEditRequest((current) => ({
|
|
13230
|
+
rowId: address.rowId,
|
|
13231
|
+
field,
|
|
13232
|
+
nonce: (current?.nonce ?? 0) + 1,
|
|
13233
|
+
seed
|
|
10861
13234
|
}));
|
|
13235
|
+
return true;
|
|
10862
13236
|
};
|
|
13237
|
+
const requestCellEditRef = (0, import_react21.useRef)(requestCellEdit);
|
|
13238
|
+
requestCellEditRef.current = requestCellEdit;
|
|
10863
13239
|
const buildRecordControls = (row) => {
|
|
10864
13240
|
const rowId = getRowId(row);
|
|
10865
13241
|
const pending = edits[rowId];
|
|
@@ -10885,7 +13261,7 @@ function MatrxDataTableCore({
|
|
|
10885
13261
|
};
|
|
10886
13262
|
const hierarchyRows = hierarchy?.rows ?? data;
|
|
10887
13263
|
const hierarchyGetParentId = hierarchy?.getParentId;
|
|
10888
|
-
const hierarchyIndex = (0,
|
|
13264
|
+
const hierarchyIndex = (0, import_react21.useMemo)(() => {
|
|
10889
13265
|
if (!hierarchyGetParentId) return null;
|
|
10890
13266
|
const byId = /* @__PURE__ */ new Map();
|
|
10891
13267
|
const parentById = /* @__PURE__ */ new Map();
|
|
@@ -10917,7 +13293,7 @@ function MatrxDataTableCore({
|
|
|
10917
13293
|
return { byId, parentById, depthById };
|
|
10918
13294
|
}, [hierarchyGetParentId, hierarchyRows, getRowId]);
|
|
10919
13295
|
const draggedRow = draggedRowId && hierarchyIndex ? hierarchyIndex.byId.get(draggedRowId) : void 0;
|
|
10920
|
-
const hierarchyBlockedIds = (0,
|
|
13296
|
+
const hierarchyBlockedIds = (0, import_react21.useMemo)(() => {
|
|
10921
13297
|
if (!draggedRowId || !hierarchyIndex) return null;
|
|
10922
13298
|
const childrenById = /* @__PURE__ */ new Map();
|
|
10923
13299
|
for (const [id, parentId] of hierarchyIndex.parentById) {
|
|
@@ -11100,19 +13476,80 @@ function MatrxDataTableCore({
|
|
|
11100
13476
|
setEdits({});
|
|
11101
13477
|
edit?.onCancel?.();
|
|
11102
13478
|
};
|
|
11103
|
-
|
|
11104
|
-
|
|
11105
|
-
return host.rowContextRegistry.register(tableContextMenuInstanceId, (rowId) => {
|
|
13479
|
+
const resolveMenuLevel = (target) => {
|
|
13480
|
+
const rowFor = (rowId) => {
|
|
11106
13481
|
const row = data.find((candidate) => getRowId(candidate) === rowId);
|
|
11107
13482
|
if (!row) return null;
|
|
11108
|
-
|
|
11109
|
-
|
|
11110
|
-
|
|
11111
|
-
|
|
11112
|
-
|
|
11113
|
-
|
|
13483
|
+
return applyRowEdits(row, edits[rowId]);
|
|
13484
|
+
};
|
|
13485
|
+
const columnFor = (id) => visibleColumns.find((col) => columnId(col) === id);
|
|
13486
|
+
const labelFor = (col, id) => col?.label ?? (typeof col?.header === "string" ? col.header : id);
|
|
13487
|
+
const fromHost = (payload) => host.createDefaultMenuContext?.(payload) ?? null;
|
|
13488
|
+
switch (target.level) {
|
|
13489
|
+
case "row": {
|
|
13490
|
+
if (!target.rowId) return null;
|
|
13491
|
+
const displayRow = rowFor(target.rowId);
|
|
13492
|
+
if (!displayRow) return null;
|
|
13493
|
+
const controls = buildRecordControls(displayRow);
|
|
13494
|
+
return contextMenu?.resolveRowContext?.(displayRow, controls) ?? fromHost({ level: "row", row: displayRow, rowId: target.rowId, controls });
|
|
13495
|
+
}
|
|
13496
|
+
case "cell": {
|
|
13497
|
+
if (!target.rowId || !target.columnId) return null;
|
|
13498
|
+
const displayRow = rowFor(target.rowId);
|
|
13499
|
+
const col = columnFor(target.columnId);
|
|
13500
|
+
if (!displayRow || !col) return null;
|
|
13501
|
+
const controls = buildRecordControls(displayRow);
|
|
13502
|
+
const value = spreadsheet?.readCell ? spreadsheet.readCell(displayRow, target.columnId) : getCellValue(displayRow, col);
|
|
13503
|
+
const args = {
|
|
13504
|
+
row: displayRow,
|
|
13505
|
+
rowId: target.rowId,
|
|
13506
|
+
columnId: target.columnId,
|
|
13507
|
+
columnLabel: labelFor(col, target.columnId),
|
|
13508
|
+
value,
|
|
13509
|
+
text: stringifyCellValue(value),
|
|
13510
|
+
controls
|
|
13511
|
+
};
|
|
13512
|
+
return contextMenu?.resolveCellContext?.(args) ?? fromHost({ level: "cell", ...args });
|
|
13513
|
+
}
|
|
13514
|
+
case "column": {
|
|
13515
|
+
if (!target.columnId) return null;
|
|
13516
|
+
const col = columnFor(target.columnId);
|
|
13517
|
+
if (!col) return null;
|
|
13518
|
+
const args = {
|
|
13519
|
+
columnId: target.columnId,
|
|
13520
|
+
columnLabel: labelFor(col, target.columnId),
|
|
13521
|
+
values: paginated.map(
|
|
13522
|
+
(row) => getCellValue(applyRowEdits(row, edits[getRowId(row)]), col)
|
|
13523
|
+
)
|
|
13524
|
+
};
|
|
13525
|
+
return contextMenu?.resolveColumnContext?.(args) ?? fromHost({ level: "column", ...args });
|
|
13526
|
+
}
|
|
13527
|
+
case "selection": {
|
|
13528
|
+
const addresses = sheetRef.current.selectionAddresses();
|
|
13529
|
+
const cellCount = addresses.rowIds.length * addresses.columnIds.length;
|
|
13530
|
+
if (cellCount <= 1) {
|
|
13531
|
+
return resolveMenuLevel({ ...target, level: "cell" });
|
|
13532
|
+
}
|
|
13533
|
+
const args = { ...addresses, tsv: sheetRef.current.selectionTsv(), cellCount };
|
|
13534
|
+
return contextMenu?.resolveSelectionContext?.(args) ?? fromHost({ level: "selection", ...args });
|
|
13535
|
+
}
|
|
13536
|
+
case "table": {
|
|
13537
|
+
const args = { rowCount: data.length, columnIds: visibleColumns.map((col) => columnId(col)) };
|
|
13538
|
+
return contextMenu?.resolveTableContext?.(args) ?? fromHost({ level: "table", ...args });
|
|
13539
|
+
}
|
|
13540
|
+
}
|
|
13541
|
+
};
|
|
13542
|
+
const resolveMenuLevelRef = (0, import_react21.useRef)(resolveMenuLevel);
|
|
13543
|
+
resolveMenuLevelRef.current = resolveMenuLevel;
|
|
13544
|
+
(0, import_react21.useEffect)(() => {
|
|
13545
|
+
if (!host.rowContextRegistry) return;
|
|
13546
|
+
return host.rowContextRegistry.register(
|
|
13547
|
+
tableContextMenuInstanceId,
|
|
13548
|
+
(target) => resolveMenuLevelRef.current(target)
|
|
13549
|
+
);
|
|
13550
|
+
}, [host.rowContextRegistry, tableContextMenuInstanceId]);
|
|
11114
13551
|
const showActionsCol = windowEnabled || Boolean(rowActions) || showInlineRowCopy;
|
|
11115
|
-
const selectedIdSet = (0,
|
|
13552
|
+
const selectedIdSet = (0, import_react21.useMemo)(
|
|
11116
13553
|
() => new Set(selection?.selectedIds ?? []),
|
|
11117
13554
|
[selection?.selectedIds]
|
|
11118
13555
|
);
|
|
@@ -11124,11 +13561,11 @@ function MatrxDataTableCore({
|
|
|
11124
13561
|
);
|
|
11125
13562
|
const allOnPageSelected = selectableRows.length > 0 && selectedOnPage.length === selectableRows.length;
|
|
11126
13563
|
const someOnPageSelected = selectedOnPage.length > 0 && !allOnPageSelected;
|
|
11127
|
-
const selectedRows = (0,
|
|
13564
|
+
const selectedRows = (0, import_react21.useMemo)(
|
|
11128
13565
|
() => data.filter((row) => selectedIdSet.has(getRowId(row))),
|
|
11129
13566
|
[data, selectedIdSet, getRowId]
|
|
11130
13567
|
);
|
|
11131
|
-
const lastToggledIndex = (0,
|
|
13568
|
+
const lastToggledIndex = (0, import_react21.useRef)(null);
|
|
11132
13569
|
const setSelectedIds = (next) => selection?.onSelectedIdsChange([...next]);
|
|
11133
13570
|
const toggleRowSelected = (index, shiftKey) => {
|
|
11134
13571
|
if (!selection) return;
|
|
@@ -11165,6 +13602,7 @@ function MatrxDataTableCore({
|
|
|
11165
13602
|
const selectionNoun = selection?.noun ?? "row";
|
|
11166
13603
|
const selectionCount = selection?.selectedIds.length ?? 0;
|
|
11167
13604
|
const leadingCols = selection ? 1 : 0;
|
|
13605
|
+
const renderedColSpan = renderedColumns.length + leadingCols + (showActionsCol ? 1 : 0) + (columnSpacers ? (columnSpacers.start > 0 ? 1 : 0) + (columnSpacers.end > 0 ? 1 : 0) : 0);
|
|
11168
13606
|
const renderedFacets = controlledQuery ? toolbar?.facets?.map(
|
|
11169
13607
|
(facet) => facet.type === "button-group" ? {
|
|
11170
13608
|
...facet,
|
|
@@ -11191,14 +13629,25 @@ function MatrxDataTableCore({
|
|
|
11191
13629
|
dirty: Boolean(rowEdits && field in rowEdits),
|
|
11192
13630
|
onCommit: (next) => commitCell(id, field, next),
|
|
11193
13631
|
...href === void 0 ? {} : { href },
|
|
11194
|
-
...
|
|
11195
|
-
|
|
13632
|
+
...spreadsheetEnabled ? {
|
|
13633
|
+
// 🚨 THE CLICK LAW, enforced where the two paths meet. In a grid
|
|
13634
|
+
// with spreadsheet gestures a single click SELECTS a cell — it
|
|
13635
|
+
// may never drop a person into a free-text buffer, because the
|
|
13636
|
+
// same click is how they start a range, and an editor that opens
|
|
13637
|
+
// under the pointer eats the drag and the next keystroke. So the
|
|
13638
|
+
// editor opens the way it does in Excel: Enter, F2, the hover
|
|
13639
|
+
// pencil, or simply typing. An explicit `editTrigger: "click"`
|
|
13640
|
+
// does not override this; the law is the table's, not the
|
|
13641
|
+
// column's.
|
|
13642
|
+
editTrigger: "pencil"
|
|
13643
|
+
} : col.editTrigger === void 0 ? {} : { editTrigger: col.editTrigger },
|
|
13644
|
+
...editRequest?.rowId === id && editRequest.field === field ? { editRequest: editRequest.nonce, editSeed: editRequest.seed } : {}
|
|
11196
13645
|
}
|
|
11197
13646
|
);
|
|
11198
13647
|
}
|
|
11199
13648
|
return href ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Link, { href, onClick: (event) => event.stopPropagation(), className: "block w-full min-w-0 rounded outline-none focus-visible:ring-2 focus-visible:ring-ring", children: display }) : display;
|
|
11200
13649
|
};
|
|
11201
|
-
const currentViewSnapshot = (0,
|
|
13650
|
+
const currentViewSnapshot = (0, import_react21.useMemo)(
|
|
11202
13651
|
() => ({
|
|
11203
13652
|
__kind: "matrx-table-view",
|
|
11204
13653
|
version: 1,
|
|
@@ -11233,7 +13682,7 @@ function MatrxDataTableCore({
|
|
|
11233
13682
|
sort
|
|
11234
13683
|
]
|
|
11235
13684
|
);
|
|
11236
|
-
const declaredDefaultViewSnapshot = (0,
|
|
13685
|
+
const declaredDefaultViewSnapshot = (0, import_react21.useMemo)(
|
|
11237
13686
|
() => defaultViewSnapshot ?? {
|
|
11238
13687
|
__kind: "matrx-table-view",
|
|
11239
13688
|
version: 1,
|
|
@@ -11252,7 +13701,7 @@ function MatrxDataTableCore({
|
|
|
11252
13701
|
},
|
|
11253
13702
|
[columns, defaultPageSize, defaultSort, defaultViewSnapshot]
|
|
11254
13703
|
);
|
|
11255
|
-
const applySavedView = (0,
|
|
13704
|
+
const applySavedView = (0, import_react21.useCallback)(
|
|
11256
13705
|
(rawSnapshot) => {
|
|
11257
13706
|
const snapshot = parseTableViewSnapshot(rawSnapshot);
|
|
11258
13707
|
if (!snapshot) {
|
|
@@ -11604,6 +14053,28 @@ function MatrxDataTableCore({
|
|
|
11604
14053
|
}
|
|
11605
14054
|
}
|
|
11606
14055
|
) : null,
|
|
14056
|
+
grouping?.onColumnIdChange ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
14057
|
+
Select,
|
|
14058
|
+
{
|
|
14059
|
+
value: groupingColumnId ?? NO_GROUPING_VALUE,
|
|
14060
|
+
onValueChange: (value) => grouping.onColumnIdChange?.(value === NO_GROUPING_VALUE ? null : value),
|
|
14061
|
+
children: [
|
|
14062
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
14063
|
+
SelectTrigger,
|
|
14064
|
+
{
|
|
14065
|
+
"data-matrx-table-group-by": true,
|
|
14066
|
+
"aria-label": "Group rows by a column",
|
|
14067
|
+
className: "h-8 w-auto min-w-[9rem] gap-1 text-xs",
|
|
14068
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(SelectValue, { placeholder: "No groups" })
|
|
14069
|
+
}
|
|
14070
|
+
),
|
|
14071
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(SelectContent, { children: [
|
|
14072
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(SelectItem, { value: NO_GROUPING_VALUE, children: "No groups" }),
|
|
14073
|
+
groupableColumns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(SelectItem, { value: columnId(col), children: `Group by ${col.label ?? (typeof col.header === "string" ? col.header : columnId(col))}` }, columnId(col)))
|
|
14074
|
+
] })
|
|
14075
|
+
]
|
|
14076
|
+
}
|
|
14077
|
+
) : null,
|
|
11607
14078
|
columns.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
11608
14079
|
TableToolbarAction,
|
|
11609
14080
|
{
|
|
@@ -11671,65 +14142,6 @@ function MatrxDataTableCore({
|
|
|
11671
14142
|
]
|
|
11672
14143
|
}
|
|
11673
14144
|
),
|
|
11674
|
-
selection && selectionCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex shrink-0 flex-wrap items-center gap-2 rounded-md border border-primary/30 bg-primary/5 px-2 py-1.5", children: [
|
|
11675
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "text-xs font-medium text-foreground", children: [
|
|
11676
|
-
(0, import_format5.formatCount)(selectionCount),
|
|
11677
|
-
" ",
|
|
11678
|
-
selectionNoun,
|
|
11679
|
-
selectionCount === 1 ? "" : "s",
|
|
11680
|
-
" selected"
|
|
11681
|
-
] }),
|
|
11682
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
11683
|
-
Button,
|
|
11684
|
-
{
|
|
11685
|
-
type: "button",
|
|
11686
|
-
variant: "ghost",
|
|
11687
|
-
size: "sm",
|
|
11688
|
-
className: "h-7 gap-1 px-2 text-xs",
|
|
11689
|
-
onClick: () => {
|
|
11690
|
-
lastToggledIndex.current = null;
|
|
11691
|
-
selection.onSelectedIdsChange([]);
|
|
11692
|
-
},
|
|
11693
|
-
children: [
|
|
11694
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(X, { className: "h-3.5 w-3.5" }),
|
|
11695
|
-
"Clear"
|
|
11696
|
-
]
|
|
11697
|
-
}
|
|
11698
|
-
),
|
|
11699
|
-
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "ml-auto flex flex-wrap items-center gap-1.5", children: [
|
|
11700
|
-
effectiveCopy && selectedRows.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
11701
|
-
CopyButtons,
|
|
11702
|
-
{
|
|
11703
|
-
size: "icon",
|
|
11704
|
-
"data-matrx-table-icon-action": true,
|
|
11705
|
-
sourceId: `${tableCopySourceNamespace}:selection`,
|
|
11706
|
-
...effectiveCopy.references ? { references: effectiveCopy.references(selectedRows, data) } : {},
|
|
11707
|
-
...effectiveCopy.triggerVariant ? { triggerVariant: effectiveCopy.triggerVariant } : {},
|
|
11708
|
-
label: `${selectedRows.length} selected ${selectionNoun}${selectedRows.length === 1 ? "" : "s"}`,
|
|
11709
|
-
...copy === void 0 ? {} : {
|
|
11710
|
-
human: () => buildViewHuman(effectiveCopy, selectedRows, effectiveCopyColumns),
|
|
11711
|
-
json: () => selectedRows.map((row) => effectiveCopy.agentRow ? effectiveCopy.agentRow(row) : row)
|
|
11712
|
-
},
|
|
11713
|
-
agent: () => copy === void 0 ? buildDefaultTableViewAgentInput(effectiveCopy, selectedRows, data, declaredVisibleCopyColumns, { scope: "selected" }) : buildViewAgentInput(effectiveCopy, selectedRows, data, { scope: "selected" }),
|
|
11714
|
-
aiVariants: copySubsetVariantFor(
|
|
11715
|
-
() => selectedRows,
|
|
11716
|
-
"selected"
|
|
11717
|
-
),
|
|
11718
|
-
export: {
|
|
11719
|
-
items: [],
|
|
11720
|
-
sheetRows: () => selectedRows.map(
|
|
11721
|
-
(row) => projectDefaultTableCopyRow(row, declaredVisibleCopyColumns)
|
|
11722
|
-
),
|
|
11723
|
-
sheetColumns: () => declaredVisibleCopyColumns.map((column) => ({
|
|
11724
|
-
id: columnId(column),
|
|
11725
|
-
label: column.label ?? (typeof column.header === "string" ? column.header : columnId(column))
|
|
11726
|
-
}))
|
|
11727
|
-
}
|
|
11728
|
-
}
|
|
11729
|
-
) : null,
|
|
11730
|
-
selection.actions?.(selectedRows, selection.selectedIds)
|
|
11731
|
-
] })
|
|
11732
|
-
] }) : null,
|
|
11733
14145
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { "data-matrx-table-body-region": true, className: "flex min-h-0 flex-1 flex-col gap-2", children: [
|
|
11734
14146
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "relative min-h-0 flex-1", children: [
|
|
11735
14147
|
mobileCards ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
@@ -11837,12 +14249,33 @@ function MatrxDataTableCore({
|
|
|
11837
14249
|
]
|
|
11838
14250
|
}
|
|
11839
14251
|
) : null,
|
|
14252
|
+
coverageResult && coverageResult.notice ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
14253
|
+
"div",
|
|
14254
|
+
{
|
|
14255
|
+
"data-matrx-table-coverage": true,
|
|
14256
|
+
"data-matrx-table-coverage-scope": coverageResult.scope,
|
|
14257
|
+
role: "status",
|
|
14258
|
+
className: "mb-1 flex items-start gap-2 rounded-md border border-amber-300/70 bg-amber-50 px-3 py-2 text-xs text-amber-900 dark:border-amber-500/40 dark:bg-amber-950/40 dark:text-amber-200",
|
|
14259
|
+
children: [
|
|
14260
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "font-semibold", children: coverageResult.badge }),
|
|
14261
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { children: coverageResult.notice })
|
|
14262
|
+
]
|
|
14263
|
+
}
|
|
14264
|
+
) : null,
|
|
11840
14265
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
11841
14266
|
"div",
|
|
11842
14267
|
{
|
|
11843
14268
|
ref: scrollRef,
|
|
11844
14269
|
"data-matrx-table-scroll": true,
|
|
11845
14270
|
onScroll: updateScrollHint,
|
|
14271
|
+
...spreadsheetEnabled ? {
|
|
14272
|
+
tabIndex: sheet.containerProps.tabIndex,
|
|
14273
|
+
onKeyDown: sheet.containerProps.onKeyDown,
|
|
14274
|
+
onCopy: sheet.containerProps.onCopy,
|
|
14275
|
+
onCut: sheet.containerProps.onCut,
|
|
14276
|
+
onPaste: sheet.containerProps.onPaste,
|
|
14277
|
+
"data-matrx-table-spreadsheet": "true"
|
|
14278
|
+
} : {},
|
|
11846
14279
|
"aria-busy": isLoading || isFetching,
|
|
11847
14280
|
style: { containerType: "inline-size" },
|
|
11848
14281
|
className: cn(
|
|
@@ -11900,7 +14333,14 @@ function MatrxDataTableCore({
|
|
|
11900
14333
|
ref: tableHeaderRef,
|
|
11901
14334
|
"data-matrx-table-sticky-header": stickyHeader ? "true" : void 0,
|
|
11902
14335
|
className: cn(
|
|
11903
|
-
|
|
14336
|
+
// 🚨 ABOVE THE FROZEN COLUMN, NOT UNDER IT. A frozen body
|
|
14337
|
+
// cell is `sm:z-20` so it can slide under the columns to
|
|
14338
|
+
// its right; the header was `z-10`, so the frozen column's
|
|
14339
|
+
// cells scrolled straight OVER the header they belong to
|
|
14340
|
+
// and the top data row printed through the column names.
|
|
14341
|
+
// Only a table long enough to scroll shows it, which is why
|
|
14342
|
+
// it survived until a hundred-thousand-row screenshot.
|
|
14343
|
+
"z-30 border-b border-border bg-muted/90 shadow-[0_1px_0_0_var(--border)] backdrop-blur-sm",
|
|
11904
14344
|
stickyHeader && (documentStickyHeader ? "relative translate-y-[var(--matrx-document-sticky-offset)]" : "sticky top-0")
|
|
11905
14345
|
),
|
|
11906
14346
|
children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("tr", { children: [
|
|
@@ -11933,7 +14373,17 @@ function MatrxDataTableCore({
|
|
|
11933
14373
|
)
|
|
11934
14374
|
}
|
|
11935
14375
|
) : null,
|
|
11936
|
-
|
|
14376
|
+
columnSpacers && columnSpacers.start > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
14377
|
+
"th",
|
|
14378
|
+
{
|
|
14379
|
+
"aria-hidden": "true",
|
|
14380
|
+
"data-matrx-table-column-spacer": "start",
|
|
14381
|
+
className: "border-0 p-0",
|
|
14382
|
+
style: { width: `${columnSpacers.start}px`, minWidth: `${columnSpacers.start}px` }
|
|
14383
|
+
},
|
|
14384
|
+
"matrx-column-spacer-start"
|
|
14385
|
+
) : null,
|
|
14386
|
+
renderedColumns.map((col) => {
|
|
11937
14387
|
const id = columnId(col);
|
|
11938
14388
|
const meta = filterMeta.get(id);
|
|
11939
14389
|
const isSorted = sort?.id === id;
|
|
@@ -11949,6 +14399,7 @@ function MatrxDataTableCore({
|
|
|
11949
14399
|
"th",
|
|
11950
14400
|
{
|
|
11951
14401
|
"data-matrx-table-column-id": id,
|
|
14402
|
+
"data-matrx-header-column-id": id,
|
|
11952
14403
|
"data-matrx-column-drag-shadow": isColumnDragShadow ? "true" : void 0,
|
|
11953
14404
|
"aria-sort": isSorted ? sort?.direction === "asc" ? "ascending" : "descending" : void 0,
|
|
11954
14405
|
className: cn(
|
|
@@ -11976,7 +14427,7 @@ function MatrxDataTableCore({
|
|
|
11976
14427
|
frozenEdgeId === id && FROZEN_EDGE_CLASS
|
|
11977
14428
|
),
|
|
11978
14429
|
style: {
|
|
11979
|
-
...columnWidthVar(width,
|
|
14430
|
+
...columnWidthVar(width, windowedWidthFor(id, width), id, columnResizable),
|
|
11980
14431
|
...frozenStyle(id)
|
|
11981
14432
|
},
|
|
11982
14433
|
children: [
|
|
@@ -11985,6 +14436,12 @@ function MatrxDataTableCore({
|
|
|
11985
14436
|
{
|
|
11986
14437
|
label: col.header,
|
|
11987
14438
|
labelText: headerLabel,
|
|
14439
|
+
...facetsEnabled ? {
|
|
14440
|
+
facets: facetState[id]?.data ?? null,
|
|
14441
|
+
facetsLoading: facetState[id]?.loading ?? false,
|
|
14442
|
+
...facetState[id]?.error === void 0 ? {} : { facetsError: facetState[id]?.error },
|
|
14443
|
+
onFilterOpen: () => requestFacets(id)
|
|
14444
|
+
} : {},
|
|
11988
14445
|
sortable: col.sortable !== false,
|
|
11989
14446
|
isSorted: Boolean(isSorted),
|
|
11990
14447
|
sortDirection: sort?.direction ?? defaultSortDirection,
|
|
@@ -12040,6 +14497,16 @@ function MatrxDataTableCore({
|
|
|
12040
14497
|
id
|
|
12041
14498
|
);
|
|
12042
14499
|
}),
|
|
14500
|
+
columnSpacers && columnSpacers.end > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
14501
|
+
"th",
|
|
14502
|
+
{
|
|
14503
|
+
"aria-hidden": "true",
|
|
14504
|
+
"data-matrx-table-column-spacer": "end",
|
|
14505
|
+
className: "border-0 p-0",
|
|
14506
|
+
style: { width: `${columnSpacers.end}px`, minWidth: `${columnSpacers.end}px` }
|
|
14507
|
+
},
|
|
14508
|
+
"matrx-column-spacer-end"
|
|
14509
|
+
) : null,
|
|
12043
14510
|
showActionsCol && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
12044
14511
|
"th",
|
|
12045
14512
|
{
|
|
@@ -12055,7 +14522,17 @@ function MatrxDataTableCore({
|
|
|
12055
14522
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("tbody", { children: [
|
|
12056
14523
|
isLoading ? Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("tr", { className: "border-b border-border/60", children: [
|
|
12057
14524
|
selection ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("td", { className: "px-2 py-2", style: fixedUtilityWidth(fixedTableGeometry?.selectionWidth), children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Skeleton, { className: "h-3.5 w-3.5" }) }) : null,
|
|
12058
|
-
|
|
14525
|
+
columnSpacers && columnSpacers.start > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
14526
|
+
"td",
|
|
14527
|
+
{
|
|
14528
|
+
"aria-hidden": "true",
|
|
14529
|
+
"data-matrx-table-column-spacer": "start",
|
|
14530
|
+
className: "border-0 p-0",
|
|
14531
|
+
style: { width: `${columnSpacers.start}px`, minWidth: `${columnSpacers.start}px` }
|
|
14532
|
+
},
|
|
14533
|
+
"matrx-column-spacer-start"
|
|
14534
|
+
) : null,
|
|
14535
|
+
renderedColumns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
12059
14536
|
"td",
|
|
12060
14537
|
{
|
|
12061
14538
|
className: cn(
|
|
@@ -12067,11 +14544,21 @@ function MatrxDataTableCore({
|
|
|
12067
14544
|
},
|
|
12068
14545
|
columnId(col)
|
|
12069
14546
|
)),
|
|
12070
|
-
showActionsCol && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("td", { className: "text-right align-middle", style: fixedUtilityWidth(fixedTableGeometry?.actionsWidth), children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Skeleton, { className: "ml-auto h-5 w-10" }) })
|
|
14547
|
+
showActionsCol && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("td", { className: "text-right align-middle", style: fixedUtilityWidth(fixedTableGeometry?.actionsWidth), children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Skeleton, { className: "ml-auto h-5 w-10" }) }),
|
|
14548
|
+
columnSpacers && columnSpacers.end > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
14549
|
+
"td",
|
|
14550
|
+
{
|
|
14551
|
+
"aria-hidden": "true",
|
|
14552
|
+
"data-matrx-table-column-spacer": "end",
|
|
14553
|
+
className: "border-0 p-0",
|
|
14554
|
+
style: { width: `${columnSpacers.end}px`, minWidth: `${columnSpacers.end}px` }
|
|
14555
|
+
},
|
|
14556
|
+
"matrx-column-spacer-end"
|
|
14557
|
+
) : null
|
|
12071
14558
|
] }, `sk-${i}`)) : paginated.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
12072
14559
|
"td",
|
|
12073
14560
|
{
|
|
12074
|
-
colSpan:
|
|
14561
|
+
colSpan: renderedColSpan,
|
|
12075
14562
|
className: "px-0 py-12 text-center",
|
|
12076
14563
|
children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { "data-matrx-table-empty-state": true, className: "sticky left-0 flex flex-col items-center gap-2 whitespace-normal px-4", style: { width: "100cqw", maxWidth: "100%" }, children: [
|
|
12077
14564
|
renderedEmptyState?.icon,
|
|
@@ -12080,7 +14567,43 @@ function MatrxDataTableCore({
|
|
|
12080
14567
|
renderedEmptyState?.action
|
|
12081
14568
|
] })
|
|
12082
14569
|
}
|
|
12083
|
-
) }) :
|
|
14570
|
+
) }) : bodyEntries.map((entry) => {
|
|
14571
|
+
if (entry.kind === "spacer") {
|
|
14572
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
14573
|
+
"tr",
|
|
14574
|
+
{
|
|
14575
|
+
"aria-hidden": "true",
|
|
14576
|
+
"data-matrx-table-virtual-spacer": entry.place,
|
|
14577
|
+
style: { height: `${entry.height}px` },
|
|
14578
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
14579
|
+
"td",
|
|
14580
|
+
{
|
|
14581
|
+
className: "border-0 p-0",
|
|
14582
|
+
colSpan: renderedColSpan
|
|
14583
|
+
}
|
|
14584
|
+
)
|
|
14585
|
+
},
|
|
14586
|
+
`matrx-virtual-spacer-${entry.place}`
|
|
14587
|
+
);
|
|
14588
|
+
}
|
|
14589
|
+
if (entry.kind === "group") {
|
|
14590
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
14591
|
+
TableGroupHeaderRow,
|
|
14592
|
+
{
|
|
14593
|
+
group: entry.group,
|
|
14594
|
+
collapsed: entry.collapsed,
|
|
14595
|
+
columns: renderedColumns,
|
|
14596
|
+
spacers: columnSpacers,
|
|
14597
|
+
leadingCols,
|
|
14598
|
+
showActionsCol,
|
|
14599
|
+
rowNoun: grouping?.rowNoun ?? "row",
|
|
14600
|
+
onToggle: () => setCollapsedGroups(toggleGroupCollapsed(collapsedGroups, entry.group.key))
|
|
14601
|
+
},
|
|
14602
|
+
`matrx-group-${entry.group.key}`
|
|
14603
|
+
);
|
|
14604
|
+
}
|
|
14605
|
+
const row = entry.row;
|
|
14606
|
+
const index = entry.index;
|
|
12084
14607
|
const id = getRowId(row);
|
|
12085
14608
|
const isSelected = selectedId === id;
|
|
12086
14609
|
const rowEdits = edits[id];
|
|
@@ -12091,6 +14614,7 @@ function MatrxDataTableCore({
|
|
|
12091
14614
|
"tr",
|
|
12092
14615
|
{
|
|
12093
14616
|
"data-row-id": id,
|
|
14617
|
+
style: explicitRowHeight !== void 0 ? { height: `${explicitRowHeight}px` } : virtualizeActive ? { height: `${virtualRowHeight}px` } : void 0,
|
|
12094
14618
|
"data-state": isSelected ? "selected" : void 0,
|
|
12095
14619
|
onClick: (e) => {
|
|
12096
14620
|
if (rowEventTargetsInteractiveDescendant(e.target)) return;
|
|
@@ -12163,15 +14687,40 @@ function MatrxDataTableCore({
|
|
|
12163
14687
|
) : null
|
|
12164
14688
|
}
|
|
12165
14689
|
) : null,
|
|
12166
|
-
|
|
14690
|
+
columnSpacers && columnSpacers.start > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
14691
|
+
"td",
|
|
14692
|
+
{
|
|
14693
|
+
"aria-hidden": "true",
|
|
14694
|
+
"data-matrx-table-column-spacer": "start",
|
|
14695
|
+
className: "border-0 p-0",
|
|
14696
|
+
style: { width: `${columnSpacers.start}px`, minWidth: `${columnSpacers.start}px` }
|
|
14697
|
+
},
|
|
14698
|
+
"matrx-column-spacer-start"
|
|
14699
|
+
) : null,
|
|
14700
|
+
renderedColumns.map((col, colIdx) => {
|
|
12167
14701
|
const isColumnDragShadow = columnDragPreview?.draggedId === columnId(col) && columnDragPreview.targetId !== null;
|
|
12168
|
-
|
|
14702
|
+
const sheetCell = spreadsheetEnabled ? sheet.cellProps(id, columnId(col)) : null;
|
|
14703
|
+
const carriesFillHandle = sheetCell !== null && sheet.isFillHandleCell(id, columnId(col));
|
|
14704
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
12169
14705
|
"td",
|
|
12170
14706
|
{
|
|
12171
14707
|
"data-matrx-table-column-id": columnId(col),
|
|
12172
14708
|
"data-matrx-column-drag-shadow": isColumnDragShadow ? "true" : void 0,
|
|
14709
|
+
...sheetCell ? {
|
|
14710
|
+
"data-matrx-cell-row": sheetCell["data-matrx-cell-row"],
|
|
14711
|
+
"data-matrx-cell-col": sheetCell["data-matrx-cell-col"],
|
|
14712
|
+
...sheetCell["data-matrx-cell-selected"] ? { "data-matrx-cell-selected": "true" } : {},
|
|
14713
|
+
...sheetCell["data-matrx-cell-active"] ? { "data-matrx-cell-active": "true" } : {},
|
|
14714
|
+
...sheetCell["data-matrx-cell-fill-preview"] ? { "data-matrx-cell-fill-preview": "true" } : {},
|
|
14715
|
+
onMouseDown: sheetCell.onMouseDown,
|
|
14716
|
+
onMouseEnter: sheetCell.onMouseEnter
|
|
14717
|
+
} : {},
|
|
12173
14718
|
className: cn(
|
|
12174
14719
|
"py-1.5 align-middle lg:py-0.5",
|
|
14720
|
+
sheetCell?.["data-matrx-cell-selected"] && "bg-primary/10",
|
|
14721
|
+
sheetCell?.["data-matrx-cell-fill-preview"] && "ring-1 ring-inset ring-primary/40",
|
|
14722
|
+
sheetCell?.["data-matrx-cell-active"] && "relative z-10 ring-2 ring-inset ring-primary",
|
|
14723
|
+
carriesFillHandle && "relative",
|
|
12175
14724
|
col.compact || resolveColumnMarker(col) !== void 0 ? "px-1" : "px-2",
|
|
12176
14725
|
// nowrap (NOT truncate — truncate clips the cell and
|
|
12177
14726
|
// defeats w-max, killing the horizontal scroll).
|
|
@@ -12193,42 +14742,64 @@ function MatrxDataTableCore({
|
|
|
12193
14742
|
style: {
|
|
12194
14743
|
...columnWidthVar(
|
|
12195
14744
|
resolveColumnMarker(col) && col.width === void 0 ? 40 : col.width,
|
|
12196
|
-
|
|
14745
|
+
windowedWidthFor(columnId(col), col.width),
|
|
12197
14746
|
columnId(col),
|
|
12198
14747
|
resizableColumns && col.resizable !== false
|
|
12199
14748
|
),
|
|
12200
14749
|
...frozenStyle(columnId(col))
|
|
12201
14750
|
},
|
|
12202
|
-
children:
|
|
12203
|
-
|
|
12204
|
-
|
|
12205
|
-
|
|
12206
|
-
|
|
12207
|
-
|
|
12208
|
-
|
|
12209
|
-
|
|
12210
|
-
|
|
12211
|
-
|
|
12212
|
-
|
|
12213
|
-
|
|
12214
|
-
|
|
12215
|
-
|
|
12216
|
-
|
|
12217
|
-
|
|
12218
|
-
|
|
12219
|
-
|
|
12220
|
-
|
|
12221
|
-
|
|
12222
|
-
|
|
12223
|
-
|
|
12224
|
-
|
|
12225
|
-
|
|
12226
|
-
|
|
12227
|
-
|
|
14751
|
+
children: [
|
|
14752
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
14753
|
+
"div",
|
|
14754
|
+
{
|
|
14755
|
+
className: cn(
|
|
14756
|
+
colIdx === 0 && hierarchy && "flex min-w-0 items-center"
|
|
14757
|
+
),
|
|
14758
|
+
children: [
|
|
14759
|
+
colIdx === 0 && hierarchy ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
14760
|
+
HierarchyDragHandle,
|
|
14761
|
+
{
|
|
14762
|
+
id,
|
|
14763
|
+
label: hierarchy.itemLabel?.(row) ?? "row",
|
|
14764
|
+
disabled: !(hierarchy.canReparent?.(row) ?? true)
|
|
14765
|
+
}
|
|
14766
|
+
) : null,
|
|
14767
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
14768
|
+
"div",
|
|
14769
|
+
{
|
|
14770
|
+
"data-matrx-cell-content": true,
|
|
14771
|
+
className: "min-w-0 max-w-full flex-1 whitespace-normal break-words [overflow-wrap:anywhere] sm:[&_*]:min-w-0 sm:[&_*]:whitespace-normal sm:[&_*]:[overflow-wrap:anywhere] sm:[&_.truncate]:whitespace-nowrap sm:[&_[data-slot=badge]]:whitespace-nowrap sm:[&_[data-slot=badge]]:[overflow-wrap:normal] sm:[&_[data-matrx-cell-control]]:w-max sm:[&_[data-matrx-cell-control]]:min-w-max sm:[&_[data-matrx-cell-control]]:max-w-none sm:[&_[data-matrx-cell-control]]:whitespace-nowrap sm:[&_[data-matrx-cell-control]]:[overflow-wrap:normal] sm:[&_[data-matrx-cell-control]_*]:whitespace-nowrap sm:[&_[data-matrx-cell-control]_*]:[overflow-wrap:normal]",
|
|
14772
|
+
children: renderRecordCell(row, col, index)
|
|
14773
|
+
}
|
|
14774
|
+
)
|
|
14775
|
+
]
|
|
14776
|
+
}
|
|
14777
|
+
),
|
|
14778
|
+
carriesFillHandle ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
14779
|
+
"button",
|
|
14780
|
+
{
|
|
14781
|
+
type: "button",
|
|
14782
|
+
"data-matrx-table-fill-handle": true,
|
|
14783
|
+
"aria-label": "Drag to fill the cells below or beside this selection",
|
|
14784
|
+
onMouseDown: sheet.startFillDrag,
|
|
14785
|
+
className: "absolute -bottom-[3px] -right-[3px] z-20 h-2 w-2 cursor-crosshair rounded-[1px] border border-background bg-primary"
|
|
14786
|
+
}
|
|
14787
|
+
) : null
|
|
14788
|
+
]
|
|
12228
14789
|
},
|
|
12229
14790
|
columnId(col)
|
|
12230
14791
|
);
|
|
12231
14792
|
}),
|
|
14793
|
+
columnSpacers && columnSpacers.end > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
14794
|
+
"td",
|
|
14795
|
+
{
|
|
14796
|
+
"aria-hidden": "true",
|
|
14797
|
+
"data-matrx-table-column-spacer": "end",
|
|
14798
|
+
className: "border-0 p-0",
|
|
14799
|
+
style: { width: `${columnSpacers.end}px`, minWidth: `${columnSpacers.end}px` }
|
|
14800
|
+
},
|
|
14801
|
+
"matrx-column-spacer-end"
|
|
14802
|
+
) : null,
|
|
12232
14803
|
showActionsCol && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
12233
14804
|
"td",
|
|
12234
14805
|
{
|
|
@@ -12291,7 +14862,7 @@ function MatrxDataTableCore({
|
|
|
12291
14862
|
children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
12292
14863
|
"td",
|
|
12293
14864
|
{
|
|
12294
|
-
colSpan:
|
|
14865
|
+
colSpan: renderedColSpan,
|
|
12295
14866
|
className: "p-4",
|
|
12296
14867
|
children: expandedDetail.render(displayRow, controls)
|
|
12297
14868
|
}
|
|
@@ -12299,7 +14870,7 @@ function MatrxDataTableCore({
|
|
|
12299
14870
|
},
|
|
12300
14871
|
`${id}:expanded-detail`
|
|
12301
14872
|
) : null;
|
|
12302
|
-
return hierarchy ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
14873
|
+
return hierarchy ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react21.Fragment, { children: [
|
|
12303
14874
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
12304
14875
|
HierarchyDroppableRow,
|
|
12305
14876
|
{
|
|
@@ -12309,7 +14880,7 @@ function MatrxDataTableCore({
|
|
|
12309
14880
|
}
|
|
12310
14881
|
),
|
|
12311
14882
|
inlineDetail
|
|
12312
|
-
] }, id) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
14883
|
+
] }, id) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react21.Fragment, { children: [
|
|
12313
14884
|
wrappedRow,
|
|
12314
14885
|
inlineDetail
|
|
12315
14886
|
] }, id);
|
|
@@ -12317,7 +14888,7 @@ function MatrxDataTableCore({
|
|
|
12317
14888
|
appendQuery !== null && isFetching && !isLoading ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("tr", { "data-matrx-table-append-loading-row": true, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
12318
14889
|
"td",
|
|
12319
14890
|
{
|
|
12320
|
-
colSpan:
|
|
14891
|
+
colSpan: renderedColSpan,
|
|
12321
14892
|
className: "sticky bottom-0 z-20 h-16 border-y border-border bg-card/95 px-0 py-0 text-left shadow-sm backdrop-blur-sm",
|
|
12322
14893
|
children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
12323
14894
|
"div",
|
|
@@ -12342,7 +14913,17 @@ function MatrxDataTableCore({
|
|
|
12342
14913
|
] }),
|
|
12343
14914
|
footerRows.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("tfoot", { className: "border-t-2 border-border bg-muted/50 font-semibold", children: footerRows.map((row, index) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("tr", { children: [
|
|
12344
14915
|
selection ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("td", { className: "px-2 py-2" }) : null,
|
|
12345
|
-
|
|
14916
|
+
columnSpacers && columnSpacers.start > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
14917
|
+
"td",
|
|
14918
|
+
{
|
|
14919
|
+
"aria-hidden": "true",
|
|
14920
|
+
"data-matrx-table-column-spacer": "start",
|
|
14921
|
+
className: "border-0 p-0",
|
|
14922
|
+
style: { width: `${columnSpacers.start}px`, minWidth: `${columnSpacers.start}px` }
|
|
14923
|
+
},
|
|
14924
|
+
"matrx-column-spacer-start"
|
|
14925
|
+
) : null,
|
|
14926
|
+
renderedColumns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
12346
14927
|
"td",
|
|
12347
14928
|
{
|
|
12348
14929
|
className: cn(
|
|
@@ -12354,7 +14935,7 @@ function MatrxDataTableCore({
|
|
|
12354
14935
|
),
|
|
12355
14936
|
style: columnWidthVar(
|
|
12356
14937
|
resolveColumnMarker(column) && column.width === void 0 ? 40 : column.width,
|
|
12357
|
-
|
|
14938
|
+
windowedWidthFor(columnId(column), column.width),
|
|
12358
14939
|
columnId(column),
|
|
12359
14940
|
resizableColumns && column.resizable !== false
|
|
12360
14941
|
),
|
|
@@ -12362,6 +14943,16 @@ function MatrxDataTableCore({
|
|
|
12362
14943
|
},
|
|
12363
14944
|
columnId(column)
|
|
12364
14945
|
)),
|
|
14946
|
+
columnSpacers && columnSpacers.end > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
14947
|
+
"td",
|
|
14948
|
+
{
|
|
14949
|
+
"aria-hidden": "true",
|
|
14950
|
+
"data-matrx-table-column-spacer": "end",
|
|
14951
|
+
className: "border-0 p-0",
|
|
14952
|
+
style: { width: `${columnSpacers.end}px`, minWidth: `${columnSpacers.end}px` }
|
|
14953
|
+
},
|
|
14954
|
+
"matrx-column-spacer-end"
|
|
14955
|
+
) : null,
|
|
12365
14956
|
showActionsCol ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("td", {}) : null
|
|
12366
14957
|
] }, `footer-${index}`)) }) : null
|
|
12367
14958
|
]
|
|
@@ -12525,8 +15116,8 @@ function MatrxDataTableCore({
|
|
|
12525
15116
|
itemsPerPage: pageSize === 0 && allRowsAreLoaded ? 0 : effectivePageSize,
|
|
12526
15117
|
currentPage: safePage,
|
|
12527
15118
|
onPageChange: setPage,
|
|
12528
|
-
onItemsPerPageChange: (
|
|
12529
|
-
setPageSize(
|
|
15119
|
+
onItemsPerPageChange: (n2) => {
|
|
15120
|
+
setPageSize(n2);
|
|
12530
15121
|
if (!controlledQuery) setPage(1);
|
|
12531
15122
|
},
|
|
12532
15123
|
pageSizeOptions: pageSizeOptions.filter((size) => size > 0),
|
|
@@ -12536,7 +15127,73 @@ function MatrxDataTableCore({
|
|
|
12536
15127
|
compact: true,
|
|
12537
15128
|
hideEntriesInfo: false
|
|
12538
15129
|
}
|
|
12539
|
-
) }) : null
|
|
15130
|
+
) }) : null,
|
|
15131
|
+
selection && selectionCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
15132
|
+
"div",
|
|
15133
|
+
{
|
|
15134
|
+
"data-matrx-table-bulk-bar": true,
|
|
15135
|
+
className: "mt-2 flex shrink-0 flex-wrap items-center gap-2 rounded-md border border-primary/30 bg-primary/5 px-2 py-1.5",
|
|
15136
|
+
children: [
|
|
15137
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "text-xs font-medium text-foreground", children: [
|
|
15138
|
+
(0, import_format5.formatCount)(selectionCount),
|
|
15139
|
+
" ",
|
|
15140
|
+
selectionNoun,
|
|
15141
|
+
selectionCount === 1 ? "" : "s",
|
|
15142
|
+
" selected"
|
|
15143
|
+
] }),
|
|
15144
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
15145
|
+
Button,
|
|
15146
|
+
{
|
|
15147
|
+
type: "button",
|
|
15148
|
+
variant: "ghost",
|
|
15149
|
+
size: "sm",
|
|
15150
|
+
className: "h-7 gap-1 px-2 text-xs",
|
|
15151
|
+
onClick: () => {
|
|
15152
|
+
lastToggledIndex.current = null;
|
|
15153
|
+
selection.onSelectedIdsChange([]);
|
|
15154
|
+
},
|
|
15155
|
+
children: [
|
|
15156
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(X, { className: "h-3.5 w-3.5" }),
|
|
15157
|
+
"Clear"
|
|
15158
|
+
]
|
|
15159
|
+
}
|
|
15160
|
+
),
|
|
15161
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "ml-auto flex flex-wrap items-center gap-1.5", children: [
|
|
15162
|
+
effectiveCopy && selectedRows.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
15163
|
+
CopyButtons,
|
|
15164
|
+
{
|
|
15165
|
+
size: "icon",
|
|
15166
|
+
"data-matrx-table-icon-action": true,
|
|
15167
|
+
sourceId: `${tableCopySourceNamespace}:selection`,
|
|
15168
|
+
...effectiveCopy.references ? { references: effectiveCopy.references(selectedRows, data) } : {},
|
|
15169
|
+
...effectiveCopy.triggerVariant ? { triggerVariant: effectiveCopy.triggerVariant } : {},
|
|
15170
|
+
label: `${selectedRows.length} selected ${selectionNoun}${selectedRows.length === 1 ? "" : "s"}`,
|
|
15171
|
+
...copy === void 0 ? {} : {
|
|
15172
|
+
human: () => buildViewHuman(effectiveCopy, selectedRows, effectiveCopyColumns),
|
|
15173
|
+
json: () => selectedRows.map((row) => effectiveCopy.agentRow ? effectiveCopy.agentRow(row) : row)
|
|
15174
|
+
},
|
|
15175
|
+
agent: () => copy === void 0 ? buildDefaultTableViewAgentInput(effectiveCopy, selectedRows, data, declaredVisibleCopyColumns, { scope: "selected" }) : buildViewAgentInput(effectiveCopy, selectedRows, data, { scope: "selected" }),
|
|
15176
|
+
aiVariants: copySubsetVariantFor(
|
|
15177
|
+
() => selectedRows,
|
|
15178
|
+
"selected"
|
|
15179
|
+
),
|
|
15180
|
+
export: {
|
|
15181
|
+
items: [],
|
|
15182
|
+
sheetRows: () => selectedRows.map(
|
|
15183
|
+
(row) => projectDefaultTableCopyRow(row, declaredVisibleCopyColumns)
|
|
15184
|
+
),
|
|
15185
|
+
sheetColumns: () => declaredVisibleCopyColumns.map((column) => ({
|
|
15186
|
+
id: columnId(column),
|
|
15187
|
+
label: column.label ?? (typeof column.header === "string" ? column.header : columnId(column))
|
|
15188
|
+
}))
|
|
15189
|
+
}
|
|
15190
|
+
}
|
|
15191
|
+
) : null,
|
|
15192
|
+
selection.actions?.(selectedRows, selection.selectedIds)
|
|
15193
|
+
] })
|
|
15194
|
+
]
|
|
15195
|
+
}
|
|
15196
|
+
) : null
|
|
12540
15197
|
] }),
|
|
12541
15198
|
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
12542
15199
|
ColumnManager,
|
|
@@ -12818,7 +15475,7 @@ function HierarchyDragIndicatorLayer({
|
|
|
12818
15475
|
scrollRef,
|
|
12819
15476
|
resolve: resolve2
|
|
12820
15477
|
}) {
|
|
12821
|
-
const [indicator, setIndicator] = (0,
|
|
15478
|
+
const [indicator, setIndicator] = (0, import_react21.useState)(
|
|
12822
15479
|
null
|
|
12823
15480
|
);
|
|
12824
15481
|
(0, import_core3.useDndMonitor)({
|
|
@@ -12922,9 +15579,9 @@ function HierarchyDroppableRow({
|
|
|
12922
15579
|
children
|
|
12923
15580
|
}) {
|
|
12924
15581
|
const { setNodeRef } = (0, import_core3.useDroppable)({ id, disabled });
|
|
12925
|
-
if (!(0,
|
|
15582
|
+
if (!(0, import_react21.isValidElement)(children) || children.type !== "tr") return children;
|
|
12926
15583
|
const row = children;
|
|
12927
|
-
return (0,
|
|
15584
|
+
return (0, import_react21.cloneElement)(row, {
|
|
12928
15585
|
ref: setNodeRef,
|
|
12929
15586
|
className: row.props.className
|
|
12930
15587
|
});
|
|
@@ -12959,6 +15616,71 @@ function normalizeColumnWidthsForColumns(widths, columns) {
|
|
|
12959
15616
|
})
|
|
12960
15617
|
);
|
|
12961
15618
|
}
|
|
15619
|
+
function TableGroupHeaderRow({
|
|
15620
|
+
group,
|
|
15621
|
+
collapsed,
|
|
15622
|
+
columns,
|
|
15623
|
+
spacers,
|
|
15624
|
+
leadingCols,
|
|
15625
|
+
showActionsCol,
|
|
15626
|
+
rowNoun,
|
|
15627
|
+
onToggle
|
|
15628
|
+
}) {
|
|
15629
|
+
const count = group.rows.length;
|
|
15630
|
+
const summary = `${count.toLocaleString()} ${count === 1 ? rowNoun : `${rowNoun}s`}`;
|
|
15631
|
+
const firstId = columns[0] ? columnId(columns[0]) : null;
|
|
15632
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
15633
|
+
"tr",
|
|
15634
|
+
{
|
|
15635
|
+
"data-matrx-table-group-row": group.key,
|
|
15636
|
+
"data-matrx-table-group-collapsed": collapsed ? "true" : "false",
|
|
15637
|
+
className: "border-y border-border bg-muted/40",
|
|
15638
|
+
children: [
|
|
15639
|
+
Array.from({ length: leadingCols }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("td", { className: "px-2 py-1.5" }, `group-lead-${i}`)),
|
|
15640
|
+
spacers && spacers.start > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("td", { "aria-hidden": "true", className: "border-0 p-0", style: { width: `${spacers.start}px` } }) : null,
|
|
15641
|
+
columns.map((col) => {
|
|
15642
|
+
const id = columnId(col);
|
|
15643
|
+
const aggregate = group.aggregates[id];
|
|
15644
|
+
if (id === firstId) {
|
|
15645
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("td", { className: cn("px-2 py-1.5 align-middle", col.mobileHidden && "max-sm:hidden"), children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
15646
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
15647
|
+
"button",
|
|
15648
|
+
{
|
|
15649
|
+
type: "button",
|
|
15650
|
+
onClick: onToggle,
|
|
15651
|
+
"aria-expanded": !collapsed,
|
|
15652
|
+
"aria-label": `${collapsed ? "Show" : "Hide"} ${group.label}`,
|
|
15653
|
+
className: "inline-flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
15654
|
+
children: collapsed ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ChevronRight, { className: "h-4 w-4" }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ChevronDown, { className: "h-4 w-4" })
|
|
15655
|
+
}
|
|
15656
|
+
),
|
|
15657
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "truncate text-sm font-semibold text-foreground", children: group.label }),
|
|
15658
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "whitespace-nowrap text-xs text-muted-foreground", children: summary })
|
|
15659
|
+
] }) }, id);
|
|
15660
|
+
}
|
|
15661
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
15662
|
+
"td",
|
|
15663
|
+
{
|
|
15664
|
+
className: cn(
|
|
15665
|
+
"px-2 py-1.5 align-middle text-xs font-medium text-muted-foreground",
|
|
15666
|
+
// A subtotal lines up with the numbers it is a subtotal OF.
|
|
15667
|
+
// Left-aligned under a right-aligned money column it reads as a
|
|
15668
|
+
// different column's value.
|
|
15669
|
+
alignForFormat(col) === "center" && "text-center",
|
|
15670
|
+
alignForFormat(col) === "right" && "text-right",
|
|
15671
|
+
col.mobileHidden && "max-sm:hidden"
|
|
15672
|
+
),
|
|
15673
|
+
children: aggregate ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { "data-matrx-table-group-aggregate": id, className: "whitespace-nowrap", children: aggregate.label }) : null
|
|
15674
|
+
},
|
|
15675
|
+
id
|
|
15676
|
+
);
|
|
15677
|
+
}),
|
|
15678
|
+
spacers && spacers.end > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("td", { "aria-hidden": "true", className: "border-0 p-0", style: { width: `${spacers.end}px` } }) : null,
|
|
15679
|
+
showActionsCol ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("td", { className: "px-2 py-1.5" }) : null
|
|
15680
|
+
]
|
|
15681
|
+
}
|
|
15682
|
+
);
|
|
15683
|
+
}
|
|
12962
15684
|
function columnWidthVar(width, resizedWidth, id, resizable) {
|
|
12963
15685
|
if (width === void 0 && resizedWidth === void 0 && !resizable) return void 0;
|
|
12964
15686
|
const inferredWidth = resizable && inferTableSearchRole(id) === "name" ? "12rem" : "auto";
|
|
@@ -12968,7 +15690,7 @@ function columnWidthVar(width, resizedWidth, id, resizable) {
|
|
|
12968
15690
|
};
|
|
12969
15691
|
}
|
|
12970
15692
|
function DefaultJsonCell({ value }) {
|
|
12971
|
-
const [open, setOpen] = (0,
|
|
15693
|
+
const [open, setOpen] = (0, import_react21.useState)(false);
|
|
12972
15694
|
const host = useMatrxDataTableHost();
|
|
12973
15695
|
const Viewer = host.JsonViewer;
|
|
12974
15696
|
const text = JSON.stringify(value, null, 2);
|
|
@@ -13051,7 +15773,7 @@ function resolveStringTitle(title, fallback) {
|
|
|
13051
15773
|
}
|
|
13052
15774
|
|
|
13053
15775
|
// src/data-table/SavedViewsControl.tsx
|
|
13054
|
-
var
|
|
15776
|
+
var import_react22 = require("react");
|
|
13055
15777
|
|
|
13056
15778
|
// src/dropdown-menu.tsx
|
|
13057
15779
|
var DropdownMenuPrimitive = __toESM(require("@radix-ui/react-dropdown-menu"), 1);
|
|
@@ -13194,11 +15916,11 @@ function SavedViewsControl({
|
|
|
13194
15916
|
onUpdate,
|
|
13195
15917
|
onReload
|
|
13196
15918
|
}) {
|
|
13197
|
-
const unsavedChangesId = (0,
|
|
13198
|
-
const [saveOpen, setSaveOpen] = (0,
|
|
13199
|
-
const [name, setName] = (0,
|
|
13200
|
-
const [saving, setSaving] = (0,
|
|
13201
|
-
const [actionError, setActionError] = (0,
|
|
15919
|
+
const unsavedChangesId = (0, import_react22.useId)();
|
|
15920
|
+
const [saveOpen, setSaveOpen] = (0, import_react22.useState)(false);
|
|
15921
|
+
const [name, setName] = (0, import_react22.useState)("");
|
|
15922
|
+
const [saving, setSaving] = (0, import_react22.useState)(false);
|
|
15923
|
+
const [actionError, setActionError] = (0, import_react22.useState)(null);
|
|
13202
15924
|
const visibleError = actionError ?? error;
|
|
13203
15925
|
const save = async () => {
|
|
13204
15926
|
const next = name.trim();
|