@ai-matrx/records-ui 0.110.4 → 0.110.6

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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog — @ai-matrx/records-ui
2
2
 
3
+ ## 0.110.6
4
+
5
+ Automatic changed-only republish (docs/metadata drift since the last tag — see
6
+ `git diff npm/records-ui/v0.110.5..npm/records-ui/v0.110.6 -- apps/shared/records-ui`).
7
+ No source changes intended and no consumer action required.
8
+
9
+ ## 0.110.5
10
+
11
+ Automatic changed-only republish (docs/metadata drift since the last tag — see
12
+ `git diff npm/records-ui/v0.110.4..npm/records-ui/v0.110.5 -- apps/shared/records-ui`).
13
+ No source changes intended and no consumer action required.
14
+
3
15
  ## 0.110.4
4
16
  ### lane PERF-REVIEW-FIX
5
17
 
@@ -1,15 +1,24 @@
1
1
  'use strict';
2
2
 
3
3
  var core = require('@ai-matrx/records/core');
4
+ var uuid = require('@ai-matrx/kit/uuid');
5
+ var textCase = require('@ai-matrx/kit/text-case');
4
6
  var records = require('@ai-matrx/records');
5
- require('@ai-matrx/kit/text-case');
6
- require('@ai-matrx/design-system/data-table');
7
+ var dataTable = require('@ai-matrx/design-system/data-table');
8
+ require('react');
7
9
  var tableStyle = require('@ai-matrx/design-system/data-table/table-style');
8
10
  require('@ai-matrx/design-system/field-formats');
9
- var uuid = require('@ai-matrx/kit/uuid');
10
11
  var realtime = require('@ai-matrx/realtime');
11
12
 
12
13
  // src/firstPage.ts
14
+ function fieldName(field2) {
15
+ const label = (field2.label ?? "").trim();
16
+ if (label !== "" && label === field2.key && /^[a-z0-9]+(?:[_.-][a-z0-9]+)+$/.test(label)) return textCase.humanizeIdentifier(label);
17
+ if (label !== "") return label;
18
+ const name = (field2.name ?? "").trim();
19
+ if (name !== "") return name;
20
+ return textCase.humanizeIdentifier(field2.key);
21
+ }
13
22
  var kernelId = (name) => records.KERNEL_TABLES.find((t) => t.name === name)?.id ?? "";
14
23
  var KERNEL_FILE_TABLE = kernelId("File");
15
24
  var KERNEL_PERSON_TABLE = kernelId("Person");
@@ -17,8 +26,8 @@ Object.fromEntries(
17
26
  records.PARITY_FIELD_TYPES.map((p) => [p.parity_type, p.made_of])
18
27
  );
19
28
  var KERNEL = { file: KERNEL_FILE_TABLE, person: KERNEL_PERSON_TABLE };
20
- function editorKindFor(field) {
21
- return records.fieldKindFor(field, KERNEL);
29
+ function editorKindFor(field2) {
30
+ return records.fieldKindFor(field2, KERNEL);
22
31
  }
23
32
 
24
33
  // src/gridLook.ts
@@ -45,25 +54,212 @@ function defaultSortOf(table, fields) {
45
54
  if (String(entry["direction"] ?? "").toLowerCase() === "desc") direction = "desc";
46
55
  }
47
56
  if (!name) return null;
48
- const field = fields.find((f) => f.key === name) ?? fields.find((f) => f.id === name);
49
- return field ? { id: field.key, direction } : null;
57
+ const field2 = fields.find((f) => f.key === name) ?? fields.find((f) => f.id === name);
58
+ return field2 ? { id: field2.key, direction } : null;
59
+ }
60
+ var MEASURE_LABEL = {
61
+ count: "Count",
62
+ sum: "Sum",
63
+ avg: "Average",
64
+ min: "Smallest",
65
+ max: "Largest",
66
+ median: "Median",
67
+ filled: "Filled",
68
+ empty: "Empty",
69
+ unique: "Unique",
70
+ percent_empty: "Percent empty",
71
+ percent_filled: "Percent filled",
72
+ range: "Range"
73
+ };
74
+
75
+ // src/gridPage.ts
76
+ function filterRefusal(f) {
77
+ if (!computedOnRead(f)) return null;
78
+ return `${fieldName(f)} is worked out each time it is read, so the store keeps no value to filter the whole table by. Filter by a column it is worked out from.`;
79
+ }
80
+ function computedOnRead(f) {
81
+ const kind = String(editorKindFor(f));
82
+ return (f.type === "formula" || kind === "formula" || kind === "lookup" || kind === "rollup") && String(f.compute_on ?? "read") === "read";
50
83
  }
51
- function holdsNumbers(field) {
52
- const kind = String(editorKindFor(field));
84
+ function holdsNumbers(field2) {
85
+ const kind = String(editorKindFor(field2));
53
86
  if (kind === "number" || kind === "currency" || kind === "percent") return true;
54
- return String((field.config ?? {})["system"] ?? "") === "autonumber";
87
+ return String((field2.config ?? {})["system"] ?? "") === "autonumber";
55
88
  }
56
- function sortAsFor(field) {
57
- const kind = String(editorKindFor(field));
58
- if (holdsNumbers(field)) return "number";
89
+ function sortAsFor(field2) {
90
+ const kind = String(editorKindFor(field2));
91
+ if (holdsNumbers(field2)) return "number";
59
92
  if (kind === "datetime") return "date";
60
93
  return "text";
61
94
  }
62
95
  function pageSortFor(fields, sort) {
63
96
  if (!sort) return [];
64
- const field = fields.find((f) => f.key === sort.id);
65
- if (!field) return [];
66
- return [{ field: field.key, direction: sort.direction === "desc" ? "desc" : "asc", as: sortAsFor(field) }];
97
+ const field2 = fields.find((f) => f.key === sort.id);
98
+ if (!field2) return [];
99
+ return [{ field: field2.key, direction: sort.direction === "desc" ? "desc" : "asc", as: sortAsFor(field2) }];
100
+ }
101
+ function containsPattern(text) {
102
+ return `(?i)${text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`;
103
+ }
104
+ var BLANK_VALUE = "__empty__";
105
+ var field = (f) => ({ field: f.id });
106
+ var constant = (value) => ({ const: value });
107
+ var withinWindow = (f, window) => ({ op: "within", args: [field(f), constant(window)] });
108
+ var op = (name, ...args) => ({ op: name, args });
109
+ function clauseFor(f, value, now = /* @__PURE__ */ new Date()) {
110
+ const name = fieldName(f);
111
+ const refused = filterRefusal(f);
112
+ if (refused) return refused;
113
+ const not = (rule) => op("not", rule);
114
+ switch (value.kind) {
115
+ case "text": {
116
+ const mode = value.mode ?? "contains";
117
+ if (mode === "empty" || mode === "null") return value.negated ? { rule: op("present", field(f)) } : { rule: not(op("present", field(f))) };
118
+ if (mode === "not_empty" || mode === "not_null") return value.negated ? { rule: not(op("present", field(f))) } : { rule: op("present", field(f)) };
119
+ const text = value.value.trim();
120
+ if (text === "") return null;
121
+ const kind = String(editorKindFor(f));
122
+ if (kind === "number" || kind === "currency" || kind === "percent" || kind === "checkbox") {
123
+ return `${name} holds numbers, so it is filtered by a range, not by words.`;
124
+ }
125
+ const matches = op("matches", field(f), constant(containsPattern(text)));
126
+ return { rule: value.negated ? not(matches) : matches };
127
+ }
128
+ case "select": {
129
+ const ticked = value.values ?? (value.value === "" ? [] : [value.value]);
130
+ const blank = ticked.includes(BLANK_VALUE);
131
+ const words = ticked.filter((w) => w !== BLANK_VALUE);
132
+ if (!blank && words.length === 0) return value.negated ? null : { rule: constant(false) };
133
+ const present = op("present", field(f));
134
+ const kind = String(editorKindFor(f));
135
+ if (kind === "datetime" || kind === "date") {
136
+ if (words.length === 0) return { rule: value.negated ? present : not(present) };
137
+ const holdsDays = String((f.config ?? {})["kind"] ?? "") === "date";
138
+ if (words.length === 1 && !blank && !value.negated) return { flat: { [f.key]: dayWindow(words[0], holdsDays) } };
139
+ const leaves = words.map((day) => withinWindow(f, dayWindow(day, holdsDays)));
140
+ const anyDay = leaves.length === 1 ? leaves[0] : op("or", ...leaves);
141
+ if (!value.negated) return { rule: blank ? op("or", not(present), anyDay) : anyDay };
142
+ return { rule: blank ? op("and", present, not(anyDay)) : not(anyDay) };
143
+ }
144
+ const asStored = (w) => holdsNumbers(f) || kind === "rating" ? Number.isFinite(Number(w)) ? Number(w) : w : kind === "checkbox" && (w === "true" || w === "false") ? w === "true" : w;
145
+ const stored = words.map(asStored);
146
+ const anyWord = stored.length === 0 ? null : stored.length === 1 ? op("eq", field(f), constant(stored[0])) : op("or", ...stored.map((w) => op("eq", field(f), constant(w))));
147
+ if (!value.negated) {
148
+ if (!blank && stored.length === 1) return { flat: { [f.key]: stored[0] } };
149
+ if (!blank) return { rule: anyWord };
150
+ return { rule: anyWord ? op("or", not(present), anyWord) : not(present) };
151
+ }
152
+ if (blank) return { rule: anyWord ? op("and", present, not(anyWord)) : present };
153
+ return { rule: op("or", not(present), not(anyWord)) };
154
+ }
155
+ case "boolean":
156
+ return value.negated ? { rule: op("ne", field(f), constant(value.value)) } : { flat: { [f.key]: value.value } };
157
+ case "number": {
158
+ const turned = (rule) => ({ rule: value.negated ? not(rule) : rule });
159
+ if (value.op === "empty") return turned(not(op("present", field(f))));
160
+ if (value.op === "not_empty") return turned(op("present", field(f)));
161
+ if (value.op === "eq" || value.op === "ne") {
162
+ if (typeof value.min !== "number") return null;
163
+ return turned(op(value.op, field(f), constant(value.min)));
164
+ }
165
+ if (value.op === "lt") return typeof value.max === "number" ? turned(op("lt", field(f), constant(value.max))) : null;
166
+ if (value.op === "gt") return typeof value.min === "number" ? turned(op("gt", field(f), constant(value.min))) : null;
167
+ const parts = [];
168
+ if (typeof value.min === "number") parts.push(op("gte", field(f), constant(value.min)));
169
+ if (typeof value.max === "number") parts.push(op("lte", field(f), constant(value.max)));
170
+ if (parts.length === 0) return null;
171
+ const range = parts.length === 1 ? parts[0] : op("and", ...parts);
172
+ return { rule: value.negated ? not(range) : range };
173
+ }
174
+ case "date": {
175
+ const zone2 = void 0;
176
+ const moments = dataTable.dateFilterBounds(value.preset ? { ...value, anchor: now.toISOString() } : value, now, zone2);
177
+ const holdsDays = String((f.config ?? {})["kind"] ?? "") === "date";
178
+ const bounds = holdsDays ? dataTable.dateFilterDayBounds(moments, zone2) : moments;
179
+ if (bounds.since === void 0 && bounds.until === void 0) return null;
180
+ return {
181
+ flat: {
182
+ [f.key]: {
183
+ ...bounds.since === void 0 ? {} : { from: bounds.since },
184
+ ...bounds.until === void 0 ? {} : { to: bounds.until }
185
+ }
186
+ }
187
+ };
188
+ }
189
+ default:
190
+ return `${name} cannot be filtered that way by the store.`;
191
+ }
192
+ }
193
+ function dayWindow(day, holdsDays) {
194
+ if (!holdsDays) return dataTable.dayInstantWindow(day, void 0);
195
+ const [y, m, d] = day.split("-").map(Number);
196
+ const ymd = (t) => `${t.getUTCFullYear()}-${String(t.getUTCMonth() + 1).padStart(2, "0")}-${String(t.getUTCDate()).padStart(2, "0")}`;
197
+ return { from: ymd(new Date(Date.UTC(y, (m ?? 1) - 1, d ?? 1))), to: ymd(new Date(Date.UTC(y, (m ?? 1) - 1, (d ?? 1) + 1))) };
198
+ }
199
+ function storeQuestion(fields, base, columnFilters, now = /* @__PURE__ */ new Date()) {
200
+ const refused = [];
201
+ const flat = {};
202
+ const rules = [];
203
+ if (base && records.isRuleFilter(base)) rules.push(base);
204
+ else if (base) Object.assign(flat, base);
205
+ for (const [key, value] of Object.entries(columnFilters)) {
206
+ if (!value) continue;
207
+ const f = fields.find((candidate) => candidate.key === key);
208
+ if (!f) continue;
209
+ const clause = clauseFor(f, value, now);
210
+ if (clause === null) continue;
211
+ if (typeof clause === "string") {
212
+ refused.push(clause);
213
+ continue;
214
+ }
215
+ if ("flat" in clause) Object.assign(flat, clause.flat);
216
+ else rules.push(clause.rule);
217
+ }
218
+ const flatKeys = Object.keys(flat);
219
+ if (rules.length === 0) return { filter: flatKeys.length > 0 ? flat : void 0, refused };
220
+ for (const key of flatKeys) {
221
+ const f = fields.find((candidate) => candidate.key === key);
222
+ const value = flat[key];
223
+ if (!f) continue;
224
+ if (value !== null && typeof value === "object") {
225
+ rules.push(withinWindow(f, value));
226
+ continue;
227
+ }
228
+ rules.push(value === null ? op("not", op("present", field(f))) : op("eq", field(f), constant(value)));
229
+ }
230
+ return { filter: rules.length === 1 ? rules[0] : op("and", ...rules), refused };
231
+ }
232
+
233
+ // src/rowVersion.ts
234
+ function ownVersion(row) {
235
+ const v = row.version;
236
+ return typeof v === "number" ? v : null;
237
+ }
238
+
239
+ // src/groupReads.ts
240
+ function isPlainGrouping(grouping) {
241
+ return Boolean(grouping) && !(grouping.then && grouping.then.length > 0) && !grouping.across && !(grouping.trail && grouping.trail.length > 0);
242
+ }
243
+ function groupedPageSort(fields, groupKey, sort) {
244
+ if (!groupKey) return sort;
245
+ const field2 = fields.find((f) => f.key === groupKey);
246
+ if (!field2) return sort;
247
+ return [{ field: groupKey, direction: "asc", as: sortAsFor(field2) }, ...sort.filter((s) => s.field !== groupKey)];
248
+ }
249
+ function chosenEntries(chosen) {
250
+ return JSON.parse(JSON.stringify(Object.entries(chosen).sort())).filter(([, op2]) => op2 in MEASURE_LABEL);
251
+ }
252
+ function groupFactMeasures(chosen) {
253
+ return [{ op: "count" }, ...chosenEntries(chosen).filter(([, op2]) => op2 !== "count").map(([key, op2]) => ({ op: op2, key }))];
254
+ }
255
+ function summaryBarMeasures(chosen) {
256
+ return chosenEntries(chosen).map(([key, op2]) => op2 === "count" ? { op: "count" } : { op: op2, key });
257
+ }
258
+ function choiceFieldKeys(fields) {
259
+ return fields.filter((f) => {
260
+ const kind = String(editorKindFor(f));
261
+ return kind === "select" || kind === "multi_select";
262
+ }).map((f) => f.key);
67
263
  }
68
264
  var MIN_ROW_HEIGHT = 24;
69
265
  var MAX_ROW_HEIGHT = 96;
@@ -163,8 +359,8 @@ function parseGridPresentation(raw) {
163
359
  if (footer === "sticky" || footer === "inline") out.footer = footer;
164
360
  if (isRecord(value["summaries"])) {
165
361
  const summaries = {};
166
- for (const [key, op] of Object.entries(value["summaries"])) {
167
- if (typeof op === "string" && op.trim() !== "") summaries[key] = op;
362
+ for (const [key, op2] of Object.entries(value["summaries"])) {
363
+ if (typeof op2 === "string" && op2.trim() !== "") summaries[key] = op2;
168
364
  }
169
365
  if (Object.keys(summaries).length > 0) out.summaries = summaries;
170
366
  }
@@ -172,9 +368,9 @@ function parseGridPresentation(raw) {
172
368
  }
173
369
  function parseGrouping(raw) {
174
370
  if (!isRecord(raw)) return void 0;
175
- const field = raw["field"];
176
- if (typeof field !== "string" || field.trim() === "") return void 0;
177
- const out = { field };
371
+ const field2 = raw["field"];
372
+ if (typeof field2 !== "string" || field2.trim() === "") return void 0;
373
+ const out = { field: field2 };
178
374
  if (isRecord(raw["aggregates"])) {
179
375
  const aggregates = {};
180
376
  for (const [key, spec] of Object.entries(raw["aggregates"])) {
@@ -954,39 +1150,68 @@ async function askTileSeed(input) {
954
1150
  // src/firstPage.ts
955
1151
  var TABLE_PAGE_SIZE = 100;
956
1152
  var EMBEDDED_PAGE_SIZE = 50;
1153
+ function viewFilterOf(shown, fields) {
1154
+ if (!shown) return void 0;
1155
+ const base = shown.where ?? (shown.filters && Object.keys(shown.filters).length > 0 ? shown.filters : void 0);
1156
+ return storeQuestion(fields, base, {}).filter;
1157
+ }
957
1158
  function firstGridPageArgs(input) {
958
1159
  const { shown, fields } = input;
959
1160
  if (!shown) return null;
960
1161
  if ((shown.layout ?? "grid") !== "grid") return null;
961
1162
  if (shown.ruleId) return null;
962
1163
  if (shown.order === "manual") return null;
963
- if (shown.filters && Object.keys(shown.filters).length > 0) return null;
964
- if (shown.presentation?.grouping) return null;
1164
+ const grouping = shown.presentation?.grouping;
1165
+ if (grouping && !(input.merged && isPlainGrouping(grouping))) return null;
965
1166
  const first = (shown.sorts ?? [])[0];
966
1167
  const viewSort = first && fields.some((f) => f.key === first.field) ? { id: first.field, direction: first.direction } : null;
967
1168
  const opening = viewSort ?? defaultSortOf(input.table, fields);
968
1169
  return {
969
1170
  p_table_id: input.tableId,
970
- p_filter: {},
1171
+ p_filter: viewFilterOf(shown, fields) ?? {},
971
1172
  p_search: null,
972
- p_sort: pageSortFor(fields, opening),
1173
+ p_sort: groupedPageSort(fields, grouping?.field ?? null, pageSortFor(fields, opening)),
973
1174
  p_view_id: null,
974
1175
  p_limit: input.pageSize ?? TABLE_PAGE_SIZE,
975
1176
  p_offset: 0
976
1177
  };
977
1178
  }
978
1179
  async function firstGridPageRequest(client, tableId, options = {}) {
1180
+ return (await firstGridOpening(client, tableId, options))?.args ?? null;
1181
+ }
1182
+ function defaultSpec(tableId) {
1183
+ return { name: "All", subject: tableId, layout: "grid", isDefault: true };
1184
+ }
1185
+ function shownFromSpec(spec, tableId) {
1186
+ return { ...spec, subject: spec.subject ?? tableId, id: "", movedFrom: null };
1187
+ }
1188
+ async function firstGridOpening(client, tableId, options) {
1189
+ const explicit = options.view;
979
1190
  const [table, fields, views, looks] = await Promise.all([
980
1191
  client.tableRead({ table_id: tableId }),
981
1192
  client.fields({ table_id: tableId }),
982
- client.views({ table_id: tableId }),
983
- readLooks(client, tableId)
1193
+ explicit ? Promise.resolve(null) : client.views({ table_id: tableId }),
1194
+ explicit ? Promise.resolve(null) : readLooks(client, tableId)
984
1195
  ]);
985
- if (!table.ok || !fields.ok || !views.ok || !looks.ok) return null;
986
- const mine = views.data.map(viewFromRow).filter((v) => v.subject === tableId);
987
- const view = defaultViewOf(mine) ?? mine[0] ?? null;
988
- const shown = view ? applyLook(view, looks.data[view.id]) : null;
989
- return firstGridPageArgs({ tableId, table: table.data, fields: fields.data, shown, ...options.pageSize ? { pageSize: options.pageSize } : {} });
1196
+ if (!table.ok || !fields.ok) return null;
1197
+ let shown;
1198
+ if (explicit) {
1199
+ shown = shownFromSpec(explicit, tableId);
1200
+ } else {
1201
+ if (!views?.ok || !looks?.ok) return null;
1202
+ const mine = views.data.map(viewFromRow).filter((v) => v.subject === tableId);
1203
+ const view = defaultViewOf(mine) ?? mine[0] ?? null;
1204
+ shown = view ? applyLook(view, looks.data[view.id]) : shownFromSpec(defaultSpec(tableId), tableId);
1205
+ }
1206
+ const args = firstGridPageArgs({
1207
+ tableId,
1208
+ table: table.data,
1209
+ fields: fields.data,
1210
+ shown,
1211
+ ...options.pageSize ? { pageSize: options.pageSize } : {},
1212
+ ...options.merged ? { merged: true } : {}
1213
+ });
1214
+ return args ? { args, shown, fields: fields.data } : null;
990
1215
  }
991
1216
  function serverRowsOf(seed) {
992
1217
  const found = seed?.answers.find((a) => a.door === "server_rows");
@@ -1008,10 +1233,11 @@ async function askTablePageSeed(input) {
1008
1233
  ).catch(() => null) : null;
1009
1234
  try {
1010
1235
  const pageSize = input.pageSize ?? (input.embedded ? EMBEDDED_PAGE_SIZE : TABLE_PAGE_SIZE);
1011
- const args = await firstGridPageRequest(client, input.tableId, { pageSize });
1236
+ const opening = await firstGridOpening(client, input.tableId, { pageSize, ...input.merged ? { merged: true } : {}, ...input.view ? { view: input.view } : {} });
1012
1237
  const wantRows = typeof input.rows === "function" ? input.rows(recording.seed()) : input.rows !== false;
1013
- if (args && wantRows) {
1014
- await client.listPage({
1238
+ if (opening && wantRows) {
1239
+ const { args, shown, fields } = opening;
1240
+ const page = await client.listPage({
1015
1241
  table_id: args.p_table_id,
1016
1242
  filter: args.p_filter,
1017
1243
  search: args.p_search,
@@ -1020,6 +1246,34 @@ async function askTablePageSeed(input) {
1020
1246
  limit: args.p_limit,
1021
1247
  offset: args.p_offset
1022
1248
  });
1249
+ if (page.ok) {
1250
+ const chosen = shown?.presentation?.summaries ?? {};
1251
+ const groupKey = shown?.presentation?.grouping?.field ?? null;
1252
+ const reads = [];
1253
+ const filter = args.p_filter && Object.keys(args.p_filter).length > 0 ? args.p_filter : void 0;
1254
+ if (groupKey) {
1255
+ reads.push(client.recordAggregate({ table_id: input.tableId, groupBy: [groupKey], measures: groupFactMeasures(chosen), limit: 1e3, ...filter ? { filter } : {} }));
1256
+ }
1257
+ const bar = summaryBarMeasures(chosen);
1258
+ if (bar.length > 0) reads.push(client.recordAggregate({ table_id: input.tableId, measures: bar, ...filter ? { filter } : {} }));
1259
+ for (const field2 of fields) {
1260
+ if (field2.type !== "list" && field2.type !== "relation") continue;
1261
+ const ids = /* @__PURE__ */ new Set();
1262
+ for (const row of page.data.rows) {
1263
+ const value = row.document?.[field2.key];
1264
+ for (const id of Array.isArray(value) ? value.map(String) : typeof value === "string" ? [value] : []) if (uuid.isUuidShape(id)) ids.add(id);
1265
+ }
1266
+ if (ids.size > 0) reads.push(client.relationWordsMany({ field_id: field2.id, record_ids: [...ids] }));
1267
+ }
1268
+ if (input.merged) {
1269
+ for (const key of choiceFieldKeys(fields)) {
1270
+ reads.push(client.recordAggregate({ table_id: input.tableId, groupBy: [key], measures: [{ op: "count" }], limit: 500, ...filter ? { filter } : {} }));
1271
+ }
1272
+ }
1273
+ const unversioned = page.data.rows.filter((row) => ownVersion(row) === null).map((row) => row.id);
1274
+ if (unversioned.length > 0) reads.push(client.recordHeaders({ ids: unversioned }));
1275
+ await Promise.all(reads.map((read) => read.catch(() => null)));
1276
+ }
1023
1277
  }
1024
1278
  } catch {
1025
1279
  }
@@ -1037,5 +1291,6 @@ exports.firstGridPageArgs = firstGridPageArgs;
1037
1291
  exports.firstGridPageRequest = firstGridPageRequest;
1038
1292
  exports.mergeSeeds = mergeSeeds;
1039
1293
  exports.serverRowsOf = serverRowsOf;
1294
+ exports.viewFilterOf = viewFilterOf;
1040
1295
  //# sourceMappingURL=first-page.cjs.map
1041
1296
  //# sourceMappingURL=first-page.cjs.map