grist-widget-sdk 0.3.27 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -0
- package/README.md +1 -1
- package/dist/app.cjs +1139 -4336
- package/dist/app.cjs.map +1 -1
- package/dist/app.d.cts +1 -3
- package/dist/app.d.ts +1 -3
- package/dist/app.js +3 -7
- package/dist/chunk-4ZGVKGDF.js +204 -0
- package/dist/chunk-4ZGVKGDF.js.map +1 -0
- package/dist/{chunk-YQNMIL33.js → chunk-B5ZZNLVS.js} +528 -181
- package/dist/chunk-B5ZZNLVS.js.map +1 -0
- package/dist/chunk-O7NY46QY.js +1830 -0
- package/dist/chunk-O7NY46QY.js.map +1 -0
- package/dist/{chunk-6Y2IONGJ.js → chunk-P6VTEKWO.js} +113 -14
- package/dist/chunk-P6VTEKWO.js.map +1 -0
- package/dist/emulator/testing.cjs +1504 -4822
- package/dist/emulator/testing.cjs.map +1 -1
- package/dist/emulator/testing.d.cts +3 -6
- package/dist/emulator/testing.d.ts +3 -6
- package/dist/emulator/testing.js +7 -20
- package/dist/emulator/testing.js.map +1 -1
- package/dist/emulator.cjs +59 -249
- package/dist/emulator.cjs.map +1 -1
- package/dist/emulator.d.cts +3 -5
- package/dist/emulator.d.ts +3 -5
- package/dist/emulator.js +5 -11
- package/dist/index.cjs +1373 -4859
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +81 -260
- package/dist/index.d.ts +81 -260
- package/dist/index.js +8 -158
- package/dist/{inline-DpcT8tV9.d.ts → templates-CGmRIQBV.d.cts} +89 -35
- package/dist/{inline-C7DkvuET.d.cts → templates-Cq94qOcf.d.ts} +89 -35
- package/dist/{types-D3JxUCfL.d.cts → types-DBStn0Dk.d.cts} +2 -26
- package/dist/{types-D3JxUCfL.d.ts → types-DBStn0Dk.d.ts} +2 -26
- package/dist/use-grist-BK0eke9K.d.cts +358 -0
- package/dist/use-grist-C5DMZ3wU.d.ts +358 -0
- package/package.json +8 -37
- package/dist/advanced.cjs +0 -2799
- package/dist/advanced.cjs.map +0 -1
- package/dist/advanced.d.cts +0 -822
- package/dist/advanced.d.ts +0 -822
- package/dist/advanced.js +0 -872
- package/dist/advanced.js.map +0 -1
- package/dist/chunk-22U7WAY3.js +0 -463
- package/dist/chunk-22U7WAY3.js.map +0 -1
- package/dist/chunk-64SVRWW7.js +0 -758
- package/dist/chunk-64SVRWW7.js.map +0 -1
- package/dist/chunk-6Y2IONGJ.js.map +0 -1
- package/dist/chunk-B4AKVSWV.js +0 -2362
- package/dist/chunk-B4AKVSWV.js.map +0 -1
- package/dist/chunk-ELGVOHFD.js +0 -32
- package/dist/chunk-ELGVOHFD.js.map +0 -1
- package/dist/chunk-GTTD5HPO.js +0 -36
- package/dist/chunk-GTTD5HPO.js.map +0 -1
- package/dist/chunk-NO6FYX33.js +0 -2084
- package/dist/chunk-NO6FYX33.js.map +0 -1
- package/dist/chunk-OPTOYD2Y.js +0 -277
- package/dist/chunk-OPTOYD2Y.js.map +0 -1
- package/dist/chunk-PM3B4WYV.js +0 -12
- package/dist/chunk-PM3B4WYV.js.map +0 -1
- package/dist/chunk-REV5AUXD.js +0 -25
- package/dist/chunk-REV5AUXD.js.map +0 -1
- package/dist/chunk-YQNMIL33.js.map +0 -1
- package/dist/create-grist-emulator-BCqp1BF9.d.ts +0 -81
- package/dist/create-grist-emulator-DBM8OSIR.d.cts +0 -81
- package/dist/emulator/devtools.cjs +0 -1404
- package/dist/emulator/devtools.cjs.map +0 -1
- package/dist/emulator/devtools.d.cts +0 -48
- package/dist/emulator/devtools.d.ts +0 -48
- package/dist/emulator/devtools.js +0 -506
- package/dist/emulator/devtools.js.map +0 -1
- package/dist/emulator/transports.cjs +0 -1132
- package/dist/emulator/transports.cjs.map +0 -1
- package/dist/emulator/transports.d.cts +0 -38
- package/dist/emulator/transports.d.ts +0 -38
- package/dist/emulator/transports.js +0 -12
- package/dist/emulator/transports.js.map +0 -1
- package/dist/templates-8k2LKoO-.d.cts +0 -24
- package/dist/templates-DIwi_mvI.d.ts +0 -24
- package/dist/use-grist-reads-DUMvJgV7.d.ts +0 -480
- package/dist/use-grist-reads-DpjVuI0H.d.cts +0 -480
- package/dist/use-grist-types-DdOLEJXN.d.cts +0 -499
- package/dist/use-grist-types-kwxoFeub.d.ts +0 -499
- package/dist/use-grist-widget-options-from-context-CGOlQ5Vc.d.cts +0 -43
- package/dist/use-grist-widget-options-from-context-CGOlQ5Vc.d.ts +0 -43
package/dist/advanced.d.cts
DELETED
|
@@ -1,822 +0,0 @@
|
|
|
1
|
-
import { a8 as GristTerminationReason, a9 as GristGeneration, aa as GristMappingSource, G as GristWidgetSnapshot, c as GristCapabilities } from './use-grist-reads-DpjVuI0H.cjs';
|
|
2
|
-
import { UseGristCoreOptions, GristWidgetStatus, GristUserActionTuple, GristAccessToken, GristColumnarTable } from './index.cjs';
|
|
3
|
-
export { ab as GristAuthz, e as GristColumnInfo, ac as GristConfig, ad as GristCurrentTableState, ae as GristLifecycle, af as GristLifecyclePhase, ag as GristLink, ah as GristLinkState, ai as GristMappingComplete, aj as GristMappingIncomplete, ak as GristMappingState, al as GristStreamFreshness, am as GristSync, L as ListColumnsOptions, r as ListTablesOptions } from './use-grist-reads-DpjVuI0H.cjs';
|
|
4
|
-
import { GristRequiredAccess, GristColumnsToMap, GristWidgetColumnMap, GristReadyOptions, GristDocApi, GristApplyUserActionsOptions, GristTableNewRecord, GristTableOpOptions, GristMinimalRecord, GristTableUpdateRecord, GristTableUpsertRecord, GristTableUpsertOptions, GristRowRecord, GristFetchSelectedOptions } from './index.cjs';
|
|
5
|
-
import * as react from 'react';
|
|
6
|
-
import { ReactNode } from 'react';
|
|
7
|
-
export { U as UseGristWidgetOptionsFromContextConfig, a as UseGristWidgetOptionsFromContextResult, u as useGristWidgetOptionsFromContext } from './use-grist-widget-options-from-context-CGOlQ5Vc.cjs';
|
|
8
|
-
import 'zod';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Action union for the handshake state machine.
|
|
12
|
-
*
|
|
13
|
-
* Every action that can mutate the snapshot is listed here as a discriminated
|
|
14
|
-
* union — exhaustiveness checks in the reducer rely on it.
|
|
15
|
-
*
|
|
16
|
-
* Actions either:
|
|
17
|
-
* - target a single axis (e.g. `RPC_SUCCESS` → link), OR
|
|
18
|
-
* - target multiple axes via a single transition (e.g. `NEGOTIATE_SUCCESS`
|
|
19
|
-
* advances lifecycle AND authz at once).
|
|
20
|
-
*
|
|
21
|
-
* Generation-carrying actions can be **dropped** by the reducer if their
|
|
22
|
-
* `generation` is older than the snapshot's current generation; this is the
|
|
23
|
-
* primary defence against stale events arriving after a reload/restart.
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
type GristLifecycleAction = {
|
|
27
|
-
type: "DETECT_START";
|
|
28
|
-
atMs: number;
|
|
29
|
-
} | {
|
|
30
|
-
type: "DETECT_TICK";
|
|
31
|
-
attempts: number;
|
|
32
|
-
atMs: number;
|
|
33
|
-
} | {
|
|
34
|
-
type: "DETECT_AVAILABLE";
|
|
35
|
-
atMs: number;
|
|
36
|
-
} | {
|
|
37
|
-
type: "DETECT_TIMEOUT";
|
|
38
|
-
attempts: number;
|
|
39
|
-
atMs: number;
|
|
40
|
-
} | {
|
|
41
|
-
type: "NOT_EMBEDDED";
|
|
42
|
-
atMs: number;
|
|
43
|
-
} | {
|
|
44
|
-
type: "NEGOTIATE_START";
|
|
45
|
-
access: GristRequiredAccess;
|
|
46
|
-
atMs: number;
|
|
47
|
-
} | {
|
|
48
|
-
type: "NEGOTIATE_SUCCESS";
|
|
49
|
-
access: GristRequiredAccess;
|
|
50
|
-
grantedLevel: GristRequiredAccess;
|
|
51
|
-
atMs: number;
|
|
52
|
-
} | {
|
|
53
|
-
type: "NEGOTIATE_FAIL";
|
|
54
|
-
reason: GristTerminationReason;
|
|
55
|
-
atMs: number;
|
|
56
|
-
} | {
|
|
57
|
-
type: "TERMINATE";
|
|
58
|
-
reason: GristTerminationReason;
|
|
59
|
-
atMs: number;
|
|
60
|
-
};
|
|
61
|
-
type GristLinkAction = {
|
|
62
|
-
type: "RPC_SUCCESS";
|
|
63
|
-
atMs: number;
|
|
64
|
-
} | {
|
|
65
|
-
type: "RPC_FAILURE";
|
|
66
|
-
atMs: number;
|
|
67
|
-
kind: "timeout" | "rejected" | "other";
|
|
68
|
-
} | {
|
|
69
|
-
type: "HEARTBEAT_OK";
|
|
70
|
-
atMs: number;
|
|
71
|
-
} | {
|
|
72
|
-
type: "HEARTBEAT_FAIL";
|
|
73
|
-
atMs: number;
|
|
74
|
-
};
|
|
75
|
-
type GristAuthzAction = {
|
|
76
|
-
type: "AUTHZ_REPORT";
|
|
77
|
-
/** Effective access level reported by Grist (`onOptions` / `interaction.access_level`). */
|
|
78
|
-
level: GristRequiredAccess;
|
|
79
|
-
atMs: number;
|
|
80
|
-
generation: GristGeneration;
|
|
81
|
-
};
|
|
82
|
-
type GristGenerationAction = {
|
|
83
|
-
type: "BUMP_GENERATION";
|
|
84
|
-
atMs: number;
|
|
85
|
-
reason: "reload" | "restart" | "link_recovery" | "widening";
|
|
86
|
-
};
|
|
87
|
-
type GristMappingAction = {
|
|
88
|
-
type: "MAPPING_DECLARE";
|
|
89
|
-
declared: GristColumnsToMap;
|
|
90
|
-
atMs: number;
|
|
91
|
-
generation: GristGeneration;
|
|
92
|
-
} | {
|
|
93
|
-
type: "MAPPING_REPORT";
|
|
94
|
-
source: GristMappingSource;
|
|
95
|
-
payload: GristWidgetColumnMap | null;
|
|
96
|
-
atMs: number;
|
|
97
|
-
generation: GristGeneration;
|
|
98
|
-
} | {
|
|
99
|
-
type: "MAPPING_INVALIDATE";
|
|
100
|
-
atMs: number;
|
|
101
|
-
generation: GristGeneration;
|
|
102
|
-
} | {
|
|
103
|
-
type: "MAPPING_INVALIDATION_RESOLVE";
|
|
104
|
-
atMs: number;
|
|
105
|
-
generation: GristGeneration;
|
|
106
|
-
} | {
|
|
107
|
-
type: "MAPPING_TIMEOUT";
|
|
108
|
-
atMs: number;
|
|
109
|
-
generation: GristGeneration;
|
|
110
|
-
};
|
|
111
|
-
type GristSyncStream = "record" | "records" | "options" | "newRecord";
|
|
112
|
-
type GristSyncAction = {
|
|
113
|
-
type: "STREAM_RECEIVED";
|
|
114
|
-
stream: GristSyncStream;
|
|
115
|
-
payloadHash: string;
|
|
116
|
-
atMs: number;
|
|
117
|
-
generation: GristGeneration;
|
|
118
|
-
} | {
|
|
119
|
-
type: "STREAM_WARMING";
|
|
120
|
-
stream: GristSyncStream;
|
|
121
|
-
atMs: number;
|
|
122
|
-
} | {
|
|
123
|
-
type: "STREAM_STALE";
|
|
124
|
-
stream: GristSyncStream;
|
|
125
|
-
atMs: number;
|
|
126
|
-
reason: "link_lost" | "tab_hidden" | "host_quiet";
|
|
127
|
-
} | {
|
|
128
|
-
type: "CURRENT_TABLE_KNOWN";
|
|
129
|
-
tableId: string;
|
|
130
|
-
atMs: number;
|
|
131
|
-
} | {
|
|
132
|
-
type: "CURRENT_TABLE_REFRESH_START";
|
|
133
|
-
atMs: number;
|
|
134
|
-
} | {
|
|
135
|
-
type: "CURRENT_TABLE_ERROR";
|
|
136
|
-
message: string;
|
|
137
|
-
atMs: number;
|
|
138
|
-
};
|
|
139
|
-
type GristAction = GristLifecycleAction | GristLinkAction | GristAuthzAction | GristGenerationAction | GristMappingAction | GristSyncAction;
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Pure reducer for the handshake state machine.
|
|
143
|
-
*
|
|
144
|
-
* Contract
|
|
145
|
-
* --------
|
|
146
|
-
* - **Pure**: `(snapshot, action, ctx) => nextSnapshot`. No I/O, no globals,
|
|
147
|
-
* no Date.now() — callers pass timestamps via `action.atMs` and (optionally)
|
|
148
|
-
* a context object for the {@link MappingResolver}.
|
|
149
|
-
* - **Total**: every (snapshot.lifecycle.phase × action.type) pair returns
|
|
150
|
-
* either an updated snapshot or the identity snapshot.
|
|
151
|
-
* - **Idempotent for replays**: same generation-stamped action applied twice
|
|
152
|
-
* leaves the snapshot unchanged (`payloadHash` short-circuit on streams,
|
|
153
|
-
* resolver hash short-circuit on mappings).
|
|
154
|
-
* - **Generation-safe**: any action carrying a `generation` lower than the
|
|
155
|
-
* current snapshot generation is dropped silently — this is what makes
|
|
156
|
-
* the SDK robust to late events after reload/restart.
|
|
157
|
-
*
|
|
158
|
-
* The reducer never throws. Invariant violations are surfaced via
|
|
159
|
-
* `./invariants.ts` if the caller opts in.
|
|
160
|
-
*/
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Tuning knobs. Pass `Partial<ReducerConfig>` to override defaults; values
|
|
164
|
-
* are read by the reducer at each step.
|
|
165
|
-
*/
|
|
166
|
-
type ReducerConfig = {
|
|
167
|
-
/** Stale-pings threshold before link transitions to `stale`. */
|
|
168
|
-
staleAfterMissed: number;
|
|
169
|
-
/** Stale-pings threshold before link transitions to `lost`. */
|
|
170
|
-
lostAfterMissed: number;
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Environment abstraction for the handshake effects layer.
|
|
175
|
-
*
|
|
176
|
-
* Why an abstraction
|
|
177
|
-
* ------------------
|
|
178
|
-
* The detect / negotiate / heartbeat effects need access to:
|
|
179
|
-
* - the `grist` global (or absence thereof),
|
|
180
|
-
* - `window.self !== window.top` to detect iframe embedding,
|
|
181
|
-
* - timers (`setTimeout`, `clearTimeout`),
|
|
182
|
-
* - the wall clock (`performance.now()` or `Date.now()`),
|
|
183
|
-
* - `navigator.connection?.effectiveType` for adaptive policy.
|
|
184
|
-
*
|
|
185
|
-
* Putting these behind a small interface lets us test the manager and effects
|
|
186
|
-
* **without touching `window`**, using deterministic fake timers and stubbed
|
|
187
|
-
* detectors / negotiators.
|
|
188
|
-
*
|
|
189
|
-
* Production code calls {@link createBrowserEnvironment()} which returns an
|
|
190
|
-
* adapter against `globalThis`. Tests pass {@link createTestEnvironment} or a
|
|
191
|
-
* hand-rolled stub.
|
|
192
|
-
*/
|
|
193
|
-
|
|
194
|
-
type GristEnvironment = {
|
|
195
|
-
/** Wall-clock ms (monotonic preferred but not required). */
|
|
196
|
-
now(): number;
|
|
197
|
-
/** Schedule a callback. */
|
|
198
|
-
setTimeout(cb: () => void, ms: number): TimerHandle;
|
|
199
|
-
/** Cancel a timer. */
|
|
200
|
-
clearTimeout(handle: TimerHandle): void;
|
|
201
|
-
/**
|
|
202
|
-
* Probe whether the `grist` global is present in this realm.
|
|
203
|
-
* Returns `{ embedded }` when the global exists; `null` otherwise.
|
|
204
|
-
*/
|
|
205
|
-
probeGrist(): {
|
|
206
|
-
embedded: boolean;
|
|
207
|
-
} | null;
|
|
208
|
-
/**
|
|
209
|
-
* Snapshot of the `grist` global. Effects use this once detection has
|
|
210
|
-
* succeeded; callers must NOT cache the result across `restart()`.
|
|
211
|
-
*/
|
|
212
|
-
getGrist(): GristLike | null;
|
|
213
|
-
/** Adaptive detection budget hint (ms). `null` if unknown. */
|
|
214
|
-
effectiveTypeHint(): EffectiveTypeHint | null;
|
|
215
|
-
/** Add a listener for `visibilitychange` / `online` / `focus`. Returns cleanup. */
|
|
216
|
-
onVisibilityChange?(listener: (visible: boolean) => void): () => void;
|
|
217
|
-
onOnline?(listener: () => void): () => void;
|
|
218
|
-
};
|
|
219
|
-
type TimerHandle = ReturnType<typeof setTimeout> | number | {
|
|
220
|
-
__opaque: true;
|
|
221
|
-
};
|
|
222
|
-
type EffectiveTypeHint = "slow-2g" | "2g" | "3g" | "4g" | "5g";
|
|
223
|
-
/**
|
|
224
|
-
* Subset of `window.grist` actually used by handshake effects. Mirrors the
|
|
225
|
-
* declared shape in `grist-global.d.ts` but only the pieces we need.
|
|
226
|
-
*/
|
|
227
|
-
type GristLike = {
|
|
228
|
-
ready: (options?: GristReadyOptions) => Promise<void> | void;
|
|
229
|
-
docApi: GristDocApi | null | undefined;
|
|
230
|
-
onRecord?: (cb: (record: Record<string, unknown> | null, mappings?: GristWidgetColumnMap | null) => void, options?: {
|
|
231
|
-
keepEncoded?: boolean;
|
|
232
|
-
}) => void;
|
|
233
|
-
onRecords?: (cb: (records: Record<string, unknown>[], mappings?: GristWidgetColumnMap | null) => void, options?: {
|
|
234
|
-
keepEncoded?: boolean;
|
|
235
|
-
format?: string;
|
|
236
|
-
}) => void;
|
|
237
|
-
onOptions?: (cb: (options: Record<string, unknown> | null, interaction: unknown) => void) => void;
|
|
238
|
-
onNewRecord?: (cb: (mappings: GristWidgetColumnMap | null) => void) => void;
|
|
239
|
-
sectionApi?: {
|
|
240
|
-
mappings: () => Promise<GristWidgetColumnMap | null>;
|
|
241
|
-
};
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* Detect effect — poll for `window.grist` with exponential backoff inside a
|
|
246
|
-
* finite, optionally adaptive budget.
|
|
247
|
-
*
|
|
248
|
-
* Outputs (dispatched to the manager):
|
|
249
|
-
* - DETECT_START (once, at start)
|
|
250
|
-
* - DETECT_TICK (each unsuccessful poll, with attempts count)
|
|
251
|
-
* - DETECT_AVAILABLE (grist global present AND embedded)
|
|
252
|
-
* - NOT_EMBEDDED (grist global present but `self === top`)
|
|
253
|
-
* - DETECT_TIMEOUT (budget consumed without detection)
|
|
254
|
-
*
|
|
255
|
-
* The effect aborts on `signal.aborted` and clears its pending timer.
|
|
256
|
-
*
|
|
257
|
-
* Pure of `window`: relies on the {@link GristEnvironment} adapter so the
|
|
258
|
-
* effect is fully unit-testable with a virtual clock.
|
|
259
|
-
*/
|
|
260
|
-
|
|
261
|
-
type DetectOptions = {
|
|
262
|
-
/** Custom poll sequence in ms. Index past end uses last value. */
|
|
263
|
-
pollSequenceMs?: readonly number[];
|
|
264
|
-
/** Total wall-clock budget across all polls. */
|
|
265
|
-
budgetMs?: number;
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* Negotiate effect — issue `grist.ready(payload)` race-d against a timeout
|
|
270
|
-
* and an external `AbortSignal`.
|
|
271
|
-
*
|
|
272
|
-
* Dispatches:
|
|
273
|
-
* - NEGOTIATE_START
|
|
274
|
-
* - NEGOTIATE_SUCCESS (grist.ready resolved AND `docApi` is present)
|
|
275
|
-
* - NEGOTIATE_FAIL (reason: ready_failed | ready_timeout | manual_terminate)
|
|
276
|
-
*
|
|
277
|
-
* The effect never throws to the caller. Aborts before resolution silently
|
|
278
|
-
* stop dispatching.
|
|
279
|
-
*/
|
|
280
|
-
|
|
281
|
-
type NegotiateOptions = {
|
|
282
|
-
/** Max ms to wait for `grist.ready` to resolve. */
|
|
283
|
-
timeoutMs?: number;
|
|
284
|
-
/**
|
|
285
|
-
* Custom implementation of `grist.ready(payload)`. Defaults to calling
|
|
286
|
-
* `grist.ready` directly via the env. Production callers (the provider)
|
|
287
|
-
* inject a wrapper that routes through `ensureGristReady()` so the
|
|
288
|
-
* page-level singleton dedupes concurrent ready calls.
|
|
289
|
-
*/
|
|
290
|
-
readyImpl?: (payload: GristReadyOptions) => Promise<void> | void;
|
|
291
|
-
};
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
* Subscriptions effect — bind Grist event streams once and feed the handshake
|
|
295
|
-
* machine with generation-stamped, hash-deduplicated dispatches.
|
|
296
|
-
*
|
|
297
|
-
* Why a dedicated effect
|
|
298
|
-
* ----------------------
|
|
299
|
-
* The SDK already has a {@link "../../subscriptions"} module that owns the
|
|
300
|
-
* one-time binding to `grist.on*` and the BehaviorSubject-style cache. We do
|
|
301
|
-
* NOT re-bind here — instead, we install a single listener per stream that
|
|
302
|
-
* forwards into the handshake reducer.
|
|
303
|
-
*
|
|
304
|
-
* Generation discipline: every dispatched action carries the CURRENT manager
|
|
305
|
-
* generation read at the moment the event arrives. The reducer enforces
|
|
306
|
-
* `action.generation >= snapshot.generation`, so events arriving after a
|
|
307
|
-
* `reload()` / `restart()` that bumped generation are dropped automatically.
|
|
308
|
-
*
|
|
309
|
-
* Hash: payloads are reduced to a compact, deterministic string so duplicates
|
|
310
|
-
* (e.g. emulator triple-replay of initial state) become no-ops at the reducer.
|
|
311
|
-
*/
|
|
312
|
-
|
|
313
|
-
type SubscriptionsHandle = {
|
|
314
|
-
cancel(): void;
|
|
315
|
-
};
|
|
316
|
-
/**
|
|
317
|
-
* Pluggable binder type. The default {@link defaultSubscriptionsBinder}
|
|
318
|
-
* subscribes to the SDK's singleton {@link GristEvent} instances. Tests can
|
|
319
|
-
* supply a stub that never touches the real `grist` global.
|
|
320
|
-
*/
|
|
321
|
-
type SubscriptionsBinder = (ctx: SubscriptionsContext) => SubscriptionsHandle;
|
|
322
|
-
type SubscriptionsContext = {
|
|
323
|
-
dispatch: (action: GristAction) => void;
|
|
324
|
-
/**
|
|
325
|
-
* Snapshot generation provider. Must be read lazily (inside the callback)
|
|
326
|
-
* because `generation` is monotone but mutates over the lifetime of the
|
|
327
|
-
* subscription.
|
|
328
|
-
*/
|
|
329
|
-
getGeneration: () => GristGeneration;
|
|
330
|
-
/** Hook for the mapping effect: receive payloads in arrival order. */
|
|
331
|
-
onRecordPayload?: (mappings: Record<string, unknown> | null | undefined) => void;
|
|
332
|
-
onRecordsPayload?: (mappings: Record<string, unknown> | null | undefined) => void;
|
|
333
|
-
onOptionsPayload?: (options: Record<string, unknown> | null) => void;
|
|
334
|
-
onNewRecordPayload?: (mappings: Record<string, unknown> | null | undefined) => void;
|
|
335
|
-
};
|
|
336
|
-
|
|
337
|
-
/**
|
|
338
|
-
* Mappings effect — feed column-mapping payloads into the reducer from the
|
|
339
|
-
* three Grist sources (`sectionApi.mappings()`, `onRecord`, `onRecords`,
|
|
340
|
-
* `onNewRecord`) and trigger the mapping timeout if nothing arrives in time.
|
|
341
|
-
*
|
|
342
|
-
* Inputs:
|
|
343
|
-
* - `declared` — `columns` from the provider options.
|
|
344
|
-
* - `getGeneration()` — current snapshot generation (for stale-drop).
|
|
345
|
-
* - `getGrist()` — environment accessor to `grist.sectionApi.mappings()`.
|
|
346
|
-
*
|
|
347
|
-
* Outputs:
|
|
348
|
-
* - `MAPPING_DECLARE` (once at start when `declared.length > 0`)
|
|
349
|
-
* - `MAPPING_REPORT` (one per source payload received)
|
|
350
|
-
* - `MAPPING_TIMEOUT` (if no payload after `timeoutMs`)
|
|
351
|
-
*
|
|
352
|
-
* The effect does NOT subscribe to grist events directly — it consumes them
|
|
353
|
-
* via the {@link SubscriptionsContext} payload callbacks. This keeps the
|
|
354
|
-
* single-binding contract of `subscriptions.ts` intact (one `grist.onRecord`
|
|
355
|
-
* binding per page).
|
|
356
|
-
*/
|
|
357
|
-
|
|
358
|
-
type MappingsOptions = {
|
|
359
|
-
/**
|
|
360
|
-
* Time after `MAPPING_DECLARE` before falling back to `unreported` state.
|
|
361
|
-
* Default 5 000 ms.
|
|
362
|
-
*/
|
|
363
|
-
timeoutMs?: number;
|
|
364
|
-
/**
|
|
365
|
-
* If true, dispatch `MAPPING_INVALIDATE` whenever a payload differs from
|
|
366
|
-
* the last applied mappings. Default false — graceful invalidation requires
|
|
367
|
-
* a `mappingsChange: true` envelope flag the SDK doesn't currently surface,
|
|
368
|
-
* so we leave it opt-in for tests.
|
|
369
|
-
*/
|
|
370
|
-
invalidateOnDiff?: boolean;
|
|
371
|
-
};
|
|
372
|
-
|
|
373
|
-
/**
|
|
374
|
-
* Heartbeat effect — periodically verify the RPC channel is alive.
|
|
375
|
-
*
|
|
376
|
-
* Strategy
|
|
377
|
-
* --------
|
|
378
|
-
* 1. Schedule a ping every `intervalMs` (default 30 s).
|
|
379
|
-
* 2. The ping calls a cheap RPC (default `grist.docApi.getDocName()`).
|
|
380
|
-
* 3. Success → `HEARTBEAT_OK`. Failure / timeout → `HEARTBEAT_FAIL`.
|
|
381
|
-
* 4. Any externally-observed RPC success (the caller invokes
|
|
382
|
-
* {@link HeartbeatHandle.recordRpcSuccess}) coalesces with the heartbeat
|
|
383
|
-
* and reschedules the next ping — we don't burn a request when natural
|
|
384
|
-
* traffic already proves the link.
|
|
385
|
-
* 5. Tab hidden? Pause via `env.onVisibilityChange`. Resume on `visible`.
|
|
386
|
-
*
|
|
387
|
-
* The effect is **purely an observer**: it never mutates application state
|
|
388
|
-
* directly — it only dispatches actions the reducer consumes.
|
|
389
|
-
*/
|
|
390
|
-
|
|
391
|
-
type HeartbeatOptions = {
|
|
392
|
-
/** How often to issue a probe when no natural RPC traffic occurred. */
|
|
393
|
-
intervalMs?: number;
|
|
394
|
-
/** Max time to wait for the probe before counting it as a failure. */
|
|
395
|
-
pingTimeoutMs?: number;
|
|
396
|
-
/** If true, pause the heartbeat when the document becomes hidden. */
|
|
397
|
-
pauseWhenHidden?: boolean;
|
|
398
|
-
/**
|
|
399
|
-
* Probe used when the interval elapses. Defaults to
|
|
400
|
-
* `() => env.getGrist().docApi.getDocName()`. Tests pass a controlled stub.
|
|
401
|
-
*/
|
|
402
|
-
probe?: () => Promise<unknown>;
|
|
403
|
-
};
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* GristHandshakeManager — single owner of the handshake snapshot.
|
|
407
|
-
*
|
|
408
|
-
* Responsibilities
|
|
409
|
-
* ----------------
|
|
410
|
-
* 1. Hold the snapshot and the {@link GristReducerContext}.
|
|
411
|
-
* 2. Run effects (detect → negotiate → subscriptions + mappings) in order.
|
|
412
|
-
* 3. Bump generation on `reload()` / `restart()` and propagate cancellation
|
|
413
|
-
* through a per-generation {@link AbortController}.
|
|
414
|
-
* 4. Notify subscribers on each snapshot change (interface compatible with
|
|
415
|
-
* React's `useSyncExternalStore`).
|
|
416
|
-
*
|
|
417
|
-
* The manager is a **class**, not a hook. React hooks subscribe to it via the
|
|
418
|
-
* standard `subscribe` / `getSnapshot` pair so unit tests can drive the
|
|
419
|
-
* manager directly with a virtual clock — no React needed.
|
|
420
|
-
*/
|
|
421
|
-
|
|
422
|
-
type ManagerOptions = GristReadyOptions & {
|
|
423
|
-
detect?: DetectOptions;
|
|
424
|
-
negotiate?: NegotiateOptions;
|
|
425
|
-
mappings?: MappingsOptions;
|
|
426
|
-
heartbeat?: HeartbeatOptions | false;
|
|
427
|
-
reducerConfig?: Partial<ReducerConfig>;
|
|
428
|
-
/**
|
|
429
|
-
* Where to read `grist`, timers, and platform hints from. Defaults to a
|
|
430
|
-
* browser adapter. Tests pass {@link createTestEnvironment}.
|
|
431
|
-
*/
|
|
432
|
-
env?: GristEnvironment;
|
|
433
|
-
/**
|
|
434
|
-
* Binder for grist event streams. Defaults to
|
|
435
|
-
* {@link defaultSubscriptionsBinder} which wires the SDK's singleton
|
|
436
|
-
* {@link "../../subscriptions"} module. Tests can pass `noopSubscriptionsBinder`
|
|
437
|
-
* to avoid touching the real `grist` global.
|
|
438
|
-
*/
|
|
439
|
-
subscriptionsBinder?: SubscriptionsBinder;
|
|
440
|
-
/**
|
|
441
|
-
* Called when the manager catches an unexpected internal error.
|
|
442
|
-
* Telemetry hook — does not affect reducer state.
|
|
443
|
-
*/
|
|
444
|
-
onError?: (err: unknown, where: string) => void;
|
|
445
|
-
/**
|
|
446
|
-
* Called from inside {@link ManagerControls.reload} BEFORE generation bump.
|
|
447
|
-
* Production callers route `resetGristReadySingleton()` through here so
|
|
448
|
-
* the page-level ready singleton is cleared and the next negotiate effect
|
|
449
|
-
* issues a fresh `grist.ready` instead of re-using the cached promise.
|
|
450
|
-
*/
|
|
451
|
-
onBeforeReload?: () => void;
|
|
452
|
-
};
|
|
453
|
-
|
|
454
|
-
type UseGristAvailabilityOptions = Pick<UseGristCoreOptions, "availabilityMaxAttempts" | "availabilityIntervalMs" | "logWhenNotEmbedded">;
|
|
455
|
-
/**
|
|
456
|
-
* Handshake-backed availability — projects `isAvailable` from the FSM.
|
|
457
|
-
*/
|
|
458
|
-
declare function useGristAvailability(options?: UseGristAvailabilityOptions): boolean | null;
|
|
459
|
-
|
|
460
|
-
type UseGristReadyOptions = GristReadyOptions & {
|
|
461
|
-
availabilityMaxAttempts?: number;
|
|
462
|
-
availabilityIntervalMs?: number;
|
|
463
|
-
logWhenNotEmbedded?: boolean;
|
|
464
|
-
};
|
|
465
|
-
type UseGristReadyResult = {
|
|
466
|
-
isAvailable: boolean | null;
|
|
467
|
-
docApi: GristDocApi | null;
|
|
468
|
-
error: string | null;
|
|
469
|
-
reload: () => Promise<void>;
|
|
470
|
-
};
|
|
471
|
-
/**
|
|
472
|
-
* Handshake-backed `grist.ready` — delegates to {@link useGristCore} (FSM).
|
|
473
|
-
*
|
|
474
|
-
* Prefer `<GristWidgetProvider>` + `useGrist()` for full widget state; use this
|
|
475
|
-
* hook when you only need `docApi` and connection status.
|
|
476
|
-
*/
|
|
477
|
-
declare function useGristReady(options?: UseGristReadyOptions): UseGristReadyResult;
|
|
478
|
-
|
|
479
|
-
/**
|
|
480
|
-
* `useGristHandshake()` — React adapter over {@link GristHandshakeManager}.
|
|
481
|
-
*
|
|
482
|
-
* Exposes the full {@link GristWidgetSnapshot} plus derived
|
|
483
|
-
* {@link GristCapabilities}, plus `reload()` / `restart()` controls.
|
|
484
|
-
*
|
|
485
|
-
* Identity stability
|
|
486
|
-
* ------------------
|
|
487
|
-
* The snapshot reference changes whenever the reducer produces a new
|
|
488
|
-
* snapshot. Capabilities are memoized by snapshot identity, so consumers
|
|
489
|
-
* branching on a single capability (e.g. `canWriteRecords`) avoid extra
|
|
490
|
-
* re-renders unless that boolean actually flips.
|
|
491
|
-
*
|
|
492
|
-
* SSR-safe: `getServerSnapshot` returns the initial snapshot deterministically.
|
|
493
|
-
*/
|
|
494
|
-
|
|
495
|
-
type UseGristHandshakeOptions = ManagerOptions;
|
|
496
|
-
type UseGristHandshakeResult = {
|
|
497
|
-
snapshot: GristWidgetSnapshot;
|
|
498
|
-
status: GristWidgetStatus;
|
|
499
|
-
error: string | null;
|
|
500
|
-
capabilities: GristCapabilities;
|
|
501
|
-
reload: () => void;
|
|
502
|
-
restart: () => void;
|
|
503
|
-
};
|
|
504
|
-
/**
|
|
505
|
-
* Mount a handshake manager local to the component subtree. Multiple
|
|
506
|
-
* widgets in the same page should NOT call this in parallel — instead,
|
|
507
|
-
* mount a single `<GristWidgetProvider>` at the app root.
|
|
508
|
-
*
|
|
509
|
-
* In tests, pass `options.env` (see `createTestEnvironment`) to drive the
|
|
510
|
-
* machine with a virtual clock.
|
|
511
|
-
*/
|
|
512
|
-
declare function useGristHandshake(options?: UseGristHandshakeOptions): UseGristHandshakeResult;
|
|
513
|
-
/**
|
|
514
|
-
* Convenience hook — equivalent to `useGristHandshake().capabilities` but
|
|
515
|
-
* skips returning the full snapshot. Intended for leaf components that only
|
|
516
|
-
* need to gate UI on `canRender` / `canWriteRecords` / etc.
|
|
517
|
-
*/
|
|
518
|
-
declare function useGristCapabilities(options?: UseGristHandshakeOptions): GristCapabilities;
|
|
519
|
-
|
|
520
|
-
/**
|
|
521
|
-
* `useAmbientGristHandshake()` — observe an already-mounted handshake
|
|
522
|
-
* manager without ever creating one.
|
|
523
|
-
*
|
|
524
|
-
* `useGristHandshake()` / `<GristHandshakeProvider>` both mount their OWN
|
|
525
|
-
* manager, which calls the real `grist.ready()` independently of any
|
|
526
|
-
* `<GristWidgetProvider>` elsewhere on the page. That's fine for a widget's
|
|
527
|
-
* single app-root provider, but wrong for read-only UI (a connection-status
|
|
528
|
-
* chip, a debug overlay) that must share the *same* handshake as the real
|
|
529
|
-
* widget rather than run a second, competing one. This hook only reads
|
|
530
|
-
* whatever manager a `<GristWidgetProvider>` ancestor already published;
|
|
531
|
-
* it returns `null` outside one instead of falling back to creating its own.
|
|
532
|
-
*/
|
|
533
|
-
|
|
534
|
-
type UseAmbientGristHandshakeResult = {
|
|
535
|
-
snapshot: GristWidgetSnapshot;
|
|
536
|
-
status: GristWidgetStatus;
|
|
537
|
-
error: string | null;
|
|
538
|
-
capabilities: GristCapabilities;
|
|
539
|
-
reload: () => void;
|
|
540
|
-
restart: () => void;
|
|
541
|
-
};
|
|
542
|
-
/**
|
|
543
|
-
* Returns `null` when mounted outside a `<GristWidgetProvider>` — there is
|
|
544
|
-
* no ambient manager to observe, and this hook intentionally never creates
|
|
545
|
-
* one. Mount inside `<GristWidgetProvider>` to get a live value.
|
|
546
|
-
*/
|
|
547
|
-
declare function useAmbientGristHandshake(): UseAmbientGristHandshakeResult | null;
|
|
548
|
-
|
|
549
|
-
type GristHandshakeContextValue = {
|
|
550
|
-
snapshot: GristWidgetSnapshot;
|
|
551
|
-
status: GristWidgetStatus;
|
|
552
|
-
error: string | null;
|
|
553
|
-
capabilities: GristCapabilities;
|
|
554
|
-
reload: () => void;
|
|
555
|
-
restart: () => void;
|
|
556
|
-
recordRpcSuccess: () => void;
|
|
557
|
-
recordRpcFailure: () => void;
|
|
558
|
-
};
|
|
559
|
-
type GristHandshakeProviderProps = {
|
|
560
|
-
options?: ManagerOptions;
|
|
561
|
-
children: ReactNode;
|
|
562
|
-
};
|
|
563
|
-
/**
|
|
564
|
-
* Mount a single {@link GristHandshakeManager} for the React subtree and
|
|
565
|
-
* expose its snapshot via context.
|
|
566
|
-
*
|
|
567
|
-
* The manager is created **once** on first mount; the `options` prop is
|
|
568
|
-
* captured at that time. To re-create the manager with new options, unmount
|
|
569
|
-
* and re-mount the provider (e.g. via a `key`).
|
|
570
|
-
*/
|
|
571
|
-
declare function GristHandshakeProvider({ options, children }: GristHandshakeProviderProps): react.JSX.Element;
|
|
572
|
-
/**
|
|
573
|
-
* Read the handshake context. Throws if no `<GristHandshakeProvider>` is
|
|
574
|
-
* mounted in the tree.
|
|
575
|
-
*
|
|
576
|
-
* Use {@link useGristHandshakeContextOptional} when the provider is optional
|
|
577
|
-
* (e.g. when the same component is sometimes used standalone).
|
|
578
|
-
*/
|
|
579
|
-
declare function useGristHandshakeContext(): GristHandshakeContextValue;
|
|
580
|
-
/** Non-throwing variant. */
|
|
581
|
-
declare function useGristHandshakeContextOptional(): GristHandshakeContextValue | null;
|
|
582
|
-
|
|
583
|
-
type UseGristRecordSubscriptionResult = {
|
|
584
|
-
loading: boolean;
|
|
585
|
-
error: string | null;
|
|
586
|
-
/** Latest mappings from `grist.onRecord` (logical name → real column id, or `string[]` for `allowMultiple`). */
|
|
587
|
-
mappings: GristWidgetColumnMap | null;
|
|
588
|
-
};
|
|
589
|
-
/**
|
|
590
|
-
* Subscribes to the currently-selected row in the widget's section.
|
|
591
|
-
*
|
|
592
|
-
* The Grist event is shared across all hook instances (no leak).
|
|
593
|
-
*/
|
|
594
|
-
declare function useGristRecord(cb: (record: Record<string, unknown> | null, mappings: GristWidgetColumnMap | null) => void, options?: GristReadyOptions): UseGristRecordSubscriptionResult;
|
|
595
|
-
|
|
596
|
-
/**
|
|
597
|
-
* Subscribes to the full row set visible in the widget's section
|
|
598
|
-
* (filters, sorts, and linked rows applied).
|
|
599
|
-
*/
|
|
600
|
-
declare function useGristRecords(cb: (records: Record<string, unknown>[], mappings: GristWidgetColumnMap | null) => void, options?: GristReadyOptions): UseGristRecordSubscriptionResult;
|
|
601
|
-
|
|
602
|
-
type UseGristNewRecordResult = {
|
|
603
|
-
/** True when the user has selected the blank "new row" placeholder. */
|
|
604
|
-
isNewRecord: boolean;
|
|
605
|
-
/** Mappings reported by Grist alongside the new-record event. */
|
|
606
|
-
mappings: GristWidgetColumnMap | null;
|
|
607
|
-
loading: boolean;
|
|
608
|
-
error: string | null;
|
|
609
|
-
};
|
|
610
|
-
/**
|
|
611
|
-
* Subscribes to `grist.onNewRecord` — fires when the user selects the blank
|
|
612
|
-
* row in the linked section. Useful for form-style widgets that need to
|
|
613
|
-
* switch into "create" mode.
|
|
614
|
-
*
|
|
615
|
-
* `isNewRecord` is reset to `false` whenever a real `onRecord` payload arrives,
|
|
616
|
-
* so callers don't need to manage that themselves.
|
|
617
|
-
*/
|
|
618
|
-
declare function useGristNewRecord(options?: GristReadyOptions): UseGristNewRecordResult;
|
|
619
|
-
|
|
620
|
-
type GristActionsStatus = "idle" | "running" | "error";
|
|
621
|
-
type UseGristActionsOptions = Pick<GristReadyOptions, "requiredAccess" | "columns" | "allowSelectBy" | "hasCustomOptions" | "onEditOptions">;
|
|
622
|
-
type UseGristActionsResult = {
|
|
623
|
-
status: GristActionsStatus;
|
|
624
|
-
error: string | null;
|
|
625
|
-
/** Apply raw user actions. `applyOptions.desc` is shown in the document undo stack. */
|
|
626
|
-
apply: (actions: GristUserActionTuple[], applyOptions?: GristApplyUserActionsOptions) => Promise<unknown>;
|
|
627
|
-
updateRecord: (tableId: string, recordId: number, patch: Record<string, unknown>, applyOptions?: GristApplyUserActionsOptions) => Promise<unknown>;
|
|
628
|
-
addRecord: (tableId: string, values: Record<string, unknown>, applyOptions?: GristApplyUserActionsOptions) => Promise<unknown>;
|
|
629
|
-
removeRecord: (tableId: string, recordId: number, applyOptions?: GristApplyUserActionsOptions) => Promise<unknown>;
|
|
630
|
-
bulkAddRecord: (tableId: string, values: Record<string, unknown[]>, applyOptions?: GristApplyUserActionsOptions) => Promise<unknown>;
|
|
631
|
-
bulkUpdateRecord: (tableId: string, rowIds: number[], columnarPatch: Record<string, unknown[]>, applyOptions?: GristApplyUserActionsOptions) => Promise<unknown>;
|
|
632
|
-
bulkRemoveRecord: (tableId: string, rowIds: number[], applyOptions?: GristApplyUserActionsOptions) => Promise<unknown>;
|
|
633
|
-
};
|
|
634
|
-
declare function useGristActions(options?: UseGristActionsOptions): UseGristActionsResult;
|
|
635
|
-
|
|
636
|
-
type UseGristMappedRecordResult<T> = {
|
|
637
|
-
rawRecord: Record<string, unknown> | null;
|
|
638
|
-
mappedRecord: T | null;
|
|
639
|
-
/** Current column mappings reported by Grist. */
|
|
640
|
-
mappings: GristWidgetColumnMap | null;
|
|
641
|
-
loading: boolean;
|
|
642
|
-
error: string | null;
|
|
643
|
-
/**
|
|
644
|
-
* Reverse-map a logical patch (`{ logicalName: value }`) into a real-column
|
|
645
|
-
* patch (`{ realColId: value }`) ready for `applyUserActions` /
|
|
646
|
-
* `useGristTableOps.update`.
|
|
647
|
-
* Falls back to `grist.mapColumnNamesBack` when present, otherwise resolves
|
|
648
|
-
* names manually from `mappings` (single-mapped columns only).
|
|
649
|
-
*/
|
|
650
|
-
mapBack: (patch: Partial<T>) => Record<string, unknown>;
|
|
651
|
-
/** Resolve a single logical name to its current real column id. */
|
|
652
|
-
resolveColumnId: (logicalName: keyof T & string) => string | undefined;
|
|
653
|
-
};
|
|
654
|
-
/**
|
|
655
|
-
* Subscribes to the selected row, applies `grist.mapColumnNames` so widget code
|
|
656
|
-
* sees logical column names, and exposes `mapBack` for safe writes.
|
|
657
|
-
*/
|
|
658
|
-
declare function useGristMappedRecord<T = Record<string, unknown>>(options?: GristReadyOptions): UseGristMappedRecordResult<T>;
|
|
659
|
-
|
|
660
|
-
type GristTableOpsStatus = "idle" | "running" | "error";
|
|
661
|
-
type UseGristTableOpsOptions = {
|
|
662
|
-
/**
|
|
663
|
-
* Table to operate on:
|
|
664
|
-
* - `"selected"` (default): use `grist.selectedTable` (the widget's current table).
|
|
665
|
-
* - any other string: use `grist.getTable(tableId)`.
|
|
666
|
-
*/
|
|
667
|
-
tableId?: "selected" | string;
|
|
668
|
-
/** Defaults to `"full"` since these operations write to the document. */
|
|
669
|
-
requiredAccess?: GristReadyOptions["requiredAccess"];
|
|
670
|
-
} & Pick<GristReadyOptions, "columns" | "allowSelectBy" | "hasCustomOptions" | "onEditOptions">;
|
|
671
|
-
type UseGristTableOpsResult = {
|
|
672
|
-
status: GristTableOpsStatus;
|
|
673
|
-
error: string | null;
|
|
674
|
-
/** Resolves the runtime tableId (only meaningful when `tableId` is `"selected"`). */
|
|
675
|
-
getTableId: () => Promise<string>;
|
|
676
|
-
create: (records: GristTableNewRecord | GristTableNewRecord[], opOptions?: GristTableOpOptions) => Promise<GristMinimalRecord | GristMinimalRecord[]>;
|
|
677
|
-
update: (records: GristTableUpdateRecord | GristTableUpdateRecord[], opOptions?: GristTableOpOptions) => Promise<void>;
|
|
678
|
-
upsert: (records: GristTableUpsertRecord | GristTableUpsertRecord[], opOptions?: GristTableUpsertOptions) => Promise<void>;
|
|
679
|
-
destroy: (recordIds: number | number[]) => Promise<void>;
|
|
680
|
-
};
|
|
681
|
-
/**
|
|
682
|
-
* Strongly-typed CRUD wrapper around Grist's `TableOperations` (`grist.selectedTable`
|
|
683
|
-
* or `grist.getTable(tableId)`). Prefer this over hand-rolled `applyUserActions`.
|
|
684
|
-
*
|
|
685
|
-
* @see https://support.getgrist.com/code/interfaces/TableOperations.TableOperations/
|
|
686
|
-
*/
|
|
687
|
-
declare function useGristTableOps(options?: UseGristTableOpsOptions): UseGristTableOpsResult;
|
|
688
|
-
|
|
689
|
-
type UseGristRowsFromTableOptions<T> = {
|
|
690
|
-
tableId: string;
|
|
691
|
-
/** Re-fetch on a fixed cadence (ms). Default: disabled. */
|
|
692
|
-
pollIntervalMs?: number;
|
|
693
|
-
/** Map raw rows to a domain shape (e.g. `decodeGristValue` your columns). */
|
|
694
|
-
transform?: (row: GristRowRecord) => GristRowRecord<T>;
|
|
695
|
-
requiredAccess?: GristReadyOptions["requiredAccess"];
|
|
696
|
-
} & Pick<GristReadyOptions, "columns" | "allowSelectBy" | "hasCustomOptions" | "onEditOptions">;
|
|
697
|
-
type UseGristRowsFromTableResult<T> = {
|
|
698
|
-
rows: GristRowRecord<T>[] | null;
|
|
699
|
-
loading: boolean;
|
|
700
|
-
error: string | null;
|
|
701
|
-
/** Force a re-fetch (call after writes that should be reflected immediately). */
|
|
702
|
-
refresh: () => Promise<void>;
|
|
703
|
-
};
|
|
704
|
-
/**
|
|
705
|
-
* Subscribes to a full table's rows via `docApi.fetchTable`.
|
|
706
|
-
*
|
|
707
|
-
* Unlike `useGristRecords` (which is bound to the widget's selected section),
|
|
708
|
-
* this hook works against any table id and **doesn't auto-update on Grist
|
|
709
|
-
* writes from elsewhere** — call `refresh()` after your own writes, or set
|
|
710
|
-
* `pollIntervalMs` for polling.
|
|
711
|
-
*/
|
|
712
|
-
declare function useGristRowsFromTable<T = Record<string, unknown>>(options: UseGristRowsFromTableOptions<T>): UseGristRowsFromTableResult<T>;
|
|
713
|
-
|
|
714
|
-
type UseGristAccessTokenOptions = {
|
|
715
|
-
/** Default for all token requests issued by this hook. */
|
|
716
|
-
readOnly?: boolean;
|
|
717
|
-
/** Pre-fetch a token on mount so `token` is non-null when widgets render. */
|
|
718
|
-
prefetch?: boolean;
|
|
719
|
-
/** Defaults to `"full"` since tokens are used for REST calls. */
|
|
720
|
-
requiredAccess?: GristReadyOptions["requiredAccess"];
|
|
721
|
-
} & Pick<GristReadyOptions, "columns" | "allowSelectBy" | "hasCustomOptions" | "onEditOptions">;
|
|
722
|
-
type UseGristAccessTokenResult = {
|
|
723
|
-
token: GristAccessToken | null;
|
|
724
|
-
loading: boolean;
|
|
725
|
-
error: string | null;
|
|
726
|
-
/** Request a fresh token (Grist tokens are short-lived; do not cache aggressively). */
|
|
727
|
-
refresh: (overrides?: {
|
|
728
|
-
readOnly?: boolean;
|
|
729
|
-
}) => Promise<GristAccessToken>;
|
|
730
|
-
/** `fetch()` against Grist's REST API with auth attached. */
|
|
731
|
-
fetch: (path: string, init?: RequestInit & {
|
|
732
|
-
readOnly?: boolean;
|
|
733
|
-
}) => Promise<Response>;
|
|
734
|
-
};
|
|
735
|
-
/**
|
|
736
|
-
* Exposes `docApi.getAccessToken` plus a ready-to-use `fetch` for calling
|
|
737
|
-
* Grist's REST API (e.g. attachments, records, sql) from a widget.
|
|
738
|
-
*/
|
|
739
|
-
declare function useGristAccessToken(options?: UseGristAccessTokenOptions): UseGristAccessTokenResult;
|
|
740
|
-
|
|
741
|
-
type UseGristSectionResult = {
|
|
742
|
-
/** Current widget ↔ section column mappings, refreshed on demand. */
|
|
743
|
-
mappings: GristWidgetColumnMap | null;
|
|
744
|
-
loading: boolean;
|
|
745
|
-
error: string | null;
|
|
746
|
-
/** Re-read mappings from `sectionApi`. */
|
|
747
|
-
refresh: () => Promise<void>;
|
|
748
|
-
/**
|
|
749
|
-
* Update the widget's declared `ColumnsToMap` (and other ready options) after
|
|
750
|
-
* mount. Use this to dynamically request more columns once the user has
|
|
751
|
-
* configured the widget.
|
|
752
|
-
*/
|
|
753
|
-
configure: (options: GristReadyOptions) => Promise<void>;
|
|
754
|
-
};
|
|
755
|
-
/**
|
|
756
|
-
* Wraps Grist's `sectionApi` (`mappings()` + `configure()`) so widgets can
|
|
757
|
-
* inspect/refresh the column mapping and re-declare requirements without
|
|
758
|
-
* touching `grist` directly.
|
|
759
|
-
*/
|
|
760
|
-
declare function useGristSection(options?: GristReadyOptions): UseGristSectionResult;
|
|
761
|
-
|
|
762
|
-
type UseGristWidgetOptionsConfig<T> = {
|
|
763
|
-
/** Default values returned before Grist responds and merged with stored options. */
|
|
764
|
-
defaults: T;
|
|
765
|
-
/** Debounce window for `setOptions` writes (ms). Default: 250. */
|
|
766
|
-
debounceMs?: number;
|
|
767
|
-
/**
|
|
768
|
-
* Optional namespace inside `grist.setOptions`. When set, this hook reads/writes
|
|
769
|
-
* `grist.setOption(namespace, value)` instead of the whole options blob — useful
|
|
770
|
-
* to share the options bag with `hasCustomOptions` / unrelated widget state.
|
|
771
|
-
*/
|
|
772
|
-
namespace?: string;
|
|
773
|
-
requiredAccess?: GristReadyOptions["requiredAccess"];
|
|
774
|
-
} & Pick<GristReadyOptions, "columns" | "allowSelectBy" | "hasCustomOptions" | "onEditOptions">;
|
|
775
|
-
type UseGristWidgetOptionsResult<T> = {
|
|
776
|
-
options: T;
|
|
777
|
-
/** True until Grist has responded with the initial `onOptions` payload. */
|
|
778
|
-
loading: boolean;
|
|
779
|
-
error: string | null;
|
|
780
|
-
/** Replace the options object (debounced write to Grist). */
|
|
781
|
-
setOptions: (next: T) => void;
|
|
782
|
-
/** Patch a subset of keys (debounced write to Grist). */
|
|
783
|
-
patchOptions: (patch: Partial<T>) => void;
|
|
784
|
-
/** Reset to `defaults` (immediate write to Grist). */
|
|
785
|
-
reset: () => Promise<void>;
|
|
786
|
-
};
|
|
787
|
-
/**
|
|
788
|
-
* Persist a typed object of widget settings via `grist.onOptions` / `setOptions`.
|
|
789
|
-
*
|
|
790
|
-
* - Defaults are returned immediately (no flicker before Grist responds).
|
|
791
|
-
* - Writes are debounced and batched.
|
|
792
|
-
* - `hasCustomOptions` defaults to `true` so Grist exposes the gear icon — pass
|
|
793
|
-
* `hasCustomOptions: false` to opt out.
|
|
794
|
-
*/
|
|
795
|
-
declare function useGristWidgetOptions<T extends Record<string, unknown>>(config: UseGristWidgetOptionsConfig<T>): UseGristWidgetOptionsResult<T>;
|
|
796
|
-
|
|
797
|
-
type UseGristTableOptions = {
|
|
798
|
-
requiredAccess?: GristRequiredAccess;
|
|
799
|
-
/**
|
|
800
|
-
* `'current'` (default): follow the widget’s selected table.
|
|
801
|
-
* Any other string: fixed table id (no `grist.selectedTable` polling).
|
|
802
|
-
*/
|
|
803
|
-
tableId?: "current" | string;
|
|
804
|
-
} & Pick<GristReadyOptions, "columns" | "allowSelectBy" | "hasCustomOptions" | "onEditOptions">;
|
|
805
|
-
type UseGristTableResult = {
|
|
806
|
-
tableId: string | null;
|
|
807
|
-
loading: boolean;
|
|
808
|
-
error: string | null;
|
|
809
|
-
refresh: () => Promise<void>;
|
|
810
|
-
fetchTable: (targetTableId: string) => Promise<GristColumnarTable>;
|
|
811
|
-
listTables: () => Promise<string[]>;
|
|
812
|
-
getDocName: () => Promise<string>;
|
|
813
|
-
fetchSelectedTable: (fetchOptions?: GristFetchSelectedOptions) => Promise<GristColumnarTable>;
|
|
814
|
-
fetchSelectedRecord: (rowId: number, fetchOptions?: GristFetchSelectedOptions) => Promise<Record<string, unknown>>;
|
|
815
|
-
};
|
|
816
|
-
/**
|
|
817
|
-
* Selected or fixed table id plus document reads — no raw `docApi` on the result.
|
|
818
|
-
*/
|
|
819
|
-
declare function useGristTable(options?: UseGristTableOptions): UseGristTableResult;
|
|
820
|
-
|
|
821
|
-
export { GristCapabilities, GristGeneration, GristHandshakeProvider, GristMappingSource, GristTerminationReason, GristWidgetSnapshot, useAmbientGristHandshake, useGristAccessToken, useGristActions, useGristAvailability, useGristCapabilities, useGristHandshake, useGristHandshakeContext, useGristHandshakeContextOptional, useGristMappedRecord, useGristNewRecord, useGristReady, useGristRecord, useGristRecords, useGristRowsFromTable, useGristSection, useGristTable, useGristTableOps, useGristWidgetOptions };
|
|
822
|
-
export type { GristActionsStatus, GristHandshakeContextValue, GristHandshakeProviderProps, GristTableOpsStatus, UseAmbientGristHandshakeResult, UseGristAccessTokenOptions, UseGristAccessTokenResult, UseGristActionsOptions, UseGristActionsResult, UseGristHandshakeOptions, UseGristHandshakeResult, UseGristMappedRecordResult, UseGristNewRecordResult, UseGristReadyOptions, UseGristReadyResult, UseGristRecordSubscriptionResult, UseGristRowsFromTableOptions, UseGristRowsFromTableResult, UseGristSectionResult, UseGristTableOpsOptions, UseGristTableOpsResult, UseGristTableOptions, UseGristTableResult, UseGristWidgetOptionsConfig, UseGristWidgetOptionsResult };
|