grist-widget-sdk 0.3.27 → 0.4.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.
Files changed (86) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +1 -1
  3. package/dist/app.cjs +1139 -4336
  4. package/dist/app.cjs.map +1 -1
  5. package/dist/app.d.cts +1 -3
  6. package/dist/app.d.ts +1 -3
  7. package/dist/app.js +3 -7
  8. package/dist/chunk-4ZGVKGDF.js +204 -0
  9. package/dist/chunk-4ZGVKGDF.js.map +1 -0
  10. package/dist/{chunk-YQNMIL33.js → chunk-B5ZZNLVS.js} +528 -181
  11. package/dist/chunk-B5ZZNLVS.js.map +1 -0
  12. package/dist/chunk-O7NY46QY.js +1830 -0
  13. package/dist/chunk-O7NY46QY.js.map +1 -0
  14. package/dist/{chunk-6Y2IONGJ.js → chunk-P6VTEKWO.js} +113 -14
  15. package/dist/chunk-P6VTEKWO.js.map +1 -0
  16. package/dist/emulator/testing.cjs +1504 -4822
  17. package/dist/emulator/testing.cjs.map +1 -1
  18. package/dist/emulator/testing.d.cts +3 -6
  19. package/dist/emulator/testing.d.ts +3 -6
  20. package/dist/emulator/testing.js +7 -20
  21. package/dist/emulator/testing.js.map +1 -1
  22. package/dist/emulator.cjs +59 -249
  23. package/dist/emulator.cjs.map +1 -1
  24. package/dist/emulator.d.cts +3 -5
  25. package/dist/emulator.d.ts +3 -5
  26. package/dist/emulator.js +5 -11
  27. package/dist/index.cjs +1373 -4859
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +81 -260
  30. package/dist/index.d.ts +81 -260
  31. package/dist/index.js +8 -158
  32. package/dist/{inline-DpcT8tV9.d.ts → templates-CGmRIQBV.d.cts} +89 -35
  33. package/dist/{inline-C7DkvuET.d.cts → templates-Cq94qOcf.d.ts} +89 -35
  34. package/dist/{types-D3JxUCfL.d.cts → types-DBStn0Dk.d.cts} +2 -26
  35. package/dist/{types-D3JxUCfL.d.ts → types-DBStn0Dk.d.ts} +2 -26
  36. package/dist/use-grist-BK0eke9K.d.cts +358 -0
  37. package/dist/use-grist-C5DMZ3wU.d.ts +358 -0
  38. package/package.json +8 -37
  39. package/dist/advanced.cjs +0 -2799
  40. package/dist/advanced.cjs.map +0 -1
  41. package/dist/advanced.d.cts +0 -822
  42. package/dist/advanced.d.ts +0 -822
  43. package/dist/advanced.js +0 -872
  44. package/dist/advanced.js.map +0 -1
  45. package/dist/chunk-22U7WAY3.js +0 -463
  46. package/dist/chunk-22U7WAY3.js.map +0 -1
  47. package/dist/chunk-64SVRWW7.js +0 -758
  48. package/dist/chunk-64SVRWW7.js.map +0 -1
  49. package/dist/chunk-6Y2IONGJ.js.map +0 -1
  50. package/dist/chunk-B4AKVSWV.js +0 -2362
  51. package/dist/chunk-B4AKVSWV.js.map +0 -1
  52. package/dist/chunk-ELGVOHFD.js +0 -32
  53. package/dist/chunk-ELGVOHFD.js.map +0 -1
  54. package/dist/chunk-GTTD5HPO.js +0 -36
  55. package/dist/chunk-GTTD5HPO.js.map +0 -1
  56. package/dist/chunk-NO6FYX33.js +0 -2084
  57. package/dist/chunk-NO6FYX33.js.map +0 -1
  58. package/dist/chunk-OPTOYD2Y.js +0 -277
  59. package/dist/chunk-OPTOYD2Y.js.map +0 -1
  60. package/dist/chunk-PM3B4WYV.js +0 -12
  61. package/dist/chunk-PM3B4WYV.js.map +0 -1
  62. package/dist/chunk-REV5AUXD.js +0 -25
  63. package/dist/chunk-REV5AUXD.js.map +0 -1
  64. package/dist/chunk-YQNMIL33.js.map +0 -1
  65. package/dist/create-grist-emulator-BCqp1BF9.d.ts +0 -81
  66. package/dist/create-grist-emulator-DBM8OSIR.d.cts +0 -81
  67. package/dist/emulator/devtools.cjs +0 -1404
  68. package/dist/emulator/devtools.cjs.map +0 -1
  69. package/dist/emulator/devtools.d.cts +0 -48
  70. package/dist/emulator/devtools.d.ts +0 -48
  71. package/dist/emulator/devtools.js +0 -506
  72. package/dist/emulator/devtools.js.map +0 -1
  73. package/dist/emulator/transports.cjs +0 -1132
  74. package/dist/emulator/transports.cjs.map +0 -1
  75. package/dist/emulator/transports.d.cts +0 -38
  76. package/dist/emulator/transports.d.ts +0 -38
  77. package/dist/emulator/transports.js +0 -12
  78. package/dist/emulator/transports.js.map +0 -1
  79. package/dist/templates-8k2LKoO-.d.cts +0 -24
  80. package/dist/templates-DIwi_mvI.d.ts +0 -24
  81. package/dist/use-grist-reads-DUMvJgV7.d.ts +0 -480
  82. package/dist/use-grist-reads-DpjVuI0H.d.cts +0 -480
  83. package/dist/use-grist-types-DdOLEJXN.d.cts +0 -499
  84. package/dist/use-grist-types-kwxoFeub.d.ts +0 -499
  85. package/dist/use-grist-widget-options-from-context-CGOlQ5Vc.d.cts +0 -43
  86. package/dist/use-grist-widget-options-from-context-CGOlQ5Vc.d.ts +0 -43
@@ -1,1132 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/emulator/transports/index.ts
21
- var transports_exports = {};
22
- __export(transports_exports, {
23
- createIframeTransport: () => createIframeTransport,
24
- createInlineTransport: () => createInlineTransport
25
- });
26
- module.exports = __toCommonJS(transports_exports);
27
-
28
- // src/emulator/transports/iframe.ts
29
- var import_grain_rpc = require("grain-rpc");
30
-
31
- // src/emulator/theme-message.ts
32
- function buildGristThemeHostMessage(appearance, options) {
33
- return {
34
- theme: {
35
- appearance,
36
- name: appearance,
37
- colors: {}
38
- },
39
- ...options?.fromReady ? { fromReady: true } : {}
40
- };
41
- }
42
-
43
- // src/emulator/transports/iframe.ts
44
- function createIframeTransport(options) {
45
- const { iframe, state, bus, api, targetOrigin = "*" } = options;
46
- const timers = /* @__PURE__ */ new Set();
47
- const rpc = new import_grain_rpc.Rpc({
48
- sendMessage: (msg) => {
49
- const target = iframe.contentWindow;
50
- if (!target) return;
51
- target.postMessage(msg, targetOrigin);
52
- },
53
- logger: { info: () => {
54
- }, warn: () => {
55
- } }
56
- });
57
- rpc.queueOutgoingUntilReadyMessage();
58
- const receiveFromWidget = rpc.receiveMessage.bind(rpc);
59
- rpc.receiveMessage = (msg) => {
60
- if (msg && typeof msg === "object" && msg.mtype === import_grain_rpc.MsgType.RpcCall && msg.mdest === "grist") {
61
- const copy = { ...msg };
62
- delete copy.mdest;
63
- receiveFromWidget(copy);
64
- return;
65
- }
66
- receiveFromWidget(msg);
67
- };
68
- const onMessage = (event) => {
69
- if (event.source !== iframe.contentWindow) return;
70
- if (!isRpcEnvelope(event.data)) return;
71
- rpc.receiveMessage(event.data);
72
- };
73
- window.addEventListener("message", onMessage);
74
- rpc.registerImpl("GristView", api.GristView);
75
- rpc.registerImpl("GristDocAPI", api.GristDocAPI);
76
- rpc.registerImpl("WidgetAPI", api.WidgetAPI);
77
- rpc.registerImpl("CustomSectionAPI", api.CustomSectionAPI);
78
- rpc.registerImpl("_grist_api", api.GristAPI);
79
- rpc.registerImpl("CommandAPI", api.CommandAPI);
80
- const buildInteraction = options.buildInteraction ?? defaultInteraction(state);
81
- const cursorOf = options.cursor ?? (() => state.selection.cursor);
82
- const initialCursorOf = options.initialCursor ?? (() => state.selection.rowId);
83
- function fireDataChange(tableId, opts) {
84
- safePostMessage({
85
- tableId: tableId ?? state.selection.tableId,
86
- dataChange: true,
87
- ...opts?.mappingsChange ? { mappingsChange: true } : {}
88
- });
89
- }
90
- function fireCursor(rowId, opts) {
91
- const id = rowId === void 0 ? initialCursorOf() : rowId;
92
- if (id === null) return;
93
- safePostMessage({
94
- tableId: state.selection.tableId,
95
- rowId: id,
96
- cursor: cursorOf(),
97
- ...opts?.mappingsChange ? { mappingsChange: true } : {}
98
- });
99
- }
100
- function fireOptions() {
101
- safePostMessage({
102
- options: hasOptions(state.widgetOptions) ? { ...state.widgetOptions } : null,
103
- settings: { ...buildInteraction() }
104
- });
105
- }
106
- function fireTheme(message) {
107
- safePostMessage(message);
108
- }
109
- function emitInitialState(opts) {
110
- fireOptions();
111
- if (options.initialTheme) {
112
- fireTheme(buildGristThemeHostMessage(options.initialTheme, { fromReady: true }));
113
- }
114
- fireDataChange(void 0, opts);
115
- fireCursor(void 0, opts);
116
- }
117
- function emitInitialStateWithReplay(opts) {
118
- emitInitialState(opts);
119
- queueMicrotask(() => emitInitialState(opts));
120
- const timer = setTimeout(() => {
121
- timers.delete(timer);
122
- emitInitialState(opts);
123
- }, 0);
124
- timers.add(timer);
125
- }
126
- const offBus = bus.on((event) => {
127
- switch (event.type) {
128
- case "ready":
129
- emitInitialStateWithReplay();
130
- break;
131
- case "data-change":
132
- fireDataChange(event.tableId);
133
- break;
134
- case "cursor-change": {
135
- const rowId = event.rowId === null ? state.selection.rowId : event.rowId;
136
- if (rowId !== null) {
137
- safePostMessage({
138
- tableId: event.tableId,
139
- rowId,
140
- cursor: cursorOf()
141
- });
142
- }
143
- fireDataChange(event.tableId);
144
- break;
145
- }
146
- case "options-change":
147
- fireOptions();
148
- break;
149
- case "mappings-change":
150
- emitInitialStateWithReplay({ mappingsChange: true });
151
- break;
152
- case "theme-change":
153
- fireTheme(event.message);
154
- break;
155
- }
156
- });
157
- rpc.processIncoming();
158
- function safePostMessage(payload) {
159
- try {
160
- rpc.postMessage(payload);
161
- } catch (err) {
162
- console.warn("[grist-emulator/iframe] failed to deliver postMessage", err);
163
- }
164
- }
165
- return {
166
- dispose() {
167
- window.removeEventListener("message", onMessage);
168
- offBus();
169
- for (const timer of timers) clearTimeout(timer);
170
- timers.clear();
171
- },
172
- fireDataChange,
173
- fireCursor,
174
- fireOptions,
175
- fireTheme,
176
- emitInitialState
177
- };
178
- }
179
- function hasOptions(options) {
180
- return Object.keys(options).length > 0;
181
- }
182
- function isRpcEnvelope(data) {
183
- if (!data || typeof data !== "object") return false;
184
- return typeof data.mtype === "number";
185
- }
186
- function defaultInteraction(state) {
187
- return () => ({
188
- access_level: state.configuration?.requiredAccess ?? "read table",
189
- ...state.widgetInteraction
190
- });
191
- }
192
-
193
- // src/sdk/helpers/grist-user-actions.ts
194
- function gristUpdateRecordAction(tableId, rowId, patch) {
195
- return ["UpdateRecord", tableId, rowId, patch];
196
- }
197
- function gristAddRecordAction(tableId, values) {
198
- return ["AddRecord", tableId, null, values];
199
- }
200
- function gristRemoveRecordAction(tableId, rowId) {
201
- return ["RemoveRecord", tableId, rowId];
202
- }
203
- function gristBulkUpdateRecordAction(tableId, rowIds, columnarPatch) {
204
- return ["BulkUpdateRecord", tableId, rowIds, columnarPatch];
205
- }
206
- function gristBulkAddRecordAction(tableId, values, rowIds) {
207
- const length = inferBulkLength(values);
208
- const ids = rowIds ?? new Array(length).fill(null);
209
- return ["BulkAddRecord", tableId, ids, values];
210
- }
211
- function gristBulkRemoveRecordAction(tableId, rowIds) {
212
- return ["BulkRemoveRecord", tableId, rowIds];
213
- }
214
- function inferBulkLength(values) {
215
- for (const arr of Object.values(values)) if (Array.isArray(arr)) return arr.length;
216
- return 0;
217
- }
218
-
219
- // src/sdk/helpers/grist-value-codec.ts
220
- function coerceGristDocApiRefRowId(value) {
221
- if (typeof value === "number" && Number.isFinite(value)) return value;
222
- if (!Array.isArray(value) || value.length < 2) return void 0;
223
- const tag = value[0];
224
- if (tag === "R" && typeof value[2] === "number" && Number.isFinite(value[2])) return value[2];
225
- if (tag === "r" && typeof value[1] === "number" && Number.isFinite(value[1])) return value[1];
226
- return void 0;
227
- }
228
-
229
- // src/sdk/helpers/grist-safe-parse.ts
230
- var import_zod = require("zod");
231
- var gristSafeRefValueSchema = import_zod.z.object({
232
- rowId: import_zod.z.number(),
233
- display: import_zod.z.string().nullable().optional()
234
- });
235
- var gristSafeRefListValueSchema = import_zod.z.object({
236
- rowIds: import_zod.z.array(import_zod.z.number()),
237
- displays: import_zod.z.array(import_zod.z.string()).optional()
238
- });
239
- var gristCellValueSchema = import_zod.z.union([
240
- import_zod.z.null(),
241
- import_zod.z.string(),
242
- import_zod.z.number(),
243
- import_zod.z.boolean(),
244
- import_zod.z.date(),
245
- import_zod.z.array(import_zod.z.unknown()),
246
- gristSafeRefValueSchema,
247
- gristSafeRefListValueSchema
248
- ]);
249
- function inferDisplayHelpersByRef(columns) {
250
- const out = {};
251
- const helperColumns = Object.entries(columns).filter(
252
- ([colId]) => colId.startsWith("gristHelper_")
253
- );
254
- const usedHelpers = /* @__PURE__ */ new Set();
255
- const colRefToColId = /* @__PURE__ */ new Map();
256
- for (const [colId, col] of Object.entries(columns)) {
257
- if (typeof col?.colRef === "number" && Number.isFinite(col.colRef)) {
258
- colRefToColId.set(col.colRef, colId);
259
- }
260
- }
261
- for (const [colId, col] of Object.entries(columns)) {
262
- const type = col?.type;
263
- if (typeof type !== "string" || !type.startsWith("Ref:") && !type.startsWith("RefList:")) {
264
- continue;
265
- }
266
- if (typeof col.displayColRef === "number" && Number.isFinite(col.displayColRef)) {
267
- const helperColId = colRefToColId.get(col.displayColRef);
268
- if (helperColId) {
269
- out[colId] = helperColId;
270
- usedHelpers.add(helperColId);
271
- continue;
272
- }
273
- }
274
- const match = helperColumns.find(([, helper]) => {
275
- const formula = helper?.formula;
276
- return typeof formula === "string" && (formula.includes(`$${colId}.`) || formula.includes(`$${colId}`));
277
- });
278
- if (match) {
279
- out[colId] = match[0];
280
- usedHelpers.add(match[0]);
281
- }
282
- }
283
- const unresolvedRefs = Object.entries(columns).filter(([colId, col]) => {
284
- const type = col?.type;
285
- return !out[colId] && typeof type === "string" && (type.startsWith("Ref:") || type.startsWith("RefList:"));
286
- }).sort((a, b) => (a[1]?.parentPos ?? Number.MAX_SAFE_INTEGER) - (b[1]?.parentPos ?? Number.MAX_SAFE_INTEGER));
287
- const helperByPos = helperColumns.filter(([helperId]) => !usedHelpers.has(helperId)).sort((a, b) => (a[1]?.parentPos ?? Number.MAX_SAFE_INTEGER) - (b[1]?.parentPos ?? Number.MAX_SAFE_INTEGER));
288
- for (const [refId, refCol] of unresolvedRefs) {
289
- const refPos = refCol?.parentPos ?? Number.MAX_SAFE_INTEGER;
290
- const candidate = helperByPos.find(([, helperCol]) => {
291
- const helperPos = helperCol?.parentPos ?? Number.MAX_SAFE_INTEGER;
292
- return helperPos > refPos;
293
- });
294
- if (!candidate) continue;
295
- out[refId] = candidate[0];
296
- usedHelpers.add(candidate[0]);
297
- }
298
- for (const [refId] of unresolvedRefs) {
299
- if (out[refId]) continue;
300
- const candidate = helperByPos.find(([helperId]) => !usedHelpers.has(helperId));
301
- if (!candidate) continue;
302
- out[refId] = candidate[0];
303
- usedHelpers.add(candidate[0]);
304
- }
305
- return out;
306
- }
307
-
308
- // src/emulator/core/document.ts
309
- function getTable(state, tableId) {
310
- const table = state.tables.get(tableId);
311
- if (!table) throw new Error(`Unknown table: ${tableId}`);
312
- return table;
313
- }
314
- function nextRowId(table) {
315
- let max = 0;
316
- for (const row of table.rows) {
317
- if (typeof row.id === "number" && row.id > max) max = row.id;
318
- }
319
- return max + 1;
320
- }
321
- function findRow(table, rowId) {
322
- return table.rows.find((r) => r.id === rowId);
323
- }
324
- function findRowIndex(table, rowId) {
325
- return table.rows.findIndex((r) => r.id === rowId);
326
- }
327
- function evaluateRowFormulas(state, table, row) {
328
- for (const [colId, col] of Object.entries(table.columns)) {
329
- if (col.formulaFn) {
330
- try {
331
- row[colId] = col.formulaFn(row, { table, document: state });
332
- } catch (err) {
333
- row[colId] = formulaError(err);
334
- }
335
- }
336
- }
337
- }
338
- function escapeRegExp(s) {
339
- return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
340
- }
341
- function extractRefListIdsFromWire(raw) {
342
- if (raw == null) return [];
343
- if (!Array.isArray(raw)) return [];
344
- const items = raw[0] === "L" ? raw.slice(1) : raw;
345
- const out = [];
346
- for (const item of items) {
347
- if (typeof item === "number" && Number.isFinite(item) && item > 0) {
348
- out.push(Math.trunc(item));
349
- continue;
350
- }
351
- if (item && typeof item === "object" && "rowId" in item) {
352
- const r = item.rowId;
353
- if (typeof r === "number" && Number.isFinite(r) && r > 0) {
354
- out.push(Math.trunc(r));
355
- continue;
356
- }
357
- }
358
- const t = coerceGristDocApiRefRowId(item);
359
- if (t !== void 0 && t > 0) out.push(Math.trunc(t));
360
- }
361
- return Array.from(new Set(out));
362
- }
363
- function fieldFromRefListHelperFormula(formula, refColId) {
364
- if (!formula) return null;
365
- const re = new RegExp(`\\$${escapeRegExp(refColId)}\\.([A-Za-z_]\\w*)`);
366
- const m = formula.match(re);
367
- return m?.[1] ?? null;
368
- }
369
- function firstTextLikeColumnId(columns) {
370
- let best = null;
371
- for (const [colId, col] of Object.entries(columns)) {
372
- if (colId === "id" || colId.startsWith("gristHelper_")) continue;
373
- const t = col.type;
374
- if (t !== "Text" && t !== "Choice") continue;
375
- const pos = col.parentPos ?? 99999;
376
- if (!best || pos < best.pos) best = { id: colId, pos };
377
- }
378
- return best?.id ?? null;
379
- }
380
- function formatLabelFromCell(value) {
381
- if (value == null) return "";
382
- if (typeof value === "string") return value.trim();
383
- if (typeof value === "number" || typeof value === "boolean") return String(value);
384
- if (value instanceof Date) return value.toISOString();
385
- if (Array.isArray(value) && value[0] === "E") return "";
386
- if (typeof value === "object" && value && "__ref" in value) {
387
- const r = value.rowId;
388
- return typeof r === "number" && Number.isFinite(r) ? String(r) : "";
389
- }
390
- return "";
391
- }
392
- function syncRefListDisplayHelpers(state, table, row) {
393
- const displayHelpersByRef = inferDisplayHelpersByRef(table.columns);
394
- for (const [colId, col] of Object.entries(table.columns)) {
395
- const type = col.type;
396
- if (typeof type !== "string" || !type.startsWith("RefList:")) continue;
397
- const helperColId = displayHelpersByRef[colId];
398
- if (!helperColId) continue;
399
- const helperMeta = table.columns[helperColId];
400
- if (!helperMeta || helperMeta.formulaFn) continue;
401
- const targetTableId = type.slice("RefList:".length);
402
- const targetTable = state.tables.get(targetTableId);
403
- if (!targetTable) continue;
404
- const ids = extractRefListIdsFromWire(row[colId]);
405
- if (ids.length === 0) {
406
- row[helperColId] = [];
407
- continue;
408
- }
409
- const fieldId = fieldFromRefListHelperFormula(helperMeta.formula, colId) ?? firstTextLikeColumnId(targetTable.columns);
410
- const labels = ids.map((rid) => {
411
- if (!fieldId) return String(rid);
412
- const trow = findRow(targetTable, rid);
413
- if (!trow) return String(rid);
414
- const lbl = formatLabelFromCell(trow[fieldId]);
415
- return lbl !== "" ? lbl : String(rid);
416
- });
417
- row[helperColId] = labels;
418
- }
419
- }
420
- function formulaError(err) {
421
- const message = err instanceof Error ? err.message : String(err);
422
- return ["E", "Error", message];
423
- }
424
-
425
- // src/emulator/core/action-engine.ts
426
- var EmulatorActionError = class extends Error {
427
- constructor(action, message) {
428
- super(message);
429
- this.action = action;
430
- this.name = "EmulatorActionError";
431
- }
432
- };
433
- function applyUserActions(state, bus, actions) {
434
- const retValues = [];
435
- const changed = /* @__PURE__ */ new Set();
436
- for (const action of actions) {
437
- bus.emit({ type: "user-action", action });
438
- const ret = applySingle(state, action, changed);
439
- retValues.push(ret);
440
- }
441
- for (const tableId of changed) {
442
- bus.emit({ type: "data-change", tableId });
443
- }
444
- return { retValues, changedTableIds: [...changed] };
445
- }
446
- function applySingle(state, action, changed) {
447
- const [name, ...args] = action;
448
- switch (name) {
449
- case "AddRecord":
450
- return addRecord(state, args, changed);
451
- case "BulkAddRecord":
452
- return bulkAddRecord(state, args, changed);
453
- case "UpdateRecord":
454
- return updateRecord(state, args, changed);
455
- case "BulkUpdateRecord":
456
- return bulkUpdateRecord(state, args, changed);
457
- case "RemoveRecord":
458
- return removeRecord(state, args, changed);
459
- case "BulkRemoveRecord":
460
- return bulkRemoveRecord(state, args, changed);
461
- case "AddColumn":
462
- return addColumn(state, args);
463
- case "AddVisibleColumn":
464
- return addColumn(state, args);
465
- case "RemoveColumn":
466
- return removeColumn(state, args, changed);
467
- case "RenameColumn":
468
- return renameColumn(state, args, changed);
469
- case "ModifyColumn":
470
- return modifyColumn(state, args, changed);
471
- case "AddTable":
472
- return addTable(state, args);
473
- case "RemoveTable":
474
- return removeTable(state, args);
475
- case "RenameTable":
476
- return renameTable(state, args);
477
- default:
478
- throw new EmulatorActionError(action, `Unsupported user action: ${String(name)}`);
479
- }
480
- }
481
- function addRecord(state, [tableId, rowId, values], changed) {
482
- const table = getTable(state, requireString(tableId, "AddRecord.tableId"));
483
- const id = typeof rowId === "number" ? rowId : nextRowId(table);
484
- const normalizedValues = normalizeValuesForTable(
485
- table,
486
- values ?? {}
487
- );
488
- const row = { id, ...normalizedValues };
489
- ensureColumns(table, normalizedValues);
490
- evaluateRowFormulas(state, table, row);
491
- syncRefListDisplayHelpers(state, table, row);
492
- table.rows.push(row);
493
- changed.add(table.tableId);
494
- return id;
495
- }
496
- function bulkAddRecord(state, [tableId, rowIds, columnar], changed) {
497
- const table = getTable(state, requireString(tableId, "BulkAddRecord.tableId"));
498
- const cols = normalizeColumnarForTable(
499
- table,
500
- columnar ?? {}
501
- );
502
- const ids = Array.isArray(rowIds) ? rowIds : [];
503
- const length = ids.length || lengthOf(cols);
504
- const out = [];
505
- ensureColumns(table, cols, true);
506
- for (let i = 0; i < length; i++) {
507
- const id = typeof ids[i] === "number" ? ids[i] : nextRowId(table);
508
- const row = { id };
509
- for (const colId of Object.keys(cols)) row[colId] = cols[colId][i];
510
- evaluateRowFormulas(state, table, row);
511
- syncRefListDisplayHelpers(state, table, row);
512
- table.rows.push(row);
513
- out.push(id);
514
- }
515
- changed.add(table.tableId);
516
- return out;
517
- }
518
- function updateRecord(state, [tableId, rowId, values], changed) {
519
- const table = getTable(state, requireString(tableId, "UpdateRecord.tableId"));
520
- const id = requireNumber(rowId, "UpdateRecord.rowId");
521
- const row = findRow(table, id);
522
- if (!row) throw new EmulatorActionError(["UpdateRecord", tableId, rowId, values], `Row ${id} not found in ${table.tableId}`);
523
- const normalizedValues = normalizeValuesForTable(
524
- table,
525
- values ?? {}
526
- );
527
- ensureColumns(table, normalizedValues);
528
- Object.assign(row, normalizedValues);
529
- evaluateRowFormulas(state, table, row);
530
- syncRefListDisplayHelpers(state, table, row);
531
- changed.add(table.tableId);
532
- return null;
533
- }
534
- function bulkUpdateRecord(state, [tableId, rowIds, columnar], changed) {
535
- const table = getTable(state, requireString(tableId, "BulkUpdateRecord.tableId"));
536
- const ids = rowIds;
537
- const cols = normalizeColumnarForTable(
538
- table,
539
- columnar ?? {}
540
- );
541
- ensureColumns(table, cols, true);
542
- ids.forEach((id, idx) => {
543
- const row = findRow(table, id);
544
- if (!row) throw new EmulatorActionError(["BulkUpdateRecord", tableId, ids, cols], `Row ${id} not found in ${table.tableId}`);
545
- for (const colId of Object.keys(cols)) row[colId] = cols[colId][idx];
546
- evaluateRowFormulas(state, table, row);
547
- syncRefListDisplayHelpers(state, table, row);
548
- });
549
- changed.add(table.tableId);
550
- return null;
551
- }
552
- function removeRecord(state, [tableId, rowId], changed) {
553
- const table = getTable(state, requireString(tableId, "RemoveRecord.tableId"));
554
- const id = requireNumber(rowId, "RemoveRecord.rowId");
555
- const idx = findRowIndex(table, id);
556
- if (idx >= 0) table.rows.splice(idx, 1);
557
- if (state.selection.tableId === table.tableId && state.selection.rowId === id) {
558
- state.selection.rowId = table.rows[0]?.id ?? null;
559
- }
560
- changed.add(table.tableId);
561
- return null;
562
- }
563
- function bulkRemoveRecord(state, [tableId, rowIds], changed) {
564
- const table = getTable(state, requireString(tableId, "BulkRemoveRecord.tableId"));
565
- const ids = new Set(rowIds);
566
- table.rows = table.rows.filter((r) => !ids.has(r.id));
567
- if (state.selection.tableId === table.tableId && typeof state.selection.rowId === "number" && ids.has(state.selection.rowId)) {
568
- state.selection.rowId = table.rows[0]?.id ?? null;
569
- }
570
- changed.add(table.tableId);
571
- return null;
572
- }
573
- function addColumn(state, [tableId, colId, info]) {
574
- const table = getTable(state, requireString(tableId, "AddColumn.tableId"));
575
- const col = requireString(colId, "AddColumn.colId");
576
- if (table.columns[col]) throw new EmulatorActionError(["AddColumn", tableId, colId], `Column ${col} already exists`);
577
- table.columns[col] = info ?? {};
578
- for (const row of table.rows) {
579
- if (!(col in row)) row[col] = null;
580
- }
581
- return null;
582
- }
583
- function removeColumn(state, [tableId, colId], changed) {
584
- const table = getTable(state, requireString(tableId, "RemoveColumn.tableId"));
585
- const col = requireString(colId, "RemoveColumn.colId");
586
- delete table.columns[col];
587
- for (const row of table.rows) delete row[col];
588
- changed.add(table.tableId);
589
- return null;
590
- }
591
- function renameColumn(state, [tableId, colId, newColId], changed) {
592
- const table = getTable(state, requireString(tableId, "RenameColumn.tableId"));
593
- const from = requireString(colId, "RenameColumn.colId");
594
- const to = requireString(newColId, "RenameColumn.newColId");
595
- if (!table.columns[from]) throw new EmulatorActionError(["RenameColumn", tableId, from, to], `Column ${from} not found`);
596
- if (from === to) return null;
597
- table.columns[to] = table.columns[from];
598
- delete table.columns[from];
599
- for (const row of table.rows) {
600
- if (from in row) {
601
- row[to] = row[from];
602
- delete row[from];
603
- }
604
- }
605
- changed.add(table.tableId);
606
- return null;
607
- }
608
- function modifyColumn(state, [tableId, colId, info], changed) {
609
- const table = getTable(state, requireString(tableId, "ModifyColumn.tableId"));
610
- const col = requireString(colId, "ModifyColumn.colId");
611
- if (!table.columns[col]) throw new EmulatorActionError(["ModifyColumn", tableId, colId], `Column ${col} not found`);
612
- table.columns[col] = { ...table.columns[col], ...info };
613
- changed.add(table.tableId);
614
- return null;
615
- }
616
- function addTable(state, [tableId, columns]) {
617
- const id = requireString(tableId, "AddTable.tableId");
618
- if (state.tables.has(id)) throw new EmulatorActionError(["AddTable", tableId], `Table ${id} already exists`);
619
- const cols = {};
620
- for (const c of columns ?? []) {
621
- cols[c.id] = { ...c };
622
- }
623
- state.tables.set(id, { tableId: id, columns: cols, rows: [] });
624
- return id;
625
- }
626
- function removeTable(state, [tableId]) {
627
- const id = requireString(tableId, "RemoveTable.tableId");
628
- state.tables.delete(id);
629
- if (state.selection.tableId === id) {
630
- const fallback = state.tables.keys().next().value;
631
- if (fallback) {
632
- state.selection.tableId = fallback;
633
- state.selection.rowId = null;
634
- }
635
- }
636
- return null;
637
- }
638
- function renameTable(state, [from, to]) {
639
- const fromId = requireString(from, "RenameTable.from");
640
- const toId = requireString(to, "RenameTable.to");
641
- const table = state.tables.get(fromId);
642
- if (!table) throw new EmulatorActionError(["RenameTable", fromId], `Table ${fromId} not found`);
643
- state.tables.delete(fromId);
644
- table.tableId = toId;
645
- state.tables.set(toId, table);
646
- if (state.selection.tableId === fromId) state.selection.tableId = toId;
647
- return null;
648
- }
649
- function ensureColumns(table, values, bulk = false) {
650
- for (const col of Object.keys(values)) {
651
- if (!table.columns[col]) {
652
- const sample = bulk ? values[col]?.[0] : values[col];
653
- table.columns[col] = inferType(sample);
654
- }
655
- }
656
- }
657
- function inferType(sample) {
658
- switch (typeof sample) {
659
- case "number":
660
- return { type: "Numeric" };
661
- case "boolean":
662
- return { type: "Bool" };
663
- case "string":
664
- return { type: "Text" };
665
- default:
666
- return { type: "Any" };
667
- }
668
- }
669
- function lengthOf(cols) {
670
- for (const arr of Object.values(cols)) if (Array.isArray(arr)) return arr.length;
671
- return 0;
672
- }
673
- function requireString(value, name) {
674
- if (typeof value !== "string" || !value) throw new Error(`Expected non-empty string for ${name}`);
675
- return value;
676
- }
677
- function requireNumber(value, name) {
678
- if (typeof value !== "number" || Number.isNaN(value)) throw new Error(`Expected number for ${name}`);
679
- return value;
680
- }
681
- function normalizeValuesForTable(table, values) {
682
- const out = {};
683
- for (const [colId, value] of Object.entries(values)) {
684
- out[colId] = normalizeCellValueForType(value, table.columns[colId]?.type);
685
- }
686
- return out;
687
- }
688
- function normalizeColumnarForTable(table, columns) {
689
- const out = {};
690
- for (const [colId, values] of Object.entries(columns)) {
691
- const type = table.columns[colId]?.type;
692
- out[colId] = Array.isArray(values) ? values.map((value) => normalizeCellValueForType(value, type)) : [];
693
- }
694
- return out;
695
- }
696
- function normalizeCellValueForType(value, type) {
697
- if (value === null || value === void 0 || typeof type !== "string") return value;
698
- if (type.startsWith("Ref:")) return normalizeRefValue(value);
699
- if (type.startsWith("RefList:")) return normalizeRefListValue(value);
700
- return value;
701
- }
702
- function extractRefRowId(value) {
703
- if (value === null || value === void 0) return null;
704
- if (value && typeof value === "object" && "__ref" in value) {
705
- const inner = value.rowId;
706
- return extractRefRowId(inner);
707
- }
708
- if (value && typeof value === "object" && "rowId" in value) {
709
- return extractRefRowId(value.rowId);
710
- }
711
- const fromTuple = coerceGristDocApiRefRowId(value);
712
- if (fromTuple !== void 0 && fromTuple > 0) return Math.trunc(fromTuple);
713
- return toPositiveInt(value);
714
- }
715
- function normalizeRefValue(value) {
716
- return extractRefRowId(value);
717
- }
718
- function normalizeRefListValue(value) {
719
- const toIdList = (items) => Array.from(
720
- new Set(items.map((item) => extractRefRowId(item)).filter((item) => item !== null))
721
- );
722
- if (Array.isArray(value) && value[0] === "L") {
723
- return ["L", ...toIdList(value.slice(1))];
724
- }
725
- if (Array.isArray(value)) {
726
- return ["L", ...toIdList(value)];
727
- }
728
- if (typeof value === "string") {
729
- const tokens = value.split(",").map((t) => t.trim()).filter(Boolean);
730
- return ["L", ...toIdList(tokens)];
731
- }
732
- if (value && typeof value === "object" && Array.isArray(value.rowIds)) {
733
- return ["L", ...toIdList(value.rowIds)];
734
- }
735
- return ["L"];
736
- }
737
- function toPositiveInt(value) {
738
- if (typeof value === "number" && Number.isFinite(value) && value > 0) return Math.trunc(value);
739
- if (typeof value === "string") {
740
- const n = Number.parseInt(value.trim(), 10);
741
- if (Number.isFinite(n) && n > 0) return n;
742
- }
743
- return null;
744
- }
745
-
746
- // src/emulator/core/mappings.ts
747
- function resolveMappings(state) {
748
- if (state.selection.mappings !== void 0 && state.selection.mappings !== null) {
749
- return state.selection.mappings;
750
- }
751
- return null;
752
- }
753
-
754
- // src/emulator/transports/inline.ts
755
- function createInlineTransport(options) {
756
- const { state, bus, api } = options;
757
- const target = options.target ?? globalThis;
758
- installFakeIframeContext(target);
759
- const recordCbs = /* @__PURE__ */ new Map();
760
- const recordsCbs = /* @__PURE__ */ new Map();
761
- const optionsCbs = /* @__PURE__ */ new Set();
762
- const newRecordCbs = /* @__PURE__ */ new Set();
763
- const generic = /* @__PURE__ */ new Map();
764
- let lastRecord = null;
765
- let lastRecords = null;
766
- let lastOptions = null;
767
- let lastNewRecord = void 0;
768
- const buildInteraction = options.buildInteraction ?? (() => ({
769
- access_level: state.configuration?.requiredAccess ?? "read table",
770
- ...state.widgetInteraction
771
- }));
772
- async function pushRecord(rowId) {
773
- const mappings = resolveMappings(state);
774
- if (rowId === "new") {
775
- lastNewRecord = mappings;
776
- for (const cb of newRecordCbs) {
777
- try {
778
- cb(mappings);
779
- } catch (err) {
780
- logErr(err);
781
- }
782
- }
783
- lastRecord = { record: null, mappings };
784
- for (const [cb] of recordCbs) {
785
- try {
786
- cb(null, mappings);
787
- } catch (err) {
788
- logErr(err);
789
- }
790
- }
791
- return;
792
- }
793
- if (rowId === null) {
794
- lastRecord = { record: null, mappings };
795
- for (const [cb] of recordCbs) {
796
- try {
797
- cb(null, mappings);
798
- } catch (err) {
799
- logErr(err);
800
- }
801
- }
802
- return;
803
- }
804
- let record = null;
805
- try {
806
- record = await api.GristView.fetchSelectedRecord(rowId);
807
- } catch (err) {
808
- logErr(err);
809
- }
810
- lastRecord = { record, mappings };
811
- for (const [cb, opts] of recordCbs) {
812
- try {
813
- const r = opts?.keepEncoded ? await api.GristView.fetchSelectedRecord(rowId, { keepEncoded: true }) : record;
814
- cb(r, mappings);
815
- } catch (err) {
816
- logErr(err);
817
- }
818
- }
819
- }
820
- async function pushRecords() {
821
- const mappings = resolveMappings(state);
822
- let baseRows = [];
823
- try {
824
- const columnar = await api.GristView.fetchSelectedTable({});
825
- baseRows = columnsToRows(columnar);
826
- } catch (err) {
827
- logErr(err);
828
- }
829
- lastRecords = { records: baseRows, mappings };
830
- for (const [cb, opts] of recordsCbs) {
831
- try {
832
- const fetchOptions = coerceFetchOptions(opts);
833
- const rows = fetchOptions?.keepEncoded ? columnsToRows(await api.GristView.fetchSelectedTable({ keepEncoded: true })) : baseRows;
834
- cb(rows, mappings);
835
- } catch (err) {
836
- logErr(err);
837
- }
838
- }
839
- }
840
- async function fetchSelectedTableShaped(opts) {
841
- const fetchOptions = coerceFetchOptions(opts);
842
- const columnar = await api.GristView.fetchSelectedTable(
843
- fetchOptions ? { keepEncoded: fetchOptions.keepEncoded } : {}
844
- );
845
- if (fetchOptions?.format === "rows") return columnsToRows(columnar);
846
- return columnar;
847
- }
848
- function pushOptions() {
849
- const opts = Object.keys(state.widgetOptions).length > 0 ? { ...state.widgetOptions } : null;
850
- const interaction = buildInteraction();
851
- lastOptions = { options: opts, interaction };
852
- for (const cb of optionsCbs) {
853
- try {
854
- cb(opts, interaction);
855
- } catch (err) {
856
- logErr(err);
857
- }
858
- }
859
- }
860
- const offBus = bus.on(async (event) => {
861
- switch (event.type) {
862
- case "data-change":
863
- await pushRecords();
864
- await pushRecord(state.selection.rowId);
865
- break;
866
- case "cursor-change":
867
- await pushRecord(event.rowId);
868
- break;
869
- case "options-change":
870
- pushOptions();
871
- break;
872
- case "ready":
873
- pushOptions();
874
- if (options.initialTheme) {
875
- notify("message", buildGristThemeHostMessage(options.initialTheme, { fromReady: true }));
876
- }
877
- await pushRecords();
878
- await pushRecord(state.selection.rowId);
879
- break;
880
- case "mappings-change":
881
- await pushRecords();
882
- await pushRecord(state.selection.rowId);
883
- break;
884
- case "theme-change":
885
- notify("message", event.message);
886
- break;
887
- }
888
- });
889
- function makeTableOps(tableId) {
890
- return {
891
- async getTableId() {
892
- return tableId;
893
- },
894
- async create(records, options2) {
895
- const list = Array.isArray(records) ? records : [records];
896
- const ids = [];
897
- for (const r of list) {
898
- const result = applyUserActions(state, bus, [
899
- gristAddRecordAction(tableId, parseFields(r.fields, options2))
900
- ]);
901
- ids.push({ id: result.retValues[0] });
902
- }
903
- return Array.isArray(records) ? ids : ids[0];
904
- },
905
- async update(records, options2) {
906
- const list = Array.isArray(records) ? records : [records];
907
- const actions = list.map((r) => gristUpdateRecordAction(tableId, r.id, parseFields(r.fields, options2)));
908
- applyUserActions(state, bus, actions);
909
- },
910
- async upsert(records, options2) {
911
- const list = Array.isArray(records) ? records : [records];
912
- const allowAdd = options2?.add !== false;
913
- const allowUpdate = options2?.update !== false;
914
- const table = getTable(state, tableId);
915
- const actions = [];
916
- for (const r of list) {
917
- const matches = table.rows.filter(
918
- (row) => Object.entries(r.require).every(([k, v]) => row[k] === v)
919
- );
920
- if (matches.length > 0) {
921
- if (!allowUpdate) continue;
922
- const fields = parseFields(r.fields ?? {}, options2);
923
- for (const m of matches) actions.push(gristUpdateRecordAction(tableId, m.id, fields));
924
- } else if (allowAdd) {
925
- actions.push(gristAddRecordAction(tableId, { ...r.require, ...parseFields(r.fields ?? {}, options2) }));
926
- }
927
- }
928
- if (actions.length > 0) applyUserActions(state, bus, actions);
929
- },
930
- async destroy(recordIds) {
931
- if (Array.isArray(recordIds)) {
932
- applyUserActions(state, bus, [gristBulkRemoveRecordAction(tableId, recordIds)]);
933
- } else {
934
- applyUserActions(state, bus, [gristRemoveRecordAction(tableId, recordIds)]);
935
- }
936
- void gristBulkAddRecordAction;
937
- void gristBulkUpdateRecordAction;
938
- }
939
- };
940
- }
941
- function notify(event, ...args) {
942
- const set = generic.get(event);
943
- if (!set) return;
944
- for (const fn of set) {
945
- try {
946
- fn(...args);
947
- } catch (err) {
948
- logErr(err);
949
- }
950
- }
951
- }
952
- const grist = {
953
- async ready(opts) {
954
- await api.CustomSectionAPI.configure(opts ? { ...opts, onEditOptions: void 0 } : {});
955
- },
956
- onRecord(cb, opts) {
957
- recordCbs.set(cb, opts);
958
- if (lastRecord) {
959
- try {
960
- cb(lastRecord.record, lastRecord.mappings);
961
- } catch (err) {
962
- logErr(err);
963
- }
964
- }
965
- },
966
- onRecords(cb, opts) {
967
- recordsCbs.set(cb, opts);
968
- if (lastRecords) {
969
- try {
970
- cb(lastRecords.records, lastRecords.mappings);
971
- } catch (err) {
972
- logErr(err);
973
- }
974
- }
975
- },
976
- onOptions(cb) {
977
- optionsCbs.add(cb);
978
- if (lastOptions) {
979
- try {
980
- cb(lastOptions.options, lastOptions.interaction);
981
- } catch (err) {
982
- logErr(err);
983
- }
984
- }
985
- },
986
- onNewRecord(cb) {
987
- newRecordCbs.add(cb);
988
- if (lastNewRecord !== void 0) {
989
- try {
990
- cb(lastNewRecord);
991
- } catch (err) {
992
- logErr(err);
993
- }
994
- }
995
- },
996
- mapColumnNames(data) {
997
- const mappings = resolveMappings(state);
998
- if (!mappings) return null;
999
- const out = {};
1000
- let allMapped = true;
1001
- for (const [logical, real] of Object.entries(mappings)) {
1002
- if (Array.isArray(real)) {
1003
- out[logical] = real.map((r) => data[r]);
1004
- } else if (typeof real === "string") {
1005
- out[logical] = data[real];
1006
- } else {
1007
- allMapped = false;
1008
- }
1009
- }
1010
- return allMapped ? out : null;
1011
- },
1012
- mapColumnNamesBack(data) {
1013
- const mappings = resolveMappings(state);
1014
- if (!mappings) return data;
1015
- const out = {};
1016
- for (const [logical, real] of Object.entries(mappings)) {
1017
- if (typeof real === "string" && logical in data) {
1018
- out[real] = data[logical];
1019
- }
1020
- }
1021
- return out;
1022
- },
1023
- getOption: (k) => api.WidgetAPI.getOption(k),
1024
- setOption: (k, v) => api.WidgetAPI.setOption(k, v),
1025
- getOptions: () => api.WidgetAPI.getOptions(),
1026
- setOptions: (o) => api.WidgetAPI.setOptions(o),
1027
- clearOptions: () => api.WidgetAPI.clearOptions(),
1028
- setCursorPos: (pos) => api.GristView.setCursorPos(pos),
1029
- setSelectedRows: (rowIds) => api.GristView.setSelectedRows(rowIds),
1030
- fetchSelectedTable: (opts) => fetchSelectedTableShaped(opts),
1031
- fetchSelectedRecord: (rowId, opts) => api.GristView.fetchSelectedRecord(rowId, coerceFetchOptions(opts)),
1032
- docApi: {
1033
- getDocName: () => api.GristDocAPI.getDocName(),
1034
- listTables: () => api.GristDocAPI.listTables(),
1035
- fetchTable: (id) => api.GristDocAPI.fetchTable(id),
1036
- applyUserActions: (actions, options2) => api.GristDocAPI.applyUserActions(actions, options2),
1037
- getAccessToken: (opts) => api.GristDocAPI.getAccessToken(opts),
1038
- fetchSelectedTable: (opts) => fetchSelectedTableShaped(opts),
1039
- fetchSelectedRecord: (rowId, opts) => api.GristView.fetchSelectedRecord(rowId, coerceFetchOptions(opts))
1040
- },
1041
- get selectedTable() {
1042
- return makeTableOps(state.selection.tableId);
1043
- },
1044
- getTable(tableId) {
1045
- return makeTableOps(tableId ?? state.selection.tableId);
1046
- },
1047
- sectionApi: {
1048
- configure: (settings) => api.CustomSectionAPI.configure(settings),
1049
- mappings: () => api.CustomSectionAPI.mappings()
1050
- },
1051
- on(eventName, listener) {
1052
- let set = generic.get(eventName);
1053
- if (!set) generic.set(eventName, set = /* @__PURE__ */ new Set());
1054
- set.add(listener);
1055
- return () => set.delete(listener);
1056
- }
1057
- };
1058
- target.grist = grist;
1059
- return {
1060
- grist,
1061
- dispose() {
1062
- offBus();
1063
- const t = target;
1064
- if (t.grist === grist) delete t.grist;
1065
- recordCbs.clear();
1066
- recordsCbs.clear();
1067
- optionsCbs.clear();
1068
- newRecordCbs.clear();
1069
- generic.clear();
1070
- lastRecord = null;
1071
- lastRecords = null;
1072
- lastOptions = null;
1073
- lastNewRecord = void 0;
1074
- },
1075
- fireDataChange(tableId) {
1076
- bus.emit({ type: "data-change", tableId: tableId ?? state.selection.tableId });
1077
- },
1078
- fireCursor(rowId) {
1079
- const id = rowId === void 0 ? state.selection.rowId : rowId;
1080
- bus.emit({ type: "cursor-change", tableId: state.selection.tableId, rowId: id });
1081
- },
1082
- fireOptions() {
1083
- pushOptions();
1084
- },
1085
- fireTheme(message) {
1086
- bus.emit({ type: "theme-change", message });
1087
- },
1088
- emitInitialState() {
1089
- pushOptions();
1090
- void pushRecords().then(() => pushRecord(state.selection.rowId));
1091
- }
1092
- };
1093
- }
1094
- function columnsToRows(columnar) {
1095
- const cols = Object.keys(columnar);
1096
- if (cols.length === 0) return [];
1097
- const length = (columnar[cols[0]] ?? []).length;
1098
- const rows = [];
1099
- for (let i = 0; i < length; i++) {
1100
- const row = {};
1101
- for (const c of cols) row[c] = columnar[c][i];
1102
- rows.push(row);
1103
- }
1104
- return rows;
1105
- }
1106
- function parseFields(fields, _options) {
1107
- return { ...fields };
1108
- }
1109
- function coerceFetchOptions(opts) {
1110
- if (!opts) return void 0;
1111
- const format = opts.format === "rows" || opts.format === "columns" ? opts.format : void 0;
1112
- return { keepEncoded: opts.keepEncoded, format };
1113
- }
1114
- function logErr(err) {
1115
- console.error("[grist-emulator/inline]", err);
1116
- }
1117
- function installFakeIframeContext(target) {
1118
- try {
1119
- if (target.self !== target.top) return;
1120
- Object.defineProperty(target, "top", {
1121
- configurable: true,
1122
- get: () => ({})
1123
- });
1124
- } catch {
1125
- }
1126
- }
1127
- // Annotate the CommonJS export names for ESM import in node:
1128
- 0 && (module.exports = {
1129
- createIframeTransport,
1130
- createInlineTransport
1131
- });
1132
- //# sourceMappingURL=transports.cjs.map