grist-widget-sdk 0.4.0 → 0.5.1

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 (37) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +79 -208
  3. package/dist/app.cjs +186 -65
  4. package/dist/app.cjs.map +1 -1
  5. package/dist/app.d.cts +5 -100
  6. package/dist/app.d.ts +5 -100
  7. package/dist/app.js +4 -2
  8. package/dist/{chunk-O7NY46QY.js → chunk-MAPAWVQC.js} +88 -20
  9. package/dist/chunk-MAPAWVQC.js.map +1 -0
  10. package/dist/{chunk-B5ZZNLVS.js → chunk-OXA2VITC.js} +5 -1
  11. package/dist/chunk-OXA2VITC.js.map +1 -0
  12. package/dist/{chunk-P6VTEKWO.js → chunk-P5I5MRC6.js} +86 -10
  13. package/dist/chunk-P5I5MRC6.js.map +1 -0
  14. package/dist/{use-grist-BK0eke9K.d.cts → define-widget-B1FIvI-h.d.cts} +179 -104
  15. package/dist/{use-grist-C5DMZ3wU.d.ts → define-widget-B9gEtJP0.d.ts} +179 -104
  16. package/dist/emulator/testing.cjs +2393 -2243
  17. package/dist/emulator/testing.cjs.map +1 -1
  18. package/dist/emulator/testing.d.cts +27 -9
  19. package/dist/emulator/testing.d.ts +27 -9
  20. package/dist/emulator/testing.js +75 -55
  21. package/dist/emulator/testing.js.map +1 -1
  22. package/dist/emulator.cjs +4 -0
  23. package/dist/emulator.cjs.map +1 -1
  24. package/dist/emulator.d.cts +3 -3
  25. package/dist/emulator.d.ts +3 -3
  26. package/dist/emulator.js +1 -1
  27. package/dist/index.cjs +133 -67
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +2 -2
  30. package/dist/index.d.ts +2 -2
  31. package/dist/index.js +5 -1
  32. package/dist/mount-grist-widget-CkB-3iG_.d.ts +137 -0
  33. package/dist/mount-grist-widget-Dtelqao_.d.cts +137 -0
  34. package/package.json +1 -1
  35. package/dist/chunk-B5ZZNLVS.js.map +0 -1
  36. package/dist/chunk-O7NY46QY.js.map +0 -1
  37. package/dist/chunk-P6VTEKWO.js.map +0 -1
package/dist/app.d.cts CHANGED
@@ -1,103 +1,8 @@
1
- import * as react from 'react';
2
- import { ComponentType, ReactNode } from 'react';
3
- import { UseGristOptions } from './index.cjs';
1
+ export { D as DeployChannel, a as DeployPath, G as GristWidgetApp, b as GristWidgetAppProps, c as GristWidgetEntry, M as MountGristWidgetConfig, d as MountedGristWidget, e as deployChannelLabel, f as entryProps, m as mountGristWidget, p as parseDeployPath } from './mount-grist-widget-Dtelqao_.cjs';
2
+ import 'react';
3
+ import './define-widget-B1FIvI-h.cjs';
4
4
  import './types-DBStn0Dk.cjs';
5
5
 
6
- /**
7
- * Where a deployed build is being served from.
8
- *
9
- * A widget's deploy pipeline publishes the same build at its root and at
10
- * `/latest/`, a preview at `/dev/`, and each release at `/v<version>/`, all
11
- * under one base path (e.g. `/my-widget/` on GitHub Pages). Opened outside
12
- * Grist, the page tells them apart from `window.location.pathname` alone.
13
- */
14
- type DeployChannel = {
15
- kind: "latest";
16
- } | {
17
- kind: "dev";
18
- } | {
19
- kind: "version";
20
- version: string;
21
- };
22
- type DeployPath = {
23
- channel: DeployChannel;
24
- /**
25
- * The path the channels live under, always ending in `/`: the current
26
- * path without its channel segment. `"/my-widget/v1.2.0/"` gives
27
- * `"/my-widget/"`.
28
- */
29
- basePath: string;
30
- };
31
- /**
32
- * Parse a pathname into its deploy channel and base path. A path without a
33
- * channel segment (the deployed root, or a local dev server) is `latest`:
34
- * the deploy places the latest release at the root too.
35
- */
36
- declare function parseDeployPath(pathname: string): DeployPath;
37
- /** `"latest"`, `"dev"` or `"v1.2.0"`. */
38
- declare function deployChannelLabel(channel: DeployChannel): string;
39
-
40
- type GristWidgetAppProps = {
41
- /** The widget. A `React.lazy()` component works too: its code then loads only inside Grist. */
42
- App: ComponentType;
43
- /** The widget's `GRIST_OPTIONS`: access level, columns, and so on. */
44
- options: UseGristOptions;
45
- /**
46
- * Whether this is the local dev server. Pass `import.meta.env.DEV`.
47
- * Outside Grist it picks the local-dev page over the release page.
48
- */
49
- dev?: boolean;
50
- /**
51
- * Wraps the widget inside Grist, under {@link GristBoundary}. The default
52
- * lists what needs the user's attention (column mapping, access level,
53
- * failed writes) above the widget; `null` renders the widget alone.
54
- */
55
- Alerts?: ComponentType<{
56
- children: ReactNode;
57
- }> | null;
58
- /** Shown outside Grist on the local dev server. Defaults to a page pointing at `pnpm test` and the `dev` loop. */
59
- LocalDevPage?: ComponentType;
60
- /**
61
- * Shown outside Grist on a deployed URL (`/latest/`, `/dev/`, `/v<version>/`).
62
- * Defaults to a page linking every channel and version, with the URL to
63
- * paste into Grist.
64
- */
65
- ReleasePage?: ComponentType<{
66
- channel: DeployChannel;
67
- }>;
68
- };
69
- type MountGristWidgetConfig = GristWidgetAppProps & {
70
- /** The element to render into, or its CSS selector. Defaults to `#root`. */
71
- root?: Element | string;
72
- };
73
- type MountedGristWidget = {
74
- unmount: () => void;
75
- };
76
- /**
77
- * Render a widget into the page: everything `src/main.tsx` used to wire by
78
- * hand.
79
- *
80
- * ```tsx
81
- * import { mountGristWidget } from "grist-widget-sdk/app"
82
- * import "./index.css"
83
- * import App, { GRIST_OPTIONS } from "./App"
84
- *
85
- * mountGristWidget({ App, options: GRIST_OPTIONS, dev: import.meta.env.DEV })
86
- * ```
87
- *
88
- * Inside Grist, the widget renders in {@link GristWidgetProvider} and
89
- * {@link GristBoundary}, which gates on its mapped columns when it declares
90
- * any, and follows Grist's light/dark theme. Outside Grist, where there is
91
- * nothing to connect to, the page shows `LocalDevPage` on the dev server and
92
- * `ReleasePage` on a deployed URL.
93
- */
94
- declare function mountGristWidget(config: MountGristWidgetConfig): MountedGristWidget;
95
- /**
96
- * The tree {@link mountGristWidget} renders, as a component: for a test, or
97
- * for a page that manages its own React root.
98
- */
99
- declare function GristWidgetApp({ App, options, dev, Alerts, LocalDevPage, ReleasePage, }: GristWidgetAppProps): react.JSX.Element;
100
-
101
6
  type WidgetTheme = "light" | "dark" | "system";
102
7
  type ResolvedWidgetTheme = "light" | "dark";
103
8
  type UseThemeResult = {
@@ -141,5 +46,5 @@ type UseReleasedVersionsResult = {
141
46
  */
142
47
  declare function useReleasedVersions(pathname?: string): UseReleasedVersionsResult;
143
48
 
144
- export { GristWidgetApp, deployChannelLabel, mountGristWidget, parseDeployPath, useReleasedVersions, useTheme };
145
- export type { DeployChannel, DeployPath, GristWidgetAppProps, MountGristWidgetConfig, MountedGristWidget, ReleasedVersion, ResolvedWidgetTheme, UseReleasedVersionsResult, UseThemeResult, WidgetTheme };
49
+ export { useReleasedVersions, useTheme };
50
+ export type { ReleasedVersion, ResolvedWidgetTheme, UseReleasedVersionsResult, UseThemeResult, WidgetTheme };
package/dist/app.d.ts CHANGED
@@ -1,103 +1,8 @@
1
- import * as react from 'react';
2
- import { ComponentType, ReactNode } from 'react';
3
- import { UseGristOptions } from './index.js';
1
+ export { D as DeployChannel, a as DeployPath, G as GristWidgetApp, b as GristWidgetAppProps, c as GristWidgetEntry, M as MountGristWidgetConfig, d as MountedGristWidget, e as deployChannelLabel, f as entryProps, m as mountGristWidget, p as parseDeployPath } from './mount-grist-widget-CkB-3iG_.js';
2
+ import 'react';
3
+ import './define-widget-B9gEtJP0.js';
4
4
  import './types-DBStn0Dk.js';
5
5
 
6
- /**
7
- * Where a deployed build is being served from.
8
- *
9
- * A widget's deploy pipeline publishes the same build at its root and at
10
- * `/latest/`, a preview at `/dev/`, and each release at `/v<version>/`, all
11
- * under one base path (e.g. `/my-widget/` on GitHub Pages). Opened outside
12
- * Grist, the page tells them apart from `window.location.pathname` alone.
13
- */
14
- type DeployChannel = {
15
- kind: "latest";
16
- } | {
17
- kind: "dev";
18
- } | {
19
- kind: "version";
20
- version: string;
21
- };
22
- type DeployPath = {
23
- channel: DeployChannel;
24
- /**
25
- * The path the channels live under, always ending in `/`: the current
26
- * path without its channel segment. `"/my-widget/v1.2.0/"` gives
27
- * `"/my-widget/"`.
28
- */
29
- basePath: string;
30
- };
31
- /**
32
- * Parse a pathname into its deploy channel and base path. A path without a
33
- * channel segment (the deployed root, or a local dev server) is `latest`:
34
- * the deploy places the latest release at the root too.
35
- */
36
- declare function parseDeployPath(pathname: string): DeployPath;
37
- /** `"latest"`, `"dev"` or `"v1.2.0"`. */
38
- declare function deployChannelLabel(channel: DeployChannel): string;
39
-
40
- type GristWidgetAppProps = {
41
- /** The widget. A `React.lazy()` component works too: its code then loads only inside Grist. */
42
- App: ComponentType;
43
- /** The widget's `GRIST_OPTIONS`: access level, columns, and so on. */
44
- options: UseGristOptions;
45
- /**
46
- * Whether this is the local dev server. Pass `import.meta.env.DEV`.
47
- * Outside Grist it picks the local-dev page over the release page.
48
- */
49
- dev?: boolean;
50
- /**
51
- * Wraps the widget inside Grist, under {@link GristBoundary}. The default
52
- * lists what needs the user's attention (column mapping, access level,
53
- * failed writes) above the widget; `null` renders the widget alone.
54
- */
55
- Alerts?: ComponentType<{
56
- children: ReactNode;
57
- }> | null;
58
- /** Shown outside Grist on the local dev server. Defaults to a page pointing at `pnpm test` and the `dev` loop. */
59
- LocalDevPage?: ComponentType;
60
- /**
61
- * Shown outside Grist on a deployed URL (`/latest/`, `/dev/`, `/v<version>/`).
62
- * Defaults to a page linking every channel and version, with the URL to
63
- * paste into Grist.
64
- */
65
- ReleasePage?: ComponentType<{
66
- channel: DeployChannel;
67
- }>;
68
- };
69
- type MountGristWidgetConfig = GristWidgetAppProps & {
70
- /** The element to render into, or its CSS selector. Defaults to `#root`. */
71
- root?: Element | string;
72
- };
73
- type MountedGristWidget = {
74
- unmount: () => void;
75
- };
76
- /**
77
- * Render a widget into the page: everything `src/main.tsx` used to wire by
78
- * hand.
79
- *
80
- * ```tsx
81
- * import { mountGristWidget } from "grist-widget-sdk/app"
82
- * import "./index.css"
83
- * import App, { GRIST_OPTIONS } from "./App"
84
- *
85
- * mountGristWidget({ App, options: GRIST_OPTIONS, dev: import.meta.env.DEV })
86
- * ```
87
- *
88
- * Inside Grist, the widget renders in {@link GristWidgetProvider} and
89
- * {@link GristBoundary}, which gates on its mapped columns when it declares
90
- * any, and follows Grist's light/dark theme. Outside Grist, where there is
91
- * nothing to connect to, the page shows `LocalDevPage` on the dev server and
92
- * `ReleasePage` on a deployed URL.
93
- */
94
- declare function mountGristWidget(config: MountGristWidgetConfig): MountedGristWidget;
95
- /**
96
- * The tree {@link mountGristWidget} renders, as a component: for a test, or
97
- * for a page that manages its own React root.
98
- */
99
- declare function GristWidgetApp({ App, options, dev, Alerts, LocalDevPage, ReleasePage, }: GristWidgetAppProps): react.JSX.Element;
100
-
101
6
  type WidgetTheme = "light" | "dark" | "system";
102
7
  type ResolvedWidgetTheme = "light" | "dark";
103
8
  type UseThemeResult = {
@@ -141,5 +46,5 @@ type UseReleasedVersionsResult = {
141
46
  */
142
47
  declare function useReleasedVersions(pathname?: string): UseReleasedVersionsResult;
143
48
 
144
- export { GristWidgetApp, deployChannelLabel, mountGristWidget, parseDeployPath, useReleasedVersions, useTheme };
145
- export type { DeployChannel, DeployPath, GristWidgetAppProps, MountGristWidgetConfig, MountedGristWidget, ReleasedVersion, ResolvedWidgetTheme, UseReleasedVersionsResult, UseThemeResult, WidgetTheme };
49
+ export { useReleasedVersions, useTheme };
50
+ export type { ReleasedVersion, ResolvedWidgetTheme, UseReleasedVersionsResult, UseThemeResult, WidgetTheme };
package/dist/app.js CHANGED
@@ -1,16 +1,18 @@
1
1
  import {
2
2
  GristWidgetApp,
3
3
  deployChannelLabel,
4
+ entryProps,
4
5
  mountGristWidget,
5
6
  parseDeployPath,
6
7
  useReleasedVersions,
7
8
  useTheme
8
- } from "./chunk-P6VTEKWO.js";
9
- import "./chunk-O7NY46QY.js";
9
+ } from "./chunk-P5I5MRC6.js";
10
+ import "./chunk-MAPAWVQC.js";
10
11
  import "./chunk-4ZGVKGDF.js";
11
12
  export {
12
13
  GristWidgetApp,
13
14
  deployChannelLabel,
15
+ entryProps,
14
16
  mountGristWidget,
15
17
  parseDeployPath,
16
18
  useReleasedVersions,
@@ -528,10 +528,13 @@ function checkOne(base, value) {
528
528
  return ok(value);
529
529
  }
530
530
  }
531
+ function basesOf(type) {
532
+ return (type ?? "Any").split(",").map((t) => t.trim().split(":")[0]).filter(Boolean);
533
+ }
531
534
  function checkGristCell(type, value) {
532
535
  const error = formulaError(value);
533
536
  if (error) return bad(`formula error (${error})`);
534
- const bases = (type ?? "Any").split(",").map((t) => t.trim().split(":")[0]).filter(Boolean);
537
+ const bases = basesOf(type);
535
538
  if (bases.length === 0 || bases.includes("Any")) return ok(value === void 0 ? null : value);
536
539
  let first = null;
537
540
  for (const base of bases) {
@@ -541,6 +544,19 @@ function checkGristCell(type, value) {
541
544
  }
542
545
  return first;
543
546
  }
547
+ var LIST_BASES = ["ChoiceList", "RefList", "Attachments"];
548
+ function encodeGristCell(type, value) {
549
+ if (value === null || value === void 0) return value;
550
+ const bases = basesOf(type);
551
+ const accepts = (...names) => names.some((n) => bases.includes(n));
552
+ if (value instanceof Date) return accepts("Date", "DateTime") ? Math.floor(value.getTime() / 1e3) : value;
553
+ if (Array.isArray(value)) {
554
+ if (!accepts(...LIST_BASES) || value[0] === "L") return value;
555
+ return ["L", ...value.map((item) => rowIdOf(item) ?? item)];
556
+ }
557
+ if (accepts("Ref") && typeof value === "object") return rowIdOf(value) ?? value;
558
+ return value;
559
+ }
544
560
  var nameOf = (c) => typeof c === "string" ? c : c.name;
545
561
  var typeOf = (c) => typeof c === "string" ? void 0 : c.type;
546
562
  var isOptional = (c) => typeof c === "object" && c.optional === true;
@@ -819,16 +835,24 @@ function createGristApi(runtime) {
819
835
  throw err;
820
836
  }
821
837
  };
822
- const write = async (fn) => {
838
+ let running = 0;
839
+ let failure = null;
840
+ const write = (fn) => {
841
+ if (running++ === 0) failure = null;
823
842
  runtime.update({ actionStatus: "running", actionError: null });
824
- try {
825
- const out = await fn();
826
- runtime.update({ actionStatus: "idle" });
827
- return out;
828
- } catch (err) {
829
- runtime.update({ actionStatus: "error", actionError: message(err) });
830
- throw err;
831
- }
843
+ const done = (async () => {
844
+ try {
845
+ return await fn();
846
+ } catch (err) {
847
+ failure = message(err);
848
+ throw err;
849
+ } finally {
850
+ if (--running === 0) runtime.update(failure ? { actionStatus: "error", actionError: failure } : { actionStatus: "idle" });
851
+ }
852
+ })();
853
+ done.catch(() => {
854
+ });
855
+ return done;
832
856
  };
833
857
  const tableOps = (resolve) => ({
834
858
  getTableId: () => resolve().getTableId(),
@@ -973,14 +997,18 @@ function deriveColumnMappingStatus(columns, mappings) {
973
997
  if (mappings === null) return MAPPINGS_PENDING;
974
998
  return validateColumnMappings(columns, mappings);
975
999
  }
976
- function mapBackPatch(patch, mappings) {
1000
+ function mapBackPatch(patch, mappings, columns) {
977
1001
  const fields = {};
978
1002
  const skipped = [];
979
1003
  for (const [name, value] of Object.entries(patch)) {
980
1004
  if (value === void 0) continue;
981
1005
  const real = mappings[name];
982
- if (Array.isArray(real)) skipped.push(name);
983
- else fields[typeof real === "string" && real ? real : name] = value;
1006
+ if (Array.isArray(real)) {
1007
+ skipped.push(name);
1008
+ continue;
1009
+ }
1010
+ const declared = columns?.find((c) => nameOf(c) === name);
1011
+ fields[typeof real === "string" && real ? real : name] = declared ? encodeGristCell(typeOf(declared), value) : value;
984
1012
  }
985
1013
  return { fields, skipped };
986
1014
  }
@@ -1340,7 +1368,27 @@ function useMapped(state, options) {
1340
1368
  return { record: selected.value, records: mappedRecords, issues: issues.length ? issues : NO_ISSUES };
1341
1369
  }, [record, records, mappings, columns, schema]);
1342
1370
  }
1343
- function buildResult(state, mapped, connection, mapBack, resolveMappedColumnId) {
1371
+ function recordWrites(connection) {
1372
+ const { runtime, api } = connection;
1373
+ const fieldsOf = (patch) => {
1374
+ const { id: _id, ...rest } = patch;
1375
+ return mapBackPatch(rest, runtime.getState().mappings ?? EMPTY_MAPPINGS, runtime.options.columns).fields;
1376
+ };
1377
+ const updateRecord = ((a, b) => {
1378
+ const rowId = typeof a === "number" ? a : runtime.getState().record?.id;
1379
+ const patch = typeof a === "number" ? b ?? {} : a;
1380
+ if (typeof rowId !== "number") {
1381
+ return Promise.reject(new Error("updateRecord(): no row is selected. Pass the row id: updateRecord(rowId, patch)."));
1382
+ }
1383
+ return api.table.update({ id: rowId, fields: fieldsOf(patch) });
1384
+ });
1385
+ const addRecord = async (patch) => {
1386
+ const created = await api.table.create({ fields: fieldsOf(patch) });
1387
+ return (Array.isArray(created) ? created[0] : created).id;
1388
+ };
1389
+ return { updateRecord, addRecord };
1390
+ }
1391
+ function buildResult(state, mapped, connection, mapBack, resolveMappedColumnId, writes) {
1344
1392
  const { runtime, api } = connection;
1345
1393
  const status = deriveStatus(state);
1346
1394
  const columns = runtime.options.columns;
@@ -1361,6 +1409,8 @@ function buildResult(state, mapped, connection, mapBack, resolveMappedColumnId)
1361
1409
  mode: state.isNewRecord ? "new-row" : state.record ? "row" : "empty",
1362
1410
  resolveMappedColumnId,
1363
1411
  mapBack,
1412
+ updateRecord: writes.updateRecord,
1413
+ addRecord: writes.addRecord,
1364
1414
  currentTableId: state.currentTableId,
1365
1415
  actionStatus: state.actionStatus,
1366
1416
  actionError: state.actionError,
@@ -1383,7 +1433,7 @@ function useGristResult(connection) {
1383
1433
  );
1384
1434
  const mapBack = useCallback(
1385
1435
  (patch) => {
1386
- const { fields, skipped } = mapBackPatch(patch, mappings);
1436
+ const { fields, skipped } = mapBackPatch(patch, mappings, runtime.options.columns);
1387
1437
  const previous = runtime.getState().mapBackSkipped;
1388
1438
  if (previous.join("\0") !== skipped.join("\0")) runtime.update({ mapBackSkipped: skipped });
1389
1439
  return fields;
@@ -1391,9 +1441,10 @@ function useGristResult(connection) {
1391
1441
  [mappings, runtime]
1392
1442
  );
1393
1443
  const mapped = useMapped(state, runtime.options);
1444
+ const writes = useMemo(() => recordWrites(connection), [connection]);
1394
1445
  return useMemo(
1395
- () => buildResult(state, mapped, connection, mapBack, resolveMappedColumnId),
1396
- [state, mapped, connection, mapBack, resolveMappedColumnId]
1446
+ () => buildResult(state, mapped, connection, mapBack, resolveMappedColumnId, writes),
1447
+ [state, mapped, connection, mapBack, resolveMappedColumnId, writes]
1397
1448
  );
1398
1449
  }
1399
1450
  function useGrist(options) {
@@ -1435,6 +1486,20 @@ function useNearestGristState() {
1435
1486
  return { connection, state, cellIssues: issues };
1436
1487
  }
1437
1488
 
1489
+ // src/sdk/define-widget.ts
1490
+ function defineGristWidget(definition) {
1491
+ const { title, description, ...options } = definition;
1492
+ return {
1493
+ definition,
1494
+ options,
1495
+ metadata: { title, description },
1496
+ useGrist: () => useGrist(options)
1497
+ };
1498
+ }
1499
+ function isGristWidget(value) {
1500
+ return typeof value === "object" && value !== null && "definition" in value && "useGrist" in value;
1501
+ }
1502
+
1438
1503
  // src/sdk/components/grist-widget-provider.tsx
1439
1504
  import { useState } from "react";
1440
1505
  import { jsx } from "react/jsx-runtime";
@@ -1641,9 +1706,9 @@ function useGristSchema(options) {
1641
1706
  const [document2, setDocument] = useState3(null);
1642
1707
  const [loading, setLoading] = useState3(false);
1643
1708
  const [error, setError] = useState3(null);
1644
- const includeRowsForBuild = replicaRowMode === "schema-only" ? false : replicaRowMode === "schema+data" ? "full" : "samples";
1645
1709
  const load = useCallback3(async () => {
1646
1710
  if (!docApi) return;
1711
+ const includeRowsForBuild = replicaRowMode === "schema-only" ? false : replicaRowMode === "schema+data" ? "full" : "samples";
1647
1712
  setLoading(true);
1648
1713
  setError(null);
1649
1714
  try {
@@ -1813,18 +1878,21 @@ export {
1813
1878
  gristAttachmentCellValue,
1814
1879
  mergeGristAttachmentCellValue,
1815
1880
  isAccessInsufficientError,
1881
+ checkGristCell,
1882
+ encodeGristCell,
1816
1883
  deriveStatus,
1817
1884
  deriveColumnMappingStatus,
1818
- checkGristCell,
1819
1885
  parseGristWidgetLinkingInfo,
1820
1886
  resetGristForTests,
1821
1887
  useGrist,
1822
1888
  useGristOptional,
1823
1889
  useGristContext,
1824
1890
  useNearestGristState,
1891
+ defineGristWidget,
1892
+ isGristWidget,
1825
1893
  GristWidgetProvider,
1826
1894
  GristBoundary,
1827
1895
  useGristSchema,
1828
1896
  useWidgetMetadata
1829
1897
  };
1830
- //# sourceMappingURL=chunk-O7NY46QY.js.map
1898
+ //# sourceMappingURL=chunk-MAPAWVQC.js.map