grist-widget-sdk 0.2.1 → 0.2.15

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.
@@ -515,6 +515,35 @@ declare function useGristHandshake(options?: UseGristHandshakeOptions): UseGrist
515
515
  */
516
516
  declare function useGristCapabilities(options?: UseGristHandshakeOptions): GristCapabilities;
517
517
 
518
+ /**
519
+ * `useAmbientGristHandshake()` — observe an already-mounted handshake
520
+ * manager without ever creating one.
521
+ *
522
+ * `useGristHandshake()` / `<GristHandshakeProvider>` both mount their OWN
523
+ * manager, which calls the real `grist.ready()` independently of any
524
+ * `<GristWidgetProvider>` elsewhere on the page. That's fine for a widget's
525
+ * single app-root provider, but wrong for read-only UI (a connection-status
526
+ * chip, a debug overlay) that must share the *same* handshake as the real
527
+ * widget rather than run a second, competing one. This hook only reads
528
+ * whatever manager a `<GristWidgetProvider>` ancestor already published;
529
+ * it returns `null` outside one instead of falling back to creating its own.
530
+ */
531
+
532
+ type UseAmbientGristHandshakeResult = {
533
+ snapshot: GristWidgetSnapshot;
534
+ status: GristWidgetStatus;
535
+ error: string | null;
536
+ capabilities: GristCapabilities;
537
+ reload: () => void;
538
+ restart: () => void;
539
+ };
540
+ /**
541
+ * Returns `null` when mounted outside a `<GristWidgetProvider>` — there is
542
+ * no ambient manager to observe, and this hook intentionally never creates
543
+ * one. Mount inside `<GristWidgetProvider>` to get a live value.
544
+ */
545
+ declare function useAmbientGristHandshake(): UseAmbientGristHandshakeResult | null;
546
+
518
547
  type GristHandshakeContextValue = {
519
548
  snapshot: GristWidgetSnapshot;
520
549
  status: GristWidgetStatus;
@@ -787,4 +816,4 @@ type UseGristTableResult = {
787
816
  */
788
817
  declare function useGristTable(options?: UseGristTableOptions): UseGristTableResult;
789
818
 
790
- export { type GristActionsStatus, GristCapabilities, GristGeneration, type GristHandshakeContextValue, GristHandshakeProvider, type GristHandshakeProviderProps, GristMappingSource, type GristTableOpsStatus, GristTerminationReason, GristWidgetSnapshot, type UseGristAccessTokenOptions, type UseGristAccessTokenResult, type UseGristActionsOptions, type UseGristActionsResult, type UseGristHandshakeOptions, type UseGristHandshakeResult, type UseGristMappedRecordResult, type UseGristNewRecordResult, type UseGristReadyOptions, type UseGristReadyResult, type UseGristRecordSubscriptionResult, type UseGristRowsFromTableOptions, type UseGristRowsFromTableResult, type UseGristSectionResult, type UseGristTableOpsOptions, type UseGristTableOpsResult, type UseGristTableOptions, type UseGristTableResult, type UseGristWidgetOptionsConfig, type UseGristWidgetOptionsResult, useGristAccessToken, useGristActions, useGristAvailability, useGristCapabilities, useGristHandshake, useGristHandshakeContext, useGristHandshakeContextOptional, useGristMappedRecord, useGristNewRecord, useGristReady, useGristRecord, useGristRecords, useGristRowsFromTable, useGristSection, useGristTable, useGristTableOps, useGristWidgetOptions };
819
+ export { type GristActionsStatus, GristCapabilities, GristGeneration, type GristHandshakeContextValue, GristHandshakeProvider, type GristHandshakeProviderProps, GristMappingSource, type GristTableOpsStatus, GristTerminationReason, GristWidgetSnapshot, type UseAmbientGristHandshakeResult, type UseGristAccessTokenOptions, type UseGristAccessTokenResult, type UseGristActionsOptions, type UseGristActionsResult, type UseGristHandshakeOptions, type UseGristHandshakeResult, type UseGristMappedRecordResult, type UseGristNewRecordResult, type UseGristReadyOptions, type UseGristReadyResult, type UseGristRecordSubscriptionResult, type UseGristRowsFromTableOptions, type UseGristRowsFromTableResult, type UseGristSectionResult, type UseGristTableOpsOptions, type UseGristTableOpsResult, type UseGristTableOptions, type UseGristTableResult, type UseGristWidgetOptionsConfig, type UseGristWidgetOptionsResult, useAmbientGristHandshake, useGristAccessToken, useGristActions, useGristAvailability, useGristCapabilities, useGristHandshake, useGristHandshakeContext, useGristHandshakeContextOptional, useGristMappedRecord, useGristNewRecord, useGristReady, useGristRecord, useGristRecords, useGristRowsFromTable, useGristSection, useGristTable, useGristTableOps, useGristWidgetOptions };
@@ -515,6 +515,35 @@ declare function useGristHandshake(options?: UseGristHandshakeOptions): UseGrist
515
515
  */
516
516
  declare function useGristCapabilities(options?: UseGristHandshakeOptions): GristCapabilities;
517
517
 
518
+ /**
519
+ * `useAmbientGristHandshake()` — observe an already-mounted handshake
520
+ * manager without ever creating one.
521
+ *
522
+ * `useGristHandshake()` / `<GristHandshakeProvider>` both mount their OWN
523
+ * manager, which calls the real `grist.ready()` independently of any
524
+ * `<GristWidgetProvider>` elsewhere on the page. That's fine for a widget's
525
+ * single app-root provider, but wrong for read-only UI (a connection-status
526
+ * chip, a debug overlay) that must share the *same* handshake as the real
527
+ * widget rather than run a second, competing one. This hook only reads
528
+ * whatever manager a `<GristWidgetProvider>` ancestor already published;
529
+ * it returns `null` outside one instead of falling back to creating its own.
530
+ */
531
+
532
+ type UseAmbientGristHandshakeResult = {
533
+ snapshot: GristWidgetSnapshot;
534
+ status: GristWidgetStatus;
535
+ error: string | null;
536
+ capabilities: GristCapabilities;
537
+ reload: () => void;
538
+ restart: () => void;
539
+ };
540
+ /**
541
+ * Returns `null` when mounted outside a `<GristWidgetProvider>` — there is
542
+ * no ambient manager to observe, and this hook intentionally never creates
543
+ * one. Mount inside `<GristWidgetProvider>` to get a live value.
544
+ */
545
+ declare function useAmbientGristHandshake(): UseAmbientGristHandshakeResult | null;
546
+
518
547
  type GristHandshakeContextValue = {
519
548
  snapshot: GristWidgetSnapshot;
520
549
  status: GristWidgetStatus;
@@ -787,4 +816,4 @@ type UseGristTableResult = {
787
816
  */
788
817
  declare function useGristTable(options?: UseGristTableOptions): UseGristTableResult;
789
818
 
790
- export { type GristActionsStatus, GristCapabilities, GristGeneration, type GristHandshakeContextValue, GristHandshakeProvider, type GristHandshakeProviderProps, GristMappingSource, type GristTableOpsStatus, GristTerminationReason, GristWidgetSnapshot, type UseGristAccessTokenOptions, type UseGristAccessTokenResult, type UseGristActionsOptions, type UseGristActionsResult, type UseGristHandshakeOptions, type UseGristHandshakeResult, type UseGristMappedRecordResult, type UseGristNewRecordResult, type UseGristReadyOptions, type UseGristReadyResult, type UseGristRecordSubscriptionResult, type UseGristRowsFromTableOptions, type UseGristRowsFromTableResult, type UseGristSectionResult, type UseGristTableOpsOptions, type UseGristTableOpsResult, type UseGristTableOptions, type UseGristTableResult, type UseGristWidgetOptionsConfig, type UseGristWidgetOptionsResult, useGristAccessToken, useGristActions, useGristAvailability, useGristCapabilities, useGristHandshake, useGristHandshakeContext, useGristHandshakeContextOptional, useGristMappedRecord, useGristNewRecord, useGristReady, useGristRecord, useGristRecords, useGristRowsFromTable, useGristSection, useGristTable, useGristTableOps, useGristWidgetOptions };
819
+ export { type GristActionsStatus, GristCapabilities, GristGeneration, type GristHandshakeContextValue, GristHandshakeProvider, type GristHandshakeProviderProps, GristMappingSource, type GristTableOpsStatus, GristTerminationReason, GristWidgetSnapshot, type UseAmbientGristHandshakeResult, type UseGristAccessTokenOptions, type UseGristAccessTokenResult, type UseGristActionsOptions, type UseGristActionsResult, type UseGristHandshakeOptions, type UseGristHandshakeResult, type UseGristMappedRecordResult, type UseGristNewRecordResult, type UseGristReadyOptions, type UseGristReadyResult, type UseGristRecordSubscriptionResult, type UseGristRowsFromTableOptions, type UseGristRowsFromTableResult, type UseGristSectionResult, type UseGristTableOpsOptions, type UseGristTableOpsResult, type UseGristTableOptions, type UseGristTableResult, type UseGristWidgetOptionsConfig, type UseGristWidgetOptionsResult, useAmbientGristHandshake, useGristAccessToken, useGristActions, useGristAvailability, useGristCapabilities, useGristHandshake, useGristHandshakeContext, useGristHandshakeContextOptional, useGristMappedRecord, useGristNewRecord, useGristReady, useGristRecord, useGristRecords, useGristRowsFromTable, useGristSection, useGristTable, useGristTableOps, useGristWidgetOptions };
package/dist/advanced.js CHANGED
@@ -3,21 +3,24 @@ import {
3
3
  fetchWithGristAuth,
4
4
  getGristAccessToken,
5
5
  useGristCore,
6
+ useGristManagerOptional,
6
7
  useGristReady,
7
8
  useGristWidgetOptionsFromContext,
8
9
  useRpcHeartbeatCoalesce
9
- } from "./chunk-BNBV24WM.js";
10
+ } from "./chunk-ER6UWHZA.js";
10
11
  import {
11
12
  createGristHandshakeManager,
12
13
  deriveCapabilities,
13
14
  deriveErrorMessage,
14
15
  deriveStatus,
16
+ ensureGristReady,
15
17
  initialGristSnapshot,
16
18
  newRecordEvent,
17
19
  optionsEvent,
18
20
  recordEvent,
19
- recordsEvent
20
- } from "./chunk-XE2SKNLH.js";
21
+ recordsEvent,
22
+ resetGristReadySingleton
23
+ } from "./chunk-KOVYBNPJ.js";
21
24
  import {
22
25
  tableDataToRows
23
26
  } from "./chunk-JASMM2YC.js";
@@ -43,7 +46,17 @@ function useGristHandshake(options = {}) {
43
46
  optionsRef.current = options;
44
47
  const managerRef = useRef(null);
45
48
  if (managerRef.current === null) {
46
- managerRef.current = createGristHandshakeManager(options);
49
+ managerRef.current = createGristHandshakeManager({
50
+ ...options,
51
+ negotiate: {
52
+ readyImpl: (payload) => ensureGristReady(payload),
53
+ ...options.negotiate
54
+ },
55
+ onBeforeReload: () => {
56
+ resetGristReadySingleton();
57
+ options.onBeforeReload?.();
58
+ }
59
+ });
47
60
  }
48
61
  const manager = managerRef.current;
49
62
  useEffect(() => {
@@ -81,21 +94,56 @@ function useGristCapabilities(options = {}) {
81
94
  return useGristHandshake(options).capabilities;
82
95
  }
83
96
 
97
+ // src/sdk/low-level-hooks/use-ambient-grist-handshake.ts
98
+ import { useMemo as useMemo2, useSyncExternalStore as useSyncExternalStore2 } from "react";
99
+ var noopSubscribe = () => () => {
100
+ };
101
+ var getInitialSnapshot = () => initialGristSnapshot();
102
+ function useAmbientGristHandshake() {
103
+ const manager = useGristManagerOptional();
104
+ const snapshot = useSyncExternalStore2(
105
+ manager?.subscribe ?? noopSubscribe,
106
+ manager?.getSnapshot ?? getInitialSnapshot,
107
+ getInitialSnapshot
108
+ );
109
+ return useMemo2(() => {
110
+ if (!manager) return null;
111
+ return {
112
+ snapshot,
113
+ status: deriveStatus(snapshot),
114
+ error: deriveErrorMessage(snapshot),
115
+ capabilities: deriveCapabilities(snapshot),
116
+ reload: manager.reload,
117
+ restart: manager.restart
118
+ };
119
+ }, [manager, snapshot]);
120
+ }
121
+
84
122
  // src/sdk/components/grist-handshake-provider.tsx
85
123
  import {
86
124
  createContext,
87
125
  useContext,
88
126
  useEffect as useEffect2,
89
- useMemo as useMemo2,
127
+ useMemo as useMemo3,
90
128
  useRef as useRef2,
91
- useSyncExternalStore as useSyncExternalStore2
129
+ useSyncExternalStore as useSyncExternalStore3
92
130
  } from "react";
93
131
  import { jsx } from "react/jsx-runtime";
94
132
  var GristHandshakeReactContext = createContext(null);
95
133
  function GristHandshakeProvider({ options, children }) {
96
134
  const managerRef = useRef2(null);
97
135
  if (managerRef.current === null) {
98
- managerRef.current = createGristHandshakeManager(options ?? {});
136
+ managerRef.current = createGristHandshakeManager({
137
+ ...options,
138
+ negotiate: {
139
+ readyImpl: (payload) => ensureGristReady(payload),
140
+ ...options?.negotiate
141
+ },
142
+ onBeforeReload: () => {
143
+ resetGristReadySingleton();
144
+ options?.onBeforeReload?.();
145
+ }
146
+ });
99
147
  }
100
148
  const manager = managerRef.current;
101
149
  useEffect2(() => {
@@ -104,12 +152,12 @@ function GristHandshakeProvider({ options, children }) {
104
152
  manager.stop();
105
153
  };
106
154
  }, [manager]);
107
- const snapshot = useSyncExternalStore2(
155
+ const snapshot = useSyncExternalStore3(
108
156
  manager.subscribe,
109
157
  manager.getSnapshot,
110
158
  initialGristSnapshot
111
159
  );
112
- const value = useMemo2(
160
+ const value = useMemo3(
113
161
  () => ({
114
162
  snapshot,
115
163
  status: deriveStatus(snapshot),
@@ -608,7 +656,7 @@ function useGristSection(options) {
608
656
  }
609
657
 
610
658
  // src/sdk/mid-level-hooks/use-grist-widget-options.ts
611
- import { useCallback as useCallback7, useEffect as useEffect10, useMemo as useMemo3, useRef as useRef7, useState as useState10 } from "react";
659
+ import { useCallback as useCallback7, useEffect as useEffect10, useMemo as useMemo4, useRef as useRef7, useState as useState10 } from "react";
612
660
  function mergeWithDefaults(defaults, stored, namespace) {
613
661
  if (stored === null || stored === void 0) return { ...defaults };
614
662
  const source = namespace ? stored[namespace] : stored;
@@ -700,7 +748,7 @@ function useGristWidgetOptions(config) {
700
748
  setOptionsState(next);
701
749
  await flushWrite(next);
702
750
  }, [flushWrite]);
703
- return useMemo3(
751
+ return useMemo4(
704
752
  () => ({
705
753
  options,
706
754
  loading,
@@ -803,6 +851,7 @@ function useGristTable(options) {
803
851
  }
804
852
  export {
805
853
  GristHandshakeProvider,
854
+ useAmbientGristHandshake,
806
855
  useGristAccessToken,
807
856
  useGristActions,
808
857
  useGristAvailability,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sdk/low-level-hooks/use-grist-availability.ts","../src/sdk/low-level-hooks/use-grist-handshake.ts","../src/sdk/components/grist-handshake-provider.tsx","../src/sdk/low-level-hooks/use-grist-record.ts","../src/sdk/low-level-hooks/use-grist-records.ts","../src/sdk/low-level-hooks/use-grist-new-record.ts","../src/sdk/mid-level-hooks/use-grist-actions.ts","../src/sdk/mid-level-hooks/use-grist-mapped-record.ts","../src/sdk/mid-level-hooks/use-grist-table-ops.ts","../src/sdk/mid-level-hooks/use-grist-rows-from-table.ts","../src/sdk/mid-level-hooks/use-grist-access-token.ts","../src/sdk/mid-level-hooks/use-grist-section.ts","../src/sdk/mid-level-hooks/use-grist-widget-options.ts","../src/sdk/use-grist-table.ts"],"sourcesContent":["import { useGristCore, type UseGristCoreOptions } from \"../internal/hooks/use-grist-core\"\n\nexport type UseGristAvailabilityOptions = Pick<\n UseGristCoreOptions,\n \"availabilityMaxAttempts\" | \"availabilityIntervalMs\" | \"logWhenNotEmbedded\"\n>\n\n/**\n * Handshake-backed availability — projects `isAvailable` from the FSM.\n */\nexport function useGristAvailability(options?: UseGristAvailabilityOptions): boolean | null {\n const { isAvailable } = useGristCore(options)\n return isAvailable\n}\n","/**\n * `useGristHandshake()` — React adapter over {@link GristHandshakeManager}.\n *\n * Exposes the full {@link GristWidgetSnapshot} plus derived\n * {@link GristCapabilities}, plus `reload()` / `restart()` controls.\n *\n * Identity stability\n * ------------------\n * The snapshot reference changes whenever the reducer produces a new\n * snapshot. Capabilities are memoized by snapshot identity, so consumers\n * branching on a single capability (e.g. `canWriteRecords`) avoid extra\n * re-renders unless that boolean actually flips.\n *\n * SSR-safe: `getServerSnapshot` returns the initial snapshot deterministically.\n */\n\nimport { useEffect, useMemo, useRef, useSyncExternalStore } from \"react\"\n\nimport {\n deriveCapabilities,\n deriveErrorMessage,\n deriveStatus,\n initialGristSnapshot,\n type GristCapabilities,\n type GristWidgetSnapshot,\n type GristWidgetStatus,\n} from \"../internal/handshake\"\nimport {\n createGristHandshakeManager,\n type ManagerControls,\n type ManagerOptions,\n} from \"../internal/handshake/manager\"\n\nexport type UseGristHandshakeOptions = ManagerOptions\n\nexport type UseGristHandshakeResult = {\n snapshot: GristWidgetSnapshot\n status: GristWidgetStatus\n error: string | null\n capabilities: GristCapabilities\n reload: () => void\n restart: () => void\n}\n\n/**\n * Mount a handshake manager local to the component subtree. Multiple\n * widgets in the same page should NOT call this in parallel — instead,\n * mount a single `<GristWidgetProvider>` at the app root.\n *\n * In tests, pass `options.env` (see `createTestEnvironment`) to drive the\n * machine with a virtual clock.\n */\nexport function useGristHandshake(options: UseGristHandshakeOptions = {}): UseGristHandshakeResult {\n // Memoize the manager so it survives re-renders. Caller is responsible for\n // passing stable options; in practice this is set once at the provider.\n const optionsRef = useRef(options)\n optionsRef.current = options\n const managerRef = useRef<ManagerControls | null>(null)\n if (managerRef.current === null) {\n managerRef.current = createGristHandshakeManager(options)\n }\n const manager = managerRef.current\n\n useEffect(() => {\n manager.start()\n return () => {\n manager.stop()\n }\n }, [manager])\n\n const snapshot = useSyncExternalStore(\n manager.subscribe,\n manager.getSnapshot,\n initialGristSnapshot\n )\n\n const projected = useMemo(\n () => ({\n status: deriveStatus(snapshot),\n error: deriveErrorMessage(snapshot),\n capabilities: deriveCapabilities(snapshot),\n }),\n [snapshot]\n )\n\n return useMemo(\n () => ({\n snapshot,\n status: projected.status,\n error: projected.error,\n capabilities: projected.capabilities,\n reload: manager.reload,\n restart: manager.restart,\n }),\n [snapshot, projected, manager]\n )\n}\n\n/**\n * Convenience hook — equivalent to `useGristHandshake().capabilities` but\n * skips returning the full snapshot. Intended for leaf components that only\n * need to gate UI on `canRender` / `canWriteRecords` / etc.\n */\nexport function useGristCapabilities(\n options: UseGristHandshakeOptions = {}\n): GristCapabilities {\n return useGristHandshake(options).capabilities\n}\n","/**\n * `<GristHandshakeProvider>` — opt-in React provider that mounts a single\n * {@link GristHandshakeManager} at the app root and broadcasts its snapshot\n * to all descendants.\n *\n * Use this provider when you want the full SOTA handshake model (snapshot +\n * capabilities + heartbeat + reload/restart) without the slice composition\n * of `<GristWidgetProvider>`. The two providers are independent:\n *\n * - `<GristWidgetProvider>` (legacy) — full SDK surface, hooks slices.\n * - `<GristHandshakeProvider>` (new) — handshake state machine only.\n *\n * Both can coexist if you need both surfaces; `grist.ready` is deduped by\n * the SDK's ready singleton so concurrent calls are safe.\n */\n\nimport {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n type ReactNode,\n} from \"react\"\n\nimport {\n createGristHandshakeManager,\n type ManagerControls,\n type ManagerOptions,\n} from \"../internal/handshake/manager\"\nimport {\n deriveCapabilities,\n deriveErrorMessage,\n deriveStatus,\n initialGristSnapshot,\n type GristCapabilities,\n type GristWidgetSnapshot,\n type GristWidgetStatus,\n} from \"../internal/handshake\"\n\nexport type GristHandshakeContextValue = {\n snapshot: GristWidgetSnapshot\n status: GristWidgetStatus\n error: string | null\n capabilities: GristCapabilities\n reload: () => void\n restart: () => void\n recordRpcSuccess: () => void\n recordRpcFailure: () => void\n}\n\nconst GristHandshakeReactContext = createContext<GristHandshakeContextValue | null>(null)\n\nexport type GristHandshakeProviderProps = {\n options?: ManagerOptions\n children: ReactNode\n}\n\n/**\n * Mount a single {@link GristHandshakeManager} for the React subtree and\n * expose its snapshot via context.\n *\n * The manager is created **once** on first mount; the `options` prop is\n * captured at that time. To re-create the manager with new options, unmount\n * and re-mount the provider (e.g. via a `key`).\n */\nexport function GristHandshakeProvider({ options, children }: GristHandshakeProviderProps) {\n // Manager is allocated once. Subsequent option changes are intentionally\n // ignored — handshake configuration should be stable for the lifetime of\n // the widget.\n const managerRef = useRef<ManagerControls | null>(null)\n if (managerRef.current === null) {\n managerRef.current = createGristHandshakeManager(options ?? {})\n }\n const manager = managerRef.current\n\n useEffect(() => {\n manager.start()\n return () => {\n manager.stop()\n }\n }, [manager])\n\n const snapshot = useSyncExternalStore(\n manager.subscribe,\n manager.getSnapshot,\n initialGristSnapshot\n )\n\n const value = useMemo<GristHandshakeContextValue>(\n () => ({\n snapshot,\n status: deriveStatus(snapshot),\n error: deriveErrorMessage(snapshot),\n capabilities: deriveCapabilities(snapshot),\n reload: manager.reload,\n restart: manager.restart,\n recordRpcSuccess: manager.recordRpcSuccess,\n recordRpcFailure: manager.recordRpcFailure,\n }),\n [snapshot, manager]\n )\n\n return (\n <GristHandshakeReactContext.Provider value={value}>\n {children}\n </GristHandshakeReactContext.Provider>\n )\n}\n\n/**\n * Read the handshake context. Throws if no `<GristHandshakeProvider>` is\n * mounted in the tree.\n *\n * Use {@link useGristHandshakeContextOptional} when the provider is optional\n * (e.g. when the same component is sometimes used standalone).\n */\nexport function useGristHandshakeContext(): GristHandshakeContextValue {\n const ctx = useContext(GristHandshakeReactContext)\n if (!ctx) {\n throw new Error(\n \"useGristHandshakeContext() must be used inside <GristHandshakeProvider>\"\n )\n }\n return ctx\n}\n\n/** Non-throwing variant. */\nexport function useGristHandshakeContextOptional(): GristHandshakeContextValue | null {\n return useContext(GristHandshakeReactContext)\n}\n","import { useEffect, useRef, useState } from \"react\"\n\nimport { recordEvent } from \"../internal/subscriptions\"\nimport type { GristReadyOptions, GristWidgetColumnMap } from \"../types\"\nimport { useGristReady } from \"./use-grist-ready\"\n\nexport type UseGristRecordSubscriptionResult = {\n loading: boolean\n error: string | null\n /** Latest mappings from `grist.onRecord` (logical name → real column id, or `string[]` for `allowMultiple`). */\n mappings: GristWidgetColumnMap | null\n}\n\n// Subscription errors are logged inside the singleton; nothing surfaces here.\n\n/**\n * Subscribes to the currently-selected row in the widget's section.\n *\n * The Grist event is shared across all hook instances (no leak).\n */\nexport function useGristRecord(\n cb: (record: Record<string, unknown> | null, mappings: GristWidgetColumnMap | null) => void,\n options?: GristReadyOptions\n): UseGristRecordSubscriptionResult {\n const cbRef = useRef(cb)\n useEffect(() => {\n cbRef.current = cb\n }, [cb])\n\n const [mappings, setMappings] = useState<GristWidgetColumnMap | null>(null)\n const { docApi, error: readyError } = useGristReady({\n requiredAccess: options?.requiredAccess ?? \"read table\",\n columns: options?.columns,\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n })\n\n useEffect(() => {\n if (!docApi) return\n return recordEvent.subscribe(({ record, mappings: nextMappings }) => {\n setMappings(nextMappings)\n cbRef.current(record, nextMappings)\n })\n }, [docApi])\n\n return {\n loading: docApi === null && !readyError,\n error: readyError,\n mappings,\n }\n}\n","import { useEffect, useRef, useState } from \"react\"\n\nimport { recordsEvent } from \"../internal/subscriptions\"\nimport type { GristReadyOptions, GristWidgetColumnMap } from \"../types\"\nimport { useGristReady } from \"./use-grist-ready\"\nimport type { UseGristRecordSubscriptionResult } from \"./use-grist-record\"\n\n/**\n * Subscribes to the full row set visible in the widget's section\n * (filters, sorts, and linked rows applied).\n */\nexport function useGristRecords(\n cb: (records: Record<string, unknown>[], mappings: GristWidgetColumnMap | null) => void,\n options?: GristReadyOptions\n): UseGristRecordSubscriptionResult {\n const cbRef = useRef(cb)\n useEffect(() => {\n cbRef.current = cb\n }, [cb])\n\n const [mappings, setMappings] = useState<GristWidgetColumnMap | null>(null)\n const { docApi, error: readyError } = useGristReady({\n requiredAccess: options?.requiredAccess ?? \"read table\",\n columns: options?.columns,\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n })\n\n useEffect(() => {\n if (!docApi) return\n return recordsEvent.subscribe(({ records, mappings: nextMappings }) => {\n setMappings(nextMappings)\n cbRef.current(records, nextMappings)\n })\n }, [docApi])\n\n return {\n loading: docApi === null && !readyError,\n error: readyError,\n mappings,\n }\n}\n","import { useEffect, useRef, useState } from \"react\"\n\nimport { newRecordEvent } from \"../internal/subscriptions\"\nimport type { GristReadyOptions, GristWidgetColumnMap } from \"../types\"\nimport { useGristReady } from \"./use-grist-ready\"\n\nexport type UseGristNewRecordResult = {\n /** True when the user has selected the blank \"new row\" placeholder. */\n isNewRecord: boolean\n /** Mappings reported by Grist alongside the new-record event. */\n mappings: GristWidgetColumnMap | null\n loading: boolean\n error: string | null\n}\n\n/**\n * Subscribes to `grist.onNewRecord` — fires when the user selects the blank\n * row in the linked section. Useful for form-style widgets that need to\n * switch into \"create\" mode.\n *\n * `isNewRecord` is reset to `false` whenever a real `onRecord` payload arrives,\n * so callers don't need to manage that themselves.\n */\nexport function useGristNewRecord(options?: GristReadyOptions): UseGristNewRecordResult {\n const { docApi, error: readyError } = useGristReady({\n requiredAccess: options?.requiredAccess ?? \"read table\",\n columns: options?.columns,\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n })\n\n const [isNewRecord, setIsNewRecord] = useState(false)\n const [mappings, setMappings] = useState<GristWidgetColumnMap | null>(null)\n const subscribedRef = useRef(false)\n\n useEffect(() => {\n if (!docApi || subscribedRef.current) return\n if (typeof grist.onNewRecord !== \"function\") return\n subscribedRef.current = true\n return newRecordEvent.subscribe(({ mappings: nextMappings }) => {\n setIsNewRecord(true)\n setMappings(nextMappings)\n })\n }, [docApi])\n\n return {\n isNewRecord,\n mappings,\n loading: docApi === null && !readyError,\n error: readyError,\n }\n}\n","import { useCallback, useState } from \"react\"\n\nimport {\n gristAddRecordAction,\n gristBulkAddRecordAction,\n gristBulkRemoveRecordAction,\n gristBulkUpdateRecordAction,\n gristRemoveRecordAction,\n gristUpdateRecordAction,\n type GristUserActionTuple,\n} from \"../helpers/grist-user-actions\"\nimport { useRpcHeartbeatCoalesce } from \"../internal/hooks/use-rpc-heartbeat-coalesce\"\nimport { useGristReady } from \"../low-level-hooks/use-grist-ready\"\nimport type { GristApplyUserActionsOptions, GristReadyOptions } from \"../types\"\n\nexport type GristActionsStatus = \"idle\" | \"running\" | \"error\"\n\nexport type UseGristActionsOptions = Pick<\n GristReadyOptions,\n \"requiredAccess\" | \"columns\" | \"allowSelectBy\" | \"hasCustomOptions\" | \"onEditOptions\"\n>\n\nexport type UseGristActionsResult = {\n status: GristActionsStatus\n error: string | null\n /** Apply raw user actions. `applyOptions.desc` is shown in the document undo stack. */\n apply: (actions: GristUserActionTuple[], applyOptions?: GristApplyUserActionsOptions) => Promise<unknown>\n updateRecord: (\n tableId: string,\n recordId: number,\n patch: Record<string, unknown>,\n applyOptions?: GristApplyUserActionsOptions\n ) => Promise<unknown>\n addRecord: (\n tableId: string,\n values: Record<string, unknown>,\n applyOptions?: GristApplyUserActionsOptions\n ) => Promise<unknown>\n removeRecord: (\n tableId: string,\n recordId: number,\n applyOptions?: GristApplyUserActionsOptions\n ) => Promise<unknown>\n bulkAddRecord: (\n tableId: string,\n values: Record<string, unknown[]>,\n applyOptions?: GristApplyUserActionsOptions\n ) => Promise<unknown>\n bulkUpdateRecord: (\n tableId: string,\n rowIds: number[],\n columnarPatch: Record<string, unknown[]>,\n applyOptions?: GristApplyUserActionsOptions\n ) => Promise<unknown>\n bulkRemoveRecord: (\n tableId: string,\n rowIds: number[],\n applyOptions?: GristApplyUserActionsOptions\n ) => Promise<unknown>\n}\n\nexport function useGristActions(options?: UseGristActionsOptions): UseGristActionsResult {\n const requiredAccess = options?.requiredAccess ?? \"full\"\n const { docApi, error: readyError } = useGristReady({\n requiredAccess,\n columns: options?.columns,\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n })\n const [status, setStatus] = useState<GristActionsStatus>(\"idle\")\n const [actionError, setActionError] = useState<string | null>(null)\n const coalesceRpc = useRpcHeartbeatCoalesce()\n\n const apply = useCallback(\n async (actions: GristUserActionTuple[], applyOptions?: GristApplyUserActionsOptions): Promise<unknown> => {\n if (!docApi) throw new Error(\"Grist docApi is not ready\")\n setStatus(\"running\")\n setActionError(null)\n try {\n const out = await coalesceRpc(() => docApi.applyUserActions(actions, applyOptions))\n setStatus(\"idle\")\n return out\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n setActionError(message)\n setStatus(\"error\")\n throw err\n }\n },\n [docApi, coalesceRpc]\n )\n\n const updateRecord = useCallback(\n (tableId: string, recordId: number, patch: Record<string, unknown>, applyOptions?: GristApplyUserActionsOptions) =>\n apply([gristUpdateRecordAction(tableId, recordId, patch)], applyOptions),\n [apply]\n )\n\n const addRecord = useCallback(\n (tableId: string, values: Record<string, unknown>, applyOptions?: GristApplyUserActionsOptions) =>\n apply([gristAddRecordAction(tableId, values)], applyOptions),\n [apply]\n )\n\n const removeRecord = useCallback(\n (tableId: string, recordId: number, applyOptions?: GristApplyUserActionsOptions) =>\n apply([gristRemoveRecordAction(tableId, recordId)], applyOptions),\n [apply]\n )\n\n const bulkAddRecord = useCallback(\n (tableId: string, values: Record<string, unknown[]>, applyOptions?: GristApplyUserActionsOptions) =>\n apply([gristBulkAddRecordAction(tableId, values)], applyOptions),\n [apply]\n )\n\n const bulkUpdateRecord = useCallback(\n (tableId: string, rowIds: number[], columnarPatch: Record<string, unknown[]>, applyOptions?: GristApplyUserActionsOptions) =>\n apply([gristBulkUpdateRecordAction(tableId, rowIds, columnarPatch)], applyOptions),\n [apply]\n )\n\n const bulkRemoveRecord = useCallback(\n (tableId: string, rowIds: number[], applyOptions?: GristApplyUserActionsOptions) =>\n apply([gristBulkRemoveRecordAction(tableId, rowIds)], applyOptions),\n [apply]\n )\n\n return {\n status: readyError ? \"error\" : status,\n error: readyError ?? actionError,\n apply,\n updateRecord,\n addRecord,\n removeRecord,\n bulkAddRecord,\n bulkUpdateRecord,\n bulkRemoveRecord,\n }\n}\n","import { useCallback, useEffect, useState } from \"react\"\n\nimport { recordEvent } from \"../internal/subscriptions\"\nimport { useGristReady } from \"../low-level-hooks/use-grist-ready\"\nimport type { GristReadyOptions, GristWidgetColumnMap } from \"../types\"\n\nexport type UseGristMappedRecordResult<T> = {\n rawRecord: Record<string, unknown> | null\n mappedRecord: T | null\n /** Current column mappings reported by Grist. */\n mappings: GristWidgetColumnMap | null\n loading: boolean\n error: string | null\n /**\n * Reverse-map a logical patch (`{ logicalName: value }`) into a real-column\n * patch (`{ realColId: value }`) ready for `applyUserActions` /\n * `useGristTableOps.update`.\n * Falls back to `grist.mapColumnNamesBack` when present, otherwise resolves\n * names manually from `mappings` (single-mapped columns only).\n */\n mapBack: (patch: Partial<T>) => Record<string, unknown>\n /** Resolve a single logical name to its current real column id. */\n resolveColumnId: (logicalName: keyof T & string) => string | undefined\n}\n\nfunction manualMapBack<T>(patch: Partial<T>, mappings: GristWidgetColumnMap | null): Record<string, unknown> {\n if (!mappings) return { ...(patch as Record<string, unknown>) }\n const out: Record<string, unknown> = {}\n for (const [name, value] of Object.entries(patch as Record<string, unknown>)) {\n const target = mappings[name]\n if (Array.isArray(target)) {\n // allowMultiple: cannot decide which underlying column to write — skip and warn.\n if (typeof console !== \"undefined\") {\n console.warn(`[lib/grist] mapBack: cannot reverse-map allowMultiple field \"${name}\" without grist.mapColumnNamesBack`)\n }\n continue\n }\n out[target ?? name] = value\n }\n return out\n}\n\n/**\n * Subscribes to the selected row, applies `grist.mapColumnNames` so widget code\n * sees logical column names, and exposes `mapBack` for safe writes.\n */\nexport function useGristMappedRecord<T = Record<string, unknown>>(\n options?: GristReadyOptions\n): UseGristMappedRecordResult<T> {\n const requiredAccess = options?.requiredAccess ?? \"read table\"\n const { docApi, error: readyError } = useGristReady({\n requiredAccess,\n columns: options?.columns,\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n })\n const [rawRecord, setRawRecord] = useState<Record<string, unknown> | null>(null)\n const [mappedRecord, setMappedRecord] = useState<T | null>(null)\n const [mappings, setMappings] = useState<GristWidgetColumnMap | null>(null)\n\n useEffect(() => {\n if (!docApi) return\n return recordEvent.subscribe(({ record, mappings: nextMappings }) => {\n setRawRecord(record)\n setMappings(nextMappings)\n if (!record) {\n setMappedRecord(null)\n return\n }\n if (typeof grist.mapColumnNames === \"function\") {\n const mapped = grist.mapColumnNames(record)\n setMappedRecord(\n mapped !== null && mapped !== undefined ? (mapped as T) : null\n )\n return\n }\n setMappedRecord(record as T)\n })\n }, [docApi])\n\n const mapBack = useCallback(\n (patch: Partial<T>): Record<string, unknown> => {\n if (typeof grist.mapColumnNamesBack === \"function\") {\n return grist.mapColumnNamesBack(patch as Record<string, unknown>)\n }\n return manualMapBack<T>(patch, mappings)\n },\n [mappings]\n )\n\n const resolveColumnId = useCallback(\n (logicalName: keyof T & string): string | undefined => {\n const value = mappings?.[logicalName]\n if (Array.isArray(value)) return undefined\n return value ?? undefined\n },\n [mappings]\n )\n\n return {\n rawRecord,\n mappedRecord,\n mappings,\n loading: docApi === null && !readyError,\n error: readyError,\n mapBack,\n resolveColumnId,\n }\n}\n","import { useCallback, useState } from \"react\"\n\nimport { useRpcHeartbeatCoalesce } from \"../internal/hooks/use-rpc-heartbeat-coalesce\"\nimport { useGristReady } from \"../low-level-hooks/use-grist-ready\"\nimport type {\n GristMinimalRecord,\n GristReadyOptions,\n GristTableNewRecord,\n GristTableOpOptions,\n GristTableOperations,\n GristTableUpdateRecord,\n GristTableUpsertOptions,\n GristTableUpsertRecord,\n} from \"../types\"\n\nexport type GristTableOpsStatus = \"idle\" | \"running\" | \"error\"\n\nexport type UseGristTableOpsOptions = {\n /**\n * Table to operate on:\n * - `\"selected\"` (default): use `grist.selectedTable` (the widget's current table).\n * - any other string: use `grist.getTable(tableId)`.\n */\n tableId?: \"selected\" | string\n /** Defaults to `\"full\"` since these operations write to the document. */\n requiredAccess?: GristReadyOptions[\"requiredAccess\"]\n} & Pick<GristReadyOptions, \"columns\" | \"allowSelectBy\" | \"hasCustomOptions\" | \"onEditOptions\">\n\nexport type UseGristTableOpsResult = {\n status: GristTableOpsStatus\n error: string | null\n /** Resolves the runtime tableId (only meaningful when `tableId` is `\"selected\"`). */\n getTableId: () => Promise<string>\n create: (\n records: GristTableNewRecord | GristTableNewRecord[],\n opOptions?: GristTableOpOptions\n ) => Promise<GristMinimalRecord | GristMinimalRecord[]>\n update: (\n records: GristTableUpdateRecord | GristTableUpdateRecord[],\n opOptions?: GristTableOpOptions\n ) => Promise<void>\n upsert: (\n records: GristTableUpsertRecord | GristTableUpsertRecord[],\n opOptions?: GristTableUpsertOptions\n ) => Promise<void>\n destroy: (recordIds: number | number[]) => Promise<void>\n}\n\nfunction resolveOps(tableId: \"selected\" | string): GristTableOperations {\n if (tableId === \"selected\") {\n if (!grist.selectedTable) throw new Error(\"grist.selectedTable is not available\")\n return grist.selectedTable\n }\n if (typeof grist.getTable !== \"function\") {\n throw new Error(\"grist.getTable is not available in this Grist version\")\n }\n return grist.getTable(tableId)\n}\n\n/**\n * Strongly-typed CRUD wrapper around Grist's `TableOperations` (`grist.selectedTable`\n * or `grist.getTable(tableId)`). Prefer this over hand-rolled `applyUserActions`.\n *\n * @see https://support.getgrist.com/code/interfaces/TableOperations.TableOperations/\n */\nexport function useGristTableOps(options?: UseGristTableOpsOptions): UseGristTableOpsResult {\n const requiredAccess = options?.requiredAccess ?? \"full\"\n const tableIdOption: \"selected\" | string = options?.tableId ?? \"selected\"\n const { docApi, error: readyError } = useGristReady({\n requiredAccess,\n columns: options?.columns,\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n })\n\n const [status, setStatus] = useState<GristTableOpsStatus>(\"idle\")\n const [actionError, setActionError] = useState<string | null>(null)\n const coalesceRpc = useRpcHeartbeatCoalesce()\n\n // `resolveOps` is synchronous and idempotent (it only reads `grist.selectedTable`\n // / `grist.getTable`), so derive `ops` during render instead of via effect.\n let ops: GristTableOperations | null = null\n let resolveError: string | null = null\n if (docApi) {\n try {\n ops = resolveOps(tableIdOption)\n } catch (err) {\n resolveError = err instanceof Error ? err.message : String(err)\n }\n }\n\n const wrap = useCallback(\n async <T>(run: (ops: GristTableOperations) => Promise<T>): Promise<T> => {\n if (!ops) throw new Error(\"Grist table operations are not ready\")\n setStatus(\"running\")\n setActionError(null)\n try {\n const out = await coalesceRpc(() => run(ops))\n setStatus(\"idle\")\n return out\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n setActionError(message)\n setStatus(\"error\")\n throw err\n }\n },\n [ops, coalesceRpc]\n )\n\n const getTableId = useCallback(async () => {\n if (!ops) throw new Error(\"Grist table operations are not ready\")\n return ops.getTableId()\n }, [ops])\n\n const create = useCallback(\n (records: GristTableNewRecord | GristTableNewRecord[], opOptions?: GristTableOpOptions) =>\n wrap((o) => o.create(records, opOptions)),\n [wrap]\n )\n\n const update = useCallback(\n (records: GristTableUpdateRecord | GristTableUpdateRecord[], opOptions?: GristTableOpOptions) =>\n wrap((o) => o.update(records, opOptions)),\n [wrap]\n )\n\n const upsert = useCallback(\n (records: GristTableUpsertRecord | GristTableUpsertRecord[], opOptions?: GristTableUpsertOptions) =>\n wrap((o) => o.upsert(records, opOptions)),\n [wrap]\n )\n\n const destroy = useCallback(\n (recordIds: number | number[]) => wrap((o) => o.destroy(recordIds)),\n [wrap]\n )\n\n return {\n status: readyError || resolveError ? \"error\" : status,\n error: readyError ?? resolveError ?? actionError,\n getTableId,\n create,\n update,\n upsert,\n destroy,\n }\n}\n","import { useCallback, useContext, useEffect, useRef, useState } from \"react\"\n\nimport { tableDataToRows, type GristColumnarTable } from \"../helpers/grist-table-data\"\nimport { GristReadsContext } from \"../internal/contexts\"\nimport { useRpcHeartbeatCoalesce } from \"../internal/hooks/use-rpc-heartbeat-coalesce\"\nimport { useGristReady } from \"../low-level-hooks/use-grist-ready\"\nimport type { GristReadyOptions, GristRowRecord } from \"../types\"\n\nexport type UseGristRowsFromTableOptions<T> = {\n tableId: string\n /** Re-fetch on a fixed cadence (ms). Default: disabled. */\n pollIntervalMs?: number\n /** Map raw rows to a domain shape (e.g. `decodeGristValue` your columns). */\n transform?: (row: GristRowRecord) => GristRowRecord<T>\n requiredAccess?: GristReadyOptions[\"requiredAccess\"]\n} & Pick<GristReadyOptions, \"columns\" | \"allowSelectBy\" | \"hasCustomOptions\" | \"onEditOptions\">\n\nexport type UseGristRowsFromTableResult<T> = {\n rows: GristRowRecord<T>[] | null\n loading: boolean\n error: string | null\n /** Force a re-fetch (call after writes that should be reflected immediately). */\n refresh: () => Promise<void>\n}\n\n/**\n * Subscribes to a full table's rows via `docApi.fetchTable`.\n *\n * Unlike `useGristRecords` (which is bound to the widget's selected section),\n * this hook works against any table id and **doesn't auto-update on Grist\n * writes from elsewhere** — call `refresh()` after your own writes, or set\n * `pollIntervalMs` for polling.\n */\nexport function useGristRowsFromTable<T = Record<string, unknown>>(\n options: UseGristRowsFromTableOptions<T>\n): UseGristRowsFromTableResult<T> {\n const requiredAccess = options.requiredAccess ?? \"read table\"\n const { docApi, error: readyError } = useGristReady({\n requiredAccess,\n columns: options.columns,\n allowSelectBy: options.allowSelectBy,\n hasCustomOptions: options.hasCustomOptions,\n onEditOptions: options.onEditOptions,\n })\n\n // When inside a GristWidgetProvider, delegate to the provider's guarded\n // fetchTable so access-insufficient errors flow through readError → alerts.\n const providerFetchTable = useContext(GristReadsContext)?.fetchTable\n\n const [rows, setRows] = useState<GristRowRecord<T>[] | null>(null)\n const [loading, setLoading] = useState(false)\n const [fetchError, setFetchError] = useState<string | null>(null)\n const transformRef = useRef(options.transform)\n transformRef.current = options.transform\n const coalesceRpc = useRpcHeartbeatCoalesce()\n\n const refresh = useCallback(async () => {\n if (!docApi) return\n setLoading(true)\n setFetchError(null)\n try {\n const data = providerFetchTable\n ? await providerFetchTable(options.tableId)\n : ((await coalesceRpc(\n () => docApi.fetchTable(options.tableId) as Promise<GristColumnarTable>\n )) as GristColumnarTable)\n const raw = tableDataToRows(data)\n const t = transformRef.current\n setRows(t ? raw.map((r) => t(r)) : (raw as GristRowRecord<T>[]))\n } catch (err) {\n setFetchError(err instanceof Error ? err.message : String(err))\n setRows(null)\n } finally {\n setLoading(false)\n }\n }, [docApi, providerFetchTable, options.tableId, coalesceRpc])\n\n useEffect(() => {\n if (docApi) void refresh()\n }, [docApi, refresh])\n\n useEffect(() => {\n if (!docApi || !options.pollIntervalMs || options.pollIntervalMs <= 0) return\n const id = window.setInterval(() => void refresh(), options.pollIntervalMs)\n return () => window.clearInterval(id)\n }, [docApi, options.pollIntervalMs, refresh])\n\n return {\n rows,\n loading,\n error: readyError ?? fetchError,\n refresh,\n }\n}\n","import { useCallback, useEffect, useState } from \"react\"\n\nimport {\n fetchWithGristAuth as fetchWithGristAuthCore,\n getGristAccessToken,\n type GristAccessToken,\n} from \"../helpers/grist-fetch-with-auth\"\nimport { useGristReady } from \"../low-level-hooks/use-grist-ready\"\nimport type { GristReadyOptions } from \"../types\"\n\nexport type UseGristAccessTokenOptions = {\n /** Default for all token requests issued by this hook. */\n readOnly?: boolean\n /** Pre-fetch a token on mount so `token` is non-null when widgets render. */\n prefetch?: boolean\n /** Defaults to `\"full\"` since tokens are used for REST calls. */\n requiredAccess?: GristReadyOptions[\"requiredAccess\"]\n} & Pick<GristReadyOptions, \"columns\" | \"allowSelectBy\" | \"hasCustomOptions\" | \"onEditOptions\">\n\nexport type UseGristAccessTokenResult = {\n token: GristAccessToken | null\n loading: boolean\n error: string | null\n /** Request a fresh token (Grist tokens are short-lived; do not cache aggressively). */\n refresh: (overrides?: { readOnly?: boolean }) => Promise<GristAccessToken>\n /** `fetch()` against Grist's REST API with auth attached. */\n fetch: (path: string, init?: RequestInit & { readOnly?: boolean }) => Promise<Response>\n}\n\n/**\n * Exposes `docApi.getAccessToken` plus a ready-to-use `fetch` for calling\n * Grist's REST API (e.g. attachments, records, sql) from a widget.\n */\nexport function useGristAccessToken(options?: UseGristAccessTokenOptions): UseGristAccessTokenResult {\n const requiredAccess = options?.requiredAccess ?? \"full\"\n const readOnlyDefault = options?.readOnly ?? false\n const prefetch = options?.prefetch ?? false\n const { docApi, error: readyError } = useGristReady({\n requiredAccess,\n columns: options?.columns,\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n })\n\n const [token, setToken] = useState<GristAccessToken | null>(null)\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const refresh = useCallback(\n async (overrides?: { readOnly?: boolean }): Promise<GristAccessToken> => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n setLoading(true)\n setError(null)\n try {\n const next = await getGristAccessToken(docApi, { readOnly: overrides?.readOnly ?? readOnlyDefault })\n setToken(next)\n return next\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n setError(message)\n throw err\n } finally {\n setLoading(false)\n }\n },\n [docApi, readOnlyDefault]\n )\n\n const fetchFn = useCallback(\n (path: string, init?: RequestInit & { readOnly?: boolean }) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return fetchWithGristAuthCore(docApi, path, { readOnly: readOnlyDefault, ...init })\n },\n [docApi, readOnlyDefault]\n )\n\n useEffect(() => {\n if (docApi && prefetch) void refresh()\n }, [docApi, prefetch, refresh])\n\n return {\n token,\n loading,\n error: readyError ?? error,\n refresh,\n fetch: fetchFn,\n }\n}\n","import { useCallback, useEffect, useState } from \"react\"\n\nimport { useGristReady } from \"../low-level-hooks/use-grist-ready\"\nimport type { GristReadyOptions, GristWidgetColumnMap } from \"../types\"\n\nexport type UseGristSectionResult = {\n /** Current widget ↔ section column mappings, refreshed on demand. */\n mappings: GristWidgetColumnMap | null\n loading: boolean\n error: string | null\n /** Re-read mappings from `sectionApi`. */\n refresh: () => Promise<void>\n /**\n * Update the widget's declared `ColumnsToMap` (and other ready options) after\n * mount. Use this to dynamically request more columns once the user has\n * configured the widget.\n */\n configure: (options: GristReadyOptions) => Promise<void>\n}\n\n/**\n * Wraps Grist's `sectionApi` (`mappings()` + `configure()`) so widgets can\n * inspect/refresh the column mapping and re-declare requirements without\n * touching `grist` directly.\n */\nexport function useGristSection(options?: GristReadyOptions): UseGristSectionResult {\n const { docApi, error: readyError } = useGristReady({\n requiredAccess: options?.requiredAccess ?? \"read table\",\n columns: options?.columns,\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n })\n\n const [mappings, setMappings] = useState<GristWidgetColumnMap | null>(null)\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const refresh = useCallback(async () => {\n if (!docApi) return\n if (!grist.sectionApi?.mappings) {\n setError(\"grist.sectionApi.mappings is not available in this Grist version\")\n return\n }\n setLoading(true)\n setError(null)\n try {\n const next = await grist.sectionApi.mappings()\n setMappings(next)\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err))\n } finally {\n setLoading(false)\n }\n }, [docApi])\n\n const configure = useCallback(async (next: GristReadyOptions) => {\n if (!grist.sectionApi?.configure) {\n throw new Error(\"grist.sectionApi.configure is not available in this Grist version\")\n }\n await grist.sectionApi.configure(next)\n }, [])\n\n useEffect(() => {\n if (docApi) void refresh()\n }, [docApi, refresh])\n\n return {\n mappings,\n loading,\n error: readyError ?? error,\n refresh,\n configure,\n }\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\n\nimport { optionsEvent } from \"../internal/subscriptions\"\nimport { useGristReady } from \"../low-level-hooks/use-grist-ready\"\nimport type { GristReadyOptions } from \"../types\"\n\nexport type UseGristWidgetOptionsConfig<T> = {\n /** Default values returned before Grist responds and merged with stored options. */\n defaults: T\n /** Debounce window for `setOptions` writes (ms). Default: 250. */\n debounceMs?: number\n /**\n * Optional namespace inside `grist.setOptions`. When set, this hook reads/writes\n * `grist.setOption(namespace, value)` instead of the whole options blob — useful\n * to share the options bag with `hasCustomOptions` / unrelated widget state.\n */\n namespace?: string\n requiredAccess?: GristReadyOptions[\"requiredAccess\"]\n} & Pick<GristReadyOptions, \"columns\" | \"allowSelectBy\" | \"hasCustomOptions\" | \"onEditOptions\">\n\nexport type UseGristWidgetOptionsResult<T> = {\n options: T\n /** True until Grist has responded with the initial `onOptions` payload. */\n loading: boolean\n error: string | null\n /** Replace the options object (debounced write to Grist). */\n setOptions: (next: T) => void\n /** Patch a subset of keys (debounced write to Grist). */\n patchOptions: (patch: Partial<T>) => void\n /** Reset to `defaults` (immediate write to Grist). */\n reset: () => Promise<void>\n}\n\nfunction mergeWithDefaults<T>(defaults: T, stored: unknown, namespace?: string): T {\n if (stored === null || stored === undefined) return { ...defaults }\n const source = (namespace ? (stored as Record<string, unknown>)[namespace] : stored) as Partial<T> | undefined\n if (!source || typeof source !== \"object\") return { ...defaults }\n return { ...defaults, ...source }\n}\n\n/**\n * Persist a typed object of widget settings via `grist.onOptions` / `setOptions`.\n *\n * - Defaults are returned immediately (no flicker before Grist responds).\n * - Writes are debounced and batched.\n * - `hasCustomOptions` defaults to `true` so Grist exposes the gear icon — pass\n * `hasCustomOptions: false` to opt out.\n */\nexport function useGristWidgetOptions<T extends Record<string, unknown>>(\n config: UseGristWidgetOptionsConfig<T>\n): UseGristWidgetOptionsResult<T> {\n const requiredAccess = config.requiredAccess ?? \"read table\"\n const debounceMs = config.debounceMs ?? 250\n const hasCustomOptions = config.hasCustomOptions ?? true\n const { docApi, error: readyError } = useGristReady({\n requiredAccess,\n columns: config.columns,\n allowSelectBy: config.allowSelectBy,\n hasCustomOptions,\n onEditOptions: config.onEditOptions,\n })\n\n const defaultsRef = useRef(config.defaults)\n useEffect(() => {\n defaultsRef.current = config.defaults\n }, [config.defaults])\n\n const [options, setOptionsState] = useState<T>(() => ({ ...config.defaults }))\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const lastWrittenRef = useRef<T | null>(null)\n const debounceRef = useRef<number | null>(null)\n\n // Subscribe to remote changes (initial + external edits)\n useEffect(() => {\n if (!docApi) return\n return optionsEvent.subscribe(({ options: stored }) => {\n const merged = mergeWithDefaults(defaultsRef.current, stored, config.namespace)\n lastWrittenRef.current = merged\n setOptionsState(merged)\n setLoading(false)\n })\n }, [docApi, config.namespace])\n\n const flushWrite = useCallback(\n async (value: T) => {\n try {\n if (config.namespace) {\n await grist.setOption(config.namespace, value)\n } else {\n await grist.setOptions({ ...value })\n }\n lastWrittenRef.current = value\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err))\n }\n },\n [config.namespace]\n )\n\n const scheduleWrite = useCallback(\n (value: T) => {\n if (debounceRef.current) window.clearTimeout(debounceRef.current)\n debounceRef.current = window.setTimeout(() => {\n debounceRef.current = null\n void flushWrite(value)\n }, debounceMs)\n },\n [debounceMs, flushWrite]\n )\n\n useEffect(() => {\n return () => {\n if (debounceRef.current) window.clearTimeout(debounceRef.current)\n }\n }, [])\n\n const setOptionsApi = useCallback(\n (next: T) => {\n setOptionsState(next)\n scheduleWrite(next)\n },\n [scheduleWrite]\n )\n\n const patchOptionsApi = useCallback(\n (patch: Partial<T>) => {\n setOptionsState((prev) => {\n const next = { ...prev, ...patch }\n scheduleWrite(next)\n return next\n })\n },\n [scheduleWrite]\n )\n\n const reset = useCallback(async () => {\n if (debounceRef.current) {\n window.clearTimeout(debounceRef.current)\n debounceRef.current = null\n }\n const next = { ...defaultsRef.current }\n setOptionsState(next)\n await flushWrite(next)\n }, [flushWrite])\n\n return useMemo(\n () => ({\n options,\n loading,\n error: readyError ?? error,\n setOptions: setOptionsApi,\n patchOptions: patchOptionsApi,\n reset,\n }),\n [options, loading, readyError, error, setOptionsApi, patchOptionsApi, reset]\n )\n}\n","import { useCallback, useEffect, useState } from \"react\"\n\nimport type { GristColumnarTable } from \"./helpers/grist-table-data\"\nimport { useGristReady } from \"./low-level-hooks/use-grist-ready\"\nimport type { GristFetchSelectedOptions, GristReadyOptions, GristRequiredAccess } from \"./types\"\n\nexport type UseGristTableOptions = {\n requiredAccess?: GristRequiredAccess\n /**\n * `'current'` (default): follow the widget’s selected table.\n * Any other string: fixed table id (no `grist.selectedTable` polling).\n */\n tableId?: \"current\" | string\n} & Pick<GristReadyOptions, \"columns\" | \"allowSelectBy\" | \"hasCustomOptions\" | \"onEditOptions\">\n\nexport type UseGristTableResult = {\n tableId: string | null\n loading: boolean\n error: string | null\n refresh: () => Promise<void>\n fetchTable: (targetTableId: string) => Promise<GristColumnarTable>\n listTables: () => Promise<string[]>\n getDocName: () => Promise<string>\n fetchSelectedTable: (fetchOptions?: GristFetchSelectedOptions) => Promise<GristColumnarTable>\n fetchSelectedRecord: (rowId: number, fetchOptions?: GristFetchSelectedOptions) => Promise<Record<string, unknown>>\n}\n\nfunction isCurrentMode(option: string | undefined): boolean {\n return option === undefined || option === \"current\"\n}\n\n/**\n * Selected or fixed table id plus document reads — no raw `docApi` on the result.\n */\nexport function useGristTable(options?: UseGristTableOptions): UseGristTableResult {\n const requiredAccess = options?.requiredAccess ?? \"read table\"\n const tableIdOption = options?.tableId ?? \"current\"\n const { docApi, error: readyError } = useGristReady({\n requiredAccess,\n columns: options?.columns,\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n })\n const [tableId, setTableId] = useState<string | null>(null)\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const fetchTable = useCallback(\n async (targetTableId: string) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return docApi.fetchTable(targetTableId) as Promise<GristColumnarTable>\n },\n [docApi]\n )\n\n const listTables = useCallback(async () => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n const out = await Promise.resolve(docApi.listTables())\n return [...out]\n }, [docApi])\n\n const getDocName = useCallback(async () => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return String(await Promise.resolve(docApi.getDocName()))\n }, [docApi])\n\n const fetchSelectedTable = useCallback(\n async (fetchOptions?: GristFetchSelectedOptions) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n const impl = docApi.fetchSelectedTable ?? grist.fetchSelectedTable\n if (!impl) throw new Error(\"fetchSelectedTable is not available in this Grist version\")\n const merged: GristFetchSelectedOptions = { keepEncoded: false, format: \"rows\", ...fetchOptions }\n return (await impl(merged)) as GristColumnarTable\n },\n [docApi]\n )\n\n const fetchSelectedRecord = useCallback(\n async (rowId: number, fetchOptions?: GristFetchSelectedOptions) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n const impl = docApi.fetchSelectedRecord ?? grist.fetchSelectedRecord\n if (!impl) throw new Error(\"fetchSelectedRecord is not available in this Grist version\")\n const merged: GristFetchSelectedOptions = { keepEncoded: false, format: \"rows\", ...fetchOptions }\n return (await impl(rowId, merged)) as Record<string, unknown>\n },\n [docApi]\n )\n\n const refresh = useCallback(async () => {\n if (!docApi) return\n if (!isCurrentMode(tableIdOption)) {\n setTableId(tableIdOption)\n setError(null)\n return\n }\n setLoading(true)\n setError(null)\n try {\n const next = await grist.selectedTable?.getTableId()\n setTableId(next ?? null)\n } catch (err) {\n setTableId(null)\n setError(err instanceof Error ? err.message : String(err))\n } finally {\n setLoading(false)\n }\n }, [docApi, tableIdOption])\n\n useEffect(() => {\n if (docApi) void refresh()\n }, [docApi, refresh])\n\n return {\n tableId,\n loading,\n error: readyError ?? error,\n refresh,\n fetchTable,\n listTables,\n getDocName,\n fetchSelectedTable,\n fetchSelectedRecord,\n }\n}\n"],"mappings":"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","names":["useEffect","useMemo","useRef","useSyncExternalStore","useRef","useEffect","useSyncExternalStore","useMemo","useEffect","useRef","useRef","useEffect","useEffect","useRef","useState","useRef","useEffect","useState","useEffect","useRef","useState","useState","useRef","useEffect","useState","useState","useCallback","useEffect","useState","useState","useEffect","useCallback","useCallback","useState","useState","useCallback","useCallback","useContext","useEffect","useRef","useState","useContext","useState","useRef","useCallback","useEffect","useCallback","useEffect","useState","useState","useCallback","useEffect","useCallback","useEffect","useState","useState","useCallback","useEffect","useCallback","useEffect","useMemo","useRef","useState","useRef","useEffect","useState","useCallback","useMemo","useCallback","useEffect","useState","useState","useCallback","useEffect"]}
1
+ {"version":3,"sources":["../src/sdk/low-level-hooks/use-grist-availability.ts","../src/sdk/low-level-hooks/use-grist-handshake.ts","../src/sdk/low-level-hooks/use-ambient-grist-handshake.ts","../src/sdk/components/grist-handshake-provider.tsx","../src/sdk/low-level-hooks/use-grist-record.ts","../src/sdk/low-level-hooks/use-grist-records.ts","../src/sdk/low-level-hooks/use-grist-new-record.ts","../src/sdk/mid-level-hooks/use-grist-actions.ts","../src/sdk/mid-level-hooks/use-grist-mapped-record.ts","../src/sdk/mid-level-hooks/use-grist-table-ops.ts","../src/sdk/mid-level-hooks/use-grist-rows-from-table.ts","../src/sdk/mid-level-hooks/use-grist-access-token.ts","../src/sdk/mid-level-hooks/use-grist-section.ts","../src/sdk/mid-level-hooks/use-grist-widget-options.ts","../src/sdk/use-grist-table.ts"],"sourcesContent":["import { useGristCore, type UseGristCoreOptions } from \"../internal/hooks/use-grist-core\"\n\nexport type UseGristAvailabilityOptions = Pick<\n UseGristCoreOptions,\n \"availabilityMaxAttempts\" | \"availabilityIntervalMs\" | \"logWhenNotEmbedded\"\n>\n\n/**\n * Handshake-backed availability — projects `isAvailable` from the FSM.\n */\nexport function useGristAvailability(options?: UseGristAvailabilityOptions): boolean | null {\n const { isAvailable } = useGristCore(options)\n return isAvailable\n}\n","/**\n * `useGristHandshake()` — React adapter over {@link GristHandshakeManager}.\n *\n * Exposes the full {@link GristWidgetSnapshot} plus derived\n * {@link GristCapabilities}, plus `reload()` / `restart()` controls.\n *\n * Identity stability\n * ------------------\n * The snapshot reference changes whenever the reducer produces a new\n * snapshot. Capabilities are memoized by snapshot identity, so consumers\n * branching on a single capability (e.g. `canWriteRecords`) avoid extra\n * re-renders unless that boolean actually flips.\n *\n * SSR-safe: `getServerSnapshot` returns the initial snapshot deterministically.\n */\n\nimport { useEffect, useMemo, useRef, useSyncExternalStore } from \"react\"\n\nimport {\n deriveCapabilities,\n deriveErrorMessage,\n deriveStatus,\n initialGristSnapshot,\n type GristCapabilities,\n type GristWidgetSnapshot,\n type GristWidgetStatus,\n} from \"../internal/handshake\"\nimport {\n createGristHandshakeManager,\n type ManagerControls,\n type ManagerOptions,\n} from \"../internal/handshake/manager\"\nimport { ensureGristReady, resetGristReadySingleton } from \"../internal/ready-singleton\"\n\nexport type UseGristHandshakeOptions = ManagerOptions\n\nexport type UseGristHandshakeResult = {\n snapshot: GristWidgetSnapshot\n status: GristWidgetStatus\n error: string | null\n capabilities: GristCapabilities\n reload: () => void\n restart: () => void\n}\n\n/**\n * Mount a handshake manager local to the component subtree. Multiple\n * widgets in the same page should NOT call this in parallel — instead,\n * mount a single `<GristWidgetProvider>` at the app root.\n *\n * In tests, pass `options.env` (see `createTestEnvironment`) to drive the\n * machine with a virtual clock.\n */\nexport function useGristHandshake(options: UseGristHandshakeOptions = {}): UseGristHandshakeResult {\n // Memoize the manager so it survives re-renders. Caller is responsible for\n // passing stable options; in practice this is set once at the provider.\n const optionsRef = useRef(options)\n optionsRef.current = options\n const managerRef = useRef<ManagerControls | null>(null)\n if (managerRef.current === null) {\n // Default to the page-level `ensureGristReady()` singleton so a\n // standalone `useGristHandshake()` (mounted alongside a real\n // `<GristWidgetProvider>` for its observable snapshot, per the \"custom\n // retry / observability\" pattern) can't call the real `grist.ready()`\n // independently and race the widget's own declared options. Callers\n // that pass their own `negotiate`/`onBeforeReload` still win.\n managerRef.current = createGristHandshakeManager({\n ...options,\n negotiate: {\n readyImpl: (payload) => ensureGristReady(payload),\n ...options.negotiate,\n },\n onBeforeReload: () => {\n resetGristReadySingleton()\n options.onBeforeReload?.()\n },\n })\n }\n const manager = managerRef.current\n\n useEffect(() => {\n manager.start()\n return () => {\n manager.stop()\n }\n }, [manager])\n\n const snapshot = useSyncExternalStore(\n manager.subscribe,\n manager.getSnapshot,\n initialGristSnapshot\n )\n\n const projected = useMemo(\n () => ({\n status: deriveStatus(snapshot),\n error: deriveErrorMessage(snapshot),\n capabilities: deriveCapabilities(snapshot),\n }),\n [snapshot]\n )\n\n return useMemo(\n () => ({\n snapshot,\n status: projected.status,\n error: projected.error,\n capabilities: projected.capabilities,\n reload: manager.reload,\n restart: manager.restart,\n }),\n [snapshot, projected, manager]\n )\n}\n\n/**\n * Convenience hook — equivalent to `useGristHandshake().capabilities` but\n * skips returning the full snapshot. Intended for leaf components that only\n * need to gate UI on `canRender` / `canWriteRecords` / etc.\n */\nexport function useGristCapabilities(\n options: UseGristHandshakeOptions = {}\n): GristCapabilities {\n return useGristHandshake(options).capabilities\n}\n","/**\n * `useAmbientGristHandshake()` — observe an already-mounted handshake\n * manager without ever creating one.\n *\n * `useGristHandshake()` / `<GristHandshakeProvider>` both mount their OWN\n * manager, which calls the real `grist.ready()` independently of any\n * `<GristWidgetProvider>` elsewhere on the page. That's fine for a widget's\n * single app-root provider, but wrong for read-only UI (a connection-status\n * chip, a debug overlay) that must share the *same* handshake as the real\n * widget rather than run a second, competing one. This hook only reads\n * whatever manager a `<GristWidgetProvider>` ancestor already published;\n * it returns `null` outside one instead of falling back to creating its own.\n */\n\nimport { useMemo, useSyncExternalStore } from \"react\"\n\nimport {\n deriveCapabilities,\n deriveErrorMessage,\n deriveStatus,\n initialGristSnapshot,\n type GristCapabilities,\n type GristWidgetSnapshot,\n type GristWidgetStatus,\n} from \"../internal/handshake\"\nimport { useGristManagerOptional } from \"../internal/handshake-manager-context\"\n\nexport type UseAmbientGristHandshakeResult = {\n snapshot: GristWidgetSnapshot\n status: GristWidgetStatus\n error: string | null\n capabilities: GristCapabilities\n reload: () => void\n restart: () => void\n}\n\nconst noopSubscribe = () => () => {}\nconst getInitialSnapshot = () => initialGristSnapshot()\n\n/**\n * Returns `null` when mounted outside a `<GristWidgetProvider>` — there is\n * no ambient manager to observe, and this hook intentionally never creates\n * one. Mount inside `<GristWidgetProvider>` to get a live value.\n */\nexport function useAmbientGristHandshake(): UseAmbientGristHandshakeResult | null {\n const manager = useGristManagerOptional()\n\n const snapshot = useSyncExternalStore(\n manager?.subscribe ?? noopSubscribe,\n manager?.getSnapshot ?? getInitialSnapshot,\n getInitialSnapshot\n )\n\n return useMemo(() => {\n if (!manager) return null\n return {\n snapshot,\n status: deriveStatus(snapshot),\n error: deriveErrorMessage(snapshot),\n capabilities: deriveCapabilities(snapshot),\n reload: manager.reload,\n restart: manager.restart,\n }\n }, [manager, snapshot])\n}\n","/**\n * `<GristHandshakeProvider>` — opt-in React provider that mounts a single\n * {@link GristHandshakeManager} at the app root and broadcasts its snapshot\n * to all descendants.\n *\n * Use this provider when you want the full SOTA handshake model (snapshot +\n * capabilities + heartbeat + reload/restart) without the slice composition\n * of `<GristWidgetProvider>`. The two providers are independent:\n *\n * - `<GristWidgetProvider>` (legacy) — full SDK surface, hooks slices.\n * - `<GristHandshakeProvider>` (new) — handshake state machine only.\n *\n * Both can coexist if you need both surfaces; `grist.ready` is deduped by\n * the SDK's ready singleton so concurrent calls are safe.\n */\n\nimport {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n type ReactNode,\n} from \"react\"\n\nimport {\n createGristHandshakeManager,\n type ManagerControls,\n type ManagerOptions,\n} from \"../internal/handshake/manager\"\nimport {\n deriveCapabilities,\n deriveErrorMessage,\n deriveStatus,\n initialGristSnapshot,\n type GristCapabilities,\n type GristWidgetSnapshot,\n type GristWidgetStatus,\n} from \"../internal/handshake\"\nimport { ensureGristReady, resetGristReadySingleton } from \"../internal/ready-singleton\"\n\nexport type GristHandshakeContextValue = {\n snapshot: GristWidgetSnapshot\n status: GristWidgetStatus\n error: string | null\n capabilities: GristCapabilities\n reload: () => void\n restart: () => void\n recordRpcSuccess: () => void\n recordRpcFailure: () => void\n}\n\nconst GristHandshakeReactContext = createContext<GristHandshakeContextValue | null>(null)\n\nexport type GristHandshakeProviderProps = {\n options?: ManagerOptions\n children: ReactNode\n}\n\n/**\n * Mount a single {@link GristHandshakeManager} for the React subtree and\n * expose its snapshot via context.\n *\n * The manager is created **once** on first mount; the `options` prop is\n * captured at that time. To re-create the manager with new options, unmount\n * and re-mount the provider (e.g. via a `key`).\n */\nexport function GristHandshakeProvider({ options, children }: GristHandshakeProviderProps) {\n // Manager is allocated once. Subsequent option changes are intentionally\n // ignored — handshake configuration should be stable for the lifetime of\n // the widget.\n const managerRef = useRef<ManagerControls | null>(null)\n if (managerRef.current === null) {\n // Default to the page-level `ensureGristReady()` singleton so a bare\n // `<GristHandshakeProvider>` (no options) can't win a race against a\n // sibling `<GristWidgetProvider>` by calling the real `grist.ready()`\n // directly with its own default payload. Callers that pass their own\n // `negotiate`/`onBeforeReload` still win. (Read-only observers of an\n // ancestor `<GristWidgetProvider>`, like the template's `GristStatusChip`,\n // should prefer `useAmbientGristHandshake()` instead of this provider —\n // it observes the existing manager rather than allocating a new one.)\n managerRef.current = createGristHandshakeManager({\n ...options,\n negotiate: {\n readyImpl: (payload) => ensureGristReady(payload),\n ...options?.negotiate,\n },\n onBeforeReload: () => {\n resetGristReadySingleton()\n options?.onBeforeReload?.()\n },\n })\n }\n const manager = managerRef.current\n\n useEffect(() => {\n manager.start()\n return () => {\n manager.stop()\n }\n }, [manager])\n\n const snapshot = useSyncExternalStore(\n manager.subscribe,\n manager.getSnapshot,\n initialGristSnapshot\n )\n\n const value = useMemo<GristHandshakeContextValue>(\n () => ({\n snapshot,\n status: deriveStatus(snapshot),\n error: deriveErrorMessage(snapshot),\n capabilities: deriveCapabilities(snapshot),\n reload: manager.reload,\n restart: manager.restart,\n recordRpcSuccess: manager.recordRpcSuccess,\n recordRpcFailure: manager.recordRpcFailure,\n }),\n [snapshot, manager]\n )\n\n return (\n <GristHandshakeReactContext.Provider value={value}>\n {children}\n </GristHandshakeReactContext.Provider>\n )\n}\n\n/**\n * Read the handshake context. Throws if no `<GristHandshakeProvider>` is\n * mounted in the tree.\n *\n * Use {@link useGristHandshakeContextOptional} when the provider is optional\n * (e.g. when the same component is sometimes used standalone).\n */\nexport function useGristHandshakeContext(): GristHandshakeContextValue {\n const ctx = useContext(GristHandshakeReactContext)\n if (!ctx) {\n throw new Error(\n \"useGristHandshakeContext() must be used inside <GristHandshakeProvider>\"\n )\n }\n return ctx\n}\n\n/** Non-throwing variant. */\nexport function useGristHandshakeContextOptional(): GristHandshakeContextValue | null {\n return useContext(GristHandshakeReactContext)\n}\n","import { useEffect, useRef, useState } from \"react\"\n\nimport { recordEvent } from \"../internal/subscriptions\"\nimport type { GristReadyOptions, GristWidgetColumnMap } from \"../types\"\nimport { useGristReady } from \"./use-grist-ready\"\n\nexport type UseGristRecordSubscriptionResult = {\n loading: boolean\n error: string | null\n /** Latest mappings from `grist.onRecord` (logical name → real column id, or `string[]` for `allowMultiple`). */\n mappings: GristWidgetColumnMap | null\n}\n\n// Subscription errors are logged inside the singleton; nothing surfaces here.\n\n/**\n * Subscribes to the currently-selected row in the widget's section.\n *\n * The Grist event is shared across all hook instances (no leak).\n */\nexport function useGristRecord(\n cb: (record: Record<string, unknown> | null, mappings: GristWidgetColumnMap | null) => void,\n options?: GristReadyOptions\n): UseGristRecordSubscriptionResult {\n const cbRef = useRef(cb)\n useEffect(() => {\n cbRef.current = cb\n }, [cb])\n\n const [mappings, setMappings] = useState<GristWidgetColumnMap | null>(null)\n const { docApi, error: readyError } = useGristReady({\n requiredAccess: options?.requiredAccess ?? \"read table\",\n columns: options?.columns,\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n })\n\n useEffect(() => {\n if (!docApi) return\n return recordEvent.subscribe(({ record, mappings: nextMappings }) => {\n setMappings(nextMappings)\n cbRef.current(record, nextMappings)\n })\n }, [docApi])\n\n return {\n loading: docApi === null && !readyError,\n error: readyError,\n mappings,\n }\n}\n","import { useEffect, useRef, useState } from \"react\"\n\nimport { recordsEvent } from \"../internal/subscriptions\"\nimport type { GristReadyOptions, GristWidgetColumnMap } from \"../types\"\nimport { useGristReady } from \"./use-grist-ready\"\nimport type { UseGristRecordSubscriptionResult } from \"./use-grist-record\"\n\n/**\n * Subscribes to the full row set visible in the widget's section\n * (filters, sorts, and linked rows applied).\n */\nexport function useGristRecords(\n cb: (records: Record<string, unknown>[], mappings: GristWidgetColumnMap | null) => void,\n options?: GristReadyOptions\n): UseGristRecordSubscriptionResult {\n const cbRef = useRef(cb)\n useEffect(() => {\n cbRef.current = cb\n }, [cb])\n\n const [mappings, setMappings] = useState<GristWidgetColumnMap | null>(null)\n const { docApi, error: readyError } = useGristReady({\n requiredAccess: options?.requiredAccess ?? \"read table\",\n columns: options?.columns,\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n })\n\n useEffect(() => {\n if (!docApi) return\n return recordsEvent.subscribe(({ records, mappings: nextMappings }) => {\n setMappings(nextMappings)\n cbRef.current(records, nextMappings)\n })\n }, [docApi])\n\n return {\n loading: docApi === null && !readyError,\n error: readyError,\n mappings,\n }\n}\n","import { useEffect, useRef, useState } from \"react\"\n\nimport { newRecordEvent } from \"../internal/subscriptions\"\nimport type { GristReadyOptions, GristWidgetColumnMap } from \"../types\"\nimport { useGristReady } from \"./use-grist-ready\"\n\nexport type UseGristNewRecordResult = {\n /** True when the user has selected the blank \"new row\" placeholder. */\n isNewRecord: boolean\n /** Mappings reported by Grist alongside the new-record event. */\n mappings: GristWidgetColumnMap | null\n loading: boolean\n error: string | null\n}\n\n/**\n * Subscribes to `grist.onNewRecord` — fires when the user selects the blank\n * row in the linked section. Useful for form-style widgets that need to\n * switch into \"create\" mode.\n *\n * `isNewRecord` is reset to `false` whenever a real `onRecord` payload arrives,\n * so callers don't need to manage that themselves.\n */\nexport function useGristNewRecord(options?: GristReadyOptions): UseGristNewRecordResult {\n const { docApi, error: readyError } = useGristReady({\n requiredAccess: options?.requiredAccess ?? \"read table\",\n columns: options?.columns,\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n })\n\n const [isNewRecord, setIsNewRecord] = useState(false)\n const [mappings, setMappings] = useState<GristWidgetColumnMap | null>(null)\n const subscribedRef = useRef(false)\n\n useEffect(() => {\n if (!docApi || subscribedRef.current) return\n if (typeof grist.onNewRecord !== \"function\") return\n subscribedRef.current = true\n return newRecordEvent.subscribe(({ mappings: nextMappings }) => {\n setIsNewRecord(true)\n setMappings(nextMappings)\n })\n }, [docApi])\n\n return {\n isNewRecord,\n mappings,\n loading: docApi === null && !readyError,\n error: readyError,\n }\n}\n","import { useCallback, useState } from \"react\"\n\nimport {\n gristAddRecordAction,\n gristBulkAddRecordAction,\n gristBulkRemoveRecordAction,\n gristBulkUpdateRecordAction,\n gristRemoveRecordAction,\n gristUpdateRecordAction,\n type GristUserActionTuple,\n} from \"../helpers/grist-user-actions\"\nimport { useRpcHeartbeatCoalesce } from \"../internal/hooks/use-rpc-heartbeat-coalesce\"\nimport { useGristReady } from \"../low-level-hooks/use-grist-ready\"\nimport type { GristApplyUserActionsOptions, GristReadyOptions } from \"../types\"\n\nexport type GristActionsStatus = \"idle\" | \"running\" | \"error\"\n\nexport type UseGristActionsOptions = Pick<\n GristReadyOptions,\n \"requiredAccess\" | \"columns\" | \"allowSelectBy\" | \"hasCustomOptions\" | \"onEditOptions\"\n>\n\nexport type UseGristActionsResult = {\n status: GristActionsStatus\n error: string | null\n /** Apply raw user actions. `applyOptions.desc` is shown in the document undo stack. */\n apply: (actions: GristUserActionTuple[], applyOptions?: GristApplyUserActionsOptions) => Promise<unknown>\n updateRecord: (\n tableId: string,\n recordId: number,\n patch: Record<string, unknown>,\n applyOptions?: GristApplyUserActionsOptions\n ) => Promise<unknown>\n addRecord: (\n tableId: string,\n values: Record<string, unknown>,\n applyOptions?: GristApplyUserActionsOptions\n ) => Promise<unknown>\n removeRecord: (\n tableId: string,\n recordId: number,\n applyOptions?: GristApplyUserActionsOptions\n ) => Promise<unknown>\n bulkAddRecord: (\n tableId: string,\n values: Record<string, unknown[]>,\n applyOptions?: GristApplyUserActionsOptions\n ) => Promise<unknown>\n bulkUpdateRecord: (\n tableId: string,\n rowIds: number[],\n columnarPatch: Record<string, unknown[]>,\n applyOptions?: GristApplyUserActionsOptions\n ) => Promise<unknown>\n bulkRemoveRecord: (\n tableId: string,\n rowIds: number[],\n applyOptions?: GristApplyUserActionsOptions\n ) => Promise<unknown>\n}\n\nexport function useGristActions(options?: UseGristActionsOptions): UseGristActionsResult {\n const requiredAccess = options?.requiredAccess ?? \"full\"\n const { docApi, error: readyError } = useGristReady({\n requiredAccess,\n columns: options?.columns,\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n })\n const [status, setStatus] = useState<GristActionsStatus>(\"idle\")\n const [actionError, setActionError] = useState<string | null>(null)\n const coalesceRpc = useRpcHeartbeatCoalesce()\n\n const apply = useCallback(\n async (actions: GristUserActionTuple[], applyOptions?: GristApplyUserActionsOptions): Promise<unknown> => {\n if (!docApi) throw new Error(\"Grist docApi is not ready\")\n setStatus(\"running\")\n setActionError(null)\n try {\n const out = await coalesceRpc(() => docApi.applyUserActions(actions, applyOptions))\n setStatus(\"idle\")\n return out\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n setActionError(message)\n setStatus(\"error\")\n throw err\n }\n },\n [docApi, coalesceRpc]\n )\n\n const updateRecord = useCallback(\n (tableId: string, recordId: number, patch: Record<string, unknown>, applyOptions?: GristApplyUserActionsOptions) =>\n apply([gristUpdateRecordAction(tableId, recordId, patch)], applyOptions),\n [apply]\n )\n\n const addRecord = useCallback(\n (tableId: string, values: Record<string, unknown>, applyOptions?: GristApplyUserActionsOptions) =>\n apply([gristAddRecordAction(tableId, values)], applyOptions),\n [apply]\n )\n\n const removeRecord = useCallback(\n (tableId: string, recordId: number, applyOptions?: GristApplyUserActionsOptions) =>\n apply([gristRemoveRecordAction(tableId, recordId)], applyOptions),\n [apply]\n )\n\n const bulkAddRecord = useCallback(\n (tableId: string, values: Record<string, unknown[]>, applyOptions?: GristApplyUserActionsOptions) =>\n apply([gristBulkAddRecordAction(tableId, values)], applyOptions),\n [apply]\n )\n\n const bulkUpdateRecord = useCallback(\n (tableId: string, rowIds: number[], columnarPatch: Record<string, unknown[]>, applyOptions?: GristApplyUserActionsOptions) =>\n apply([gristBulkUpdateRecordAction(tableId, rowIds, columnarPatch)], applyOptions),\n [apply]\n )\n\n const bulkRemoveRecord = useCallback(\n (tableId: string, rowIds: number[], applyOptions?: GristApplyUserActionsOptions) =>\n apply([gristBulkRemoveRecordAction(tableId, rowIds)], applyOptions),\n [apply]\n )\n\n return {\n status: readyError ? \"error\" : status,\n error: readyError ?? actionError,\n apply,\n updateRecord,\n addRecord,\n removeRecord,\n bulkAddRecord,\n bulkUpdateRecord,\n bulkRemoveRecord,\n }\n}\n","import { useCallback, useEffect, useState } from \"react\"\n\nimport { recordEvent } from \"../internal/subscriptions\"\nimport { useGristReady } from \"../low-level-hooks/use-grist-ready\"\nimport type { GristReadyOptions, GristWidgetColumnMap } from \"../types\"\n\nexport type UseGristMappedRecordResult<T> = {\n rawRecord: Record<string, unknown> | null\n mappedRecord: T | null\n /** Current column mappings reported by Grist. */\n mappings: GristWidgetColumnMap | null\n loading: boolean\n error: string | null\n /**\n * Reverse-map a logical patch (`{ logicalName: value }`) into a real-column\n * patch (`{ realColId: value }`) ready for `applyUserActions` /\n * `useGristTableOps.update`.\n * Falls back to `grist.mapColumnNamesBack` when present, otherwise resolves\n * names manually from `mappings` (single-mapped columns only).\n */\n mapBack: (patch: Partial<T>) => Record<string, unknown>\n /** Resolve a single logical name to its current real column id. */\n resolveColumnId: (logicalName: keyof T & string) => string | undefined\n}\n\nfunction manualMapBack<T>(patch: Partial<T>, mappings: GristWidgetColumnMap | null): Record<string, unknown> {\n if (!mappings) return { ...(patch as Record<string, unknown>) }\n const out: Record<string, unknown> = {}\n for (const [name, value] of Object.entries(patch as Record<string, unknown>)) {\n const target = mappings[name]\n if (Array.isArray(target)) {\n // allowMultiple: cannot decide which underlying column to write — skip and warn.\n if (typeof console !== \"undefined\") {\n console.warn(`[lib/grist] mapBack: cannot reverse-map allowMultiple field \"${name}\" without grist.mapColumnNamesBack`)\n }\n continue\n }\n out[target ?? name] = value\n }\n return out\n}\n\n/**\n * Subscribes to the selected row, applies `grist.mapColumnNames` so widget code\n * sees logical column names, and exposes `mapBack` for safe writes.\n */\nexport function useGristMappedRecord<T = Record<string, unknown>>(\n options?: GristReadyOptions\n): UseGristMappedRecordResult<T> {\n const requiredAccess = options?.requiredAccess ?? \"read table\"\n const { docApi, error: readyError } = useGristReady({\n requiredAccess,\n columns: options?.columns,\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n })\n const [rawRecord, setRawRecord] = useState<Record<string, unknown> | null>(null)\n const [mappedRecord, setMappedRecord] = useState<T | null>(null)\n const [mappings, setMappings] = useState<GristWidgetColumnMap | null>(null)\n\n useEffect(() => {\n if (!docApi) return\n return recordEvent.subscribe(({ record, mappings: nextMappings }) => {\n setRawRecord(record)\n setMappings(nextMappings)\n if (!record) {\n setMappedRecord(null)\n return\n }\n if (typeof grist.mapColumnNames === \"function\") {\n const mapped = grist.mapColumnNames(record)\n setMappedRecord(\n mapped !== null && mapped !== undefined ? (mapped as T) : null\n )\n return\n }\n setMappedRecord(record as T)\n })\n }, [docApi])\n\n const mapBack = useCallback(\n (patch: Partial<T>): Record<string, unknown> => {\n if (typeof grist.mapColumnNamesBack === \"function\") {\n return grist.mapColumnNamesBack(patch as Record<string, unknown>)\n }\n return manualMapBack<T>(patch, mappings)\n },\n [mappings]\n )\n\n const resolveColumnId = useCallback(\n (logicalName: keyof T & string): string | undefined => {\n const value = mappings?.[logicalName]\n if (Array.isArray(value)) return undefined\n return value ?? undefined\n },\n [mappings]\n )\n\n return {\n rawRecord,\n mappedRecord,\n mappings,\n loading: docApi === null && !readyError,\n error: readyError,\n mapBack,\n resolveColumnId,\n }\n}\n","import { useCallback, useState } from \"react\"\n\nimport { useRpcHeartbeatCoalesce } from \"../internal/hooks/use-rpc-heartbeat-coalesce\"\nimport { useGristReady } from \"../low-level-hooks/use-grist-ready\"\nimport type {\n GristMinimalRecord,\n GristReadyOptions,\n GristTableNewRecord,\n GristTableOpOptions,\n GristTableOperations,\n GristTableUpdateRecord,\n GristTableUpsertOptions,\n GristTableUpsertRecord,\n} from \"../types\"\n\nexport type GristTableOpsStatus = \"idle\" | \"running\" | \"error\"\n\nexport type UseGristTableOpsOptions = {\n /**\n * Table to operate on:\n * - `\"selected\"` (default): use `grist.selectedTable` (the widget's current table).\n * - any other string: use `grist.getTable(tableId)`.\n */\n tableId?: \"selected\" | string\n /** Defaults to `\"full\"` since these operations write to the document. */\n requiredAccess?: GristReadyOptions[\"requiredAccess\"]\n} & Pick<GristReadyOptions, \"columns\" | \"allowSelectBy\" | \"hasCustomOptions\" | \"onEditOptions\">\n\nexport type UseGristTableOpsResult = {\n status: GristTableOpsStatus\n error: string | null\n /** Resolves the runtime tableId (only meaningful when `tableId` is `\"selected\"`). */\n getTableId: () => Promise<string>\n create: (\n records: GristTableNewRecord | GristTableNewRecord[],\n opOptions?: GristTableOpOptions\n ) => Promise<GristMinimalRecord | GristMinimalRecord[]>\n update: (\n records: GristTableUpdateRecord | GristTableUpdateRecord[],\n opOptions?: GristTableOpOptions\n ) => Promise<void>\n upsert: (\n records: GristTableUpsertRecord | GristTableUpsertRecord[],\n opOptions?: GristTableUpsertOptions\n ) => Promise<void>\n destroy: (recordIds: number | number[]) => Promise<void>\n}\n\nfunction resolveOps(tableId: \"selected\" | string): GristTableOperations {\n if (tableId === \"selected\") {\n if (!grist.selectedTable) throw new Error(\"grist.selectedTable is not available\")\n return grist.selectedTable\n }\n if (typeof grist.getTable !== \"function\") {\n throw new Error(\"grist.getTable is not available in this Grist version\")\n }\n return grist.getTable(tableId)\n}\n\n/**\n * Strongly-typed CRUD wrapper around Grist's `TableOperations` (`grist.selectedTable`\n * or `grist.getTable(tableId)`). Prefer this over hand-rolled `applyUserActions`.\n *\n * @see https://support.getgrist.com/code/interfaces/TableOperations.TableOperations/\n */\nexport function useGristTableOps(options?: UseGristTableOpsOptions): UseGristTableOpsResult {\n const requiredAccess = options?.requiredAccess ?? \"full\"\n const tableIdOption: \"selected\" | string = options?.tableId ?? \"selected\"\n const { docApi, error: readyError } = useGristReady({\n requiredAccess,\n columns: options?.columns,\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n })\n\n const [status, setStatus] = useState<GristTableOpsStatus>(\"idle\")\n const [actionError, setActionError] = useState<string | null>(null)\n const coalesceRpc = useRpcHeartbeatCoalesce()\n\n // `resolveOps` is synchronous and idempotent (it only reads `grist.selectedTable`\n // / `grist.getTable`), so derive `ops` during render instead of via effect.\n let ops: GristTableOperations | null = null\n let resolveError: string | null = null\n if (docApi) {\n try {\n ops = resolveOps(tableIdOption)\n } catch (err) {\n resolveError = err instanceof Error ? err.message : String(err)\n }\n }\n\n const wrap = useCallback(\n async <T>(run: (ops: GristTableOperations) => Promise<T>): Promise<T> => {\n if (!ops) throw new Error(\"Grist table operations are not ready\")\n setStatus(\"running\")\n setActionError(null)\n try {\n const out = await coalesceRpc(() => run(ops))\n setStatus(\"idle\")\n return out\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n setActionError(message)\n setStatus(\"error\")\n throw err\n }\n },\n [ops, coalesceRpc]\n )\n\n const getTableId = useCallback(async () => {\n if (!ops) throw new Error(\"Grist table operations are not ready\")\n return ops.getTableId()\n }, [ops])\n\n const create = useCallback(\n (records: GristTableNewRecord | GristTableNewRecord[], opOptions?: GristTableOpOptions) =>\n wrap((o) => o.create(records, opOptions)),\n [wrap]\n )\n\n const update = useCallback(\n (records: GristTableUpdateRecord | GristTableUpdateRecord[], opOptions?: GristTableOpOptions) =>\n wrap((o) => o.update(records, opOptions)),\n [wrap]\n )\n\n const upsert = useCallback(\n (records: GristTableUpsertRecord | GristTableUpsertRecord[], opOptions?: GristTableUpsertOptions) =>\n wrap((o) => o.upsert(records, opOptions)),\n [wrap]\n )\n\n const destroy = useCallback(\n (recordIds: number | number[]) => wrap((o) => o.destroy(recordIds)),\n [wrap]\n )\n\n return {\n status: readyError || resolveError ? \"error\" : status,\n error: readyError ?? resolveError ?? actionError,\n getTableId,\n create,\n update,\n upsert,\n destroy,\n }\n}\n","import { useCallback, useContext, useEffect, useRef, useState } from \"react\"\n\nimport { tableDataToRows, type GristColumnarTable } from \"../helpers/grist-table-data\"\nimport { GristReadsContext } from \"../internal/contexts\"\nimport { useRpcHeartbeatCoalesce } from \"../internal/hooks/use-rpc-heartbeat-coalesce\"\nimport { useGristReady } from \"../low-level-hooks/use-grist-ready\"\nimport type { GristReadyOptions, GristRowRecord } from \"../types\"\n\nexport type UseGristRowsFromTableOptions<T> = {\n tableId: string\n /** Re-fetch on a fixed cadence (ms). Default: disabled. */\n pollIntervalMs?: number\n /** Map raw rows to a domain shape (e.g. `decodeGristValue` your columns). */\n transform?: (row: GristRowRecord) => GristRowRecord<T>\n requiredAccess?: GristReadyOptions[\"requiredAccess\"]\n} & Pick<GristReadyOptions, \"columns\" | \"allowSelectBy\" | \"hasCustomOptions\" | \"onEditOptions\">\n\nexport type UseGristRowsFromTableResult<T> = {\n rows: GristRowRecord<T>[] | null\n loading: boolean\n error: string | null\n /** Force a re-fetch (call after writes that should be reflected immediately). */\n refresh: () => Promise<void>\n}\n\n/**\n * Subscribes to a full table's rows via `docApi.fetchTable`.\n *\n * Unlike `useGristRecords` (which is bound to the widget's selected section),\n * this hook works against any table id and **doesn't auto-update on Grist\n * writes from elsewhere** — call `refresh()` after your own writes, or set\n * `pollIntervalMs` for polling.\n */\nexport function useGristRowsFromTable<T = Record<string, unknown>>(\n options: UseGristRowsFromTableOptions<T>\n): UseGristRowsFromTableResult<T> {\n const requiredAccess = options.requiredAccess ?? \"read table\"\n const { docApi, error: readyError } = useGristReady({\n requiredAccess,\n columns: options.columns,\n allowSelectBy: options.allowSelectBy,\n hasCustomOptions: options.hasCustomOptions,\n onEditOptions: options.onEditOptions,\n })\n\n // When inside a GristWidgetProvider, delegate to the provider's guarded\n // fetchTable so access-insufficient errors flow through readError → alerts.\n const providerFetchTable = useContext(GristReadsContext)?.fetchTable\n\n const [rows, setRows] = useState<GristRowRecord<T>[] | null>(null)\n const [loading, setLoading] = useState(false)\n const [fetchError, setFetchError] = useState<string | null>(null)\n const transformRef = useRef(options.transform)\n transformRef.current = options.transform\n const coalesceRpc = useRpcHeartbeatCoalesce()\n\n const refresh = useCallback(async () => {\n if (!docApi) return\n setLoading(true)\n setFetchError(null)\n try {\n const data = providerFetchTable\n ? await providerFetchTable(options.tableId)\n : ((await coalesceRpc(\n () => docApi.fetchTable(options.tableId) as Promise<GristColumnarTable>\n )) as GristColumnarTable)\n const raw = tableDataToRows(data)\n const t = transformRef.current\n setRows(t ? raw.map((r) => t(r)) : (raw as GristRowRecord<T>[]))\n } catch (err) {\n setFetchError(err instanceof Error ? err.message : String(err))\n setRows(null)\n } finally {\n setLoading(false)\n }\n }, [docApi, providerFetchTable, options.tableId, coalesceRpc])\n\n useEffect(() => {\n if (docApi) void refresh()\n }, [docApi, refresh])\n\n useEffect(() => {\n if (!docApi || !options.pollIntervalMs || options.pollIntervalMs <= 0) return\n const id = window.setInterval(() => void refresh(), options.pollIntervalMs)\n return () => window.clearInterval(id)\n }, [docApi, options.pollIntervalMs, refresh])\n\n return {\n rows,\n loading,\n error: readyError ?? fetchError,\n refresh,\n }\n}\n","import { useCallback, useEffect, useState } from \"react\"\n\nimport {\n fetchWithGristAuth as fetchWithGristAuthCore,\n getGristAccessToken,\n type GristAccessToken,\n} from \"../helpers/grist-fetch-with-auth\"\nimport { useGristReady } from \"../low-level-hooks/use-grist-ready\"\nimport type { GristReadyOptions } from \"../types\"\n\nexport type UseGristAccessTokenOptions = {\n /** Default for all token requests issued by this hook. */\n readOnly?: boolean\n /** Pre-fetch a token on mount so `token` is non-null when widgets render. */\n prefetch?: boolean\n /** Defaults to `\"full\"` since tokens are used for REST calls. */\n requiredAccess?: GristReadyOptions[\"requiredAccess\"]\n} & Pick<GristReadyOptions, \"columns\" | \"allowSelectBy\" | \"hasCustomOptions\" | \"onEditOptions\">\n\nexport type UseGristAccessTokenResult = {\n token: GristAccessToken | null\n loading: boolean\n error: string | null\n /** Request a fresh token (Grist tokens are short-lived; do not cache aggressively). */\n refresh: (overrides?: { readOnly?: boolean }) => Promise<GristAccessToken>\n /** `fetch()` against Grist's REST API with auth attached. */\n fetch: (path: string, init?: RequestInit & { readOnly?: boolean }) => Promise<Response>\n}\n\n/**\n * Exposes `docApi.getAccessToken` plus a ready-to-use `fetch` for calling\n * Grist's REST API (e.g. attachments, records, sql) from a widget.\n */\nexport function useGristAccessToken(options?: UseGristAccessTokenOptions): UseGristAccessTokenResult {\n const requiredAccess = options?.requiredAccess ?? \"full\"\n const readOnlyDefault = options?.readOnly ?? false\n const prefetch = options?.prefetch ?? false\n const { docApi, error: readyError } = useGristReady({\n requiredAccess,\n columns: options?.columns,\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n })\n\n const [token, setToken] = useState<GristAccessToken | null>(null)\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const refresh = useCallback(\n async (overrides?: { readOnly?: boolean }): Promise<GristAccessToken> => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n setLoading(true)\n setError(null)\n try {\n const next = await getGristAccessToken(docApi, { readOnly: overrides?.readOnly ?? readOnlyDefault })\n setToken(next)\n return next\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n setError(message)\n throw err\n } finally {\n setLoading(false)\n }\n },\n [docApi, readOnlyDefault]\n )\n\n const fetchFn = useCallback(\n (path: string, init?: RequestInit & { readOnly?: boolean }) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return fetchWithGristAuthCore(docApi, path, { readOnly: readOnlyDefault, ...init })\n },\n [docApi, readOnlyDefault]\n )\n\n useEffect(() => {\n if (docApi && prefetch) void refresh()\n }, [docApi, prefetch, refresh])\n\n return {\n token,\n loading,\n error: readyError ?? error,\n refresh,\n fetch: fetchFn,\n }\n}\n","import { useCallback, useEffect, useState } from \"react\"\n\nimport { useGristReady } from \"../low-level-hooks/use-grist-ready\"\nimport type { GristReadyOptions, GristWidgetColumnMap } from \"../types\"\n\nexport type UseGristSectionResult = {\n /** Current widget ↔ section column mappings, refreshed on demand. */\n mappings: GristWidgetColumnMap | null\n loading: boolean\n error: string | null\n /** Re-read mappings from `sectionApi`. */\n refresh: () => Promise<void>\n /**\n * Update the widget's declared `ColumnsToMap` (and other ready options) after\n * mount. Use this to dynamically request more columns once the user has\n * configured the widget.\n */\n configure: (options: GristReadyOptions) => Promise<void>\n}\n\n/**\n * Wraps Grist's `sectionApi` (`mappings()` + `configure()`) so widgets can\n * inspect/refresh the column mapping and re-declare requirements without\n * touching `grist` directly.\n */\nexport function useGristSection(options?: GristReadyOptions): UseGristSectionResult {\n const { docApi, error: readyError } = useGristReady({\n requiredAccess: options?.requiredAccess ?? \"read table\",\n columns: options?.columns,\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n })\n\n const [mappings, setMappings] = useState<GristWidgetColumnMap | null>(null)\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const refresh = useCallback(async () => {\n if (!docApi) return\n if (!grist.sectionApi?.mappings) {\n setError(\"grist.sectionApi.mappings is not available in this Grist version\")\n return\n }\n setLoading(true)\n setError(null)\n try {\n const next = await grist.sectionApi.mappings()\n setMappings(next)\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err))\n } finally {\n setLoading(false)\n }\n }, [docApi])\n\n const configure = useCallback(async (next: GristReadyOptions) => {\n if (!grist.sectionApi?.configure) {\n throw new Error(\"grist.sectionApi.configure is not available in this Grist version\")\n }\n await grist.sectionApi.configure(next)\n }, [])\n\n useEffect(() => {\n if (docApi) void refresh()\n }, [docApi, refresh])\n\n return {\n mappings,\n loading,\n error: readyError ?? error,\n refresh,\n configure,\n }\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\n\nimport { optionsEvent } from \"../internal/subscriptions\"\nimport { useGristReady } from \"../low-level-hooks/use-grist-ready\"\nimport type { GristReadyOptions } from \"../types\"\n\nexport type UseGristWidgetOptionsConfig<T> = {\n /** Default values returned before Grist responds and merged with stored options. */\n defaults: T\n /** Debounce window for `setOptions` writes (ms). Default: 250. */\n debounceMs?: number\n /**\n * Optional namespace inside `grist.setOptions`. When set, this hook reads/writes\n * `grist.setOption(namespace, value)` instead of the whole options blob — useful\n * to share the options bag with `hasCustomOptions` / unrelated widget state.\n */\n namespace?: string\n requiredAccess?: GristReadyOptions[\"requiredAccess\"]\n} & Pick<GristReadyOptions, \"columns\" | \"allowSelectBy\" | \"hasCustomOptions\" | \"onEditOptions\">\n\nexport type UseGristWidgetOptionsResult<T> = {\n options: T\n /** True until Grist has responded with the initial `onOptions` payload. */\n loading: boolean\n error: string | null\n /** Replace the options object (debounced write to Grist). */\n setOptions: (next: T) => void\n /** Patch a subset of keys (debounced write to Grist). */\n patchOptions: (patch: Partial<T>) => void\n /** Reset to `defaults` (immediate write to Grist). */\n reset: () => Promise<void>\n}\n\nfunction mergeWithDefaults<T>(defaults: T, stored: unknown, namespace?: string): T {\n if (stored === null || stored === undefined) return { ...defaults }\n const source = (namespace ? (stored as Record<string, unknown>)[namespace] : stored) as Partial<T> | undefined\n if (!source || typeof source !== \"object\") return { ...defaults }\n return { ...defaults, ...source }\n}\n\n/**\n * Persist a typed object of widget settings via `grist.onOptions` / `setOptions`.\n *\n * - Defaults are returned immediately (no flicker before Grist responds).\n * - Writes are debounced and batched.\n * - `hasCustomOptions` defaults to `true` so Grist exposes the gear icon — pass\n * `hasCustomOptions: false` to opt out.\n */\nexport function useGristWidgetOptions<T extends Record<string, unknown>>(\n config: UseGristWidgetOptionsConfig<T>\n): UseGristWidgetOptionsResult<T> {\n const requiredAccess = config.requiredAccess ?? \"read table\"\n const debounceMs = config.debounceMs ?? 250\n const hasCustomOptions = config.hasCustomOptions ?? true\n const { docApi, error: readyError } = useGristReady({\n requiredAccess,\n columns: config.columns,\n allowSelectBy: config.allowSelectBy,\n hasCustomOptions,\n onEditOptions: config.onEditOptions,\n })\n\n const defaultsRef = useRef(config.defaults)\n useEffect(() => {\n defaultsRef.current = config.defaults\n }, [config.defaults])\n\n const [options, setOptionsState] = useState<T>(() => ({ ...config.defaults }))\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const lastWrittenRef = useRef<T | null>(null)\n const debounceRef = useRef<number | null>(null)\n\n // Subscribe to remote changes (initial + external edits)\n useEffect(() => {\n if (!docApi) return\n return optionsEvent.subscribe(({ options: stored }) => {\n const merged = mergeWithDefaults(defaultsRef.current, stored, config.namespace)\n lastWrittenRef.current = merged\n setOptionsState(merged)\n setLoading(false)\n })\n }, [docApi, config.namespace])\n\n const flushWrite = useCallback(\n async (value: T) => {\n try {\n if (config.namespace) {\n await grist.setOption(config.namespace, value)\n } else {\n await grist.setOptions({ ...value })\n }\n lastWrittenRef.current = value\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err))\n }\n },\n [config.namespace]\n )\n\n const scheduleWrite = useCallback(\n (value: T) => {\n if (debounceRef.current) window.clearTimeout(debounceRef.current)\n debounceRef.current = window.setTimeout(() => {\n debounceRef.current = null\n void flushWrite(value)\n }, debounceMs)\n },\n [debounceMs, flushWrite]\n )\n\n useEffect(() => {\n return () => {\n if (debounceRef.current) window.clearTimeout(debounceRef.current)\n }\n }, [])\n\n const setOptionsApi = useCallback(\n (next: T) => {\n setOptionsState(next)\n scheduleWrite(next)\n },\n [scheduleWrite]\n )\n\n const patchOptionsApi = useCallback(\n (patch: Partial<T>) => {\n setOptionsState((prev) => {\n const next = { ...prev, ...patch }\n scheduleWrite(next)\n return next\n })\n },\n [scheduleWrite]\n )\n\n const reset = useCallback(async () => {\n if (debounceRef.current) {\n window.clearTimeout(debounceRef.current)\n debounceRef.current = null\n }\n const next = { ...defaultsRef.current }\n setOptionsState(next)\n await flushWrite(next)\n }, [flushWrite])\n\n return useMemo(\n () => ({\n options,\n loading,\n error: readyError ?? error,\n setOptions: setOptionsApi,\n patchOptions: patchOptionsApi,\n reset,\n }),\n [options, loading, readyError, error, setOptionsApi, patchOptionsApi, reset]\n )\n}\n","import { useCallback, useEffect, useState } from \"react\"\n\nimport type { GristColumnarTable } from \"./helpers/grist-table-data\"\nimport { useGristReady } from \"./low-level-hooks/use-grist-ready\"\nimport type { GristFetchSelectedOptions, GristReadyOptions, GristRequiredAccess } from \"./types\"\n\nexport type UseGristTableOptions = {\n requiredAccess?: GristRequiredAccess\n /**\n * `'current'` (default): follow the widget’s selected table.\n * Any other string: fixed table id (no `grist.selectedTable` polling).\n */\n tableId?: \"current\" | string\n} & Pick<GristReadyOptions, \"columns\" | \"allowSelectBy\" | \"hasCustomOptions\" | \"onEditOptions\">\n\nexport type UseGristTableResult = {\n tableId: string | null\n loading: boolean\n error: string | null\n refresh: () => Promise<void>\n fetchTable: (targetTableId: string) => Promise<GristColumnarTable>\n listTables: () => Promise<string[]>\n getDocName: () => Promise<string>\n fetchSelectedTable: (fetchOptions?: GristFetchSelectedOptions) => Promise<GristColumnarTable>\n fetchSelectedRecord: (rowId: number, fetchOptions?: GristFetchSelectedOptions) => Promise<Record<string, unknown>>\n}\n\nfunction isCurrentMode(option: string | undefined): boolean {\n return option === undefined || option === \"current\"\n}\n\n/**\n * Selected or fixed table id plus document reads — no raw `docApi` on the result.\n */\nexport function useGristTable(options?: UseGristTableOptions): UseGristTableResult {\n const requiredAccess = options?.requiredAccess ?? \"read table\"\n const tableIdOption = options?.tableId ?? \"current\"\n const { docApi, error: readyError } = useGristReady({\n requiredAccess,\n columns: options?.columns,\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n })\n const [tableId, setTableId] = useState<string | null>(null)\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const fetchTable = useCallback(\n async (targetTableId: string) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return docApi.fetchTable(targetTableId) as Promise<GristColumnarTable>\n },\n [docApi]\n )\n\n const listTables = useCallback(async () => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n const out = await Promise.resolve(docApi.listTables())\n return [...out]\n }, [docApi])\n\n const getDocName = useCallback(async () => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return String(await Promise.resolve(docApi.getDocName()))\n }, [docApi])\n\n const fetchSelectedTable = useCallback(\n async (fetchOptions?: GristFetchSelectedOptions) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n const impl = docApi.fetchSelectedTable ?? grist.fetchSelectedTable\n if (!impl) throw new Error(\"fetchSelectedTable is not available in this Grist version\")\n const merged: GristFetchSelectedOptions = { keepEncoded: false, format: \"rows\", ...fetchOptions }\n return (await impl(merged)) as GristColumnarTable\n },\n [docApi]\n )\n\n const fetchSelectedRecord = useCallback(\n async (rowId: number, fetchOptions?: GristFetchSelectedOptions) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n const impl = docApi.fetchSelectedRecord ?? grist.fetchSelectedRecord\n if (!impl) throw new Error(\"fetchSelectedRecord is not available in this Grist version\")\n const merged: GristFetchSelectedOptions = { keepEncoded: false, format: \"rows\", ...fetchOptions }\n return (await impl(rowId, merged)) as Record<string, unknown>\n },\n [docApi]\n )\n\n const refresh = useCallback(async () => {\n if (!docApi) return\n if (!isCurrentMode(tableIdOption)) {\n setTableId(tableIdOption)\n setError(null)\n return\n }\n setLoading(true)\n setError(null)\n try {\n const next = await grist.selectedTable?.getTableId()\n setTableId(next ?? null)\n } catch (err) {\n setTableId(null)\n setError(err instanceof Error ? err.message : String(err))\n } finally {\n setLoading(false)\n }\n }, [docApi, tableIdOption])\n\n useEffect(() => {\n if (docApi) void refresh()\n }, [docApi, refresh])\n\n return {\n tableId,\n loading,\n error: readyError ?? error,\n refresh,\n fetchTable,\n listTables,\n getDocName,\n fetchSelectedTable,\n fetchSelectedRecord,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUO,SAAS,qBAAqB,SAAuD;AAC1F,QAAM,EAAE,YAAY,IAAI,aAAa,OAAO;AAC5C,SAAO;AACT;;;ACGA,SAAS,WAAW,SAAS,QAAQ,4BAA4B;AAqC1D,SAAS,kBAAkB,UAAoC,CAAC,GAA4B;AAGjG,QAAM,aAAa,OAAO,OAAO;AACjC,aAAW,UAAU;AACrB,QAAM,aAAa,OAA+B,IAAI;AACtD,MAAI,WAAW,YAAY,MAAM;AAO/B,eAAW,UAAU,4BAA4B;AAAA,MAC/C,GAAG;AAAA,MACH,WAAW;AAAA,QACT,WAAW,CAAC,YAAY,iBAAiB,OAAO;AAAA,QAChD,GAAG,QAAQ;AAAA,MACb;AAAA,MACA,gBAAgB,MAAM;AACpB,iCAAyB;AACzB,gBAAQ,iBAAiB;AAAA,MAC3B;AAAA,IACF,CAAC;AAAA,EACH;AACA,QAAM,UAAU,WAAW;AAE3B,YAAU,MAAM;AACd,YAAQ,MAAM;AACd,WAAO,MAAM;AACX,cAAQ,KAAK;AAAA,IACf;AAAA,EACF,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,WAAW;AAAA,IACf,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR;AAAA,EACF;AAEA,QAAM,YAAY;AAAA,IAChB,OAAO;AAAA,MACL,QAAQ,aAAa,QAAQ;AAAA,MAC7B,OAAO,mBAAmB,QAAQ;AAAA,MAClC,cAAc,mBAAmB,QAAQ;AAAA,IAC3C;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA,QAAQ,UAAU;AAAA,MAClB,OAAO,UAAU;AAAA,MACjB,cAAc,UAAU;AAAA,MACxB,QAAQ,QAAQ;AAAA,MAChB,SAAS,QAAQ;AAAA,IACnB;AAAA,IACA,CAAC,UAAU,WAAW,OAAO;AAAA,EAC/B;AACF;AAOO,SAAS,qBACd,UAAoC,CAAC,GAClB;AACnB,SAAO,kBAAkB,OAAO,EAAE;AACpC;;;AC9GA,SAAS,WAAAA,UAAS,wBAAAC,6BAA4B;AAsB9C,IAAM,gBAAgB,MAAM,MAAM;AAAC;AACnC,IAAM,qBAAqB,MAAM,qBAAqB;AAO/C,SAAS,2BAAkE;AAChF,QAAM,UAAU,wBAAwB;AAExC,QAAM,WAAWC;AAAA,IACf,SAAS,aAAa;AAAA,IACtB,SAAS,eAAe;AAAA,IACxB;AAAA,EACF;AAEA,SAAOC,SAAQ,MAAM;AACnB,QAAI,CAAC,QAAS,QAAO;AACrB,WAAO;AAAA,MACL;AAAA,MACA,QAAQ,aAAa,QAAQ;AAAA,MAC7B,OAAO,mBAAmB,QAAQ;AAAA,MAClC,cAAc,mBAAmB,QAAQ;AAAA,MACzC,QAAQ,QAAQ;AAAA,MAChB,SAAS,QAAQ;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,SAAS,QAAQ,CAAC;AACxB;;;AChDA;AAAA,EACE;AAAA,EACA;AAAA,EACA,aAAAC;AAAA,EACA,WAAAC;AAAA,EACA,UAAAC;AAAA,EACA,wBAAAC;AAAA,OAEK;AAoGH;AAvEJ,IAAM,6BAA6B,cAAiD,IAAI;AAejF,SAAS,uBAAuB,EAAE,SAAS,SAAS,GAAgC;AAIzF,QAAM,aAAaC,QAA+B,IAAI;AACtD,MAAI,WAAW,YAAY,MAAM;AAS/B,eAAW,UAAU,4BAA4B;AAAA,MAC/C,GAAG;AAAA,MACH,WAAW;AAAA,QACT,WAAW,CAAC,YAAY,iBAAiB,OAAO;AAAA,QAChD,GAAG,SAAS;AAAA,MACd;AAAA,MACA,gBAAgB,MAAM;AACpB,iCAAyB;AACzB,iBAAS,iBAAiB;AAAA,MAC5B;AAAA,IACF,CAAC;AAAA,EACH;AACA,QAAM,UAAU,WAAW;AAE3B,EAAAC,WAAU,MAAM;AACd,YAAQ,MAAM;AACd,WAAO,MAAM;AACX,cAAQ,KAAK;AAAA,IACf;AAAA,EACF,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,WAAWC;AAAA,IACf,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR;AAAA,EACF;AAEA,QAAM,QAAQC;AAAA,IACZ,OAAO;AAAA,MACL;AAAA,MACA,QAAQ,aAAa,QAAQ;AAAA,MAC7B,OAAO,mBAAmB,QAAQ;AAAA,MAClC,cAAc,mBAAmB,QAAQ;AAAA,MACzC,QAAQ,QAAQ;AAAA,MAChB,SAAS,QAAQ;AAAA,MACjB,kBAAkB,QAAQ;AAAA,MAC1B,kBAAkB,QAAQ;AAAA,IAC5B;AAAA,IACA,CAAC,UAAU,OAAO;AAAA,EACpB;AAEA,SACE,oBAAC,2BAA2B,UAA3B,EAAoC,OAClC,UACH;AAEJ;AASO,SAAS,2BAAuD;AACrE,QAAM,MAAM,WAAW,0BAA0B;AACjD,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,mCAAsE;AACpF,SAAO,WAAW,0BAA0B;AAC9C;;;ACtJA,SAAS,aAAAC,YAAW,UAAAC,SAAQ,gBAAgB;AAoBrC,SAAS,eACd,IACA,SACkC;AAClC,QAAM,QAAQC,QAAO,EAAE;AACvB,EAAAC,WAAU,MAAM;AACd,UAAM,UAAU;AAAA,EAClB,GAAG,CAAC,EAAE,CAAC;AAEP,QAAM,CAAC,UAAU,WAAW,IAAI,SAAsC,IAAI;AAC1E,QAAM,EAAE,QAAQ,OAAO,WAAW,IAAI,cAAc;AAAA,IAClD,gBAAgB,SAAS,kBAAkB;AAAA,IAC3C,SAAS,SAAS;AAAA,IAClB,eAAe,SAAS;AAAA,IACxB,kBAAkB,SAAS;AAAA,IAC3B,eAAe,SAAS;AAAA,EAC1B,CAAC;AAED,EAAAA,WAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,WAAO,YAAY,UAAU,CAAC,EAAE,QAAQ,UAAU,aAAa,MAAM;AACnE,kBAAY,YAAY;AACxB,YAAM,QAAQ,QAAQ,YAAY;AAAA,IACpC,CAAC;AAAA,EACH,GAAG,CAAC,MAAM,CAAC;AAEX,SAAO;AAAA,IACL,SAAS,WAAW,QAAQ,CAAC;AAAA,IAC7B,OAAO;AAAA,IACP;AAAA,EACF;AACF;;;ACnDA,SAAS,aAAAC,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;AAWrC,SAAS,gBACd,IACA,SACkC;AAClC,QAAM,QAAQC,QAAO,EAAE;AACvB,EAAAC,WAAU,MAAM;AACd,UAAM,UAAU;AAAA,EAClB,GAAG,CAAC,EAAE,CAAC;AAEP,QAAM,CAAC,UAAU,WAAW,IAAIC,UAAsC,IAAI;AAC1E,QAAM,EAAE,QAAQ,OAAO,WAAW,IAAI,cAAc;AAAA,IAClD,gBAAgB,SAAS,kBAAkB;AAAA,IAC3C,SAAS,SAAS;AAAA,IAClB,eAAe,SAAS;AAAA,IACxB,kBAAkB,SAAS;AAAA,IAC3B,eAAe,SAAS;AAAA,EAC1B,CAAC;AAED,EAAAD,WAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,WAAO,aAAa,UAAU,CAAC,EAAE,SAAS,UAAU,aAAa,MAAM;AACrE,kBAAY,YAAY;AACxB,YAAM,QAAQ,SAAS,YAAY;AAAA,IACrC,CAAC;AAAA,EACH,GAAG,CAAC,MAAM,CAAC;AAEX,SAAO;AAAA,IACL,SAAS,WAAW,QAAQ,CAAC;AAAA,IAC7B,OAAO;AAAA,IACP;AAAA,EACF;AACF;;;AC1CA,SAAS,aAAAE,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;AAuBrC,SAAS,kBAAkB,SAAsD;AACtF,QAAM,EAAE,QAAQ,OAAO,WAAW,IAAI,cAAc;AAAA,IAClD,gBAAgB,SAAS,kBAAkB;AAAA,IAC3C,SAAS,SAAS;AAAA,IAClB,eAAe,SAAS;AAAA,IACxB,kBAAkB,SAAS;AAAA,IAC3B,eAAe,SAAS;AAAA,EAC1B,CAAC;AAED,QAAM,CAAC,aAAa,cAAc,IAAIC,UAAS,KAAK;AACpD,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAsC,IAAI;AAC1E,QAAM,gBAAgBC,QAAO,KAAK;AAElC,EAAAC,WAAU,MAAM;AACd,QAAI,CAAC,UAAU,cAAc,QAAS;AACtC,QAAI,OAAO,MAAM,gBAAgB,WAAY;AAC7C,kBAAc,UAAU;AACxB,WAAO,eAAe,UAAU,CAAC,EAAE,UAAU,aAAa,MAAM;AAC9D,qBAAe,IAAI;AACnB,kBAAY,YAAY;AAAA,IAC1B,CAAC;AAAA,EACH,GAAG,CAAC,MAAM,CAAC;AAEX,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,SAAS,WAAW,QAAQ,CAAC;AAAA,IAC7B,OAAO;AAAA,EACT;AACF;;;ACpDA,SAAS,aAAa,YAAAC,iBAAgB;AA6D/B,SAAS,gBAAgB,SAAyD;AACvF,QAAM,iBAAiB,SAAS,kBAAkB;AAClD,QAAM,EAAE,QAAQ,OAAO,WAAW,IAAI,cAAc;AAAA,IAClD;AAAA,IACA,SAAS,SAAS;AAAA,IAClB,eAAe,SAAS;AAAA,IACxB,kBAAkB,SAAS;AAAA,IAC3B,eAAe,SAAS;AAAA,EAC1B,CAAC;AACD,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAA6B,MAAM;AAC/D,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAwB,IAAI;AAClE,QAAM,cAAc,wBAAwB;AAE5C,QAAM,QAAQ;AAAA,IACZ,OAAO,SAAiC,iBAAkE;AACxG,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,2BAA2B;AACxD,gBAAU,SAAS;AACnB,qBAAe,IAAI;AACnB,UAAI;AACF,cAAM,MAAM,MAAM,YAAY,MAAM,OAAO,iBAAiB,SAAS,YAAY,CAAC;AAClF,kBAAU,MAAM;AAChB,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,cAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,uBAAe,OAAO;AACtB,kBAAU,OAAO;AACjB,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,WAAW;AAAA,EACtB;AAEA,QAAM,eAAe;AAAA,IACnB,CAAC,SAAiB,UAAkB,OAAgC,iBAClE,MAAM,CAAC,wBAAwB,SAAS,UAAU,KAAK,CAAC,GAAG,YAAY;AAAA,IACzE,CAAC,KAAK;AAAA,EACR;AAEA,QAAM,YAAY;AAAA,IAChB,CAAC,SAAiB,QAAiC,iBACjD,MAAM,CAAC,qBAAqB,SAAS,MAAM,CAAC,GAAG,YAAY;AAAA,IAC7D,CAAC,KAAK;AAAA,EACR;AAEA,QAAM,eAAe;AAAA,IACnB,CAAC,SAAiB,UAAkB,iBAClC,MAAM,CAAC,wBAAwB,SAAS,QAAQ,CAAC,GAAG,YAAY;AAAA,IAClE,CAAC,KAAK;AAAA,EACR;AAEA,QAAM,gBAAgB;AAAA,IACpB,CAAC,SAAiB,QAAmC,iBACnD,MAAM,CAAC,yBAAyB,SAAS,MAAM,CAAC,GAAG,YAAY;AAAA,IACjE,CAAC,KAAK;AAAA,EACR;AAEA,QAAM,mBAAmB;AAAA,IACvB,CAAC,SAAiB,QAAkB,eAA0C,iBAC5E,MAAM,CAAC,4BAA4B,SAAS,QAAQ,aAAa,CAAC,GAAG,YAAY;AAAA,IACnF,CAAC,KAAK;AAAA,EACR;AAEA,QAAM,mBAAmB;AAAA,IACvB,CAAC,SAAiB,QAAkB,iBAClC,MAAM,CAAC,4BAA4B,SAAS,MAAM,CAAC,GAAG,YAAY;AAAA,IACpE,CAAC,KAAK;AAAA,EACR;AAEA,SAAO;AAAA,IACL,QAAQ,aAAa,UAAU;AAAA,IAC/B,OAAO,cAAc;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC5IA,SAAS,eAAAC,cAAa,aAAAC,YAAW,YAAAC,iBAAgB;AAyBjD,SAAS,cAAiB,OAAmB,UAAgE;AAC3G,MAAI,CAAC,SAAU,QAAO,EAAE,GAAI,MAAkC;AAC9D,QAAM,MAA+B,CAAC;AACtC,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,KAAgC,GAAG;AAC5E,UAAM,SAAS,SAAS,IAAI;AAC5B,QAAI,MAAM,QAAQ,MAAM,GAAG;AAEzB,UAAI,OAAO,YAAY,aAAa;AAClC,gBAAQ,KAAK,gEAAgE,IAAI,oCAAoC;AAAA,MACvH;AACA;AAAA,IACF;AACA,QAAI,UAAU,IAAI,IAAI;AAAA,EACxB;AACA,SAAO;AACT;AAMO,SAAS,qBACd,SAC+B;AAC/B,QAAM,iBAAiB,SAAS,kBAAkB;AAClD,QAAM,EAAE,QAAQ,OAAO,WAAW,IAAI,cAAc;AAAA,IAClD;AAAA,IACA,SAAS,SAAS;AAAA,IAClB,eAAe,SAAS;AAAA,IACxB,kBAAkB,SAAS;AAAA,IAC3B,eAAe,SAAS;AAAA,EAC1B,CAAC;AACD,QAAM,CAAC,WAAW,YAAY,IAAIC,UAAyC,IAAI;AAC/E,QAAM,CAAC,cAAc,eAAe,IAAIA,UAAmB,IAAI;AAC/D,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAsC,IAAI;AAE1E,EAAAC,WAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,WAAO,YAAY,UAAU,CAAC,EAAE,QAAQ,UAAU,aAAa,MAAM;AACnE,mBAAa,MAAM;AACnB,kBAAY,YAAY;AACxB,UAAI,CAAC,QAAQ;AACX,wBAAgB,IAAI;AACpB;AAAA,MACF;AACA,UAAI,OAAO,MAAM,mBAAmB,YAAY;AAC9C,cAAM,SAAS,MAAM,eAAe,MAAM;AAC1C;AAAA,UACE,WAAW,QAAQ,WAAW,SAAa,SAAe;AAAA,QAC5D;AACA;AAAA,MACF;AACA,sBAAgB,MAAW;AAAA,IAC7B,CAAC;AAAA,EACH,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,UAAUC;AAAA,IACd,CAAC,UAA+C;AAC9C,UAAI,OAAO,MAAM,uBAAuB,YAAY;AAClD,eAAO,MAAM,mBAAmB,KAAgC;AAAA,MAClE;AACA,aAAO,cAAiB,OAAO,QAAQ;AAAA,IACzC;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,QAAM,kBAAkBA;AAAA,IACtB,CAAC,gBAAsD;AACrD,YAAM,QAAQ,WAAW,WAAW;AACpC,UAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,aAAO,SAAS;AAAA,IAClB;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,WAAW,QAAQ,CAAC;AAAA,IAC7B,OAAO;AAAA,IACP;AAAA,IACA;AAAA,EACF;AACF;;;AC7GA,SAAS,eAAAC,cAAa,YAAAC,iBAAgB;AAgDtC,SAAS,WAAW,SAAoD;AACtE,MAAI,YAAY,YAAY;AAC1B,QAAI,CAAC,MAAM,cAAe,OAAM,IAAI,MAAM,sCAAsC;AAChF,WAAO,MAAM;AAAA,EACf;AACA,MAAI,OAAO,MAAM,aAAa,YAAY;AACxC,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AACA,SAAO,MAAM,SAAS,OAAO;AAC/B;AAQO,SAAS,iBAAiB,SAA2D;AAC1F,QAAM,iBAAiB,SAAS,kBAAkB;AAClD,QAAM,gBAAqC,SAAS,WAAW;AAC/D,QAAM,EAAE,QAAQ,OAAO,WAAW,IAAI,cAAc;AAAA,IAClD;AAAA,IACA,SAAS,SAAS;AAAA,IAClB,eAAe,SAAS;AAAA,IACxB,kBAAkB,SAAS;AAAA,IAC3B,eAAe,SAAS;AAAA,EAC1B,CAAC;AAED,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAA8B,MAAM;AAChE,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAwB,IAAI;AAClE,QAAM,cAAc,wBAAwB;AAI5C,MAAI,MAAmC;AACvC,MAAI,eAA8B;AAClC,MAAI,QAAQ;AACV,QAAI;AACF,YAAM,WAAW,aAAa;AAAA,IAChC,SAAS,KAAK;AACZ,qBAAe,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IAChE;AAAA,EACF;AAEA,QAAM,OAAOC;AAAA,IACX,OAAU,QAA+D;AACvE,UAAI,CAAC,IAAK,OAAM,IAAI,MAAM,sCAAsC;AAChE,gBAAU,SAAS;AACnB,qBAAe,IAAI;AACnB,UAAI;AACF,cAAM,MAAM,MAAM,YAAY,MAAM,IAAI,GAAG,CAAC;AAC5C,kBAAU,MAAM;AAChB,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,cAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,uBAAe,OAAO;AACtB,kBAAU,OAAO;AACjB,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,CAAC,KAAK,WAAW;AAAA,EACnB;AAEA,QAAM,aAAaA,aAAY,YAAY;AACzC,QAAI,CAAC,IAAK,OAAM,IAAI,MAAM,sCAAsC;AAChE,WAAO,IAAI,WAAW;AAAA,EACxB,GAAG,CAAC,GAAG,CAAC;AAER,QAAM,SAASA;AAAA,IACb,CAAC,SAAsD,cACrD,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS,SAAS,CAAC;AAAA,IAC1C,CAAC,IAAI;AAAA,EACP;AAEA,QAAM,SAASA;AAAA,IACb,CAAC,SAA4D,cAC3D,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS,SAAS,CAAC;AAAA,IAC1C,CAAC,IAAI;AAAA,EACP;AAEA,QAAM,SAASA;AAAA,IACb,CAAC,SAA4D,cAC3D,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS,SAAS,CAAC;AAAA,IAC1C,CAAC,IAAI;AAAA,EACP;AAEA,QAAM,UAAUA;AAAA,IACd,CAAC,cAAiC,KAAK,CAAC,MAAM,EAAE,QAAQ,SAAS,CAAC;AAAA,IAClE,CAAC,IAAI;AAAA,EACP;AAEA,SAAO;AAAA,IACL,QAAQ,cAAc,eAAe,UAAU;AAAA,IAC/C,OAAO,cAAc,gBAAgB;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACpJA,SAAS,eAAAC,cAAa,cAAAC,aAAY,aAAAC,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;AAiC9D,SAAS,sBACd,SACgC;AAChC,QAAM,iBAAiB,QAAQ,kBAAkB;AACjD,QAAM,EAAE,QAAQ,OAAO,WAAW,IAAI,cAAc;AAAA,IAClD;AAAA,IACA,SAAS,QAAQ;AAAA,IACjB,eAAe,QAAQ;AAAA,IACvB,kBAAkB,QAAQ;AAAA,IAC1B,eAAe,QAAQ;AAAA,EACzB,CAAC;AAID,QAAM,qBAAqBC,YAAW,iBAAiB,GAAG;AAE1D,QAAM,CAAC,MAAM,OAAO,IAAIC,UAAqC,IAAI;AACjE,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,KAAK;AAC5C,QAAM,CAAC,YAAY,aAAa,IAAIA,UAAwB,IAAI;AAChE,QAAM,eAAeC,QAAO,QAAQ,SAAS;AAC7C,eAAa,UAAU,QAAQ;AAC/B,QAAM,cAAc,wBAAwB;AAE5C,QAAM,UAAUC,aAAY,YAAY;AACtC,QAAI,CAAC,OAAQ;AACb,eAAW,IAAI;AACf,kBAAc,IAAI;AAClB,QAAI;AACF,YAAM,OAAO,qBACT,MAAM,mBAAmB,QAAQ,OAAO,IACtC,MAAM;AAAA,QACN,MAAM,OAAO,WAAW,QAAQ,OAAO;AAAA,MACzC;AACJ,YAAM,MAAM,gBAAgB,IAAI;AAChC,YAAM,IAAI,aAAa;AACvB,cAAQ,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAK,GAA2B;AAAA,IACjE,SAAS,KAAK;AACZ,oBAAc,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC9D,cAAQ,IAAI;AAAA,IACd,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,QAAQ,oBAAoB,QAAQ,SAAS,WAAW,CAAC;AAE7D,EAAAC,WAAU,MAAM;AACd,QAAI,OAAQ,MAAK,QAAQ;AAAA,EAC3B,GAAG,CAAC,QAAQ,OAAO,CAAC;AAEpB,EAAAA,WAAU,MAAM;AACd,QAAI,CAAC,UAAU,CAAC,QAAQ,kBAAkB,QAAQ,kBAAkB,EAAG;AACvE,UAAM,KAAK,OAAO,YAAY,MAAM,KAAK,QAAQ,GAAG,QAAQ,cAAc;AAC1E,WAAO,MAAM,OAAO,cAAc,EAAE;AAAA,EACtC,GAAG,CAAC,QAAQ,QAAQ,gBAAgB,OAAO,CAAC;AAE5C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,OAAO,cAAc;AAAA,IACrB;AAAA,EACF;AACF;;;AC7FA,SAAS,eAAAC,cAAa,aAAAC,YAAW,YAAAC,iBAAgB;AAiC1C,SAAS,oBAAoB,SAAiE;AACnG,QAAM,iBAAiB,SAAS,kBAAkB;AAClD,QAAM,kBAAkB,SAAS,YAAY;AAC7C,QAAM,WAAW,SAAS,YAAY;AACtC,QAAM,EAAE,QAAQ,OAAO,WAAW,IAAI,cAAc;AAAA,IAClD;AAAA,IACA,SAAS,SAAS;AAAA,IAClB,eAAe,SAAS;AAAA,IACxB,kBAAkB,SAAS;AAAA,IAC3B,eAAe,SAAS;AAAA,EAC1B,CAAC;AAED,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAAkC,IAAI;AAChE,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,KAAK;AAC5C,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAwB,IAAI;AAEtD,QAAM,UAAUC;AAAA,IACd,OAAO,cAAkE;AACvE,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,iBAAW,IAAI;AACf,eAAS,IAAI;AACb,UAAI;AACF,cAAM,OAAO,MAAM,oBAAoB,QAAQ,EAAE,UAAU,WAAW,YAAY,gBAAgB,CAAC;AACnG,iBAAS,IAAI;AACb,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,cAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,iBAAS,OAAO;AAChB,cAAM;AAAA,MACR,UAAE;AACA,mBAAW,KAAK;AAAA,MAClB;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,eAAe;AAAA,EAC1B;AAEA,QAAM,UAAUA;AAAA,IACd,CAAC,MAAc,SAAgD;AAC7D,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,aAAO,mBAAuB,QAAQ,MAAM,EAAE,UAAU,iBAAiB,GAAG,KAAK,CAAC;AAAA,IACpF;AAAA,IACA,CAAC,QAAQ,eAAe;AAAA,EAC1B;AAEA,EAAAC,WAAU,MAAM;AACd,QAAI,UAAU,SAAU,MAAK,QAAQ;AAAA,EACvC,GAAG,CAAC,QAAQ,UAAU,OAAO,CAAC;AAE9B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,OAAO,cAAc;AAAA,IACrB;AAAA,IACA,OAAO;AAAA,EACT;AACF;;;ACxFA,SAAS,eAAAC,cAAa,aAAAC,YAAW,YAAAC,iBAAgB;AAyB1C,SAAS,gBAAgB,SAAoD;AAClF,QAAM,EAAE,QAAQ,OAAO,WAAW,IAAI,cAAc;AAAA,IAClD,gBAAgB,SAAS,kBAAkB;AAAA,IAC3C,SAAS,SAAS;AAAA,IAClB,eAAe,SAAS;AAAA,IACxB,kBAAkB,SAAS;AAAA,IAC3B,eAAe,SAAS;AAAA,EAC1B,CAAC;AAED,QAAM,CAAC,UAAU,WAAW,IAAIC,UAAsC,IAAI;AAC1E,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,KAAK;AAC5C,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAwB,IAAI;AAEtD,QAAM,UAAUC,aAAY,YAAY;AACtC,QAAI,CAAC,OAAQ;AACb,QAAI,CAAC,MAAM,YAAY,UAAU;AAC/B,eAAS,kEAAkE;AAC3E;AAAA,IACF;AACA,eAAW,IAAI;AACf,aAAS,IAAI;AACb,QAAI;AACF,YAAM,OAAO,MAAM,MAAM,WAAW,SAAS;AAC7C,kBAAY,IAAI;AAAA,IAClB,SAAS,KAAK;AACZ,eAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAC3D,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,YAAYA,aAAY,OAAO,SAA4B;AAC/D,QAAI,CAAC,MAAM,YAAY,WAAW;AAChC,YAAM,IAAI,MAAM,mEAAmE;AAAA,IACrF;AACA,UAAM,MAAM,WAAW,UAAU,IAAI;AAAA,EACvC,GAAG,CAAC,CAAC;AAEL,EAAAC,WAAU,MAAM;AACd,QAAI,OAAQ,MAAK,QAAQ;AAAA,EAC3B,GAAG,CAAC,QAAQ,OAAO,CAAC;AAEpB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,OAAO,cAAc;AAAA,IACrB;AAAA,IACA;AAAA,EACF;AACF;;;AC1EA,SAAS,eAAAC,cAAa,aAAAC,aAAW,WAAAC,UAAS,UAAAC,SAAQ,YAAAC,kBAAgB;AAiClE,SAAS,kBAAqB,UAAa,QAAiB,WAAuB;AACjF,MAAI,WAAW,QAAQ,WAAW,OAAW,QAAO,EAAE,GAAG,SAAS;AAClE,QAAM,SAAU,YAAa,OAAmC,SAAS,IAAI;AAC7E,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO,EAAE,GAAG,SAAS;AAChE,SAAO,EAAE,GAAG,UAAU,GAAG,OAAO;AAClC;AAUO,SAAS,sBACd,QACgC;AAChC,QAAM,iBAAiB,OAAO,kBAAkB;AAChD,QAAM,aAAa,OAAO,cAAc;AACxC,QAAM,mBAAmB,OAAO,oBAAoB;AACpD,QAAM,EAAE,QAAQ,OAAO,WAAW,IAAI,cAAc;AAAA,IAClD;AAAA,IACA,SAAS,OAAO;AAAA,IAChB,eAAe,OAAO;AAAA,IACtB;AAAA,IACA,eAAe,OAAO;AAAA,EACxB,CAAC;AAED,QAAM,cAAcC,QAAO,OAAO,QAAQ;AAC1C,EAAAC,YAAU,MAAM;AACd,gBAAY,UAAU,OAAO;AAAA,EAC/B,GAAG,CAAC,OAAO,QAAQ,CAAC;AAEpB,QAAM,CAAC,SAAS,eAAe,IAAIC,WAAY,OAAO,EAAE,GAAG,OAAO,SAAS,EAAE;AAC7E,QAAM,CAAC,SAAS,UAAU,IAAIA,WAAS,IAAI;AAC3C,QAAM,CAAC,OAAO,QAAQ,IAAIA,WAAwB,IAAI;AACtD,QAAM,iBAAiBF,QAAiB,IAAI;AAC5C,QAAM,cAAcA,QAAsB,IAAI;AAG9C,EAAAC,YAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,WAAO,aAAa,UAAU,CAAC,EAAE,SAAS,OAAO,MAAM;AACrD,YAAM,SAAS,kBAAkB,YAAY,SAAS,QAAQ,OAAO,SAAS;AAC9E,qBAAe,UAAU;AACzB,sBAAgB,MAAM;AACtB,iBAAW,KAAK;AAAA,IAClB,CAAC;AAAA,EACH,GAAG,CAAC,QAAQ,OAAO,SAAS,CAAC;AAE7B,QAAM,aAAaE;AAAA,IACjB,OAAO,UAAa;AAClB,UAAI;AACF,YAAI,OAAO,WAAW;AACpB,gBAAM,MAAM,UAAU,OAAO,WAAW,KAAK;AAAA,QAC/C,OAAO;AACL,gBAAM,MAAM,WAAW,EAAE,GAAG,MAAM,CAAC;AAAA,QACrC;AACA,uBAAe,UAAU;AAAA,MAC3B,SAAS,KAAK;AACZ,iBAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAC3D;AAAA,IACF;AAAA,IACA,CAAC,OAAO,SAAS;AAAA,EACnB;AAEA,QAAM,gBAAgBA;AAAA,IACpB,CAAC,UAAa;AACZ,UAAI,YAAY,QAAS,QAAO,aAAa,YAAY,OAAO;AAChE,kBAAY,UAAU,OAAO,WAAW,MAAM;AAC5C,oBAAY,UAAU;AACtB,aAAK,WAAW,KAAK;AAAA,MACvB,GAAG,UAAU;AAAA,IACf;AAAA,IACA,CAAC,YAAY,UAAU;AAAA,EACzB;AAEA,EAAAF,YAAU,MAAM;AACd,WAAO,MAAM;AACX,UAAI,YAAY,QAAS,QAAO,aAAa,YAAY,OAAO;AAAA,IAClE;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,gBAAgBE;AAAA,IACpB,CAAC,SAAY;AACX,sBAAgB,IAAI;AACpB,oBAAc,IAAI;AAAA,IACpB;AAAA,IACA,CAAC,aAAa;AAAA,EAChB;AAEA,QAAM,kBAAkBA;AAAA,IACtB,CAAC,UAAsB;AACrB,sBAAgB,CAAC,SAAS;AACxB,cAAM,OAAO,EAAE,GAAG,MAAM,GAAG,MAAM;AACjC,sBAAc,IAAI;AAClB,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,IACA,CAAC,aAAa;AAAA,EAChB;AAEA,QAAM,QAAQA,aAAY,YAAY;AACpC,QAAI,YAAY,SAAS;AACvB,aAAO,aAAa,YAAY,OAAO;AACvC,kBAAY,UAAU;AAAA,IACxB;AACA,UAAM,OAAO,EAAE,GAAG,YAAY,QAAQ;AACtC,oBAAgB,IAAI;AACpB,UAAM,WAAW,IAAI;AAAA,EACvB,GAAG,CAAC,UAAU,CAAC;AAEf,SAAOC;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,OAAO,cAAc;AAAA,MACrB,YAAY;AAAA,MACZ,cAAc;AAAA,MACd;AAAA,IACF;AAAA,IACA,CAAC,SAAS,SAAS,YAAY,OAAO,eAAe,iBAAiB,KAAK;AAAA,EAC7E;AACF;;;AC7JA,SAAS,eAAAC,cAAa,aAAAC,aAAW,YAAAC,kBAAgB;AA2BjD,SAAS,cAAc,QAAqC;AAC1D,SAAO,WAAW,UAAa,WAAW;AAC5C;AAKO,SAAS,cAAc,SAAqD;AACjF,QAAM,iBAAiB,SAAS,kBAAkB;AAClD,QAAM,gBAAgB,SAAS,WAAW;AAC1C,QAAM,EAAE,QAAQ,OAAO,WAAW,IAAI,cAAc;AAAA,IAClD;AAAA,IACA,SAAS,SAAS;AAAA,IAClB,eAAe,SAAS;AAAA,IACxB,kBAAkB,SAAS;AAAA,IAC3B,eAAe,SAAS;AAAA,EAC1B,CAAC;AACD,QAAM,CAAC,SAAS,UAAU,IAAIC,WAAwB,IAAI;AAC1D,QAAM,CAAC,SAAS,UAAU,IAAIA,WAAS,KAAK;AAC5C,QAAM,CAAC,OAAO,QAAQ,IAAIA,WAAwB,IAAI;AAEtD,QAAM,aAAaC;AAAA,IACjB,OAAO,kBAA0B;AAC/B,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,aAAO,OAAO,WAAW,aAAa;AAAA,IACxC;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,aAAaA,aAAY,YAAY;AACzC,QAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,UAAM,MAAM,MAAM,QAAQ,QAAQ,OAAO,WAAW,CAAC;AACrD,WAAO,CAAC,GAAG,GAAG;AAAA,EAChB,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,aAAaA,aAAY,YAAY;AACzC,QAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,WAAO,OAAO,MAAM,QAAQ,QAAQ,OAAO,WAAW,CAAC,CAAC;AAAA,EAC1D,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,qBAAqBA;AAAA,IACzB,OAAO,iBAA6C;AAClD,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,YAAM,OAAO,OAAO,sBAAsB,MAAM;AAChD,UAAI,CAAC,KAAM,OAAM,IAAI,MAAM,2DAA2D;AACtF,YAAM,SAAoC,EAAE,aAAa,OAAO,QAAQ,QAAQ,GAAG,aAAa;AAChG,aAAQ,MAAM,KAAK,MAAM;AAAA,IAC3B;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,sBAAsBA;AAAA,IAC1B,OAAO,OAAe,iBAA6C;AACjE,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,YAAM,OAAO,OAAO,uBAAuB,MAAM;AACjD,UAAI,CAAC,KAAM,OAAM,IAAI,MAAM,4DAA4D;AACvF,YAAM,SAAoC,EAAE,aAAa,OAAO,QAAQ,QAAQ,GAAG,aAAa;AAChG,aAAQ,MAAM,KAAK,OAAO,MAAM;AAAA,IAClC;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,UAAUA,aAAY,YAAY;AACtC,QAAI,CAAC,OAAQ;AACb,QAAI,CAAC,cAAc,aAAa,GAAG;AACjC,iBAAW,aAAa;AACxB,eAAS,IAAI;AACb;AAAA,IACF;AACA,eAAW,IAAI;AACf,aAAS,IAAI;AACb,QAAI;AACF,YAAM,OAAO,MAAM,MAAM,eAAe,WAAW;AACnD,iBAAW,QAAQ,IAAI;AAAA,IACzB,SAAS,KAAK;AACZ,iBAAW,IAAI;AACf,eAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAC3D,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,QAAQ,aAAa,CAAC;AAE1B,EAAAC,YAAU,MAAM;AACd,QAAI,OAAQ,MAAK,QAAQ;AAAA,EAC3B,GAAG,CAAC,QAAQ,OAAO,CAAC;AAEpB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,OAAO,cAAc;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":["useMemo","useSyncExternalStore","useSyncExternalStore","useMemo","useEffect","useMemo","useRef","useSyncExternalStore","useRef","useEffect","useSyncExternalStore","useMemo","useEffect","useRef","useRef","useEffect","useEffect","useRef","useState","useRef","useEffect","useState","useEffect","useRef","useState","useState","useRef","useEffect","useState","useState","useCallback","useEffect","useState","useState","useEffect","useCallback","useCallback","useState","useState","useCallback","useCallback","useContext","useEffect","useRef","useState","useContext","useState","useRef","useCallback","useEffect","useCallback","useEffect","useState","useState","useCallback","useEffect","useCallback","useEffect","useState","useState","useCallback","useEffect","useCallback","useEffect","useMemo","useRef","useState","useRef","useEffect","useState","useCallback","useMemo","useCallback","useEffect","useState","useState","useCallback","useEffect"]}
@@ -7,7 +7,7 @@ import {
7
7
  initialGristSnapshot,
8
8
  releaseEmbeddedHandshakeManager,
9
9
  resetGristReadySingleton
10
- } from "./chunk-XE2SKNLH.js";
10
+ } from "./chunk-KOVYBNPJ.js";
11
11
 
12
12
  // src/sdk/helpers/grist-fetch-with-auth.ts
13
13
  var TOKEN_TTL_MS = 45e3;
@@ -476,4 +476,4 @@ export {
476
476
  useGristReady,
477
477
  useGristWidgetOptionsFromContext
478
478
  };
479
- //# sourceMappingURL=chunk-BNBV24WM.js.map
479
+ //# sourceMappingURL=chunk-ER6UWHZA.js.map