@ai-matrx/design-system 0.25.0 → 0.27.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 +94 -0
- package/dist/data-table/copy-helpers.cjs.map +1 -1
- package/dist/data-table/copy-helpers.d.cts +3 -1
- package/dist/data-table/copy-helpers.d.ts +3 -1
- package/dist/data-table/copy-helpers.js.map +1 -1
- 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/date-filter.cjs +145 -0
- package/dist/data-table/date-filter.cjs.map +1 -0
- package/dist/data-table/date-filter.d.cts +31 -0
- package/dist/data-table/date-filter.d.ts +31 -0
- package/dist/data-table/date-filter.js +125 -0
- package/dist/data-table/date-filter.js.map +1 -0
- 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/filter-engine.cjs +88 -0
- package/dist/data-table/filter-engine.cjs.map +1 -1
- package/dist/data-table/filter-engine.d.cts +3 -1
- package/dist/data-table/filter-engine.d.ts +3 -1
- package/dist/data-table/filter-engine.js +88 -0
- package/dist/data-table/filter-engine.js.map +1 -1
- package/dist/data-table/host.cjs.map +1 -1
- package/dist/data-table/host.d.cts +14 -3
- package/dist/data-table/host.d.ts +14 -3
- package/dist/data-table/host.js.map +1 -1
- package/dist/data-table/index.cjs +918 -152
- package/dist/data-table/index.cjs.map +1 -1
- package/dist/data-table/index.d.cts +5 -2
- package/dist/data-table/index.d.ts +5 -2
- package/dist/data-table/index.js +956 -189
- package/dist/data-table/index.js.map +1 -1
- package/dist/data-table/infer-filter.cjs +2 -0
- package/dist/data-table/infer-filter.cjs.map +1 -1
- package/dist/data-table/infer-filter.d.cts +4 -2
- package/dist/data-table/infer-filter.d.ts +4 -2
- package/dist/data-table/infer-filter.js +2 -0
- package/dist/data-table/infer-filter.js.map +1 -1
- package/dist/data-table/layered-filters.d.cts +3 -1
- package/dist/data-table/layered-filters.d.ts +3 -1
- 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.cjs.map +1 -1
- package/dist/data-table/query-control.d.cts +3 -1
- package/dist/data-table/query-control.d.ts +3 -1
- package/dist/data-table/query-control.js.map +1 -1
- package/dist/data-table/spreadsheet.cjs +61 -13
- package/dist/data-table/spreadsheet.cjs.map +1 -1
- package/dist/data-table/spreadsheet.d.cts +36 -1
- package/dist/data-table/spreadsheet.d.ts +36 -1
- package/dist/data-table/spreadsheet.js +61 -13
- package/dist/data-table/spreadsheet.js.map +1 -1
- package/dist/data-table/types.cjs.map +1 -1
- package/dist/data-table/types.d.cts +3 -1
- package/dist/data-table/types.d.ts +3 -1
- package/dist/data-table/url-state.d.cts +3 -1
- package/dist/data-table/url-state.d.ts +3 -1
- package/dist/data-table/uuid-cell.cjs.map +1 -1
- package/dist/data-table/uuid-cell.js.map +1 -1
- package/dist/data-table/xlsx.cjs.map +1 -1
- package/dist/data-table/xlsx.d.cts +3 -1
- package/dist/data-table/xlsx.d.ts +3 -1
- package/dist/data-table/xlsx.js.map +1 -1
- package/dist/field-formats/index.cjs +15 -0
- package/dist/field-formats/index.cjs.map +1 -1
- package/dist/field-formats/index.js +15 -0
- package/dist/field-formats/index.js.map +1 -1
- package/dist/{types-nlLCMiqd.d.ts → types-D9JBR6ZU.d.ts} +118 -5
- package/dist/{types-CmQrOz-T.d.cts → types-jQddSUnj.d.cts} +118 -5
- package/package.json +31 -1
|
@@ -58,6 +58,8 @@ __export(data_table_exports, {
|
|
|
58
58
|
SavedViewsControl: () => SavedViewsControl,
|
|
59
59
|
TABLE_STYLE_METADATA_KEY: () => TABLE_STYLE_METADATA_KEY,
|
|
60
60
|
TABLE_STYLE_VERSION: () => TABLE_STYLE_VERSION,
|
|
61
|
+
TIME_RANGE_PRESETS: () => TIME_RANGE_PRESETS,
|
|
62
|
+
TIME_RANGE_PRESET_VALUES: () => TIME_RANGE_PRESET_VALUES,
|
|
61
63
|
TableTitleRow: () => TableTitleRow,
|
|
62
64
|
TableViewTabs: () => TableViewTabs,
|
|
63
65
|
UNKNOWN_TOTAL_BADGE: () => UNKNOWN_TOTAL_BADGE,
|
|
@@ -81,6 +83,7 @@ __export(data_table_exports, {
|
|
|
81
83
|
computeVariableWindow: () => computeVariableWindow,
|
|
82
84
|
computeWindow: () => computeWindow,
|
|
83
85
|
createUndoStack: () => createUndoStack,
|
|
86
|
+
dateFilterBounds: () => dateFilterBounds,
|
|
84
87
|
describeCoverage: () => describeCoverage,
|
|
85
88
|
detectSeries: () => detectSeries,
|
|
86
89
|
directClickKinds: () => directClickKinds,
|
|
@@ -5131,6 +5134,124 @@ function layeredFilterRuleSummary(rule, fields) {
|
|
|
5131
5134
|
return rule.operator === "between" ? `${fieldLabel} ${operator} ${value} and ${rule.valueTo ?? ""}` : `${fieldLabel} ${operator} ${value}`;
|
|
5132
5135
|
}
|
|
5133
5136
|
|
|
5137
|
+
// src/data-table/date-filter.ts
|
|
5138
|
+
var TIME_RANGE_PRESET_VALUES = [
|
|
5139
|
+
"all",
|
|
5140
|
+
"1m",
|
|
5141
|
+
"15m",
|
|
5142
|
+
"30m",
|
|
5143
|
+
"1h",
|
|
5144
|
+
"2h",
|
|
5145
|
+
"6h",
|
|
5146
|
+
"12h",
|
|
5147
|
+
"today",
|
|
5148
|
+
"yesterday",
|
|
5149
|
+
"this_week",
|
|
5150
|
+
"this_month",
|
|
5151
|
+
"this_year",
|
|
5152
|
+
"older_1m",
|
|
5153
|
+
"older_15m",
|
|
5154
|
+
"older_30m",
|
|
5155
|
+
"older_1h",
|
|
5156
|
+
"older_2h",
|
|
5157
|
+
"older_6h",
|
|
5158
|
+
"older_12h",
|
|
5159
|
+
"older_today",
|
|
5160
|
+
"older_this_week",
|
|
5161
|
+
"older_this_month",
|
|
5162
|
+
"older_this_year"
|
|
5163
|
+
];
|
|
5164
|
+
var TIME_RANGE_PRESETS = [
|
|
5165
|
+
{ value: "all", label: "All time", group: "all" },
|
|
5166
|
+
{ value: "1m", label: "Last minute", group: "recent" },
|
|
5167
|
+
{ value: "15m", label: "Last 15 minutes", group: "recent" },
|
|
5168
|
+
{ value: "30m", label: "Last 30 minutes", group: "recent" },
|
|
5169
|
+
{ value: "1h", label: "Last hour", group: "recent" },
|
|
5170
|
+
{ value: "2h", label: "Last 2 hours", group: "recent" },
|
|
5171
|
+
{ value: "6h", label: "Last 6 hours", group: "recent" },
|
|
5172
|
+
{ value: "12h", label: "Last 12 hours", group: "recent" },
|
|
5173
|
+
{ value: "today", label: "Today", group: "calendar" },
|
|
5174
|
+
{ value: "yesterday", label: "Yesterday", group: "calendar" },
|
|
5175
|
+
{ value: "this_week", label: "This week", group: "calendar" },
|
|
5176
|
+
{ value: "this_month", label: "This month", group: "calendar" },
|
|
5177
|
+
{ value: "this_year", label: "This year", group: "calendar" },
|
|
5178
|
+
{ value: "older_1m", label: "Older than 1 minute", group: "older" },
|
|
5179
|
+
{ value: "older_15m", label: "Older than 15 minutes", group: "older" },
|
|
5180
|
+
{ value: "older_30m", label: "Older than 30 minutes", group: "older" },
|
|
5181
|
+
{ value: "older_1h", label: "Older than 1 hour", group: "older" },
|
|
5182
|
+
{ value: "older_2h", label: "Older than 2 hours", group: "older" },
|
|
5183
|
+
{ value: "older_6h", label: "Older than 6 hours", group: "older" },
|
|
5184
|
+
{ value: "older_12h", label: "Older than 12 hours", group: "older" },
|
|
5185
|
+
{ value: "older_today", label: "Before today", group: "older" },
|
|
5186
|
+
{ value: "older_this_week", label: "Before this week", group: "older" },
|
|
5187
|
+
{ value: "older_this_month", label: "Before this month", group: "older" },
|
|
5188
|
+
{ value: "older_this_year", label: "Before this year", group: "older" }
|
|
5189
|
+
];
|
|
5190
|
+
function startOfDay(date) {
|
|
5191
|
+
const next = new Date(date);
|
|
5192
|
+
next.setHours(0, 0, 0, 0);
|
|
5193
|
+
return next;
|
|
5194
|
+
}
|
|
5195
|
+
function startOfWeek(date) {
|
|
5196
|
+
const next = startOfDay(date);
|
|
5197
|
+
next.setDate(next.getDate() - (next.getDay() === 0 ? 6 : next.getDay() - 1));
|
|
5198
|
+
return next;
|
|
5199
|
+
}
|
|
5200
|
+
function startOfMonth(date) {
|
|
5201
|
+
return new Date(date.getFullYear(), date.getMonth(), 1);
|
|
5202
|
+
}
|
|
5203
|
+
function startOfYear(date) {
|
|
5204
|
+
return new Date(date.getFullYear(), 0, 1);
|
|
5205
|
+
}
|
|
5206
|
+
function validDate(value) {
|
|
5207
|
+
if (value === void 0) return void 0;
|
|
5208
|
+
const date = value instanceof Date ? new Date(value) : new Date(value);
|
|
5209
|
+
return Number.isNaN(date.valueOf()) ? void 0 : date;
|
|
5210
|
+
}
|
|
5211
|
+
function dateFilterBounds(filter, now = /* @__PURE__ */ new Date()) {
|
|
5212
|
+
if (!filter.preset) {
|
|
5213
|
+
return {
|
|
5214
|
+
...filter.since === void 0 ? {} : { since: filter.since },
|
|
5215
|
+
...filter.until === void 0 ? {} : { until: filter.until }
|
|
5216
|
+
};
|
|
5217
|
+
}
|
|
5218
|
+
if (filter.preset === "all") return {};
|
|
5219
|
+
const anchor = validDate(filter.anchor) ?? validDate(now) ?? /* @__PURE__ */ new Date();
|
|
5220
|
+
const ago = (milliseconds) => new Date(anchor.valueOf() - milliseconds).toISOString();
|
|
5221
|
+
const recent = {
|
|
5222
|
+
"1m": 6e4,
|
|
5223
|
+
"15m": 15 * 6e4,
|
|
5224
|
+
"30m": 30 * 6e4,
|
|
5225
|
+
"1h": 60 * 6e4,
|
|
5226
|
+
"2h": 2 * 60 * 6e4,
|
|
5227
|
+
"6h": 6 * 60 * 6e4,
|
|
5228
|
+
"12h": 12 * 60 * 6e4
|
|
5229
|
+
};
|
|
5230
|
+
const duration = recent[filter.preset.replace("older_", "")];
|
|
5231
|
+
if (duration !== void 0) {
|
|
5232
|
+
return filter.preset.startsWith("older_") ? { until: ago(duration) } : { since: ago(duration) };
|
|
5233
|
+
}
|
|
5234
|
+
const starts = {
|
|
5235
|
+
today: startOfDay(anchor),
|
|
5236
|
+
this_week: startOfWeek(anchor),
|
|
5237
|
+
this_month: startOfMonth(anchor),
|
|
5238
|
+
this_year: startOfYear(anchor),
|
|
5239
|
+
older_today: startOfDay(anchor),
|
|
5240
|
+
older_this_week: startOfWeek(anchor),
|
|
5241
|
+
older_this_month: startOfMonth(anchor),
|
|
5242
|
+
older_this_year: startOfYear(anchor)
|
|
5243
|
+
};
|
|
5244
|
+
if (filter.preset === "yesterday") {
|
|
5245
|
+
const until = startOfDay(anchor);
|
|
5246
|
+
const since = new Date(until);
|
|
5247
|
+
since.setDate(since.getDate() - 1);
|
|
5248
|
+
return { since: since.toISOString(), until: until.toISOString() };
|
|
5249
|
+
}
|
|
5250
|
+
const start = starts[filter.preset];
|
|
5251
|
+
if (!start) return {};
|
|
5252
|
+
return filter.preset.startsWith("older_") ? { until: start.toISOString() } : { since: start.toISOString() };
|
|
5253
|
+
}
|
|
5254
|
+
|
|
5134
5255
|
// src/data-table/filter-engine.ts
|
|
5135
5256
|
var SELECT_EMPTY_VALUE = "__empty__";
|
|
5136
5257
|
var SELECT_NOT_EMPTY_VALUE = "__not_empty__";
|
|
@@ -5227,10 +5348,25 @@ function passesColumnFilter(value, filter) {
|
|
|
5227
5348
|
if (raw === "") return false;
|
|
5228
5349
|
const normalized = raw.replace(/[^0-9.-]/g, "");
|
|
5229
5350
|
if (normalized === "") return false;
|
|
5230
|
-
const
|
|
5231
|
-
if (!Number.isFinite(
|
|
5232
|
-
if (filter.min !== void 0 &&
|
|
5233
|
-
if (filter.max !== void 0 &&
|
|
5351
|
+
const n2 = typeof value === "number" ? value : Number(normalized);
|
|
5352
|
+
if (!Number.isFinite(n2)) return false;
|
|
5353
|
+
if (filter.min !== void 0 && n2 < filter.min) return false;
|
|
5354
|
+
if (filter.max !== void 0 && n2 > filter.max) return false;
|
|
5355
|
+
return true;
|
|
5356
|
+
}
|
|
5357
|
+
case "date": {
|
|
5358
|
+
const raw = value instanceof Date ? value : new Date(stringifyCellValue(value));
|
|
5359
|
+
if (Number.isNaN(raw.valueOf())) return false;
|
|
5360
|
+
const { since, until } = dateFilterBounds(filter);
|
|
5361
|
+
const timestamp = raw.valueOf();
|
|
5362
|
+
if (since !== void 0) {
|
|
5363
|
+
const sinceTimestamp = new Date(since).valueOf();
|
|
5364
|
+
if (Number.isNaN(sinceTimestamp) || timestamp < sinceTimestamp) return false;
|
|
5365
|
+
}
|
|
5366
|
+
if (until !== void 0) {
|
|
5367
|
+
const untilTimestamp = new Date(until).valueOf();
|
|
5368
|
+
if (Number.isNaN(untilTimestamp) || timestamp >= untilTimestamp) return false;
|
|
5369
|
+
}
|
|
5234
5370
|
return true;
|
|
5235
5371
|
}
|
|
5236
5372
|
}
|
|
@@ -5293,26 +5429,29 @@ function filterAndSortRows(rows, columns, columnFilters, sort, globalSearch, any
|
|
|
5293
5429
|
return result;
|
|
5294
5430
|
}
|
|
5295
5431
|
function countActiveColumnFilters(filters) {
|
|
5296
|
-
let
|
|
5432
|
+
let n2 = 0;
|
|
5297
5433
|
for (const f of Object.values(filters)) {
|
|
5298
5434
|
if (!f) continue;
|
|
5299
5435
|
switch (f.kind) {
|
|
5300
5436
|
case "text":
|
|
5301
|
-
if (f.value.trim() || f.mode && f.mode !== "contains")
|
|
5437
|
+
if (f.value.trim() || f.mode && f.mode !== "contains") n2 += 1;
|
|
5302
5438
|
break;
|
|
5303
5439
|
case "select":
|
|
5304
5440
|
if (f.values !== void 0 || f.value && f.value !== "__all__")
|
|
5305
|
-
|
|
5441
|
+
n2 += 1;
|
|
5306
5442
|
break;
|
|
5307
5443
|
case "boolean":
|
|
5308
|
-
|
|
5444
|
+
n2 += 1;
|
|
5309
5445
|
break;
|
|
5310
5446
|
case "number":
|
|
5311
|
-
if (f.min !== void 0 || f.max !== void 0)
|
|
5447
|
+
if (f.min !== void 0 || f.max !== void 0) n2 += 1;
|
|
5448
|
+
break;
|
|
5449
|
+
case "date":
|
|
5450
|
+
if (isColumnFilterActive(f)) n2 += 1;
|
|
5312
5451
|
break;
|
|
5313
5452
|
}
|
|
5314
5453
|
}
|
|
5315
|
-
return
|
|
5454
|
+
return n2;
|
|
5316
5455
|
}
|
|
5317
5456
|
function isColumnFilterActive(filter) {
|
|
5318
5457
|
if (!filter) return false;
|
|
@@ -5325,6 +5464,10 @@ function isColumnFilterActive(filter) {
|
|
|
5325
5464
|
return true;
|
|
5326
5465
|
case "number":
|
|
5327
5466
|
return filter.min !== void 0 || filter.max !== void 0;
|
|
5467
|
+
case "date": {
|
|
5468
|
+
const bounds = dateFilterBounds(filter);
|
|
5469
|
+
return bounds.since !== void 0 || bounds.until !== void 0;
|
|
5470
|
+
}
|
|
5328
5471
|
}
|
|
5329
5472
|
}
|
|
5330
5473
|
function applyRowEdits(row, edits) {
|
|
@@ -5591,8 +5734,8 @@ function parseLayeredFilters(raw) {
|
|
|
5591
5734
|
}
|
|
5592
5735
|
}
|
|
5593
5736
|
function positiveInt(raw, fallback) {
|
|
5594
|
-
const
|
|
5595
|
-
return Number.isFinite(
|
|
5737
|
+
const n2 = raw ? Number.parseInt(raw, 10) : Number.NaN;
|
|
5738
|
+
return Number.isFinite(n2) && n2 > 0 ? n2 : fallback;
|
|
5596
5739
|
}
|
|
5597
5740
|
function tableUrlParamPrefix(tableId) {
|
|
5598
5741
|
if (!/^[a-z][a-z0-9-]{0,63}$/.test(tableId)) {
|
|
@@ -5931,6 +6074,95 @@ var CommandShortcut = ({
|
|
|
5931
6074
|
};
|
|
5932
6075
|
CommandShortcut.displayName = "CommandShortcut";
|
|
5933
6076
|
|
|
6077
|
+
// src/data-table/facets.ts
|
|
6078
|
+
var MAX_LISTABLE_FACET_LENGTH = 300;
|
|
6079
|
+
var DEFAULT_FACET_LIMIT = 200;
|
|
6080
|
+
var MAX_FACET_LIMIT = 500;
|
|
6081
|
+
function facetText(raw) {
|
|
6082
|
+
if (raw === null || raw === void 0) return "";
|
|
6083
|
+
if (typeof raw === "object") {
|
|
6084
|
+
try {
|
|
6085
|
+
return JSON.stringify(raw);
|
|
6086
|
+
} catch {
|
|
6087
|
+
return String(raw);
|
|
6088
|
+
}
|
|
6089
|
+
}
|
|
6090
|
+
return String(raw);
|
|
6091
|
+
}
|
|
6092
|
+
function computeColumnFacets(args) {
|
|
6093
|
+
const { columnId: columnId2, rows, readValue: readValue2 } = args;
|
|
6094
|
+
const limit = Math.min(Math.max(args.limit ?? DEFAULT_FACET_LIMIT, 1), MAX_FACET_LIMIT);
|
|
6095
|
+
const counts = /* @__PURE__ */ new Map();
|
|
6096
|
+
const longValues = /* @__PURE__ */ new Set();
|
|
6097
|
+
let blank = 0;
|
|
6098
|
+
let maxLength = 0;
|
|
6099
|
+
for (const row of rows) {
|
|
6100
|
+
let raw;
|
|
6101
|
+
try {
|
|
6102
|
+
raw = readValue2(row, columnId2);
|
|
6103
|
+
} catch {
|
|
6104
|
+
raw = void 0;
|
|
6105
|
+
}
|
|
6106
|
+
const trimmed = facetText(raw).trim();
|
|
6107
|
+
if (trimmed === "") {
|
|
6108
|
+
blank += 1;
|
|
6109
|
+
continue;
|
|
6110
|
+
}
|
|
6111
|
+
if (trimmed.length > maxLength) maxLength = trimmed.length;
|
|
6112
|
+
if (trimmed.length > MAX_LISTABLE_FACET_LENGTH) {
|
|
6113
|
+
longValues.add(trimmed);
|
|
6114
|
+
continue;
|
|
6115
|
+
}
|
|
6116
|
+
counts.set(trimmed, (counts.get(trimmed) ?? 0) + 1);
|
|
6117
|
+
}
|
|
6118
|
+
const values = [...counts.entries()].map(([value, count]) => ({ value, count })).sort((a, b) => b.count - a.count || a.value.localeCompare(b.value)).slice(0, limit);
|
|
6119
|
+
return {
|
|
6120
|
+
columnId: columnId2,
|
|
6121
|
+
totalRows: rows.length,
|
|
6122
|
+
filled: rows.length - blank,
|
|
6123
|
+
blank,
|
|
6124
|
+
distinctCount: counts.size + longValues.size,
|
|
6125
|
+
maxLength,
|
|
6126
|
+
unlistable: longValues.size,
|
|
6127
|
+
limit,
|
|
6128
|
+
truncated: counts.size > limit,
|
|
6129
|
+
values,
|
|
6130
|
+
answeredBy: "local",
|
|
6131
|
+
complete: args.complete ?? true
|
|
6132
|
+
};
|
|
6133
|
+
}
|
|
6134
|
+
function localFacetsAreComplete(loadedRowCount, total) {
|
|
6135
|
+
if (total === void 0 || !Number.isFinite(total) || total < 0) return false;
|
|
6136
|
+
return loadedRowCount >= total;
|
|
6137
|
+
}
|
|
6138
|
+
var NUMBERS = new Intl.NumberFormat("en-US");
|
|
6139
|
+
function n(value) {
|
|
6140
|
+
try {
|
|
6141
|
+
return NUMBERS.format(value);
|
|
6142
|
+
} catch {
|
|
6143
|
+
return String(value);
|
|
6144
|
+
}
|
|
6145
|
+
}
|
|
6146
|
+
function describeFacetSource(facets, noun = "row") {
|
|
6147
|
+
if (!facets) return "";
|
|
6148
|
+
const plural2 = `${noun}s`;
|
|
6149
|
+
if (!facets.complete) {
|
|
6150
|
+
return `These counts cover the ${n(facets.totalRows)} ${plural2} loaded here, not the whole table.`;
|
|
6151
|
+
}
|
|
6152
|
+
if (facets.truncated) {
|
|
6153
|
+
return `Showing the ${n(facets.values.length)} most common of ${n(facets.distinctCount)} values.`;
|
|
6154
|
+
}
|
|
6155
|
+
if (facets.unlistable > 0) {
|
|
6156
|
+
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"}.`;
|
|
6157
|
+
}
|
|
6158
|
+
return "";
|
|
6159
|
+
}
|
|
6160
|
+
var FACETS_LOADING_NOTICE = "Counting values\u2026";
|
|
6161
|
+
function describeFacetFailure(error) {
|
|
6162
|
+
const detail = error instanceof Error ? error.message : String(error ?? "");
|
|
6163
|
+
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.";
|
|
6164
|
+
}
|
|
6165
|
+
|
|
5934
6166
|
// src/data-table/column-marker.ts
|
|
5935
6167
|
var MARKER_ACCESSORS = {
|
|
5936
6168
|
favorite: "favorite",
|
|
@@ -5998,6 +6230,10 @@ function ColumnHeaderCell({
|
|
|
5998
6230
|
filterFooterHint,
|
|
5999
6231
|
allowNegation = false,
|
|
6000
6232
|
allowNullModes = false,
|
|
6233
|
+
facets,
|
|
6234
|
+
facetsLoading = false,
|
|
6235
|
+
facetsError,
|
|
6236
|
+
onFilterOpen,
|
|
6001
6237
|
reorderColumn
|
|
6002
6238
|
}) {
|
|
6003
6239
|
const reorderEnabled = reorderColumn !== void 0;
|
|
@@ -6032,6 +6268,11 @@ function ColumnHeaderCell({
|
|
|
6032
6268
|
setPendingNegation(filterValue?.negated ?? false);
|
|
6033
6269
|
}
|
|
6034
6270
|
}, [filterOpen, filterValue]);
|
|
6271
|
+
const notifyOpen = (0, import_react13.useRef)(onFilterOpen);
|
|
6272
|
+
notifyOpen.current = onFilterOpen;
|
|
6273
|
+
(0, import_react13.useEffect)(() => {
|
|
6274
|
+
if (filterOpen) notifyOpen.current?.();
|
|
6275
|
+
}, [filterOpen]);
|
|
6035
6276
|
const applyFilter = () => {
|
|
6036
6277
|
onFilterChange(draftFilter);
|
|
6037
6278
|
setFilterOpen(false);
|
|
@@ -6043,7 +6284,7 @@ function ColumnHeaderCell({
|
|
|
6043
6284
|
const visibleFilter = deferredFilter ? draftFilter : filterValue;
|
|
6044
6285
|
const setNegated = (negated) => {
|
|
6045
6286
|
setPendingNegation(negated);
|
|
6046
|
-
if (!visibleFilter) return;
|
|
6287
|
+
if (!visibleFilter || visibleFilter.kind === "date") return;
|
|
6047
6288
|
const next = { ...visibleFilter, ...negated ? { negated: true } : {} };
|
|
6048
6289
|
if (!negated) delete next.negated;
|
|
6049
6290
|
if (deferredFilter) setDraftFilter(next);
|
|
@@ -6051,7 +6292,7 @@ function ColumnHeaderCell({
|
|
|
6051
6292
|
};
|
|
6052
6293
|
const markerLabels = marker ? markerCopy(marker) : void 0;
|
|
6053
6294
|
const accessibleLabel = markerLabels?.label ?? labelText;
|
|
6054
|
-
const menuLabel = accessibleLabel ? `Sort or filter ${accessibleLabel}` : "Sort or filter column";
|
|
6295
|
+
const menuLabel = filterKind ? accessibleLabel ? `Sort or filter ${accessibleLabel}` : "Sort or filter column" : accessibleLabel ? `Sort ${accessibleLabel}` : "Sort column";
|
|
6055
6296
|
const menuContent = /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
6056
6297
|
PopoverContent,
|
|
6057
6298
|
{
|
|
@@ -6119,13 +6360,16 @@ function ColumnHeaderCell({
|
|
|
6119
6360
|
kind: filterKind,
|
|
6120
6361
|
value: visibleFilter,
|
|
6121
6362
|
onChange: (next) => {
|
|
6122
|
-
const preservingNegation = next && (visibleFilter?.negated ?? pendingNegation) ? { ...next, negated: true } : next;
|
|
6363
|
+
const preservingNegation = next && next.kind !== "date" && (visibleFilter?.negated ?? pendingNegation) ? { ...next, negated: true } : next;
|
|
6123
6364
|
if (deferredFilter) setDraftFilter(preservingNegation);
|
|
6124
6365
|
else onFilterChange(preservingNegation);
|
|
6125
6366
|
},
|
|
6126
6367
|
selectOptions,
|
|
6127
6368
|
selectSingle,
|
|
6128
6369
|
selectAllowCustom,
|
|
6370
|
+
facets: facets ?? null,
|
|
6371
|
+
facetsLoading,
|
|
6372
|
+
...facetsError === void 0 ? {} : { facetsError },
|
|
6129
6373
|
...markerLabels ? {
|
|
6130
6374
|
booleanLabels: {
|
|
6131
6375
|
all: "All",
|
|
@@ -6136,7 +6380,7 @@ function ColumnHeaderCell({
|
|
|
6136
6380
|
allowNullModes
|
|
6137
6381
|
}
|
|
6138
6382
|
) : null,
|
|
6139
|
-
filterKind && allowNegation ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "mt-2 border-t border-border pt-2", children: [
|
|
6383
|
+
filterKind && filterKind !== "date" && allowNegation ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "mt-2 border-t border-border pt-2", children: [
|
|
6140
6384
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "mb-1 text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: "Match mode" }),
|
|
6141
6385
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "grid grid-cols-2 gap-1 rounded-md border p-0.5", children: [
|
|
6142
6386
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
@@ -6350,8 +6594,43 @@ function FilterBody({
|
|
|
6350
6594
|
selectSingle = false,
|
|
6351
6595
|
selectAllowCustom = false,
|
|
6352
6596
|
allowNullModes = false,
|
|
6353
|
-
booleanLabels
|
|
6597
|
+
booleanLabels,
|
|
6598
|
+
facets = null,
|
|
6599
|
+
facetsLoading = false,
|
|
6600
|
+
facetsError
|
|
6354
6601
|
}) {
|
|
6602
|
+
const checklist = facetsLoading || facetsError || facets && (facets.values.length > 0 || facets.blank > 0) ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6603
|
+
FacetChecklist,
|
|
6604
|
+
{
|
|
6605
|
+
facets,
|
|
6606
|
+
loading: facetsLoading,
|
|
6607
|
+
...facetsError === void 0 ? {} : { error: facetsError },
|
|
6608
|
+
value,
|
|
6609
|
+
onChange
|
|
6610
|
+
}
|
|
6611
|
+
) : null;
|
|
6612
|
+
if (checklist && kind === "select" && facets && facets.values.length > 0) {
|
|
6613
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "space-y-2", children: checklist });
|
|
6614
|
+
}
|
|
6615
|
+
if (checklist) {
|
|
6616
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "space-y-2", children: [
|
|
6617
|
+
checklist,
|
|
6618
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "h-px bg-border" }),
|
|
6619
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6620
|
+
FilterBody,
|
|
6621
|
+
{
|
|
6622
|
+
kind,
|
|
6623
|
+
value,
|
|
6624
|
+
onChange,
|
|
6625
|
+
selectOptions,
|
|
6626
|
+
selectSingle,
|
|
6627
|
+
selectAllowCustom,
|
|
6628
|
+
allowNullModes,
|
|
6629
|
+
...booleanLabels === void 0 ? {} : { booleanLabels }
|
|
6630
|
+
}
|
|
6631
|
+
)
|
|
6632
|
+
] });
|
|
6633
|
+
}
|
|
6355
6634
|
if (kind === "text") {
|
|
6356
6635
|
const text = value?.kind === "text" ? value.value : "";
|
|
6357
6636
|
const mode = (value?.kind === "text" ? value.mode : void 0) ?? "contains";
|
|
@@ -6460,8 +6739,183 @@ function FilterBody({
|
|
|
6460
6739
|
)
|
|
6461
6740
|
] });
|
|
6462
6741
|
}
|
|
6742
|
+
if (kind === "date") {
|
|
6743
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(DateFilterBody, { value, onChange });
|
|
6744
|
+
}
|
|
6463
6745
|
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(NumberFilterBody, { value, onChange });
|
|
6464
6746
|
}
|
|
6747
|
+
function FacetChecklist({
|
|
6748
|
+
facets,
|
|
6749
|
+
loading,
|
|
6750
|
+
error,
|
|
6751
|
+
value,
|
|
6752
|
+
onChange
|
|
6753
|
+
}) {
|
|
6754
|
+
const [query, setQuery] = (0, import_react13.useState)("");
|
|
6755
|
+
const selected = value?.kind === "select" ? value.values ?? (value.value && value.value !== "__all__" ? [value.value] : []) : [];
|
|
6756
|
+
const selectedSet = new Set(selected);
|
|
6757
|
+
const rows = (0, import_react13.useMemo)(() => {
|
|
6758
|
+
if (!facets) return [];
|
|
6759
|
+
const listed = facets.values.map((entry) => ({
|
|
6760
|
+
value: entry.value,
|
|
6761
|
+
label: entry.value,
|
|
6762
|
+
count: entry.count
|
|
6763
|
+
}));
|
|
6764
|
+
const withBlank = facets.blank > 0 ? [{ value: "", label: "(empty)", count: facets.blank }, ...listed] : listed;
|
|
6765
|
+
const q = query.trim().toLowerCase();
|
|
6766
|
+
if (!q) return withBlank;
|
|
6767
|
+
return withBlank.filter((row) => row.label.toLowerCase().includes(q));
|
|
6768
|
+
}, [facets, query]);
|
|
6769
|
+
const toggle = (candidate) => {
|
|
6770
|
+
const next = new Set(selectedSet);
|
|
6771
|
+
if (next.has(candidate)) next.delete(candidate);
|
|
6772
|
+
else next.add(candidate);
|
|
6773
|
+
const values = [...next];
|
|
6774
|
+
onChange(
|
|
6775
|
+
values.length === 0 ? void 0 : { kind: "select", value: values[0] ?? "", values }
|
|
6776
|
+
);
|
|
6777
|
+
};
|
|
6778
|
+
const notice = error ?? (loading ? FACETS_LOADING_NOTICE : describeFacetSource(facets));
|
|
6779
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "space-y-1.5", children: [
|
|
6780
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "px-1 text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: "Values" }),
|
|
6781
|
+
facets && facets.values.length + (facets.blank > 0 ? 1 : 0) > 8 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6782
|
+
Input,
|
|
6783
|
+
{
|
|
6784
|
+
"data-matrx-filter-autofocus": true,
|
|
6785
|
+
value: query,
|
|
6786
|
+
onChange: (event) => setQuery(event.target.value),
|
|
6787
|
+
placeholder: "Find a value\u2026",
|
|
6788
|
+
className: "h-7 text-sm",
|
|
6789
|
+
style: { fontSize: "16px" }
|
|
6790
|
+
}
|
|
6791
|
+
) : null,
|
|
6792
|
+
rows.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("ul", { className: "max-h-56 space-y-0.5 overflow-y-auto", "data-matrx-facet-list": "true", children: rows.map((row) => {
|
|
6793
|
+
const checked = selectedSet.has(row.value);
|
|
6794
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
6795
|
+
"button",
|
|
6796
|
+
{
|
|
6797
|
+
type: "button",
|
|
6798
|
+
role: "checkbox",
|
|
6799
|
+
"aria-checked": checked,
|
|
6800
|
+
"data-matrx-facet-value": row.value === "" ? "__blank__" : row.value,
|
|
6801
|
+
onClick: () => toggle(row.value),
|
|
6802
|
+
className: cn(
|
|
6803
|
+
"flex w-full items-center gap-2 rounded px-1.5 py-1 text-left text-xs hover:bg-muted",
|
|
6804
|
+
checked && "bg-primary/10"
|
|
6805
|
+
),
|
|
6806
|
+
children: [
|
|
6807
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6808
|
+
"span",
|
|
6809
|
+
{
|
|
6810
|
+
"aria-hidden": true,
|
|
6811
|
+
className: cn(
|
|
6812
|
+
"flex h-3.5 w-3.5 shrink-0 items-center justify-center rounded-[3px] border",
|
|
6813
|
+
checked ? "border-primary bg-primary text-primary-foreground" : "border-border"
|
|
6814
|
+
),
|
|
6815
|
+
children: checked ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Check, { className: "h-2.5 w-2.5" }) : null
|
|
6816
|
+
}
|
|
6817
|
+
),
|
|
6818
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: cn("min-w-0 flex-1 truncate", row.value === "" && "italic text-muted-foreground"), children: row.label }),
|
|
6819
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6820
|
+
"span",
|
|
6821
|
+
{
|
|
6822
|
+
"data-matrx-facet-count": String(row.count),
|
|
6823
|
+
className: "shrink-0 tabular-nums text-[11px] text-muted-foreground",
|
|
6824
|
+
children: row.count.toLocaleString("en-US")
|
|
6825
|
+
}
|
|
6826
|
+
)
|
|
6827
|
+
]
|
|
6828
|
+
}
|
|
6829
|
+
) }, row.value === "" ? "__blank__" : row.value);
|
|
6830
|
+
}) }) : loading ? null : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "px-1 text-[11px] text-muted-foreground", children: query.trim() ? "No value matches that." : "This column has no values yet." }),
|
|
6831
|
+
notice ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6832
|
+
"p",
|
|
6833
|
+
{
|
|
6834
|
+
"data-matrx-facet-notice": "true",
|
|
6835
|
+
className: cn(
|
|
6836
|
+
"px-1 text-[11px] leading-snug",
|
|
6837
|
+
error ? "text-amber-700 dark:text-amber-400" : "text-muted-foreground"
|
|
6838
|
+
),
|
|
6839
|
+
children: notice
|
|
6840
|
+
}
|
|
6841
|
+
) : null,
|
|
6842
|
+
selected.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
6843
|
+
"button",
|
|
6844
|
+
{
|
|
6845
|
+
type: "button",
|
|
6846
|
+
onClick: () => onChange(void 0),
|
|
6847
|
+
className: "px-1 text-[11px] text-muted-foreground underline-offset-2 hover:underline",
|
|
6848
|
+
children: "Clear selection"
|
|
6849
|
+
}
|
|
6850
|
+
) : null
|
|
6851
|
+
] });
|
|
6852
|
+
}
|
|
6853
|
+
function DateFilterBody({
|
|
6854
|
+
value,
|
|
6855
|
+
onChange
|
|
6856
|
+
}) {
|
|
6857
|
+
const dateValue = value?.kind === "date" ? value : void 0;
|
|
6858
|
+
const isCustom = dateValue !== void 0 && dateValue.preset === void 0;
|
|
6859
|
+
const selected = dateValue?.preset ?? (isCustom ? "__custom__" : "all");
|
|
6860
|
+
const setBound = (bound, raw) => {
|
|
6861
|
+
const next = raw ? new Date(raw) : void 0;
|
|
6862
|
+
const iso = next && !Number.isNaN(next.valueOf()) ? next.toISOString() : void 0;
|
|
6863
|
+
const current = dateValue && dateValue.preset === void 0 ? dateValue : { kind: "date" };
|
|
6864
|
+
const updated = { ...current, [bound]: iso };
|
|
6865
|
+
if (updated.since === void 0 && updated.until === void 0) onChange(void 0);
|
|
6866
|
+
else onChange(updated);
|
|
6867
|
+
};
|
|
6868
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "space-y-2 px-1", children: [
|
|
6869
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
6870
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: "Date range" }),
|
|
6871
|
+
dateValue ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", className: "text-[11px] text-muted-foreground hover:text-foreground", onClick: () => onChange(void 0), children: "clear" }) : null
|
|
6872
|
+
] }),
|
|
6873
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
6874
|
+
Select,
|
|
6875
|
+
{
|
|
6876
|
+
value: selected,
|
|
6877
|
+
onValueChange: (next) => {
|
|
6878
|
+
if (next === "all") {
|
|
6879
|
+
onChange(void 0);
|
|
6880
|
+
return;
|
|
6881
|
+
}
|
|
6882
|
+
if (next === "__custom__") {
|
|
6883
|
+
onChange({ kind: "date" });
|
|
6884
|
+
return;
|
|
6885
|
+
}
|
|
6886
|
+
onChange({ kind: "date", preset: next, anchor: (/* @__PURE__ */ new Date()).toISOString() });
|
|
6887
|
+
},
|
|
6888
|
+
children: [
|
|
6889
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(SelectValue, {}) }),
|
|
6890
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(SelectContent, { children: [
|
|
6891
|
+
["all", "recent", "calendar", "older"].map((group) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { children: [
|
|
6892
|
+
group !== "all" ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "px-2 py-1 text-[10px] font-medium uppercase tracking-wider text-muted-foreground", children: group }) : null,
|
|
6893
|
+
TIME_RANGE_PRESETS.filter((option) => option.group === group).map((option) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(SelectItem, { value: option.value, children: option.label }, option.value))
|
|
6894
|
+
] }, group)),
|
|
6895
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(SelectItem, { value: "__custom__", children: "Custom range" })
|
|
6896
|
+
] })
|
|
6897
|
+
]
|
|
6898
|
+
}
|
|
6899
|
+
),
|
|
6900
|
+
isCustom ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "grid gap-1.5", children: [
|
|
6901
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("label", { className: "grid gap-0.5 text-[11px] text-muted-foreground", children: [
|
|
6902
|
+
"On or after",
|
|
6903
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Input, { type: "datetime-local", value: dateTimeLocal(dateValue?.since), onChange: (event) => setBound("since", event.target.value), className: "h-8 text-xs" })
|
|
6904
|
+
] }),
|
|
6905
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("label", { className: "grid gap-0.5 text-[11px] text-muted-foreground", children: [
|
|
6906
|
+
"Before",
|
|
6907
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Input, { type: "datetime-local", value: dateTimeLocal(dateValue?.until), onChange: (event) => setBound("until", event.target.value), className: "h-8 text-xs" })
|
|
6908
|
+
] })
|
|
6909
|
+
] }) : null
|
|
6910
|
+
] });
|
|
6911
|
+
}
|
|
6912
|
+
function dateTimeLocal(value) {
|
|
6913
|
+
if (!value) return "";
|
|
6914
|
+
const date = new Date(value);
|
|
6915
|
+
if (Number.isNaN(date.valueOf())) return "";
|
|
6916
|
+
const offset = date.getTimezoneOffset() * 6e4;
|
|
6917
|
+
return new Date(date.valueOf() - offset).toISOString().slice(0, 16);
|
|
6918
|
+
}
|
|
6465
6919
|
function SearchableSelectFilter({
|
|
6466
6920
|
selected,
|
|
6467
6921
|
options,
|
|
@@ -6648,8 +7102,8 @@ function NumberFilterBody({
|
|
|
6648
7102
|
}
|
|
6649
7103
|
function parseOptionalNumber(raw) {
|
|
6650
7104
|
if (raw.trim() === "") return void 0;
|
|
6651
|
-
const
|
|
6652
|
-
return Number.isFinite(
|
|
7105
|
+
const n2 = Number(raw.replace(/[^0-9.-]/g, ""));
|
|
7106
|
+
return Number.isFinite(n2) ? n2 : void 0;
|
|
6653
7107
|
}
|
|
6654
7108
|
|
|
6655
7109
|
// src/data-table/ColumnResizeHandle.tsx
|
|
@@ -6961,16 +7415,16 @@ function computeAggregate(rows, column) {
|
|
|
6961
7415
|
value = total;
|
|
6962
7416
|
break;
|
|
6963
7417
|
case "sum":
|
|
6964
|
-
value = numbers.length === 0 ? null : numbers.reduce((acc,
|
|
7418
|
+
value = numbers.length === 0 ? null : numbers.reduce((acc, n2) => acc + n2, 0);
|
|
6965
7419
|
break;
|
|
6966
7420
|
case "average":
|
|
6967
|
-
value = numbers.length === 0 ? null : numbers.reduce((acc,
|
|
7421
|
+
value = numbers.length === 0 ? null : numbers.reduce((acc, n2) => acc + n2, 0) / numbers.length;
|
|
6968
7422
|
break;
|
|
6969
7423
|
case "min":
|
|
6970
|
-
value = numbers.length === 0 ? null : numbers.reduce((acc,
|
|
7424
|
+
value = numbers.length === 0 ? null : numbers.reduce((acc, n2) => n2 < acc ? n2 : acc);
|
|
6971
7425
|
break;
|
|
6972
7426
|
case "max":
|
|
6973
|
-
value = numbers.length === 0 ? null : numbers.reduce((acc,
|
|
7427
|
+
value = numbers.length === 0 ? null : numbers.reduce((acc, n2) => n2 > acc ? n2 : acc);
|
|
6974
7428
|
break;
|
|
6975
7429
|
case "empty":
|
|
6976
7430
|
value = total - filled.length;
|
|
@@ -7394,7 +7848,7 @@ function moveSelection(current, move, rowIds, fieldNames) {
|
|
|
7394
7848
|
if (r === -1 || c === -1) return first;
|
|
7395
7849
|
const lastRow = rowIds.length - 1;
|
|
7396
7850
|
const lastCol = fieldNames.length - 1;
|
|
7397
|
-
const clamp = (
|
|
7851
|
+
const clamp = (n2, max) => Math.min(Math.max(n2, 0), max);
|
|
7398
7852
|
switch (move) {
|
|
7399
7853
|
case "up":
|
|
7400
7854
|
r = clamp(r - 1, lastRow);
|
|
@@ -7526,14 +7980,14 @@ function parseClipboardGrid(text) {
|
|
|
7526
7980
|
let row = [];
|
|
7527
7981
|
let cell = "";
|
|
7528
7982
|
let i = 0;
|
|
7529
|
-
const
|
|
7530
|
-
while (i <
|
|
7983
|
+
const n2 = text.length;
|
|
7984
|
+
while (i < n2) {
|
|
7531
7985
|
const ch = text[i];
|
|
7532
7986
|
if (cell === "" && ch === '"') {
|
|
7533
7987
|
let j = i + 1;
|
|
7534
7988
|
let out = "";
|
|
7535
7989
|
let closed = false;
|
|
7536
|
-
while (j <
|
|
7990
|
+
while (j < n2) {
|
|
7537
7991
|
const c = text[j];
|
|
7538
7992
|
if (c === '"') {
|
|
7539
7993
|
if (text[j + 1] === '"') {
|
|
@@ -7548,10 +8002,10 @@ function parseClipboardGrid(text) {
|
|
|
7548
8002
|
out += c;
|
|
7549
8003
|
j += 1;
|
|
7550
8004
|
}
|
|
7551
|
-
if (closed && (j >=
|
|
8005
|
+
if (closed && (j >= n2 || text[j] === " " || text[j] === "\n" || text[j] === "\r")) {
|
|
7552
8006
|
cell = out;
|
|
7553
8007
|
i = j;
|
|
7554
|
-
if (i >=
|
|
8008
|
+
if (i >= n2) break;
|
|
7555
8009
|
const d = text[i];
|
|
7556
8010
|
if (d === " ") {
|
|
7557
8011
|
row.push(cell);
|
|
@@ -7587,7 +8041,7 @@ function parseClipboardGrid(text) {
|
|
|
7587
8041
|
cell += ch;
|
|
7588
8042
|
i += 1;
|
|
7589
8043
|
}
|
|
7590
|
-
const endedOnBreak =
|
|
8044
|
+
const endedOnBreak = n2 > 0 && (text[n2 - 1] === "\n" || text[n2 - 1] === "\r");
|
|
7591
8045
|
if (!endedOnBreak) {
|
|
7592
8046
|
row.push(cell);
|
|
7593
8047
|
rows.push(row);
|
|
@@ -7666,11 +8120,11 @@ function directionOf(source, target) {
|
|
|
7666
8120
|
return null;
|
|
7667
8121
|
}
|
|
7668
8122
|
function tileIndex(i, a, b) {
|
|
7669
|
-
const
|
|
7670
|
-
if (
|
|
8123
|
+
const n2 = b - a + 1;
|
|
8124
|
+
if (n2 <= 0) return a;
|
|
7671
8125
|
if (i >= a && i <= b) return i;
|
|
7672
|
-
if (i > b) return a + (i - a) %
|
|
7673
|
-
return b - (a - 1 - i) %
|
|
8126
|
+
if (i > b) return a + (i - a) % n2;
|
|
8127
|
+
return b - (a - 1 - i) % n2;
|
|
7674
8128
|
}
|
|
7675
8129
|
function isFiniteNumber(v) {
|
|
7676
8130
|
return typeof v === "number" && Number.isFinite(v);
|
|
@@ -8015,6 +8469,26 @@ function useSpreadsheetGrid(options) {
|
|
|
8015
8469
|
for (let i = 0; i < columnIds.length; i += 1) map.set(columnIds[i], i);
|
|
8016
8470
|
return map;
|
|
8017
8471
|
}, [columnIds]);
|
|
8472
|
+
const screenPatches = (0, import_react15.useCallback)(
|
|
8473
|
+
(patches) => {
|
|
8474
|
+
const validate = optionsRef.current?.validateCell;
|
|
8475
|
+
if (!validate) return { accepted: patches, refusals: [] };
|
|
8476
|
+
const accepted = [];
|
|
8477
|
+
const refusals = [];
|
|
8478
|
+
for (const patch of patches) {
|
|
8479
|
+
let reason;
|
|
8480
|
+
try {
|
|
8481
|
+
reason = validate({ rowId: patch.rowId, columnId: patch.columnId, value: patch.value });
|
|
8482
|
+
} catch {
|
|
8483
|
+
reason = void 0;
|
|
8484
|
+
}
|
|
8485
|
+
if (reason) refusals.push({ columnId: patch.columnId, reason });
|
|
8486
|
+
else accepted.push(patch);
|
|
8487
|
+
}
|
|
8488
|
+
return { accepted, refusals };
|
|
8489
|
+
},
|
|
8490
|
+
[]
|
|
8491
|
+
);
|
|
8018
8492
|
const applyPatches = (0, import_react15.useCallback)(
|
|
8019
8493
|
async (patches, intent, label) => {
|
|
8020
8494
|
const current = optionsRef.current;
|
|
@@ -8071,9 +8545,10 @@ function useSpreadsheetGrid(options) {
|
|
|
8071
8545
|
...base,
|
|
8072
8546
|
range: { top: bounds.r0, left: bounds.c0, bottom: bounds.r1, right: bounds.c1 }
|
|
8073
8547
|
});
|
|
8074
|
-
|
|
8075
|
-
|
|
8076
|
-
|
|
8548
|
+
const screened = screenPatches(result.patches);
|
|
8549
|
+
await applyPatches(screened.accepted, "fill-down", "Filled down");
|
|
8550
|
+
announceSkips([...result.skipped, ...screened.refusals], result.summary);
|
|
8551
|
+
}, [fillRequestBase, bounds, applyPatches, announceSkips, screenPatches]);
|
|
8077
8552
|
const doClear = (0, import_react15.useCallback)(async () => {
|
|
8078
8553
|
const current = optionsRef.current;
|
|
8079
8554
|
if (!current || !bounds) return;
|
|
@@ -8094,9 +8569,13 @@ function useSpreadsheetGrid(options) {
|
|
|
8094
8569
|
patches.push({ rowId, columnId: columnId2, value: null });
|
|
8095
8570
|
}
|
|
8096
8571
|
}
|
|
8097
|
-
|
|
8098
|
-
|
|
8099
|
-
|
|
8572
|
+
const screened = screenPatches(patches);
|
|
8573
|
+
await applyPatches(screened.accepted, "clear", "Cleared");
|
|
8574
|
+
announceSkips(
|
|
8575
|
+
[...skipped, ...screened.refusals],
|
|
8576
|
+
`Cleared ${screened.accepted.length} cells.`
|
|
8577
|
+
);
|
|
8578
|
+
}, [bounds, applyPatches, announceSkips, screenPatches]);
|
|
8100
8579
|
const doUndo = (0, import_react15.useCallback)(async () => {
|
|
8101
8580
|
const taken = popUndo(stack);
|
|
8102
8581
|
if (!taken.entry) return;
|
|
@@ -8181,6 +8660,14 @@ function useSpreadsheetGrid(options) {
|
|
|
8181
8660
|
case "escape":
|
|
8182
8661
|
setRange(null);
|
|
8183
8662
|
return;
|
|
8663
|
+
case "edit":
|
|
8664
|
+
case "editSeeded": {
|
|
8665
|
+
const focused = range?.focus;
|
|
8666
|
+
if (!focused || !current.onEditRequest) return;
|
|
8667
|
+
const seed = action.kind === "editSeeded" ? action.seed : null;
|
|
8668
|
+
if (current.onEditRequest(focused, seed)) event.preventDefault();
|
|
8669
|
+
return;
|
|
8670
|
+
}
|
|
8184
8671
|
default:
|
|
8185
8672
|
return;
|
|
8186
8673
|
}
|
|
@@ -8195,6 +8682,13 @@ function useSpreadsheetGrid(options) {
|
|
|
8195
8682
|
);
|
|
8196
8683
|
return gridToTsv(grid);
|
|
8197
8684
|
}, [range, rowIds, columnIds]);
|
|
8685
|
+
const selectionAddresses = (0, import_react15.useCallback)(() => {
|
|
8686
|
+
if (!range || !bounds) return { rowIds: [], columnIds: [] };
|
|
8687
|
+
return {
|
|
8688
|
+
rowIds: rowIds.slice(bounds.r0, bounds.r1 + 1),
|
|
8689
|
+
columnIds: columnIds.slice(bounds.c0, bounds.c1 + 1)
|
|
8690
|
+
};
|
|
8691
|
+
}, [range, bounds, rowIds, columnIds]);
|
|
8198
8692
|
const onCopy = (0, import_react15.useCallback)(
|
|
8199
8693
|
(event) => {
|
|
8200
8694
|
if (!optionsRef.current || !range || targetsAnEditor(event.target)) return;
|
|
@@ -8250,11 +8744,12 @@ function useSpreadsheetGrid(options) {
|
|
|
8250
8744
|
patches.push({ rowId, columnId: columnId2, value: line[c] ?? null });
|
|
8251
8745
|
}
|
|
8252
8746
|
}
|
|
8253
|
-
|
|
8747
|
+
const screened = screenPatches(patches);
|
|
8748
|
+
void applyPatches(screened.accepted, "paste", "Pasted");
|
|
8254
8749
|
const tail = outside > 0 ? ` ${outside} landed past the edge of the table and were ignored.` : "";
|
|
8255
|
-
announceSkips(skipped, `Pasted ${
|
|
8750
|
+
announceSkips([...skipped, ...screened.refusals], `Pasted ${screened.accepted.length} cells.${tail}`);
|
|
8256
8751
|
},
|
|
8257
|
-
[range, rowIds, columnIds, applyPatches, announceSkips]
|
|
8752
|
+
[range, rowIds, columnIds, applyPatches, announceSkips, screenPatches]
|
|
8258
8753
|
);
|
|
8259
8754
|
const cellProps = (0, import_react15.useCallback)(
|
|
8260
8755
|
(rowId, columnId2) => {
|
|
@@ -8273,6 +8768,10 @@ function useSpreadsheetGrid(options) {
|
|
|
8273
8768
|
onMouseDown: (event) => {
|
|
8274
8769
|
if (event.button !== 0) return;
|
|
8275
8770
|
event.preventDefault();
|
|
8771
|
+
const origin = event.currentTarget;
|
|
8772
|
+
if (typeof HTMLElement !== "undefined" && origin instanceof HTMLElement) {
|
|
8773
|
+
origin.closest('[data-matrx-table-spreadsheet="true"]')?.focus({ preventScroll: true });
|
|
8774
|
+
}
|
|
8276
8775
|
setRange(
|
|
8277
8776
|
(previous) => event.shiftKey && previous ? { anchor: previous.anchor, focus: address } : { anchor: address, focus: address }
|
|
8278
8777
|
);
|
|
@@ -8334,12 +8833,13 @@ function useSpreadsheetGrid(options) {
|
|
|
8334
8833
|
source: { top: source.r0, left: source.c0, bottom: source.r1, right: source.c1 },
|
|
8335
8834
|
target
|
|
8336
8835
|
});
|
|
8337
|
-
|
|
8338
|
-
|
|
8836
|
+
const screened = screenPatches(result.patches);
|
|
8837
|
+
void applyPatches(screened.accepted, "fill", "Filled");
|
|
8838
|
+
announceSkips([...result.skipped, ...screened.refusals], result.summary);
|
|
8339
8839
|
};
|
|
8340
8840
|
window.addEventListener("mouseup", commit);
|
|
8341
8841
|
return () => window.removeEventListener("mouseup", commit);
|
|
8342
|
-
}, [options, fillRequestBase, applyPatches, announceSkips]);
|
|
8842
|
+
}, [options, fillRequestBase, applyPatches, announceSkips, screenPatches]);
|
|
8343
8843
|
return {
|
|
8344
8844
|
range,
|
|
8345
8845
|
bounds,
|
|
@@ -8355,17 +8855,19 @@ function useSpreadsheetGrid(options) {
|
|
|
8355
8855
|
isFillHandleCell,
|
|
8356
8856
|
startFillDrag,
|
|
8357
8857
|
canUndo: stack.past.length > 0,
|
|
8358
|
-
canRedo: stack.future.length > 0
|
|
8858
|
+
canRedo: stack.future.length > 0,
|
|
8859
|
+
selectionTsv: selectionAsTsv,
|
|
8860
|
+
selectionAddresses
|
|
8359
8861
|
};
|
|
8360
8862
|
}
|
|
8361
8863
|
|
|
8362
8864
|
// src/data-table/coverage.ts
|
|
8363
8865
|
var PARTIAL_BADGE = "Partial";
|
|
8364
8866
|
var UNKNOWN_TOTAL_BADGE = "Unknown total";
|
|
8365
|
-
var
|
|
8867
|
+
var NUMBERS2 = new Intl.NumberFormat("en-US");
|
|
8366
8868
|
function formatNumber(value) {
|
|
8367
8869
|
try {
|
|
8368
|
-
return
|
|
8870
|
+
return NUMBERS2.format(value);
|
|
8369
8871
|
} catch {
|
|
8370
8872
|
return String(value);
|
|
8371
8873
|
}
|
|
@@ -8996,7 +9498,8 @@ var filterSchema = import_zod2.z.union([
|
|
|
8996
9498
|
import_zod2.z.object({ kind: import_zod2.z.literal("text"), value: import_zod2.z.string(), mode: import_zod2.z.enum(["contains", "empty", "not_empty", "null", "not_null"]).optional(), negated: import_zod2.z.boolean().optional() }),
|
|
8997
9499
|
import_zod2.z.object({ kind: import_zod2.z.literal("select"), value: import_zod2.z.string(), values: import_zod2.z.array(import_zod2.z.string()).optional(), negated: import_zod2.z.boolean().optional() }),
|
|
8998
9500
|
import_zod2.z.object({ kind: import_zod2.z.literal("boolean"), value: import_zod2.z.boolean(), negated: import_zod2.z.boolean().optional() }),
|
|
8999
|
-
import_zod2.z.object({ kind: import_zod2.z.literal("number"), min: import_zod2.z.number().optional(), max: import_zod2.z.number().optional(), negated: import_zod2.z.boolean().optional() })
|
|
9501
|
+
import_zod2.z.object({ kind: import_zod2.z.literal("number"), min: import_zod2.z.number().optional(), max: import_zod2.z.number().optional(), negated: import_zod2.z.boolean().optional() }),
|
|
9502
|
+
import_zod2.z.object({ kind: import_zod2.z.literal("date"), preset: import_zod2.z.enum(TIME_RANGE_PRESET_VALUES).optional(), since: import_zod2.z.string().datetime({ offset: true }).optional(), until: import_zod2.z.string().datetime({ offset: true }).optional(), anchor: import_zod2.z.string().datetime({ offset: true }).optional() })
|
|
9000
9503
|
]);
|
|
9001
9504
|
var layeredRuleSchema = import_zod2.z.object({ id: import_zod2.z.string().min(1), field: import_zod2.z.string().min(1), operator: import_zod2.z.enum(LAYERED_FILTER_OPERATORS), value: import_zod2.z.string(), valueTo: import_zod2.z.string().optional() });
|
|
9002
9505
|
var snapshotSchema = import_zod2.z.object({
|
|
@@ -9024,7 +9527,8 @@ function normalizeFilters(raw) {
|
|
|
9024
9527
|
if (value.kind === "text") filters[id] = { kind: "text", value: value.value, ...value.mode === void 0 ? {} : { mode: value.mode }, ...value.negated === void 0 ? {} : { negated: value.negated } };
|
|
9025
9528
|
else if (value.kind === "select") filters[id] = { kind: "select", value: value.value, ...value.values === void 0 ? {} : { values: value.values }, ...value.negated === void 0 ? {} : { negated: value.negated } };
|
|
9026
9529
|
else if (value.kind === "boolean") filters[id] = { kind: "boolean", value: value.value, ...value.negated === void 0 ? {} : { negated: value.negated } };
|
|
9027
|
-
else filters[id] = { kind: "number", ...value.min === void 0 ? {} : { min: value.min }, ...value.max === void 0 ? {} : { max: value.max }, ...value.negated === void 0 ? {} : { negated: value.negated } };
|
|
9530
|
+
else if (value.kind === "number") filters[id] = { kind: "number", ...value.min === void 0 ? {} : { min: value.min }, ...value.max === void 0 ? {} : { max: value.max }, ...value.negated === void 0 ? {} : { negated: value.negated } };
|
|
9531
|
+
else filters[id] = { kind: "date", ...value.preset === void 0 ? {} : { preset: value.preset }, ...value.since === void 0 ? {} : { since: value.since }, ...value.until === void 0 ? {} : { until: value.until }, ...value.anchor === void 0 ? {} : { anchor: value.anchor } };
|
|
9028
9532
|
}
|
|
9029
9533
|
return filters;
|
|
9030
9534
|
}
|
|
@@ -9563,8 +10067,8 @@ function toNumber(value) {
|
|
|
9563
10067
|
if (typeof value === "string") {
|
|
9564
10068
|
const cleaned = value.replace(/[,\s$€£¥%]/g, "");
|
|
9565
10069
|
if (cleaned === "") return null;
|
|
9566
|
-
const
|
|
9567
|
-
return Number.isFinite(
|
|
10070
|
+
const n2 = Number(cleaned);
|
|
10071
|
+
return Number.isFinite(n2) ? n2 : null;
|
|
9568
10072
|
}
|
|
9569
10073
|
return null;
|
|
9570
10074
|
}
|
|
@@ -9574,6 +10078,7 @@ function toText(value) {
|
|
|
9574
10078
|
return String(value);
|
|
9575
10079
|
return null;
|
|
9576
10080
|
}
|
|
10081
|
+
var BARE_CALENDAR_DATE = /^(\d{4})-(\d{2})-(\d{2})(?:[T ]00:00(?::00(?:\.0+)?)?)?$/;
|
|
9577
10082
|
function toDate(value) {
|
|
9578
10083
|
if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value;
|
|
9579
10084
|
if (typeof value === "number") {
|
|
@@ -9581,6 +10086,20 @@ function toDate(value) {
|
|
|
9581
10086
|
return Number.isNaN(d.getTime()) ? null : d;
|
|
9582
10087
|
}
|
|
9583
10088
|
if (typeof value === "string" && value.trim()) {
|
|
10089
|
+
const bare = BARE_CALENDAR_DATE.exec(value.trim());
|
|
10090
|
+
if (bare) {
|
|
10091
|
+
const [year, month, day] = [
|
|
10092
|
+
Number(bare[1]),
|
|
10093
|
+
Number(bare[2]),
|
|
10094
|
+
Number(bare[3])
|
|
10095
|
+
];
|
|
10096
|
+
const d2 = new Date(year, month - 1, day);
|
|
10097
|
+
d2.setFullYear(year);
|
|
10098
|
+
if (d2.getFullYear() !== year || d2.getMonth() !== month - 1 || d2.getDate() !== day) {
|
|
10099
|
+
return null;
|
|
10100
|
+
}
|
|
10101
|
+
return d2;
|
|
10102
|
+
}
|
|
9584
10103
|
const d = new Date(value);
|
|
9585
10104
|
return Number.isNaN(d.getTime()) ? null : d;
|
|
9586
10105
|
}
|
|
@@ -9602,14 +10121,14 @@ function toList(value) {
|
|
|
9602
10121
|
}
|
|
9603
10122
|
return null;
|
|
9604
10123
|
}
|
|
9605
|
-
function groupedNumber(
|
|
10124
|
+
function groupedNumber(n2, options) {
|
|
9606
10125
|
return new Intl.NumberFormat(void 0, {
|
|
9607
10126
|
useGrouping: options.useGrouping !== false,
|
|
9608
10127
|
...options.precision != null ? {
|
|
9609
10128
|
minimumFractionDigits: options.precision,
|
|
9610
10129
|
maximumFractionDigits: options.precision
|
|
9611
10130
|
} : { maximumFractionDigits: 10 }
|
|
9612
|
-
}).format(
|
|
10131
|
+
}).format(n2);
|
|
9613
10132
|
}
|
|
9614
10133
|
function affix(text, options) {
|
|
9615
10134
|
return `${options.prefix ?? ""}${text}${options.suffix ?? ""}`;
|
|
@@ -9743,8 +10262,8 @@ var DEFS = [
|
|
|
9743
10262
|
numericAlign: true,
|
|
9744
10263
|
optionKeys: ["useGrouping", "precision", "prefix", "suffix"],
|
|
9745
10264
|
format: (v, o) => {
|
|
9746
|
-
const
|
|
9747
|
-
return
|
|
10265
|
+
const n2 = toNumber(v);
|
|
10266
|
+
return n2 === null ? null : affix(groupedNumber(n2, o), o);
|
|
9748
10267
|
},
|
|
9749
10268
|
parse: (raw) => toNumber(raw)
|
|
9750
10269
|
},
|
|
@@ -9759,9 +10278,9 @@ var DEFS = [
|
|
|
9759
10278
|
numericAlign: true,
|
|
9760
10279
|
optionKeys: ["precision", "useGrouping", "prefix", "suffix"],
|
|
9761
10280
|
format: (v, o) => {
|
|
9762
|
-
const
|
|
9763
|
-
if (
|
|
9764
|
-
return affix(groupedNumber(
|
|
10281
|
+
const n2 = toNumber(v);
|
|
10282
|
+
if (n2 === null) return null;
|
|
10283
|
+
return affix(groupedNumber(n2, { ...o, precision: o.precision ?? 2 }), o);
|
|
9765
10284
|
},
|
|
9766
10285
|
parse: (raw) => toNumber(raw)
|
|
9767
10286
|
},
|
|
@@ -9776,8 +10295,8 @@ var DEFS = [
|
|
|
9776
10295
|
numericAlign: true,
|
|
9777
10296
|
optionKeys: ["currency", "precision"],
|
|
9778
10297
|
format: (v, o) => {
|
|
9779
|
-
const
|
|
9780
|
-
if (
|
|
10298
|
+
const n2 = toNumber(v);
|
|
10299
|
+
if (n2 === null) return null;
|
|
9781
10300
|
const currency = (o.currency || "USD").toUpperCase();
|
|
9782
10301
|
try {
|
|
9783
10302
|
return new Intl.NumberFormat(void 0, {
|
|
@@ -9787,9 +10306,9 @@ var DEFS = [
|
|
|
9787
10306
|
minimumFractionDigits: o.precision,
|
|
9788
10307
|
maximumFractionDigits: o.precision
|
|
9789
10308
|
} : {}
|
|
9790
|
-
}).format(
|
|
10309
|
+
}).format(n2);
|
|
9791
10310
|
} catch {
|
|
9792
|
-
return `${groupedNumber(
|
|
10311
|
+
return `${groupedNumber(n2, { precision: o.precision ?? 2 })} ${currency}`;
|
|
9793
10312
|
}
|
|
9794
10313
|
},
|
|
9795
10314
|
parse: (raw) => toNumber(raw)
|
|
@@ -9805,9 +10324,9 @@ var DEFS = [
|
|
|
9805
10324
|
numericAlign: true,
|
|
9806
10325
|
optionKeys: ["percentScale", "precision"],
|
|
9807
10326
|
format: (v, o) => {
|
|
9808
|
-
const
|
|
9809
|
-
if (
|
|
9810
|
-
const shown = o.percentScale === "fraction" ?
|
|
10327
|
+
const n2 = toNumber(v);
|
|
10328
|
+
if (n2 === null) return null;
|
|
10329
|
+
const shown = o.percentScale === "fraction" ? n2 * 100 : n2;
|
|
9811
10330
|
return `${groupedNumber(shown, o.precision === void 0 ? {} : { precision: o.precision })}%`;
|
|
9812
10331
|
},
|
|
9813
10332
|
parse: (raw) => toNumber(raw)
|
|
@@ -9823,9 +10342,9 @@ var DEFS = [
|
|
|
9823
10342
|
numericAlign: true,
|
|
9824
10343
|
optionKeys: ["durationUnit"],
|
|
9825
10344
|
format: (v, o) => {
|
|
9826
|
-
const
|
|
9827
|
-
if (
|
|
9828
|
-
return formatSignedDuration(
|
|
10345
|
+
const n2 = toNumber(v);
|
|
10346
|
+
if (n2 === null) return null;
|
|
10347
|
+
return formatSignedDuration(n2 * DURATION_TO_SECONDS[o.durationUnit ?? "seconds"]);
|
|
9829
10348
|
},
|
|
9830
10349
|
parse: (raw) => toNumber(raw)
|
|
9831
10350
|
},
|
|
@@ -9840,13 +10359,13 @@ var DEFS = [
|
|
|
9840
10359
|
numericAlign: true,
|
|
9841
10360
|
optionKeys: ["useGrouping", "prefix", "suffix"],
|
|
9842
10361
|
format: (v, o) => {
|
|
9843
|
-
const
|
|
9844
|
-
if (
|
|
9845
|
-
return affix(groupedNumber(Math.trunc(
|
|
10362
|
+
const n2 = toNumber(v);
|
|
10363
|
+
if (n2 === null) return null;
|
|
10364
|
+
return affix(groupedNumber(Math.trunc(n2), { ...o, precision: 0 }), o);
|
|
9846
10365
|
},
|
|
9847
10366
|
parse: (raw) => {
|
|
9848
|
-
const
|
|
9849
|
-
return
|
|
10367
|
+
const n2 = toNumber(raw);
|
|
10368
|
+
return n2 === null ? null : Math.trunc(n2);
|
|
9850
10369
|
}
|
|
9851
10370
|
},
|
|
9852
10371
|
{
|
|
@@ -9860,15 +10379,15 @@ var DEFS = [
|
|
|
9860
10379
|
rich: true,
|
|
9861
10380
|
optionKeys: ["ratingMax"],
|
|
9862
10381
|
format: (v, o) => {
|
|
9863
|
-
const
|
|
9864
|
-
if (
|
|
10382
|
+
const n2 = toNumber(v);
|
|
10383
|
+
if (n2 === null) return null;
|
|
9865
10384
|
const max = o.ratingMax ?? 5;
|
|
9866
|
-
if (
|
|
9867
|
-
return `${
|
|
10385
|
+
if (n2 < 0 || n2 > max) return null;
|
|
10386
|
+
return `${n2} / ${max}`;
|
|
9868
10387
|
},
|
|
9869
10388
|
parse: (raw) => {
|
|
9870
|
-
const
|
|
9871
|
-
return
|
|
10389
|
+
const n2 = toNumber(raw);
|
|
10390
|
+
return n2 === null ? null : Math.round(n2);
|
|
9872
10391
|
}
|
|
9873
10392
|
},
|
|
9874
10393
|
{
|
|
@@ -9881,12 +10400,12 @@ var DEFS = [
|
|
|
9881
10400
|
editor: "number",
|
|
9882
10401
|
numericAlign: true,
|
|
9883
10402
|
format: (v) => {
|
|
9884
|
-
const
|
|
9885
|
-
return
|
|
10403
|
+
const n2 = toNumber(v);
|
|
10404
|
+
return n2 === null ? null : (0, import_format3.formatFileSize)(n2);
|
|
9886
10405
|
},
|
|
9887
10406
|
parse: (raw) => {
|
|
9888
|
-
const
|
|
9889
|
-
return
|
|
10407
|
+
const n2 = toNumber(raw);
|
|
10408
|
+
return n2 === null ? null : Math.trunc(n2);
|
|
9890
10409
|
}
|
|
9891
10410
|
},
|
|
9892
10411
|
// ── Choice ────────────────────────────────────────────────────────────────
|
|
@@ -10298,6 +10817,17 @@ function DirtySavePill({
|
|
|
10298
10817
|
// src/data-table/EditableTableCell.tsx
|
|
10299
10818
|
var import_react19 = require("react");
|
|
10300
10819
|
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
10820
|
+
function CellRefusal({ reason }) {
|
|
10821
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
10822
|
+
"p",
|
|
10823
|
+
{
|
|
10824
|
+
role: "alert",
|
|
10825
|
+
"data-matrx-cell-refusal": "true",
|
|
10826
|
+
className: "mt-1 text-[11px] leading-snug text-amber-700 dark:text-amber-400",
|
|
10827
|
+
children: reason
|
|
10828
|
+
}
|
|
10829
|
+
);
|
|
10830
|
+
}
|
|
10301
10831
|
function CellEditShell({
|
|
10302
10832
|
href,
|
|
10303
10833
|
display,
|
|
@@ -10344,12 +10874,17 @@ function EditableTableCell({
|
|
|
10344
10874
|
className,
|
|
10345
10875
|
href,
|
|
10346
10876
|
editTrigger = "click",
|
|
10347
|
-
editRequest
|
|
10877
|
+
editRequest,
|
|
10878
|
+
editSeed
|
|
10348
10879
|
}) {
|
|
10349
10880
|
const [open, setOpen] = (0, import_react19.useState)(false);
|
|
10881
|
+
const [refusal, setRefusal] = (0, import_react19.useState)(null);
|
|
10350
10882
|
(0, import_react19.useEffect)(() => {
|
|
10351
10883
|
if (editRequest !== void 0) setOpen(true);
|
|
10352
10884
|
}, [editRequest]);
|
|
10885
|
+
(0, import_react19.useEffect)(() => {
|
|
10886
|
+
if (!open) setRefusal(null);
|
|
10887
|
+
}, [open]);
|
|
10353
10888
|
const usePencil = Boolean(href) || editTrigger === "pencil";
|
|
10354
10889
|
if (editType === "string") {
|
|
10355
10890
|
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
@@ -10362,7 +10897,8 @@ function EditableTableCell({
|
|
|
10362
10897
|
...className === void 0 ? {} : { className },
|
|
10363
10898
|
...href === void 0 ? {} : { href },
|
|
10364
10899
|
usePencil,
|
|
10365
|
-
...editRequest === void 0 ? {} : { editRequest }
|
|
10900
|
+
...editRequest === void 0 ? {} : { editRequest },
|
|
10901
|
+
...editSeed === void 0 || editSeed === null ? {} : { editSeed }
|
|
10366
10902
|
}
|
|
10367
10903
|
);
|
|
10368
10904
|
}
|
|
@@ -10407,25 +10943,33 @@ function EditableTableCell({
|
|
|
10407
10943
|
) }) }),
|
|
10408
10944
|
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(TooltipContent, { children: "Edit value" })
|
|
10409
10945
|
] }),
|
|
10410
|
-
/* @__PURE__ */ (0, import_jsx_runtime39.
|
|
10946
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
|
|
10411
10947
|
PopoverContent,
|
|
10412
10948
|
{
|
|
10413
10949
|
align: "start",
|
|
10414
10950
|
className: "w-56 p-2",
|
|
10415
10951
|
onClick: (e) => e.stopPropagation(),
|
|
10416
|
-
children:
|
|
10417
|
-
|
|
10418
|
-
|
|
10419
|
-
|
|
10420
|
-
|
|
10421
|
-
|
|
10422
|
-
|
|
10423
|
-
onCommit(next)
|
|
10424
|
-
|
|
10425
|
-
|
|
10426
|
-
|
|
10427
|
-
|
|
10428
|
-
|
|
10952
|
+
children: [
|
|
10953
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
10954
|
+
TypedEditor,
|
|
10955
|
+
{
|
|
10956
|
+
editType,
|
|
10957
|
+
value,
|
|
10958
|
+
editOptions,
|
|
10959
|
+
onCommit: (next) => {
|
|
10960
|
+
const refused = onCommit(next);
|
|
10961
|
+
if (typeof refused === "string" && refused) {
|
|
10962
|
+
setRefusal(refused);
|
|
10963
|
+
return;
|
|
10964
|
+
}
|
|
10965
|
+
setRefusal(null);
|
|
10966
|
+
setOpen(false);
|
|
10967
|
+
},
|
|
10968
|
+
onCancel: () => setOpen(false)
|
|
10969
|
+
}
|
|
10970
|
+
),
|
|
10971
|
+
refusal ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(CellRefusal, { reason: refusal }) : null
|
|
10972
|
+
]
|
|
10429
10973
|
}
|
|
10430
10974
|
)
|
|
10431
10975
|
] });
|
|
@@ -10438,17 +10982,31 @@ function InlineStringEditor({
|
|
|
10438
10982
|
className,
|
|
10439
10983
|
href,
|
|
10440
10984
|
usePencil,
|
|
10441
|
-
editRequest
|
|
10985
|
+
editRequest,
|
|
10986
|
+
editSeed
|
|
10442
10987
|
}) {
|
|
10443
10988
|
const [editing, setEditing] = (0, import_react19.useState)(false);
|
|
10444
10989
|
const [draft, setDraft] = (0, import_react19.useState)(value);
|
|
10990
|
+
const [refusal, setRefusal] = (0, import_react19.useState)(null);
|
|
10445
10991
|
const handledEditRequest = (0, import_react19.useRef)(void 0);
|
|
10992
|
+
const seedRef = (0, import_react19.useRef)(editSeed);
|
|
10993
|
+
seedRef.current = editSeed;
|
|
10446
10994
|
(0, import_react19.useEffect)(() => {
|
|
10447
10995
|
if (editRequest === void 0 || handledEditRequest.current === editRequest) return;
|
|
10448
10996
|
handledEditRequest.current = editRequest;
|
|
10449
|
-
setDraft(value);
|
|
10997
|
+
setDraft(seedRef.current ?? value);
|
|
10998
|
+
setRefusal(null);
|
|
10450
10999
|
setEditing(true);
|
|
10451
11000
|
}, [editRequest, value]);
|
|
11001
|
+
const commit = (next) => {
|
|
11002
|
+
const refused = onCommit(next);
|
|
11003
|
+
if (typeof refused === "string" && refused) {
|
|
11004
|
+
setRefusal(refused);
|
|
11005
|
+
return false;
|
|
11006
|
+
}
|
|
11007
|
+
setRefusal(null);
|
|
11008
|
+
return true;
|
|
11009
|
+
};
|
|
10452
11010
|
if (!editing) {
|
|
10453
11011
|
if (usePencil) {
|
|
10454
11012
|
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
@@ -10499,32 +11057,38 @@ function InlineStringEditor({
|
|
|
10499
11057
|
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(TooltipContent, { children: "Click to edit" })
|
|
10500
11058
|
] });
|
|
10501
11059
|
}
|
|
10502
|
-
return /* @__PURE__ */ (0, import_jsx_runtime39.
|
|
10503
|
-
|
|
10504
|
-
|
|
10505
|
-
|
|
10506
|
-
|
|
10507
|
-
|
|
10508
|
-
|
|
10509
|
-
|
|
10510
|
-
|
|
10511
|
-
|
|
10512
|
-
|
|
10513
|
-
|
|
10514
|
-
|
|
10515
|
-
|
|
10516
|
-
|
|
10517
|
-
|
|
10518
|
-
|
|
10519
|
-
|
|
10520
|
-
|
|
10521
|
-
|
|
10522
|
-
|
|
10523
|
-
|
|
10524
|
-
|
|
10525
|
-
|
|
10526
|
-
|
|
10527
|
-
|
|
11060
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "block w-full", children: [
|
|
11061
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
11062
|
+
Input,
|
|
11063
|
+
{
|
|
11064
|
+
autoFocus: true,
|
|
11065
|
+
value: draft,
|
|
11066
|
+
onClick: (e) => e.stopPropagation(),
|
|
11067
|
+
onChange: (e) => {
|
|
11068
|
+
setDraft(e.target.value);
|
|
11069
|
+
if (refusal) setRefusal(null);
|
|
11070
|
+
},
|
|
11071
|
+
onBlur: () => {
|
|
11072
|
+
if (commit(draft)) setEditing(false);
|
|
11073
|
+
},
|
|
11074
|
+
onKeyDown: (e) => {
|
|
11075
|
+
if (e.key === "Enter") {
|
|
11076
|
+
e.preventDefault();
|
|
11077
|
+
if (commit(draft)) setEditing(false);
|
|
11078
|
+
}
|
|
11079
|
+
if (e.key === "Escape") {
|
|
11080
|
+
e.preventDefault();
|
|
11081
|
+
setRefusal(null);
|
|
11082
|
+
setEditing(false);
|
|
11083
|
+
}
|
|
11084
|
+
},
|
|
11085
|
+
"aria-invalid": refusal ? true : void 0,
|
|
11086
|
+
className: cn("h-7 text-sm", refusal && "border-amber-500 focus-visible:ring-amber-500"),
|
|
11087
|
+
style: { fontSize: "16px" }
|
|
11088
|
+
}
|
|
11089
|
+
),
|
|
11090
|
+
refusal ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(CellRefusal, { reason: refusal }) : null
|
|
11091
|
+
] });
|
|
10528
11092
|
}
|
|
10529
11093
|
function TypedEditor({
|
|
10530
11094
|
editType,
|
|
@@ -10709,8 +11273,8 @@ function NumberEditor({
|
|
|
10709
11273
|
style: { fontSize: "16px" },
|
|
10710
11274
|
onKeyDown: (e) => {
|
|
10711
11275
|
if (e.key === "Enter") {
|
|
10712
|
-
const
|
|
10713
|
-
if (Number.isFinite(
|
|
11276
|
+
const n2 = Number(draft);
|
|
11277
|
+
if (Number.isFinite(n2)) onCommit(n2);
|
|
10714
11278
|
}
|
|
10715
11279
|
if (e.key === "Escape") onCancel();
|
|
10716
11280
|
}
|
|
@@ -10737,8 +11301,8 @@ function NumberEditor({
|
|
|
10737
11301
|
className: "h-7",
|
|
10738
11302
|
"aria-label": "Apply value",
|
|
10739
11303
|
onClick: () => {
|
|
10740
|
-
const
|
|
10741
|
-
if (Number.isFinite(
|
|
11304
|
+
const n2 = Number(draft);
|
|
11305
|
+
if (Number.isFinite(n2)) onCommit(n2);
|
|
10742
11306
|
},
|
|
10743
11307
|
children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Check, { className: "h-3.5 w-3.5" })
|
|
10744
11308
|
}
|
|
@@ -11258,6 +11822,8 @@ function filterKindLabel(kind) {
|
|
|
11258
11822
|
return "Boolean";
|
|
11259
11823
|
case "number":
|
|
11260
11824
|
return "Number";
|
|
11825
|
+
case "date":
|
|
11826
|
+
return "Date";
|
|
11261
11827
|
case "auto":
|
|
11262
11828
|
return "Auto";
|
|
11263
11829
|
case false:
|
|
@@ -11546,6 +12112,7 @@ function MatrxDataTableCore({
|
|
|
11546
12112
|
virtualize,
|
|
11547
12113
|
coverage,
|
|
11548
12114
|
spreadsheet,
|
|
12115
|
+
facets,
|
|
11549
12116
|
rowHeight: explicitRowHeight
|
|
11550
12117
|
}) {
|
|
11551
12118
|
const appendQuery = query?.mode === "controlled-append" ? query : null;
|
|
@@ -12603,9 +13170,92 @@ function MatrxDataTableCore({
|
|
|
12603
13170
|
...spreadsheet.undoDepth === void 0 ? {} : { undoDepth: spreadsheet.undoDepth },
|
|
12604
13171
|
...spreadsheet.fillHandle === void 0 ? {} : { fillHandle: spreadsheet.fillHandle },
|
|
12605
13172
|
...spreadsheet.paste === void 0 ? {} : { paste: spreadsheet.paste },
|
|
12606
|
-
notify: spreadsheet.notify ?? ((message) => toast.success(message))
|
|
13173
|
+
notify: spreadsheet.notify ?? ((message) => toast.success(message)),
|
|
13174
|
+
onEditRequest: (address, seed) => requestCellEditRef.current(address, seed),
|
|
13175
|
+
...spreadsheet.validateCell ? { validateCell: spreadsheet.validateCell } : {}
|
|
12607
13176
|
} : null
|
|
12608
13177
|
);
|
|
13178
|
+
const sheetRef = (0, import_react21.useRef)(sheet);
|
|
13179
|
+
sheetRef.current = sheet;
|
|
13180
|
+
const searchValueRef = (0, import_react21.useRef)(searchValue);
|
|
13181
|
+
searchValueRef.current = searchValue;
|
|
13182
|
+
const facetsEnabled = Boolean(facets && facets.enabled !== false);
|
|
13183
|
+
const [facetState, setFacetState] = (0, import_react21.useState)({});
|
|
13184
|
+
const facetReadCell = (0, import_react21.useCallback)(
|
|
13185
|
+
(row, colId) => {
|
|
13186
|
+
if (facets?.readCell) return facets.readCell(row, colId);
|
|
13187
|
+
const col = visibleColumns.find((candidate) => columnId(candidate) === colId);
|
|
13188
|
+
return col ? getFilterValue(row, col) : void 0;
|
|
13189
|
+
},
|
|
13190
|
+
[facets, visibleColumns]
|
|
13191
|
+
);
|
|
13192
|
+
const facetInputsRef = (0, import_react21.useRef)({ data, facets, facetReadCell });
|
|
13193
|
+
facetInputsRef.current = { data, facets, facetReadCell };
|
|
13194
|
+
const facetRequestRef = (0, import_react21.useRef)(/* @__PURE__ */ new Map());
|
|
13195
|
+
const requestFacets = (0, import_react21.useCallback)((colId) => {
|
|
13196
|
+
const { data: rows, facets: config, facetReadCell: readCell } = facetInputsRef.current;
|
|
13197
|
+
if (!config || config.enabled === false) return;
|
|
13198
|
+
const complete = localFacetsAreComplete(rows.length, config.totalRows);
|
|
13199
|
+
const limit = config.limit;
|
|
13200
|
+
if (complete || !config.source) {
|
|
13201
|
+
setFacetState((current) => ({
|
|
13202
|
+
...current,
|
|
13203
|
+
[colId]: {
|
|
13204
|
+
loading: false,
|
|
13205
|
+
data: computeColumnFacets({
|
|
13206
|
+
columnId: colId,
|
|
13207
|
+
rows,
|
|
13208
|
+
readValue: readCell,
|
|
13209
|
+
...limit === void 0 ? {} : { limit },
|
|
13210
|
+
complete
|
|
13211
|
+
})
|
|
13212
|
+
}
|
|
13213
|
+
}));
|
|
13214
|
+
return;
|
|
13215
|
+
}
|
|
13216
|
+
const ticket = (facetRequestRef.current.get(colId) ?? 0) + 1;
|
|
13217
|
+
facetRequestRef.current.set(colId, ticket);
|
|
13218
|
+
setFacetState((current) => ({
|
|
13219
|
+
...current,
|
|
13220
|
+
[colId]: { loading: true, data: current[colId]?.data ?? null }
|
|
13221
|
+
}));
|
|
13222
|
+
void Promise.resolve().then(
|
|
13223
|
+
() => config.source?.({ columnId: colId, search: searchValueRef.current, limit: limit ?? 200 })
|
|
13224
|
+
).then((answer) => {
|
|
13225
|
+
if (facetRequestRef.current.get(colId) !== ticket) return;
|
|
13226
|
+
if (!answer) {
|
|
13227
|
+
setFacetState((current) => ({
|
|
13228
|
+
...current,
|
|
13229
|
+
[colId]: {
|
|
13230
|
+
loading: false,
|
|
13231
|
+
data: computeColumnFacets({
|
|
13232
|
+
columnId: colId,
|
|
13233
|
+
rows: facetInputsRef.current.data,
|
|
13234
|
+
readValue: facetInputsRef.current.facetReadCell,
|
|
13235
|
+
...limit === void 0 ? {} : { limit },
|
|
13236
|
+
complete: false
|
|
13237
|
+
})
|
|
13238
|
+
}
|
|
13239
|
+
}));
|
|
13240
|
+
return;
|
|
13241
|
+
}
|
|
13242
|
+
setFacetState((current) => ({
|
|
13243
|
+
...current,
|
|
13244
|
+
[colId]: { loading: false, data: { ...answer, answeredBy: "source", complete: true } }
|
|
13245
|
+
}));
|
|
13246
|
+
}).catch((error) => {
|
|
13247
|
+
if (facetRequestRef.current.get(colId) !== ticket) return;
|
|
13248
|
+
setFacetState((current) => ({
|
|
13249
|
+
...current,
|
|
13250
|
+
[colId]: { loading: false, data: null, error: describeFacetFailure(error) }
|
|
13251
|
+
}));
|
|
13252
|
+
});
|
|
13253
|
+
}, []);
|
|
13254
|
+
(0, import_react21.useEffect)(() => {
|
|
13255
|
+
if (!facetsEnabled) return;
|
|
13256
|
+
setFacetState({});
|
|
13257
|
+
facetRequestRef.current = /* @__PURE__ */ new Map();
|
|
13258
|
+
}, [facetsEnabled, data, searchValue]);
|
|
12609
13259
|
(0, import_react21.useEffect)(() => {
|
|
12610
13260
|
if (!controlledQuery || controlledQuery.state.page === safePage) return;
|
|
12611
13261
|
emitControlledQueryChange({ page: safePage });
|
|
@@ -12650,11 +13300,11 @@ function MatrxDataTableCore({
|
|
|
12650
13300
|
});
|
|
12651
13301
|
const hasActiveFilters = activeFilterCount > 0 || Boolean(searchValue.trim()) || intelligentSearchEnabled && searchScope !== "all" || Boolean(anyOfValue.trim()) || completeLayeredFilterRules(layeredFilters).length > 0 || facetActive;
|
|
12652
13302
|
const changeCount = (0, import_react21.useMemo)(() => {
|
|
12653
|
-
let
|
|
13303
|
+
let n2 = 0;
|
|
12654
13304
|
for (const fields of Object.values(edits)) {
|
|
12655
|
-
|
|
13305
|
+
n2 += Object.keys(fields).length;
|
|
12656
13306
|
}
|
|
12657
|
-
return
|
|
13307
|
+
return n2;
|
|
12658
13308
|
}, [edits]);
|
|
12659
13309
|
const showSearch = toolbar?.search !== false;
|
|
12660
13310
|
const openDetail = (row) => {
|
|
@@ -12733,6 +13383,23 @@ function MatrxDataTableCore({
|
|
|
12733
13383
|
icon: void 0
|
|
12734
13384
|
} : emptyState;
|
|
12735
13385
|
const commitCell = (rowId, field, next) => {
|
|
13386
|
+
if (edit?.validate) {
|
|
13387
|
+
const row = data.find((candidate) => getRowId(candidate) === rowId);
|
|
13388
|
+
if (row) {
|
|
13389
|
+
let refusal;
|
|
13390
|
+
try {
|
|
13391
|
+
refusal = edit.validate({
|
|
13392
|
+
row: applyRowEdits(row, edits[rowId]),
|
|
13393
|
+
rowId,
|
|
13394
|
+
columnId: field,
|
|
13395
|
+
value: next
|
|
13396
|
+
});
|
|
13397
|
+
} catch {
|
|
13398
|
+
refusal = void 0;
|
|
13399
|
+
}
|
|
13400
|
+
if (refusal) return refusal;
|
|
13401
|
+
}
|
|
13402
|
+
}
|
|
12736
13403
|
const scope = editScopeKey;
|
|
12737
13404
|
const nextEdits = { [rowId]: { [field]: next } };
|
|
12738
13405
|
const revision = setCellEdit(rowId, field, next);
|
|
@@ -12777,9 +13444,29 @@ function MatrxDataTableCore({
|
|
|
12777
13444
|
setEditRequest((current) => ({
|
|
12778
13445
|
rowId: getRowId(row),
|
|
12779
13446
|
field,
|
|
12780
|
-
nonce: (current?.nonce ?? 0) + 1
|
|
13447
|
+
nonce: (current?.nonce ?? 0) + 1,
|
|
13448
|
+
seed: null
|
|
12781
13449
|
}));
|
|
12782
13450
|
};
|
|
13451
|
+
const requestCellEdit = (address, seed) => {
|
|
13452
|
+
if (!editEnabled) return false;
|
|
13453
|
+
const row = data.find((candidate) => getRowId(candidate) === address.rowId);
|
|
13454
|
+
if (!row) return false;
|
|
13455
|
+
const column = visibleColumns.find(
|
|
13456
|
+
(candidate) => columnId(candidate) === address.fieldName
|
|
13457
|
+
);
|
|
13458
|
+
if (!column?.editable || !(column.editableIf?.(row) ?? true)) return false;
|
|
13459
|
+
const field = column.accessorKey ? String(column.accessorKey) : columnId(column);
|
|
13460
|
+
setEditRequest((current) => ({
|
|
13461
|
+
rowId: address.rowId,
|
|
13462
|
+
field,
|
|
13463
|
+
nonce: (current?.nonce ?? 0) + 1,
|
|
13464
|
+
seed
|
|
13465
|
+
}));
|
|
13466
|
+
return true;
|
|
13467
|
+
};
|
|
13468
|
+
const requestCellEditRef = (0, import_react21.useRef)(requestCellEdit);
|
|
13469
|
+
requestCellEditRef.current = requestCellEdit;
|
|
12783
13470
|
const buildRecordControls = (row) => {
|
|
12784
13471
|
const rowId = getRowId(row);
|
|
12785
13472
|
const pending = edits[rowId];
|
|
@@ -13020,17 +13707,78 @@ function MatrxDataTableCore({
|
|
|
13020
13707
|
setEdits({});
|
|
13021
13708
|
edit?.onCancel?.();
|
|
13022
13709
|
};
|
|
13023
|
-
|
|
13024
|
-
|
|
13025
|
-
return host.rowContextRegistry.register(tableContextMenuInstanceId, (rowId) => {
|
|
13710
|
+
const resolveMenuLevel = (target) => {
|
|
13711
|
+
const rowFor = (rowId) => {
|
|
13026
13712
|
const row = data.find((candidate) => getRowId(candidate) === rowId);
|
|
13027
13713
|
if (!row) return null;
|
|
13028
|
-
|
|
13029
|
-
|
|
13030
|
-
|
|
13031
|
-
|
|
13032
|
-
|
|
13033
|
-
|
|
13714
|
+
return applyRowEdits(row, edits[rowId]);
|
|
13715
|
+
};
|
|
13716
|
+
const columnFor = (id) => visibleColumns.find((col) => columnId(col) === id);
|
|
13717
|
+
const labelFor = (col, id) => col?.label ?? (typeof col?.header === "string" ? col.header : id);
|
|
13718
|
+
const fromHost = (payload) => host.createDefaultMenuContext?.(payload) ?? null;
|
|
13719
|
+
switch (target.level) {
|
|
13720
|
+
case "row": {
|
|
13721
|
+
if (!target.rowId) return null;
|
|
13722
|
+
const displayRow = rowFor(target.rowId);
|
|
13723
|
+
if (!displayRow) return null;
|
|
13724
|
+
const controls = buildRecordControls(displayRow);
|
|
13725
|
+
return contextMenu?.resolveRowContext?.(displayRow, controls) ?? fromHost({ level: "row", row: displayRow, rowId: target.rowId, controls });
|
|
13726
|
+
}
|
|
13727
|
+
case "cell": {
|
|
13728
|
+
if (!target.rowId || !target.columnId) return null;
|
|
13729
|
+
const displayRow = rowFor(target.rowId);
|
|
13730
|
+
const col = columnFor(target.columnId);
|
|
13731
|
+
if (!displayRow || !col) return null;
|
|
13732
|
+
const controls = buildRecordControls(displayRow);
|
|
13733
|
+
const value = spreadsheet?.readCell ? spreadsheet.readCell(displayRow, target.columnId) : getCellValue(displayRow, col);
|
|
13734
|
+
const args = {
|
|
13735
|
+
row: displayRow,
|
|
13736
|
+
rowId: target.rowId,
|
|
13737
|
+
columnId: target.columnId,
|
|
13738
|
+
columnLabel: labelFor(col, target.columnId),
|
|
13739
|
+
value,
|
|
13740
|
+
text: stringifyCellValue(value),
|
|
13741
|
+
controls
|
|
13742
|
+
};
|
|
13743
|
+
return contextMenu?.resolveCellContext?.(args) ?? fromHost({ level: "cell", ...args });
|
|
13744
|
+
}
|
|
13745
|
+
case "column": {
|
|
13746
|
+
if (!target.columnId) return null;
|
|
13747
|
+
const col = columnFor(target.columnId);
|
|
13748
|
+
if (!col) return null;
|
|
13749
|
+
const args = {
|
|
13750
|
+
columnId: target.columnId,
|
|
13751
|
+
columnLabel: labelFor(col, target.columnId),
|
|
13752
|
+
values: paginated.map(
|
|
13753
|
+
(row) => getCellValue(applyRowEdits(row, edits[getRowId(row)]), col)
|
|
13754
|
+
)
|
|
13755
|
+
};
|
|
13756
|
+
return contextMenu?.resolveColumnContext?.(args) ?? fromHost({ level: "column", ...args });
|
|
13757
|
+
}
|
|
13758
|
+
case "selection": {
|
|
13759
|
+
const addresses = sheetRef.current.selectionAddresses();
|
|
13760
|
+
const cellCount = addresses.rowIds.length * addresses.columnIds.length;
|
|
13761
|
+
if (cellCount <= 1) {
|
|
13762
|
+
return resolveMenuLevel({ ...target, level: "cell" });
|
|
13763
|
+
}
|
|
13764
|
+
const args = { ...addresses, tsv: sheetRef.current.selectionTsv(), cellCount };
|
|
13765
|
+
return contextMenu?.resolveSelectionContext?.(args) ?? fromHost({ level: "selection", ...args });
|
|
13766
|
+
}
|
|
13767
|
+
case "table": {
|
|
13768
|
+
const args = { rowCount: data.length, columnIds: visibleColumns.map((col) => columnId(col)) };
|
|
13769
|
+
return contextMenu?.resolveTableContext?.(args) ?? fromHost({ level: "table", ...args });
|
|
13770
|
+
}
|
|
13771
|
+
}
|
|
13772
|
+
};
|
|
13773
|
+
const resolveMenuLevelRef = (0, import_react21.useRef)(resolveMenuLevel);
|
|
13774
|
+
resolveMenuLevelRef.current = resolveMenuLevel;
|
|
13775
|
+
(0, import_react21.useEffect)(() => {
|
|
13776
|
+
if (!host.rowContextRegistry) return;
|
|
13777
|
+
return host.rowContextRegistry.register(
|
|
13778
|
+
tableContextMenuInstanceId,
|
|
13779
|
+
(target) => resolveMenuLevelRef.current(target)
|
|
13780
|
+
);
|
|
13781
|
+
}, [host.rowContextRegistry, tableContextMenuInstanceId]);
|
|
13034
13782
|
const showActionsCol = windowEnabled || Boolean(rowActions) || showInlineRowCopy;
|
|
13035
13783
|
const selectedIdSet = (0, import_react21.useMemo)(
|
|
13036
13784
|
() => new Set(selection?.selectedIds ?? []),
|
|
@@ -13112,8 +13860,19 @@ function MatrxDataTableCore({
|
|
|
13112
13860
|
dirty: Boolean(rowEdits && field in rowEdits),
|
|
13113
13861
|
onCommit: (next) => commitCell(id, field, next),
|
|
13114
13862
|
...href === void 0 ? {} : { href },
|
|
13115
|
-
...
|
|
13116
|
-
|
|
13863
|
+
...spreadsheetEnabled ? {
|
|
13864
|
+
// 🚨 THE CLICK LAW, enforced where the two paths meet. In a grid
|
|
13865
|
+
// with spreadsheet gestures a single click SELECTS a cell — it
|
|
13866
|
+
// may never drop a person into a free-text buffer, because the
|
|
13867
|
+
// same click is how they start a range, and an editor that opens
|
|
13868
|
+
// under the pointer eats the drag and the next keystroke. So the
|
|
13869
|
+
// editor opens the way it does in Excel: Enter, F2, the hover
|
|
13870
|
+
// pencil, or simply typing. An explicit `editTrigger: "click"`
|
|
13871
|
+
// does not override this; the law is the table's, not the
|
|
13872
|
+
// column's.
|
|
13873
|
+
editTrigger: "pencil"
|
|
13874
|
+
} : col.editTrigger === void 0 ? {} : { editTrigger: col.editTrigger },
|
|
13875
|
+
...editRequest?.rowId === id && editRequest.field === field ? { editRequest: editRequest.nonce, editSeed: editRequest.seed } : {}
|
|
13117
13876
|
}
|
|
13118
13877
|
);
|
|
13119
13878
|
}
|
|
@@ -13871,6 +14630,7 @@ function MatrxDataTableCore({
|
|
|
13871
14630
|
"th",
|
|
13872
14631
|
{
|
|
13873
14632
|
"data-matrx-table-column-id": id,
|
|
14633
|
+
"data-matrx-header-column-id": id,
|
|
13874
14634
|
"data-matrx-column-drag-shadow": isColumnDragShadow ? "true" : void 0,
|
|
13875
14635
|
"aria-sort": isSorted ? sort?.direction === "asc" ? "ascending" : "descending" : void 0,
|
|
13876
14636
|
className: cn(
|
|
@@ -13907,6 +14667,12 @@ function MatrxDataTableCore({
|
|
|
13907
14667
|
{
|
|
13908
14668
|
label: col.header,
|
|
13909
14669
|
labelText: headerLabel,
|
|
14670
|
+
...facetsEnabled ? {
|
|
14671
|
+
facets: facetState[id]?.data ?? null,
|
|
14672
|
+
facetsLoading: facetState[id]?.loading ?? false,
|
|
14673
|
+
...facetState[id]?.error === void 0 ? {} : { facetsError: facetState[id]?.error },
|
|
14674
|
+
onFilterOpen: () => requestFacets(id)
|
|
14675
|
+
} : {},
|
|
13910
14676
|
sortable: col.sortable !== false,
|
|
13911
14677
|
isSorted: Boolean(isSorted),
|
|
13912
14678
|
sortDirection: sort?.direction ?? defaultSortDirection,
|
|
@@ -14233,7 +14999,7 @@ function MatrxDataTableCore({
|
|
|
14233
14999
|
"div",
|
|
14234
15000
|
{
|
|
14235
15001
|
"data-matrx-cell-content": true,
|
|
14236
|
-
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]",
|
|
15002
|
+
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] [&_[data-matrx-cell-fill]]:!w-full [&_[data-matrx-cell-fill]]:!min-w-0 [&_[data-matrx-cell-fill]]:!max-w-full sm:[&_[data-matrx-cell-fill]]:!w-full sm:[&_[data-matrx-cell-fill]]:!min-w-0 sm:[&_[data-matrx-cell-fill]]:!max-w-full",
|
|
14237
15003
|
children: renderRecordCell(row, col, index)
|
|
14238
15004
|
}
|
|
14239
15005
|
)
|
|
@@ -14581,8 +15347,8 @@ function MatrxDataTableCore({
|
|
|
14581
15347
|
itemsPerPage: pageSize === 0 && allRowsAreLoaded ? 0 : effectivePageSize,
|
|
14582
15348
|
currentPage: safePage,
|
|
14583
15349
|
onPageChange: setPage,
|
|
14584
|
-
onItemsPerPageChange: (
|
|
14585
|
-
setPageSize(
|
|
15350
|
+
onItemsPerPageChange: (n2) => {
|
|
15351
|
+
setPageSize(n2);
|
|
14586
15352
|
if (!controlledQuery) setPage(1);
|
|
14587
15353
|
},
|
|
14588
15354
|
pageSizeOptions: pageSizeOptions.filter((size) => size > 0),
|