@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
package/dist/data-table/index.js
CHANGED
|
@@ -5,13 +5,13 @@ import {
|
|
|
5
5
|
cloneElement as cloneElement2,
|
|
6
6
|
Fragment as Fragment6,
|
|
7
7
|
isValidElement as isValidElement2,
|
|
8
|
-
useCallback as
|
|
9
|
-
useEffect as
|
|
8
|
+
useCallback as useCallback8,
|
|
9
|
+
useEffect as useEffect16,
|
|
10
10
|
useId as useId2,
|
|
11
11
|
useLayoutEffect as useLayoutEffect2,
|
|
12
|
-
useMemo as
|
|
13
|
-
useRef as
|
|
14
|
-
useState as
|
|
12
|
+
useMemo as useMemo8,
|
|
13
|
+
useRef as useRef15,
|
|
14
|
+
useState as useState22
|
|
15
15
|
} from "react";
|
|
16
16
|
import {
|
|
17
17
|
DndContext,
|
|
@@ -5139,10 +5139,10 @@ function passesColumnFilter(value, filter) {
|
|
|
5139
5139
|
if (raw === "") return false;
|
|
5140
5140
|
const normalized = raw.replace(/[^0-9.-]/g, "");
|
|
5141
5141
|
if (normalized === "") return false;
|
|
5142
|
-
const
|
|
5143
|
-
if (!Number.isFinite(
|
|
5144
|
-
if (filter.min !== void 0 &&
|
|
5145
|
-
if (filter.max !== void 0 &&
|
|
5142
|
+
const n2 = typeof value === "number" ? value : Number(normalized);
|
|
5143
|
+
if (!Number.isFinite(n2)) return false;
|
|
5144
|
+
if (filter.min !== void 0 && n2 < filter.min) return false;
|
|
5145
|
+
if (filter.max !== void 0 && n2 > filter.max) return false;
|
|
5146
5146
|
return true;
|
|
5147
5147
|
}
|
|
5148
5148
|
}
|
|
@@ -5205,26 +5205,26 @@ function filterAndSortRows(rows, columns, columnFilters, sort, globalSearch, any
|
|
|
5205
5205
|
return result;
|
|
5206
5206
|
}
|
|
5207
5207
|
function countActiveColumnFilters(filters) {
|
|
5208
|
-
let
|
|
5208
|
+
let n2 = 0;
|
|
5209
5209
|
for (const f of Object.values(filters)) {
|
|
5210
5210
|
if (!f) continue;
|
|
5211
5211
|
switch (f.kind) {
|
|
5212
5212
|
case "text":
|
|
5213
|
-
if (f.value.trim() || f.mode && f.mode !== "contains")
|
|
5213
|
+
if (f.value.trim() || f.mode && f.mode !== "contains") n2 += 1;
|
|
5214
5214
|
break;
|
|
5215
5215
|
case "select":
|
|
5216
5216
|
if (f.values !== void 0 || f.value && f.value !== "__all__")
|
|
5217
|
-
|
|
5217
|
+
n2 += 1;
|
|
5218
5218
|
break;
|
|
5219
5219
|
case "boolean":
|
|
5220
|
-
|
|
5220
|
+
n2 += 1;
|
|
5221
5221
|
break;
|
|
5222
5222
|
case "number":
|
|
5223
|
-
if (f.min !== void 0 || f.max !== void 0)
|
|
5223
|
+
if (f.min !== void 0 || f.max !== void 0) n2 += 1;
|
|
5224
5224
|
break;
|
|
5225
5225
|
}
|
|
5226
5226
|
}
|
|
5227
|
-
return
|
|
5227
|
+
return n2;
|
|
5228
5228
|
}
|
|
5229
5229
|
function isColumnFilterActive(filter) {
|
|
5230
5230
|
if (!filter) return false;
|
|
@@ -5479,11 +5479,11 @@ import {
|
|
|
5479
5479
|
} from "@ai-matrx/kit/url-state";
|
|
5480
5480
|
function parseSort(raw) {
|
|
5481
5481
|
if (!raw) return null;
|
|
5482
|
-
const
|
|
5483
|
-
if (
|
|
5484
|
-
const direction = raw.slice(
|
|
5482
|
+
const at2 = raw.lastIndexOf(".");
|
|
5483
|
+
if (at2 <= 0) return null;
|
|
5484
|
+
const direction = raw.slice(at2 + 1);
|
|
5485
5485
|
if (direction !== "asc" && direction !== "desc") return null;
|
|
5486
|
-
return { id: raw.slice(0,
|
|
5486
|
+
return { id: raw.slice(0, at2), direction };
|
|
5487
5487
|
}
|
|
5488
5488
|
function parseObject(raw, fallback) {
|
|
5489
5489
|
if (!raw) return fallback;
|
|
@@ -5506,8 +5506,8 @@ function parseLayeredFilters(raw) {
|
|
|
5506
5506
|
}
|
|
5507
5507
|
}
|
|
5508
5508
|
function positiveInt(raw, fallback) {
|
|
5509
|
-
const
|
|
5510
|
-
return Number.isFinite(
|
|
5509
|
+
const n2 = raw ? Number.parseInt(raw, 10) : Number.NaN;
|
|
5510
|
+
return Number.isFinite(n2) && n2 > 0 ? n2 : fallback;
|
|
5511
5511
|
}
|
|
5512
5512
|
function tableUrlParamPrefix(tableId) {
|
|
5513
5513
|
if (!/^[a-z][a-z0-9-]{0,63}$/.test(tableId)) {
|
|
@@ -5708,6 +5708,7 @@ import {
|
|
|
5708
5708
|
forwardRef as forwardRef12,
|
|
5709
5709
|
useEffect as useEffect9,
|
|
5710
5710
|
useMemo as useMemo5,
|
|
5711
|
+
useRef as useRef10,
|
|
5711
5712
|
useState as useState14
|
|
5712
5713
|
} from "react";
|
|
5713
5714
|
import { useDraggable } from "@dnd-kit/core";
|
|
@@ -5855,6 +5856,95 @@ var CommandShortcut = ({
|
|
|
5855
5856
|
};
|
|
5856
5857
|
CommandShortcut.displayName = "CommandShortcut";
|
|
5857
5858
|
|
|
5859
|
+
// src/data-table/facets.ts
|
|
5860
|
+
var MAX_LISTABLE_FACET_LENGTH = 300;
|
|
5861
|
+
var DEFAULT_FACET_LIMIT = 200;
|
|
5862
|
+
var MAX_FACET_LIMIT = 500;
|
|
5863
|
+
function facetText(raw) {
|
|
5864
|
+
if (raw === null || raw === void 0) return "";
|
|
5865
|
+
if (typeof raw === "object") {
|
|
5866
|
+
try {
|
|
5867
|
+
return JSON.stringify(raw);
|
|
5868
|
+
} catch {
|
|
5869
|
+
return String(raw);
|
|
5870
|
+
}
|
|
5871
|
+
}
|
|
5872
|
+
return String(raw);
|
|
5873
|
+
}
|
|
5874
|
+
function computeColumnFacets(args) {
|
|
5875
|
+
const { columnId: columnId2, rows, readValue: readValue2 } = args;
|
|
5876
|
+
const limit = Math.min(Math.max(args.limit ?? DEFAULT_FACET_LIMIT, 1), MAX_FACET_LIMIT);
|
|
5877
|
+
const counts = /* @__PURE__ */ new Map();
|
|
5878
|
+
const longValues = /* @__PURE__ */ new Set();
|
|
5879
|
+
let blank = 0;
|
|
5880
|
+
let maxLength = 0;
|
|
5881
|
+
for (const row of rows) {
|
|
5882
|
+
let raw;
|
|
5883
|
+
try {
|
|
5884
|
+
raw = readValue2(row, columnId2);
|
|
5885
|
+
} catch {
|
|
5886
|
+
raw = void 0;
|
|
5887
|
+
}
|
|
5888
|
+
const trimmed = facetText(raw).trim();
|
|
5889
|
+
if (trimmed === "") {
|
|
5890
|
+
blank += 1;
|
|
5891
|
+
continue;
|
|
5892
|
+
}
|
|
5893
|
+
if (trimmed.length > maxLength) maxLength = trimmed.length;
|
|
5894
|
+
if (trimmed.length > MAX_LISTABLE_FACET_LENGTH) {
|
|
5895
|
+
longValues.add(trimmed);
|
|
5896
|
+
continue;
|
|
5897
|
+
}
|
|
5898
|
+
counts.set(trimmed, (counts.get(trimmed) ?? 0) + 1);
|
|
5899
|
+
}
|
|
5900
|
+
const values = [...counts.entries()].map(([value, count]) => ({ value, count })).sort((a, b) => b.count - a.count || a.value.localeCompare(b.value)).slice(0, limit);
|
|
5901
|
+
return {
|
|
5902
|
+
columnId: columnId2,
|
|
5903
|
+
totalRows: rows.length,
|
|
5904
|
+
filled: rows.length - blank,
|
|
5905
|
+
blank,
|
|
5906
|
+
distinctCount: counts.size + longValues.size,
|
|
5907
|
+
maxLength,
|
|
5908
|
+
unlistable: longValues.size,
|
|
5909
|
+
limit,
|
|
5910
|
+
truncated: counts.size > limit,
|
|
5911
|
+
values,
|
|
5912
|
+
answeredBy: "local",
|
|
5913
|
+
complete: args.complete ?? true
|
|
5914
|
+
};
|
|
5915
|
+
}
|
|
5916
|
+
function localFacetsAreComplete(loadedRowCount, total) {
|
|
5917
|
+
if (total === void 0 || !Number.isFinite(total) || total < 0) return false;
|
|
5918
|
+
return loadedRowCount >= total;
|
|
5919
|
+
}
|
|
5920
|
+
var NUMBERS = new Intl.NumberFormat("en-US");
|
|
5921
|
+
function n(value) {
|
|
5922
|
+
try {
|
|
5923
|
+
return NUMBERS.format(value);
|
|
5924
|
+
} catch {
|
|
5925
|
+
return String(value);
|
|
5926
|
+
}
|
|
5927
|
+
}
|
|
5928
|
+
function describeFacetSource(facets, noun = "row") {
|
|
5929
|
+
if (!facets) return "";
|
|
5930
|
+
const plural2 = `${noun}s`;
|
|
5931
|
+
if (!facets.complete) {
|
|
5932
|
+
return `These counts cover the ${n(facets.totalRows)} ${plural2} loaded here, not the whole table.`;
|
|
5933
|
+
}
|
|
5934
|
+
if (facets.truncated) {
|
|
5935
|
+
return `Showing the ${n(facets.values.length)} most common of ${n(facets.distinctCount)} values.`;
|
|
5936
|
+
}
|
|
5937
|
+
if (facets.unlistable > 0) {
|
|
5938
|
+
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"}.`;
|
|
5939
|
+
}
|
|
5940
|
+
return "";
|
|
5941
|
+
}
|
|
5942
|
+
var FACETS_LOADING_NOTICE = "Counting values\u2026";
|
|
5943
|
+
function describeFacetFailure(error) {
|
|
5944
|
+
const detail = error instanceof Error ? error.message : String(error ?? "");
|
|
5945
|
+
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.";
|
|
5946
|
+
}
|
|
5947
|
+
|
|
5858
5948
|
// src/data-table/column-marker.ts
|
|
5859
5949
|
var MARKER_ACCESSORS = {
|
|
5860
5950
|
favorite: "favorite",
|
|
@@ -5922,6 +6012,10 @@ function ColumnHeaderCell({
|
|
|
5922
6012
|
filterFooterHint,
|
|
5923
6013
|
allowNegation = false,
|
|
5924
6014
|
allowNullModes = false,
|
|
6015
|
+
facets,
|
|
6016
|
+
facetsLoading = false,
|
|
6017
|
+
facetsError,
|
|
6018
|
+
onFilterOpen,
|
|
5925
6019
|
reorderColumn
|
|
5926
6020
|
}) {
|
|
5927
6021
|
const reorderEnabled = reorderColumn !== void 0;
|
|
@@ -5956,6 +6050,11 @@ function ColumnHeaderCell({
|
|
|
5956
6050
|
setPendingNegation(filterValue?.negated ?? false);
|
|
5957
6051
|
}
|
|
5958
6052
|
}, [filterOpen, filterValue]);
|
|
6053
|
+
const notifyOpen = useRef10(onFilterOpen);
|
|
6054
|
+
notifyOpen.current = onFilterOpen;
|
|
6055
|
+
useEffect9(() => {
|
|
6056
|
+
if (filterOpen) notifyOpen.current?.();
|
|
6057
|
+
}, [filterOpen]);
|
|
5959
6058
|
const applyFilter = () => {
|
|
5960
6059
|
onFilterChange(draftFilter);
|
|
5961
6060
|
setFilterOpen(false);
|
|
@@ -6050,6 +6149,9 @@ function ColumnHeaderCell({
|
|
|
6050
6149
|
selectOptions,
|
|
6051
6150
|
selectSingle,
|
|
6052
6151
|
selectAllowCustom,
|
|
6152
|
+
facets: facets ?? null,
|
|
6153
|
+
facetsLoading,
|
|
6154
|
+
...facetsError === void 0 ? {} : { facetsError },
|
|
6053
6155
|
...markerLabels ? {
|
|
6054
6156
|
booleanLabels: {
|
|
6055
6157
|
all: "All",
|
|
@@ -6274,8 +6376,43 @@ function FilterBody({
|
|
|
6274
6376
|
selectSingle = false,
|
|
6275
6377
|
selectAllowCustom = false,
|
|
6276
6378
|
allowNullModes = false,
|
|
6277
|
-
booleanLabels
|
|
6379
|
+
booleanLabels,
|
|
6380
|
+
facets = null,
|
|
6381
|
+
facetsLoading = false,
|
|
6382
|
+
facetsError
|
|
6278
6383
|
}) {
|
|
6384
|
+
const checklist = facetsLoading || facetsError || facets && (facets.values.length > 0 || facets.blank > 0) ? /* @__PURE__ */ jsx31(
|
|
6385
|
+
FacetChecklist,
|
|
6386
|
+
{
|
|
6387
|
+
facets,
|
|
6388
|
+
loading: facetsLoading,
|
|
6389
|
+
...facetsError === void 0 ? {} : { error: facetsError },
|
|
6390
|
+
value,
|
|
6391
|
+
onChange
|
|
6392
|
+
}
|
|
6393
|
+
) : null;
|
|
6394
|
+
if (checklist && kind === "select" && facets && facets.values.length > 0) {
|
|
6395
|
+
return /* @__PURE__ */ jsx31("div", { className: "space-y-2", children: checklist });
|
|
6396
|
+
}
|
|
6397
|
+
if (checklist) {
|
|
6398
|
+
return /* @__PURE__ */ jsxs22("div", { className: "space-y-2", children: [
|
|
6399
|
+
checklist,
|
|
6400
|
+
/* @__PURE__ */ jsx31("div", { className: "h-px bg-border" }),
|
|
6401
|
+
/* @__PURE__ */ jsx31(
|
|
6402
|
+
FilterBody,
|
|
6403
|
+
{
|
|
6404
|
+
kind,
|
|
6405
|
+
value,
|
|
6406
|
+
onChange,
|
|
6407
|
+
selectOptions,
|
|
6408
|
+
selectSingle,
|
|
6409
|
+
selectAllowCustom,
|
|
6410
|
+
allowNullModes,
|
|
6411
|
+
...booleanLabels === void 0 ? {} : { booleanLabels }
|
|
6412
|
+
}
|
|
6413
|
+
)
|
|
6414
|
+
] });
|
|
6415
|
+
}
|
|
6279
6416
|
if (kind === "text") {
|
|
6280
6417
|
const text = value?.kind === "text" ? value.value : "";
|
|
6281
6418
|
const mode = (value?.kind === "text" ? value.mode : void 0) ?? "contains";
|
|
@@ -6386,6 +6523,112 @@ function FilterBody({
|
|
|
6386
6523
|
}
|
|
6387
6524
|
return /* @__PURE__ */ jsx31(NumberFilterBody, { value, onChange });
|
|
6388
6525
|
}
|
|
6526
|
+
function FacetChecklist({
|
|
6527
|
+
facets,
|
|
6528
|
+
loading,
|
|
6529
|
+
error,
|
|
6530
|
+
value,
|
|
6531
|
+
onChange
|
|
6532
|
+
}) {
|
|
6533
|
+
const [query, setQuery] = useState14("");
|
|
6534
|
+
const selected = value?.kind === "select" ? value.values ?? (value.value && value.value !== "__all__" ? [value.value] : []) : [];
|
|
6535
|
+
const selectedSet = new Set(selected);
|
|
6536
|
+
const rows = useMemo5(() => {
|
|
6537
|
+
if (!facets) return [];
|
|
6538
|
+
const listed = facets.values.map((entry) => ({
|
|
6539
|
+
value: entry.value,
|
|
6540
|
+
label: entry.value,
|
|
6541
|
+
count: entry.count
|
|
6542
|
+
}));
|
|
6543
|
+
const withBlank = facets.blank > 0 ? [{ value: "", label: "(empty)", count: facets.blank }, ...listed] : listed;
|
|
6544
|
+
const q = query.trim().toLowerCase();
|
|
6545
|
+
if (!q) return withBlank;
|
|
6546
|
+
return withBlank.filter((row) => row.label.toLowerCase().includes(q));
|
|
6547
|
+
}, [facets, query]);
|
|
6548
|
+
const toggle = (candidate) => {
|
|
6549
|
+
const next = new Set(selectedSet);
|
|
6550
|
+
if (next.has(candidate)) next.delete(candidate);
|
|
6551
|
+
else next.add(candidate);
|
|
6552
|
+
const values = [...next];
|
|
6553
|
+
onChange(
|
|
6554
|
+
values.length === 0 ? void 0 : { kind: "select", value: values[0] ?? "", values }
|
|
6555
|
+
);
|
|
6556
|
+
};
|
|
6557
|
+
const notice = error ?? (loading ? FACETS_LOADING_NOTICE : describeFacetSource(facets));
|
|
6558
|
+
return /* @__PURE__ */ jsxs22("div", { className: "space-y-1.5", children: [
|
|
6559
|
+
/* @__PURE__ */ jsx31("p", { className: "px-1 text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: "Values" }),
|
|
6560
|
+
facets && facets.values.length + (facets.blank > 0 ? 1 : 0) > 8 ? /* @__PURE__ */ jsx31(
|
|
6561
|
+
Input,
|
|
6562
|
+
{
|
|
6563
|
+
"data-matrx-filter-autofocus": true,
|
|
6564
|
+
value: query,
|
|
6565
|
+
onChange: (event) => setQuery(event.target.value),
|
|
6566
|
+
placeholder: "Find a value\u2026",
|
|
6567
|
+
className: "h-7 text-sm",
|
|
6568
|
+
style: { fontSize: "16px" }
|
|
6569
|
+
}
|
|
6570
|
+
) : null,
|
|
6571
|
+
rows.length > 0 ? /* @__PURE__ */ jsx31("ul", { className: "max-h-56 space-y-0.5 overflow-y-auto", "data-matrx-facet-list": "true", children: rows.map((row) => {
|
|
6572
|
+
const checked = selectedSet.has(row.value);
|
|
6573
|
+
return /* @__PURE__ */ jsx31("li", { children: /* @__PURE__ */ jsxs22(
|
|
6574
|
+
"button",
|
|
6575
|
+
{
|
|
6576
|
+
type: "button",
|
|
6577
|
+
role: "checkbox",
|
|
6578
|
+
"aria-checked": checked,
|
|
6579
|
+
"data-matrx-facet-value": row.value === "" ? "__blank__" : row.value,
|
|
6580
|
+
onClick: () => toggle(row.value),
|
|
6581
|
+
className: cn(
|
|
6582
|
+
"flex w-full items-center gap-2 rounded px-1.5 py-1 text-left text-xs hover:bg-muted",
|
|
6583
|
+
checked && "bg-primary/10"
|
|
6584
|
+
),
|
|
6585
|
+
children: [
|
|
6586
|
+
/* @__PURE__ */ jsx31(
|
|
6587
|
+
"span",
|
|
6588
|
+
{
|
|
6589
|
+
"aria-hidden": true,
|
|
6590
|
+
className: cn(
|
|
6591
|
+
"flex h-3.5 w-3.5 shrink-0 items-center justify-center rounded-[3px] border",
|
|
6592
|
+
checked ? "border-primary bg-primary text-primary-foreground" : "border-border"
|
|
6593
|
+
),
|
|
6594
|
+
children: checked ? /* @__PURE__ */ jsx31(Check, { className: "h-2.5 w-2.5" }) : null
|
|
6595
|
+
}
|
|
6596
|
+
),
|
|
6597
|
+
/* @__PURE__ */ jsx31("span", { className: cn("min-w-0 flex-1 truncate", row.value === "" && "italic text-muted-foreground"), children: row.label }),
|
|
6598
|
+
/* @__PURE__ */ jsx31(
|
|
6599
|
+
"span",
|
|
6600
|
+
{
|
|
6601
|
+
"data-matrx-facet-count": String(row.count),
|
|
6602
|
+
className: "shrink-0 tabular-nums text-[11px] text-muted-foreground",
|
|
6603
|
+
children: row.count.toLocaleString("en-US")
|
|
6604
|
+
}
|
|
6605
|
+
)
|
|
6606
|
+
]
|
|
6607
|
+
}
|
|
6608
|
+
) }, row.value === "" ? "__blank__" : row.value);
|
|
6609
|
+
}) }) : loading ? null : /* @__PURE__ */ jsx31("p", { className: "px-1 text-[11px] text-muted-foreground", children: query.trim() ? "No value matches that." : "This column has no values yet." }),
|
|
6610
|
+
notice ? /* @__PURE__ */ jsx31(
|
|
6611
|
+
"p",
|
|
6612
|
+
{
|
|
6613
|
+
"data-matrx-facet-notice": "true",
|
|
6614
|
+
className: cn(
|
|
6615
|
+
"px-1 text-[11px] leading-snug",
|
|
6616
|
+
error ? "text-amber-700 dark:text-amber-400" : "text-muted-foreground"
|
|
6617
|
+
),
|
|
6618
|
+
children: notice
|
|
6619
|
+
}
|
|
6620
|
+
) : null,
|
|
6621
|
+
selected.length > 0 ? /* @__PURE__ */ jsx31(
|
|
6622
|
+
"button",
|
|
6623
|
+
{
|
|
6624
|
+
type: "button",
|
|
6625
|
+
onClick: () => onChange(void 0),
|
|
6626
|
+
className: "px-1 text-[11px] text-muted-foreground underline-offset-2 hover:underline",
|
|
6627
|
+
children: "Clear selection"
|
|
6628
|
+
}
|
|
6629
|
+
) : null
|
|
6630
|
+
] });
|
|
6631
|
+
}
|
|
6389
6632
|
function SearchableSelectFilter({
|
|
6390
6633
|
selected,
|
|
6391
6634
|
options,
|
|
@@ -6572,15 +6815,15 @@ function NumberFilterBody({
|
|
|
6572
6815
|
}
|
|
6573
6816
|
function parseOptionalNumber(raw) {
|
|
6574
6817
|
if (raw.trim() === "") return void 0;
|
|
6575
|
-
const
|
|
6576
|
-
return Number.isFinite(
|
|
6818
|
+
const n2 = Number(raw.replace(/[^0-9.-]/g, ""));
|
|
6819
|
+
return Number.isFinite(n2) ? n2 : void 0;
|
|
6577
6820
|
}
|
|
6578
6821
|
|
|
6579
6822
|
// src/data-table/ColumnResizeHandle.tsx
|
|
6580
6823
|
import {
|
|
6581
6824
|
useCallback as useCallback6,
|
|
6582
6825
|
useEffect as useEffect10,
|
|
6583
|
-
useRef as
|
|
6826
|
+
useRef as useRef11,
|
|
6584
6827
|
useState as useState15
|
|
6585
6828
|
} from "react";
|
|
6586
6829
|
|
|
@@ -6624,11 +6867,11 @@ function ColumnResizeHandle({
|
|
|
6624
6867
|
onResizeCancel,
|
|
6625
6868
|
onResizeCommit
|
|
6626
6869
|
}) {
|
|
6627
|
-
const handleRef =
|
|
6628
|
-
const activeResizeRef =
|
|
6629
|
-
const previewRafRef =
|
|
6630
|
-
const queuedWidthRef =
|
|
6631
|
-
const keyboardWidthRef =
|
|
6870
|
+
const handleRef = useRef11(null);
|
|
6871
|
+
const activeResizeRef = useRef11(null);
|
|
6872
|
+
const previewRafRef = useRef11(null);
|
|
6873
|
+
const queuedWidthRef = useRef11(null);
|
|
6874
|
+
const keyboardWidthRef = useRef11(null);
|
|
6632
6875
|
const [announcedWidth, setAnnouncedWidth] = useState15(null);
|
|
6633
6876
|
const bounds = resolveColumnResizeBounds(minWidth, maxWidth);
|
|
6634
6877
|
const cssVar = columnResizeCssVar(columnId2);
|
|
@@ -6771,115 +7014,1768 @@ function projectColumnDragOrder(orderedIds, preview2) {
|
|
|
6771
7014
|
return order;
|
|
6772
7015
|
}
|
|
6773
7016
|
|
|
6774
|
-
// src/data-table/
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
if (/^(description|summary|details|notes|blurb)$/.test(key) || key.endsWith("_description")) return "description";
|
|
6780
|
-
return "other";
|
|
7017
|
+
// src/data-table/grouping.ts
|
|
7018
|
+
var EMPTY_GROUP_KEY = "empty";
|
|
7019
|
+
var DEFAULT_EMPTY_LABEL = "(empty)";
|
|
7020
|
+
function isBlankGroupValue(value) {
|
|
7021
|
+
return value === null || value === void 0 || value === "";
|
|
6781
7022
|
}
|
|
6782
|
-
function
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
7023
|
+
function groupKeyOf(value) {
|
|
7024
|
+
if (isBlankGroupValue(value)) return EMPTY_GROUP_KEY;
|
|
7025
|
+
switch (typeof value) {
|
|
7026
|
+
case "string":
|
|
7027
|
+
return `s:${value}`;
|
|
7028
|
+
case "number":
|
|
7029
|
+
return `n:${String(value)}`;
|
|
7030
|
+
case "boolean":
|
|
7031
|
+
return `b:${value ? "true" : "false"}`;
|
|
7032
|
+
case "bigint":
|
|
7033
|
+
return `i:${String(value)}`;
|
|
7034
|
+
case "symbol":
|
|
7035
|
+
return `y:${String(value)}`;
|
|
7036
|
+
case "function":
|
|
7037
|
+
return `f:${safeString(value)}`;
|
|
7038
|
+
default:
|
|
7039
|
+
break;
|
|
6786
7040
|
}
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
}
|
|
7041
|
+
if (value instanceof Date) {
|
|
7042
|
+
const time = value.getTime();
|
|
7043
|
+
return `d:${Number.isFinite(time) ? value.toISOString() : "invalid"}`;
|
|
6791
7044
|
}
|
|
6792
|
-
return
|
|
7045
|
+
return `o:${safeJson(value)}`;
|
|
6793
7046
|
}
|
|
6794
|
-
function
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
for (const [id, label] of [["id", "ID"], ["name", "Name"], ["description", "Description"]]) {
|
|
6800
|
-
if (roles.has(id)) scopes.push({ id, label });
|
|
7047
|
+
function safeString(value) {
|
|
7048
|
+
try {
|
|
7049
|
+
return String(value);
|
|
7050
|
+
} catch {
|
|
7051
|
+
return "[unreadable]";
|
|
6801
7052
|
}
|
|
6802
|
-
for (const scope of options.scopes ?? []) if (!scopes.some((s) => s.id === scope.id) && scope.fields?.length) scopes.push(scope);
|
|
6803
|
-
return scopes;
|
|
6804
7053
|
}
|
|
6805
|
-
function
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
|
|
6822
|
-
|
|
6823
|
-
|
|
6824
|
-
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
7054
|
+
function safeJson(value) {
|
|
7055
|
+
try {
|
|
7056
|
+
const json = JSON.stringify(value);
|
|
7057
|
+
return typeof json === "string" ? json : safeString(value);
|
|
7058
|
+
} catch {
|
|
7059
|
+
return safeString(value);
|
|
7060
|
+
}
|
|
7061
|
+
}
|
|
7062
|
+
var CURRENCY_AND_SPACE = /[\s,$£€¥]/g;
|
|
7063
|
+
function coerceGroupNumber(value) {
|
|
7064
|
+
if (isBlankGroupValue(value)) return null;
|
|
7065
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
7066
|
+
if (typeof value === "boolean") return value ? 1 : 0;
|
|
7067
|
+
if (typeof value === "bigint") {
|
|
7068
|
+
const asNumber = Number(value);
|
|
7069
|
+
return Number.isFinite(asNumber) ? asNumber : null;
|
|
7070
|
+
}
|
|
7071
|
+
if (typeof value !== "string") return null;
|
|
7072
|
+
const cleaned = value.replace(CURRENCY_AND_SPACE, "");
|
|
7073
|
+
if (cleaned === "" || cleaned === "-" || cleaned === "+") return null;
|
|
7074
|
+
const parsed = Number(cleaned);
|
|
7075
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
7076
|
+
}
|
|
7077
|
+
var NUMBER_FORMAT = new Intl.NumberFormat("en-US", { maximumFractionDigits: 2 });
|
|
7078
|
+
function formatGroupNumber(value) {
|
|
7079
|
+
if (!Number.isFinite(value)) return "\u2014";
|
|
7080
|
+
try {
|
|
7081
|
+
return NUMBER_FORMAT.format(value);
|
|
7082
|
+
} catch {
|
|
7083
|
+
return String(value);
|
|
7084
|
+
}
|
|
7085
|
+
}
|
|
7086
|
+
function defaultLabelOf(value, emptyLabel) {
|
|
7087
|
+
if (isBlankGroupValue(value)) return emptyLabel;
|
|
7088
|
+
if (typeof value === "string") return value;
|
|
7089
|
+
if (typeof value === "number") return formatGroupNumber(value);
|
|
7090
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
7091
|
+
if (value instanceof Date) {
|
|
7092
|
+
const time = value.getTime();
|
|
7093
|
+
return Number.isFinite(time) ? value.toISOString() : "Invalid Date";
|
|
7094
|
+
}
|
|
7095
|
+
if (typeof value === "object") return safeJson(value);
|
|
7096
|
+
return safeString(value);
|
|
7097
|
+
}
|
|
7098
|
+
var AGGREGATE_NAMES = {
|
|
7099
|
+
count: { name: "Count", position: "before" },
|
|
7100
|
+
sum: { name: "Sum", position: "before" },
|
|
7101
|
+
average: { name: "Average", position: "before" },
|
|
7102
|
+
min: { name: "Min", position: "before" },
|
|
7103
|
+
max: { name: "Max", position: "before" },
|
|
7104
|
+
empty: { name: "empty", position: "after" },
|
|
7105
|
+
filled: { name: "filled", position: "after" },
|
|
7106
|
+
unique: { name: "unique", position: "after" },
|
|
7107
|
+
checked: { name: "checked", position: "after" },
|
|
7108
|
+
unchecked: { name: "unchecked", position: "after" },
|
|
7109
|
+
percentFilled: { name: "filled", position: "after" }
|
|
7110
|
+
};
|
|
7111
|
+
function aggregateLabel(kind, value, override) {
|
|
7112
|
+
const naming = AGGREGATE_NAMES[kind] ?? { name: kind, position: "before" };
|
|
7113
|
+
const name = override && override.trim() !== "" ? override : naming.name;
|
|
7114
|
+
const shown = value === null ? "\u2014" : kind === "percentFilled" ? `${formatGroupNumber(value)}%` : formatGroupNumber(value);
|
|
7115
|
+
return naming.position === "before" ? `${name} ${shown}` : `${shown} ${name}`;
|
|
7116
|
+
}
|
|
7117
|
+
function readValue(row, reader) {
|
|
7118
|
+
try {
|
|
7119
|
+
return reader(row);
|
|
7120
|
+
} catch {
|
|
7121
|
+
return null;
|
|
7122
|
+
}
|
|
7123
|
+
}
|
|
7124
|
+
function computeAggregate(rows, column) {
|
|
7125
|
+
const kind = column.spec.kind;
|
|
7126
|
+
const raw = rows.map((row) => readValue(row, column.readCell));
|
|
7127
|
+
const total = raw.length;
|
|
7128
|
+
const filled = raw.filter((value2) => !isBlankGroupValue(value2));
|
|
7129
|
+
const numbers = filled.map((value2) => coerceGroupNumber(value2)).filter((value2) => value2 !== null);
|
|
7130
|
+
let value;
|
|
7131
|
+
switch (kind) {
|
|
7132
|
+
case "count":
|
|
7133
|
+
value = total;
|
|
7134
|
+
break;
|
|
7135
|
+
case "sum":
|
|
7136
|
+
value = numbers.length === 0 ? null : numbers.reduce((acc, n2) => acc + n2, 0);
|
|
7137
|
+
break;
|
|
7138
|
+
case "average":
|
|
7139
|
+
value = numbers.length === 0 ? null : numbers.reduce((acc, n2) => acc + n2, 0) / numbers.length;
|
|
7140
|
+
break;
|
|
7141
|
+
case "min":
|
|
7142
|
+
value = numbers.length === 0 ? null : numbers.reduce((acc, n2) => n2 < acc ? n2 : acc);
|
|
7143
|
+
break;
|
|
7144
|
+
case "max":
|
|
7145
|
+
value = numbers.length === 0 ? null : numbers.reduce((acc, n2) => n2 > acc ? n2 : acc);
|
|
7146
|
+
break;
|
|
7147
|
+
case "empty":
|
|
7148
|
+
value = total - filled.length;
|
|
7149
|
+
break;
|
|
7150
|
+
case "filled":
|
|
7151
|
+
value = filled.length;
|
|
7152
|
+
break;
|
|
7153
|
+
case "unique": {
|
|
7154
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7155
|
+
for (const entry of filled) seen.add(groupKeyOf(entry));
|
|
7156
|
+
value = seen.size;
|
|
7157
|
+
break;
|
|
6828
7158
|
}
|
|
6829
|
-
|
|
6830
|
-
|
|
7159
|
+
case "checked":
|
|
7160
|
+
value = filled.filter((entry) => entry === true).length;
|
|
7161
|
+
break;
|
|
7162
|
+
case "unchecked":
|
|
7163
|
+
value = filled.filter((entry) => entry === false).length;
|
|
7164
|
+
break;
|
|
7165
|
+
case "percentFilled":
|
|
7166
|
+
value = total === 0 ? null : filled.length / total * 100;
|
|
7167
|
+
break;
|
|
7168
|
+
default:
|
|
7169
|
+
value = null;
|
|
7170
|
+
break;
|
|
7171
|
+
}
|
|
7172
|
+
return { kind, value, label: aggregateLabel(kind, value, column.spec.label) };
|
|
7173
|
+
}
|
|
7174
|
+
function compareLabels(a, b) {
|
|
7175
|
+
if (a === b) return 0;
|
|
7176
|
+
return a < b ? -1 : 1;
|
|
7177
|
+
}
|
|
7178
|
+
function compareValues2(a, b) {
|
|
7179
|
+
const aNumber = typeof a.value === "number" ? a.value : null;
|
|
7180
|
+
const bNumber = typeof b.value === "number" ? b.value : null;
|
|
7181
|
+
if (aNumber !== null && bNumber !== null && aNumber !== bNumber) return aNumber < bNumber ? -1 : 1;
|
|
7182
|
+
if (typeof a.value === "boolean" && typeof b.value === "boolean" && a.value !== b.value) {
|
|
7183
|
+
return a.value ? 1 : -1;
|
|
7184
|
+
}
|
|
7185
|
+
return compareLabels(a.label, b.label);
|
|
7186
|
+
}
|
|
7187
|
+
function groupRows(options) {
|
|
7188
|
+
const rows = Array.isArray(options.rows) ? options.rows : [];
|
|
7189
|
+
const emptyLabel = options.emptyLabel ?? DEFAULT_EMPTY_LABEL;
|
|
7190
|
+
const order = options.order ?? "value-asc";
|
|
7191
|
+
const aggregates = options.aggregates ?? {};
|
|
7192
|
+
const labelFor = (value) => {
|
|
7193
|
+
if (!options.labelOf) return defaultLabelOf(value, emptyLabel);
|
|
7194
|
+
if (isBlankGroupValue(value)) {
|
|
7195
|
+
try {
|
|
7196
|
+
const custom = options.labelOf(value);
|
|
7197
|
+
return typeof custom === "string" && custom !== "" ? custom : emptyLabel;
|
|
7198
|
+
} catch {
|
|
7199
|
+
return emptyLabel;
|
|
7200
|
+
}
|
|
7201
|
+
}
|
|
7202
|
+
try {
|
|
7203
|
+
const custom = options.labelOf(value);
|
|
7204
|
+
return typeof custom === "string" ? custom : defaultLabelOf(value, emptyLabel);
|
|
7205
|
+
} catch {
|
|
7206
|
+
return defaultLabelOf(value, emptyLabel);
|
|
7207
|
+
}
|
|
7208
|
+
};
|
|
7209
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
7210
|
+
for (const row of rows) {
|
|
7211
|
+
const raw = readValue(row, options.readCell);
|
|
7212
|
+
const blank = isBlankGroupValue(raw);
|
|
7213
|
+
const value = blank ? null : raw;
|
|
7214
|
+
const key = groupKeyOf(value);
|
|
7215
|
+
let bucket = buckets.get(key);
|
|
7216
|
+
if (!bucket) {
|
|
7217
|
+
bucket = { key, value, label: labelFor(value), rows: [], seen: buckets.size };
|
|
7218
|
+
buckets.set(key, bucket);
|
|
7219
|
+
}
|
|
7220
|
+
bucket.rows.push(row);
|
|
7221
|
+
}
|
|
7222
|
+
const ordered = [...buckets.values()].sort((a, b) => {
|
|
7223
|
+
const aBlank = a.key === EMPTY_GROUP_KEY;
|
|
7224
|
+
const bBlank = b.key === EMPTY_GROUP_KEY;
|
|
7225
|
+
if (aBlank !== bBlank) return aBlank ? 1 : -1;
|
|
7226
|
+
if (aBlank && bBlank) return 0;
|
|
7227
|
+
switch (order) {
|
|
7228
|
+
case "value-asc":
|
|
7229
|
+
return compareValues2(a, b) || a.seen - b.seen;
|
|
7230
|
+
case "value-desc":
|
|
7231
|
+
return -compareValues2(a, b) || a.seen - b.seen;
|
|
7232
|
+
case "count-desc":
|
|
7233
|
+
return b.rows.length - a.rows.length || a.seen - b.seen;
|
|
7234
|
+
case "first-seen":
|
|
7235
|
+
default:
|
|
7236
|
+
return a.seen - b.seen;
|
|
7237
|
+
}
|
|
7238
|
+
});
|
|
7239
|
+
const aggregateEntries = Object.entries(aggregates);
|
|
7240
|
+
return ordered.map((bucket, index) => {
|
|
7241
|
+
const results = {};
|
|
7242
|
+
for (const [columnId2, column] of aggregateEntries) {
|
|
7243
|
+
if (!column || typeof column.readCell !== "function" || !column.spec) continue;
|
|
7244
|
+
results[columnId2] = computeAggregate(bucket.rows, column);
|
|
7245
|
+
}
|
|
7246
|
+
return {
|
|
7247
|
+
key: bucket.key,
|
|
7248
|
+
value: bucket.value,
|
|
7249
|
+
label: bucket.label,
|
|
7250
|
+
rows: bucket.rows,
|
|
7251
|
+
aggregates: results,
|
|
7252
|
+
index
|
|
7253
|
+
};
|
|
7254
|
+
});
|
|
7255
|
+
}
|
|
7256
|
+
function toggleGroupCollapsed(collapsed, key) {
|
|
7257
|
+
const list = Array.isArray(collapsed) ? collapsed : [];
|
|
7258
|
+
return list.includes(key) ? list.filter((entry) => entry !== key) : [...list, key];
|
|
7259
|
+
}
|
|
7260
|
+
function isGroupCollapsed(collapsed, key) {
|
|
7261
|
+
return Array.isArray(collapsed) ? collapsed.includes(key) : false;
|
|
7262
|
+
}
|
|
7263
|
+
function flattenGroups(groups, collapsed) {
|
|
7264
|
+
const out = [];
|
|
7265
|
+
let dataIndex = 0;
|
|
7266
|
+
for (const group of Array.isArray(groups) ? groups : []) {
|
|
7267
|
+
out.push({ kind: "group", group });
|
|
7268
|
+
if (isGroupCollapsed(collapsed, group.key)) continue;
|
|
7269
|
+
for (const row of group.rows) {
|
|
7270
|
+
out.push({ kind: "row", group, row, dataIndex });
|
|
7271
|
+
dataIndex += 1;
|
|
7272
|
+
}
|
|
7273
|
+
}
|
|
7274
|
+
return out;
|
|
7275
|
+
}
|
|
7276
|
+
function groupSummary(group, rowNoun = "row") {
|
|
7277
|
+
const count = group?.rows?.length ?? 0;
|
|
7278
|
+
const noun = count === 1 ? rowNoun : `${rowNoun}s`;
|
|
7279
|
+
const parts = [`${formatGroupNumber(count)} ${noun}`];
|
|
7280
|
+
for (const result of Object.values(group?.aggregates ?? {})) {
|
|
7281
|
+
if (result?.label) parts.push(result.label);
|
|
7282
|
+
}
|
|
7283
|
+
return parts.join(" \xB7 ");
|
|
6831
7284
|
}
|
|
6832
7285
|
|
|
6833
|
-
// src/data-table/
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
|
|
7286
|
+
// src/data-table/virtual-window.ts
|
|
7287
|
+
var DEFAULT_OVERSCAN = 6;
|
|
7288
|
+
function isNum(value) {
|
|
7289
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
7290
|
+
}
|
|
7291
|
+
function toCount(value) {
|
|
7292
|
+
return isNum(value) && value > 0 ? Math.floor(value) : 0;
|
|
7293
|
+
}
|
|
7294
|
+
function toLength(value) {
|
|
7295
|
+
return isNum(value) && value > 0 ? value : 0;
|
|
7296
|
+
}
|
|
7297
|
+
function toOverscan(value) {
|
|
7298
|
+
if (!isNum(value)) return DEFAULT_OVERSCAN;
|
|
7299
|
+
return value > 0 ? Math.floor(value) : 0;
|
|
7300
|
+
}
|
|
7301
|
+
function toPinned(value, count) {
|
|
7302
|
+
if (!isNum(value) || value <= 0) return 0;
|
|
7303
|
+
return Math.min(Math.floor(value), count);
|
|
7304
|
+
}
|
|
7305
|
+
function assemble(args) {
|
|
7306
|
+
const { pinnedCount, start, end, padStart, body, total } = args;
|
|
7307
|
+
let padEnd = total - (padStart + body);
|
|
7308
|
+
if (!Number.isFinite(padEnd)) padEnd = 0;
|
|
7309
|
+
const sum = padStart + body + padEnd;
|
|
7310
|
+
if (sum !== total) padEnd = padEnd + (total - sum);
|
|
7311
|
+
const pinned = [];
|
|
7312
|
+
for (let i = 0; i < pinnedCount; i += 1) pinned.push(i);
|
|
7313
|
+
return { start, end, padStart, padEnd, total, pinned };
|
|
7314
|
+
}
|
|
7315
|
+
function emptyWindow(pinnedCount) {
|
|
7316
|
+
const pinned = [];
|
|
7317
|
+
for (let i = 0; i < pinnedCount; i += 1) pinned.push(i);
|
|
7318
|
+
return { start: pinnedCount, end: pinnedCount, padStart: 0, padEnd: 0, total: 0, pinned };
|
|
7319
|
+
}
|
|
7320
|
+
function band(firstVisible, lastVisible, scrollCount, overscan) {
|
|
7321
|
+
let first = firstVisible;
|
|
7322
|
+
if (first > scrollCount - 1) first = scrollCount - 1;
|
|
7323
|
+
if (first < 0) first = 0;
|
|
7324
|
+
let last = lastVisible;
|
|
7325
|
+
if (last < first + 1) last = first + 1;
|
|
7326
|
+
if (last > scrollCount) last = scrollCount;
|
|
7327
|
+
const start = Math.max(0, first - overscan);
|
|
7328
|
+
let end = Math.min(scrollCount, last + overscan);
|
|
7329
|
+
if (end < start) end = start;
|
|
7330
|
+
return { start, end };
|
|
7331
|
+
}
|
|
7332
|
+
function computeWindow(input) {
|
|
7333
|
+
const count = toCount(input?.count);
|
|
7334
|
+
const pinnedCount = toPinned(input?.pinnedStart, count);
|
|
7335
|
+
if (count <= 0) return emptyWindow(0);
|
|
7336
|
+
const itemSize = toLength(input?.itemSize);
|
|
7337
|
+
const viewport = toLength(input?.viewport);
|
|
7338
|
+
const overscan = toOverscan(input?.overscan);
|
|
7339
|
+
const scrollCount = count - pinnedCount;
|
|
7340
|
+
if (scrollCount <= 0) return emptyWindow(pinnedCount);
|
|
7341
|
+
if (itemSize <= 0) {
|
|
7342
|
+
return assemble({ pinnedCount, start: pinnedCount, end: count, padStart: 0, body: 0, total: 0 });
|
|
7343
|
+
}
|
|
7344
|
+
const total = scrollCount * itemSize;
|
|
7345
|
+
const maxOffset = Math.max(0, total - viewport);
|
|
7346
|
+
const offset = Math.min(toLength(input?.offset), maxOffset);
|
|
7347
|
+
const { start: relStart, end: relEnd } = band(
|
|
7348
|
+
Math.floor(offset / itemSize),
|
|
7349
|
+
Math.ceil((offset + viewport) / itemSize),
|
|
7350
|
+
scrollCount,
|
|
7351
|
+
overscan
|
|
6848
7352
|
);
|
|
6849
|
-
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
|
|
6853
|
-
|
|
6854
|
-
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
7353
|
+
return assemble({
|
|
7354
|
+
pinnedCount,
|
|
7355
|
+
start: pinnedCount + relStart,
|
|
7356
|
+
end: pinnedCount + relEnd,
|
|
7357
|
+
padStart: relStart * itemSize,
|
|
7358
|
+
body: (relEnd - relStart) * itemSize,
|
|
7359
|
+
total
|
|
7360
|
+
});
|
|
7361
|
+
}
|
|
7362
|
+
var PREFIX_CACHE = /* @__PURE__ */ new WeakMap();
|
|
7363
|
+
function prefixFor(sizeAt, count) {
|
|
7364
|
+
let byCount = PREFIX_CACHE.get(sizeAt);
|
|
7365
|
+
if (!byCount) {
|
|
7366
|
+
byCount = /* @__PURE__ */ new Map();
|
|
7367
|
+
PREFIX_CACHE.set(sizeAt, byCount);
|
|
7368
|
+
}
|
|
7369
|
+
const cached = byCount.get(count);
|
|
7370
|
+
if (cached) return cached;
|
|
7371
|
+
const prefix = new Float64Array(count + 1);
|
|
7372
|
+
let running = 0;
|
|
7373
|
+
for (let i = 0; i < count; i += 1) {
|
|
7374
|
+
let size = 0;
|
|
7375
|
+
try {
|
|
7376
|
+
size = sizeAt(i);
|
|
7377
|
+
} catch {
|
|
7378
|
+
size = 0;
|
|
7379
|
+
}
|
|
7380
|
+
running += isNum(size) && size > 0 ? size : 0;
|
|
7381
|
+
prefix[i + 1] = running;
|
|
7382
|
+
}
|
|
7383
|
+
byCount.set(count, prefix);
|
|
7384
|
+
return prefix;
|
|
7385
|
+
}
|
|
7386
|
+
function at(prefix, index) {
|
|
7387
|
+
return prefix[index] ?? 0;
|
|
7388
|
+
}
|
|
7389
|
+
function lastAtOrBefore(prefix, lo, hi, target) {
|
|
7390
|
+
let a = lo;
|
|
7391
|
+
let b = hi;
|
|
7392
|
+
while (a < b) {
|
|
7393
|
+
const mid = a + Math.ceil((b - a) / 2);
|
|
7394
|
+
if (at(prefix, mid) <= target) a = mid;
|
|
7395
|
+
else b = mid - 1;
|
|
7396
|
+
}
|
|
7397
|
+
return a;
|
|
7398
|
+
}
|
|
7399
|
+
function firstAtOrAfter(prefix, lo, hi, target) {
|
|
7400
|
+
let a = lo;
|
|
7401
|
+
let b = hi;
|
|
7402
|
+
while (a < b) {
|
|
7403
|
+
const mid = a + Math.floor((b - a) / 2);
|
|
7404
|
+
if (at(prefix, mid) >= target) b = mid;
|
|
7405
|
+
else a = mid + 1;
|
|
7406
|
+
}
|
|
7407
|
+
return a;
|
|
7408
|
+
}
|
|
7409
|
+
function computeVariableWindow(input) {
|
|
7410
|
+
const count = toCount(input?.count);
|
|
7411
|
+
const pinnedCount = toPinned(input?.pinnedStart, count);
|
|
7412
|
+
if (count <= 0) return emptyWindow(0);
|
|
7413
|
+
const sizeAt = typeof input?.sizeAt === "function" ? input.sizeAt : () => 0;
|
|
7414
|
+
const viewport = toLength(input?.viewport);
|
|
7415
|
+
const overscan = toOverscan(input?.overscan);
|
|
7416
|
+
const scrollCount = count - pinnedCount;
|
|
7417
|
+
if (scrollCount <= 0) return emptyWindow(pinnedCount);
|
|
7418
|
+
const prefix = prefixFor(sizeAt, count);
|
|
7419
|
+
const pinnedLength = at(prefix, pinnedCount);
|
|
7420
|
+
const total = at(prefix, count) - pinnedLength;
|
|
7421
|
+
if (total <= 0) {
|
|
7422
|
+
return assemble({ pinnedCount, start: pinnedCount, end: count, padStart: 0, body: 0, total: total > 0 ? total : 0 });
|
|
7423
|
+
}
|
|
7424
|
+
const maxOffset = Math.max(0, total - viewport);
|
|
7425
|
+
const offset = Math.min(toLength(input?.offset), maxOffset);
|
|
7426
|
+
const firstVisible = lastAtOrBefore(prefix, pinnedCount, count, pinnedLength + offset) - pinnedCount;
|
|
7427
|
+
const lastVisible = firstAtOrAfter(prefix, pinnedCount, count, pinnedLength + offset + viewport) - pinnedCount;
|
|
7428
|
+
const { start: relStart, end: relEnd } = band(firstVisible, lastVisible, scrollCount, overscan);
|
|
7429
|
+
const absStart = pinnedCount + relStart;
|
|
7430
|
+
const absEnd = pinnedCount + relEnd;
|
|
7431
|
+
return assemble({
|
|
7432
|
+
pinnedCount,
|
|
7433
|
+
start: absStart,
|
|
7434
|
+
end: absEnd,
|
|
7435
|
+
padStart: at(prefix, absStart) - pinnedLength,
|
|
7436
|
+
body: at(prefix, absEnd) - at(prefix, absStart),
|
|
7437
|
+
total
|
|
7438
|
+
});
|
|
7439
|
+
}
|
|
7440
|
+
function scrollOffsetForIndex(input) {
|
|
7441
|
+
const count = toCount(input?.count);
|
|
7442
|
+
if (count <= 0) return null;
|
|
7443
|
+
const pinnedCount = toPinned(input?.pinnedStart, count);
|
|
7444
|
+
const itemSize = toLength(input?.itemSize);
|
|
7445
|
+
const viewport = toLength(input?.viewport);
|
|
7446
|
+
const scrollCount = count - pinnedCount;
|
|
7447
|
+
if (scrollCount <= 0 || itemSize <= 0) return null;
|
|
7448
|
+
const rawIndex = isNum(input?.index) ? Math.floor(input.index) : 0;
|
|
7449
|
+
const index = Math.min(Math.max(rawIndex, 0), count - 1);
|
|
7450
|
+
if (index < pinnedCount) return null;
|
|
7451
|
+
const total = scrollCount * itemSize;
|
|
7452
|
+
const maxOffset = Math.max(0, total - viewport);
|
|
7453
|
+
const offset = Math.min(toLength(input?.offset), maxOffset);
|
|
7454
|
+
const itemStart = (index - pinnedCount) * itemSize;
|
|
7455
|
+
const itemEnd = itemStart + itemSize;
|
|
7456
|
+
if (itemStart >= offset && itemEnd <= offset + viewport) return null;
|
|
7457
|
+
const next = itemStart < offset ? itemStart : itemEnd - viewport;
|
|
7458
|
+
const clamped = Math.min(Math.max(next, 0), maxOffset);
|
|
7459
|
+
return clamped === offset ? null : clamped;
|
|
7460
|
+
}
|
|
7461
|
+
|
|
7462
|
+
// src/data-table/useSpreadsheetGrid.ts
|
|
7463
|
+
import { useCallback as useCallback7, useEffect as useEffect11, useMemo as useMemo6, useRef as useRef12, useState as useState16 } from "react";
|
|
7464
|
+
|
|
7465
|
+
// src/data-table/grid-selection.ts
|
|
7466
|
+
function rangeBounds(range, rowIds, fieldNames) {
|
|
7467
|
+
const ra = rowIds.indexOf(range.anchor.rowId);
|
|
7468
|
+
const rf = rowIds.indexOf(range.focus.rowId);
|
|
7469
|
+
const ca = fieldNames.indexOf(range.anchor.fieldName);
|
|
7470
|
+
const cf = fieldNames.indexOf(range.focus.fieldName);
|
|
7471
|
+
if (ra === -1 || rf === -1 || ca === -1 || cf === -1) return null;
|
|
7472
|
+
return {
|
|
7473
|
+
r0: Math.min(ra, rf),
|
|
7474
|
+
r1: Math.max(ra, rf),
|
|
7475
|
+
c0: Math.min(ca, cf),
|
|
7476
|
+
c1: Math.max(ca, cf)
|
|
7477
|
+
};
|
|
7478
|
+
}
|
|
7479
|
+
function rangeSize(bounds) {
|
|
7480
|
+
const rows = bounds.r1 - bounds.r0 + 1;
|
|
7481
|
+
const cols = bounds.c1 - bounds.c0 + 1;
|
|
7482
|
+
return { rows, cols, cells: rows * cols };
|
|
7483
|
+
}
|
|
7484
|
+
function boundsContain(bounds, rowIndex, colIndex) {
|
|
7485
|
+
return rowIndex >= bounds.r0 && rowIndex <= bounds.r1 && colIndex >= bounds.c0 && colIndex <= bounds.c1;
|
|
7486
|
+
}
|
|
7487
|
+
function cellsInRange(range, rowIds, fieldNames) {
|
|
7488
|
+
const b = rangeBounds(range, rowIds, fieldNames);
|
|
7489
|
+
if (!b) return [];
|
|
7490
|
+
const out = [];
|
|
7491
|
+
for (let r = b.r0; r <= b.r1; r += 1) {
|
|
7492
|
+
const rowId = rowIds[r];
|
|
7493
|
+
if (rowId === void 0) continue;
|
|
7494
|
+
for (let c = b.c0; c <= b.c1; c += 1) {
|
|
7495
|
+
const fieldName = fieldNames[c];
|
|
7496
|
+
if (fieldName === void 0) continue;
|
|
7497
|
+
out.push({ rowId, fieldName });
|
|
7498
|
+
}
|
|
7499
|
+
}
|
|
7500
|
+
return out;
|
|
7501
|
+
}
|
|
7502
|
+
function rangeRows(range, rowIds, fieldNames) {
|
|
7503
|
+
const b = rangeBounds(range, rowIds, fieldNames);
|
|
7504
|
+
if (!b) return [];
|
|
7505
|
+
const rows = [];
|
|
7506
|
+
for (let r = b.r0; r <= b.r1; r += 1) {
|
|
7507
|
+
const rowId = rowIds[r];
|
|
7508
|
+
if (rowId === void 0) continue;
|
|
7509
|
+
const row = [];
|
|
7510
|
+
for (let c = b.c0; c <= b.c1; c += 1) {
|
|
7511
|
+
const fieldName = fieldNames[c];
|
|
7512
|
+
if (fieldName === void 0) continue;
|
|
7513
|
+
row.push({ rowId, fieldName });
|
|
7514
|
+
}
|
|
7515
|
+
rows.push(row);
|
|
7516
|
+
}
|
|
7517
|
+
return rows;
|
|
7518
|
+
}
|
|
7519
|
+
function isSingleCellRange(range) {
|
|
7520
|
+
return sameCell(range.anchor, range.focus);
|
|
7521
|
+
}
|
|
7522
|
+
function rowRange(rowId, fieldNames) {
|
|
7523
|
+
const firstField = fieldNames[0];
|
|
7524
|
+
const lastField = fieldNames[fieldNames.length - 1];
|
|
7525
|
+
if (firstField === void 0 || lastField === void 0) return null;
|
|
7526
|
+
return {
|
|
7527
|
+
anchor: { rowId, fieldName: firstField },
|
|
7528
|
+
focus: { rowId, fieldName: lastField }
|
|
7529
|
+
};
|
|
7530
|
+
}
|
|
7531
|
+
function columnRange(fieldName, rowIds) {
|
|
7532
|
+
const firstRow = rowIds[0];
|
|
7533
|
+
const lastRow = rowIds[rowIds.length - 1];
|
|
7534
|
+
if (firstRow === void 0 || lastRow === void 0) return null;
|
|
7535
|
+
return {
|
|
7536
|
+
anchor: { rowId: firstRow, fieldName },
|
|
7537
|
+
focus: { rowId: lastRow, fieldName }
|
|
7538
|
+
};
|
|
7539
|
+
}
|
|
7540
|
+
function allRange(rowIds, fieldNames) {
|
|
7541
|
+
const firstRow = rowIds[0];
|
|
7542
|
+
const lastRow = rowIds[rowIds.length - 1];
|
|
7543
|
+
const firstField = fieldNames[0];
|
|
7544
|
+
const lastField = fieldNames[fieldNames.length - 1];
|
|
7545
|
+
if (firstRow === void 0 || lastRow === void 0 || firstField === void 0 || lastField === void 0) {
|
|
7546
|
+
return null;
|
|
7547
|
+
}
|
|
7548
|
+
return {
|
|
7549
|
+
anchor: { rowId: firstRow, fieldName: firstField },
|
|
7550
|
+
focus: { rowId: lastRow, fieldName: lastField }
|
|
7551
|
+
};
|
|
7552
|
+
}
|
|
7553
|
+
function sameCell(a, b) {
|
|
7554
|
+
if (!a || !b) return a === b;
|
|
7555
|
+
return a.rowId === b.rowId && a.fieldName === b.fieldName;
|
|
7556
|
+
}
|
|
7557
|
+
function moveSelection(current, move, rowIds, fieldNames) {
|
|
7558
|
+
if (rowIds.length === 0 || fieldNames.length === 0) return null;
|
|
7559
|
+
const firstRowId = rowIds[0];
|
|
7560
|
+
const firstFieldName = fieldNames[0];
|
|
7561
|
+
if (firstRowId === void 0 || firstFieldName === void 0) return null;
|
|
7562
|
+
const first = { rowId: firstRowId, fieldName: firstFieldName };
|
|
7563
|
+
if (!current) return first;
|
|
7564
|
+
let r = rowIds.indexOf(current.rowId);
|
|
7565
|
+
let c = fieldNames.indexOf(current.fieldName);
|
|
7566
|
+
if (r === -1 || c === -1) return first;
|
|
7567
|
+
const lastRow = rowIds.length - 1;
|
|
7568
|
+
const lastCol = fieldNames.length - 1;
|
|
7569
|
+
const clamp = (n2, max) => Math.min(Math.max(n2, 0), max);
|
|
7570
|
+
switch (move) {
|
|
7571
|
+
case "up":
|
|
7572
|
+
r = clamp(r - 1, lastRow);
|
|
7573
|
+
break;
|
|
7574
|
+
case "down":
|
|
7575
|
+
r = clamp(r + 1, lastRow);
|
|
7576
|
+
break;
|
|
7577
|
+
case "left":
|
|
7578
|
+
c = clamp(c - 1, lastCol);
|
|
7579
|
+
break;
|
|
7580
|
+
case "right":
|
|
7581
|
+
c = clamp(c + 1, lastCol);
|
|
7582
|
+
break;
|
|
7583
|
+
case "rowStart":
|
|
7584
|
+
c = 0;
|
|
7585
|
+
break;
|
|
7586
|
+
case "rowEnd":
|
|
7587
|
+
c = lastCol;
|
|
7588
|
+
break;
|
|
7589
|
+
case "gridStart":
|
|
7590
|
+
r = 0;
|
|
7591
|
+
c = 0;
|
|
7592
|
+
break;
|
|
7593
|
+
case "gridEnd":
|
|
7594
|
+
r = lastRow;
|
|
7595
|
+
c = lastCol;
|
|
7596
|
+
break;
|
|
7597
|
+
case "nextCell":
|
|
7598
|
+
if (c < lastCol) c += 1;
|
|
7599
|
+
else if (r < lastRow) {
|
|
7600
|
+
r += 1;
|
|
7601
|
+
c = 0;
|
|
7602
|
+
}
|
|
7603
|
+
break;
|
|
7604
|
+
case "prevCell":
|
|
7605
|
+
if (c > 0) c -= 1;
|
|
7606
|
+
else if (r > 0) {
|
|
7607
|
+
r -= 1;
|
|
7608
|
+
c = lastCol;
|
|
7609
|
+
}
|
|
7610
|
+
break;
|
|
7611
|
+
}
|
|
7612
|
+
const rowId = rowIds[r];
|
|
7613
|
+
const fieldName = fieldNames[c];
|
|
7614
|
+
if (rowId === void 0 || fieldName === void 0) return first;
|
|
7615
|
+
return { rowId, fieldName };
|
|
7616
|
+
}
|
|
7617
|
+
function isTypingKey(e) {
|
|
7618
|
+
if (e.ctrlKey || e.metaKey || e.altKey) return false;
|
|
7619
|
+
return e.key.length === 1 && e.key !== " ";
|
|
7620
|
+
}
|
|
7621
|
+
function classifyGridKey(e) {
|
|
7622
|
+
const mod = e.ctrlKey || e.metaKey;
|
|
7623
|
+
const arrowMove = {
|
|
7624
|
+
ArrowUp: mod ? "gridStart" : "up",
|
|
7625
|
+
ArrowDown: mod ? "gridEnd" : "down",
|
|
7626
|
+
ArrowLeft: mod ? "rowStart" : "left",
|
|
7627
|
+
ArrowRight: mod ? "rowEnd" : "right",
|
|
7628
|
+
Home: mod ? "gridStart" : "rowStart",
|
|
7629
|
+
End: mod ? "gridEnd" : "rowEnd"
|
|
7630
|
+
};
|
|
7631
|
+
const arrow = arrowMove[e.key];
|
|
7632
|
+
if (arrow !== void 0) {
|
|
7633
|
+
return { kind: e.shiftKey ? "extend" : "move", move: arrow };
|
|
7634
|
+
}
|
|
7635
|
+
switch (e.key) {
|
|
7636
|
+
case "Tab":
|
|
7637
|
+
return { kind: "move", move: e.shiftKey ? "prevCell" : "nextCell" };
|
|
7638
|
+
case "Enter":
|
|
7639
|
+
case "F2":
|
|
7640
|
+
return { kind: "edit" };
|
|
7641
|
+
case " ":
|
|
7642
|
+
if (e.shiftKey) return { kind: "selectRow" };
|
|
7643
|
+
if (mod) return { kind: "selectColumn" };
|
|
7644
|
+
return { kind: "edit" };
|
|
7645
|
+
case "a":
|
|
7646
|
+
case "A":
|
|
7647
|
+
if (mod) return { kind: "selectAll" };
|
|
7648
|
+
break;
|
|
7649
|
+
case "d":
|
|
7650
|
+
case "D":
|
|
7651
|
+
if (mod) return { kind: "fillDown" };
|
|
7652
|
+
break;
|
|
7653
|
+
case "Escape":
|
|
7654
|
+
return { kind: "escape" };
|
|
7655
|
+
case "Delete":
|
|
7656
|
+
case "Backspace":
|
|
7657
|
+
return { kind: "clearCell" };
|
|
7658
|
+
case "c":
|
|
7659
|
+
case "C":
|
|
7660
|
+
if (mod) return { kind: "copy" };
|
|
7661
|
+
break;
|
|
7662
|
+
case "x":
|
|
7663
|
+
case "X":
|
|
7664
|
+
if (mod) return { kind: "cut" };
|
|
7665
|
+
break;
|
|
7666
|
+
case "v":
|
|
7667
|
+
case "V":
|
|
7668
|
+
if (mod) return { kind: "paste" };
|
|
7669
|
+
break;
|
|
7670
|
+
}
|
|
7671
|
+
if (isTypingKey(e)) return { kind: "editSeeded", seed: e.key };
|
|
7672
|
+
return null;
|
|
7673
|
+
}
|
|
7674
|
+
function directClickKinds() {
|
|
7675
|
+
return ["checkbox", "rating", "select", "multiselect"];
|
|
7676
|
+
}
|
|
7677
|
+
function isDirectClickEditor(editorKind) {
|
|
7678
|
+
return editorKind !== void 0 && directClickKinds().includes(editorKind);
|
|
7679
|
+
}
|
|
7680
|
+
function cellDomKey(address) {
|
|
7681
|
+
return `${address.rowId}::${address.fieldName}`;
|
|
7682
|
+
}
|
|
7683
|
+
|
|
7684
|
+
// src/data-table/grid-clipboard.ts
|
|
7685
|
+
function cellClipboardText(value) {
|
|
7686
|
+
if (value === null || value === void 0) return "";
|
|
7687
|
+
if (typeof value === "object") return JSON.stringify(value);
|
|
7688
|
+
return String(value);
|
|
7689
|
+
}
|
|
7690
|
+
function tsvCell(text) {
|
|
7691
|
+
return /[\t\r\n"]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
|
|
7692
|
+
}
|
|
7693
|
+
function gridToTsv(block) {
|
|
7694
|
+
return block.map((row) => row.map((cell) => tsvCell(cellClipboardText(cell))).join(" ")).join("\n");
|
|
7695
|
+
}
|
|
7696
|
+
function parseClipboardGrid(text) {
|
|
7697
|
+
const rows = [];
|
|
7698
|
+
let row = [];
|
|
7699
|
+
let cell = "";
|
|
7700
|
+
let i = 0;
|
|
7701
|
+
const n2 = text.length;
|
|
7702
|
+
while (i < n2) {
|
|
7703
|
+
const ch = text[i];
|
|
7704
|
+
if (cell === "" && ch === '"') {
|
|
7705
|
+
let j = i + 1;
|
|
7706
|
+
let out = "";
|
|
7707
|
+
let closed = false;
|
|
7708
|
+
while (j < n2) {
|
|
7709
|
+
const c = text[j];
|
|
7710
|
+
if (c === '"') {
|
|
7711
|
+
if (text[j + 1] === '"') {
|
|
7712
|
+
out += '"';
|
|
7713
|
+
j += 2;
|
|
7714
|
+
continue;
|
|
7715
|
+
}
|
|
7716
|
+
closed = true;
|
|
7717
|
+
j += 1;
|
|
7718
|
+
break;
|
|
7719
|
+
}
|
|
7720
|
+
out += c;
|
|
7721
|
+
j += 1;
|
|
7722
|
+
}
|
|
7723
|
+
if (closed && (j >= n2 || text[j] === " " || text[j] === "\n" || text[j] === "\r")) {
|
|
7724
|
+
cell = out;
|
|
7725
|
+
i = j;
|
|
7726
|
+
if (i >= n2) break;
|
|
7727
|
+
const d = text[i];
|
|
7728
|
+
if (d === " ") {
|
|
7729
|
+
row.push(cell);
|
|
7730
|
+
cell = "";
|
|
7731
|
+
i += 1;
|
|
7732
|
+
continue;
|
|
7733
|
+
}
|
|
7734
|
+
row.push(cell);
|
|
7735
|
+
rows.push(row);
|
|
7736
|
+
row = [];
|
|
7737
|
+
cell = "";
|
|
7738
|
+
i += d === "\r" && text[i + 1] === "\n" ? 2 : 1;
|
|
7739
|
+
continue;
|
|
7740
|
+
}
|
|
7741
|
+
cell += ch;
|
|
7742
|
+
i += 1;
|
|
7743
|
+
continue;
|
|
7744
|
+
}
|
|
7745
|
+
if (ch === " ") {
|
|
7746
|
+
row.push(cell);
|
|
7747
|
+
cell = "";
|
|
7748
|
+
i += 1;
|
|
7749
|
+
continue;
|
|
7750
|
+
}
|
|
7751
|
+
if (ch === "\n" || ch === "\r") {
|
|
7752
|
+
row.push(cell);
|
|
7753
|
+
rows.push(row);
|
|
7754
|
+
row = [];
|
|
7755
|
+
cell = "";
|
|
7756
|
+
i += ch === "\r" && text[i + 1] === "\n" ? 2 : 1;
|
|
7757
|
+
continue;
|
|
7758
|
+
}
|
|
7759
|
+
cell += ch;
|
|
7760
|
+
i += 1;
|
|
7761
|
+
}
|
|
7762
|
+
const endedOnBreak = n2 > 0 && (text[n2 - 1] === "\n" || text[n2 - 1] === "\r");
|
|
7763
|
+
if (!endedOnBreak) {
|
|
7764
|
+
row.push(cell);
|
|
7765
|
+
rows.push(row);
|
|
7766
|
+
} else if (row.length > 0) {
|
|
7767
|
+
row.push(cell);
|
|
7768
|
+
rows.push(row);
|
|
7769
|
+
}
|
|
7770
|
+
return rows.length === 0 ? [[""]] : rows;
|
|
7771
|
+
}
|
|
7772
|
+
function planPaste(anchor, block, rowIds, fieldNames) {
|
|
7773
|
+
const r0 = rowIds.indexOf(anchor.rowId);
|
|
7774
|
+
const c0 = fieldNames.indexOf(anchor.fieldName);
|
|
7775
|
+
if (r0 === -1 || c0 === -1) return null;
|
|
7776
|
+
const width = block.reduce((w, row) => Math.max(w, row.length), 0);
|
|
7777
|
+
const colsAvailable = fieldNames.length - c0;
|
|
7778
|
+
const colsUsed = Math.min(width, colsAvailable);
|
|
7779
|
+
const targetFields = fieldNames.slice(c0, c0 + colsUsed);
|
|
7780
|
+
const cells = [];
|
|
7781
|
+
const overflowRows = [];
|
|
7782
|
+
block.forEach((blockRow, dr) => {
|
|
7783
|
+
const rowId = rowIds[r0 + dr];
|
|
7784
|
+
if (rowId === void 0) {
|
|
7785
|
+
overflowRows.push(targetFields.map((_, dc) => blockRow[dc] ?? ""));
|
|
7786
|
+
return;
|
|
7787
|
+
}
|
|
7788
|
+
targetFields.forEach((fieldName, dc) => {
|
|
7789
|
+
if (dc >= blockRow.length) return;
|
|
7790
|
+
const raw = blockRow[dc];
|
|
7791
|
+
if (raw === void 0) return;
|
|
7792
|
+
cells.push({ rowId, fieldName, raw });
|
|
7793
|
+
});
|
|
7794
|
+
});
|
|
7795
|
+
return {
|
|
7796
|
+
cells,
|
|
7797
|
+
overflowRows,
|
|
7798
|
+
clippedColumns: Math.max(0, width - colsAvailable),
|
|
7799
|
+
fieldNames: targetFields
|
|
7800
|
+
};
|
|
7801
|
+
}
|
|
7802
|
+
function isSingleCell(block) {
|
|
7803
|
+
return block.length === 1 && block[0]?.length === 1;
|
|
7804
|
+
}
|
|
7805
|
+
function storedValuesEqual(a, b) {
|
|
7806
|
+
if (a === b) return true;
|
|
7807
|
+
if (a === null || b === null || a === void 0 || b === void 0) {
|
|
7808
|
+
return (a ?? null) === (b ?? null);
|
|
7809
|
+
}
|
|
7810
|
+
if (typeof a === "object" || typeof b === "object") {
|
|
7811
|
+
try {
|
|
7812
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
7813
|
+
} catch {
|
|
7814
|
+
return false;
|
|
7815
|
+
}
|
|
7816
|
+
}
|
|
7817
|
+
return false;
|
|
7818
|
+
}
|
|
7819
|
+
|
|
7820
|
+
// src/data-table/fill.ts
|
|
7821
|
+
var NO_SERIES = { kind: "none", step: 0 };
|
|
7822
|
+
var MS_PER_DAY = 864e5;
|
|
7823
|
+
function plural(count, one, many) {
|
|
7824
|
+
return `${count} ${count === 1 ? one : many}`;
|
|
7825
|
+
}
|
|
7826
|
+
function isValidRect(rect) {
|
|
7827
|
+
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;
|
|
7828
|
+
}
|
|
7829
|
+
function asBounds(rect) {
|
|
7830
|
+
return { r0: rect.top, r1: rect.bottom, c0: rect.left, c1: rect.right };
|
|
7831
|
+
}
|
|
7832
|
+
function directionOf(source, target) {
|
|
7833
|
+
if (!isValidRect(source) || !isValidRect(target)) return null;
|
|
7834
|
+
if (target.top === source.bottom + 1) return "down";
|
|
7835
|
+
if (target.bottom === source.top - 1) return "up";
|
|
7836
|
+
if (target.left === source.right + 1) return "right";
|
|
7837
|
+
if (target.right === source.left - 1) return "left";
|
|
7838
|
+
return null;
|
|
7839
|
+
}
|
|
7840
|
+
function tileIndex(i, a, b) {
|
|
7841
|
+
const n2 = b - a + 1;
|
|
7842
|
+
if (n2 <= 0) return a;
|
|
7843
|
+
if (i >= a && i <= b) return i;
|
|
7844
|
+
if (i > b) return a + (i - a) % n2;
|
|
7845
|
+
return b - (a - 1 - i) % n2;
|
|
7846
|
+
}
|
|
7847
|
+
function isFiniteNumber(v) {
|
|
7848
|
+
return typeof v === "number" && Number.isFinite(v);
|
|
7849
|
+
}
|
|
7850
|
+
var DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
|
|
7851
|
+
var DATE_ISH = /^\d{4}-\d{2}-\d{2}([T ]|$)/;
|
|
7852
|
+
function dateMs(v) {
|
|
7853
|
+
if (v instanceof Date) {
|
|
7854
|
+
const t = v.getTime();
|
|
7855
|
+
return Number.isFinite(t) ? t : null;
|
|
7856
|
+
}
|
|
7857
|
+
if (typeof v === "string" && DATE_ISH.test(v)) {
|
|
7858
|
+
const t = Date.parse(v);
|
|
7859
|
+
return Number.isFinite(t) ? t : null;
|
|
7860
|
+
}
|
|
7861
|
+
return null;
|
|
7862
|
+
}
|
|
7863
|
+
function detectSeries(values) {
|
|
7864
|
+
if (!Array.isArray(values) || values.length < 2) return NO_SERIES;
|
|
7865
|
+
if (values.every(isFiniteNumber)) {
|
|
7866
|
+
const nums = values;
|
|
7867
|
+
const first = nums[0];
|
|
7868
|
+
const second = nums[1];
|
|
7869
|
+
if (first === void 0 || second === void 0) return NO_SERIES;
|
|
7870
|
+
const step = second - first;
|
|
7871
|
+
for (let i = 1; i < nums.length; i += 1) {
|
|
7872
|
+
const prev = nums[i - 1];
|
|
7873
|
+
const cur = nums[i];
|
|
7874
|
+
if (prev === void 0 || cur === void 0) return NO_SERIES;
|
|
7875
|
+
if (cur - prev !== step) return NO_SERIES;
|
|
7876
|
+
}
|
|
7877
|
+
return { kind: "number", step };
|
|
7878
|
+
}
|
|
7879
|
+
const stamps = values.map(dateMs);
|
|
7880
|
+
if (stamps.every((t) => t !== null)) {
|
|
7881
|
+
const first = stamps[0];
|
|
7882
|
+
const second = stamps[1];
|
|
7883
|
+
if (first === void 0 || second === void 0) return NO_SERIES;
|
|
7884
|
+
const deltaMs = second - first;
|
|
7885
|
+
if (deltaMs % MS_PER_DAY !== 0) return NO_SERIES;
|
|
7886
|
+
for (let i = 1; i < stamps.length; i += 1) {
|
|
7887
|
+
const prev = stamps[i - 1];
|
|
7888
|
+
const cur = stamps[i];
|
|
7889
|
+
if (prev === void 0 || cur === void 0) return NO_SERIES;
|
|
7890
|
+
if (cur - prev !== deltaMs) return NO_SERIES;
|
|
7891
|
+
}
|
|
7892
|
+
return { kind: "date", step: deltaMs / MS_PER_DAY };
|
|
7893
|
+
}
|
|
7894
|
+
return NO_SERIES;
|
|
7895
|
+
}
|
|
7896
|
+
function formatDateLike(ms, sample) {
|
|
7897
|
+
const iso = new Date(ms).toISOString();
|
|
7898
|
+
if (typeof sample === "string" && DATE_ONLY.test(sample)) return iso.slice(0, 10);
|
|
7899
|
+
return iso;
|
|
7900
|
+
}
|
|
7901
|
+
function extrapolate(line, series, k) {
|
|
7902
|
+
const last = line[line.length - 1];
|
|
7903
|
+
if (series.kind === "number" && isFiniteNumber(last)) {
|
|
7904
|
+
return last + k * series.step;
|
|
7905
|
+
}
|
|
7906
|
+
if (series.kind === "date") {
|
|
7907
|
+
const base = dateMs(last);
|
|
7908
|
+
if (base === null) return jsonable(last);
|
|
7909
|
+
return formatDateLike(base + k * series.step * MS_PER_DAY, last);
|
|
7910
|
+
}
|
|
7911
|
+
return jsonable(last);
|
|
7912
|
+
}
|
|
7913
|
+
function jsonable(value) {
|
|
7914
|
+
if (value instanceof Date) {
|
|
7915
|
+
const t = value.getTime();
|
|
7916
|
+
return Number.isFinite(t) ? value.toISOString() : null;
|
|
7917
|
+
}
|
|
7918
|
+
if (value === void 0) return null;
|
|
7919
|
+
return value;
|
|
7920
|
+
}
|
|
7921
|
+
function emptyResult(summary) {
|
|
7922
|
+
return { patches: [], skipped: [], summary };
|
|
7923
|
+
}
|
|
7924
|
+
function fillRange(request) {
|
|
7925
|
+
const { source, target, columnIds, rowIds } = request;
|
|
7926
|
+
const mode = request.mode ?? "series";
|
|
7927
|
+
const isWritable = request.isColumnWritable ?? (() => true);
|
|
7928
|
+
const direction = directionOf(source, target);
|
|
7929
|
+
if (!direction) {
|
|
7930
|
+
return emptyResult(
|
|
7931
|
+
"Filled 0 cells because the fill area does not touch the selection."
|
|
7932
|
+
);
|
|
7933
|
+
}
|
|
7934
|
+
if (rowIds.length === 0 || columnIds.length === 0) {
|
|
7935
|
+
return emptyResult("Filled 0 cells because the table is empty.");
|
|
7936
|
+
}
|
|
7937
|
+
const read = (r, c) => {
|
|
7938
|
+
try {
|
|
7939
|
+
return { ok: true, value: request.valueAt(r, c) };
|
|
7940
|
+
} catch {
|
|
7941
|
+
return { ok: false, value: void 0 };
|
|
7942
|
+
}
|
|
7943
|
+
};
|
|
7944
|
+
const vertical = direction === "down" || direction === "up";
|
|
7945
|
+
const forward = direction === "down" || direction === "right";
|
|
7946
|
+
const fillStart = vertical ? source.top : source.left;
|
|
7947
|
+
const fillEnd = vertical ? source.bottom : source.right;
|
|
7948
|
+
const crossStart = vertical ? source.left : source.top;
|
|
7949
|
+
const crossEnd = vertical ? source.right : source.bottom;
|
|
7950
|
+
const maxFill = (vertical ? rowIds.length : columnIds.length) - 1;
|
|
7951
|
+
const maxCross = (vertical ? columnIds.length : rowIds.length) - 1;
|
|
7952
|
+
const rawFillFrom = vertical ? target.top : target.left;
|
|
7953
|
+
const rawFillTo = vertical ? target.bottom : target.right;
|
|
7954
|
+
const rawCrossFrom = vertical ? target.left : target.top;
|
|
7955
|
+
const rawCrossTo = vertical ? target.right : target.bottom;
|
|
7956
|
+
const fillFrom = Math.max(rawFillFrom, 0);
|
|
7957
|
+
const fillTo = Math.min(rawFillTo, maxFill);
|
|
7958
|
+
const crossFrom = Math.max(rawCrossFrom, 0);
|
|
7959
|
+
const crossTo = Math.min(rawCrossTo, maxCross);
|
|
7960
|
+
const requested = Math.max(rawFillTo - rawFillFrom + 1, 0) * Math.max(rawCrossTo - rawCrossFrom + 1, 0);
|
|
7961
|
+
const inside = Math.max(fillTo - fillFrom + 1, 0) * Math.max(crossTo - crossFrom + 1, 0);
|
|
7962
|
+
const outside = Math.max(requested - inside, 0);
|
|
7963
|
+
const sourceBounds = asBounds(source);
|
|
7964
|
+
const patches = [];
|
|
7965
|
+
const skipped = [];
|
|
7966
|
+
const touchedColumns = /* @__PURE__ */ new Set();
|
|
7967
|
+
const lines = /* @__PURE__ */ new Map();
|
|
7968
|
+
const lineFor = (crossIndex) => {
|
|
7969
|
+
const srcCross = tileIndex(crossIndex, crossStart, crossEnd);
|
|
7970
|
+
const cached = lines.get(srcCross);
|
|
7971
|
+
if (cached) return cached;
|
|
7972
|
+
const values = [];
|
|
7973
|
+
const reads = [];
|
|
7974
|
+
for (let f = fillStart; f <= fillEnd; f += 1) {
|
|
7975
|
+
const r = vertical ? f : srcCross;
|
|
7976
|
+
const c = vertical ? srcCross : f;
|
|
7977
|
+
const got = read(r, c);
|
|
7978
|
+
values.push(got.value);
|
|
7979
|
+
reads.push(got.ok);
|
|
7980
|
+
}
|
|
7981
|
+
const series = mode === "series" ? detectSeries(values) : NO_SERIES;
|
|
7982
|
+
const line = { values, reads, series };
|
|
7983
|
+
lines.set(srcCross, line);
|
|
7984
|
+
return line;
|
|
7985
|
+
};
|
|
7986
|
+
for (let f = fillFrom; f <= fillTo; f += 1) {
|
|
7987
|
+
for (let x = crossFrom; x <= crossTo; x += 1) {
|
|
7988
|
+
const rowIndex = vertical ? f : x;
|
|
7989
|
+
const colIndex = vertical ? x : f;
|
|
7990
|
+
const rowId = rowIds[rowIndex];
|
|
7991
|
+
const columnId2 = columnIds[colIndex];
|
|
7992
|
+
if (rowId === void 0 || columnId2 === void 0) continue;
|
|
7993
|
+
if (boundsContain(sourceBounds, rowIndex, colIndex)) continue;
|
|
7994
|
+
if (!isWritable(columnId2)) {
|
|
7995
|
+
skipped.push({
|
|
7996
|
+
rowId,
|
|
7997
|
+
columnId: columnId2,
|
|
7998
|
+
reason: `${columnId2} cannot be filled because that column is read-only.`
|
|
7999
|
+
});
|
|
8000
|
+
continue;
|
|
8001
|
+
}
|
|
8002
|
+
const line = lineFor(x);
|
|
8003
|
+
if (line.series.kind !== "none") {
|
|
8004
|
+
const k = forward ? f - fillEnd : fillStart - f;
|
|
8005
|
+
patches.push({ rowId, columnId: columnId2, value: jsonable(extrapolate(line.values, line.series, k)) });
|
|
8006
|
+
touchedColumns.add(columnId2);
|
|
8007
|
+
continue;
|
|
8008
|
+
}
|
|
8009
|
+
const srcFill = tileIndex(f, fillStart, fillEnd);
|
|
8010
|
+
const patternIndex = srcFill - fillStart;
|
|
8011
|
+
if (line.reads[patternIndex] !== true) {
|
|
8012
|
+
skipped.push({
|
|
8013
|
+
rowId,
|
|
8014
|
+
columnId: columnId2,
|
|
8015
|
+
reason: `The value to copy into ${columnId2} could not be read, so that cell was left alone.`
|
|
8016
|
+
});
|
|
8017
|
+
continue;
|
|
8018
|
+
}
|
|
8019
|
+
patches.push({ rowId, columnId: columnId2, value: jsonable(line.values[patternIndex]) });
|
|
8020
|
+
touchedColumns.add(columnId2);
|
|
8021
|
+
}
|
|
8022
|
+
}
|
|
8023
|
+
return { patches, skipped, summary: summarize(direction, patches, skipped, touchedColumns, outside) };
|
|
8024
|
+
}
|
|
8025
|
+
function summarize(direction, patches, skipped, touchedColumns, outside) {
|
|
8026
|
+
const parts = [];
|
|
8027
|
+
if (patches.length === 0) {
|
|
8028
|
+
parts.push("Filled 0 cells because there was nothing to fill.");
|
|
8029
|
+
} else if (direction === "down" || direction === "up") {
|
|
8030
|
+
const word = direction === "down" ? "down" : "up";
|
|
8031
|
+
parts.push(
|
|
8032
|
+
`Filled ${plural(patches.length, "cell", "cells")} ${word} ${plural(touchedColumns.size, "column", "columns")}.`
|
|
8033
|
+
);
|
|
8034
|
+
} else {
|
|
8035
|
+
const word = direction === "right" ? "right" : "left";
|
|
8036
|
+
parts.push(
|
|
8037
|
+
`Filled ${plural(patches.length, "cell", "cells")} ${word} across ${plural(touchedColumns.size, "column", "columns")}.`
|
|
8038
|
+
);
|
|
8039
|
+
}
|
|
8040
|
+
if (skipped.length > 0) {
|
|
8041
|
+
parts.push(`Skipped ${plural(skipped.length, "cell", "cells")} that could not be filled.`);
|
|
8042
|
+
}
|
|
8043
|
+
if (outside > 0) {
|
|
8044
|
+
parts.push(`Ignored ${plural(outside, "cell", "cells")} outside the table.`);
|
|
8045
|
+
}
|
|
8046
|
+
return parts.join(" ");
|
|
8047
|
+
}
|
|
8048
|
+
function fillDown(request) {
|
|
8049
|
+
const { range, ...rest } = request;
|
|
8050
|
+
if (!isValidRect(range)) {
|
|
8051
|
+
return emptyResult("Filled 0 cells because the selection is not a rectangle.");
|
|
8052
|
+
}
|
|
8053
|
+
if (range.top === range.bottom) {
|
|
8054
|
+
return emptyResult("Filled 0 cells because the selection is a single row.");
|
|
8055
|
+
}
|
|
8056
|
+
return fillRange({
|
|
8057
|
+
...rest,
|
|
8058
|
+
source: { top: range.top, left: range.left, bottom: range.top, right: range.right },
|
|
8059
|
+
target: { top: range.top + 1, left: range.left, bottom: range.bottom, right: range.right }
|
|
8060
|
+
});
|
|
8061
|
+
}
|
|
8062
|
+
function fillTargetFor(source, toRow, toColumn) {
|
|
8063
|
+
if (!isValidRect(source)) return null;
|
|
8064
|
+
if (!Number.isInteger(toRow) || !Number.isInteger(toColumn)) return null;
|
|
8065
|
+
const below = toRow - source.bottom;
|
|
8066
|
+
const above = source.top - toRow;
|
|
8067
|
+
const rightOf = toColumn - source.right;
|
|
8068
|
+
const leftOf = source.left - toColumn;
|
|
8069
|
+
const vertical = Math.max(below, above, 0);
|
|
8070
|
+
const horizontal = Math.max(rightOf, leftOf, 0);
|
|
8071
|
+
if (vertical === 0 && horizontal === 0) return null;
|
|
8072
|
+
if (vertical >= horizontal) {
|
|
8073
|
+
if (below > 0) {
|
|
8074
|
+
return { top: source.bottom + 1, bottom: toRow, left: source.left, right: source.right };
|
|
8075
|
+
}
|
|
8076
|
+
return { top: toRow, bottom: source.top - 1, left: source.left, right: source.right };
|
|
8077
|
+
}
|
|
8078
|
+
if (rightOf > 0) {
|
|
8079
|
+
return { top: source.top, bottom: source.bottom, left: source.right + 1, right: toColumn };
|
|
8080
|
+
}
|
|
8081
|
+
return { top: source.top, bottom: source.bottom, left: toColumn, right: source.left - 1 };
|
|
8082
|
+
}
|
|
8083
|
+
|
|
8084
|
+
// src/data-table/cell-undo.ts
|
|
8085
|
+
var DEFAULT_UNDO_DEPTH = 100;
|
|
8086
|
+
function createUndoStack(depth = DEFAULT_UNDO_DEPTH) {
|
|
8087
|
+
const bounded = Number.isFinite(depth) && depth > 0 ? Math.floor(depth) : 0;
|
|
8088
|
+
return { past: [], future: [], depth: bounded };
|
|
8089
|
+
}
|
|
8090
|
+
function pushUndo(stack, entry) {
|
|
8091
|
+
if (stack.depth <= 0) {
|
|
8092
|
+
return { past: [], future: [], depth: stack.depth };
|
|
8093
|
+
}
|
|
8094
|
+
const past = [...stack.past, entry];
|
|
8095
|
+
while (past.length > stack.depth) past.shift();
|
|
8096
|
+
return { past, future: [], depth: stack.depth };
|
|
8097
|
+
}
|
|
8098
|
+
function popUndo(stack) {
|
|
8099
|
+
const entry = stack.past[stack.past.length - 1];
|
|
8100
|
+
if (entry === void 0) return { stack, entry: null };
|
|
8101
|
+
return {
|
|
8102
|
+
stack: {
|
|
8103
|
+
past: stack.past.slice(0, -1),
|
|
8104
|
+
future: [...stack.future, entry],
|
|
8105
|
+
depth: stack.depth
|
|
8106
|
+
},
|
|
8107
|
+
entry
|
|
8108
|
+
};
|
|
8109
|
+
}
|
|
8110
|
+
function popRedo(stack) {
|
|
8111
|
+
const entry = stack.future[stack.future.length - 1];
|
|
8112
|
+
if (entry === void 0) return { stack, entry: null };
|
|
8113
|
+
const past = [...stack.past, entry];
|
|
8114
|
+
while (past.length > stack.depth) past.shift();
|
|
8115
|
+
return {
|
|
8116
|
+
stack: { past, future: stack.future.slice(0, -1), depth: stack.depth },
|
|
8117
|
+
entry
|
|
8118
|
+
};
|
|
8119
|
+
}
|
|
8120
|
+
function keyOf(patch) {
|
|
8121
|
+
return JSON.stringify([patch.rowId, patch.columnId]);
|
|
8122
|
+
}
|
|
8123
|
+
function undoEntryFor(before, after, label) {
|
|
8124
|
+
const priors = /* @__PURE__ */ new Map();
|
|
8125
|
+
for (const patch of before) priors.set(keyOf(patch), patch);
|
|
8126
|
+
const undo = after.map((patch) => {
|
|
8127
|
+
const prior = priors.get(keyOf(patch));
|
|
8128
|
+
return {
|
|
8129
|
+
rowId: patch.rowId,
|
|
8130
|
+
columnId: patch.columnId,
|
|
8131
|
+
value: prior ? prior.value : null
|
|
8132
|
+
};
|
|
8133
|
+
});
|
|
8134
|
+
return {
|
|
8135
|
+
label,
|
|
8136
|
+
undo,
|
|
8137
|
+
redo: after.map((patch) => ({
|
|
8138
|
+
rowId: patch.rowId,
|
|
8139
|
+
columnId: patch.columnId,
|
|
8140
|
+
value: patch.value
|
|
8141
|
+
}))
|
|
8142
|
+
};
|
|
8143
|
+
}
|
|
8144
|
+
function canUndo(stack) {
|
|
8145
|
+
return stack.depth > 0 && stack.past.length > 0;
|
|
8146
|
+
}
|
|
8147
|
+
function canRedo(stack) {
|
|
8148
|
+
return stack.depth > 0 && stack.future.length > 0;
|
|
8149
|
+
}
|
|
8150
|
+
|
|
8151
|
+
// src/data-table/useSpreadsheetGrid.ts
|
|
8152
|
+
function targetsAnEditor(target) {
|
|
8153
|
+
const element = target instanceof Element ? target : null;
|
|
8154
|
+
if (!element) return false;
|
|
8155
|
+
return element.closest("input, textarea, select, [contenteditable='true']") !== null;
|
|
8156
|
+
}
|
|
8157
|
+
function useSpreadsheetGrid(options) {
|
|
8158
|
+
const [range, setRange] = useState16(null);
|
|
8159
|
+
const [fillTarget, setFillTarget] = useState16(null);
|
|
8160
|
+
const [stack, setStack] = useState16(() => createUndoStack(options?.undoDepth ?? 100));
|
|
8161
|
+
const draggingRef = useRef12(null);
|
|
8162
|
+
const optionsRef = useRef12(options);
|
|
8163
|
+
optionsRef.current = options;
|
|
8164
|
+
const rowIds = options?.rowIds ?? [];
|
|
8165
|
+
const columnIds = useMemo6(
|
|
8166
|
+
() => options ? options.columnIds.filter((id) => id !== "") : [],
|
|
8167
|
+
[options]
|
|
8168
|
+
);
|
|
8169
|
+
useEffect11(() => {
|
|
8170
|
+
if (!range) return;
|
|
8171
|
+
const rowSet = new Set(rowIds);
|
|
8172
|
+
const colSet = new Set(columnIds);
|
|
8173
|
+
const alive = rowSet.has(range.anchor.rowId) && rowSet.has(range.focus.rowId) && colSet.has(range.anchor.fieldName) && colSet.has(range.focus.fieldName);
|
|
8174
|
+
if (!alive) setRange(null);
|
|
8175
|
+
}, [range, rowIds, columnIds]);
|
|
8176
|
+
const bounds = useMemo6(
|
|
8177
|
+
() => range ? rangeBounds(range, rowIds, columnIds) : null,
|
|
8178
|
+
[range, rowIds, columnIds]
|
|
8179
|
+
);
|
|
8180
|
+
const rowIndexById = useMemo6(() => {
|
|
8181
|
+
const map = /* @__PURE__ */ new Map();
|
|
8182
|
+
for (let i = 0; i < rowIds.length; i += 1) map.set(rowIds[i], i);
|
|
8183
|
+
return map;
|
|
8184
|
+
}, [rowIds]);
|
|
8185
|
+
const columnIndexById = useMemo6(() => {
|
|
8186
|
+
const map = /* @__PURE__ */ new Map();
|
|
8187
|
+
for (let i = 0; i < columnIds.length; i += 1) map.set(columnIds[i], i);
|
|
8188
|
+
return map;
|
|
8189
|
+
}, [columnIds]);
|
|
8190
|
+
const screenPatches = useCallback7(
|
|
8191
|
+
(patches) => {
|
|
8192
|
+
const validate = optionsRef.current?.validateCell;
|
|
8193
|
+
if (!validate) return { accepted: patches, refusals: [] };
|
|
8194
|
+
const accepted = [];
|
|
8195
|
+
const refusals = [];
|
|
8196
|
+
for (const patch of patches) {
|
|
8197
|
+
let reason;
|
|
8198
|
+
try {
|
|
8199
|
+
reason = validate({ rowId: patch.rowId, columnId: patch.columnId, value: patch.value });
|
|
8200
|
+
} catch {
|
|
8201
|
+
reason = void 0;
|
|
8202
|
+
}
|
|
8203
|
+
if (reason) refusals.push({ columnId: patch.columnId, reason });
|
|
8204
|
+
else accepted.push(patch);
|
|
8205
|
+
}
|
|
8206
|
+
return { accepted, refusals };
|
|
8207
|
+
},
|
|
8208
|
+
[]
|
|
8209
|
+
);
|
|
8210
|
+
const applyPatches = useCallback7(
|
|
8211
|
+
async (patches, intent, label) => {
|
|
8212
|
+
const current = optionsRef.current;
|
|
8213
|
+
if (!current || patches.length === 0) return;
|
|
8214
|
+
const depth = current.undoDepth ?? 100;
|
|
8215
|
+
if (depth > 0 && intent !== "undo" && intent !== "redo") {
|
|
8216
|
+
const before = patches.map((patch) => ({
|
|
8217
|
+
rowId: patch.rowId,
|
|
8218
|
+
columnId: patch.columnId,
|
|
8219
|
+
value: current.valueAt(patch.rowId, patch.columnId) ?? null
|
|
8220
|
+
}));
|
|
8221
|
+
setStack((previous) => pushUndo(previous, undoEntryFor(before, patches, label)));
|
|
8222
|
+
}
|
|
8223
|
+
await current.onPatch(patches, intent);
|
|
8224
|
+
},
|
|
8225
|
+
[]
|
|
8226
|
+
);
|
|
8227
|
+
const readValueAt = useCallback7((rowIndex, columnIndex) => {
|
|
8228
|
+
const current = optionsRef.current;
|
|
8229
|
+
const rowId = current?.rowIds[rowIndex];
|
|
8230
|
+
const columnId2 = current?.columnIds[columnIndex];
|
|
8231
|
+
if (!current || rowId === void 0 || columnId2 === void 0) return null;
|
|
8232
|
+
return current.valueAt(rowId, columnId2);
|
|
8233
|
+
}, []);
|
|
8234
|
+
const fillRequestBase = useCallback7(() => {
|
|
8235
|
+
const current = optionsRef.current;
|
|
8236
|
+
if (!current) return null;
|
|
8237
|
+
return {
|
|
8238
|
+
valueAt: readValueAt,
|
|
8239
|
+
columnIds: [...current.columnIds],
|
|
8240
|
+
rowIds: [...current.rowIds],
|
|
8241
|
+
isColumnWritable: current.isColumnWritable
|
|
8242
|
+
};
|
|
8243
|
+
}, [readValueAt]);
|
|
8244
|
+
const announceSkips = useCallback7(
|
|
8245
|
+
(skipped, summary) => {
|
|
8246
|
+
const current = optionsRef.current;
|
|
8247
|
+
if (!current?.notify) return;
|
|
8248
|
+
if (skipped.length === 0) {
|
|
8249
|
+
current.notify(summary);
|
|
8250
|
+
return;
|
|
8251
|
+
}
|
|
8252
|
+
const first = skipped[0];
|
|
8253
|
+
const reason = current.columnRefusal?.(first.columnId) ?? first.reason;
|
|
8254
|
+
const rest = skipped.length > 1 ? ` ${skipped.length - 1} more were left alone.` : "";
|
|
8255
|
+
current.notify(`${summary} ${reason}${rest}`);
|
|
8256
|
+
},
|
|
8257
|
+
[]
|
|
8258
|
+
);
|
|
8259
|
+
const doFillDown = useCallback7(async () => {
|
|
8260
|
+
const base = fillRequestBase();
|
|
8261
|
+
if (!base || !bounds) return;
|
|
8262
|
+
const result = fillDown({
|
|
8263
|
+
...base,
|
|
8264
|
+
range: { top: bounds.r0, left: bounds.c0, bottom: bounds.r1, right: bounds.c1 }
|
|
8265
|
+
});
|
|
8266
|
+
const screened = screenPatches(result.patches);
|
|
8267
|
+
await applyPatches(screened.accepted, "fill-down", "Filled down");
|
|
8268
|
+
announceSkips([...result.skipped, ...screened.refusals], result.summary);
|
|
8269
|
+
}, [fillRequestBase, bounds, applyPatches, announceSkips, screenPatches]);
|
|
8270
|
+
const doClear = useCallback7(async () => {
|
|
8271
|
+
const current = optionsRef.current;
|
|
8272
|
+
if (!current || !bounds) return;
|
|
8273
|
+
const patches = [];
|
|
8274
|
+
const skipped = [];
|
|
8275
|
+
for (let r = bounds.r0; r <= bounds.r1; r += 1) {
|
|
8276
|
+
for (let c = bounds.c0; c <= bounds.c1; c += 1) {
|
|
8277
|
+
const rowId = current.rowIds[r];
|
|
8278
|
+
const columnId2 = current.columnIds[c];
|
|
8279
|
+
if (rowId === void 0 || columnId2 === void 0) continue;
|
|
8280
|
+
if (!current.isColumnWritable(columnId2)) {
|
|
8281
|
+
skipped.push({
|
|
8282
|
+
columnId: columnId2,
|
|
8283
|
+
reason: current.columnRefusal?.(columnId2) ?? `${columnId2} cannot be cleared.`
|
|
8284
|
+
});
|
|
8285
|
+
continue;
|
|
8286
|
+
}
|
|
8287
|
+
patches.push({ rowId, columnId: columnId2, value: null });
|
|
8288
|
+
}
|
|
8289
|
+
}
|
|
8290
|
+
const screened = screenPatches(patches);
|
|
8291
|
+
await applyPatches(screened.accepted, "clear", "Cleared");
|
|
8292
|
+
announceSkips(
|
|
8293
|
+
[...skipped, ...screened.refusals],
|
|
8294
|
+
`Cleared ${screened.accepted.length} cells.`
|
|
8295
|
+
);
|
|
8296
|
+
}, [bounds, applyPatches, announceSkips, screenPatches]);
|
|
8297
|
+
const doUndo = useCallback7(async () => {
|
|
8298
|
+
const taken = popUndo(stack);
|
|
8299
|
+
if (!taken.entry) return;
|
|
8300
|
+
setStack(taken.stack);
|
|
8301
|
+
await applyPatches(taken.entry.undo, "undo", taken.entry.label);
|
|
8302
|
+
optionsRef.current?.notify?.(taken.entry.label);
|
|
8303
|
+
}, [stack, applyPatches]);
|
|
8304
|
+
const doRedo = useCallback7(async () => {
|
|
8305
|
+
const taken = popRedo(stack);
|
|
8306
|
+
if (!taken.entry) return;
|
|
8307
|
+
setStack(taken.stack);
|
|
8308
|
+
await applyPatches(taken.entry.redo, "redo", taken.entry.label);
|
|
8309
|
+
}, [stack, applyPatches]);
|
|
8310
|
+
const move = useCallback7(
|
|
8311
|
+
(direction, extend) => {
|
|
8312
|
+
setRange((previous) => {
|
|
8313
|
+
const from = previous ? previous.focus : null;
|
|
8314
|
+
const next = moveSelection(from, direction, rowIds, columnIds);
|
|
8315
|
+
if (!next) return previous;
|
|
8316
|
+
if (extend && previous) return { anchor: previous.anchor, focus: next };
|
|
8317
|
+
return { anchor: next, focus: next };
|
|
8318
|
+
});
|
|
8319
|
+
},
|
|
8320
|
+
[rowIds, columnIds]
|
|
8321
|
+
);
|
|
8322
|
+
const onKeyDown = useCallback7(
|
|
8323
|
+
(event) => {
|
|
8324
|
+
const current = optionsRef.current;
|
|
8325
|
+
if (!current) return;
|
|
8326
|
+
if (targetsAnEditor(event.target)) return;
|
|
8327
|
+
const accel = event.metaKey || event.ctrlKey;
|
|
8328
|
+
if (accel && (event.key === "z" || event.key === "Z")) {
|
|
8329
|
+
event.preventDefault();
|
|
8330
|
+
if (event.shiftKey) void doRedo();
|
|
8331
|
+
else void doUndo();
|
|
8332
|
+
return;
|
|
8333
|
+
}
|
|
8334
|
+
if (accel && (event.key === "y" || event.key === "Y")) {
|
|
8335
|
+
event.preventDefault();
|
|
8336
|
+
void doRedo();
|
|
8337
|
+
return;
|
|
8338
|
+
}
|
|
8339
|
+
const action = classifyGridKey(event);
|
|
8340
|
+
if (!action) return;
|
|
8341
|
+
switch (action.kind) {
|
|
8342
|
+
case "move":
|
|
8343
|
+
event.preventDefault();
|
|
8344
|
+
move(action.move, false);
|
|
8345
|
+
return;
|
|
8346
|
+
case "extend":
|
|
8347
|
+
event.preventDefault();
|
|
8348
|
+
move(action.move, true);
|
|
8349
|
+
return;
|
|
8350
|
+
case "selectAll": {
|
|
8351
|
+
event.preventDefault();
|
|
8352
|
+
const all = allRange(rowIds, columnIds);
|
|
8353
|
+
if (all) setRange(all);
|
|
8354
|
+
return;
|
|
8355
|
+
}
|
|
8356
|
+
case "selectRow": {
|
|
8357
|
+
event.preventDefault();
|
|
8358
|
+
const focused = range?.focus;
|
|
8359
|
+
const next = focused ? rowRange(focused.rowId, columnIds) : null;
|
|
8360
|
+
if (next) setRange(next);
|
|
8361
|
+
return;
|
|
8362
|
+
}
|
|
8363
|
+
case "selectColumn": {
|
|
8364
|
+
event.preventDefault();
|
|
8365
|
+
const focused = range?.focus;
|
|
8366
|
+
const next = focused ? columnRange(focused.fieldName, rowIds) : null;
|
|
8367
|
+
if (next) setRange(next);
|
|
8368
|
+
return;
|
|
8369
|
+
}
|
|
8370
|
+
case "clearCell":
|
|
8371
|
+
event.preventDefault();
|
|
8372
|
+
void doClear();
|
|
8373
|
+
return;
|
|
8374
|
+
case "fillDown":
|
|
8375
|
+
event.preventDefault();
|
|
8376
|
+
void doFillDown();
|
|
8377
|
+
return;
|
|
8378
|
+
case "escape":
|
|
8379
|
+
setRange(null);
|
|
8380
|
+
return;
|
|
8381
|
+
case "edit":
|
|
8382
|
+
case "editSeeded": {
|
|
8383
|
+
const focused = range?.focus;
|
|
8384
|
+
if (!focused || !current.onEditRequest) return;
|
|
8385
|
+
const seed = action.kind === "editSeeded" ? action.seed : null;
|
|
8386
|
+
if (current.onEditRequest(focused, seed)) event.preventDefault();
|
|
8387
|
+
return;
|
|
8388
|
+
}
|
|
8389
|
+
default:
|
|
8390
|
+
return;
|
|
8391
|
+
}
|
|
8392
|
+
},
|
|
8393
|
+
[move, range, rowIds, columnIds, doClear, doFillDown, doUndo, doRedo]
|
|
8394
|
+
);
|
|
8395
|
+
const selectionAsTsv = useCallback7(() => {
|
|
8396
|
+
const current = optionsRef.current;
|
|
8397
|
+
if (!current || !range) return "";
|
|
8398
|
+
const grid = rangeRows(range, rowIds, columnIds).map(
|
|
8399
|
+
(row) => row.map((address) => current.valueAt(address.rowId, address.fieldName))
|
|
8400
|
+
);
|
|
8401
|
+
return gridToTsv(grid);
|
|
8402
|
+
}, [range, rowIds, columnIds]);
|
|
8403
|
+
const selectionAddresses = useCallback7(() => {
|
|
8404
|
+
if (!range || !bounds) return { rowIds: [], columnIds: [] };
|
|
8405
|
+
return {
|
|
8406
|
+
rowIds: rowIds.slice(bounds.r0, bounds.r1 + 1),
|
|
8407
|
+
columnIds: columnIds.slice(bounds.c0, bounds.c1 + 1)
|
|
8408
|
+
};
|
|
8409
|
+
}, [range, bounds, rowIds, columnIds]);
|
|
8410
|
+
const onCopy = useCallback7(
|
|
8411
|
+
(event) => {
|
|
8412
|
+
if (!optionsRef.current || !range || targetsAnEditor(event.target)) return;
|
|
8413
|
+
const text = selectionAsTsv();
|
|
8414
|
+
if (!text) return;
|
|
8415
|
+
event.preventDefault();
|
|
8416
|
+
event.clipboardData?.setData("text/plain", text);
|
|
8417
|
+
},
|
|
8418
|
+
[range, selectionAsTsv]
|
|
8419
|
+
);
|
|
8420
|
+
const onCut = useCallback7(
|
|
8421
|
+
(event) => {
|
|
8422
|
+
if (!optionsRef.current || !range || targetsAnEditor(event.target)) return;
|
|
8423
|
+
const text = selectionAsTsv();
|
|
8424
|
+
if (!text) return;
|
|
8425
|
+
event.preventDefault();
|
|
8426
|
+
event.clipboardData?.setData("text/plain", text);
|
|
8427
|
+
void doClear();
|
|
8428
|
+
},
|
|
8429
|
+
[range, selectionAsTsv, doClear]
|
|
8430
|
+
);
|
|
8431
|
+
const onPaste = useCallback7(
|
|
8432
|
+
(event) => {
|
|
8433
|
+
const current = optionsRef.current;
|
|
8434
|
+
if (!current || current.paste === false || !range || targetsAnEditor(event.target)) return;
|
|
8435
|
+
const text = event.clipboardData?.getData("text/plain") ?? "";
|
|
8436
|
+
if (!text) return;
|
|
8437
|
+
event.preventDefault();
|
|
8438
|
+
const block = parseClipboardGrid(text);
|
|
8439
|
+
const start = range.focus;
|
|
8440
|
+
const startRow = rowIds.indexOf(start.rowId);
|
|
8441
|
+
const startCol = columnIds.indexOf(start.fieldName);
|
|
8442
|
+
if (startRow === -1 || startCol === -1) return;
|
|
8443
|
+
const patches = [];
|
|
8444
|
+
const skipped = [];
|
|
8445
|
+
let outside = 0;
|
|
8446
|
+
for (let r = 0; r < block.length; r += 1) {
|
|
8447
|
+
const line = block[r] ?? [];
|
|
8448
|
+
for (let c = 0; c < line.length; c += 1) {
|
|
8449
|
+
const rowId = rowIds[startRow + r];
|
|
8450
|
+
const columnId2 = columnIds[startCol + c];
|
|
8451
|
+
if (rowId === void 0 || columnId2 === void 0) {
|
|
8452
|
+
outside += 1;
|
|
8453
|
+
continue;
|
|
8454
|
+
}
|
|
8455
|
+
if (!current.isColumnWritable(columnId2)) {
|
|
8456
|
+
skipped.push({
|
|
8457
|
+
columnId: columnId2,
|
|
8458
|
+
reason: current.columnRefusal?.(columnId2) ?? `${columnId2} cannot take a pasted value.`
|
|
8459
|
+
});
|
|
8460
|
+
continue;
|
|
8461
|
+
}
|
|
8462
|
+
patches.push({ rowId, columnId: columnId2, value: line[c] ?? null });
|
|
8463
|
+
}
|
|
8464
|
+
}
|
|
8465
|
+
const screened = screenPatches(patches);
|
|
8466
|
+
void applyPatches(screened.accepted, "paste", "Pasted");
|
|
8467
|
+
const tail = outside > 0 ? ` ${outside} landed past the edge of the table and were ignored.` : "";
|
|
8468
|
+
announceSkips([...skipped, ...screened.refusals], `Pasted ${screened.accepted.length} cells.${tail}`);
|
|
8469
|
+
},
|
|
8470
|
+
[range, rowIds, columnIds, applyPatches, announceSkips, screenPatches]
|
|
8471
|
+
);
|
|
8472
|
+
const cellProps = useCallback7(
|
|
8473
|
+
(rowId, columnId2) => {
|
|
8474
|
+
const address = { rowId, fieldName: columnId2 };
|
|
8475
|
+
const rowIndex = rowIndexById.get(rowId) ?? -1;
|
|
8476
|
+
const colIndex = columnIndexById.get(columnId2) ?? -1;
|
|
8477
|
+
const selected = bounds !== null && rowIndex >= bounds.r0 && rowIndex <= bounds.r1 && colIndex >= bounds.c0 && colIndex <= bounds.c1;
|
|
8478
|
+
const active = range !== null && sameCell(range.focus, address);
|
|
8479
|
+
const inFillPreview = fillTarget !== null && rowIndex >= fillTarget.top && rowIndex <= fillTarget.bottom && colIndex >= fillTarget.left && colIndex <= fillTarget.right;
|
|
8480
|
+
return {
|
|
8481
|
+
"data-matrx-cell-row": rowId,
|
|
8482
|
+
"data-matrx-cell-col": columnId2,
|
|
8483
|
+
...selected ? { "data-matrx-cell-selected": "true" } : {},
|
|
8484
|
+
...active ? { "data-matrx-cell-active": "true" } : {},
|
|
8485
|
+
...inFillPreview ? { "data-matrx-cell-fill-preview": "true" } : {},
|
|
8486
|
+
onMouseDown: (event) => {
|
|
8487
|
+
if (event.button !== 0) return;
|
|
8488
|
+
event.preventDefault();
|
|
8489
|
+
const origin = event.currentTarget;
|
|
8490
|
+
if (typeof HTMLElement !== "undefined" && origin instanceof HTMLElement) {
|
|
8491
|
+
origin.closest('[data-matrx-table-spreadsheet="true"]')?.focus({ preventScroll: true });
|
|
8492
|
+
}
|
|
8493
|
+
setRange(
|
|
8494
|
+
(previous) => event.shiftKey && previous ? { anchor: previous.anchor, focus: address } : { anchor: address, focus: address }
|
|
8495
|
+
);
|
|
8496
|
+
draggingRef.current = "select";
|
|
8497
|
+
},
|
|
8498
|
+
onMouseEnter: () => {
|
|
8499
|
+
if (draggingRef.current === "select") {
|
|
8500
|
+
setRange((previous) => previous ? { anchor: previous.anchor, focus: address } : previous);
|
|
8501
|
+
return;
|
|
8502
|
+
}
|
|
8503
|
+
if (draggingRef.current === "fill" && bounds) {
|
|
8504
|
+
setFillTarget(
|
|
8505
|
+
fillTargetFor(
|
|
8506
|
+
{ top: bounds.r0, left: bounds.c0, bottom: bounds.r1, right: bounds.c1 },
|
|
8507
|
+
rowIndex,
|
|
8508
|
+
colIndex
|
|
8509
|
+
)
|
|
8510
|
+
);
|
|
8511
|
+
}
|
|
8512
|
+
}
|
|
8513
|
+
};
|
|
8514
|
+
},
|
|
8515
|
+
[rowIndexById, columnIndexById, bounds, range, fillTarget]
|
|
8516
|
+
);
|
|
8517
|
+
const isFillHandleCell = useCallback7(
|
|
8518
|
+
(rowId, columnId2) => {
|
|
8519
|
+
const current = optionsRef.current;
|
|
8520
|
+
if (!current || current.fillHandle === false || !bounds) return false;
|
|
8521
|
+
return rowIds[bounds.r1] === rowId && columnIds[bounds.c1] === columnId2;
|
|
8522
|
+
},
|
|
8523
|
+
[bounds, rowIds, columnIds]
|
|
8524
|
+
);
|
|
8525
|
+
const startFillDrag = useCallback7(
|
|
8526
|
+
(event) => {
|
|
8527
|
+
event.preventDefault();
|
|
8528
|
+
event.stopPropagation();
|
|
8529
|
+
draggingRef.current = "fill";
|
|
8530
|
+
},
|
|
8531
|
+
[]
|
|
8532
|
+
);
|
|
8533
|
+
const fillTargetRef = useRef12(null);
|
|
8534
|
+
fillTargetRef.current = fillTarget;
|
|
8535
|
+
const boundsRef = useRef12(null);
|
|
8536
|
+
boundsRef.current = bounds;
|
|
8537
|
+
useEffect11(() => {
|
|
8538
|
+
if (!options) return;
|
|
8539
|
+
const commit = () => {
|
|
8540
|
+
const wasDragging = draggingRef.current;
|
|
8541
|
+
draggingRef.current = null;
|
|
8542
|
+
if (wasDragging !== "fill") return;
|
|
8543
|
+
const target = fillTargetRef.current;
|
|
8544
|
+
const source = boundsRef.current;
|
|
8545
|
+
setFillTarget(null);
|
|
8546
|
+
if (!target || !source) return;
|
|
8547
|
+
const base = fillRequestBase();
|
|
8548
|
+
if (!base) return;
|
|
8549
|
+
const result = fillRange({
|
|
8550
|
+
...base,
|
|
8551
|
+
source: { top: source.r0, left: source.c0, bottom: source.r1, right: source.c1 },
|
|
8552
|
+
target
|
|
8553
|
+
});
|
|
8554
|
+
const screened = screenPatches(result.patches);
|
|
8555
|
+
void applyPatches(screened.accepted, "fill", "Filled");
|
|
8556
|
+
announceSkips([...result.skipped, ...screened.refusals], result.summary);
|
|
8557
|
+
};
|
|
8558
|
+
window.addEventListener("mouseup", commit);
|
|
8559
|
+
return () => window.removeEventListener("mouseup", commit);
|
|
8560
|
+
}, [options, fillRequestBase, applyPatches, announceSkips, screenPatches]);
|
|
8561
|
+
return {
|
|
8562
|
+
range,
|
|
8563
|
+
bounds,
|
|
8564
|
+
enabled: options !== null,
|
|
8565
|
+
containerProps: {
|
|
8566
|
+
tabIndex: options ? 0 : -1,
|
|
8567
|
+
onKeyDown,
|
|
8568
|
+
onCopy,
|
|
8569
|
+
onCut,
|
|
8570
|
+
onPaste
|
|
8571
|
+
},
|
|
8572
|
+
cellProps,
|
|
8573
|
+
isFillHandleCell,
|
|
8574
|
+
startFillDrag,
|
|
8575
|
+
canUndo: stack.past.length > 0,
|
|
8576
|
+
canRedo: stack.future.length > 0,
|
|
8577
|
+
selectionTsv: selectionAsTsv,
|
|
8578
|
+
selectionAddresses
|
|
8579
|
+
};
|
|
8580
|
+
}
|
|
8581
|
+
|
|
8582
|
+
// src/data-table/coverage.ts
|
|
8583
|
+
var PARTIAL_BADGE = "Partial";
|
|
8584
|
+
var UNKNOWN_TOTAL_BADGE = "Unknown total";
|
|
8585
|
+
var NUMBERS2 = new Intl.NumberFormat("en-US");
|
|
8586
|
+
function formatNumber(value) {
|
|
8587
|
+
try {
|
|
8588
|
+
return NUMBERS2.format(value);
|
|
8589
|
+
} catch {
|
|
8590
|
+
return String(value);
|
|
8591
|
+
}
|
|
8592
|
+
}
|
|
8593
|
+
function pluralize(noun) {
|
|
8594
|
+
const word = noun.trim();
|
|
8595
|
+
if (!word) return "rows";
|
|
8596
|
+
const lower = word.toLowerCase();
|
|
8597
|
+
if (/[^aeiou]y$/.test(lower)) return `${word.slice(0, -1)}ies`;
|
|
8598
|
+
if (/(s|x|z|ch|sh)$/.test(lower)) return `${word}es`;
|
|
8599
|
+
return `${word}s`;
|
|
8600
|
+
}
|
|
8601
|
+
function quantity(value, noun) {
|
|
8602
|
+
return `${formatNumber(value)} ${value === 1 ? noun.trim() || "row" : pluralize(noun)}`;
|
|
8603
|
+
}
|
|
8604
|
+
function toWhole(value) {
|
|
8605
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
|
|
8606
|
+
}
|
|
8607
|
+
function toOptionalWhole(value) {
|
|
8608
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) return void 0;
|
|
8609
|
+
return Math.floor(value);
|
|
8610
|
+
}
|
|
8611
|
+
function describeCoverage(input) {
|
|
8612
|
+
const safe = input && typeof input === "object" ? input : { loaded: 0, answeredBy: "client" };
|
|
8613
|
+
const loaded = toWhole(safe.loaded);
|
|
8614
|
+
const matched = toOptionalWhole(safe.matched);
|
|
8615
|
+
const total = toOptionalWhole(safe.total);
|
|
8616
|
+
const cap = toOptionalWhole(safe.cap);
|
|
8617
|
+
const answeredBy = safe.answeredBy === "source" ? "source" : "client";
|
|
8618
|
+
const noun = typeof safe.noun === "string" && safe.noun.trim() ? safe.noun.trim() : "row";
|
|
8619
|
+
const reference = matched ?? total;
|
|
8620
|
+
const capReached = cap !== void 0 && cap > 0 && loaded >= cap;
|
|
8621
|
+
if (reference !== void 0 && loaded >= reference) {
|
|
8622
|
+
return {
|
|
8623
|
+
scope: "all",
|
|
8624
|
+
complete: true,
|
|
8625
|
+
count: { value: matched ?? reference, exact: true },
|
|
8626
|
+
notice: "",
|
|
8627
|
+
badge: ""
|
|
8628
|
+
};
|
|
8629
|
+
}
|
|
8630
|
+
if (answeredBy === "source" && matched !== void 0 && !capReached) {
|
|
8631
|
+
return { scope: "all", complete: true, count: { value: matched, exact: true }, notice: "", badge: "" };
|
|
8632
|
+
}
|
|
8633
|
+
if (capReached && cap !== void 0) {
|
|
8634
|
+
const rest = reference !== void 0 ? `${quantity(reference, noun)} in this table; the rest were not looked at.` : "Anything past that was not looked at.";
|
|
8635
|
+
return {
|
|
8636
|
+
scope: "capped",
|
|
8637
|
+
complete: false,
|
|
8638
|
+
count: { value: loaded, exact: false },
|
|
8639
|
+
notice: `This filter searched the first ${quantity(cap, noun)} only. ${rest}`,
|
|
8640
|
+
badge: PARTIAL_BADGE
|
|
8641
|
+
};
|
|
8642
|
+
}
|
|
8643
|
+
if (answeredBy === "client" && reference !== void 0) {
|
|
8644
|
+
return {
|
|
8645
|
+
scope: "loaded",
|
|
8646
|
+
complete: false,
|
|
8647
|
+
count: { value: loaded, exact: false },
|
|
8648
|
+
notice: `Filtering the ${quantity(loaded, noun)} loaded so far, not all ${quantity(reference, noun)} in this table.`,
|
|
8649
|
+
badge: PARTIAL_BADGE
|
|
8650
|
+
};
|
|
8651
|
+
}
|
|
8652
|
+
if (answeredBy === "source" && total !== void 0) {
|
|
8653
|
+
return {
|
|
8654
|
+
scope: "all",
|
|
8655
|
+
complete: false,
|
|
8656
|
+
count: { value: loaded, exact: false },
|
|
8657
|
+
notice: `Showing the ${quantity(loaded, noun)} loaded so far out of ${quantity(total, noun)} in this table.`,
|
|
8658
|
+
badge: PARTIAL_BADGE
|
|
8659
|
+
};
|
|
8660
|
+
}
|
|
8661
|
+
return {
|
|
8662
|
+
scope: answeredBy === "source" ? "all" : "loaded",
|
|
8663
|
+
complete: false,
|
|
8664
|
+
count: { value: loaded, exact: false },
|
|
8665
|
+
notice: `Showing the ${quantity(loaded, noun)} loaded so far. The total number of ${pluralize(noun)} in this table is not known.`,
|
|
8666
|
+
badge: UNKNOWN_TOTAL_BADGE
|
|
8667
|
+
};
|
|
8668
|
+
}
|
|
8669
|
+
|
|
8670
|
+
// src/data-table/ranked-search.ts
|
|
8671
|
+
function inferTableSearchRole(field) {
|
|
8672
|
+
const key = field.replace(/([a-z])([A-Z])/g, "$1_$2").toLowerCase().replace(/[\s-]+/g, "_");
|
|
8673
|
+
if (key === "id" || key === "uuid" || key.endsWith("_id")) return "id";
|
|
8674
|
+
if (/^(name|alias|label|title|key|slug|display_name|common_name|model_name)$/.test(key) || /_(name|label|title)$/.test(key)) return "name";
|
|
8675
|
+
if (/^(description|summary|details|notes|blurb)$/.test(key) || key.endsWith("_description")) return "description";
|
|
8676
|
+
return "other";
|
|
8677
|
+
}
|
|
8678
|
+
function searchableFields(row, columns) {
|
|
8679
|
+
const values = /* @__PURE__ */ new Map();
|
|
8680
|
+
if (row !== null && typeof row === "object") {
|
|
8681
|
+
for (const [key, value] of Object.entries(row)) values.set(key, stringifyCellValue(value));
|
|
8682
|
+
}
|
|
8683
|
+
for (const column of columns) {
|
|
8684
|
+
if (column.accessorKey || column.accessorFn || column.filterValue) {
|
|
8685
|
+
values.set(columnId(column), stringifyCellValue(getFilterValue(row, column)));
|
|
8686
|
+
}
|
|
8687
|
+
}
|
|
8688
|
+
return values;
|
|
8689
|
+
}
|
|
8690
|
+
function resolveTableSearchScopes(rows, columns, options = {}) {
|
|
8691
|
+
const fields = new Set(columns.filter((c) => c.accessorKey || c.accessorFn || c.filterValue).map(columnId));
|
|
8692
|
+
for (const row of rows) if (row !== null && typeof row === "object") Object.keys(row).forEach((key) => fields.add(key));
|
|
8693
|
+
const roles = new Set([...fields].map((key) => options.roles?.[key] ?? inferTableSearchRole(key)));
|
|
8694
|
+
const scopes = [{ id: "all", label: "All" }];
|
|
8695
|
+
for (const [id, label] of [["id", "ID"], ["name", "Name"], ["description", "Description"]]) {
|
|
8696
|
+
if (roles.has(id)) scopes.push({ id, label });
|
|
8697
|
+
}
|
|
8698
|
+
for (const scope of options.scopes ?? []) if (!scopes.some((s) => s.id === scope.id) && scope.fields?.length) scopes.push(scope);
|
|
8699
|
+
return scopes;
|
|
8700
|
+
}
|
|
8701
|
+
function rankTableSearchRows(rows, columns, query, options = {}, extraText) {
|
|
8702
|
+
const q = query.trim().toLocaleLowerCase();
|
|
8703
|
+
if (!q) return [...rows];
|
|
8704
|
+
const scope = options.scope ?? "all";
|
|
8705
|
+
const customScope = options.scopes?.find((s) => s.id === scope);
|
|
8706
|
+
const mode = options.matchMode ?? "contains";
|
|
8707
|
+
return rows.flatMap((row, index) => {
|
|
8708
|
+
const fields = [...searchableFields(row, columns)].filter(([key]) => {
|
|
8709
|
+
if (scope === "all") return true;
|
|
8710
|
+
if (customScope) return customScope.fields?.includes(key) ?? false;
|
|
8711
|
+
return (options.roles?.[key] ?? inferTableSearchRole(key)) === scope;
|
|
8712
|
+
});
|
|
8713
|
+
const extra = scope === "all" ? extraText?.(row) : void 0;
|
|
8714
|
+
const texts = fields.map(([, value]) => value);
|
|
8715
|
+
if (extra) texts.push(extra);
|
|
8716
|
+
const matched = mode === "whole_words" ? matchesTableSearch(texts.join(" "), q, mode) : texts.some((value) => matchesTableSearch(value, q, mode));
|
|
8717
|
+
if (!matched) return [];
|
|
8718
|
+
let rank = 3;
|
|
8719
|
+
for (const [key, value] of fields) {
|
|
8720
|
+
if (!matchesTableSearch(value, q, mode)) continue;
|
|
8721
|
+
const role = options.roles?.[key] ?? inferTableSearchRole(key);
|
|
8722
|
+
if (role === "id" || role === "name") rank = Math.min(rank, value.trim().toLocaleLowerCase() === q ? 0 : 1);
|
|
8723
|
+
else if (role === "description") rank = Math.min(rank, 2);
|
|
8724
|
+
}
|
|
8725
|
+
return [{ row, rank, index }];
|
|
8726
|
+
}).sort((a, b) => a.rank - b.rank || a.index - b.index).map((item) => item.row);
|
|
8727
|
+
}
|
|
8728
|
+
|
|
8729
|
+
// src/data-table/ColumnManager.tsx
|
|
8730
|
+
import { useEffect as useEffect12, useMemo as useMemo7, useState as useState17 } from "react";
|
|
8731
|
+
import { useDndMonitor, useDraggable as useDraggable2, useDroppable } from "@dnd-kit/core";
|
|
8732
|
+
import { jsx as jsx33, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
8733
|
+
function ColumnManager({
|
|
8734
|
+
open,
|
|
8735
|
+
onOpenChange,
|
|
8736
|
+
columns,
|
|
8737
|
+
order,
|
|
8738
|
+
hidden,
|
|
8739
|
+
onApply
|
|
8740
|
+
}) {
|
|
8741
|
+
const byId = useMemo7(
|
|
8742
|
+
() => new Map(columns.map((column) => [columnId(column), column])),
|
|
8743
|
+
[columns]
|
|
8744
|
+
);
|
|
8745
|
+
const [draftOrder, setDraftOrder] = useState17(order);
|
|
8746
|
+
const [draftHidden, setDraftHidden] = useState17(() => new Set(hidden));
|
|
8747
|
+
const [draggedColumnId, setDraggedColumnId] = useState17(null);
|
|
8748
|
+
const [dropTarget, setDropTarget] = useState17(null);
|
|
8749
|
+
useEffect12(() => {
|
|
8750
|
+
if (!open) return;
|
|
8751
|
+
setDraftOrder(order);
|
|
8752
|
+
setDraftHidden(new Set(hidden));
|
|
8753
|
+
}, [open, order, hidden]);
|
|
8754
|
+
const move = (id, direction) => {
|
|
8755
|
+
setDraftOrder((current) => {
|
|
8756
|
+
const index = current.indexOf(id);
|
|
8757
|
+
const target = index + direction;
|
|
8758
|
+
if (index < 0 || target < 0 || target >= current.length) return current;
|
|
8759
|
+
const next = [...current];
|
|
8760
|
+
const displaced = next[target];
|
|
8761
|
+
if (displaced === void 0) return current;
|
|
8762
|
+
next[target] = id;
|
|
8763
|
+
next[index] = displaced;
|
|
8764
|
+
return next;
|
|
8765
|
+
});
|
|
8766
|
+
};
|
|
8767
|
+
const moveTo = (id, targetId) => {
|
|
8768
|
+
if (id === targetId) return;
|
|
8769
|
+
setDraftOrder((current) => {
|
|
8770
|
+
const from = current.indexOf(id);
|
|
8771
|
+
const target = current.indexOf(targetId);
|
|
8772
|
+
if (from < 0 || target < 0) return current;
|
|
8773
|
+
const next = [...current];
|
|
8774
|
+
next.splice(from, 1);
|
|
8775
|
+
const targetAfterRemoval = next.indexOf(targetId);
|
|
8776
|
+
next.splice(targetAfterRemoval, 0, id);
|
|
8777
|
+
return next;
|
|
8778
|
+
});
|
|
6883
8779
|
};
|
|
6884
8780
|
useDndMonitor({
|
|
6885
8781
|
onDragStart(event) {
|
|
@@ -7381,9 +9277,9 @@ function parseTableViewSnapshot(raw) {
|
|
|
7381
9277
|
|
|
7382
9278
|
// src/data-table/MatrxUuidCell.tsx
|
|
7383
9279
|
import {
|
|
7384
|
-
useEffect as
|
|
7385
|
-
useRef as
|
|
7386
|
-
useState as
|
|
9280
|
+
useEffect as useEffect13,
|
|
9281
|
+
useRef as useRef13,
|
|
9282
|
+
useState as useState18
|
|
7387
9283
|
} from "react";
|
|
7388
9284
|
import { jsx as jsx34, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
7389
9285
|
var SHORT_LEN = 8;
|
|
@@ -7424,11 +9320,11 @@ function MatrxUuidCell({
|
|
|
7424
9320
|
}) {
|
|
7425
9321
|
const { resolveEntityDoors, ResourcePeek } = useMatrxDataTableHost();
|
|
7426
9322
|
const { notify, notice } = useTableNotice();
|
|
7427
|
-
const [copied, setCopied] =
|
|
7428
|
-
const [opening, setOpening] =
|
|
7429
|
-
const [peekOpen, setPeekOpen] =
|
|
7430
|
-
const timer =
|
|
7431
|
-
|
|
9323
|
+
const [copied, setCopied] = useState18(false);
|
|
9324
|
+
const [opening, setOpening] = useState18(false);
|
|
9325
|
+
const [peekOpen, setPeekOpen] = useState18(false);
|
|
9326
|
+
const timer = useRef13(null);
|
|
9327
|
+
useEffect13(
|
|
7432
9328
|
() => () => {
|
|
7433
9329
|
if (timer.current) clearTimeout(timer.current);
|
|
7434
9330
|
},
|
|
@@ -7723,7 +9619,7 @@ function DataRowInspector({
|
|
|
7723
9619
|
}
|
|
7724
9620
|
|
|
7725
9621
|
// src/data-table/DataRowWindow.tsx
|
|
7726
|
-
import { useEffect as
|
|
9622
|
+
import { useEffect as useEffect14, useState as useState19 } from "react";
|
|
7727
9623
|
import { jsx as jsx36, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
7728
9624
|
function DataRowWindow({
|
|
7729
9625
|
isOpen,
|
|
@@ -7744,8 +9640,8 @@ function DataRowWindow({
|
|
|
7744
9640
|
const hasEdit = editContent != null;
|
|
7745
9641
|
const hasTabs = hasEdit && children == null;
|
|
7746
9642
|
const initialTab = defaultTab ?? (hasEdit ? "edit" : "view");
|
|
7747
|
-
const [tab, setTab] =
|
|
7748
|
-
|
|
9643
|
+
const [tab, setTab] = useState19(initialTab);
|
|
9644
|
+
useEffect14(() => {
|
|
7749
9645
|
if (!isOpen) return;
|
|
7750
9646
|
setTab(defaultTab ?? (hasEdit ? "edit" : "view"));
|
|
7751
9647
|
}, [isOpen, windowId, hasEdit, defaultTab]);
|
|
@@ -7895,8 +9791,8 @@ function toNumber(value) {
|
|
|
7895
9791
|
if (typeof value === "string") {
|
|
7896
9792
|
const cleaned = value.replace(/[,\s$€£¥%]/g, "");
|
|
7897
9793
|
if (cleaned === "") return null;
|
|
7898
|
-
const
|
|
7899
|
-
return Number.isFinite(
|
|
9794
|
+
const n2 = Number(cleaned);
|
|
9795
|
+
return Number.isFinite(n2) ? n2 : null;
|
|
7900
9796
|
}
|
|
7901
9797
|
return null;
|
|
7902
9798
|
}
|
|
@@ -7934,14 +9830,14 @@ function toList(value) {
|
|
|
7934
9830
|
}
|
|
7935
9831
|
return null;
|
|
7936
9832
|
}
|
|
7937
|
-
function groupedNumber(
|
|
9833
|
+
function groupedNumber(n2, options) {
|
|
7938
9834
|
return new Intl.NumberFormat(void 0, {
|
|
7939
9835
|
useGrouping: options.useGrouping !== false,
|
|
7940
9836
|
...options.precision != null ? {
|
|
7941
9837
|
minimumFractionDigits: options.precision,
|
|
7942
9838
|
maximumFractionDigits: options.precision
|
|
7943
9839
|
} : { maximumFractionDigits: 10 }
|
|
7944
|
-
}).format(
|
|
9840
|
+
}).format(n2);
|
|
7945
9841
|
}
|
|
7946
9842
|
function affix(text, options) {
|
|
7947
9843
|
return `${options.prefix ?? ""}${text}${options.suffix ?? ""}`;
|
|
@@ -8075,8 +9971,8 @@ var DEFS = [
|
|
|
8075
9971
|
numericAlign: true,
|
|
8076
9972
|
optionKeys: ["useGrouping", "precision", "prefix", "suffix"],
|
|
8077
9973
|
format: (v, o) => {
|
|
8078
|
-
const
|
|
8079
|
-
return
|
|
9974
|
+
const n2 = toNumber(v);
|
|
9975
|
+
return n2 === null ? null : affix(groupedNumber(n2, o), o);
|
|
8080
9976
|
},
|
|
8081
9977
|
parse: (raw) => toNumber(raw)
|
|
8082
9978
|
},
|
|
@@ -8091,9 +9987,9 @@ var DEFS = [
|
|
|
8091
9987
|
numericAlign: true,
|
|
8092
9988
|
optionKeys: ["precision", "useGrouping", "prefix", "suffix"],
|
|
8093
9989
|
format: (v, o) => {
|
|
8094
|
-
const
|
|
8095
|
-
if (
|
|
8096
|
-
return affix(groupedNumber(
|
|
9990
|
+
const n2 = toNumber(v);
|
|
9991
|
+
if (n2 === null) return null;
|
|
9992
|
+
return affix(groupedNumber(n2, { ...o, precision: o.precision ?? 2 }), o);
|
|
8097
9993
|
},
|
|
8098
9994
|
parse: (raw) => toNumber(raw)
|
|
8099
9995
|
},
|
|
@@ -8108,8 +10004,8 @@ var DEFS = [
|
|
|
8108
10004
|
numericAlign: true,
|
|
8109
10005
|
optionKeys: ["currency", "precision"],
|
|
8110
10006
|
format: (v, o) => {
|
|
8111
|
-
const
|
|
8112
|
-
if (
|
|
10007
|
+
const n2 = toNumber(v);
|
|
10008
|
+
if (n2 === null) return null;
|
|
8113
10009
|
const currency = (o.currency || "USD").toUpperCase();
|
|
8114
10010
|
try {
|
|
8115
10011
|
return new Intl.NumberFormat(void 0, {
|
|
@@ -8119,9 +10015,9 @@ var DEFS = [
|
|
|
8119
10015
|
minimumFractionDigits: o.precision,
|
|
8120
10016
|
maximumFractionDigits: o.precision
|
|
8121
10017
|
} : {}
|
|
8122
|
-
}).format(
|
|
10018
|
+
}).format(n2);
|
|
8123
10019
|
} catch {
|
|
8124
|
-
return `${groupedNumber(
|
|
10020
|
+
return `${groupedNumber(n2, { precision: o.precision ?? 2 })} ${currency}`;
|
|
8125
10021
|
}
|
|
8126
10022
|
},
|
|
8127
10023
|
parse: (raw) => toNumber(raw)
|
|
@@ -8137,9 +10033,9 @@ var DEFS = [
|
|
|
8137
10033
|
numericAlign: true,
|
|
8138
10034
|
optionKeys: ["percentScale", "precision"],
|
|
8139
10035
|
format: (v, o) => {
|
|
8140
|
-
const
|
|
8141
|
-
if (
|
|
8142
|
-
const shown = o.percentScale === "fraction" ?
|
|
10036
|
+
const n2 = toNumber(v);
|
|
10037
|
+
if (n2 === null) return null;
|
|
10038
|
+
const shown = o.percentScale === "fraction" ? n2 * 100 : n2;
|
|
8143
10039
|
return `${groupedNumber(shown, o.precision === void 0 ? {} : { precision: o.precision })}%`;
|
|
8144
10040
|
},
|
|
8145
10041
|
parse: (raw) => toNumber(raw)
|
|
@@ -8155,9 +10051,9 @@ var DEFS = [
|
|
|
8155
10051
|
numericAlign: true,
|
|
8156
10052
|
optionKeys: ["durationUnit"],
|
|
8157
10053
|
format: (v, o) => {
|
|
8158
|
-
const
|
|
8159
|
-
if (
|
|
8160
|
-
return formatSignedDuration(
|
|
10054
|
+
const n2 = toNumber(v);
|
|
10055
|
+
if (n2 === null) return null;
|
|
10056
|
+
return formatSignedDuration(n2 * DURATION_TO_SECONDS[o.durationUnit ?? "seconds"]);
|
|
8161
10057
|
},
|
|
8162
10058
|
parse: (raw) => toNumber(raw)
|
|
8163
10059
|
},
|
|
@@ -8172,13 +10068,13 @@ var DEFS = [
|
|
|
8172
10068
|
numericAlign: true,
|
|
8173
10069
|
optionKeys: ["useGrouping", "prefix", "suffix"],
|
|
8174
10070
|
format: (v, o) => {
|
|
8175
|
-
const
|
|
8176
|
-
if (
|
|
8177
|
-
return affix(groupedNumber(Math.trunc(
|
|
10071
|
+
const n2 = toNumber(v);
|
|
10072
|
+
if (n2 === null) return null;
|
|
10073
|
+
return affix(groupedNumber(Math.trunc(n2), { ...o, precision: 0 }), o);
|
|
8178
10074
|
},
|
|
8179
10075
|
parse: (raw) => {
|
|
8180
|
-
const
|
|
8181
|
-
return
|
|
10076
|
+
const n2 = toNumber(raw);
|
|
10077
|
+
return n2 === null ? null : Math.trunc(n2);
|
|
8182
10078
|
}
|
|
8183
10079
|
},
|
|
8184
10080
|
{
|
|
@@ -8192,15 +10088,15 @@ var DEFS = [
|
|
|
8192
10088
|
rich: true,
|
|
8193
10089
|
optionKeys: ["ratingMax"],
|
|
8194
10090
|
format: (v, o) => {
|
|
8195
|
-
const
|
|
8196
|
-
if (
|
|
10091
|
+
const n2 = toNumber(v);
|
|
10092
|
+
if (n2 === null) return null;
|
|
8197
10093
|
const max = o.ratingMax ?? 5;
|
|
8198
|
-
if (
|
|
8199
|
-
return `${
|
|
10094
|
+
if (n2 < 0 || n2 > max) return null;
|
|
10095
|
+
return `${n2} / ${max}`;
|
|
8200
10096
|
},
|
|
8201
10097
|
parse: (raw) => {
|
|
8202
|
-
const
|
|
8203
|
-
return
|
|
10098
|
+
const n2 = toNumber(raw);
|
|
10099
|
+
return n2 === null ? null : Math.round(n2);
|
|
8204
10100
|
}
|
|
8205
10101
|
},
|
|
8206
10102
|
{
|
|
@@ -8213,12 +10109,12 @@ var DEFS = [
|
|
|
8213
10109
|
editor: "number",
|
|
8214
10110
|
numericAlign: true,
|
|
8215
10111
|
format: (v) => {
|
|
8216
|
-
const
|
|
8217
|
-
return
|
|
10112
|
+
const n2 = toNumber(v);
|
|
10113
|
+
return n2 === null ? null : formatFileSize(n2);
|
|
8218
10114
|
},
|
|
8219
10115
|
parse: (raw) => {
|
|
8220
|
-
const
|
|
8221
|
-
return
|
|
10116
|
+
const n2 = toNumber(raw);
|
|
10117
|
+
return n2 === null ? null : Math.trunc(n2);
|
|
8222
10118
|
}
|
|
8223
10119
|
},
|
|
8224
10120
|
// ── Choice ────────────────────────────────────────────────────────────────
|
|
@@ -8628,8 +10524,19 @@ function DirtySavePill({
|
|
|
8628
10524
|
}
|
|
8629
10525
|
|
|
8630
10526
|
// src/data-table/EditableTableCell.tsx
|
|
8631
|
-
import { useEffect as
|
|
10527
|
+
import { useEffect as useEffect15, useRef as useRef14, useState as useState20 } from "react";
|
|
8632
10528
|
import { jsx as jsx39, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
10529
|
+
function CellRefusal({ reason }) {
|
|
10530
|
+
return /* @__PURE__ */ jsx39(
|
|
10531
|
+
"p",
|
|
10532
|
+
{
|
|
10533
|
+
role: "alert",
|
|
10534
|
+
"data-matrx-cell-refusal": "true",
|
|
10535
|
+
className: "mt-1 text-[11px] leading-snug text-amber-700 dark:text-amber-400",
|
|
10536
|
+
children: reason
|
|
10537
|
+
}
|
|
10538
|
+
);
|
|
10539
|
+
}
|
|
8633
10540
|
function CellEditShell({
|
|
8634
10541
|
href,
|
|
8635
10542
|
display,
|
|
@@ -8676,12 +10583,17 @@ function EditableTableCell({
|
|
|
8676
10583
|
className,
|
|
8677
10584
|
href,
|
|
8678
10585
|
editTrigger = "click",
|
|
8679
|
-
editRequest
|
|
10586
|
+
editRequest,
|
|
10587
|
+
editSeed
|
|
8680
10588
|
}) {
|
|
8681
|
-
const [open, setOpen] =
|
|
8682
|
-
|
|
10589
|
+
const [open, setOpen] = useState20(false);
|
|
10590
|
+
const [refusal, setRefusal] = useState20(null);
|
|
10591
|
+
useEffect15(() => {
|
|
8683
10592
|
if (editRequest !== void 0) setOpen(true);
|
|
8684
10593
|
}, [editRequest]);
|
|
10594
|
+
useEffect15(() => {
|
|
10595
|
+
if (!open) setRefusal(null);
|
|
10596
|
+
}, [open]);
|
|
8685
10597
|
const usePencil = Boolean(href) || editTrigger === "pencil";
|
|
8686
10598
|
if (editType === "string") {
|
|
8687
10599
|
return /* @__PURE__ */ jsx39(
|
|
@@ -8694,7 +10606,8 @@ function EditableTableCell({
|
|
|
8694
10606
|
...className === void 0 ? {} : { className },
|
|
8695
10607
|
...href === void 0 ? {} : { href },
|
|
8696
10608
|
usePencil,
|
|
8697
|
-
...editRequest === void 0 ? {} : { editRequest }
|
|
10609
|
+
...editRequest === void 0 ? {} : { editRequest },
|
|
10610
|
+
...editSeed === void 0 || editSeed === null ? {} : { editSeed }
|
|
8698
10611
|
}
|
|
8699
10612
|
);
|
|
8700
10613
|
}
|
|
@@ -8739,25 +10652,33 @@ function EditableTableCell({
|
|
|
8739
10652
|
) }) }),
|
|
8740
10653
|
/* @__PURE__ */ jsx39(TooltipContent, { children: "Edit value" })
|
|
8741
10654
|
] }),
|
|
8742
|
-
/* @__PURE__ */
|
|
10655
|
+
/* @__PURE__ */ jsxs29(
|
|
8743
10656
|
PopoverContent,
|
|
8744
10657
|
{
|
|
8745
10658
|
align: "start",
|
|
8746
|
-
className: "w-56 p-2",
|
|
8747
|
-
onClick: (e) => e.stopPropagation(),
|
|
8748
|
-
children:
|
|
8749
|
-
|
|
8750
|
-
|
|
8751
|
-
|
|
8752
|
-
|
|
8753
|
-
|
|
8754
|
-
|
|
8755
|
-
onCommit(next)
|
|
8756
|
-
|
|
8757
|
-
|
|
8758
|
-
|
|
8759
|
-
|
|
8760
|
-
|
|
10659
|
+
className: "w-56 p-2",
|
|
10660
|
+
onClick: (e) => e.stopPropagation(),
|
|
10661
|
+
children: [
|
|
10662
|
+
/* @__PURE__ */ jsx39(
|
|
10663
|
+
TypedEditor,
|
|
10664
|
+
{
|
|
10665
|
+
editType,
|
|
10666
|
+
value,
|
|
10667
|
+
editOptions,
|
|
10668
|
+
onCommit: (next) => {
|
|
10669
|
+
const refused = onCommit(next);
|
|
10670
|
+
if (typeof refused === "string" && refused) {
|
|
10671
|
+
setRefusal(refused);
|
|
10672
|
+
return;
|
|
10673
|
+
}
|
|
10674
|
+
setRefusal(null);
|
|
10675
|
+
setOpen(false);
|
|
10676
|
+
},
|
|
10677
|
+
onCancel: () => setOpen(false)
|
|
10678
|
+
}
|
|
10679
|
+
),
|
|
10680
|
+
refusal ? /* @__PURE__ */ jsx39(CellRefusal, { reason: refusal }) : null
|
|
10681
|
+
]
|
|
8761
10682
|
}
|
|
8762
10683
|
)
|
|
8763
10684
|
] });
|
|
@@ -8770,17 +10691,31 @@ function InlineStringEditor({
|
|
|
8770
10691
|
className,
|
|
8771
10692
|
href,
|
|
8772
10693
|
usePencil,
|
|
8773
|
-
editRequest
|
|
10694
|
+
editRequest,
|
|
10695
|
+
editSeed
|
|
8774
10696
|
}) {
|
|
8775
|
-
const [editing, setEditing] =
|
|
8776
|
-
const [draft, setDraft] =
|
|
8777
|
-
const
|
|
8778
|
-
|
|
10697
|
+
const [editing, setEditing] = useState20(false);
|
|
10698
|
+
const [draft, setDraft] = useState20(value);
|
|
10699
|
+
const [refusal, setRefusal] = useState20(null);
|
|
10700
|
+
const handledEditRequest = useRef14(void 0);
|
|
10701
|
+
const seedRef = useRef14(editSeed);
|
|
10702
|
+
seedRef.current = editSeed;
|
|
10703
|
+
useEffect15(() => {
|
|
8779
10704
|
if (editRequest === void 0 || handledEditRequest.current === editRequest) return;
|
|
8780
10705
|
handledEditRequest.current = editRequest;
|
|
8781
|
-
setDraft(value);
|
|
10706
|
+
setDraft(seedRef.current ?? value);
|
|
10707
|
+
setRefusal(null);
|
|
8782
10708
|
setEditing(true);
|
|
8783
10709
|
}, [editRequest, value]);
|
|
10710
|
+
const commit = (next) => {
|
|
10711
|
+
const refused = onCommit(next);
|
|
10712
|
+
if (typeof refused === "string" && refused) {
|
|
10713
|
+
setRefusal(refused);
|
|
10714
|
+
return false;
|
|
10715
|
+
}
|
|
10716
|
+
setRefusal(null);
|
|
10717
|
+
return true;
|
|
10718
|
+
};
|
|
8784
10719
|
if (!editing) {
|
|
8785
10720
|
if (usePencil) {
|
|
8786
10721
|
return /* @__PURE__ */ jsx39(
|
|
@@ -8831,32 +10766,38 @@ function InlineStringEditor({
|
|
|
8831
10766
|
/* @__PURE__ */ jsx39(TooltipContent, { children: "Click to edit" })
|
|
8832
10767
|
] });
|
|
8833
10768
|
}
|
|
8834
|
-
return /* @__PURE__ */
|
|
8835
|
-
|
|
8836
|
-
|
|
8837
|
-
|
|
8838
|
-
|
|
8839
|
-
|
|
8840
|
-
|
|
8841
|
-
|
|
8842
|
-
|
|
8843
|
-
|
|
8844
|
-
|
|
8845
|
-
|
|
8846
|
-
|
|
8847
|
-
|
|
8848
|
-
|
|
8849
|
-
|
|
8850
|
-
|
|
8851
|
-
|
|
8852
|
-
|
|
8853
|
-
|
|
8854
|
-
|
|
8855
|
-
|
|
8856
|
-
|
|
8857
|
-
|
|
8858
|
-
|
|
8859
|
-
|
|
10769
|
+
return /* @__PURE__ */ jsxs29("span", { className: "block w-full", children: [
|
|
10770
|
+
/* @__PURE__ */ jsx39(
|
|
10771
|
+
Input,
|
|
10772
|
+
{
|
|
10773
|
+
autoFocus: true,
|
|
10774
|
+
value: draft,
|
|
10775
|
+
onClick: (e) => e.stopPropagation(),
|
|
10776
|
+
onChange: (e) => {
|
|
10777
|
+
setDraft(e.target.value);
|
|
10778
|
+
if (refusal) setRefusal(null);
|
|
10779
|
+
},
|
|
10780
|
+
onBlur: () => {
|
|
10781
|
+
if (commit(draft)) setEditing(false);
|
|
10782
|
+
},
|
|
10783
|
+
onKeyDown: (e) => {
|
|
10784
|
+
if (e.key === "Enter") {
|
|
10785
|
+
e.preventDefault();
|
|
10786
|
+
if (commit(draft)) setEditing(false);
|
|
10787
|
+
}
|
|
10788
|
+
if (e.key === "Escape") {
|
|
10789
|
+
e.preventDefault();
|
|
10790
|
+
setRefusal(null);
|
|
10791
|
+
setEditing(false);
|
|
10792
|
+
}
|
|
10793
|
+
},
|
|
10794
|
+
"aria-invalid": refusal ? true : void 0,
|
|
10795
|
+
className: cn("h-7 text-sm", refusal && "border-amber-500 focus-visible:ring-amber-500"),
|
|
10796
|
+
style: { fontSize: "16px" }
|
|
10797
|
+
}
|
|
10798
|
+
),
|
|
10799
|
+
refusal ? /* @__PURE__ */ jsx39(CellRefusal, { reason: refusal }) : null
|
|
10800
|
+
] });
|
|
8860
10801
|
}
|
|
8861
10802
|
function TypedEditor({
|
|
8862
10803
|
editType,
|
|
@@ -8931,8 +10872,8 @@ function TagsEditor({
|
|
|
8931
10872
|
onCommit,
|
|
8932
10873
|
onCancel
|
|
8933
10874
|
}) {
|
|
8934
|
-
const [tags, setTags] =
|
|
8935
|
-
const [draft, setDraft] =
|
|
10875
|
+
const [tags, setTags] = useState20(value);
|
|
10876
|
+
const [draft, setDraft] = useState20("");
|
|
8936
10877
|
const add = (raw) => {
|
|
8937
10878
|
const next = raw.trim();
|
|
8938
10879
|
if (!next || tags.includes(next)) return;
|
|
@@ -9029,7 +10970,7 @@ function NumberEditor({
|
|
|
9029
10970
|
onCommit,
|
|
9030
10971
|
onCancel
|
|
9031
10972
|
}) {
|
|
9032
|
-
const [draft, setDraft] =
|
|
10973
|
+
const [draft, setDraft] = useState20(String(value));
|
|
9033
10974
|
return /* @__PURE__ */ jsxs29("div", { className: "flex flex-col gap-2", children: [
|
|
9034
10975
|
/* @__PURE__ */ jsx39(
|
|
9035
10976
|
Input,
|
|
@@ -9041,8 +10982,8 @@ function NumberEditor({
|
|
|
9041
10982
|
style: { fontSize: "16px" },
|
|
9042
10983
|
onKeyDown: (e) => {
|
|
9043
10984
|
if (e.key === "Enter") {
|
|
9044
|
-
const
|
|
9045
|
-
if (Number.isFinite(
|
|
10985
|
+
const n2 = Number(draft);
|
|
10986
|
+
if (Number.isFinite(n2)) onCommit(n2);
|
|
9046
10987
|
}
|
|
9047
10988
|
if (e.key === "Escape") onCancel();
|
|
9048
10989
|
}
|
|
@@ -9069,8 +11010,8 @@ function NumberEditor({
|
|
|
9069
11010
|
className: "h-7",
|
|
9070
11011
|
"aria-label": "Apply value",
|
|
9071
11012
|
onClick: () => {
|
|
9072
|
-
const
|
|
9073
|
-
if (Number.isFinite(
|
|
11013
|
+
const n2 = Number(draft);
|
|
11014
|
+
if (Number.isFinite(n2)) onCommit(n2);
|
|
9074
11015
|
},
|
|
9075
11016
|
children: /* @__PURE__ */ jsx39(Check, { className: "h-3.5 w-3.5" })
|
|
9076
11017
|
}
|
|
@@ -9159,7 +11100,7 @@ function resetToolbarFacets(facets) {
|
|
|
9159
11100
|
}
|
|
9160
11101
|
|
|
9161
11102
|
// src/data-table/LayeredFilterBuilder.tsx
|
|
9162
|
-
import { useState as
|
|
11103
|
+
import { useState as useState21 } from "react";
|
|
9163
11104
|
import { Fragment as Fragment5, jsx as jsx41, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
9164
11105
|
function moveRule(rules, from, to) {
|
|
9165
11106
|
if (from === to || to < 0 || to >= rules.length) return [...rules];
|
|
@@ -9176,8 +11117,8 @@ function LayeredFilterBuilder({
|
|
|
9176
11117
|
maxRules = 20,
|
|
9177
11118
|
label = "Advanced filters"
|
|
9178
11119
|
}) {
|
|
9179
|
-
const [open, setOpen] =
|
|
9180
|
-
const [draggedIndex, setDraggedIndex] =
|
|
11120
|
+
const [open, setOpen] = useState21(false);
|
|
11121
|
+
const [draggedIndex, setDraggedIndex] = useState21(null);
|
|
9181
11122
|
if (fields.length === 0) return null;
|
|
9182
11123
|
const updateRule = (index, patch) => {
|
|
9183
11124
|
onChange(
|
|
@@ -9721,7 +11662,7 @@ function MatrxDataTableWithUrlState({
|
|
|
9721
11662
|
...urlState.history === void 0 ? {} : { history: urlState.history },
|
|
9722
11663
|
...urlState.textHistory === void 0 ? {} : { textHistory: urlState.textHistory }
|
|
9723
11664
|
});
|
|
9724
|
-
|
|
11665
|
+
useEffect16(() => {
|
|
9725
11666
|
if (activeUrlTableIds.has(urlState.id)) {
|
|
9726
11667
|
throw new Error(
|
|
9727
11668
|
`Duplicate MatrxDataTable urlState.id "${urlState.id}" on one page. Give every table a unique stable id.`
|
|
@@ -9812,6 +11753,11 @@ function opensRowHref(event) {
|
|
|
9812
11753
|
function TableContextPassthrough({ children }) {
|
|
9813
11754
|
return /* @__PURE__ */ jsx42(Fragment7, { children });
|
|
9814
11755
|
}
|
|
11756
|
+
function sameWindow(a, b) {
|
|
11757
|
+
if (a === null || b === null) return a === b;
|
|
11758
|
+
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;
|
|
11759
|
+
}
|
|
11760
|
+
var NO_GROUPING_VALUE = "__matrx_no_grouping__";
|
|
9815
11761
|
function MatrxDataTableCore({
|
|
9816
11762
|
data: suppliedData,
|
|
9817
11763
|
columns,
|
|
@@ -9868,11 +11814,17 @@ function MatrxDataTableCore({
|
|
|
9868
11814
|
mobileCardsBreakpoint = "sm",
|
|
9869
11815
|
getRowHref,
|
|
9870
11816
|
onRowOpen,
|
|
9871
|
-
density
|
|
11817
|
+
density,
|
|
11818
|
+
grouping,
|
|
11819
|
+
virtualize,
|
|
11820
|
+
coverage,
|
|
11821
|
+
spreadsheet,
|
|
11822
|
+
facets,
|
|
11823
|
+
rowHeight: explicitRowHeight
|
|
9872
11824
|
}) {
|
|
9873
11825
|
const appendQuery = query?.mode === "controlled-append" ? query : null;
|
|
9874
11826
|
const appendQueryKey = appendQuery?.pagination.queryKey ?? null;
|
|
9875
|
-
const committedAppendQueryKey =
|
|
11827
|
+
const committedAppendQueryKey = useRef15(appendQueryKey);
|
|
9876
11828
|
const appendSourceChanged = appendQuery !== null && committedAppendQueryKey.current !== appendQueryKey;
|
|
9877
11829
|
const data = (appendQuery ? appendQuery.pagination.rows : suppliedData) ?? [];
|
|
9878
11830
|
const isLoading = appendQuery ? appendQuery.pagination.loading : suppliedLoading;
|
|
@@ -9884,10 +11836,10 @@ function MatrxDataTableCore({
|
|
|
9884
11836
|
const Link = host.Link ?? DefaultTableLink;
|
|
9885
11837
|
const SidePanelSurface = host.SidePanelSurface ?? DefaultTableSidePanel;
|
|
9886
11838
|
const { notify: toast, notice } = useTableNotice();
|
|
9887
|
-
const [savedViewError, setSavedViewError] =
|
|
9888
|
-
const [toolbarActionError, setToolbarActionError] =
|
|
9889
|
-
const [toolbarActionPending, setToolbarActionPending] =
|
|
9890
|
-
const toolbarActionPendingRef =
|
|
11839
|
+
const [savedViewError, setSavedViewError] = useState22(null);
|
|
11840
|
+
const [toolbarActionError, setToolbarActionError] = useState22(null);
|
|
11841
|
+
const [toolbarActionPending, setToolbarActionPending] = useState22({ refresh: false, add: false });
|
|
11842
|
+
const toolbarActionPendingRef = useRef15({ refresh: false, add: false });
|
|
9891
11843
|
const CHECKBOX_TAP_AREA = "h-4 w-4 touch-manipulation";
|
|
9892
11844
|
const mobileCardsClass = mobileCardsBreakpoint === "lg" ? "lg:hidden" : "sm:hidden";
|
|
9893
11845
|
const tableWithCardsClass = mobileCardsBreakpoint === "lg" ? "max-lg:hidden" : "max-sm:hidden";
|
|
@@ -9900,7 +11852,7 @@ function MatrxDataTableCore({
|
|
|
9900
11852
|
const sourceOwnsIntelligentSearch = sourceProcessing?.intelligentSearch === "source";
|
|
9901
11853
|
const sourceOwnsSearch = remoteQuery?.mode === "controlled" || appendQuery !== null && sourceProcessing === void 0 || sourceProcessing?.search === "source" || sourceOwnsIntelligentSearch;
|
|
9902
11854
|
const intelligentSearchEnabled = toolbar?.intelligentSearch !== void 0 && (sourceOwnsIntelligentSearch || remoteQuery === null && !sourceOwnsSearch);
|
|
9903
|
-
const emitControlledQueryChange =
|
|
11855
|
+
const emitControlledQueryChange = useCallback8(
|
|
9904
11856
|
(patch, options) => {
|
|
9905
11857
|
if (!controlledQuery) return;
|
|
9906
11858
|
controlledQuery.onStateChange(
|
|
@@ -9909,8 +11861,8 @@ function MatrxDataTableCore({
|
|
|
9909
11861
|
},
|
|
9910
11862
|
[controlledQuery]
|
|
9911
11863
|
);
|
|
9912
|
-
const [internalSearch, setInternalSearch] =
|
|
9913
|
-
const [draggedRowId, setDraggedRowId] =
|
|
11864
|
+
const [internalSearch, setInternalSearch] = useState22("");
|
|
11865
|
+
const [draggedRowId, setDraggedRowId] = useState22(null);
|
|
9914
11866
|
const hierarchySensors = useSensors(
|
|
9915
11867
|
useSensor(PointerSensor, {
|
|
9916
11868
|
activationConstraint: { distance: COLUMN_REORDER_ACTIVATION_DISTANCE }
|
|
@@ -9926,7 +11878,7 @@ function MatrxDataTableCore({
|
|
|
9926
11878
|
}
|
|
9927
11879
|
toolbar?.onSearchChange?.(v);
|
|
9928
11880
|
};
|
|
9929
|
-
const [internalSearchMatchMode, setInternalSearchMatchMode] =
|
|
11881
|
+
const [internalSearchMatchMode, setInternalSearchMatchMode] = useState22(
|
|
9930
11882
|
toolbar?.searchMatch?.defaultMode ?? "contains"
|
|
9931
11883
|
);
|
|
9932
11884
|
const searchMatchMode = controlledQuery ? controlledQuery.state.searchMatchMode ?? toolbar?.searchMatch?.defaultMode ?? "contains" : internalSearchMatchMode;
|
|
@@ -9937,7 +11889,7 @@ function MatrxDataTableCore({
|
|
|
9937
11889
|
}
|
|
9938
11890
|
setInternalSearchMatchMode(mode);
|
|
9939
11891
|
};
|
|
9940
|
-
const [internalSearchScope, setInternalSearchScope] =
|
|
11892
|
+
const [internalSearchScope, setInternalSearchScope] = useState22("all");
|
|
9941
11893
|
const searchScope = controlledQuery ? controlledQuery.state.searchScope ?? "all" : internalSearchScope;
|
|
9942
11894
|
const setSearchScope = (scope) => {
|
|
9943
11895
|
if (controlledQuery) {
|
|
@@ -9946,7 +11898,7 @@ function MatrxDataTableCore({
|
|
|
9946
11898
|
}
|
|
9947
11899
|
setInternalSearchScope(scope);
|
|
9948
11900
|
};
|
|
9949
|
-
const [internalAnyOf, setInternalAnyOf] =
|
|
11901
|
+
const [internalAnyOf, setInternalAnyOf] = useState22("");
|
|
9950
11902
|
const toolbarAnyOfControlled = toolbar?.anyOf?.value !== void 0;
|
|
9951
11903
|
const anyOfValue = controlledQuery ? controlledQuery.state.anyOf : toolbarAnyOfControlled ? toolbar?.anyOf?.value ?? "" : internalAnyOf;
|
|
9952
11904
|
const setAnyOfValue = (v) => {
|
|
@@ -9957,7 +11909,7 @@ function MatrxDataTableCore({
|
|
|
9957
11909
|
}
|
|
9958
11910
|
toolbar?.anyOf?.onChange?.(v);
|
|
9959
11911
|
};
|
|
9960
|
-
const [internalLayeredFilters, setInternalLayeredFilters] =
|
|
11912
|
+
const [internalLayeredFilters, setInternalLayeredFilters] = useState22([]);
|
|
9961
11913
|
const layeredFilters = controlledQuery ? controlledQuery.state.layeredFilters ?? [] : internalLayeredFilters;
|
|
9962
11914
|
const setLayeredFilters = (next) => {
|
|
9963
11915
|
if (controlledQuery) {
|
|
@@ -9966,7 +11918,7 @@ function MatrxDataTableCore({
|
|
|
9966
11918
|
}
|
|
9967
11919
|
setInternalLayeredFilters(next);
|
|
9968
11920
|
};
|
|
9969
|
-
const [internalColumnFilters, setInternalColumnFilters] =
|
|
11921
|
+
const [internalColumnFilters, setInternalColumnFilters] = useState22({});
|
|
9970
11922
|
const columnFilters = controlledQuery ? controlledQuery.state.columnFilters : internalColumnFilters;
|
|
9971
11923
|
const setColumnFilter = (id, next) => {
|
|
9972
11924
|
const nextFilters = { ...columnFilters, [id]: next };
|
|
@@ -9979,7 +11931,7 @@ function MatrxDataTableCore({
|
|
|
9979
11931
|
}
|
|
9980
11932
|
setInternalColumnFilters(nextFilters);
|
|
9981
11933
|
};
|
|
9982
|
-
const [internalSort, setInternalSort] =
|
|
11934
|
+
const [internalSort, setInternalSort] = useState22(defaultSort);
|
|
9983
11935
|
const sort = controlledQuery ? controlledQuery.state.sort : internalSort;
|
|
9984
11936
|
const setSort = (next) => {
|
|
9985
11937
|
if (controlledQuery) {
|
|
@@ -9988,7 +11940,7 @@ function MatrxDataTableCore({
|
|
|
9988
11940
|
}
|
|
9989
11941
|
setInternalSort(next);
|
|
9990
11942
|
};
|
|
9991
|
-
const [internalPage, setInternalPage] =
|
|
11943
|
+
const [internalPage, setInternalPage] = useState22(1);
|
|
9992
11944
|
const page = controlledQuery ? controlledQuery.state.page : internalPage;
|
|
9993
11945
|
const setPage = (next) => {
|
|
9994
11946
|
if (controlledQuery) {
|
|
@@ -9997,7 +11949,7 @@ function MatrxDataTableCore({
|
|
|
9997
11949
|
}
|
|
9998
11950
|
setInternalPage(next);
|
|
9999
11951
|
};
|
|
10000
|
-
const [internalPageSize, setInternalPageSize] =
|
|
11952
|
+
const [internalPageSize, setInternalPageSize] = useState22(
|
|
10001
11953
|
defaultPageSize
|
|
10002
11954
|
);
|
|
10003
11955
|
const pageSize = controlledQuery ? controlledQuery.state.pageSize : internalPageSize;
|
|
@@ -10008,28 +11960,28 @@ function MatrxDataTableCore({
|
|
|
10008
11960
|
}
|
|
10009
11961
|
setInternalPageSize(next);
|
|
10010
11962
|
};
|
|
10011
|
-
const [uncontrolledSelectedId, setUncontrolledSelectedId] =
|
|
11963
|
+
const [uncontrolledSelectedId, setUncontrolledSelectedId] = useState22(null);
|
|
10012
11964
|
const rawSelectedId = controlledSelectedId !== void 0 ? controlledSelectedId : uncontrolledSelectedId;
|
|
10013
11965
|
const selectedId = appendSourceChanged ? null : rawSelectedId;
|
|
10014
11966
|
const setSelectedId = (id) => {
|
|
10015
11967
|
if (controlledSelectedId === void 0) setUncontrolledSelectedId(id);
|
|
10016
11968
|
onSelectedIdChange?.(id);
|
|
10017
11969
|
};
|
|
10018
|
-
const [uncontrolledWindowRowId, setUncontrolledWindowRowId] =
|
|
11970
|
+
const [uncontrolledWindowRowId, setUncontrolledWindowRowId] = useState22(null);
|
|
10019
11971
|
const rawWindowRowId = controlledWindowRowId !== void 0 ? controlledWindowRowId : uncontrolledWindowRowId;
|
|
10020
11972
|
const windowRowId = appendSourceChanged ? null : rawWindowRowId;
|
|
10021
11973
|
const setWindowRowId = (id) => {
|
|
10022
11974
|
if (controlledWindowRowId === void 0) setUncontrolledWindowRowId(id);
|
|
10023
11975
|
onWindowRowIdChange?.(id);
|
|
10024
11976
|
};
|
|
10025
|
-
const [windowRowSnapshot, setWindowRowSnapshot] =
|
|
11977
|
+
const [windowRowSnapshot, setWindowRowSnapshot] = useState22(null);
|
|
10026
11978
|
const editScopeKey = appendQueryKey === null ? "\0local" : `append:${appendQueryKey}`;
|
|
10027
|
-
const [editsByScope, setEditsByScope] =
|
|
10028
|
-
const editRevisionRef =
|
|
10029
|
-
const [savingByScope, setSavingByScope] =
|
|
10030
|
-
const savingScopesRef =
|
|
10031
|
-
const [editRequest, setEditRequest] =
|
|
10032
|
-
const [confirmForeignDraftDiscard, setConfirmForeignDraftDiscard] =
|
|
11979
|
+
const [editsByScope, setEditsByScope] = useState22({});
|
|
11980
|
+
const editRevisionRef = useRef15({});
|
|
11981
|
+
const [savingByScope, setSavingByScope] = useState22({});
|
|
11982
|
+
const savingScopesRef = useRef15(/* @__PURE__ */ new Set());
|
|
11983
|
+
const [editRequest, setEditRequest] = useState22(null);
|
|
11984
|
+
const [confirmForeignDraftDiscard, setConfirmForeignDraftDiscard] = useState22(false);
|
|
10033
11985
|
const edits = editsByScope[editScopeKey]?.values ?? {};
|
|
10034
11986
|
const saving = (savingByScope[editScopeKey] ?? 0) > 0;
|
|
10035
11987
|
const setEdits = (next) => {
|
|
@@ -10096,7 +12048,7 @@ function MatrxDataTableCore({
|
|
|
10096
12048
|
rows: Object.entries(draft.values).map(([rowId, columns2]) => ({ rowId, columns: columns2 }))
|
|
10097
12049
|
}));
|
|
10098
12050
|
const selection = appendSourceChanged && selectionConfig ? { ...selectionConfig, selectedIds: [] } : selectionConfig;
|
|
10099
|
-
|
|
12051
|
+
useEffect16(() => {
|
|
10100
12052
|
const previous = committedAppendQueryKey.current;
|
|
10101
12053
|
committedAppendQueryKey.current = appendQueryKey;
|
|
10102
12054
|
if (previous === null || appendQueryKey === null || previous === appendQueryKey) {
|
|
@@ -10114,13 +12066,13 @@ function MatrxDataTableCore({
|
|
|
10114
12066
|
onWindowRowIdChange,
|
|
10115
12067
|
selectionConfig
|
|
10116
12068
|
]);
|
|
10117
|
-
const scrollRef =
|
|
10118
|
-
const tableRef =
|
|
10119
|
-
const tableHeaderRef =
|
|
10120
|
-
const cardsScrollRef =
|
|
10121
|
-
const [documentStickyHeader, setDocumentStickyHeader] =
|
|
10122
|
-
const documentStickyHeaderRef =
|
|
10123
|
-
const previousAppendKeyForScrollReset =
|
|
12069
|
+
const scrollRef = useRef15(null);
|
|
12070
|
+
const tableRef = useRef15(null);
|
|
12071
|
+
const tableHeaderRef = useRef15(null);
|
|
12072
|
+
const cardsScrollRef = useRef15(null);
|
|
12073
|
+
const [documentStickyHeader, setDocumentStickyHeader] = useState22(false);
|
|
12074
|
+
const documentStickyHeaderRef = useRef15(false);
|
|
12075
|
+
const previousAppendKeyForScrollReset = useRef15(appendQueryKey);
|
|
10124
12076
|
useLayoutEffect2(() => {
|
|
10125
12077
|
const previous = previousAppendKeyForScrollReset.current;
|
|
10126
12078
|
previousAppendKeyForScrollReset.current = appendQueryKey;
|
|
@@ -10146,13 +12098,13 @@ function MatrxDataTableCore({
|
|
|
10146
12098
|
...appendScrollPolicy?.mode === "scroll" && appendScrollPolicy.thresholdPx !== void 0 ? { thresholdPx: appendScrollPolicy.thresholdPx } : {},
|
|
10147
12099
|
...appendScrollPolicy?.mode === "scroll" && appendScrollPolicy.intentTimeoutMs !== void 0 ? { intentTimeoutMs: appendScrollPolicy.intentTimeoutMs } : {}
|
|
10148
12100
|
});
|
|
10149
|
-
const rootRef =
|
|
12101
|
+
const rootRef = useRef15(null);
|
|
10150
12102
|
useClippedContentGuard(rootRef, {
|
|
10151
12103
|
label: typeof copy === "object" && copy.listLabel ? `Table: ${copy.listLabel}` : "MatrxDataTable"
|
|
10152
12104
|
});
|
|
10153
|
-
const [scrollHintRight, setScrollHintRight] =
|
|
10154
|
-
const [scrollHintLeft, setScrollHintLeft] =
|
|
10155
|
-
const updateScrollHint =
|
|
12105
|
+
const [scrollHintRight, setScrollHintRight] = useState22(false);
|
|
12106
|
+
const [scrollHintLeft, setScrollHintLeft] = useState22(false);
|
|
12107
|
+
const updateScrollHint = useCallback8(() => {
|
|
10156
12108
|
const el = scrollRef.current;
|
|
10157
12109
|
if (!el) return;
|
|
10158
12110
|
setScrollHintRight(el.scrollLeft + el.clientWidth < el.scrollWidth - 2);
|
|
@@ -10166,7 +12118,7 @@ function MatrxDataTableCore({
|
|
|
10166
12118
|
behavior: "smooth"
|
|
10167
12119
|
});
|
|
10168
12120
|
};
|
|
10169
|
-
|
|
12121
|
+
useEffect16(() => {
|
|
10170
12122
|
updateScrollHint();
|
|
10171
12123
|
window.addEventListener("resize", updateScrollHint);
|
|
10172
12124
|
const el = scrollRef.current;
|
|
@@ -10240,30 +12192,30 @@ function MatrxDataTableCore({
|
|
|
10240
12192
|
window.removeEventListener("resize", requestUpdate);
|
|
10241
12193
|
};
|
|
10242
12194
|
}, [stickyHeader, data, columns]);
|
|
10243
|
-
const [columnOrder, setColumnOrder] =
|
|
10244
|
-
const [hiddenColumnIds, setHiddenColumnIds] =
|
|
12195
|
+
const [columnOrder, setColumnOrder] = useState22(() => columnState?.order ?? columns.map(columnId));
|
|
12196
|
+
const [hiddenColumnIds, setHiddenColumnIds] = useState22(
|
|
10245
12197
|
() => new Set(columnState?.hidden ?? columns.filter((column) => column.hidden).map(columnId))
|
|
10246
12198
|
);
|
|
10247
|
-
const [columnWidths, setColumnWidths] =
|
|
12199
|
+
const [columnWidths, setColumnWidths] = useState22(
|
|
10248
12200
|
() => normalizeColumnWidthsForColumns(columnState?.widths, columns)
|
|
10249
12201
|
);
|
|
10250
|
-
const [fixedTableGeometry, setFixedTableGeometry] =
|
|
10251
|
-
const knownColumnIds =
|
|
10252
|
-
const draggedColumnId =
|
|
10253
|
-
const columnDragActive =
|
|
10254
|
-
const columnDragRaf =
|
|
10255
|
-
const columnDragScrollDirection =
|
|
10256
|
-
const [columnDragPreview, setColumnDragPreview] =
|
|
10257
|
-
const stopColumnDragScroll =
|
|
12202
|
+
const [fixedTableGeometry, setFixedTableGeometry] = useState22(null);
|
|
12203
|
+
const knownColumnIds = useRef15(new Set(columns.map(columnId)));
|
|
12204
|
+
const draggedColumnId = useRef15(null);
|
|
12205
|
+
const columnDragActive = useRef15(false);
|
|
12206
|
+
const columnDragRaf = useRef15(null);
|
|
12207
|
+
const columnDragScrollDirection = useRef15(0);
|
|
12208
|
+
const [columnDragPreview, setColumnDragPreview] = useState22(null);
|
|
12209
|
+
const stopColumnDragScroll = useCallback8(() => {
|
|
10258
12210
|
if (columnDragRaf.current !== null) cancelAnimationFrame(columnDragRaf.current);
|
|
10259
12211
|
columnDragRaf.current = null;
|
|
10260
12212
|
columnDragScrollDirection.current = 0;
|
|
10261
12213
|
}, []);
|
|
10262
|
-
|
|
12214
|
+
useEffect16(() => () => {
|
|
10263
12215
|
columnDragActive.current = false;
|
|
10264
12216
|
stopColumnDragScroll();
|
|
10265
12217
|
}, [stopColumnDragScroll]);
|
|
10266
|
-
const startColumnDragScroll =
|
|
12218
|
+
const startColumnDragScroll = useCallback8(() => {
|
|
10267
12219
|
if (!columnDragActive.current || columnDragRaf.current !== null) return;
|
|
10268
12220
|
const scrollStep = () => {
|
|
10269
12221
|
const scroll = scrollRef.current;
|
|
@@ -10290,25 +12242,25 @@ function MatrxDataTableCore({
|
|
|
10290
12242
|
};
|
|
10291
12243
|
columnDragRaf.current = requestAnimationFrame(scrollStep);
|
|
10292
12244
|
}, []);
|
|
10293
|
-
const commitColumnState =
|
|
12245
|
+
const commitColumnState = useCallback8((order, hidden) => {
|
|
10294
12246
|
if (columnState) columnState.onChange({ order, hidden: [...hidden] });
|
|
10295
12247
|
else {
|
|
10296
12248
|
setColumnOrder(order);
|
|
10297
12249
|
setHiddenColumnIds(hidden);
|
|
10298
12250
|
}
|
|
10299
12251
|
}, [columnState]);
|
|
10300
|
-
const [internalColumnManagerOpen, setInternalColumnManagerOpen] =
|
|
12252
|
+
const [internalColumnManagerOpen, setInternalColumnManagerOpen] = useState22(false);
|
|
10301
12253
|
const columnManagerOpen = controlledColumnManager?.open ?? internalColumnManagerOpen;
|
|
10302
12254
|
const setColumnManagerOpen = controlledColumnManager?.onOpenChange ?? setInternalColumnManagerOpen;
|
|
10303
|
-
const columnIds =
|
|
10304
|
-
const effectiveColumnOrder =
|
|
10305
|
-
const effectiveHiddenColumnIds =
|
|
10306
|
-
const effectiveColumnWidths =
|
|
12255
|
+
const columnIds = useMemo8(() => columns.map(columnId), [columns]);
|
|
12256
|
+
const effectiveColumnOrder = useMemo8(() => 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]);
|
|
12257
|
+
const effectiveHiddenColumnIds = useMemo8(() => columnState ? new Set(columnState.hidden.filter((id) => columnIds.includes(id))) : hiddenColumnIds, [columnIds, columnState, hiddenColumnIds]);
|
|
12258
|
+
const effectiveColumnWidths = useMemo8(
|
|
10307
12259
|
() => normalizeColumnWidthsForColumns(columnState?.widths ?? columnWidths, columns),
|
|
10308
12260
|
[columns, columnState?.widths, columnWidths]
|
|
10309
12261
|
);
|
|
10310
|
-
const resizeGestureSnapshotRef =
|
|
10311
|
-
const measureVisibleColumnWidths =
|
|
12262
|
+
const resizeGestureSnapshotRef = useRef15(null);
|
|
12263
|
+
const measureVisibleColumnWidths = useCallback8(() => {
|
|
10312
12264
|
const measured = {};
|
|
10313
12265
|
const headers = tableRef.current ? Array.from(tableRef.current.querySelectorAll(
|
|
10314
12266
|
"thead th[data-matrx-table-column-id]"
|
|
@@ -10322,7 +12274,7 @@ function MatrxDataTableCore({
|
|
|
10322
12274
|
}
|
|
10323
12275
|
return normalizeColumnWidthsForColumns(measured, columns);
|
|
10324
12276
|
}, [columns]);
|
|
10325
|
-
const measureFixedTableGeometry =
|
|
12277
|
+
const measureFixedTableGeometry = useCallback8(() => {
|
|
10326
12278
|
const table = tableRef.current;
|
|
10327
12279
|
const headers = table ? Array.from(table.querySelectorAll("thead th")) : [];
|
|
10328
12280
|
const widthFor = (selector) => {
|
|
@@ -10357,16 +12309,16 @@ function MatrxDataTableCore({
|
|
|
10357
12309
|
...actionsWidth === void 0 ? {} : { actionsWidth }
|
|
10358
12310
|
};
|
|
10359
12311
|
}, [resolvedDensity]);
|
|
10360
|
-
const captureResizeGestureSnapshot =
|
|
12312
|
+
const captureResizeGestureSnapshot = useCallback8(() => {
|
|
10361
12313
|
resizeGestureSnapshotRef.current = {
|
|
10362
12314
|
widths: measureVisibleColumnWidths(),
|
|
10363
12315
|
geometry: measureFixedTableGeometry()
|
|
10364
12316
|
};
|
|
10365
12317
|
}, [measureFixedTableGeometry, measureVisibleColumnWidths]);
|
|
10366
|
-
const clearResizeGestureSnapshot =
|
|
12318
|
+
const clearResizeGestureSnapshot = useCallback8(() => {
|
|
10367
12319
|
resizeGestureSnapshotRef.current = null;
|
|
10368
12320
|
}, []);
|
|
10369
|
-
const commitColumnWidths =
|
|
12321
|
+
const commitColumnWidths = useCallback8((next, captureInitialWidths = false) => {
|
|
10370
12322
|
const gestureSnapshot = captureInitialWidths ? resizeGestureSnapshotRef.current : null;
|
|
10371
12323
|
resizeGestureSnapshotRef.current = null;
|
|
10372
12324
|
const normalized = normalizeColumnWidthsForColumns(
|
|
@@ -10385,7 +12337,7 @@ function MatrxDataTableCore({
|
|
|
10385
12337
|
}
|
|
10386
12338
|
setColumnWidths(normalized);
|
|
10387
12339
|
}, [columnIds, columnState, columns, measureFixedTableGeometry, measureVisibleColumnWidths]);
|
|
10388
|
-
|
|
12340
|
+
useEffect16(() => {
|
|
10389
12341
|
const ids = columns.map(columnId);
|
|
10390
12342
|
if (columnState) return;
|
|
10391
12343
|
const previousIds = knownColumnIds.current;
|
|
@@ -10409,12 +12361,12 @@ function MatrxDataTableCore({
|
|
|
10409
12361
|
tableRef.current?.style.removeProperty(columnResizeCssVar(id));
|
|
10410
12362
|
}
|
|
10411
12363
|
});
|
|
10412
|
-
const previewColumnOrder =
|
|
12364
|
+
const previewColumnOrder = useMemo8(
|
|
10413
12365
|
() => projectColumnDragOrder(effectiveColumnOrder, columnDragPreview),
|
|
10414
12366
|
[columnDragPreview, effectiveColumnOrder]
|
|
10415
12367
|
);
|
|
10416
12368
|
useColumnReorderAnimation(tableRef, previewColumnOrder.join("\0"), columnDragPreview !== null);
|
|
10417
|
-
const visibleColumns =
|
|
12369
|
+
const visibleColumns = useMemo8(() => {
|
|
10418
12370
|
const byId = new Map(columns.map((column) => [columnId(column), column]));
|
|
10419
12371
|
return previewColumnOrder.map((id) => byId.get(id)).filter(
|
|
10420
12372
|
(column) => column !== void 0 && !effectiveHiddenColumnIds.has(columnId(column))
|
|
@@ -10450,7 +12402,7 @@ function MatrxDataTableCore({
|
|
|
10450
12402
|
setFixedTableGeometry(geometry);
|
|
10451
12403
|
}, [resolvedDensity, measureFixedTableGeometry, usesMeasuredFixedLayout]);
|
|
10452
12404
|
const fixedLayoutActive = usesMeasuredFixedLayout && fixedTableGeometry !== null;
|
|
10453
|
-
const frozenColumns =
|
|
12405
|
+
const frozenColumns = useMemo8(() => {
|
|
10454
12406
|
if (!visibleColumns.some((column) => column.frozen)) return NO_FROZEN_COLUMNS;
|
|
10455
12407
|
const ids = visibleColumns.map(columnId);
|
|
10456
12408
|
const byId = new Map(visibleColumns.map((column) => [columnId(column), column]));
|
|
@@ -10492,7 +12444,7 @@ function MatrxDataTableCore({
|
|
|
10492
12444
|
);
|
|
10493
12445
|
return color ? CELL_TINT_CLASS[color] : void 0;
|
|
10494
12446
|
};
|
|
10495
|
-
const declaredVisibleCopyColumns =
|
|
12447
|
+
const declaredVisibleCopyColumns = useMemo8(
|
|
10496
12448
|
() => visibleColumns.filter((column) => column.accessorFn !== void 0 || column.accessorKey !== void 0),
|
|
10497
12449
|
[visibleColumns]
|
|
10498
12450
|
);
|
|
@@ -10500,7 +12452,7 @@ function MatrxDataTableCore({
|
|
|
10500
12452
|
const tableContextMenuInstanceId = useId2();
|
|
10501
12453
|
const tableDndContextId = useId2();
|
|
10502
12454
|
const defaultCopyTitle = toolbar?.title || "Table";
|
|
10503
|
-
const defaultCopy =
|
|
12455
|
+
const defaultCopy = useMemo8(() => ({
|
|
10504
12456
|
label: defaultCopyTitle,
|
|
10505
12457
|
listLabel: defaultCopyTitle,
|
|
10506
12458
|
location: defaultCopyTitle,
|
|
@@ -10535,7 +12487,7 @@ function MatrxDataTableCore({
|
|
|
10535
12487
|
serializer: (shaped) => buildViewAgentInput(effectiveCopy, shaped, data, { scope: "custom" })
|
|
10536
12488
|
}))
|
|
10537
12489
|
] : [];
|
|
10538
|
-
const filterMeta =
|
|
12490
|
+
const filterMeta = useMemo8(() => {
|
|
10539
12491
|
const meta = /* @__PURE__ */ new Map();
|
|
10540
12492
|
for (const col of visibleColumns) {
|
|
10541
12493
|
const id = columnId(col);
|
|
@@ -10543,14 +12495,14 @@ function MatrxDataTableCore({
|
|
|
10543
12495
|
}
|
|
10544
12496
|
return meta;
|
|
10545
12497
|
}, [visibleColumns, data, remoteQuery]);
|
|
10546
|
-
const intelligentSearchScopes =
|
|
12498
|
+
const intelligentSearchScopes = useMemo8(
|
|
10547
12499
|
() => resolveTableSearchScopes(data, columns, {
|
|
10548
12500
|
...toolbar?.intelligentSearch?.roles === void 0 ? {} : { roles: toolbar.intelligentSearch.roles },
|
|
10549
12501
|
...toolbar?.intelligentSearch?.scopes === void 0 ? {} : { scopes: toolbar.intelligentSearch.scopes }
|
|
10550
12502
|
}),
|
|
10551
12503
|
[columns, data, toolbar?.intelligentSearch?.roles, toolbar?.intelligentSearch?.scopes]
|
|
10552
12504
|
);
|
|
10553
|
-
const processed =
|
|
12505
|
+
const processed = useMemo8(() => {
|
|
10554
12506
|
if (remoteQuery && !appendUsesLocalProcessing) return data;
|
|
10555
12507
|
if (processLocalRows) {
|
|
10556
12508
|
return processLocalRows(data, {
|
|
@@ -10613,8 +12565,8 @@ function MatrxDataTableCore({
|
|
|
10613
12565
|
intelligentSearchEnabled,
|
|
10614
12566
|
searchScope
|
|
10615
12567
|
]);
|
|
10616
|
-
const lastNotifiedViewRows =
|
|
10617
|
-
|
|
12568
|
+
const lastNotifiedViewRows = useRef15(null);
|
|
12569
|
+
useEffect16(() => {
|
|
10618
12570
|
if (!onViewChange) {
|
|
10619
12571
|
lastNotifiedViewRows.current = null;
|
|
10620
12572
|
return;
|
|
@@ -10623,7 +12575,7 @@ function MatrxDataTableCore({
|
|
|
10623
12575
|
lastNotifiedViewRows.current = processed;
|
|
10624
12576
|
if (changed) onViewChange(processed);
|
|
10625
12577
|
}, [processed, onViewChange]);
|
|
10626
|
-
|
|
12578
|
+
useEffect16(() => {
|
|
10627
12579
|
if (controlledQuery) return;
|
|
10628
12580
|
setInternalPage(1);
|
|
10629
12581
|
}, [
|
|
@@ -10667,7 +12619,7 @@ function MatrxDataTableCore({
|
|
|
10667
12619
|
numberedPageHasMore: !hidePagination && !isLoading && !isFetching && processed.length > 0 && safePage < pageCount && (remoteQuery?.mode === "controlled" || !remoteQuery && localPagination?.mode === "numbered"),
|
|
10668
12620
|
onPageAdvance: setPage
|
|
10669
12621
|
});
|
|
10670
|
-
const paginated =
|
|
12622
|
+
const paginated = useMemo8(() => {
|
|
10671
12623
|
if (remoteQuery) return processed;
|
|
10672
12624
|
if (hidePagination) return processed;
|
|
10673
12625
|
if (localProgressiveEnabled) return [...progressiveRows.rows];
|
|
@@ -10675,15 +12627,351 @@ function MatrxDataTableCore({
|
|
|
10675
12627
|
const start = (safePage - 1) * effectivePageSize;
|
|
10676
12628
|
return processed.slice(start, start + effectivePageSize);
|
|
10677
12629
|
}, [processed, safePage, effectivePageSize, pageSize, remoteQuery, hidePagination, localProgressiveEnabled, progressiveRows.rows]);
|
|
10678
|
-
|
|
12630
|
+
const groupingColumnId = grouping?.columnId ?? null;
|
|
12631
|
+
const [uncontrolledCollapsed, setUncontrolledCollapsed] = useState22([]);
|
|
12632
|
+
const collapsedGroups = grouping?.collapsed ?? uncontrolledCollapsed;
|
|
12633
|
+
const setCollapsedGroups = useCallback8(
|
|
12634
|
+
(next) => {
|
|
12635
|
+
if (grouping?.onCollapsedChange) grouping.onCollapsedChange(next);
|
|
12636
|
+
else setUncontrolledCollapsed(next);
|
|
12637
|
+
},
|
|
12638
|
+
[grouping]
|
|
12639
|
+
);
|
|
12640
|
+
const groups = useMemo8(() => {
|
|
12641
|
+
if (!grouping || !groupingColumnId) return null;
|
|
12642
|
+
const groupColumn = columns.find((col) => columnId(col) === groupingColumnId);
|
|
12643
|
+
if (!groupColumn) return null;
|
|
12644
|
+
const aggregateColumns = {};
|
|
12645
|
+
for (const [aggColumnId, spec] of Object.entries(grouping.aggregates ?? {})) {
|
|
12646
|
+
const col = columns.find((c) => columnId(c) === aggColumnId);
|
|
12647
|
+
if (!col) continue;
|
|
12648
|
+
aggregateColumns[aggColumnId] = { spec, readCell: (row) => getCellValue(row, col) };
|
|
12649
|
+
}
|
|
12650
|
+
return groupRows({
|
|
12651
|
+
rows: paginated,
|
|
12652
|
+
columnId: groupingColumnId,
|
|
12653
|
+
readCell: (row) => grouping.readCell ? grouping.readCell(row, groupingColumnId) : getCellValue(row, groupColumn),
|
|
12654
|
+
aggregates: aggregateColumns,
|
|
12655
|
+
...grouping.order ? { order: grouping.order } : {},
|
|
12656
|
+
...grouping.emptyLabel ? { emptyLabel: grouping.emptyLabel } : {}
|
|
12657
|
+
});
|
|
12658
|
+
}, [grouping, groupingColumnId, columns, paginated]);
|
|
12659
|
+
const groupableColumns = useMemo8(() => {
|
|
12660
|
+
const allowed = grouping?.groupableColumnIds;
|
|
12661
|
+
return visibleColumns.filter((col) => {
|
|
12662
|
+
const id = columnId(col);
|
|
12663
|
+
if (allowed) return allowed.includes(id);
|
|
12664
|
+
return col.accessorKey !== void 0 || col.accessorFn !== void 0;
|
|
12665
|
+
});
|
|
12666
|
+
}, [visibleColumns, grouping?.groupableColumnIds]);
|
|
12667
|
+
const groupedRenderRows = useMemo8(
|
|
12668
|
+
() => groups ? flattenGroups(groups, collapsedGroups) : null,
|
|
12669
|
+
[groups, collapsedGroups]
|
|
12670
|
+
);
|
|
12671
|
+
const virtualizeConfig = virtualize === void 0 || virtualize === false ? null : virtualize === true ? {} : virtualize;
|
|
12672
|
+
const virtualRowHeight = explicitRowHeight ?? virtualizeConfig?.rowHeight ?? (resolvedDensity === "condensed" ? 32 : resolvedDensity === "spacious" ? 52 : 40);
|
|
12673
|
+
const virtualThreshold = virtualizeConfig?.threshold ?? 150;
|
|
12674
|
+
const bodyEntryCount = groupedRenderRows ? groupedRenderRows.length : paginated.length;
|
|
12675
|
+
const virtualizeActive = virtualizeConfig !== null && virtualizeConfig.enabled !== false && bodyEntryCount > virtualThreshold && !hierarchy && expandedDetail === void 0;
|
|
12676
|
+
const columnWindowWidth = virtualizeConfig?.columnWidth ?? 160;
|
|
12677
|
+
const frozenRunLength = useMemo8(() => {
|
|
12678
|
+
let run = 0;
|
|
12679
|
+
for (const col of visibleColumns) {
|
|
12680
|
+
if (frozenColumns.offsets[columnId(col)] === void 0) break;
|
|
12681
|
+
run += 1;
|
|
12682
|
+
}
|
|
12683
|
+
return run;
|
|
12684
|
+
}, [visibleColumns, frozenColumns]);
|
|
12685
|
+
const columnVirtualizeActive = virtualizeConfig !== null && virtualizeConfig.enabled !== false && virtualizeConfig.columns === true && visibleColumns.length - frozenRunLength > 30 && !hierarchy && mobileCards === void 0;
|
|
12686
|
+
const [rowWindow, setRowWindow] = useState22(null);
|
|
12687
|
+
const [columnWindow, setColumnWindow] = useState22(null);
|
|
12688
|
+
const windowInputs = useRef15({
|
|
12689
|
+
virtualizeActive: false,
|
|
12690
|
+
bodyEntryCount: 0,
|
|
12691
|
+
virtualRowHeight: 40,
|
|
12692
|
+
overscan: 8,
|
|
12693
|
+
columnVirtualizeActive: false,
|
|
12694
|
+
columnCount: 0,
|
|
12695
|
+
columnWindowWidth: 160,
|
|
12696
|
+
frozenRunLength: 0
|
|
12697
|
+
});
|
|
12698
|
+
windowInputs.current = {
|
|
12699
|
+
virtualizeActive,
|
|
12700
|
+
bodyEntryCount,
|
|
12701
|
+
virtualRowHeight,
|
|
12702
|
+
overscan: virtualizeConfig?.overscan ?? 8,
|
|
12703
|
+
columnVirtualizeActive,
|
|
12704
|
+
columnCount: visibleColumns.length,
|
|
12705
|
+
columnWindowWidth,
|
|
12706
|
+
frozenRunLength
|
|
12707
|
+
};
|
|
12708
|
+
const recomputeWindows = useCallback8(() => {
|
|
12709
|
+
const el = scrollRef.current;
|
|
12710
|
+
const input = windowInputs.current;
|
|
12711
|
+
const nextRow = input.virtualizeActive ? computeWindow({
|
|
12712
|
+
count: input.bodyEntryCount,
|
|
12713
|
+
itemSize: input.virtualRowHeight,
|
|
12714
|
+
viewport: el?.clientHeight || 600,
|
|
12715
|
+
offset: el?.scrollTop ?? 0,
|
|
12716
|
+
overscan: input.overscan
|
|
12717
|
+
}) : null;
|
|
12718
|
+
const nextColumn = input.columnVirtualizeActive ? computeWindow({
|
|
12719
|
+
count: input.columnCount,
|
|
12720
|
+
itemSize: input.columnWindowWidth,
|
|
12721
|
+
viewport: el?.clientWidth || 1200,
|
|
12722
|
+
offset: el?.scrollLeft ?? 0,
|
|
12723
|
+
overscan: Math.max(2, Math.round(input.overscan / 2)),
|
|
12724
|
+
pinnedStart: input.frozenRunLength
|
|
12725
|
+
}) : null;
|
|
12726
|
+
setRowWindow((prev) => sameWindow(prev, nextRow) ? prev : nextRow);
|
|
12727
|
+
setColumnWindow((prev) => sameWindow(prev, nextColumn) ? prev : nextColumn);
|
|
12728
|
+
}, []);
|
|
12729
|
+
const effectiveRowWindow = useMemo8(() => {
|
|
12730
|
+
if (!virtualizeActive) return null;
|
|
12731
|
+
if (rowWindow && rowWindow.end <= bodyEntryCount) return rowWindow;
|
|
12732
|
+
return computeWindow({
|
|
12733
|
+
count: bodyEntryCount,
|
|
12734
|
+
itemSize: virtualRowHeight,
|
|
12735
|
+
viewport: scrollRef.current?.clientHeight || 600,
|
|
12736
|
+
offset: scrollRef.current?.scrollTop ?? 0,
|
|
12737
|
+
overscan: virtualizeConfig?.overscan ?? 8
|
|
12738
|
+
});
|
|
12739
|
+
}, [virtualizeActive, rowWindow, bodyEntryCount, virtualRowHeight, virtualizeConfig?.overscan]);
|
|
12740
|
+
const effectiveColumnWindow = useMemo8(() => {
|
|
12741
|
+
if (!columnVirtualizeActive) return null;
|
|
12742
|
+
if (columnWindow && columnWindow.end <= visibleColumns.length) return columnWindow;
|
|
12743
|
+
return computeWindow({
|
|
12744
|
+
count: visibleColumns.length,
|
|
12745
|
+
itemSize: columnWindowWidth,
|
|
12746
|
+
viewport: scrollRef.current?.clientWidth || 1200,
|
|
12747
|
+
offset: scrollRef.current?.scrollLeft ?? 0,
|
|
12748
|
+
overscan: Math.max(2, Math.round((virtualizeConfig?.overscan ?? 8) / 2)),
|
|
12749
|
+
pinnedStart: frozenRunLength
|
|
12750
|
+
});
|
|
12751
|
+
}, [
|
|
12752
|
+
columnVirtualizeActive,
|
|
12753
|
+
columnWindow,
|
|
12754
|
+
visibleColumns.length,
|
|
12755
|
+
columnWindowWidth,
|
|
12756
|
+
virtualizeConfig?.overscan,
|
|
12757
|
+
frozenRunLength
|
|
12758
|
+
]);
|
|
12759
|
+
const metricsWanted = virtualizeActive || columnVirtualizeActive;
|
|
12760
|
+
useEffect16(() => {
|
|
12761
|
+
recomputeWindows();
|
|
12762
|
+
}, [
|
|
12763
|
+
recomputeWindows,
|
|
12764
|
+
virtualizeActive,
|
|
12765
|
+
bodyEntryCount,
|
|
12766
|
+
virtualRowHeight,
|
|
12767
|
+
columnVirtualizeActive,
|
|
12768
|
+
visibleColumns.length,
|
|
12769
|
+
columnWindowWidth,
|
|
12770
|
+
frozenRunLength
|
|
12771
|
+
]);
|
|
12772
|
+
useEffect16(() => {
|
|
12773
|
+
if (!metricsWanted) return;
|
|
12774
|
+
const el = scrollRef.current;
|
|
12775
|
+
if (!el) return;
|
|
12776
|
+
let frame = 0;
|
|
12777
|
+
const onScroll = () => {
|
|
12778
|
+
if (frame) return;
|
|
12779
|
+
frame = requestAnimationFrame(() => {
|
|
12780
|
+
frame = 0;
|
|
12781
|
+
recomputeWindows();
|
|
12782
|
+
});
|
|
12783
|
+
};
|
|
12784
|
+
el.addEventListener("scroll", onScroll, { passive: true });
|
|
12785
|
+
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(onScroll);
|
|
12786
|
+
observer?.observe(el);
|
|
12787
|
+
return () => {
|
|
12788
|
+
if (frame) cancelAnimationFrame(frame);
|
|
12789
|
+
el.removeEventListener("scroll", onScroll);
|
|
12790
|
+
observer?.disconnect();
|
|
12791
|
+
};
|
|
12792
|
+
}, [metricsWanted, recomputeWindows]);
|
|
12793
|
+
const renderedColumns = useMemo8(
|
|
12794
|
+
() => effectiveColumnWindow ? [
|
|
12795
|
+
...visibleColumns.slice(0, frozenRunLength),
|
|
12796
|
+
...visibleColumns.slice(effectiveColumnWindow.start, effectiveColumnWindow.end)
|
|
12797
|
+
] : visibleColumns,
|
|
12798
|
+
[effectiveColumnWindow, visibleColumns, frozenRunLength]
|
|
12799
|
+
);
|
|
12800
|
+
const columnSpacers = effectiveColumnWindow ? { start: effectiveColumnWindow.padStart, end: effectiveColumnWindow.padEnd } : null;
|
|
12801
|
+
const windowedWidthFor = useCallback8(
|
|
12802
|
+
(id, declared) => {
|
|
12803
|
+
const resized = effectiveColumnWidths[id];
|
|
12804
|
+
if (!effectiveColumnWindow) return resized;
|
|
12805
|
+
if (frozenColumns.offsets[id] !== void 0) return resized;
|
|
12806
|
+
return resized ?? (typeof declared === "number" ? declared : columnWindowWidth);
|
|
12807
|
+
},
|
|
12808
|
+
[effectiveColumnWindow, effectiveColumnWidths, frozenColumns, columnWindowWidth]
|
|
12809
|
+
);
|
|
12810
|
+
const coverageResult = useMemo8(() => {
|
|
12811
|
+
if (!coverage) return null;
|
|
12812
|
+
return describeCoverage({
|
|
12813
|
+
loaded: processed.length,
|
|
12814
|
+
...coverage.matched === void 0 ? {} : { matched: coverage.matched },
|
|
12815
|
+
...coverage.total === void 0 ? {} : { total: coverage.total },
|
|
12816
|
+
...coverage.cap === void 0 ? {} : { cap: coverage.cap },
|
|
12817
|
+
answeredBy: coverage.answeredBy ?? "client",
|
|
12818
|
+
...coverage.noun === void 0 ? {} : { noun: coverage.noun }
|
|
12819
|
+
});
|
|
12820
|
+
}, [coverage, processed.length]);
|
|
12821
|
+
const bodyEntries = useMemo8(() => {
|
|
12822
|
+
const from = effectiveRowWindow ? effectiveRowWindow.start : 0;
|
|
12823
|
+
const to = effectiveRowWindow ? effectiveRowWindow.end : void 0;
|
|
12824
|
+
const windowed = groupedRenderRows ? groupedRenderRows.slice(from, to).map(
|
|
12825
|
+
(entry) => entry.kind === "group" ? {
|
|
12826
|
+
kind: "group",
|
|
12827
|
+
group: entry.group,
|
|
12828
|
+
collapsed: isGroupCollapsed(collapsedGroups, entry.group.key)
|
|
12829
|
+
} : { kind: "row", row: entry.row, index: entry.dataIndex ?? 0 }
|
|
12830
|
+
) : paginated.slice(from, to).map((row, offset) => ({ kind: "row", row, index: from + offset }));
|
|
12831
|
+
if (!effectiveRowWindow) return windowed;
|
|
12832
|
+
if (effectiveRowWindow.padStart > 0)
|
|
12833
|
+
windowed.unshift({ kind: "spacer", height: effectiveRowWindow.padStart, place: "start" });
|
|
12834
|
+
if (effectiveRowWindow.padEnd > 0)
|
|
12835
|
+
windowed.push({ kind: "spacer", height: effectiveRowWindow.padEnd, place: "end" });
|
|
12836
|
+
return windowed;
|
|
12837
|
+
}, [groupedRenderRows, collapsedGroups, paginated, effectiveRowWindow]);
|
|
12838
|
+
const getRowIdRef = useRef15(getRowId);
|
|
12839
|
+
getRowIdRef.current = getRowId;
|
|
12840
|
+
const spreadsheetRowIds = useMemo8(
|
|
12841
|
+
() => paginated.map((row) => getRowIdRef.current(row)),
|
|
12842
|
+
[paginated]
|
|
12843
|
+
);
|
|
12844
|
+
const spreadsheetColumnIds = useMemo8(
|
|
12845
|
+
() => visibleColumns.map((col) => columnId(col)),
|
|
12846
|
+
[visibleColumns]
|
|
12847
|
+
);
|
|
12848
|
+
const spreadsheetRowById = useMemo8(() => {
|
|
12849
|
+
const map = /* @__PURE__ */ new Map();
|
|
12850
|
+
for (const row of paginated) map.set(getRowIdRef.current(row), row);
|
|
12851
|
+
return map;
|
|
12852
|
+
}, [paginated]);
|
|
12853
|
+
const spreadsheetColumnById = useMemo8(() => {
|
|
12854
|
+
const map = /* @__PURE__ */ new Map();
|
|
12855
|
+
for (const col of visibleColumns) map.set(columnId(col), col);
|
|
12856
|
+
return map;
|
|
12857
|
+
}, [visibleColumns]);
|
|
12858
|
+
const spreadsheetEnabled = Boolean(spreadsheet && spreadsheet.enabled !== false);
|
|
12859
|
+
const sheet = useSpreadsheetGrid(
|
|
12860
|
+
spreadsheetEnabled && spreadsheet ? {
|
|
12861
|
+
rowIds: spreadsheetRowIds,
|
|
12862
|
+
columnIds: spreadsheetColumnIds,
|
|
12863
|
+
valueAt: (rowId, colId) => {
|
|
12864
|
+
const row = spreadsheetRowById.get(rowId);
|
|
12865
|
+
const col = spreadsheetColumnById.get(colId);
|
|
12866
|
+
if (row === void 0 || col === void 0) return null;
|
|
12867
|
+
if (spreadsheet.readCell) return spreadsheet.readCell(row, colId);
|
|
12868
|
+
return getCellValue(applyRowEdits(row, edits[rowId]), col);
|
|
12869
|
+
},
|
|
12870
|
+
isColumnWritable: (colId) => {
|
|
12871
|
+
if (spreadsheet.writableColumnIds) return spreadsheet.writableColumnIds.includes(colId);
|
|
12872
|
+
const col = spreadsheetColumnById.get(colId);
|
|
12873
|
+
return Boolean(col && col.editable);
|
|
12874
|
+
},
|
|
12875
|
+
...spreadsheet.columnRefusal ? { columnRefusal: spreadsheet.columnRefusal } : {},
|
|
12876
|
+
onPatch: spreadsheet.onPatch,
|
|
12877
|
+
...spreadsheet.undoDepth === void 0 ? {} : { undoDepth: spreadsheet.undoDepth },
|
|
12878
|
+
...spreadsheet.fillHandle === void 0 ? {} : { fillHandle: spreadsheet.fillHandle },
|
|
12879
|
+
...spreadsheet.paste === void 0 ? {} : { paste: spreadsheet.paste },
|
|
12880
|
+
notify: spreadsheet.notify ?? ((message) => toast.success(message)),
|
|
12881
|
+
onEditRequest: (address, seed) => requestCellEditRef.current(address, seed),
|
|
12882
|
+
...spreadsheet.validateCell ? { validateCell: spreadsheet.validateCell } : {}
|
|
12883
|
+
} : null
|
|
12884
|
+
);
|
|
12885
|
+
const sheetRef = useRef15(sheet);
|
|
12886
|
+
sheetRef.current = sheet;
|
|
12887
|
+
const searchValueRef = useRef15(searchValue);
|
|
12888
|
+
searchValueRef.current = searchValue;
|
|
12889
|
+
const facetsEnabled = Boolean(facets && facets.enabled !== false);
|
|
12890
|
+
const [facetState, setFacetState] = useState22({});
|
|
12891
|
+
const facetReadCell = useCallback8(
|
|
12892
|
+
(row, colId) => {
|
|
12893
|
+
if (facets?.readCell) return facets.readCell(row, colId);
|
|
12894
|
+
const col = visibleColumns.find((candidate) => columnId(candidate) === colId);
|
|
12895
|
+
return col ? getFilterValue(row, col) : void 0;
|
|
12896
|
+
},
|
|
12897
|
+
[facets, visibleColumns]
|
|
12898
|
+
);
|
|
12899
|
+
const facetInputsRef = useRef15({ data, facets, facetReadCell });
|
|
12900
|
+
facetInputsRef.current = { data, facets, facetReadCell };
|
|
12901
|
+
const facetRequestRef = useRef15(/* @__PURE__ */ new Map());
|
|
12902
|
+
const requestFacets = useCallback8((colId) => {
|
|
12903
|
+
const { data: rows, facets: config, facetReadCell: readCell } = facetInputsRef.current;
|
|
12904
|
+
if (!config || config.enabled === false) return;
|
|
12905
|
+
const complete = localFacetsAreComplete(rows.length, config.totalRows);
|
|
12906
|
+
const limit = config.limit;
|
|
12907
|
+
if (complete || !config.source) {
|
|
12908
|
+
setFacetState((current) => ({
|
|
12909
|
+
...current,
|
|
12910
|
+
[colId]: {
|
|
12911
|
+
loading: false,
|
|
12912
|
+
data: computeColumnFacets({
|
|
12913
|
+
columnId: colId,
|
|
12914
|
+
rows,
|
|
12915
|
+
readValue: readCell,
|
|
12916
|
+
...limit === void 0 ? {} : { limit },
|
|
12917
|
+
complete
|
|
12918
|
+
})
|
|
12919
|
+
}
|
|
12920
|
+
}));
|
|
12921
|
+
return;
|
|
12922
|
+
}
|
|
12923
|
+
const ticket = (facetRequestRef.current.get(colId) ?? 0) + 1;
|
|
12924
|
+
facetRequestRef.current.set(colId, ticket);
|
|
12925
|
+
setFacetState((current) => ({
|
|
12926
|
+
...current,
|
|
12927
|
+
[colId]: { loading: true, data: current[colId]?.data ?? null }
|
|
12928
|
+
}));
|
|
12929
|
+
void Promise.resolve().then(
|
|
12930
|
+
() => config.source?.({ columnId: colId, search: searchValueRef.current, limit: limit ?? 200 })
|
|
12931
|
+
).then((answer) => {
|
|
12932
|
+
if (facetRequestRef.current.get(colId) !== ticket) return;
|
|
12933
|
+
if (!answer) {
|
|
12934
|
+
setFacetState((current) => ({
|
|
12935
|
+
...current,
|
|
12936
|
+
[colId]: {
|
|
12937
|
+
loading: false,
|
|
12938
|
+
data: computeColumnFacets({
|
|
12939
|
+
columnId: colId,
|
|
12940
|
+
rows: facetInputsRef.current.data,
|
|
12941
|
+
readValue: facetInputsRef.current.facetReadCell,
|
|
12942
|
+
...limit === void 0 ? {} : { limit },
|
|
12943
|
+
complete: false
|
|
12944
|
+
})
|
|
12945
|
+
}
|
|
12946
|
+
}));
|
|
12947
|
+
return;
|
|
12948
|
+
}
|
|
12949
|
+
setFacetState((current) => ({
|
|
12950
|
+
...current,
|
|
12951
|
+
[colId]: { loading: false, data: { ...answer, answeredBy: "source", complete: true } }
|
|
12952
|
+
}));
|
|
12953
|
+
}).catch((error) => {
|
|
12954
|
+
if (facetRequestRef.current.get(colId) !== ticket) return;
|
|
12955
|
+
setFacetState((current) => ({
|
|
12956
|
+
...current,
|
|
12957
|
+
[colId]: { loading: false, data: null, error: describeFacetFailure(error) }
|
|
12958
|
+
}));
|
|
12959
|
+
});
|
|
12960
|
+
}, []);
|
|
12961
|
+
useEffect16(() => {
|
|
12962
|
+
if (!facetsEnabled) return;
|
|
12963
|
+
setFacetState({});
|
|
12964
|
+
facetRequestRef.current = /* @__PURE__ */ new Map();
|
|
12965
|
+
}, [facetsEnabled, data, searchValue]);
|
|
12966
|
+
useEffect16(() => {
|
|
10679
12967
|
if (!controlledQuery || controlledQuery.state.page === safePage) return;
|
|
10680
12968
|
emitControlledQueryChange({ page: safePage });
|
|
10681
12969
|
}, [controlledQuery, emitControlledQueryChange, safePage]);
|
|
10682
|
-
const selectedRow =
|
|
12970
|
+
const selectedRow = useMemo8(() => {
|
|
10683
12971
|
if (!selectedId) return null;
|
|
10684
12972
|
return data.find((r) => getRowId(r) === selectedId) ?? null;
|
|
10685
12973
|
}, [data, selectedId, getRowId]);
|
|
10686
|
-
const windowRow =
|
|
12974
|
+
const windowRow = useMemo8(() => {
|
|
10687
12975
|
if (!windowRowId) return null;
|
|
10688
12976
|
return data.find((r) => getRowId(r) === windowRowId) ?? (windowRowSnapshot && windowRowSnapshot.queryKey === appendQueryKey && getRowId(windowRowSnapshot.row) === windowRowId ? windowRowSnapshot.row : null);
|
|
10689
12977
|
}, [data, windowRowId, windowRowSnapshot, getRowId, appendQueryKey]);
|
|
@@ -10718,12 +13006,12 @@ function MatrxDataTableCore({
|
|
|
10718
13006
|
return def !== void 0 && f.value !== def;
|
|
10719
13007
|
});
|
|
10720
13008
|
const hasActiveFilters = activeFilterCount > 0 || Boolean(searchValue.trim()) || intelligentSearchEnabled && searchScope !== "all" || Boolean(anyOfValue.trim()) || completeLayeredFilterRules(layeredFilters).length > 0 || facetActive;
|
|
10721
|
-
const changeCount =
|
|
10722
|
-
let
|
|
13009
|
+
const changeCount = useMemo8(() => {
|
|
13010
|
+
let n2 = 0;
|
|
10723
13011
|
for (const fields of Object.values(edits)) {
|
|
10724
|
-
|
|
13012
|
+
n2 += Object.keys(fields).length;
|
|
10725
13013
|
}
|
|
10726
|
-
return
|
|
13014
|
+
return n2;
|
|
10727
13015
|
}, [edits]);
|
|
10728
13016
|
const showSearch = toolbar?.search !== false;
|
|
10729
13017
|
const openDetail = (row) => {
|
|
@@ -10802,6 +13090,23 @@ function MatrxDataTableCore({
|
|
|
10802
13090
|
icon: void 0
|
|
10803
13091
|
} : emptyState;
|
|
10804
13092
|
const commitCell = (rowId, field, next) => {
|
|
13093
|
+
if (edit?.validate) {
|
|
13094
|
+
const row = data.find((candidate) => getRowId(candidate) === rowId);
|
|
13095
|
+
if (row) {
|
|
13096
|
+
let refusal;
|
|
13097
|
+
try {
|
|
13098
|
+
refusal = edit.validate({
|
|
13099
|
+
row: applyRowEdits(row, edits[rowId]),
|
|
13100
|
+
rowId,
|
|
13101
|
+
columnId: field,
|
|
13102
|
+
value: next
|
|
13103
|
+
});
|
|
13104
|
+
} catch {
|
|
13105
|
+
refusal = void 0;
|
|
13106
|
+
}
|
|
13107
|
+
if (refusal) return refusal;
|
|
13108
|
+
}
|
|
13109
|
+
}
|
|
10805
13110
|
const scope = editScopeKey;
|
|
10806
13111
|
const nextEdits = { [rowId]: { [field]: next } };
|
|
10807
13112
|
const revision = setCellEdit(rowId, field, next);
|
|
@@ -10846,9 +13151,29 @@ function MatrxDataTableCore({
|
|
|
10846
13151
|
setEditRequest((current) => ({
|
|
10847
13152
|
rowId: getRowId(row),
|
|
10848
13153
|
field,
|
|
10849
|
-
nonce: (current?.nonce ?? 0) + 1
|
|
13154
|
+
nonce: (current?.nonce ?? 0) + 1,
|
|
13155
|
+
seed: null
|
|
13156
|
+
}));
|
|
13157
|
+
};
|
|
13158
|
+
const requestCellEdit = (address, seed) => {
|
|
13159
|
+
if (!editEnabled) return false;
|
|
13160
|
+
const row = data.find((candidate) => getRowId(candidate) === address.rowId);
|
|
13161
|
+
if (!row) return false;
|
|
13162
|
+
const column = visibleColumns.find(
|
|
13163
|
+
(candidate) => columnId(candidate) === address.fieldName
|
|
13164
|
+
);
|
|
13165
|
+
if (!column?.editable || !(column.editableIf?.(row) ?? true)) return false;
|
|
13166
|
+
const field = column.accessorKey ? String(column.accessorKey) : columnId(column);
|
|
13167
|
+
setEditRequest((current) => ({
|
|
13168
|
+
rowId: address.rowId,
|
|
13169
|
+
field,
|
|
13170
|
+
nonce: (current?.nonce ?? 0) + 1,
|
|
13171
|
+
seed
|
|
10850
13172
|
}));
|
|
13173
|
+
return true;
|
|
10851
13174
|
};
|
|
13175
|
+
const requestCellEditRef = useRef15(requestCellEdit);
|
|
13176
|
+
requestCellEditRef.current = requestCellEdit;
|
|
10852
13177
|
const buildRecordControls = (row) => {
|
|
10853
13178
|
const rowId = getRowId(row);
|
|
10854
13179
|
const pending = edits[rowId];
|
|
@@ -10874,7 +13199,7 @@ function MatrxDataTableCore({
|
|
|
10874
13199
|
};
|
|
10875
13200
|
const hierarchyRows = hierarchy?.rows ?? data;
|
|
10876
13201
|
const hierarchyGetParentId = hierarchy?.getParentId;
|
|
10877
|
-
const hierarchyIndex =
|
|
13202
|
+
const hierarchyIndex = useMemo8(() => {
|
|
10878
13203
|
if (!hierarchyGetParentId) return null;
|
|
10879
13204
|
const byId = /* @__PURE__ */ new Map();
|
|
10880
13205
|
const parentById = /* @__PURE__ */ new Map();
|
|
@@ -10906,7 +13231,7 @@ function MatrxDataTableCore({
|
|
|
10906
13231
|
return { byId, parentById, depthById };
|
|
10907
13232
|
}, [hierarchyGetParentId, hierarchyRows, getRowId]);
|
|
10908
13233
|
const draggedRow = draggedRowId && hierarchyIndex ? hierarchyIndex.byId.get(draggedRowId) : void 0;
|
|
10909
|
-
const hierarchyBlockedIds =
|
|
13234
|
+
const hierarchyBlockedIds = useMemo8(() => {
|
|
10910
13235
|
if (!draggedRowId || !hierarchyIndex) return null;
|
|
10911
13236
|
const childrenById = /* @__PURE__ */ new Map();
|
|
10912
13237
|
for (const [id, parentId] of hierarchyIndex.parentById) {
|
|
@@ -11089,19 +13414,80 @@ function MatrxDataTableCore({
|
|
|
11089
13414
|
setEdits({});
|
|
11090
13415
|
edit?.onCancel?.();
|
|
11091
13416
|
};
|
|
11092
|
-
|
|
11093
|
-
|
|
11094
|
-
return host.rowContextRegistry.register(tableContextMenuInstanceId, (rowId) => {
|
|
13417
|
+
const resolveMenuLevel = (target) => {
|
|
13418
|
+
const rowFor = (rowId) => {
|
|
11095
13419
|
const row = data.find((candidate) => getRowId(candidate) === rowId);
|
|
11096
13420
|
if (!row) return null;
|
|
11097
|
-
|
|
11098
|
-
|
|
11099
|
-
|
|
11100
|
-
|
|
11101
|
-
|
|
11102
|
-
|
|
13421
|
+
return applyRowEdits(row, edits[rowId]);
|
|
13422
|
+
};
|
|
13423
|
+
const columnFor = (id) => visibleColumns.find((col) => columnId(col) === id);
|
|
13424
|
+
const labelFor = (col, id) => col?.label ?? (typeof col?.header === "string" ? col.header : id);
|
|
13425
|
+
const fromHost = (payload) => host.createDefaultMenuContext?.(payload) ?? null;
|
|
13426
|
+
switch (target.level) {
|
|
13427
|
+
case "row": {
|
|
13428
|
+
if (!target.rowId) return null;
|
|
13429
|
+
const displayRow = rowFor(target.rowId);
|
|
13430
|
+
if (!displayRow) return null;
|
|
13431
|
+
const controls = buildRecordControls(displayRow);
|
|
13432
|
+
return contextMenu?.resolveRowContext?.(displayRow, controls) ?? fromHost({ level: "row", row: displayRow, rowId: target.rowId, controls });
|
|
13433
|
+
}
|
|
13434
|
+
case "cell": {
|
|
13435
|
+
if (!target.rowId || !target.columnId) return null;
|
|
13436
|
+
const displayRow = rowFor(target.rowId);
|
|
13437
|
+
const col = columnFor(target.columnId);
|
|
13438
|
+
if (!displayRow || !col) return null;
|
|
13439
|
+
const controls = buildRecordControls(displayRow);
|
|
13440
|
+
const value = spreadsheet?.readCell ? spreadsheet.readCell(displayRow, target.columnId) : getCellValue(displayRow, col);
|
|
13441
|
+
const args = {
|
|
13442
|
+
row: displayRow,
|
|
13443
|
+
rowId: target.rowId,
|
|
13444
|
+
columnId: target.columnId,
|
|
13445
|
+
columnLabel: labelFor(col, target.columnId),
|
|
13446
|
+
value,
|
|
13447
|
+
text: stringifyCellValue(value),
|
|
13448
|
+
controls
|
|
13449
|
+
};
|
|
13450
|
+
return contextMenu?.resolveCellContext?.(args) ?? fromHost({ level: "cell", ...args });
|
|
13451
|
+
}
|
|
13452
|
+
case "column": {
|
|
13453
|
+
if (!target.columnId) return null;
|
|
13454
|
+
const col = columnFor(target.columnId);
|
|
13455
|
+
if (!col) return null;
|
|
13456
|
+
const args = {
|
|
13457
|
+
columnId: target.columnId,
|
|
13458
|
+
columnLabel: labelFor(col, target.columnId),
|
|
13459
|
+
values: paginated.map(
|
|
13460
|
+
(row) => getCellValue(applyRowEdits(row, edits[getRowId(row)]), col)
|
|
13461
|
+
)
|
|
13462
|
+
};
|
|
13463
|
+
return contextMenu?.resolveColumnContext?.(args) ?? fromHost({ level: "column", ...args });
|
|
13464
|
+
}
|
|
13465
|
+
case "selection": {
|
|
13466
|
+
const addresses = sheetRef.current.selectionAddresses();
|
|
13467
|
+
const cellCount = addresses.rowIds.length * addresses.columnIds.length;
|
|
13468
|
+
if (cellCount <= 1) {
|
|
13469
|
+
return resolveMenuLevel({ ...target, level: "cell" });
|
|
13470
|
+
}
|
|
13471
|
+
const args = { ...addresses, tsv: sheetRef.current.selectionTsv(), cellCount };
|
|
13472
|
+
return contextMenu?.resolveSelectionContext?.(args) ?? fromHost({ level: "selection", ...args });
|
|
13473
|
+
}
|
|
13474
|
+
case "table": {
|
|
13475
|
+
const args = { rowCount: data.length, columnIds: visibleColumns.map((col) => columnId(col)) };
|
|
13476
|
+
return contextMenu?.resolveTableContext?.(args) ?? fromHost({ level: "table", ...args });
|
|
13477
|
+
}
|
|
13478
|
+
}
|
|
13479
|
+
};
|
|
13480
|
+
const resolveMenuLevelRef = useRef15(resolveMenuLevel);
|
|
13481
|
+
resolveMenuLevelRef.current = resolveMenuLevel;
|
|
13482
|
+
useEffect16(() => {
|
|
13483
|
+
if (!host.rowContextRegistry) return;
|
|
13484
|
+
return host.rowContextRegistry.register(
|
|
13485
|
+
tableContextMenuInstanceId,
|
|
13486
|
+
(target) => resolveMenuLevelRef.current(target)
|
|
13487
|
+
);
|
|
13488
|
+
}, [host.rowContextRegistry, tableContextMenuInstanceId]);
|
|
11103
13489
|
const showActionsCol = windowEnabled || Boolean(rowActions) || showInlineRowCopy;
|
|
11104
|
-
const selectedIdSet =
|
|
13490
|
+
const selectedIdSet = useMemo8(
|
|
11105
13491
|
() => new Set(selection?.selectedIds ?? []),
|
|
11106
13492
|
[selection?.selectedIds]
|
|
11107
13493
|
);
|
|
@@ -11113,11 +13499,11 @@ function MatrxDataTableCore({
|
|
|
11113
13499
|
);
|
|
11114
13500
|
const allOnPageSelected = selectableRows.length > 0 && selectedOnPage.length === selectableRows.length;
|
|
11115
13501
|
const someOnPageSelected = selectedOnPage.length > 0 && !allOnPageSelected;
|
|
11116
|
-
const selectedRows =
|
|
13502
|
+
const selectedRows = useMemo8(
|
|
11117
13503
|
() => data.filter((row) => selectedIdSet.has(getRowId(row))),
|
|
11118
13504
|
[data, selectedIdSet, getRowId]
|
|
11119
13505
|
);
|
|
11120
|
-
const lastToggledIndex =
|
|
13506
|
+
const lastToggledIndex = useRef15(null);
|
|
11121
13507
|
const setSelectedIds = (next) => selection?.onSelectedIdsChange([...next]);
|
|
11122
13508
|
const toggleRowSelected = (index, shiftKey) => {
|
|
11123
13509
|
if (!selection) return;
|
|
@@ -11154,6 +13540,7 @@ function MatrxDataTableCore({
|
|
|
11154
13540
|
const selectionNoun = selection?.noun ?? "row";
|
|
11155
13541
|
const selectionCount = selection?.selectedIds.length ?? 0;
|
|
11156
13542
|
const leadingCols = selection ? 1 : 0;
|
|
13543
|
+
const renderedColSpan = renderedColumns.length + leadingCols + (showActionsCol ? 1 : 0) + (columnSpacers ? (columnSpacers.start > 0 ? 1 : 0) + (columnSpacers.end > 0 ? 1 : 0) : 0);
|
|
11157
13544
|
const renderedFacets = controlledQuery ? toolbar?.facets?.map(
|
|
11158
13545
|
(facet) => facet.type === "button-group" ? {
|
|
11159
13546
|
...facet,
|
|
@@ -11180,14 +13567,25 @@ function MatrxDataTableCore({
|
|
|
11180
13567
|
dirty: Boolean(rowEdits && field in rowEdits),
|
|
11181
13568
|
onCommit: (next) => commitCell(id, field, next),
|
|
11182
13569
|
...href === void 0 ? {} : { href },
|
|
11183
|
-
...
|
|
11184
|
-
|
|
13570
|
+
...spreadsheetEnabled ? {
|
|
13571
|
+
// 🚨 THE CLICK LAW, enforced where the two paths meet. In a grid
|
|
13572
|
+
// with spreadsheet gestures a single click SELECTS a cell — it
|
|
13573
|
+
// may never drop a person into a free-text buffer, because the
|
|
13574
|
+
// same click is how they start a range, and an editor that opens
|
|
13575
|
+
// under the pointer eats the drag and the next keystroke. So the
|
|
13576
|
+
// editor opens the way it does in Excel: Enter, F2, the hover
|
|
13577
|
+
// pencil, or simply typing. An explicit `editTrigger: "click"`
|
|
13578
|
+
// does not override this; the law is the table's, not the
|
|
13579
|
+
// column's.
|
|
13580
|
+
editTrigger: "pencil"
|
|
13581
|
+
} : col.editTrigger === void 0 ? {} : { editTrigger: col.editTrigger },
|
|
13582
|
+
...editRequest?.rowId === id && editRequest.field === field ? { editRequest: editRequest.nonce, editSeed: editRequest.seed } : {}
|
|
11185
13583
|
}
|
|
11186
13584
|
);
|
|
11187
13585
|
}
|
|
11188
13586
|
return href ? /* @__PURE__ */ jsx42(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;
|
|
11189
13587
|
};
|
|
11190
|
-
const currentViewSnapshot =
|
|
13588
|
+
const currentViewSnapshot = useMemo8(
|
|
11191
13589
|
() => ({
|
|
11192
13590
|
__kind: "matrx-table-view",
|
|
11193
13591
|
version: 1,
|
|
@@ -11222,7 +13620,7 @@ function MatrxDataTableCore({
|
|
|
11222
13620
|
sort
|
|
11223
13621
|
]
|
|
11224
13622
|
);
|
|
11225
|
-
const declaredDefaultViewSnapshot =
|
|
13623
|
+
const declaredDefaultViewSnapshot = useMemo8(
|
|
11226
13624
|
() => defaultViewSnapshot ?? {
|
|
11227
13625
|
__kind: "matrx-table-view",
|
|
11228
13626
|
version: 1,
|
|
@@ -11241,7 +13639,7 @@ function MatrxDataTableCore({
|
|
|
11241
13639
|
},
|
|
11242
13640
|
[columns, defaultPageSize, defaultSort, defaultViewSnapshot]
|
|
11243
13641
|
);
|
|
11244
|
-
const applySavedView =
|
|
13642
|
+
const applySavedView = useCallback8(
|
|
11245
13643
|
(rawSnapshot) => {
|
|
11246
13644
|
const snapshot = parseTableViewSnapshot(rawSnapshot);
|
|
11247
13645
|
if (!snapshot) {
|
|
@@ -11593,6 +13991,28 @@ function MatrxDataTableCore({
|
|
|
11593
13991
|
}
|
|
11594
13992
|
}
|
|
11595
13993
|
) : null,
|
|
13994
|
+
grouping?.onColumnIdChange ? /* @__PURE__ */ jsxs32(
|
|
13995
|
+
Select,
|
|
13996
|
+
{
|
|
13997
|
+
value: groupingColumnId ?? NO_GROUPING_VALUE,
|
|
13998
|
+
onValueChange: (value) => grouping.onColumnIdChange?.(value === NO_GROUPING_VALUE ? null : value),
|
|
13999
|
+
children: [
|
|
14000
|
+
/* @__PURE__ */ jsx42(
|
|
14001
|
+
SelectTrigger,
|
|
14002
|
+
{
|
|
14003
|
+
"data-matrx-table-group-by": true,
|
|
14004
|
+
"aria-label": "Group rows by a column",
|
|
14005
|
+
className: "h-8 w-auto min-w-[9rem] gap-1 text-xs",
|
|
14006
|
+
children: /* @__PURE__ */ jsx42(SelectValue, { placeholder: "No groups" })
|
|
14007
|
+
}
|
|
14008
|
+
),
|
|
14009
|
+
/* @__PURE__ */ jsxs32(SelectContent, { children: [
|
|
14010
|
+
/* @__PURE__ */ jsx42(SelectItem, { value: NO_GROUPING_VALUE, children: "No groups" }),
|
|
14011
|
+
groupableColumns.map((col) => /* @__PURE__ */ jsx42(SelectItem, { value: columnId(col), children: `Group by ${col.label ?? (typeof col.header === "string" ? col.header : columnId(col))}` }, columnId(col)))
|
|
14012
|
+
] })
|
|
14013
|
+
]
|
|
14014
|
+
}
|
|
14015
|
+
) : null,
|
|
11596
14016
|
columns.length > 0 ? /* @__PURE__ */ jsx42(
|
|
11597
14017
|
TableToolbarAction,
|
|
11598
14018
|
{
|
|
@@ -11660,65 +14080,6 @@ function MatrxDataTableCore({
|
|
|
11660
14080
|
]
|
|
11661
14081
|
}
|
|
11662
14082
|
),
|
|
11663
|
-
selection && selectionCount > 0 ? /* @__PURE__ */ jsxs32("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: [
|
|
11664
|
-
/* @__PURE__ */ jsxs32("span", { className: "text-xs font-medium text-foreground", children: [
|
|
11665
|
-
formatCount3(selectionCount),
|
|
11666
|
-
" ",
|
|
11667
|
-
selectionNoun,
|
|
11668
|
-
selectionCount === 1 ? "" : "s",
|
|
11669
|
-
" selected"
|
|
11670
|
-
] }),
|
|
11671
|
-
/* @__PURE__ */ jsxs32(
|
|
11672
|
-
Button,
|
|
11673
|
-
{
|
|
11674
|
-
type: "button",
|
|
11675
|
-
variant: "ghost",
|
|
11676
|
-
size: "sm",
|
|
11677
|
-
className: "h-7 gap-1 px-2 text-xs",
|
|
11678
|
-
onClick: () => {
|
|
11679
|
-
lastToggledIndex.current = null;
|
|
11680
|
-
selection.onSelectedIdsChange([]);
|
|
11681
|
-
},
|
|
11682
|
-
children: [
|
|
11683
|
-
/* @__PURE__ */ jsx42(X, { className: "h-3.5 w-3.5" }),
|
|
11684
|
-
"Clear"
|
|
11685
|
-
]
|
|
11686
|
-
}
|
|
11687
|
-
),
|
|
11688
|
-
/* @__PURE__ */ jsxs32("div", { className: "ml-auto flex flex-wrap items-center gap-1.5", children: [
|
|
11689
|
-
effectiveCopy && selectedRows.length > 0 ? /* @__PURE__ */ jsx42(
|
|
11690
|
-
CopyButtons,
|
|
11691
|
-
{
|
|
11692
|
-
size: "icon",
|
|
11693
|
-
"data-matrx-table-icon-action": true,
|
|
11694
|
-
sourceId: `${tableCopySourceNamespace}:selection`,
|
|
11695
|
-
...effectiveCopy.references ? { references: effectiveCopy.references(selectedRows, data) } : {},
|
|
11696
|
-
...effectiveCopy.triggerVariant ? { triggerVariant: effectiveCopy.triggerVariant } : {},
|
|
11697
|
-
label: `${selectedRows.length} selected ${selectionNoun}${selectedRows.length === 1 ? "" : "s"}`,
|
|
11698
|
-
...copy === void 0 ? {} : {
|
|
11699
|
-
human: () => buildViewHuman(effectiveCopy, selectedRows, effectiveCopyColumns),
|
|
11700
|
-
json: () => selectedRows.map((row) => effectiveCopy.agentRow ? effectiveCopy.agentRow(row) : row)
|
|
11701
|
-
},
|
|
11702
|
-
agent: () => copy === void 0 ? buildDefaultTableViewAgentInput(effectiveCopy, selectedRows, data, declaredVisibleCopyColumns, { scope: "selected" }) : buildViewAgentInput(effectiveCopy, selectedRows, data, { scope: "selected" }),
|
|
11703
|
-
aiVariants: copySubsetVariantFor(
|
|
11704
|
-
() => selectedRows,
|
|
11705
|
-
"selected"
|
|
11706
|
-
),
|
|
11707
|
-
export: {
|
|
11708
|
-
items: [],
|
|
11709
|
-
sheetRows: () => selectedRows.map(
|
|
11710
|
-
(row) => projectDefaultTableCopyRow(row, declaredVisibleCopyColumns)
|
|
11711
|
-
),
|
|
11712
|
-
sheetColumns: () => declaredVisibleCopyColumns.map((column) => ({
|
|
11713
|
-
id: columnId(column),
|
|
11714
|
-
label: column.label ?? (typeof column.header === "string" ? column.header : columnId(column))
|
|
11715
|
-
}))
|
|
11716
|
-
}
|
|
11717
|
-
}
|
|
11718
|
-
) : null,
|
|
11719
|
-
selection.actions?.(selectedRows, selection.selectedIds)
|
|
11720
|
-
] })
|
|
11721
|
-
] }) : null,
|
|
11722
14083
|
/* @__PURE__ */ jsxs32("div", { "data-matrx-table-body-region": true, className: "flex min-h-0 flex-1 flex-col gap-2", children: [
|
|
11723
14084
|
/* @__PURE__ */ jsxs32("div", { className: "relative min-h-0 flex-1", children: [
|
|
11724
14085
|
mobileCards ? /* @__PURE__ */ jsxs32(
|
|
@@ -11826,12 +14187,33 @@ function MatrxDataTableCore({
|
|
|
11826
14187
|
]
|
|
11827
14188
|
}
|
|
11828
14189
|
) : null,
|
|
14190
|
+
coverageResult && coverageResult.notice ? /* @__PURE__ */ jsxs32(
|
|
14191
|
+
"div",
|
|
14192
|
+
{
|
|
14193
|
+
"data-matrx-table-coverage": true,
|
|
14194
|
+
"data-matrx-table-coverage-scope": coverageResult.scope,
|
|
14195
|
+
role: "status",
|
|
14196
|
+
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",
|
|
14197
|
+
children: [
|
|
14198
|
+
/* @__PURE__ */ jsx42("span", { className: "font-semibold", children: coverageResult.badge }),
|
|
14199
|
+
/* @__PURE__ */ jsx42("span", { children: coverageResult.notice })
|
|
14200
|
+
]
|
|
14201
|
+
}
|
|
14202
|
+
) : null,
|
|
11829
14203
|
/* @__PURE__ */ jsxs32(
|
|
11830
14204
|
"div",
|
|
11831
14205
|
{
|
|
11832
14206
|
ref: scrollRef,
|
|
11833
14207
|
"data-matrx-table-scroll": true,
|
|
11834
14208
|
onScroll: updateScrollHint,
|
|
14209
|
+
...spreadsheetEnabled ? {
|
|
14210
|
+
tabIndex: sheet.containerProps.tabIndex,
|
|
14211
|
+
onKeyDown: sheet.containerProps.onKeyDown,
|
|
14212
|
+
onCopy: sheet.containerProps.onCopy,
|
|
14213
|
+
onCut: sheet.containerProps.onCut,
|
|
14214
|
+
onPaste: sheet.containerProps.onPaste,
|
|
14215
|
+
"data-matrx-table-spreadsheet": "true"
|
|
14216
|
+
} : {},
|
|
11835
14217
|
"aria-busy": isLoading || isFetching,
|
|
11836
14218
|
style: { containerType: "inline-size" },
|
|
11837
14219
|
className: cn(
|
|
@@ -11889,7 +14271,14 @@ function MatrxDataTableCore({
|
|
|
11889
14271
|
ref: tableHeaderRef,
|
|
11890
14272
|
"data-matrx-table-sticky-header": stickyHeader ? "true" : void 0,
|
|
11891
14273
|
className: cn(
|
|
11892
|
-
|
|
14274
|
+
// 🚨 ABOVE THE FROZEN COLUMN, NOT UNDER IT. A frozen body
|
|
14275
|
+
// cell is `sm:z-20` so it can slide under the columns to
|
|
14276
|
+
// its right; the header was `z-10`, so the frozen column's
|
|
14277
|
+
// cells scrolled straight OVER the header they belong to
|
|
14278
|
+
// and the top data row printed through the column names.
|
|
14279
|
+
// Only a table long enough to scroll shows it, which is why
|
|
14280
|
+
// it survived until a hundred-thousand-row screenshot.
|
|
14281
|
+
"z-30 border-b border-border bg-muted/90 shadow-[0_1px_0_0_var(--border)] backdrop-blur-sm",
|
|
11893
14282
|
stickyHeader && (documentStickyHeader ? "relative translate-y-[var(--matrx-document-sticky-offset)]" : "sticky top-0")
|
|
11894
14283
|
),
|
|
11895
14284
|
children: /* @__PURE__ */ jsxs32("tr", { children: [
|
|
@@ -11922,7 +14311,17 @@ function MatrxDataTableCore({
|
|
|
11922
14311
|
)
|
|
11923
14312
|
}
|
|
11924
14313
|
) : null,
|
|
11925
|
-
|
|
14314
|
+
columnSpacers && columnSpacers.start > 0 ? /* @__PURE__ */ jsx42(
|
|
14315
|
+
"th",
|
|
14316
|
+
{
|
|
14317
|
+
"aria-hidden": "true",
|
|
14318
|
+
"data-matrx-table-column-spacer": "start",
|
|
14319
|
+
className: "border-0 p-0",
|
|
14320
|
+
style: { width: `${columnSpacers.start}px`, minWidth: `${columnSpacers.start}px` }
|
|
14321
|
+
},
|
|
14322
|
+
"matrx-column-spacer-start"
|
|
14323
|
+
) : null,
|
|
14324
|
+
renderedColumns.map((col) => {
|
|
11926
14325
|
const id = columnId(col);
|
|
11927
14326
|
const meta = filterMeta.get(id);
|
|
11928
14327
|
const isSorted = sort?.id === id;
|
|
@@ -11938,6 +14337,7 @@ function MatrxDataTableCore({
|
|
|
11938
14337
|
"th",
|
|
11939
14338
|
{
|
|
11940
14339
|
"data-matrx-table-column-id": id,
|
|
14340
|
+
"data-matrx-header-column-id": id,
|
|
11941
14341
|
"data-matrx-column-drag-shadow": isColumnDragShadow ? "true" : void 0,
|
|
11942
14342
|
"aria-sort": isSorted ? sort?.direction === "asc" ? "ascending" : "descending" : void 0,
|
|
11943
14343
|
className: cn(
|
|
@@ -11965,7 +14365,7 @@ function MatrxDataTableCore({
|
|
|
11965
14365
|
frozenEdgeId === id && FROZEN_EDGE_CLASS
|
|
11966
14366
|
),
|
|
11967
14367
|
style: {
|
|
11968
|
-
...columnWidthVar(width,
|
|
14368
|
+
...columnWidthVar(width, windowedWidthFor(id, width), id, columnResizable),
|
|
11969
14369
|
...frozenStyle(id)
|
|
11970
14370
|
},
|
|
11971
14371
|
children: [
|
|
@@ -11974,6 +14374,12 @@ function MatrxDataTableCore({
|
|
|
11974
14374
|
{
|
|
11975
14375
|
label: col.header,
|
|
11976
14376
|
labelText: headerLabel,
|
|
14377
|
+
...facetsEnabled ? {
|
|
14378
|
+
facets: facetState[id]?.data ?? null,
|
|
14379
|
+
facetsLoading: facetState[id]?.loading ?? false,
|
|
14380
|
+
...facetState[id]?.error === void 0 ? {} : { facetsError: facetState[id]?.error },
|
|
14381
|
+
onFilterOpen: () => requestFacets(id)
|
|
14382
|
+
} : {},
|
|
11977
14383
|
sortable: col.sortable !== false,
|
|
11978
14384
|
isSorted: Boolean(isSorted),
|
|
11979
14385
|
sortDirection: sort?.direction ?? defaultSortDirection,
|
|
@@ -12029,6 +14435,16 @@ function MatrxDataTableCore({
|
|
|
12029
14435
|
id
|
|
12030
14436
|
);
|
|
12031
14437
|
}),
|
|
14438
|
+
columnSpacers && columnSpacers.end > 0 ? /* @__PURE__ */ jsx42(
|
|
14439
|
+
"th",
|
|
14440
|
+
{
|
|
14441
|
+
"aria-hidden": "true",
|
|
14442
|
+
"data-matrx-table-column-spacer": "end",
|
|
14443
|
+
className: "border-0 p-0",
|
|
14444
|
+
style: { width: `${columnSpacers.end}px`, minWidth: `${columnSpacers.end}px` }
|
|
14445
|
+
},
|
|
14446
|
+
"matrx-column-spacer-end"
|
|
14447
|
+
) : null,
|
|
12032
14448
|
showActionsCol && /* @__PURE__ */ jsx42(
|
|
12033
14449
|
"th",
|
|
12034
14450
|
{
|
|
@@ -12044,7 +14460,17 @@ function MatrxDataTableCore({
|
|
|
12044
14460
|
/* @__PURE__ */ jsxs32("tbody", { children: [
|
|
12045
14461
|
isLoading ? Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxs32("tr", { className: "border-b border-border/60", children: [
|
|
12046
14462
|
selection ? /* @__PURE__ */ jsx42("td", { className: "px-2 py-2", style: fixedUtilityWidth(fixedTableGeometry?.selectionWidth), children: /* @__PURE__ */ jsx42(Skeleton, { className: "h-3.5 w-3.5" }) }) : null,
|
|
12047
|
-
|
|
14463
|
+
columnSpacers && columnSpacers.start > 0 ? /* @__PURE__ */ jsx42(
|
|
14464
|
+
"td",
|
|
14465
|
+
{
|
|
14466
|
+
"aria-hidden": "true",
|
|
14467
|
+
"data-matrx-table-column-spacer": "start",
|
|
14468
|
+
className: "border-0 p-0",
|
|
14469
|
+
style: { width: `${columnSpacers.start}px`, minWidth: `${columnSpacers.start}px` }
|
|
14470
|
+
},
|
|
14471
|
+
"matrx-column-spacer-start"
|
|
14472
|
+
) : null,
|
|
14473
|
+
renderedColumns.map((col) => /* @__PURE__ */ jsx42(
|
|
12048
14474
|
"td",
|
|
12049
14475
|
{
|
|
12050
14476
|
className: cn(
|
|
@@ -12056,11 +14482,21 @@ function MatrxDataTableCore({
|
|
|
12056
14482
|
},
|
|
12057
14483
|
columnId(col)
|
|
12058
14484
|
)),
|
|
12059
|
-
showActionsCol && /* @__PURE__ */ jsx42("td", { className: "text-right align-middle", style: fixedUtilityWidth(fixedTableGeometry?.actionsWidth), children: /* @__PURE__ */ jsx42(Skeleton, { className: "ml-auto h-5 w-10" }) })
|
|
14485
|
+
showActionsCol && /* @__PURE__ */ jsx42("td", { className: "text-right align-middle", style: fixedUtilityWidth(fixedTableGeometry?.actionsWidth), children: /* @__PURE__ */ jsx42(Skeleton, { className: "ml-auto h-5 w-10" }) }),
|
|
14486
|
+
columnSpacers && columnSpacers.end > 0 ? /* @__PURE__ */ jsx42(
|
|
14487
|
+
"td",
|
|
14488
|
+
{
|
|
14489
|
+
"aria-hidden": "true",
|
|
14490
|
+
"data-matrx-table-column-spacer": "end",
|
|
14491
|
+
className: "border-0 p-0",
|
|
14492
|
+
style: { width: `${columnSpacers.end}px`, minWidth: `${columnSpacers.end}px` }
|
|
14493
|
+
},
|
|
14494
|
+
"matrx-column-spacer-end"
|
|
14495
|
+
) : null
|
|
12060
14496
|
] }, `sk-${i}`)) : paginated.length === 0 ? /* @__PURE__ */ jsx42("tr", { children: /* @__PURE__ */ jsx42(
|
|
12061
14497
|
"td",
|
|
12062
14498
|
{
|
|
12063
|
-
colSpan:
|
|
14499
|
+
colSpan: renderedColSpan,
|
|
12064
14500
|
className: "px-0 py-12 text-center",
|
|
12065
14501
|
children: /* @__PURE__ */ jsxs32("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: [
|
|
12066
14502
|
renderedEmptyState?.icon,
|
|
@@ -12069,7 +14505,43 @@ function MatrxDataTableCore({
|
|
|
12069
14505
|
renderedEmptyState?.action
|
|
12070
14506
|
] })
|
|
12071
14507
|
}
|
|
12072
|
-
) }) :
|
|
14508
|
+
) }) : bodyEntries.map((entry) => {
|
|
14509
|
+
if (entry.kind === "spacer") {
|
|
14510
|
+
return /* @__PURE__ */ jsx42(
|
|
14511
|
+
"tr",
|
|
14512
|
+
{
|
|
14513
|
+
"aria-hidden": "true",
|
|
14514
|
+
"data-matrx-table-virtual-spacer": entry.place,
|
|
14515
|
+
style: { height: `${entry.height}px` },
|
|
14516
|
+
children: /* @__PURE__ */ jsx42(
|
|
14517
|
+
"td",
|
|
14518
|
+
{
|
|
14519
|
+
className: "border-0 p-0",
|
|
14520
|
+
colSpan: renderedColSpan
|
|
14521
|
+
}
|
|
14522
|
+
)
|
|
14523
|
+
},
|
|
14524
|
+
`matrx-virtual-spacer-${entry.place}`
|
|
14525
|
+
);
|
|
14526
|
+
}
|
|
14527
|
+
if (entry.kind === "group") {
|
|
14528
|
+
return /* @__PURE__ */ jsx42(
|
|
14529
|
+
TableGroupHeaderRow,
|
|
14530
|
+
{
|
|
14531
|
+
group: entry.group,
|
|
14532
|
+
collapsed: entry.collapsed,
|
|
14533
|
+
columns: renderedColumns,
|
|
14534
|
+
spacers: columnSpacers,
|
|
14535
|
+
leadingCols,
|
|
14536
|
+
showActionsCol,
|
|
14537
|
+
rowNoun: grouping?.rowNoun ?? "row",
|
|
14538
|
+
onToggle: () => setCollapsedGroups(toggleGroupCollapsed(collapsedGroups, entry.group.key))
|
|
14539
|
+
},
|
|
14540
|
+
`matrx-group-${entry.group.key}`
|
|
14541
|
+
);
|
|
14542
|
+
}
|
|
14543
|
+
const row = entry.row;
|
|
14544
|
+
const index = entry.index;
|
|
12073
14545
|
const id = getRowId(row);
|
|
12074
14546
|
const isSelected = selectedId === id;
|
|
12075
14547
|
const rowEdits = edits[id];
|
|
@@ -12080,6 +14552,7 @@ function MatrxDataTableCore({
|
|
|
12080
14552
|
"tr",
|
|
12081
14553
|
{
|
|
12082
14554
|
"data-row-id": id,
|
|
14555
|
+
style: explicitRowHeight !== void 0 ? { height: `${explicitRowHeight}px` } : virtualizeActive ? { height: `${virtualRowHeight}px` } : void 0,
|
|
12083
14556
|
"data-state": isSelected ? "selected" : void 0,
|
|
12084
14557
|
onClick: (e) => {
|
|
12085
14558
|
if (rowEventTargetsInteractiveDescendant(e.target)) return;
|
|
@@ -12152,15 +14625,40 @@ function MatrxDataTableCore({
|
|
|
12152
14625
|
) : null
|
|
12153
14626
|
}
|
|
12154
14627
|
) : null,
|
|
12155
|
-
|
|
14628
|
+
columnSpacers && columnSpacers.start > 0 ? /* @__PURE__ */ jsx42(
|
|
14629
|
+
"td",
|
|
14630
|
+
{
|
|
14631
|
+
"aria-hidden": "true",
|
|
14632
|
+
"data-matrx-table-column-spacer": "start",
|
|
14633
|
+
className: "border-0 p-0",
|
|
14634
|
+
style: { width: `${columnSpacers.start}px`, minWidth: `${columnSpacers.start}px` }
|
|
14635
|
+
},
|
|
14636
|
+
"matrx-column-spacer-start"
|
|
14637
|
+
) : null,
|
|
14638
|
+
renderedColumns.map((col, colIdx) => {
|
|
12156
14639
|
const isColumnDragShadow = columnDragPreview?.draggedId === columnId(col) && columnDragPreview.targetId !== null;
|
|
12157
|
-
|
|
14640
|
+
const sheetCell = spreadsheetEnabled ? sheet.cellProps(id, columnId(col)) : null;
|
|
14641
|
+
const carriesFillHandle = sheetCell !== null && sheet.isFillHandleCell(id, columnId(col));
|
|
14642
|
+
return /* @__PURE__ */ jsxs32(
|
|
12158
14643
|
"td",
|
|
12159
14644
|
{
|
|
12160
14645
|
"data-matrx-table-column-id": columnId(col),
|
|
12161
14646
|
"data-matrx-column-drag-shadow": isColumnDragShadow ? "true" : void 0,
|
|
14647
|
+
...sheetCell ? {
|
|
14648
|
+
"data-matrx-cell-row": sheetCell["data-matrx-cell-row"],
|
|
14649
|
+
"data-matrx-cell-col": sheetCell["data-matrx-cell-col"],
|
|
14650
|
+
...sheetCell["data-matrx-cell-selected"] ? { "data-matrx-cell-selected": "true" } : {},
|
|
14651
|
+
...sheetCell["data-matrx-cell-active"] ? { "data-matrx-cell-active": "true" } : {},
|
|
14652
|
+
...sheetCell["data-matrx-cell-fill-preview"] ? { "data-matrx-cell-fill-preview": "true" } : {},
|
|
14653
|
+
onMouseDown: sheetCell.onMouseDown,
|
|
14654
|
+
onMouseEnter: sheetCell.onMouseEnter
|
|
14655
|
+
} : {},
|
|
12162
14656
|
className: cn(
|
|
12163
14657
|
"py-1.5 align-middle lg:py-0.5",
|
|
14658
|
+
sheetCell?.["data-matrx-cell-selected"] && "bg-primary/10",
|
|
14659
|
+
sheetCell?.["data-matrx-cell-fill-preview"] && "ring-1 ring-inset ring-primary/40",
|
|
14660
|
+
sheetCell?.["data-matrx-cell-active"] && "relative z-10 ring-2 ring-inset ring-primary",
|
|
14661
|
+
carriesFillHandle && "relative",
|
|
12164
14662
|
col.compact || resolveColumnMarker(col) !== void 0 ? "px-1" : "px-2",
|
|
12165
14663
|
// nowrap (NOT truncate — truncate clips the cell and
|
|
12166
14664
|
// defeats w-max, killing the horizontal scroll).
|
|
@@ -12182,42 +14680,64 @@ function MatrxDataTableCore({
|
|
|
12182
14680
|
style: {
|
|
12183
14681
|
...columnWidthVar(
|
|
12184
14682
|
resolveColumnMarker(col) && col.width === void 0 ? 40 : col.width,
|
|
12185
|
-
|
|
14683
|
+
windowedWidthFor(columnId(col), col.width),
|
|
12186
14684
|
columnId(col),
|
|
12187
14685
|
resizableColumns && col.resizable !== false
|
|
12188
14686
|
),
|
|
12189
14687
|
...frozenStyle(columnId(col))
|
|
12190
14688
|
},
|
|
12191
|
-
children:
|
|
12192
|
-
|
|
12193
|
-
|
|
12194
|
-
|
|
12195
|
-
|
|
12196
|
-
|
|
12197
|
-
|
|
12198
|
-
|
|
12199
|
-
|
|
12200
|
-
|
|
12201
|
-
|
|
12202
|
-
|
|
12203
|
-
|
|
12204
|
-
|
|
12205
|
-
|
|
12206
|
-
|
|
12207
|
-
|
|
12208
|
-
|
|
12209
|
-
|
|
12210
|
-
|
|
12211
|
-
|
|
12212
|
-
|
|
12213
|
-
|
|
12214
|
-
|
|
12215
|
-
|
|
12216
|
-
|
|
14689
|
+
children: [
|
|
14690
|
+
/* @__PURE__ */ jsxs32(
|
|
14691
|
+
"div",
|
|
14692
|
+
{
|
|
14693
|
+
className: cn(
|
|
14694
|
+
colIdx === 0 && hierarchy && "flex min-w-0 items-center"
|
|
14695
|
+
),
|
|
14696
|
+
children: [
|
|
14697
|
+
colIdx === 0 && hierarchy ? /* @__PURE__ */ jsx42(
|
|
14698
|
+
HierarchyDragHandle,
|
|
14699
|
+
{
|
|
14700
|
+
id,
|
|
14701
|
+
label: hierarchy.itemLabel?.(row) ?? "row",
|
|
14702
|
+
disabled: !(hierarchy.canReparent?.(row) ?? true)
|
|
14703
|
+
}
|
|
14704
|
+
) : null,
|
|
14705
|
+
/* @__PURE__ */ jsx42(
|
|
14706
|
+
"div",
|
|
14707
|
+
{
|
|
14708
|
+
"data-matrx-cell-content": true,
|
|
14709
|
+
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]",
|
|
14710
|
+
children: renderRecordCell(row, col, index)
|
|
14711
|
+
}
|
|
14712
|
+
)
|
|
14713
|
+
]
|
|
14714
|
+
}
|
|
14715
|
+
),
|
|
14716
|
+
carriesFillHandle ? /* @__PURE__ */ jsx42(
|
|
14717
|
+
"button",
|
|
14718
|
+
{
|
|
14719
|
+
type: "button",
|
|
14720
|
+
"data-matrx-table-fill-handle": true,
|
|
14721
|
+
"aria-label": "Drag to fill the cells below or beside this selection",
|
|
14722
|
+
onMouseDown: sheet.startFillDrag,
|
|
14723
|
+
className: "absolute -bottom-[3px] -right-[3px] z-20 h-2 w-2 cursor-crosshair rounded-[1px] border border-background bg-primary"
|
|
14724
|
+
}
|
|
14725
|
+
) : null
|
|
14726
|
+
]
|
|
12217
14727
|
},
|
|
12218
14728
|
columnId(col)
|
|
12219
14729
|
);
|
|
12220
14730
|
}),
|
|
14731
|
+
columnSpacers && columnSpacers.end > 0 ? /* @__PURE__ */ jsx42(
|
|
14732
|
+
"td",
|
|
14733
|
+
{
|
|
14734
|
+
"aria-hidden": "true",
|
|
14735
|
+
"data-matrx-table-column-spacer": "end",
|
|
14736
|
+
className: "border-0 p-0",
|
|
14737
|
+
style: { width: `${columnSpacers.end}px`, minWidth: `${columnSpacers.end}px` }
|
|
14738
|
+
},
|
|
14739
|
+
"matrx-column-spacer-end"
|
|
14740
|
+
) : null,
|
|
12221
14741
|
showActionsCol && /* @__PURE__ */ jsx42(
|
|
12222
14742
|
"td",
|
|
12223
14743
|
{
|
|
@@ -12280,7 +14800,7 @@ function MatrxDataTableCore({
|
|
|
12280
14800
|
children: /* @__PURE__ */ jsx42(
|
|
12281
14801
|
"td",
|
|
12282
14802
|
{
|
|
12283
|
-
colSpan:
|
|
14803
|
+
colSpan: renderedColSpan,
|
|
12284
14804
|
className: "p-4",
|
|
12285
14805
|
children: expandedDetail.render(displayRow, controls)
|
|
12286
14806
|
}
|
|
@@ -12306,7 +14826,7 @@ function MatrxDataTableCore({
|
|
|
12306
14826
|
appendQuery !== null && isFetching && !isLoading ? /* @__PURE__ */ jsx42("tr", { "data-matrx-table-append-loading-row": true, children: /* @__PURE__ */ jsx42(
|
|
12307
14827
|
"td",
|
|
12308
14828
|
{
|
|
12309
|
-
colSpan:
|
|
14829
|
+
colSpan: renderedColSpan,
|
|
12310
14830
|
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",
|
|
12311
14831
|
children: /* @__PURE__ */ jsxs32(
|
|
12312
14832
|
"div",
|
|
@@ -12331,7 +14851,17 @@ function MatrxDataTableCore({
|
|
|
12331
14851
|
] }),
|
|
12332
14852
|
footerRows.length > 0 ? /* @__PURE__ */ jsx42("tfoot", { className: "border-t-2 border-border bg-muted/50 font-semibold", children: footerRows.map((row, index) => /* @__PURE__ */ jsxs32("tr", { children: [
|
|
12333
14853
|
selection ? /* @__PURE__ */ jsx42("td", { className: "px-2 py-2" }) : null,
|
|
12334
|
-
|
|
14854
|
+
columnSpacers && columnSpacers.start > 0 ? /* @__PURE__ */ jsx42(
|
|
14855
|
+
"td",
|
|
14856
|
+
{
|
|
14857
|
+
"aria-hidden": "true",
|
|
14858
|
+
"data-matrx-table-column-spacer": "start",
|
|
14859
|
+
className: "border-0 p-0",
|
|
14860
|
+
style: { width: `${columnSpacers.start}px`, minWidth: `${columnSpacers.start}px` }
|
|
14861
|
+
},
|
|
14862
|
+
"matrx-column-spacer-start"
|
|
14863
|
+
) : null,
|
|
14864
|
+
renderedColumns.map((column) => /* @__PURE__ */ jsx42(
|
|
12335
14865
|
"td",
|
|
12336
14866
|
{
|
|
12337
14867
|
className: cn(
|
|
@@ -12343,7 +14873,7 @@ function MatrxDataTableCore({
|
|
|
12343
14873
|
),
|
|
12344
14874
|
style: columnWidthVar(
|
|
12345
14875
|
resolveColumnMarker(column) && column.width === void 0 ? 40 : column.width,
|
|
12346
|
-
|
|
14876
|
+
windowedWidthFor(columnId(column), column.width),
|
|
12347
14877
|
columnId(column),
|
|
12348
14878
|
resizableColumns && column.resizable !== false
|
|
12349
14879
|
),
|
|
@@ -12351,6 +14881,16 @@ function MatrxDataTableCore({
|
|
|
12351
14881
|
},
|
|
12352
14882
|
columnId(column)
|
|
12353
14883
|
)),
|
|
14884
|
+
columnSpacers && columnSpacers.end > 0 ? /* @__PURE__ */ jsx42(
|
|
14885
|
+
"td",
|
|
14886
|
+
{
|
|
14887
|
+
"aria-hidden": "true",
|
|
14888
|
+
"data-matrx-table-column-spacer": "end",
|
|
14889
|
+
className: "border-0 p-0",
|
|
14890
|
+
style: { width: `${columnSpacers.end}px`, minWidth: `${columnSpacers.end}px` }
|
|
14891
|
+
},
|
|
14892
|
+
"matrx-column-spacer-end"
|
|
14893
|
+
) : null,
|
|
12354
14894
|
showActionsCol ? /* @__PURE__ */ jsx42("td", {}) : null
|
|
12355
14895
|
] }, `footer-${index}`)) }) : null
|
|
12356
14896
|
]
|
|
@@ -12514,8 +15054,8 @@ function MatrxDataTableCore({
|
|
|
12514
15054
|
itemsPerPage: pageSize === 0 && allRowsAreLoaded ? 0 : effectivePageSize,
|
|
12515
15055
|
currentPage: safePage,
|
|
12516
15056
|
onPageChange: setPage,
|
|
12517
|
-
onItemsPerPageChange: (
|
|
12518
|
-
setPageSize(
|
|
15057
|
+
onItemsPerPageChange: (n2) => {
|
|
15058
|
+
setPageSize(n2);
|
|
12519
15059
|
if (!controlledQuery) setPage(1);
|
|
12520
15060
|
},
|
|
12521
15061
|
pageSizeOptions: pageSizeOptions.filter((size) => size > 0),
|
|
@@ -12525,7 +15065,73 @@ function MatrxDataTableCore({
|
|
|
12525
15065
|
compact: true,
|
|
12526
15066
|
hideEntriesInfo: false
|
|
12527
15067
|
}
|
|
12528
|
-
) }) : null
|
|
15068
|
+
) }) : null,
|
|
15069
|
+
selection && selectionCount > 0 ? /* @__PURE__ */ jsxs32(
|
|
15070
|
+
"div",
|
|
15071
|
+
{
|
|
15072
|
+
"data-matrx-table-bulk-bar": true,
|
|
15073
|
+
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",
|
|
15074
|
+
children: [
|
|
15075
|
+
/* @__PURE__ */ jsxs32("span", { className: "text-xs font-medium text-foreground", children: [
|
|
15076
|
+
formatCount3(selectionCount),
|
|
15077
|
+
" ",
|
|
15078
|
+
selectionNoun,
|
|
15079
|
+
selectionCount === 1 ? "" : "s",
|
|
15080
|
+
" selected"
|
|
15081
|
+
] }),
|
|
15082
|
+
/* @__PURE__ */ jsxs32(
|
|
15083
|
+
Button,
|
|
15084
|
+
{
|
|
15085
|
+
type: "button",
|
|
15086
|
+
variant: "ghost",
|
|
15087
|
+
size: "sm",
|
|
15088
|
+
className: "h-7 gap-1 px-2 text-xs",
|
|
15089
|
+
onClick: () => {
|
|
15090
|
+
lastToggledIndex.current = null;
|
|
15091
|
+
selection.onSelectedIdsChange([]);
|
|
15092
|
+
},
|
|
15093
|
+
children: [
|
|
15094
|
+
/* @__PURE__ */ jsx42(X, { className: "h-3.5 w-3.5" }),
|
|
15095
|
+
"Clear"
|
|
15096
|
+
]
|
|
15097
|
+
}
|
|
15098
|
+
),
|
|
15099
|
+
/* @__PURE__ */ jsxs32("div", { className: "ml-auto flex flex-wrap items-center gap-1.5", children: [
|
|
15100
|
+
effectiveCopy && selectedRows.length > 0 ? /* @__PURE__ */ jsx42(
|
|
15101
|
+
CopyButtons,
|
|
15102
|
+
{
|
|
15103
|
+
size: "icon",
|
|
15104
|
+
"data-matrx-table-icon-action": true,
|
|
15105
|
+
sourceId: `${tableCopySourceNamespace}:selection`,
|
|
15106
|
+
...effectiveCopy.references ? { references: effectiveCopy.references(selectedRows, data) } : {},
|
|
15107
|
+
...effectiveCopy.triggerVariant ? { triggerVariant: effectiveCopy.triggerVariant } : {},
|
|
15108
|
+
label: `${selectedRows.length} selected ${selectionNoun}${selectedRows.length === 1 ? "" : "s"}`,
|
|
15109
|
+
...copy === void 0 ? {} : {
|
|
15110
|
+
human: () => buildViewHuman(effectiveCopy, selectedRows, effectiveCopyColumns),
|
|
15111
|
+
json: () => selectedRows.map((row) => effectiveCopy.agentRow ? effectiveCopy.agentRow(row) : row)
|
|
15112
|
+
},
|
|
15113
|
+
agent: () => copy === void 0 ? buildDefaultTableViewAgentInput(effectiveCopy, selectedRows, data, declaredVisibleCopyColumns, { scope: "selected" }) : buildViewAgentInput(effectiveCopy, selectedRows, data, { scope: "selected" }),
|
|
15114
|
+
aiVariants: copySubsetVariantFor(
|
|
15115
|
+
() => selectedRows,
|
|
15116
|
+
"selected"
|
|
15117
|
+
),
|
|
15118
|
+
export: {
|
|
15119
|
+
items: [],
|
|
15120
|
+
sheetRows: () => selectedRows.map(
|
|
15121
|
+
(row) => projectDefaultTableCopyRow(row, declaredVisibleCopyColumns)
|
|
15122
|
+
),
|
|
15123
|
+
sheetColumns: () => declaredVisibleCopyColumns.map((column) => ({
|
|
15124
|
+
id: columnId(column),
|
|
15125
|
+
label: column.label ?? (typeof column.header === "string" ? column.header : columnId(column))
|
|
15126
|
+
}))
|
|
15127
|
+
}
|
|
15128
|
+
}
|
|
15129
|
+
) : null,
|
|
15130
|
+
selection.actions?.(selectedRows, selection.selectedIds)
|
|
15131
|
+
] })
|
|
15132
|
+
]
|
|
15133
|
+
}
|
|
15134
|
+
) : null
|
|
12529
15135
|
] }),
|
|
12530
15136
|
/* @__PURE__ */ jsx42(
|
|
12531
15137
|
ColumnManager,
|
|
@@ -12807,7 +15413,7 @@ function HierarchyDragIndicatorLayer({
|
|
|
12807
15413
|
scrollRef,
|
|
12808
15414
|
resolve: resolve2
|
|
12809
15415
|
}) {
|
|
12810
|
-
const [indicator, setIndicator] =
|
|
15416
|
+
const [indicator, setIndicator] = useState22(
|
|
12811
15417
|
null
|
|
12812
15418
|
);
|
|
12813
15419
|
useDndMonitor2({
|
|
@@ -12948,6 +15554,71 @@ function normalizeColumnWidthsForColumns(widths, columns) {
|
|
|
12948
15554
|
})
|
|
12949
15555
|
);
|
|
12950
15556
|
}
|
|
15557
|
+
function TableGroupHeaderRow({
|
|
15558
|
+
group,
|
|
15559
|
+
collapsed,
|
|
15560
|
+
columns,
|
|
15561
|
+
spacers,
|
|
15562
|
+
leadingCols,
|
|
15563
|
+
showActionsCol,
|
|
15564
|
+
rowNoun,
|
|
15565
|
+
onToggle
|
|
15566
|
+
}) {
|
|
15567
|
+
const count = group.rows.length;
|
|
15568
|
+
const summary = `${count.toLocaleString()} ${count === 1 ? rowNoun : `${rowNoun}s`}`;
|
|
15569
|
+
const firstId = columns[0] ? columnId(columns[0]) : null;
|
|
15570
|
+
return /* @__PURE__ */ jsxs32(
|
|
15571
|
+
"tr",
|
|
15572
|
+
{
|
|
15573
|
+
"data-matrx-table-group-row": group.key,
|
|
15574
|
+
"data-matrx-table-group-collapsed": collapsed ? "true" : "false",
|
|
15575
|
+
className: "border-y border-border bg-muted/40",
|
|
15576
|
+
children: [
|
|
15577
|
+
Array.from({ length: leadingCols }).map((_, i) => /* @__PURE__ */ jsx42("td", { className: "px-2 py-1.5" }, `group-lead-${i}`)),
|
|
15578
|
+
spacers && spacers.start > 0 ? /* @__PURE__ */ jsx42("td", { "aria-hidden": "true", className: "border-0 p-0", style: { width: `${spacers.start}px` } }) : null,
|
|
15579
|
+
columns.map((col) => {
|
|
15580
|
+
const id = columnId(col);
|
|
15581
|
+
const aggregate = group.aggregates[id];
|
|
15582
|
+
if (id === firstId) {
|
|
15583
|
+
return /* @__PURE__ */ jsx42("td", { className: cn("px-2 py-1.5 align-middle", col.mobileHidden && "max-sm:hidden"), children: /* @__PURE__ */ jsxs32("div", { className: "flex items-center gap-1.5", children: [
|
|
15584
|
+
/* @__PURE__ */ jsx42(
|
|
15585
|
+
"button",
|
|
15586
|
+
{
|
|
15587
|
+
type: "button",
|
|
15588
|
+
onClick: onToggle,
|
|
15589
|
+
"aria-expanded": !collapsed,
|
|
15590
|
+
"aria-label": `${collapsed ? "Show" : "Hide"} ${group.label}`,
|
|
15591
|
+
className: "inline-flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
15592
|
+
children: collapsed ? /* @__PURE__ */ jsx42(ChevronRight, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx42(ChevronDown, { className: "h-4 w-4" })
|
|
15593
|
+
}
|
|
15594
|
+
),
|
|
15595
|
+
/* @__PURE__ */ jsx42("span", { className: "truncate text-sm font-semibold text-foreground", children: group.label }),
|
|
15596
|
+
/* @__PURE__ */ jsx42("span", { className: "whitespace-nowrap text-xs text-muted-foreground", children: summary })
|
|
15597
|
+
] }) }, id);
|
|
15598
|
+
}
|
|
15599
|
+
return /* @__PURE__ */ jsx42(
|
|
15600
|
+
"td",
|
|
15601
|
+
{
|
|
15602
|
+
className: cn(
|
|
15603
|
+
"px-2 py-1.5 align-middle text-xs font-medium text-muted-foreground",
|
|
15604
|
+
// A subtotal lines up with the numbers it is a subtotal OF.
|
|
15605
|
+
// Left-aligned under a right-aligned money column it reads as a
|
|
15606
|
+
// different column's value.
|
|
15607
|
+
alignForFormat(col) === "center" && "text-center",
|
|
15608
|
+
alignForFormat(col) === "right" && "text-right",
|
|
15609
|
+
col.mobileHidden && "max-sm:hidden"
|
|
15610
|
+
),
|
|
15611
|
+
children: aggregate ? /* @__PURE__ */ jsx42("span", { "data-matrx-table-group-aggregate": id, className: "whitespace-nowrap", children: aggregate.label }) : null
|
|
15612
|
+
},
|
|
15613
|
+
id
|
|
15614
|
+
);
|
|
15615
|
+
}),
|
|
15616
|
+
spacers && spacers.end > 0 ? /* @__PURE__ */ jsx42("td", { "aria-hidden": "true", className: "border-0 p-0", style: { width: `${spacers.end}px` } }) : null,
|
|
15617
|
+
showActionsCol ? /* @__PURE__ */ jsx42("td", { className: "px-2 py-1.5" }) : null
|
|
15618
|
+
]
|
|
15619
|
+
}
|
|
15620
|
+
);
|
|
15621
|
+
}
|
|
12951
15622
|
function columnWidthVar(width, resizedWidth, id, resizable) {
|
|
12952
15623
|
if (width === void 0 && resizedWidth === void 0 && !resizable) return void 0;
|
|
12953
15624
|
const inferredWidth = resizable && inferTableSearchRole(id) === "name" ? "12rem" : "auto";
|
|
@@ -12957,7 +15628,7 @@ function columnWidthVar(width, resizedWidth, id, resizable) {
|
|
|
12957
15628
|
};
|
|
12958
15629
|
}
|
|
12959
15630
|
function DefaultJsonCell({ value }) {
|
|
12960
|
-
const [open, setOpen] =
|
|
15631
|
+
const [open, setOpen] = useState22(false);
|
|
12961
15632
|
const host = useMatrxDataTableHost();
|
|
12962
15633
|
const Viewer = host.JsonViewer;
|
|
12963
15634
|
const text = JSON.stringify(value, null, 2);
|
|
@@ -13040,7 +15711,7 @@ function resolveStringTitle(title, fallback) {
|
|
|
13040
15711
|
}
|
|
13041
15712
|
|
|
13042
15713
|
// src/data-table/SavedViewsControl.tsx
|
|
13043
|
-
import { useId as useId3, useState as
|
|
15714
|
+
import { useId as useId3, useState as useState23 } from "react";
|
|
13044
15715
|
|
|
13045
15716
|
// src/dropdown-menu.tsx
|
|
13046
15717
|
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
@@ -13184,10 +15855,10 @@ function SavedViewsControl({
|
|
|
13184
15855
|
onReload
|
|
13185
15856
|
}) {
|
|
13186
15857
|
const unsavedChangesId = useId3();
|
|
13187
|
-
const [saveOpen, setSaveOpen] =
|
|
13188
|
-
const [name, setName] =
|
|
13189
|
-
const [saving, setSaving] =
|
|
13190
|
-
const [actionError, setActionError] =
|
|
15858
|
+
const [saveOpen, setSaveOpen] = useState23(false);
|
|
15859
|
+
const [name, setName] = useState23("");
|
|
15860
|
+
const [saving, setSaving] = useState23(false);
|
|
15861
|
+
const [actionError, setActionError] = useState23(null);
|
|
13191
15862
|
const visibleError = actionError ?? error;
|
|
13192
15863
|
const save = async () => {
|
|
13193
15864
|
const next = name.trim();
|
|
@@ -13320,8 +15991,11 @@ export {
|
|
|
13320
15991
|
CELL_TINT_CLASS,
|
|
13321
15992
|
COLOR_RULE_OPS,
|
|
13322
15993
|
COLOR_RULE_OP_LABELS,
|
|
15994
|
+
DEFAULT_OVERSCAN,
|
|
15995
|
+
DEFAULT_UNDO_DEPTH,
|
|
13323
15996
|
DataRowInspector,
|
|
13324
15997
|
DataRowWindow,
|
|
15998
|
+
EMPTY_GROUP_KEY,
|
|
13325
15999
|
EMPTY_TABLE_STYLE,
|
|
13326
16000
|
FORMAT_MISMATCH_CLASS,
|
|
13327
16001
|
FormattedCell,
|
|
@@ -13332,6 +16006,7 @@ export {
|
|
|
13332
16006
|
MatrxUuidCell,
|
|
13333
16007
|
NO_FROZEN_COLUMNS,
|
|
13334
16008
|
OPS_WITH_VALUE,
|
|
16009
|
+
PARTIAL_BADGE,
|
|
13335
16010
|
ROW_TINT_CLASS,
|
|
13336
16011
|
STYLE_COLORS,
|
|
13337
16012
|
STYLE_COLOR_LABELS,
|
|
@@ -13341,22 +16016,62 @@ export {
|
|
|
13341
16016
|
TABLE_STYLE_VERSION,
|
|
13342
16017
|
TableTitleRow,
|
|
13343
16018
|
TableViewTabs,
|
|
16019
|
+
UNKNOWN_TOTAL_BADGE,
|
|
13344
16020
|
alignForFormat,
|
|
16021
|
+
allRange,
|
|
13345
16022
|
applyStylePath,
|
|
16023
|
+
boundsContain,
|
|
13346
16024
|
buildRowAgentInput,
|
|
13347
16025
|
buildViewAgentInput,
|
|
13348
16026
|
buildViewHuman,
|
|
16027
|
+
canRedo,
|
|
16028
|
+
canUndo,
|
|
16029
|
+
cellClipboardText,
|
|
16030
|
+
cellDomKey,
|
|
16031
|
+
cellsInRange,
|
|
16032
|
+
classifyGridKey,
|
|
16033
|
+
coerceGroupNumber,
|
|
13349
16034
|
collectSelectOptions,
|
|
13350
16035
|
colorForChoice,
|
|
16036
|
+
columnRange,
|
|
16037
|
+
computeVariableWindow,
|
|
16038
|
+
computeWindow,
|
|
16039
|
+
createUndoStack,
|
|
16040
|
+
describeCoverage,
|
|
16041
|
+
detectSeries,
|
|
16042
|
+
directClickKinds,
|
|
13351
16043
|
downloadTableAsXlsx,
|
|
13352
16044
|
evaluateRule,
|
|
16045
|
+
fillDown,
|
|
16046
|
+
fillRange,
|
|
16047
|
+
fillTargetFor,
|
|
13353
16048
|
filterKindLabel,
|
|
16049
|
+
flattenGroups,
|
|
13354
16050
|
formatColumnValue,
|
|
16051
|
+
formatGroupNumber,
|
|
16052
|
+
gridToTsv,
|
|
16053
|
+
groupKeyOf,
|
|
16054
|
+
groupRows,
|
|
16055
|
+
groupSummary,
|
|
13355
16056
|
inferTableSearchRole,
|
|
16057
|
+
isBlankGroupValue,
|
|
16058
|
+
isDirectClickEditor,
|
|
16059
|
+
isGroupCollapsed,
|
|
16060
|
+
isSingleCell,
|
|
16061
|
+
isSingleCellRange,
|
|
13356
16062
|
isStyleColor,
|
|
16063
|
+
moveSelection,
|
|
16064
|
+
parseClipboardGrid,
|
|
13357
16065
|
parseTableStyle,
|
|
13358
16066
|
parseTableViewSnapshot,
|
|
13359
16067
|
pixelWidth,
|
|
16068
|
+
planPaste,
|
|
16069
|
+
popRedo,
|
|
16070
|
+
popUndo,
|
|
16071
|
+
pushUndo,
|
|
16072
|
+
rangeBounds,
|
|
16073
|
+
rangeRows,
|
|
16074
|
+
rangeSize,
|
|
13360
16075
|
rankTableSearchRows,
|
|
13361
16076
|
resolveCellColor,
|
|
13362
16077
|
resolveColumnMarker,
|
|
@@ -13364,17 +16079,25 @@ export {
|
|
|
13364
16079
|
resolveFrozenColumns,
|
|
13365
16080
|
resolveRowColor,
|
|
13366
16081
|
resolveTableSearchScopes,
|
|
16082
|
+
rowRange,
|
|
13367
16083
|
rowsToCsvFromColumns,
|
|
13368
16084
|
rowsToMarkdownTable,
|
|
13369
16085
|
rowsToRecordsFromColumns,
|
|
16086
|
+
sameCell,
|
|
16087
|
+
scrollOffsetForIndex,
|
|
13370
16088
|
shortUuid,
|
|
16089
|
+
storedValuesEqual,
|
|
13371
16090
|
stylePath,
|
|
13372
16091
|
tableStyleFromMetadata,
|
|
13373
16092
|
tableStyleIsEmpty,
|
|
13374
16093
|
tableUrlParamPrefix,
|
|
16094
|
+
tileIndex,
|
|
16095
|
+
toggleGroupCollapsed,
|
|
16096
|
+
undoEntryFor,
|
|
13375
16097
|
useMatrxDataTableHost,
|
|
13376
16098
|
useMatrxTableRowAlchemy,
|
|
13377
16099
|
useScrollPagination,
|
|
16100
|
+
useSpreadsheetGrid,
|
|
13378
16101
|
useTableUrlState
|
|
13379
16102
|
};
|
|
13380
16103
|
//# sourceMappingURL=index.js.map
|