@ai-matrx/records-ui 0.107.5 → 0.108.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 CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog — @ai-matrx/records-ui
2
2
 
3
+ ## 0.108.0
4
+ ### PAGE-BUNDLE-2: the grid's first page, asked before the grid exists
5
+
6
+ NEW ENTRY `@ai-matrx/records-ui/first-page` (server-safe, no React): `firstGridPageRequest(client, tableId)` and the pure `firstGridPageArgs({ tableId, table, fields, shown })` build the EXACT `custom.read_records_page` arguments the table page's grid sends on open (the bar's default view with the person's look over it, the view's sort else the table's `default_sort`, page size 100). Null for a grouped, drilled, filtered, hand-ordered, Rule or non-grid view. A test renders the grid and holds the two byte-equal.
7
+
8
+ **Consumer action:** none (additive). A server-rendered host seeds the first page by door name + these arguments.
9
+
3
10
  ## 0.107.5
4
11
 
5
12
  TYPEFORM-2: no keystroke is lost while the store works out a branching form's route. Keys typed after Enter are held and land in the next question (appended to a text answer, replayed as keys on a choice so a letter picks). Walk: type straight on after Enter.
@@ -0,0 +1,487 @@
1
+ "use client";
2
+ "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/firstPage.ts
22
+ var firstPage_exports = {};
23
+ __export(firstPage_exports, {
24
+ TABLE_PAGE_SIZE: () => TABLE_PAGE_SIZE,
25
+ firstGridPageArgs: () => firstGridPageArgs,
26
+ firstGridPageRequest: () => firstGridPageRequest
27
+ });
28
+ module.exports = __toCommonJS(firstPage_exports);
29
+
30
+ // src/parity.ts
31
+ var import_records = require("@ai-matrx/records");
32
+ var import_text_case = require("@ai-matrx/kit/text-case");
33
+ var kernelId = (name) => import_records.KERNEL_TABLES.find((t) => t.name === name)?.id ?? "";
34
+ var KERNEL_FILE_TABLE = kernelId("File");
35
+ var KERNEL_PERSON_TABLE = kernelId("Person");
36
+ var PARITY_MADE_OF = Object.fromEntries(
37
+ import_records.PARITY_FIELD_TYPES.map((p) => [p.parity_type, p.made_of])
38
+ );
39
+ var KERNEL = { file: KERNEL_FILE_TABLE, person: KERNEL_PERSON_TABLE };
40
+ function editorKindFor(field) {
41
+ return (0, import_records.fieldKindFor)(field, KERNEL);
42
+ }
43
+
44
+ // src/gridLook.ts
45
+ function defaultSortOf(table, fields) {
46
+ const raw = table?.default_sort ?? null;
47
+ const first = Array.isArray(raw) ? raw[0] : raw;
48
+ let name = null;
49
+ let direction = "asc";
50
+ if (typeof first === "string") {
51
+ const trimmed = first.trim();
52
+ if (trimmed === "") return null;
53
+ if (trimmed.startsWith("-")) {
54
+ name = trimmed.slice(1).trim();
55
+ direction = "desc";
56
+ } else {
57
+ const [head, tail] = trimmed.split(/\s+/);
58
+ name = head ?? null;
59
+ if (tail && tail.toLowerCase() === "desc") direction = "desc";
60
+ }
61
+ } else if (first && typeof first === "object") {
62
+ const entry = first;
63
+ const named = entry["field"] ?? entry["key"] ?? entry["id"];
64
+ name = typeof named === "string" ? named : null;
65
+ if (String(entry["direction"] ?? "").toLowerCase() === "desc") direction = "desc";
66
+ }
67
+ if (!name) return null;
68
+ const field = fields.find((f) => f.key === name) ?? fields.find((f) => f.id === name);
69
+ return field ? { id: field.key, direction } : null;
70
+ }
71
+
72
+ // src/gridPage.ts
73
+ var import_records2 = require("@ai-matrx/records");
74
+ var import_data_table = require("@ai-matrx/design-system/data-table");
75
+ function holdsNumbers(field) {
76
+ const kind = String(editorKindFor(field));
77
+ if (kind === "number" || kind === "currency" || kind === "percent") return true;
78
+ return String((field.config ?? {})["system"] ?? "") === "autonumber";
79
+ }
80
+ function sortAsFor(field) {
81
+ const kind = String(editorKindFor(field));
82
+ if (holdsNumbers(field)) return "number";
83
+ if (kind === "datetime") return "date";
84
+ return "text";
85
+ }
86
+ function pageSortFor(fields, sort) {
87
+ if (!sort) return [];
88
+ const field = fields.find((f) => f.key === sort.id);
89
+ if (!field) return [];
90
+ return [{ field: field.key, direction: sort.direction === "desc" ? "desc" : "asc", as: sortAsFor(field) }];
91
+ }
92
+
93
+ // src/presentation.ts
94
+ var import_data_table2 = require("@ai-matrx/design-system/data-table");
95
+ var import_field_formats = require("@ai-matrx/design-system/field-formats");
96
+ var import_records3 = require("@ai-matrx/records");
97
+ var MIN_ROW_HEIGHT = 24;
98
+ var MAX_ROW_HEIGHT = 96;
99
+ var AGGREGATE_KINDS = [
100
+ "count",
101
+ "sum",
102
+ "average",
103
+ "min",
104
+ "max",
105
+ "empty",
106
+ "filled",
107
+ "unique",
108
+ "checked",
109
+ "unchecked",
110
+ "percentFilled"
111
+ ];
112
+ var GROUP_ORDERS = [
113
+ "value-asc",
114
+ "value-desc",
115
+ "count-desc",
116
+ "first-seen"
117
+ ];
118
+ function isRecord(v) {
119
+ return typeof v === "object" && v !== null && !Array.isArray(v);
120
+ }
121
+ function parseGridPresentation(raw) {
122
+ let value = raw;
123
+ if (typeof value === "string") {
124
+ const trimmed = value.trim();
125
+ if (trimmed === "") return {};
126
+ try {
127
+ value = JSON.parse(trimmed);
128
+ } catch {
129
+ return {};
130
+ }
131
+ }
132
+ if (!isRecord(value)) return {};
133
+ const out = {};
134
+ const style = (0, import_data_table2.parseTableStyle)(value["style"]);
135
+ if (!(0, import_data_table2.tableStyleIsEmpty)(style)) out.style = style;
136
+ if (isRecord(value["formats"])) {
137
+ const formats = {};
138
+ for (const [key, cfg] of Object.entries(value["formats"])) {
139
+ if (!isRecord(cfg)) continue;
140
+ const id = cfg["id"];
141
+ if (typeof id !== "string") continue;
142
+ const options = cfg["options"];
143
+ formats[key] = isRecord(options) ? {
144
+ id,
145
+ options
146
+ } : { id };
147
+ }
148
+ if (Object.keys(formats).length > 0) out.formats = formats;
149
+ }
150
+ if (Array.isArray(value["frozen"])) {
151
+ const frozen = value["frozen"].filter((k) => typeof k === "string");
152
+ if (frozen.length > 0) out.frozen = frozen;
153
+ }
154
+ const grouping = parseGrouping(value["grouping"]);
155
+ if (grouping) out.grouping = grouping;
156
+ if (isRecord(value["widths"])) {
157
+ const widths = {};
158
+ for (const [key, raw2] of Object.entries(value["widths"])) {
159
+ if (typeof raw2 !== "number" || !Number.isFinite(raw2) || raw2 <= 0) continue;
160
+ widths[key] = Math.round(raw2);
161
+ }
162
+ if (Object.keys(widths).length > 0) out.widths = widths;
163
+ }
164
+ const rowHeight = value["rowHeight"];
165
+ if (typeof rowHeight === "number" && Number.isFinite(rowHeight) && rowHeight >= MIN_ROW_HEIGHT && rowHeight <= MAX_ROW_HEIGHT) {
166
+ out.rowHeight = Math.round(rowHeight);
167
+ }
168
+ if (Array.isArray(value["hiddenFields"])) {
169
+ const hiddenFields = value["hiddenFields"].filter((k) => typeof k === "string");
170
+ if (hiddenFields.length > 0) out.hiddenFields = hiddenFields;
171
+ }
172
+ if (Array.isArray(value["cardHidden"])) {
173
+ out.cardHidden = value["cardHidden"].filter((k) => typeof k === "string");
174
+ }
175
+ if (Array.isArray(value["columnOrder"])) {
176
+ const columnOrder = value["columnOrder"].filter((k) => typeof k === "string");
177
+ if (columnOrder.length > 0) out.columnOrder = columnOrder;
178
+ }
179
+ const gallerySize = value["gallerySize"];
180
+ if (gallerySize === "small" || gallerySize === "medium" || gallerySize === "large") {
181
+ out.gallerySize = gallerySize;
182
+ }
183
+ if (typeof value["wrap"] === "boolean") out.wrap = value["wrap"];
184
+ if (Array.isArray(value["wrapColumns"])) {
185
+ const wrapColumns = value["wrapColumns"].filter((k) => typeof k === "string");
186
+ if (wrapColumns.length > 0) out.wrapColumns = wrapColumns;
187
+ }
188
+ const fit = value["fit"];
189
+ if (fit === "auto" || fit === "fit" || fit === "scroll") out.fit = fit;
190
+ if (typeof value["freezeFirst"] === "boolean") out.freezeFirst = value["freezeFirst"];
191
+ const footer = value["footer"];
192
+ if (footer === "sticky" || footer === "inline") out.footer = footer;
193
+ if (isRecord(value["summaries"])) {
194
+ const summaries = {};
195
+ for (const [key, op] of Object.entries(value["summaries"])) {
196
+ if (typeof op === "string" && op.trim() !== "") summaries[key] = op;
197
+ }
198
+ if (Object.keys(summaries).length > 0) out.summaries = summaries;
199
+ }
200
+ return out;
201
+ }
202
+ function parseGrouping(raw) {
203
+ if (!isRecord(raw)) return void 0;
204
+ const field = raw["field"];
205
+ if (typeof field !== "string" || field.trim() === "") return void 0;
206
+ const out = { field };
207
+ if (isRecord(raw["aggregates"])) {
208
+ const aggregates = {};
209
+ for (const [key, spec] of Object.entries(raw["aggregates"])) {
210
+ if (!isRecord(spec)) continue;
211
+ const kind = spec["kind"];
212
+ if (typeof kind !== "string") continue;
213
+ if (!AGGREGATE_KINDS.includes(kind)) continue;
214
+ const label = spec["label"];
215
+ aggregates[key] = typeof label === "string" ? { kind, label } : { kind };
216
+ }
217
+ if (Object.keys(aggregates).length > 0) out.aggregates = aggregates;
218
+ }
219
+ const order = raw["order"];
220
+ if (typeof order === "string" && GROUP_ORDERS.includes(order)) {
221
+ out.order = order;
222
+ }
223
+ if (Array.isArray(raw["collapsed"])) {
224
+ const collapsed = raw["collapsed"].filter((k) => typeof k === "string");
225
+ if (collapsed.length > 0) out.collapsed = collapsed;
226
+ }
227
+ if (raw["showColumn"] === true) out.showColumn = true;
228
+ if (Array.isArray(raw["then"])) {
229
+ const then = [];
230
+ for (const level of raw["then"]) {
231
+ if (!isRecord(level)) continue;
232
+ const sub = level["field"];
233
+ if (typeof sub !== "string" || sub.trim() === "") continue;
234
+ const subOrder = level["order"];
235
+ const subGrain = level["grain"];
236
+ then.push({
237
+ field: sub,
238
+ ...typeof subOrder === "string" && GROUP_ORDERS.includes(subOrder) ? { order: subOrder } : {},
239
+ ...typeof subGrain === "string" && subGrain !== "" ? { grain: subGrain } : {}
240
+ });
241
+ }
242
+ if (then.length > 0) out.then = then.slice(0, 2);
243
+ }
244
+ const grain = raw["grain"];
245
+ if (typeof grain === "string" && grain !== "") out.grain = grain;
246
+ const across = raw["across"];
247
+ if (typeof across === "string" && across.trim() !== "") out.across = across;
248
+ if (Array.isArray(raw["show"])) {
249
+ const show = raw["show"].filter((k) => typeof k === "string" && k !== "");
250
+ if (show.length > 0) out.show = show;
251
+ }
252
+ if (Array.isArray(raw["trail"])) {
253
+ const trail = [];
254
+ for (const step of raw["trail"]) {
255
+ if (!isRecord(step) || typeof step["dim"] !== "string" || step["dim"] === "") continue;
256
+ const value = step["value"];
257
+ if (value !== null && typeof value !== "string") continue;
258
+ trail.push({ dim: step["dim"], value });
259
+ }
260
+ if (trail.length > 0) out.trail = trail;
261
+ }
262
+ return out;
263
+ }
264
+
265
+ // src/viewKeys.ts
266
+ var STORE_KEEPS_TIMELINE = true;
267
+ var ALL = ["grid", "kanban", "calendar", "gallery", ...STORE_KEEPS_TIMELINE ? ["timeline"] : [], "list"];
268
+ var HIDES = ["grid", "gallery", "kanban", "calendar", ...STORE_KEEPS_TIMELINE ? ["timeline"] : [], "list"];
269
+ var GRIDS = ["grid"];
270
+ var VIEW_KEYS = [
271
+ { path: "layout", shape: "kind", layouts: ALL, writer: "caller" },
272
+ { path: "filters", shape: "filter", layouts: ALL, writer: "caller" },
273
+ { path: "where", shape: "rule", layouts: ALL, writer: "caller" },
274
+ { path: "group_field", shape: "field", layouts: ["kanban", ...STORE_KEEPS_TIMELINE ? ["timeline"] : []], writer: "caller" },
275
+ { path: "swimlane_field", shape: "field:lane", layouts: ["kanban"], writer: "caller" },
276
+ { path: "collapsed_columns", shape: "values", layouts: ["kanban"], writer: "caller" },
277
+ { path: "measure", shape: "field:number", layouts: ["kanban"], writer: "caller" },
278
+ { path: "date_field", shape: "field:date", layouts: ["calendar"], writer: "caller" },
279
+ ...STORE_KEEPS_TIMELINE ? [
280
+ { path: "start_field", shape: "field:date", layouts: ["timeline"], writer: "caller" },
281
+ { path: "end_field", shape: "field:date", layouts: ["calendar", "timeline"], writer: "caller" }
282
+ ] : [],
283
+ { path: "image_field", shape: "field", layouts: ["gallery"], writer: "caller" },
284
+ { path: "sorts", shape: "sorts", layouts: ALL, writer: "caller" },
285
+ { path: "rule_id", shape: "uuid", layouts: ALL, writer: "caller" },
286
+ { path: "is_default", shape: "boolean", layouts: ALL, writer: "caller" },
287
+ { path: "presentation", shape: "presentation", layouts: ALL, writer: "caller" },
288
+ { path: "presentation.style", shape: "style", layouts: ALL, writer: "caller" },
289
+ { path: "presentation.formats", shape: "object", layouts: GRIDS, writer: "caller" },
290
+ { path: "presentation.frozen", shape: "fields", layouts: GRIDS, writer: "caller" },
291
+ { path: "presentation.grouping", shape: "grouping", layouts: ["grid", "gallery", "list"], writer: "caller" },
292
+ { path: "presentation.widths", shape: "widths", layouts: GRIDS, writer: "caller" },
293
+ { path: "presentation.rowHeight", shape: "row_height", layouts: GRIDS, writer: "caller" },
294
+ { path: "presentation.hiddenFields", shape: "fields", layouts: HIDES, writer: "caller" },
295
+ { path: "presentation.cardHidden", shape: "fields", layouts: ["kanban", "calendar", ...STORE_KEEPS_TIMELINE ? ["timeline"] : [], "list", "gallery"], writer: "caller" },
296
+ { path: "presentation.columnOrder", shape: "fields", layouts: GRIDS, writer: "caller" },
297
+ { path: "presentation.gallerySize", shape: "gallery_size", layouts: ["gallery"], writer: "caller" },
298
+ { path: "presentation.wrap", shape: "boolean", layouts: GRIDS, writer: "caller" },
299
+ { path: "presentation.wrapColumns", shape: "fields", layouts: GRIDS, writer: "caller" },
300
+ { path: "presentation.fit", shape: "fit", layouts: GRIDS, writer: "caller" },
301
+ { path: "presentation.freezeFirst", shape: "boolean", layouts: GRIDS, writer: "caller" },
302
+ { path: "presentation.footer", shape: "footer", layouts: GRIDS, writer: "caller" },
303
+ { path: "presentation.summaries", shape: "summaries", layouts: GRIDS, writer: "caller" },
304
+ { path: "grid", shape: "grid", layouts: GRIDS, writer: "caller" },
305
+ { path: "hidden_fields", shape: "input", layouts: HIDES, writer: "input" },
306
+ { path: "table_id", shape: "server", layouts: ALL, writer: "server" },
307
+ { path: "order", shape: "server", layouts: GRIDS, writer: "server" },
308
+ { path: "moved_from", shape: "server", layouts: ALL, writer: "server" }
309
+ ];
310
+ var STORE_KEPT_LAYOUTS = ["grid", "kanban", "calendar", "gallery", ...STORE_KEEPS_TIMELINE ? ["timeline"] : [], "list"];
311
+ var KINDS = STORE_KEPT_LAYOUTS;
312
+ function viewSettings(definition, rowFilters) {
313
+ const data = definition ?? {};
314
+ const text = (key) => {
315
+ const v = data[key];
316
+ return typeof v === "string" && v !== "" ? v : null;
317
+ };
318
+ const layout = String(data["layout"] ?? "grid");
319
+ const flat = rowFilters ?? (isObject(data["filters"]) ? data["filters"] : null);
320
+ const moved = data["moved_from"];
321
+ return {
322
+ layout: KINDS.includes(layout) ? layout : "grid",
323
+ filters: flat && Object.keys(flat).length > 0 ? flat : null,
324
+ where: isRule(data["where"]) ? data["where"] : null,
325
+ groupField: text("group_field"),
326
+ swimlaneField: text("swimlane_field"),
327
+ collapsedColumns: Array.isArray(data["collapsed_columns"]) ? data["collapsed_columns"].filter((v) => ["string", "number", "boolean"].includes(typeof v)).map(String) : [],
328
+ measure: text("measure"),
329
+ dateField: text("date_field"),
330
+ startField: text("start_field"),
331
+ endField: text("end_field"),
332
+ imageField: text("image_field"),
333
+ sorts: parseSorts(data["sorts"]),
334
+ ruleId: text("rule_id"),
335
+ isDefault: data["is_default"] === true || data["is_default"] === "true",
336
+ presentation: parseGridPresentation(data["presentation"]),
337
+ movedFrom: isObject(moved) ? moved : null
338
+ };
339
+ }
340
+ function isObject(raw) {
341
+ return Boolean(raw) && typeof raw === "object" && !Array.isArray(raw);
342
+ }
343
+ function isRule(raw) {
344
+ if (!isObject(raw)) return false;
345
+ const node = raw;
346
+ return typeof node.op === "string" && Array.isArray(node.args);
347
+ }
348
+ function parseSorts(raw) {
349
+ let list = raw;
350
+ if (typeof raw === "string") {
351
+ try {
352
+ list = raw.trim() === "" ? [] : JSON.parse(raw);
353
+ } catch {
354
+ return [];
355
+ }
356
+ }
357
+ if (!Array.isArray(list)) return [];
358
+ return list.filter((s) => isObject(s) && typeof s.field === "string").map((s) => ({ field: s.field, direction: s.direction === "desc" ? "desc" : "asc" }));
359
+ }
360
+
361
+ // src/views.ts
362
+ var VIEW_LAYOUTS = ["grid", "kanban", "calendar", "gallery", "timeline", "list"];
363
+ var LAYOUT_LABEL = {
364
+ grid: "Grid",
365
+ kanban: "Kanban",
366
+ calendar: "Calendar",
367
+ gallery: "Gallery",
368
+ timeline: "Timeline",
369
+ list: "List"
370
+ };
371
+ function viewOrderOf(definition) {
372
+ const raw = definition?.["order"];
373
+ return raw === "manual" ? "manual" : raw === "sorted" ? "sorted" : null;
374
+ }
375
+ function defaultViewOf(views) {
376
+ return views.find((v) => v.isDefault);
377
+ }
378
+ var PAGE_VIEWS = [...VIEW_LAYOUTS, "dashboards", "archived"];
379
+ var PAGE_VIEW_LABEL = {
380
+ ...LAYOUT_LABEL,
381
+ dashboards: "Dashboards",
382
+ archived: "Archived"
383
+ };
384
+ function viewFromRow(row) {
385
+ const data = row.definition ?? {};
386
+ const k = viewSettings(data, row.filters && Object.keys(row.filters).length > 0 ? row.filters : null);
387
+ const tableFromDefinition = typeof data["table_id"] === "string" && data["table_id"] !== "" ? data["table_id"] : null;
388
+ return {
389
+ id: row.view_id,
390
+ name: row.name || "Untitled view",
391
+ subject: row.table_id ?? tableFromDefinition ?? "",
392
+ layout: k.layout,
393
+ groupField: k.groupField,
394
+ swimlaneField: k.swimlaneField,
395
+ collapsedColumns: k.collapsedColumns,
396
+ measure: k.measure,
397
+ dateField: k.dateField,
398
+ startField: k.startField,
399
+ endField: k.endField,
400
+ imageField: k.imageField,
401
+ sorts: k.sorts,
402
+ order: viewOrderOf(data),
403
+ ruleId: k.ruleId,
404
+ ...k.filters ? { filters: k.filters } : {},
405
+ where: k.where,
406
+ // The older table's own default view, carried in by the mover, IS this table's default —
407
+ // the mover wrote the row's column, which `custom.views` does not return. Read as anything
408
+ // else, the page would seed a second "All records" beside it and open on that.
409
+ isDefault: k.isDefault || k.movedFrom?.["kind"] === "default_view",
410
+ presentation: k.presentation,
411
+ movedFrom: k.movedFrom
412
+ };
413
+ }
414
+
415
+ // src/viewLook.ts
416
+ function lookFromDocument(doc) {
417
+ const data = doc ?? {};
418
+ const read = viewSettings(data);
419
+ const out = {};
420
+ const has = (key) => Object.prototype.hasOwnProperty.call(data, key);
421
+ if (has("layout") && VIEW_LAYOUTS.includes(String(data["layout"]))) {
422
+ out.layout = data["layout"];
423
+ }
424
+ if (has("group_field")) out.groupField = read.groupField;
425
+ if (has("swimlane_field")) out.swimlaneField = read.swimlaneField;
426
+ if (has("collapsed_columns")) out.collapsedColumns = read.collapsedColumns;
427
+ if (has("measure")) out.measure = read.measure;
428
+ if (has("date_field")) out.dateField = read.dateField;
429
+ if (has("start_field")) out.startField = read.startField;
430
+ if (has("end_field")) out.endField = read.endField;
431
+ if (has("image_field")) out.imageField = read.imageField;
432
+ if (has("sorts")) out.sorts = read.sorts;
433
+ if (has("where")) out.where = read.where;
434
+ if (has("presentation")) out.presentation = parseGridPresentation(data["presentation"]);
435
+ return out;
436
+ }
437
+ function applyLook(view, look) {
438
+ if (!look) return view;
439
+ return { ...view, ...look };
440
+ }
441
+ async function readLooks(client, tableId) {
442
+ const answered = await client.viewLookRead({ table_id: tableId });
443
+ if (!answered.ok) return answered;
444
+ const out = {};
445
+ for (const [viewId, row] of Object.entries(answered.data ?? {})) {
446
+ out[viewId] = lookFromDocument(row?.look ?? null);
447
+ }
448
+ return { ok: true, data: out };
449
+ }
450
+
451
+ // src/firstPage.ts
452
+ var TABLE_PAGE_SIZE = 100;
453
+ function firstGridPageArgs(input) {
454
+ const { shown, fields } = input;
455
+ if (!shown) return null;
456
+ if ((shown.layout ?? "grid") !== "grid") return null;
457
+ if (shown.ruleId) return null;
458
+ if (shown.order === "manual") return null;
459
+ if (shown.filters && Object.keys(shown.filters).length > 0) return null;
460
+ if (shown.presentation?.grouping) return null;
461
+ const first = (shown.sorts ?? [])[0];
462
+ const viewSort = first && fields.some((f) => f.key === first.field) ? { id: first.field, direction: first.direction } : null;
463
+ const opening = viewSort ?? defaultSortOf(input.table, fields);
464
+ return {
465
+ p_table_id: input.tableId,
466
+ p_filter: {},
467
+ p_search: null,
468
+ p_sort: pageSortFor(fields, opening),
469
+ p_view_id: null,
470
+ p_limit: input.pageSize ?? TABLE_PAGE_SIZE,
471
+ p_offset: 0
472
+ };
473
+ }
474
+ async function firstGridPageRequest(client, tableId, options = {}) {
475
+ const [table, fields, views, looks] = await Promise.all([
476
+ client.tableRead({ table_id: tableId }),
477
+ client.fields({ table_id: tableId }),
478
+ client.views({ table_id: tableId }),
479
+ readLooks(client, tableId)
480
+ ]);
481
+ if (!table.ok || !fields.ok || !views.ok || !looks.ok) return null;
482
+ const mine = views.data.map(viewFromRow).filter((v) => v.subject === tableId);
483
+ const view = defaultViewOf(mine) ?? mine[0] ?? null;
484
+ const shown = view ? applyLook(view, looks.data[view.id]) : null;
485
+ return firstGridPageArgs({ tableId, table: table.data, fields: fields.data, shown, ...options.pageSize ? { pageSize: options.pageSize } : {} });
486
+ }
487
+ //# sourceMappingURL=first-page.cjs.map