grist-widget-sdk 0.2.0 → 0.2.2-rc.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/sdk/helpers/grist-attachment-download.ts","../src/sdk/helpers/grist-fetch-with-auth.ts","../src/sdk/helpers/grist-value-codec.ts","../src/sdk/helpers/grist-attachment-upload.ts","../src/sdk/helpers/grist-safe-parse.ts","../src/sdk/helpers/grist-widget-options.ts","../src/sdk/helpers/grist-table-data.ts","../src/sdk/helpers/grist-user-actions.ts","../src/sdk/helpers/grist-columns-filters.ts","../src/sdk/helpers/grist-schema-formula.ts","../src/sdk/helpers/build-replica-document.ts","../src/sdk/helpers/replica-normalize.ts","../src/sdk/helpers/grist-mappings.ts","../src/sdk/internal/handshake/access.ts","../src/sdk/internal/handshake/types.ts","../src/sdk/internal/handshake/actions.ts","../src/sdk/internal/handshake/mapping-resolver.ts","../src/sdk/internal/handshake/reducer.ts","../src/sdk/internal/handshake/derive.ts","../src/sdk/helpers/grist-boundary-view.ts","../src/sdk/helpers/grist-widget-interaction.ts","../src/sdk/helpers/grist-sdk-alerts.ts","../src/sdk/hooks/use-grist-sdk-alert-descriptors.ts","../src/sdk/internal/handshake-manager-context.ts","../src/sdk/internal/ready-singleton.ts","../src/sdk/internal/build-manager-options.ts","../src/sdk/internal/handshake/effects/detect.ts","../src/sdk/internal/handshake/effects/negotiate.ts","../src/sdk/internal/subscriptions.ts","../src/sdk/internal/handshake/effects/subscriptions.ts","../src/sdk/internal/handshake/effects/mappings.ts","../src/sdk/internal/handshake/effects/heartbeat.ts","../src/sdk/internal/handshake/authz-from-options-cache.ts","../src/sdk/internal/handshake/environment.ts","../src/sdk/internal/handshake/manager.ts","../src/sdk/internal/embedded-handshake-manager.ts","../src/sdk/components/grist-widget-provider.tsx","../src/sdk/internal/contexts.tsx","../src/sdk/internal/merge-grist-result.ts","../src/sdk/internal/grist-widget-context-tree.tsx","../src/sdk/internal/compose-grist-widget.ts","../src/sdk/internal/hooks/use-grist-core.ts","../src/sdk/internal/hooks/use-grist-current-table.ts","../src/sdk/internal/hooks/use-rpc-heartbeat-coalesce.ts","../src/sdk/internal/hooks/use-grist-selection.ts","../src/sdk/internal/hooks/use-grist-table-ops-bound.ts","../src/sdk/internal/hooks/use-grist-reads.ts","../src/sdk/internal/hooks/use-grist-widget-options-api.ts","../src/sdk/internal/hooks/use-grist-linking.ts","../src/sdk/internal/hooks/use-grist-attachments-rest.ts","../src/sdk/internal/hooks/use-grist-theme.ts","../src/sdk/helpers/grist-theme-payload.ts","../src/sdk/internal/hooks/use-grist-section-api.ts","../src/sdk/components/grist-boundary.tsx","../src/sdk/use-grist.ts","../src/sdk/use-grist-schema.ts","../src/sdk/low-level-hooks/use-grist-ready.ts","../src/sdk/mid-level-hooks/use-grist-widget-options-from-context.ts","../src/sdk/use-widget-metadata.ts"],"sourcesContent":["export * from \"./sdk\"","import type { GristDocApi } from \"../types\"\n\nexport type GristFetchedAttachment = {\n base64: string\n contentType: string\n}\n\nexport type GristFetchedAttachmentBlob = {\n blob: Blob\n contentType: string\n}\n\nfunction attachmentIdFromObjectRecord(record: Record<string, unknown>): string | undefined {\n for (const candidate of [record.id, record.attachmentId, record.fileId]) {\n if (candidate === undefined || candidate === null) continue\n return String(candidate)\n }\n return undefined\n}\n\n/**\n * All attachment ids found in a Grist attachment cell value (ordered, deduped).\n * Attachment columns are usually an **array** of file refs; a single id or one JSON object is also supported.\n */\nexport function extractGristAttachmentIdsFromCell(value: unknown): string[] {\n const out: string[] = []\n const seen = new Set<string>()\n const push = (id: string) => {\n if (seen.has(id)) return\n seen.add(id)\n out.push(id)\n }\n\n const walk = (v: unknown): void => {\n if (v === undefined || v === null) return\n if (typeof v === \"number\") {\n push(String(v))\n return\n }\n if (typeof v === \"string\") {\n const trimmed = v.trim()\n if (!trimmed) return\n if (/^\\d+$/.test(trimmed)) {\n push(trimmed)\n return\n }\n try {\n walk(JSON.parse(trimmed) as unknown)\n } catch {\n /* ignore */\n }\n return\n }\n if (Array.isArray(v)) {\n for (const item of v) walk(item)\n return\n }\n if (typeof v === \"object\") {\n const record = v as Record<string, unknown>\n const direct = attachmentIdFromObjectRecord(record)\n if (direct !== undefined) {\n push(direct)\n return\n }\n for (const nested of Object.values(record)) walk(nested)\n }\n }\n\n walk(value)\n return out\n}\n\n/** First attachment id in the cell, if any (see {@link extractGristAttachmentIdsFromCell}). */\nexport function extractGristAttachmentId(value: unknown): string | undefined {\n return extractGristAttachmentIdsFromCell(value)[0]\n}\n\n/**\n * Signed Grist download URL for a single attachment id (`getAccessToken` + query auth).\n */\nexport async function getAttachmentDownloadUrl(\n docApi: GristDocApi,\n attachmentId: string,\n options?: { readOnly?: boolean }\n): Promise<string> {\n const getAccessToken = docApi.getAccessToken\n if (!getAccessToken) {\n throw new Error(\"getAccessToken is not available on docApi\")\n }\n const { token, baseUrl } = await getAccessToken({ readOnly: options?.readOnly ?? false })\n return `${baseUrl}/attachments/${attachmentId}/download?auth=${token}`\n}\n\n/** URL for the `index`’th attachment in a cell value (0-based). */\nexport async function getAttachmentDownloadUrlForCell(\n docApi: GristDocApi,\n cellValue: unknown,\n index: number,\n options?: { readOnly?: boolean }\n): Promise<string | null> {\n const ids = extractGristAttachmentIdsFromCell(cellValue)\n const id = ids[index]\n if (!id) return null\n return getAttachmentDownloadUrl(docApi, id, options)\n}\n\nasync function fetchBytesFromSignedAttachmentUrl(url: string): Promise<{\n buffer: ArrayBuffer\n contentType: string\n}> {\n const response = await fetch(url)\n const contentType = response.headers.get(\"content-type\")?.trim() || \"application/octet-stream\"\n if (!response.ok) {\n throw new Error(`Attachment download failed (${response.status})`)\n }\n const buffer = await response.arrayBuffer()\n return { buffer, contentType }\n}\n\nfunction bufferToBase64(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer)\n let binary = \"\"\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i])\n return btoa(binary)\n}\n\n/** Token + URL + fetch for one attachment id. */\nexport async function fetchAttachmentBase64(\n docApi: GristDocApi,\n attachmentId: string,\n options?: { readOnly?: boolean }\n): Promise<GristFetchedAttachment> {\n const url = await getAttachmentDownloadUrl(docApi, attachmentId, options)\n const { buffer, contentType } = await fetchBytesFromSignedAttachmentUrl(url)\n return { base64: bufferToBase64(buffer), contentType }\n}\n\n/** Download attachment bytes as a `Blob` (preferred for large files). */\nexport async function fetchAttachmentBlob(\n docApi: GristDocApi,\n attachmentId: string,\n options?: { readOnly?: boolean }\n): Promise<GristFetchedAttachmentBlob> {\n const url = await getAttachmentDownloadUrl(docApi, attachmentId, options)\n const { buffer, contentType } = await fetchBytesFromSignedAttachmentUrl(url)\n return { blob: new Blob([buffer], { type: contentType }), contentType }\n}\n\n/** Download the `index`’th attachment in a cell (0-based). */\nexport async function fetchAttachmentBase64ForCell(\n docApi: GristDocApi,\n cellValue: unknown,\n index: number,\n options?: { readOnly?: boolean }\n): Promise<GristFetchedAttachment | null> {\n const url = await getAttachmentDownloadUrlForCell(docApi, cellValue, index, options)\n if (!url) return null\n const { buffer, contentType } = await fetchBytesFromSignedAttachmentUrl(url)\n return { base64: bufferToBase64(buffer), contentType }\n}\n","import type { GristDocApi } from \"../types\"\n\nexport type GristAccessToken = {\n token: string\n baseUrl: string\n}\n\ntype TokenCacheEntry = {\n token: GristAccessToken\n fetchedAt: number\n}\n\nconst TOKEN_TTL_MS = 45_000\nconst cache = new Map<string, TokenCacheEntry>()\nconst inFlight = new Map<string, Promise<GristAccessToken>>()\n\nfunction cacheKey(readOnly: boolean): string {\n return readOnly ? \"ro\" : \"rw\"\n}\n\n/**\n * Returns an access token suitable for calling Grist's REST API directly.\n * Tokens are short-lived; results are cached briefly and coalesced per readOnly flag.\n */\nexport async function getGristAccessToken(\n docApi: GristDocApi,\n options?: { readOnly?: boolean }\n): Promise<GristAccessToken> {\n if (!docApi.getAccessToken) {\n throw new Error(\"getAccessToken is not available on docApi (need higher access level)\")\n }\n\n const readOnly = options?.readOnly ?? false\n const key = cacheKey(readOnly)\n const now = Date.now()\n const hit = cache.get(key)\n if (hit && now - hit.fetchedAt < TOKEN_TTL_MS) {\n return hit.token\n }\n\n const pending = inFlight.get(key)\n if (pending) return pending\n\n const next = docApi.getAccessToken({ readOnly }).then((token) => {\n cache.set(key, { token, fetchedAt: Date.now() })\n inFlight.delete(key)\n return token\n })\n\n inFlight.set(key, next)\n return next\n}\n\n/** Clear cached tokens (tests or after auth errors). */\nexport function clearGristAccessTokenCache(): void {\n cache.clear()\n inFlight.clear()\n}\n\n/**\n * `fetch()` against Grist's REST API with the doc access token attached.\n */\nexport async function fetchWithGristAuth(\n docApi: GristDocApi,\n path: string,\n init?: RequestInit & { readOnly?: boolean }\n): Promise<Response> {\n const readOnly = init?.readOnly ?? false\n let token: GristAccessToken\n try {\n token = await getGristAccessToken(docApi, { readOnly })\n } catch (err) {\n clearGristAccessTokenCache()\n throw err\n }\n\n const isAbsolute = /^https?:\\/\\//i.test(path)\n const cleanPath = isAbsolute ? path : path.startsWith(\"/\") ? path : `/${path}`\n const method = (init?.method ?? \"GET\").toUpperCase()\n\n const url = isAbsolute\n ? new URL(path)\n : new URL(`${token.baseUrl.replace(/\\/$/, \"\")}${cleanPath}`)\n\n // Grist signs widget REST calls with a short-lived `auth` query parameter.\n // Do not send `Authorization: Bearer` from the browser: many Grist deployments\n // omit it from Access-Control-Allow-Headers, which breaks POST (e.g. attachment upload).\n if (!url.searchParams.has(\"auth\")) url.searchParams.set(\"auth\", token.token)\n\n const headers = new Headers(init?.headers ?? {})\n headers.delete(\"Authorization\")\n\n const response = await fetch(url.toString(), { ...init, headers })\n if (response.status === 401) {\n clearGristAccessTokenCache()\n const retryToken = await getGristAccessToken(docApi, { readOnly })\n url.searchParams.set(\"auth\", retryToken.token)\n return fetch(url.toString(), { ...init, headers })\n }\n return response\n}\n","/**\n * Encoding helpers for Grist cell values.\n *\n * Grist sends some types as marshalled tuples or numeric epochs. This file\n * exposes pure decode/encode functions so widget code never has to spelunk\n * Grist's wire format.\n *\n * References: Grist `grist/RowRecord` and `grist/DocActions` typings.\n */\n\nimport type { GristReplicaColumn } from \"../types\"\n\n/** `[\"E\", \"ErrorClass\", \"message\", traceback?]` — Grist error sentinel. */\nexport type GristEncodedError = [\"E\", string, string?, string?]\n/** `[\"L\", ...items]` — list (used for ChoiceList, RefList, Attachments). */\nexport type GristEncodedList = [\"L\", ...unknown[]]\n/** `[\"D\", epochSeconds, \"tz/Name\"]` — DateTime with timezone. */\nexport type GristEncodedDateTime = [\"D\", number, string]\n/** `[\"d\", epochSeconds]` — Date (no time). */\nexport type GristEncodedDate = [\"d\", number]\n/** `[\"R\", tableId, rowId]` — explicit reference. */\nexport type GristEncodedRef = [\"R\", string, number]\n/** `[\"r\", rowId]` — bare reference (when table is contextual). */\nexport type GristEncodedBareRef = [\"r\", number]\n/** `[\"P\", encoded]` — pending marker. */\nexport type GristEncodedPending = [\"P\"]\n\nexport type GristDecodedValue =\n | null\n | string\n | number\n | boolean\n | Date\n | GristDecodedValue[]\n | { __error: true; type: string; message?: string; traceback?: string }\n | { __ref: true; tableId?: string; rowId: number }\n\nconst MARSHALLED_TAGS = new Set([\"E\", \"L\", \"D\", \"d\", \"R\", \"r\", \"P\"])\n\nfunction isMarshalledTuple(value: unknown): value is unknown[] {\n return (\n Array.isArray(value) &&\n typeof value[0] === \"string\" &&\n value[0].length <= 2 &&\n MARSHALLED_TAGS.has(value[0])\n )\n}\n\n/**\n * Normalises a Grist `fetchTable` cell that points at a row in another table.\n * Most payloads use a bare numeric row id, but `Ref:*` values may appear as\n * `[\"R\", tableId, rowId]` or `[\"r\", rowId]` (same shape as {@link decodeGristValue}).\n */\nexport function coerceGristDocApiRefRowId(value: unknown): number | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) return value\n if (!Array.isArray(value) || value.length < 2) return undefined\n const tag = value[0]\n if (tag === \"R\" && typeof value[2] === \"number\" && Number.isFinite(value[2])) return value[2]\n if (tag === \"r\" && typeof value[1] === \"number\" && Number.isFinite(value[1])) return value[1]\n return undefined\n}\n\nfunction looksLikeAttachmentColumn(column?: GristReplicaColumn): boolean {\n return column?.type === \"Attachments\"\n}\n\nfunction looksLikeChoiceListColumn(column?: GristReplicaColumn): boolean {\n return column?.type === \"ChoiceList\"\n}\n\nfunction looksLikeRefListColumn(column?: GristReplicaColumn): boolean {\n return typeof column?.type === \"string\" && column.type.startsWith(\"RefList:\")\n}\n\nfunction looksLikeRefColumn(column?: GristReplicaColumn): boolean {\n return typeof column?.type === \"string\" && column.type.startsWith(\"Ref:\")\n}\n\nfunction looksLikeDateColumn(column?: GristReplicaColumn): boolean {\n return column?.type === \"Date\"\n}\n\nfunction looksLikeDateTimeColumn(column?: GristReplicaColumn): boolean {\n return typeof column?.type === \"string\" && column.type.startsWith(\"DateTime\")\n}\n\n/**\n * Decodes a Grist cell value into an idiomatic JS value.\n *\n * Pass the column's metadata (from `useGristSchema` or `_grist_Tables_column`)\n * for type-aware decoding (e.g. `Date` columns return `Date` even when stored as a number).\n */\nexport function decodeGristValue(value: unknown, column?: GristReplicaColumn): GristDecodedValue {\n if (value === null || value === undefined) return null\n\n if (isMarshalledTuple(value)) {\n const tag = value[0] as string\n switch (tag) {\n case \"E\":\n return {\n __error: true,\n type: typeof value[1] === \"string\" ? value[1] : \"Error\",\n message: typeof value[2] === \"string\" ? value[2] : undefined,\n traceback: typeof value[3] === \"string\" ? value[3] : undefined,\n }\n case \"L\":\n return value.slice(1).map((v) => decodeGristValue(v, undefined)) as GristDecodedValue[]\n case \"D\":\n if (typeof value[1] === \"number\") return new Date(value[1] * 1000)\n return null\n case \"d\":\n if (typeof value[1] === \"number\") return new Date(value[1] * 1000)\n return null\n case \"R\":\n return {\n __ref: true,\n tableId: typeof value[1] === \"string\" ? value[1] : undefined,\n rowId: typeof value[2] === \"number\" ? value[2] : 0,\n }\n case \"r\":\n return { __ref: true, rowId: typeof value[1] === \"number\" ? value[1] : 0 }\n case \"P\":\n return null\n default:\n return null\n }\n }\n\n if (looksLikeDateColumn(column) || looksLikeDateTimeColumn(column)) {\n if (typeof value === \"number\" && Number.isFinite(value)) return new Date(value * 1000)\n }\n\n if (looksLikeRefColumn(column) && typeof value === \"number\") {\n return { __ref: true, rowId: value }\n }\n\n if ((looksLikeRefListColumn(column) || looksLikeChoiceListColumn(column) || looksLikeAttachmentColumn(column)) && Array.isArray(value)) {\n return value.map((v) => decodeGristValue(v, undefined)) as GristDecodedValue[]\n }\n\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") return value\n if (Array.isArray(value)) return value.map((v) => decodeGristValue(v, undefined)) as GristDecodedValue[]\n return null\n}\n\n/** Convenience: true when the cell is a Grist error sentinel. */\nexport function isGristCellError(value: unknown): value is GristEncodedError {\n return Array.isArray(value) && value[0] === \"E\"\n}\n\n/**\n * Encodes a JS value into Grist's expected wire form for a given column type.\n *\n * Use before passing values to `applyUserActions` or `TableOperations.update`\n * for `Date`, `DateTime`, `Ref`, `RefList`, and `ChoiceList` columns.\n */\nexport function encodeGristValue(value: unknown, column?: GristReplicaColumn): unknown {\n if (value === null || value === undefined) return null\n\n if (looksLikeDateColumn(column) || looksLikeDateTimeColumn(column)) {\n if (value instanceof Date) return Math.floor(value.getTime() / 1000)\n if (typeof value === \"string\") {\n const parsed = Date.parse(value)\n if (!Number.isNaN(parsed)) return Math.floor(parsed / 1000)\n }\n if (typeof value === \"number\") return Math.floor(value)\n }\n\n if (looksLikeRefColumn(column)) {\n if (typeof value === \"number\") return value\n if (value && typeof value === \"object\" && \"rowId\" in value) {\n return (value as { rowId: number }).rowId\n }\n }\n\n if (looksLikeRefListColumn(column) || looksLikeChoiceListColumn(column) || looksLikeAttachmentColumn(column)) {\n if (Array.isArray(value)) {\n const items = value.map((v) => {\n if (v && typeof v === \"object\" && \"rowId\" in v) return (v as { rowId: number }).rowId\n return v\n })\n return [\"L\", ...items]\n }\n }\n\n return value\n}\n","import type { GristDocApi } from \"../types\"\nimport { extractGristAttachmentIdsFromCell } from \"./grist-attachment-download\"\nimport { fetchWithGristAuth } from \"./grist-fetch-with-auth\"\nimport { encodeGristValue } from \"./grist-value-codec\"\n\nconst ATTACHMENTS_COLUMN = { type: \"Attachments\" as const }\n\nexport type GristEncodedAttachmentList = [\"L\", ...(number | string)[]]\n\nexport type GristAttachmentUploadResult = {\n /** All attachment ids returned by `POST /attachments`. */\n ids: string[]\n /** First id in `ids` (convenience for single-file uploads). */\n firstId: string\n}\n\n/**\n * Parse the body of `POST /attachments` (widget or REST).\n * Grist returns a JSON array of attachment ids, e.g. `[42]` or `[101, 102]`.\n */\nexport function parseGristAttachmentUploadResponseIds(\n raw: string,\n options?: { strict?: boolean }\n): string[] {\n const trimmed = raw.trim()\n if (!trimmed) {\n throw new Error(\"Attachment upload returned an empty response.\")\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(trimmed) as unknown\n } catch {\n if (options?.strict) {\n throw new Error(\"Attachment upload returned non-JSON response.\")\n }\n parsed = trimmed\n }\n\n return extractAttachmentIdsFromUploadPayload(parsed, options)\n}\n\n/**\n * First attachment id from an upload response (see {@link parseGristAttachmentUploadResponseIds}).\n */\nexport function parseGristAttachmentUploadResponse(\n raw: string,\n options?: { strict?: boolean }\n): string {\n const ids = parseGristAttachmentUploadResponseIds(raw, options)\n return ids[0]!\n}\n\nexport function extractAttachmentIdsFromUploadPayload(\n parsed: unknown,\n options?: { strict?: boolean }\n): string[] {\n if (options?.strict) {\n return extractAttachmentIdsFromUploadPayloadStrict(parsed)\n }\n\n const first = extractFirstAttachmentIdFromUploadPayload(parsed)\n if (first !== undefined) {\n if (Array.isArray(parsed)) {\n const ids: string[] = []\n const seen = new Set<string>()\n for (const item of parsed) {\n const id = coerceAttachmentId(item)\n if (id && !seen.has(id)) {\n seen.add(id)\n ids.push(id)\n }\n }\n return ids.length > 0 ? ids : [first]\n }\n return [first]\n }\n\n throw new Error(\"Attachment upload returned an unexpected response shape.\")\n}\n\nfunction extractAttachmentIdsFromUploadPayloadStrict(parsed: unknown): string[] {\n if (typeof parsed === \"number\" && Number.isFinite(parsed)) {\n return [String(parsed)]\n }\n\n if (Array.isArray(parsed)) {\n const ids: string[] = []\n const seen = new Set<string>()\n for (const item of parsed) {\n if (typeof item !== \"number\" || !Number.isFinite(item)) {\n throw new Error(\"Attachment upload returned an unexpected response shape.\")\n }\n const id = String(item)\n if (!seen.has(id)) {\n seen.add(id)\n ids.push(id)\n }\n }\n if (ids.length === 0) {\n throw new Error(\"Attachment upload returned an empty id list.\")\n }\n return ids\n }\n\n throw new Error(\"Attachment upload returned an unexpected response shape.\")\n}\n\n/** @deprecated Prefer {@link extractAttachmentIdsFromUploadPayload}. */\nexport function extractFirstAttachmentIdFromUploadPayload(parsed: unknown): string | undefined {\n if (typeof parsed === \"number\" && Number.isFinite(parsed)) {\n return String(parsed)\n }\n\n if (typeof parsed === \"string\" && parsed.trim()) {\n return parsed.trim()\n }\n\n if (Array.isArray(parsed)) {\n for (const item of parsed) {\n const id = coerceAttachmentId(item)\n if (id) return id\n }\n return undefined\n }\n\n if (parsed && typeof parsed === \"object\") {\n const record = parsed as Record<string, unknown>\n for (const key of [\"id\", \"attachmentId\", \"fileId\"]) {\n const id = coerceAttachmentId(record[key])\n if (id) return id\n }\n }\n\n return undefined\n}\n\nfunction coerceAttachmentId(value: unknown): string | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return String(value)\n }\n if (typeof value === \"string\" && value.trim()) {\n return value.trim()\n }\n return undefined\n}\n\nfunction normalizeAttachmentIdForWire(id: string | number): number | string {\n const numeric = typeof id === \"number\" ? id : Number(id)\n if (Number.isFinite(numeric) && String(numeric) === String(id).trim()) {\n return numeric\n }\n return typeof id === \"number\" ? String(id) : id.trim()\n}\n\n/** Wire value for an Attachments cell (Grist list encoding). */\nexport function gristAttachmentCellValues(\n attachmentIds: (string | number)[]\n): GristEncodedAttachmentList {\n const items = attachmentIds.map(normalizeAttachmentIdForWire)\n const encoded = encodeGristValue(items, ATTACHMENTS_COLUMN)\n if (!Array.isArray(encoded) || encoded[0] !== \"L\") {\n return [\"L\", ...items]\n }\n return encoded as GristEncodedAttachmentList\n}\n\n/** Wire value for a single-file Attachments cell. */\nexport function gristAttachmentCellValue(attachmentId: string | number): GristEncodedAttachmentList {\n return gristAttachmentCellValues([attachmentId])\n}\n\n/**\n * Merge new attachment ids into an existing Attachments cell value (deduped, order preserved).\n */\nexport function mergeGristAttachmentCellValue(\n existingCell: unknown,\n newIds: (string | number)[]\n): GristEncodedAttachmentList {\n const existing = extractGristAttachmentIdsFromCell(existingCell)\n const merged: string[] = []\n const seen = new Set<string>()\n const push = (raw: string | number) => {\n const id = String(raw).trim()\n if (!id || seen.has(id)) return\n seen.add(id)\n merged.push(id)\n }\n for (const id of existing) push(id)\n for (const id of newIds) push(id)\n return gristAttachmentCellValues(merged)\n}\n\nconst UPLOAD_HEADERS = {\n \"X-Requested-With\": \"XMLHttpRequest\",\n Accept: \"application/json\",\n} as const\n\n/**\n * Upload a file to the current document via `POST /attachments`.\n *\n * Uses `getAccessToken({ readOnly: false })` and `?auth=` (see Grist widget docs).\n * Requires document **full** access in the widget.\n */\nexport async function uploadGristAttachment(\n docApi: GristDocApi,\n file: Blob | File,\n options?: { fileName?: string }\n): Promise<GristAttachmentUploadResult> {\n const form = new FormData()\n const fileName =\n options?.fileName ?? (file instanceof File && file.name ? file.name : \"upload\")\n form.append(\"upload\", file, fileName)\n\n let response: Response\n try {\n response = await fetchWithGristAuth(docApi, \"/attachments\", {\n method: \"POST\",\n body: form,\n readOnly: false,\n headers: UPLOAD_HEADERS,\n })\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n if (/failed to fetch/i.test(msg)) {\n const widgetOrigin =\n typeof globalThis.location !== \"undefined\"\n ? globalThis.location.origin\n : \"this widget origin\"\n throw new Error(\n `Attachment upload was blocked by the Grist host (CORS). The browser could not POST from ${widgetOrigin} to the document API. If upload worked from a dev URL (e.g. ngrok) but fails after deploy, add the new widget URL to your Grist server CORS allowlist (see grist-core#2040).`\n )\n }\n throw err\n }\n\n const raw = await response.text()\n if (!response.ok) {\n throw new Error(\n raw.trim()\n ? `Attachment upload failed (${response.status}): ${raw.slice(0, 200)}`\n : `Attachment upload failed (${response.status})`\n )\n }\n\n const ids = parseGristAttachmentUploadResponseIds(raw)\n return { ids, firstId: ids[0]! }\n}\n","import { z, type ZodType } from \"zod\"\n\nimport type { GristReplicaColumn, GristRowRecord } from \"../types\"\nimport type { GristColumnarTable } from \"./grist-table-data\"\nimport { normalizeGristChoiceListEntries, type GristChoiceListEntry } from \"./grist-widget-options\"\nimport { decodeGristValue, type GristDecodedValue } from \"./grist-value-codec\"\n\nexport type GristSafeParseIssueCode =\n | \"grist_error\"\n | \"invalid_format\"\n | \"type_mismatch\"\n | \"helper_mismatch\"\n | \"zod_error\"\n\nexport type GristSafeParseIssue = {\n code: GristSafeParseIssueCode\n message: string\n}\n\nexport type GristSafeRefValue = {\n rowId: number\n display?: string | null\n}\n\nexport type GristSafeRefListValue = {\n rowIds: number[]\n displays?: string[]\n}\n\nexport const gristSafeRefValueSchema = z.object({\n rowId: z.number(),\n display: z.string().nullable().optional(),\n})\n\nexport const gristSafeRefListValueSchema = z.object({\n rowIds: z.array(z.number()),\n displays: z.array(z.string()).optional(),\n})\n\nexport const gristCellValueSchema = z.union([\n z.null(),\n z.string(),\n z.number(),\n z.boolean(),\n z.date(),\n z.array(z.unknown()),\n gristSafeRefValueSchema,\n gristSafeRefListValueSchema,\n])\n\nexport type GristCellValue = z.infer<typeof gristCellValueSchema>\n\nexport type GristSafeParseCellResult<TValue = unknown> = {\n ok: boolean\n typedValue: TValue | null\n displayValue: unknown\n raw: unknown\n issues: GristSafeParseIssue[]\n}\n\ntype RefMode = \"id\" | \"detailed\"\n\nexport type SafeParseGristValuesOptions<TValue = unknown> = {\n values: readonly unknown[]\n column?: GristReplicaColumn\n helperValues?: readonly unknown[]\n schema?: ZodType<TValue>\n fallbackUntypedToString?: boolean\n refMode?: RefMode\n}\n\nexport type SafeParseGristTableDataOptions = {\n columns?: Record<string, GristReplicaColumn>\n displayHelpersByRef?: Record<string, string>\n order?: \"none\" | \"id\" | \"grist\"\n fallbackUntypedToString?: boolean\n refMode?: RefMode\n}\n\nexport type GristSafeTableCellIssue = GristSafeParseIssue & {\n rowIndex: number\n colId: string\n}\n\nexport type GristSafeChoiceTokenMeta = {\n value: string\n label: string\n fillColor?: string\n textColor?: string\n valid: boolean\n}\n\nexport type GristSafeTableCellMeta = {\n rowIndex: number\n colId: string\n ok: boolean\n issues: GristSafeParseIssue[]\n choiceTokens?: GristSafeChoiceTokenMeta[]\n}\n\nexport type SafeParseGristTableDataResult<TRow extends Record<string, unknown> = Record<string, unknown>> = {\n rows: GristRowRecord<TRow>[]\n cellIssues: GristSafeTableCellIssue[]\n cellMeta: GristSafeTableCellMeta[]\n cellMetaByKey: Record<string, GristSafeTableCellMeta>\n cellResultsByColumn: Record<string, GristSafeParseCellResult[]>\n}\n\n/** Maps `Ref:*` / `RefList:*` column ids to their paired `gristHelper_*` column id (same rules as safe-parse). */\nexport function inferDisplayHelpersByRef(\n columns: Record<string, GristReplicaColumn>\n): Record<string, string> {\n const out: Record<string, string> = {}\n const helperColumns = Object.entries(columns).filter(([colId]) =>\n colId.startsWith(\"gristHelper_\")\n )\n const usedHelpers = new Set<string>()\n const colRefToColId = new Map<number, string>()\n for (const [colId, col] of Object.entries(columns)) {\n if (typeof col?.colRef === \"number\" && Number.isFinite(col.colRef)) {\n colRefToColId.set(col.colRef, colId)\n }\n }\n for (const [colId, col] of Object.entries(columns)) {\n const type = col?.type\n if (typeof type !== \"string\" || (!type.startsWith(\"Ref:\") && !type.startsWith(\"RefList:\"))) {\n continue\n }\n if (typeof col.displayColRef === \"number\" && Number.isFinite(col.displayColRef)) {\n const helperColId = colRefToColId.get(col.displayColRef)\n if (helperColId) {\n out[colId] = helperColId\n usedHelpers.add(helperColId)\n continue\n }\n }\n const match = helperColumns.find(([, helper]) => {\n const formula = helper?.formula\n return typeof formula === \"string\" && (formula.includes(`$${colId}.`) || formula.includes(`$${colId}`))\n })\n if (match) {\n out[colId] = match[0]\n usedHelpers.add(match[0])\n }\n }\n\n // Secondary fallback for schemas where helper formulas are unavailable:\n // pair unresolved Ref/RefList columns with nearest following gristHelper_*.\n const unresolvedRefs = Object.entries(columns)\n .filter(([colId, col]) => {\n const type = col?.type\n return (\n !out[colId] &&\n typeof type === \"string\" &&\n (type.startsWith(\"Ref:\") || type.startsWith(\"RefList:\"))\n )\n })\n .sort((a, b) => (a[1]?.parentPos ?? Number.MAX_SAFE_INTEGER) - (b[1]?.parentPos ?? Number.MAX_SAFE_INTEGER))\n const helperByPos = helperColumns\n .filter(([helperId]) => !usedHelpers.has(helperId))\n .sort((a, b) => (a[1]?.parentPos ?? Number.MAX_SAFE_INTEGER) - (b[1]?.parentPos ?? Number.MAX_SAFE_INTEGER))\n for (const [refId, refCol] of unresolvedRefs) {\n const refPos = refCol?.parentPos ?? Number.MAX_SAFE_INTEGER\n const candidate = helperByPos.find(([, helperCol]) => {\n const helperPos = helperCol?.parentPos ?? Number.MAX_SAFE_INTEGER\n return helperPos > refPos\n })\n if (!candidate) continue\n out[refId] = candidate[0]\n usedHelpers.add(candidate[0])\n }\n // If multiple unresolved refs remain, greedily map by order.\n for (const [refId] of unresolvedRefs) {\n if (out[refId]) continue\n const candidate = helperByPos.find(([helperId]) => !usedHelpers.has(helperId))\n if (!candidate) continue\n out[refId] = candidate[0]\n usedHelpers.add(candidate[0])\n }\n return out\n}\n\nfunction computeRowCount(data: Record<string, unknown[]>): number {\n const idCol = data.id\n if (Array.isArray(idCol)) return idCol.length\n for (const key of Object.keys(data)) {\n const col = data[key]\n if (Array.isArray(col)) return col.length\n }\n return 0\n}\n\nfunction manualSortKey(row: Record<string, unknown>): number | null {\n const v = row.manualSort\n if (typeof v === \"number\" && !Number.isNaN(v)) return v\n if (typeof v === \"string\" && v.trim() !== \"\") {\n const n = Number(v)\n if (!Number.isNaN(n)) return n\n }\n return null\n}\n\nfunction sortRowsByGristOrder<T = Record<string, unknown>>(\n rows: readonly GristRowRecord<T>[]\n): GristRowRecord<T>[] {\n const hasManual = rows.some((r) => manualSortKey(r as Record<string, unknown>) !== null)\n if (!hasManual) {\n return [...rows].sort((a, b) => {\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n })\n }\n return [...rows].sort((a, b) => {\n const ma = manualSortKey(a as Record<string, unknown>)\n const mb = manualSortKey(b as Record<string, unknown>)\n if (ma !== null && mb !== null && ma !== mb) return ma - mb\n if (ma !== null && mb === null) return -1\n if (ma === null && mb !== null) return 1\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n })\n}\n\nfunction columnKind(column?: GristReplicaColumn):\n | \"text\"\n | \"numeric\"\n | \"int\"\n | \"bool\"\n | \"date\"\n | \"datetime\"\n | \"choice\"\n | \"choiceList\"\n | \"ref\"\n | \"refList\"\n | \"attachments\"\n | \"any\"\n | \"unknown\" {\n const type = column?.type\n if (!type) return \"unknown\"\n if (type === \"Text\") return \"text\"\n if (type === \"Numeric\") return \"numeric\"\n if (type === \"Int\") return \"int\"\n if (type === \"Bool\") return \"bool\"\n if (type === \"Date\") return \"date\"\n if (type === \"DateTime\" || type.startsWith(\"DateTime:\")) return \"datetime\"\n if (type === \"Choice\") return \"choice\"\n if (type === \"ChoiceList\") return \"choiceList\"\n if (type.startsWith(\"Ref:\")) return \"ref\"\n if (type.startsWith(\"RefList:\")) return \"refList\"\n if (type === \"Attachments\") return \"attachments\"\n if (type === \"Any\") return \"any\"\n return \"unknown\"\n}\n\nfunction primitiveToString(value: unknown): string | null {\n if (value === null || value === undefined) return null\n if (typeof value === \"string\") return value\n if (typeof value === \"number\" || typeof value === \"boolean\" || typeof value === \"bigint\") {\n return String(value)\n }\n return null\n}\n\nfunction normalizeRefDisplay(value: unknown): { value?: string | null; issue?: GristSafeParseIssue } {\n if (value === null || value === undefined) return { value: null }\n if (typeof value === \"string\") return { value }\n if (typeof value === \"number\" || typeof value === \"boolean\") return { value: String(value) }\n return {\n issue: {\n code: \"helper_mismatch\",\n message: \"Ref display helper value should be a scalar value.\",\n },\n }\n}\n\nfunction normalizeRefListDisplays(value: unknown): { values?: string[]; issue?: GristSafeParseIssue } {\n if (value === null || value === undefined) return { values: [] }\n if (typeof value === \"string\") {\n const s = value.trim()\n if (s === \"\") return { values: [] }\n if (s.startsWith(\"[\")) {\n try {\n const parsed = JSON.parse(s)\n if (Array.isArray(parsed)) {\n return normalizeRefListDisplays(parsed)\n }\n } catch {\n // Keep existing error below for non-array/non-JSON helper strings.\n }\n }\n }\n if (!Array.isArray(value)) {\n return {\n issue: {\n code: \"helper_mismatch\",\n message: \"RefList display helper value should be an array.\",\n },\n }\n }\n // Grist list wire format may leak through as [\"L\", ...items].\n // Treat a leading \"L\" marker as metadata, not a display label.\n const items =\n value.length > 0 && value[0] === \"L\"\n ? value.slice(1)\n : value\n const out: string[] = []\n for (const item of items) {\n const s = primitiveToString(item)\n if (s === null) {\n return {\n issue: {\n code: \"helper_mismatch\",\n message: \"RefList helper items should be scalar values.\",\n },\n }\n }\n out.push(s)\n }\n return { values: out }\n}\n\nfunction normalizeRefValue(\n decoded: GristDecodedValue,\n helperValue: unknown,\n refMode: RefMode\n): { value: number | GristSafeRefValue | null; issues: GristSafeParseIssue[] } {\n const issues: GristSafeParseIssue[] = []\n if (decoded === null) return { value: null, issues }\n\n const rowId =\n typeof decoded === \"number\" && Number.isFinite(decoded)\n ? decoded\n : decoded && typeof decoded === \"object\" && \"__ref\" in decoded\n ? (decoded as { rowId: number }).rowId\n : null\n\n // Grist empty refs can surface as 0; treat as empty cell.\n if (rowId === 0) return { value: null, issues }\n if (rowId === null || !Number.isFinite(rowId)) {\n issues.push({\n code: \"type_mismatch\",\n message: \"Expected a Ref row id.\",\n })\n return { value: null, issues }\n }\n\n if (refMode === \"id\") return { value: rowId, issues }\n\n const helper = normalizeRefDisplay(helperValue)\n if (helper.issue) issues.push(helper.issue)\n return {\n value: { rowId, display: helper.value },\n issues,\n }\n}\n\nfunction normalizeRefListValue(\n decoded: GristDecodedValue,\n helperValue: unknown,\n refMode: RefMode\n): { value: number[] | GristSafeRefListValue | null; issues: GristSafeParseIssue[] } {\n const issues: GristSafeParseIssue[] = []\n if (decoded === null) return { value: null, issues }\n if (!Array.isArray(decoded)) {\n issues.push({\n code: \"type_mismatch\",\n message: \"Expected an array for RefList.\",\n })\n return { value: null, issues }\n }\n\n const rowIds: number[] = []\n for (const item of decoded) {\n if (typeof item === \"number\" && Number.isFinite(item) && item !== 0) {\n rowIds.push(item)\n continue\n }\n if (item && typeof item === \"object\" && \"__ref\" in item) {\n const rowId = (item as { rowId: number }).rowId\n if (typeof rowId === \"number\" && Number.isFinite(rowId) && rowId !== 0) {\n rowIds.push(rowId)\n continue\n }\n }\n issues.push({\n code: \"type_mismatch\",\n message: \"RefList items should be row ids.\",\n })\n return { value: null, issues }\n }\n\n if (refMode === \"id\") return { value: rowIds, issues }\n\n const helper = normalizeRefListDisplays(helperValue)\n if (helper.issue) {\n issues.push(helper.issue)\n } else if (helper.values && helper.values.length > 0 && helper.values.length !== rowIds.length) {\n issues.push({\n code: \"helper_mismatch\",\n message: \"RefList helper labels count does not match row ids count.\",\n })\n }\n return {\n value: { rowIds, displays: helper.values },\n issues,\n }\n}\n\nfunction normalizeByColumnKind(\n decoded: GristDecodedValue,\n kind: ReturnType<typeof columnKind>,\n helperValue: unknown,\n fallbackUntypedToString: boolean,\n refMode: RefMode\n): { value: unknown; issues: GristSafeParseIssue[] } {\n const issues: GristSafeParseIssue[] = []\n if (decoded && typeof decoded === \"object\" && \"__error\" in decoded) {\n issues.push({\n code: \"grist_error\",\n message: (decoded as { message?: string }).message ?? \"Grist returned a cell error.\",\n })\n return { value: null, issues }\n }\n\n switch (kind) {\n case \"ref\":\n return normalizeRefValue(decoded, helperValue, refMode)\n case \"refList\":\n return normalizeRefListValue(decoded, helperValue, refMode)\n case \"date\":\n case \"datetime\":\n if (decoded === null || decoded instanceof Date) return { value: decoded, issues }\n issues.push({ code: \"type_mismatch\", message: \"Expected a Date value.\" })\n return { value: null, issues }\n case \"bool\":\n if (decoded === null || typeof decoded === \"boolean\") return { value: decoded, issues }\n issues.push({ code: \"type_mismatch\", message: \"Expected a boolean value.\" })\n return { value: null, issues }\n case \"numeric\":\n if (decoded === null || (typeof decoded === \"number\" && Number.isFinite(decoded))) {\n return { value: decoded, issues }\n }\n issues.push({ code: \"type_mismatch\", message: \"Expected a numeric value.\" })\n return {\n value:\n typeof decoded === \"string\" ||\n typeof decoded === \"number\" ||\n typeof decoded === \"boolean\"\n ? decoded\n : null,\n issues,\n }\n case \"int\":\n if (decoded === null || (typeof decoded === \"number\" && Number.isInteger(decoded))) {\n return { value: decoded, issues }\n }\n issues.push({ code: \"type_mismatch\", message: \"Expected an integer value.\" })\n return {\n value:\n typeof decoded === \"string\" ||\n typeof decoded === \"number\" ||\n typeof decoded === \"boolean\"\n ? decoded\n : null,\n issues,\n }\n case \"choice\":\n case \"text\":\n if (decoded === null || typeof decoded === \"string\") return { value: decoded, issues }\n issues.push({ code: \"type_mismatch\", message: \"Expected a string value.\" })\n return { value: null, issues }\n case \"choiceList\":\n case \"attachments\":\n if (decoded === null || Array.isArray(decoded)) return { value: decoded, issues }\n issues.push({ code: \"type_mismatch\", message: \"Expected a list value.\" })\n return { value: null, issues }\n case \"any\":\n case \"unknown\":\n // Heuristic fallback: when schema typing is missing but a helper column is\n // attached, infer Ref/RefList from the decoded shape.\n if (helperValue !== undefined) {\n if (typeof decoded === \"number\" || (decoded && typeof decoded === \"object\" && \"__ref\" in decoded)) {\n return normalizeRefValue(decoded, helperValue, refMode)\n }\n if (Array.isArray(decoded)) {\n return normalizeRefListValue(decoded, helperValue, refMode)\n }\n }\n if (!fallbackUntypedToString) return { value: decoded, issues }\n if (decoded === null) return { value: null, issues }\n if (typeof decoded === \"string\") return { value: decoded, issues }\n if (\n typeof decoded === \"number\" ||\n typeof decoded === \"boolean\" ||\n decoded instanceof Date\n ) {\n return {\n value: decoded instanceof Date ? decoded.toISOString() : String(decoded),\n issues,\n }\n }\n if (Array.isArray(decoded)) {\n try {\n return { value: JSON.stringify(decoded), issues }\n } catch {\n issues.push({\n code: \"invalid_format\",\n message: \"Unable to stringify list value.\",\n })\n return { value: null, issues }\n }\n }\n issues.push({\n code: \"type_mismatch\",\n message: \"Untyped value could not be represented as a string.\",\n })\n return { value: null, issues }\n }\n}\n\nfunction buildChoiceTokens(\n col: GristReplicaColumn | undefined,\n value: unknown\n): GristSafeChoiceTokenMeta[] | undefined {\n const type = col?.type\n if (type !== \"Choice\" && type !== \"ChoiceList\") return undefined\n const entries = normalizeGristChoiceListEntries(col?.widgetOptions)\n const byValue = new Map<string, GristChoiceListEntry>(entries.map((entry) => [entry.value, entry]))\n\n if (type === \"Choice\") {\n if (value == null || typeof value !== \"string\" || value.trim() === \"\") return []\n const meta = byValue.get(value)\n if (!meta) return [{ value, label: value, valid: false }]\n return [\n {\n value,\n label: meta.label,\n fillColor: meta.fillColor,\n textColor: meta.textColor,\n valid: true,\n },\n ]\n }\n\n if (!Array.isArray(value)) return []\n const out: GristSafeChoiceTokenMeta[] = []\n for (const item of value) {\n const v = typeof item === \"string\" ? item : String(item)\n const meta = byValue.get(v)\n if (!meta) {\n out.push({ value: v, label: v, valid: false })\n continue\n }\n out.push({\n value: v,\n label: meta.label,\n fillColor: meta.fillColor,\n textColor: meta.textColor,\n valid: true,\n })\n }\n return out\n}\n\nexport function safeParseGristValues<TValue = unknown>(\n options: SafeParseGristValuesOptions<TValue>\n): GristSafeParseCellResult<TValue>[] {\n const fallbackUntypedToString = options.fallbackUntypedToString ?? true\n const refMode = options.refMode ?? \"id\"\n const kind = columnKind(options.column)\n return options.values.map((raw, index) => {\n const decoded = decodeGristValue(raw, options.column)\n const helperValue = options.helperValues?.[index]\n const normalized = normalizeByColumnKind(\n decoded,\n kind,\n helperValue,\n fallbackUntypedToString,\n refMode\n )\n const issues = [...normalized.issues]\n\n if (options.schema) {\n const result = options.schema.safeParse(normalized.value)\n if (!result.success) {\n issues.push({\n code: \"zod_error\",\n message: result.error.issues.map((issue) => issue.message).join(\"; \"),\n })\n }\n }\n\n return {\n ok: issues.length === 0,\n typedValue: normalized.value as TValue | null,\n displayValue: normalized.value,\n raw,\n issues,\n }\n })\n}\n\nexport function safeParseGristTableData<TRow extends Record<string, unknown> = Record<string, unknown>>(\n data: GristColumnarTable,\n options?: SafeParseGristTableDataOptions\n): SafeParseGristTableDataResult<TRow> {\n const columns = options?.columns ?? {}\n const inferredDisplayHelpersByRef = inferDisplayHelpersByRef(columns)\n const displayHelpersByRef: Record<string, string> = {\n ...inferredDisplayHelpersByRef,\n ...(options?.displayHelpersByRef ?? {}),\n }\n // Fallback convention: if `owner` exists and `gristHelper_owner` is fetched,\n // use it as display helper even when formula metadata is unavailable.\n for (const [colId, col] of Object.entries(columns)) {\n const type = col?.type\n if (typeof type !== \"string\" || (!type.startsWith(\"Ref:\") && !type.startsWith(\"RefList:\"))) {\n continue\n }\n if (displayHelpersByRef[colId]) continue\n const byName = `gristHelper_${colId}`\n if (Array.isArray(data[byName])) {\n displayHelpersByRef[colId] = byName\n }\n }\n const fallbackUntypedToString = options?.fallbackUntypedToString ?? true\n const refMode = options?.refMode ?? \"id\"\n const colIds = Object.keys(data)\n const parsedByColumn: Record<string, GristSafeParseCellResult[]> = {}\n\n for (const colId of colIds) {\n const rawValues = Array.isArray(data[colId]) ? data[colId] : []\n const helperColId = displayHelpersByRef[colId]\n const helperValues = helperColId && Array.isArray(data[helperColId]) ? data[helperColId] : undefined\n parsedByColumn[colId] =\n colId === \"id\"\n ? rawValues.map((raw) => ({\n ok: typeof raw === \"number\" && Number.isFinite(raw),\n typedValue: typeof raw === \"number\" && Number.isFinite(raw) ? raw : null,\n displayValue: raw,\n raw,\n issues:\n typeof raw === \"number\" && Number.isFinite(raw)\n ? []\n : [{ code: \"type_mismatch\", message: \"Row id should be numeric.\" }],\n }))\n : safeParseGristValues({\n values: rawValues,\n column: columns[colId],\n helperValues,\n fallbackUntypedToString,\n refMode,\n })\n }\n\n const rowCount = computeRowCount(data)\n const rows: GristRowRecord<TRow>[] = []\n const cellIssues: GristSafeTableCellIssue[] = []\n const cellMeta: GristSafeTableCellMeta[] = []\n for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {\n const row: Record<string, unknown> = {}\n for (const colId of colIds) {\n const parsed = parsedByColumn[colId]?.[rowIndex]\n row[colId] = parsed?.typedValue ?? null\n const choiceTokens = buildChoiceTokens(columns[colId], parsed?.displayValue)\n if (parsed) {\n if (parsed.issues.length > 0 || (choiceTokens && choiceTokens.length > 0)) {\n cellMeta.push({\n rowIndex,\n colId,\n ok: parsed.ok,\n issues: parsed.issues,\n choiceTokens,\n })\n }\n }\n if (!parsed || parsed.issues.length === 0) continue\n for (const issue of parsed.issues) {\n cellIssues.push({ ...issue, rowIndex, colId })\n }\n }\n rows.push(row as GristRowRecord<TRow>)\n }\n\n const cellMetaByKey: Record<string, GristSafeTableCellMeta> = {}\n for (const meta of cellMeta) {\n const rowId = rows[meta.rowIndex]?.id\n if (typeof rowId !== \"number\") continue\n cellMetaByKey[`${rowId}:${meta.colId}`] = meta\n }\n\n const order = options?.order ?? \"grist\"\n if (order === \"none\") {\n return { rows, cellIssues, cellMeta, cellMetaByKey, cellResultsByColumn: parsedByColumn }\n }\n if (order === \"id\") {\n return {\n rows: [...rows].sort((a, b) => {\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n }),\n cellIssues,\n cellMeta,\n cellMetaByKey,\n cellResultsByColumn: parsedByColumn,\n }\n }\n return {\n rows: sortRowsByGristOrder(rows),\n cellIssues,\n cellMeta,\n cellMetaByKey,\n cellResultsByColumn: parsedByColumn,\n }\n}\n","/**\n * Grist stores column widget configuration in `_grist_Tables_column.widgetOptions`\n * as a JSON string. Choice fields use `choices: string[]` plus optional\n * `choiceOptions: Record<string, Style>` (e.g. `fillColor`, `textColor`).\n *\n * @see https://github.com/gristlabs/grist-core/blob/main/app/client/widgets/ChoiceEditor.js\n */\n\n/** One selectable choice for UI (value stored in the cell is `value`). */\nexport type GristChoiceListEntry = {\n value: string\n label: string\n fillColor?: string\n textColor?: string\n}\n\n/**\n * Parse a cell value from `_grist_Tables_column.widgetOptions` into a plain object.\n */\nexport function parseGristWidgetOptionsCell(raw: unknown): Record<string, unknown> | undefined {\n if (raw == null || raw === \"\") return undefined\n if (typeof raw === \"string\") {\n try {\n const parsed: unknown = JSON.parse(raw)\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>\n }\n } catch {\n return undefined\n }\n return undefined\n }\n if (typeof raw === \"object\" && !Array.isArray(raw)) {\n return raw as Record<string, unknown>\n }\n return undefined\n}\n\nfunction readStyleColor(style: Record<string, unknown>, key: string): string | undefined {\n const v = style[key]\n return typeof v === \"string\" ? v : undefined\n}\n\n/**\n * Normalizes Grist Choice / ChoiceList widgetOptions into a flat list for dropdowns.\n * `choices` entries are string labels (the stored cell value). Per-choice styling\n * lives in `choiceOptions[label]`.\n */\nexport function normalizeGristChoiceListEntries(\n widgetOptions: Record<string, unknown> | undefined\n): GristChoiceListEntry[] {\n if (!widgetOptions) return []\n const rawChoices = widgetOptions.choices\n if (!Array.isArray(rawChoices)) return []\n\n const choiceOptionsRaw = widgetOptions.choiceOptions\n const choiceOptions: Record<string, Record<string, unknown>> =\n choiceOptionsRaw &&\n typeof choiceOptionsRaw === \"object\" &&\n !Array.isArray(choiceOptionsRaw)\n ? (choiceOptionsRaw as Record<string, Record<string, unknown>>)\n : {}\n\n const out: GristChoiceListEntry[] = []\n for (const c of rawChoices) {\n const value = typeof c === \"string\" ? c : c != null ? String(c) : \"\"\n if (!value) continue\n const style = choiceOptions[value] ?? {}\n out.push({\n value,\n label: value,\n fillColor: readStyleColor(style, \"fillColor\"),\n textColor: readStyleColor(style, \"textColor\"),\n })\n }\n return out\n}\n","import type { GristDocApi, GristReplicaColumn, GristRowRecord } from \"../types\"\nimport { decodeGristValue } from \"./grist-value-codec\"\nimport {\n type GristSafeParseCellResult,\n type GristSafeTableCellMeta,\n safeParseGristTableData,\n type GristSafeTableCellIssue,\n type SafeParseGristTableDataOptions,\n} from \"./grist-safe-parse\"\n\n/**\n * Column-oriented table payload from `grist.docApi.fetchTable`.\n */\nexport type GristColumnarTable = Record<string, unknown[]>\nexport type GristTableRowsOrder = \"none\" | \"id\" | \"grist\"\nexport type FetchGristTableRowsOptions = {\n /** Optional schema metadata map to decode cells (except `id`) with `decodeGristValue`. */\n columns?: Record<string, GristReplicaColumn>\n /**\n * Row ordering strategy.\n * - `grist` (default): `manualSort` ascending when present, fallback `id`.\n * - `id`: numeric `id` ascending.\n * - `none`: preserve raw `fetchTable` row order.\n */\n order?: GristTableRowsOrder\n /**\n * Enable safe parsing with issue reporting.\n * - `true`: use safe parsing with defaults.\n * - object: pass safe-parse options (`displayHelpersByRef`, `refMode`, ...).\n */\n safeParse?: boolean | Omit<SafeParseGristTableDataOptions, \"columns\" | \"order\">\n /** Optional callback fired with per-cell parse issues when `safeParse` is enabled. */\n onSafeParseIssues?: (issues: GristSafeTableCellIssue[]) => void\n /** Optional callback fired with enriched per-cell safe-parse metadata. */\n onSafeParseCellMeta?: (meta: GristSafeTableCellMeta[]) => void\n /** Optional callback fired with keyed per-cell metadata (`${rowId}:${colId}`). */\n onSafeParseCellMetaByKey?: (metaByKey: Record<string, GristSafeTableCellMeta>) => void\n}\n\nfunction inferDisplayHelpersByNameFromData(data: GristColumnarTable): Record<string, string> {\n const out: Record<string, string> = {}\n for (const colId of Object.keys(data)) {\n if (!colId.startsWith(\"gristHelper_\")) continue\n const baseColId = colId.slice(\"gristHelper_\".length)\n if (!baseColId) continue\n if (!Array.isArray(data[baseColId])) continue\n out[baseColId] = colId\n }\n return out\n}\n\nfunction enrichSafeParseColumnsFromData(\n data: GristColumnarTable,\n columns?: Record<string, GristReplicaColumn>\n): Record<string, GristReplicaColumn> {\n const out: Record<string, GristReplicaColumn> = { ...(columns ?? {}) }\n const keys = Object.keys(data)\n const positionByColId = new Map<string, number>(keys.map((colId, index) => [colId, index + 1]))\n\n // Ensure helper columns exist in safe-parse metadata even when caller schema\n // excluded them (common for UI schemas). Parent positions are synthesized from\n // fetchTable key order so helper/ref fallback matching still works.\n for (const colId of keys) {\n if (!colId.startsWith(\"gristHelper_\")) continue\n if (out[colId]) continue\n out[colId] = {\n type: \"Any\",\n label: colId,\n parentPos: positionByColId.get(colId),\n }\n }\n return out\n}\n\nfunction rowsFromSafeCellResults(\n parsedByColumn: Record<string, GristSafeParseCellResult[]>\n): GristRowRecord<Record<string, unknown>>[] {\n const colIds = Object.keys(parsedByColumn)\n const rowCount = colIds.reduce((max, colId) => {\n const len = parsedByColumn[colId]?.length ?? 0\n return Math.max(max, len)\n }, 0)\n const rows: GristRowRecord<Record<string, unknown>>[] = []\n for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {\n const row: Record<string, unknown> = {}\n for (const colId of colIds) {\n row[colId] = parsedByColumn[colId]?.[rowIndex] ?? null\n }\n rows.push(row as GristRowRecord<Record<string, unknown>>)\n }\n return rows\n}\n\nfunction safeCellRowId(row: Record<string, unknown>): number | null {\n const idCell = row.id\n if (!idCell || typeof idCell !== \"object\" || !(\"typedValue\" in idCell)) return null\n const typed = (idCell as { typedValue?: unknown }).typedValue\n return typeof typed === \"number\" && Number.isFinite(typed) ? typed : null\n}\n\nfunction orderSafeCellRowsByParsedRows(\n rows: GristRowRecord<Record<string, unknown>>[],\n orderedParsedRows: ReadonlyArray<Record<string, unknown>>\n): GristRowRecord<Record<string, unknown>>[] {\n const byId = new Map<number, GristRowRecord<Record<string, unknown>>[]>()\n for (const row of rows) {\n const id = safeCellRowId(row)\n if (id === null) continue\n const bucket = byId.get(id)\n if (bucket) bucket.push(row)\n else byId.set(id, [row])\n }\n const out: GristRowRecord<Record<string, unknown>>[] = []\n for (const parsedRow of orderedParsedRows) {\n const id = typeof parsedRow.id === \"number\" ? parsedRow.id : null\n if (id === null) continue\n const bucket = byId.get(id)\n if (!bucket || bucket.length === 0) continue\n const next = bucket.shift()\n if (next) out.push(next)\n }\n // Preserve any unexpected leftovers (defensive).\n for (const bucket of byId.values()) {\n out.push(...bucket)\n }\n return out\n}\n\n/**\n * Project safe-parse rows to UI display rows by taking each cell's `displayValue`.\n * Useful for grids that render human-friendly values while keeping safe-cell\n * objects available for logic and metadata.\n */\nexport function safeParseRowsToDisplayRows(\n rows: ReadonlyArray<Record<string, unknown>>\n): GristRowRecord<Record<string, unknown>>[] {\n return rows.map((row) => {\n const out: Record<string, unknown> = {}\n for (const [colId, cell] of Object.entries(row)) {\n if (cell && typeof cell === \"object\" && \"displayValue\" in cell) {\n out[colId] = (cell as { displayValue: unknown }).displayValue\n } else {\n out[colId] = cell\n }\n }\n return out as GristRowRecord<Record<string, unknown>>\n })\n}\n\n/** Row count from columnar `fetchTable` data (prefers `id` column length). */\nexport function computeRowCount(data: Record<string, unknown[]>): number {\n const idCol = data.id\n if (Array.isArray(idCol)) return idCol.length\n for (const key of Object.keys(data)) {\n const col = data[key]\n if (Array.isArray(col)) return col.length\n }\n return 0\n}\n\n/**\n * Decode columnar `fetchTable` into replica row objects (same convention as the playground grid).\n */\nexport function decodeColumnarToReplicaRows(\n data: GristColumnarTable,\n columnIds: string[],\n columns: Record<string, GristReplicaColumn>,\n maxRows?: number\n): GristRowRecord[] {\n const nFull = computeRowCount(data)\n const n = maxRows !== undefined ? Math.min(nFull, maxRows) : nFull\n const out: GristRowRecord[] = []\n for (let i = 0; i < n; i++) {\n const row: Record<string, unknown> = {}\n for (const k of columnIds) {\n const arr = data[k]\n const raw = Array.isArray(arr) ? arr[i] : undefined\n if (k === \"id\") {\n row[k] = raw\n } else {\n row[k] = decodeGristValue(raw, columns[k]) as unknown\n }\n }\n out.push(row as GristRowRecord)\n }\n return out\n}\n\n/** Turn `fetchTable` output into row objects (order follows the `id` column). */\nexport function tableDataToRows<T = Record<string, unknown>>(\n data: GristColumnarTable\n): GristRowRecord<T>[] {\n const idCol = data.id\n if (!Array.isArray(idCol) || idCol.length === 0) return []\n const keys = Object.keys(data)\n const n = idCol.length\n const rows: GristRowRecord<T>[] = []\n for (let i = 0; i < n; i++) {\n const row: Record<string, unknown> = {}\n for (const k of keys) {\n const col = data[k]\n row[k] = Array.isArray(col) ? col[i] : undefined\n }\n rows.push(row as GristRowRecord<T>)\n }\n return rows\n}\n\nfunction manualSortKey(row: Record<string, unknown>): number | null {\n const v = row.manualSort\n if (typeof v === \"number\" && !Number.isNaN(v)) return v\n if (typeof v === \"string\" && v.trim() !== \"\") {\n const n = Number(v)\n if (!Number.isNaN(n)) return n\n }\n return null\n}\n\n/**\n * Sort rows by Grist's display order: `manualSort` ascending when present on\n * any row, otherwise numeric `id` ascending.\n */\nexport function sortRowsByGristOrder<T = Record<string, unknown>>(\n rows: readonly GristRowRecord<T>[]\n): GristRowRecord<T>[] {\n const hasManual = rows.some((r) => manualSortKey(r as Record<string, unknown>) !== null)\n if (!hasManual) {\n return [...rows].sort((a, b) => {\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n })\n }\n return [...rows].sort((a, b) => {\n const ma = manualSortKey(a as Record<string, unknown>)\n const mb = manualSortKey(b as Record<string, unknown>)\n if (ma !== null && mb !== null && ma !== mb) return ma - mb\n if (ma !== null && mb === null) return -1\n if (ma === null && mb !== null) return 1\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n })\n}\n\n/** Row index where `id` matches `rowId`, or `null`. */\nexport function findRowIndexById(data: GristColumnarTable, rowId: number | string): number | null {\n const idCol = data.id\n if (!Array.isArray(idCol)) return null\n const idx = idCol.findIndex((v) => v === rowId || (typeof v === \"number\" && v === Number(rowId)))\n return idx === -1 ? null : idx\n}\n\n/** Single row at `index`, or `null` if out of range. */\nexport function rowAtIndex<T = Record<string, unknown>>(\n data: GristColumnarTable,\n index: number\n): GristRowRecord<T> | null {\n const idCol = data.id\n if (!Array.isArray(idCol) || index < 0 || index >= idCol.length) return null\n const keys = Object.keys(data)\n const row: Record<string, unknown> = {}\n for (const k of keys) {\n const col = data[k]\n row[k] = Array.isArray(col) ? col[index] : undefined\n }\n return row as GristRowRecord<T>\n}\n\n/**\n * Fetch a single row from any table by id. Convenience around\n * `docApi.fetchTable` + {@link findRowIndexById} + {@link rowAtIndex}.\n */\nexport async function fetchGristRow<T = Record<string, unknown>>(\n docApi: GristDocApi,\n tableId: string,\n rowId: number\n): Promise<GristRowRecord<T> | null> {\n const data = (await docApi.fetchTable(tableId)) as GristColumnarTable\n const index = findRowIndexById(data, rowId)\n if (index === null) return null\n return rowAtIndex<T>(data, index)\n}\n\n/**\n * Same row materialization as {@link fetchGristTableRows} after `fetchTable`\n * returns columnar data. Hosts that already have columnar data (e.g. the\n * emulator building from in-memory rows) can use this and skip `docApi.fetchTable`.\n */\nexport function materializeGristRowsFromColumnar<T extends Record<string, unknown> = Record<string, unknown>>(\n data: GristColumnarTable,\n options?: FetchGristTableRowsOptions\n): GristRowRecord<T>[] {\n const order = options?.order ?? \"grist\"\n if (options?.safeParse) {\n const safeOptions = options.safeParse === true ? {} : options.safeParse\n const columnsForSafeParse = enrichSafeParseColumnsFromData(data, options?.columns)\n const displayHelpersByRef = {\n ...inferDisplayHelpersByNameFromData(data),\n ...(safeOptions.displayHelpersByRef ?? {}),\n }\n const parsed = safeParseGristTableData<T>(data, {\n ...safeOptions,\n columns: columnsForSafeParse,\n displayHelpersByRef,\n order,\n })\n options.onSafeParseIssues?.(parsed.cellIssues)\n options.onSafeParseCellMeta?.(parsed.cellMeta)\n options.onSafeParseCellMetaByKey?.(parsed.cellMetaByKey)\n const rawSafeRows = rowsFromSafeCellResults(parsed.cellResultsByColumn)\n const orderedSafeRows =\n order === \"none\"\n ? rawSafeRows\n : orderSafeCellRowsByParsedRows(rawSafeRows, parsed.rows as ReadonlyArray<Record<string, unknown>>)\n return orderedSafeRows as GristRowRecord<T>[]\n }\n\n let rows: GristRowRecord<T>[]\n if (options?.columns) {\n const columnIds = Object.keys(data)\n rows = decodeColumnarToReplicaRows(data, columnIds, options.columns) as GristRowRecord<T>[]\n } else {\n rows = tableDataToRows<T>(data)\n }\n\n if (order === \"none\") return rows\n if (order === \"id\") {\n return [...rows].sort((a, b) => {\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n })\n }\n return sortRowsByGristOrder(rows)\n}\n\n/**\n * Fetch a table and return rows as objects, optionally decoded from schema and sorted.\n */\nexport async function fetchGristTableRows<T extends Record<string, unknown> = Record<string, unknown>>(\n docApi: GristDocApi,\n tableId: string,\n options: FetchGristTableRowsOptions & { safeParse: true | Omit<SafeParseGristTableDataOptions, \"columns\" | \"order\"> }\n): Promise<GristRowRecord<{ [K in keyof T]: GristSafeParseCellResult<T[K]> | null }>[]>\nexport async function fetchGristTableRows<T extends Record<string, unknown> = Record<string, unknown>>(\n docApi: GristDocApi,\n tableId: string,\n options?: FetchGristTableRowsOptions\n): Promise<GristRowRecord<T>[]>\nexport async function fetchGristTableRows<T extends Record<string, unknown> = Record<string, unknown>>(\n docApi: GristDocApi,\n tableId: string,\n options?: FetchGristTableRowsOptions\n): Promise<GristRowRecord<T>[]> {\n const data = (await docApi.fetchTable(tableId)) as GristColumnarTable\n return materializeGristRowsFromColumnar<T>(data, options)\n}\n","/**\n * Grist `docApi.applyUserActions` payloads are arrays of user-action tuples.\n * @see https://support.getgrist.com/code/interfaces/grist_plugin_api.GristDocAPI/#applyuseractions\n */\n\nexport type GristUserActionTuple = unknown[]\n\n/** `[\"UpdateRecord\", tableId, rowId, { col: value, ... }]` */\nexport function gristUpdateRecordAction(\n tableId: string,\n rowId: number,\n patch: Record<string, unknown>\n): GristUserActionTuple {\n return [\"UpdateRecord\", tableId, rowId, patch]\n}\n\n/** `[\"AddRecord\", tableId, null, { col: value, ... }]` */\nexport function gristAddRecordAction(tableId: string, values: Record<string, unknown>): GristUserActionTuple {\n return [\"AddRecord\", tableId, null, values]\n}\n\n/** `[\"RemoveRecord\", tableId, rowId]` */\nexport function gristRemoveRecordAction(tableId: string, rowId: number): GristUserActionTuple {\n return [\"RemoveRecord\", tableId, rowId]\n}\n\n/** `[\"BulkUpdateRecord\", tableId, rowIds, { col: value[], ... }]` — column arrays must align with `rowIds`. */\nexport function gristBulkUpdateRecordAction(\n tableId: string,\n rowIds: number[],\n columnarPatch: Record<string, unknown[]>\n): GristUserActionTuple {\n return [\"BulkUpdateRecord\", tableId, rowIds, columnarPatch]\n}\n\n/**\n * `[\"BulkAddRecord\", tableId, rowIds | nullArray, { col: value[], ... }]`.\n * Pass `null` (or omit) for `rowIds` to let Grist allocate ids; in user-action\n * format Grist expects an array of nulls of the same length as the value arrays.\n */\nexport function gristBulkAddRecordAction(\n tableId: string,\n values: Record<string, unknown[]>,\n rowIds?: Array<number | null>\n): GristUserActionTuple {\n const length = inferBulkLength(values)\n const ids = rowIds ?? new Array<number | null>(length).fill(null)\n return [\"BulkAddRecord\", tableId, ids, values]\n}\n\n/** `[\"BulkRemoveRecord\", tableId, rowIds]` */\nexport function gristBulkRemoveRecordAction(tableId: string, rowIds: number[]): GristUserActionTuple {\n return [\"BulkRemoveRecord\", tableId, rowIds]\n}\n\n/** `[\"AddColumn\", tableId, colId, colInfo]` — `colInfo` shape depends on Grist version / column type. */\nexport function gristAddColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"AddVisibleColumn\", tableId, colId, colInfo]` — like `AddColumn` but also adds the column to the current view section. */\nexport function gristAddVisibleColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddVisibleColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"RenameColumn\", tableId, colId, newColId]` */\nexport function gristRenameColumnAction(tableId: string, colId: string, newColId: string): GristUserActionTuple {\n return [\"RenameColumn\", tableId, colId, newColId]\n}\n\n/** `[\"ModifyColumn\", tableId, colId, colInfo]` */\nexport function gristModifyColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"ModifyColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"RemoveColumn\", tableId, colId]` */\nexport function gristRemoveColumnAction(tableId: string, colId: string): GristUserActionTuple {\n return [\"RemoveColumn\", tableId, colId]\n}\n\n/** `[\"AddTable\", tableId, tableInfo]` */\nexport function gristAddTableAction(tableId: string, tableInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddTable\", tableId, tableInfo]\n}\n\n/** `[\"RenameTable\", tableId, newTableId]` */\nexport function gristRenameTableAction(tableId: string, newTableId: string): GristUserActionTuple {\n return [\"RenameTable\", tableId, newTableId]\n}\n\n/** `[\"RemoveTable\", tableId]` */\nexport function gristRemoveTableAction(tableId: string): GristUserActionTuple {\n return [\"RemoveTable\", tableId]\n}\n\n/** `[\"DuplicateTable\", tableId, newTableId, options?]` */\nexport function gristDuplicateTableAction(\n tableId: string,\n newTableId: string,\n options?: Record<string, unknown>\n): GristUserActionTuple {\n return options ? [\"DuplicateTable\", tableId, newTableId, options] : [\"DuplicateTable\", tableId, newTableId]\n}\n\n/** `[\"ReplaceTableData\", tableId, rowIds, columnarData]` */\nexport function gristReplaceTableDataAction(\n tableId: string,\n rowIds: Array<number | null>,\n columnarData: Record<string, unknown[]>\n): GristUserActionTuple {\n return [\"ReplaceTableData\", tableId, rowIds, columnarData]\n}\n\n/** `[\"SetDocumentInfo\", info]` */\nexport function gristSetDocumentInfoAction(info: Record<string, unknown>): GristUserActionTuple {\n return [\"SetDocumentInfo\", info]\n}\n\nfunction inferBulkLength(values: Record<string, unknown[]>): number {\n for (const arr of Object.values(values)) if (Array.isArray(arr)) return arr.length\n return 0\n}\n","export type GristColumnLike = {\n formula?: string\n}\n\nexport type GristNoiseColumnsOptions = {\n excludeId?: boolean\n excludeGristHelpers?: boolean\n excludeLoggingColumns?: boolean\n /**\n * When `true`, treat Grist's `manualSort` column as noise (omit from filtered replicas).\n * Default `false` — `manualSort` is kept unless you opt in.\n */\n excludeManualSort?: boolean\n}\n\nconst NOISE_COLUMN_FORMULAS = new Set([\"now()\"])\n\nfunction normalizeFormulaForComparison(formula: string): string {\n return formula.trim().toLowerCase().replace(/\\s+/g, \"\")\n}\n\n/**\n * Grist-centric \"technical column\" detection used by document hooks and widgets.\n *\n * - `id` (when {@link GristNoiseColumnsOptions.excludeId} is true — default)\n * - `manualSort` (only when {@link GristNoiseColumnsOptions.excludeManualSort} is true)\n * - `gristHelper_*` (when `excludeGristHelpers` is true — default)\n * - trigger/logging formulas (`NOW()`, `user.*`) (when `excludeLoggingColumns` is true — default)\n */\nexport function isGristNoiseColumn(\n colId: string,\n col?: GristColumnLike,\n options?: GristNoiseColumnsOptions\n): boolean {\n const excludeId = options?.excludeId ?? true\n const excludeGristHelpers = options?.excludeGristHelpers ?? true\n const excludeLoggingColumns = options?.excludeLoggingColumns ?? true\n const excludeManualSort = options?.excludeManualSort ?? false\n\n if (excludeId && colId === \"id\") return true\n if (excludeManualSort && colId === \"manualSort\") return true\n if (excludeGristHelpers && colId.startsWith(\"gristHelper_\")) return true\n\n if (excludeLoggingColumns) {\n const formula = typeof col?.formula === \"string\" ? normalizeFormulaForComparison(col.formula) : \"\"\n if (formula && NOISE_COLUMN_FORMULAS.has(formula)) return true\n if (formula.startsWith(\"user.\")) return true\n }\n\n return false\n}\n","import type { GristFormulaKind, GristReplicaColumn } from \"../types\"\n\nexport function inferGristFormulaKind(isFormula: boolean, formulaTrimmed: string): GristFormulaKind {\n if (formulaTrimmed.length > 0) return isFormula ? \"computed\" : \"trigger\"\n return isFormula ? \"empty_slot\" : \"none\"\n}\n\n/** Use when `formulaKind` may be missing (e.g. older document builds). */\nexport function resolveGristFormulaKind(col: GristReplicaColumn): GristFormulaKind {\n if (col.formulaKind) return col.formulaKind\n const f = col.formula?.trim() ?? \"\"\n if (f.length > 0) return col.isFormula === true ? \"computed\" : \"trigger\"\n return col.isFormula === true ? \"empty_slot\" : \"none\"\n}\n\n/** Serialize cell values for JSON output. */\nexport function serializeJsonFriendly(value: unknown): unknown {\n if (value === null || value === undefined) return null\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") return value\n try {\n return JSON.parse(JSON.stringify(value)) as unknown\n } catch {\n return String(value)\n }\n}\n","import type {\n GristDocApi,\n GristDocumentMode,\n GristReplicaColumn,\n GristReplicaDocument,\n GristReplicaTable,\n} from \"../types\"\nimport { computeRowCount, decodeColumnarToReplicaRows, type GristColumnarTable } from \"./grist-table-data\"\nimport { inferGristFormulaKind } from \"./grist-schema-formula\"\nimport { parseGristWidgetOptionsCell } from \"./grist-widget-options\"\nimport { coerceGristDocApiRefRowId } from \"./grist-value-codec\"\n\nexport type ReplicaTableColumnMetaLite = {\n colRef?: number\n type?: string\n label?: string\n parentPos?: number\n isFormula?: boolean\n formula?: string\n description?: string\n widgetOptions?: Record<string, unknown>\n displayColRef?: number\n visibleColRef?: number\n}\n\nconst FORMULA_PREVIEW_MAX = 500\n\nfunction readCellStr(table: Record<string, unknown[]>, key: string, rowIndex: number): string | undefined {\n const col = table[key]\n if (!Array.isArray(col)) return undefined\n const v = col[rowIndex]\n if (v === null || v === undefined) return undefined\n if (typeof v === \"string\") return v\n if (typeof v === \"number\" || typeof v === \"boolean\") return String(v)\n return undefined\n}\n\nfunction readCellNum(table: Record<string, unknown[]>, key: string, rowIndex: number): number | undefined {\n const col = table[key]\n if (!Array.isArray(col)) return undefined\n const v = col[rowIndex]\n if (typeof v === \"number\" && !Number.isNaN(v)) return v\n if (typeof v === \"string\" && v.trim() !== \"\") {\n const n = Number(v)\n if (!Number.isNaN(n)) return n\n }\n return undefined\n}\n\nfunction pickColumnMeta(meta: ReplicaTableColumnMetaLite | undefined): GristReplicaColumn {\n if (!meta) return {}\n const out: GristReplicaColumn = {}\n if (meta.colRef !== undefined) out.colRef = meta.colRef\n if (meta.type) out.type = meta.type\n if (meta.label) out.label = meta.label\n if (meta.parentPos !== undefined) out.parentPos = meta.parentPos\n if (meta.isFormula) out.isFormula = true\n const formulaRaw = meta.formula?.trim() ?? \"\"\n out.formulaKind = inferGristFormulaKind(Boolean(meta.isFormula), formulaRaw)\n if (formulaRaw) {\n out.formula =\n formulaRaw.length > FORMULA_PREVIEW_MAX ? `${formulaRaw.slice(0, FORMULA_PREVIEW_MAX)}...` : formulaRaw\n }\n if (meta.description) out.description = meta.description\n if (meta.widgetOptions && Object.keys(meta.widgetOptions).length > 0) {\n out.widgetOptions = meta.widgetOptions\n }\n if (meta.displayColRef !== undefined) out.displayColRef = meta.displayColRef\n if (meta.visibleColRef !== undefined) out.visibleColRef = meta.visibleColRef\n return out\n}\n\nexport async function loadColumnMetadataByTable(\n docApi: GristDocApi\n): Promise<Map<string, Map<string, ReplicaTableColumnMetaLite>>> {\n const byTable = new Map<string, Map<string, ReplicaTableColumnMetaLite>>()\n try {\n const tables = await docApi.fetchTable(\"_grist_Tables\")\n const columns = await docApi.fetchTable(\"_grist_Tables_column\")\n const tableIds = tables.tableId\n const tableInternalIds = tables.id\n if (!Array.isArray(tableIds) || !Array.isArray(tableInternalIds)) return byTable\n\n const internalIdToTableId = new Map<number, string>()\n for (let i = 0; i < tableInternalIds.length; i++) {\n const tid = tableIds[i]\n const iid = coerceGristDocApiRefRowId(tableInternalIds[i])\n if (typeof tid === \"string\" && iid !== undefined) internalIdToTableId.set(iid, tid)\n }\n\n const parentIds = columns.parentId\n const colIds = columns.colId\n const columnIds = columns.id\n if (\n !Array.isArray(parentIds) ||\n !Array.isArray(colIds) ||\n !Array.isArray(columnIds) ||\n parentIds.length !== colIds.length ||\n colIds.length !== columnIds.length\n ) {\n return byTable\n }\n\n const n = parentIds.length\n for (let i = 0; i < n; i++) {\n const parentRowId = coerceGristDocApiRefRowId(parentIds[i])\n const colRef = coerceGristDocApiRefRowId(columnIds[i])\n const colId = colIds[i]\n if (parentRowId === undefined || colRef === undefined || typeof colId !== \"string\") continue\n const tableId = internalIdToTableId.get(parentRowId)\n if (!tableId) continue\n\n let colMap = byTable.get(tableId)\n if (!colMap) {\n colMap = new Map()\n byTable.set(tableId, colMap)\n }\n\n const parentPos = readCellNum(columns, \"parentPos\", i)\n const isFormulaCol = columns.isFormula\n const isFormula = Array.isArray(isFormulaCol) ? Boolean(isFormulaCol[i]) : false\n\n const woCol = columns.widgetOptions\n const widgetOptions =\n Array.isArray(woCol) && i < woCol.length ? parseGristWidgetOptionsCell(woCol[i]) : undefined\n const displayColRef = coerceGristDocApiRefRowId(\n Array.isArray(columns.displayCol) ? columns.displayCol[i] : undefined\n )\n const visibleColRef = coerceGristDocApiRefRowId(\n Array.isArray(columns.visibleCol) ? columns.visibleCol[i] : undefined\n )\n\n colMap.set(colId, {\n colRef,\n type: readCellStr(columns, \"type\", i),\n label: readCellStr(columns, \"label\", i),\n parentPos: parentPos !== undefined ? parentPos : undefined,\n isFormula,\n formula: readCellStr(columns, \"formula\", i),\n description: readCellStr(columns, \"description\", i) ?? readCellStr(columns, \"descr\", i),\n widgetOptions,\n displayColRef,\n visibleColRef,\n })\n }\n } catch {\n // Metadata is best-effort; document build still works from cell data alone.\n }\n return byTable\n}\n\nexport function orderedColumnIds(\n data: Record<string, unknown[]>,\n metaByCol: Map<string, ReplicaTableColumnMetaLite>\n): string[] {\n const keys = Object.keys(data).filter((k) => Array.isArray(data[k]))\n keys.sort((a, b) => {\n const pa = metaByCol.get(a)?.parentPos\n const pb = metaByCol.get(b)?.parentPos\n if (pa !== undefined && pb !== undefined && pa !== pb) return pa - pb\n if (pa !== undefined && pb === undefined) return -1\n if (pa === undefined && pb !== undefined) return 1\n return a.localeCompare(b)\n })\n return keys\n}\n\n/** Build replica column metadata from columnar `fetchTable` + `_grist_Tables_column` maps. */\nexport function buildReplicaColumnsFromColumnar(\n data: Record<string, unknown[]>,\n colMeta: Map<string, ReplicaTableColumnMetaLite>\n): Record<string, GristReplicaColumn> {\n const columnIds = orderedColumnIds(data, colMeta)\n const columns: Record<string, GristReplicaColumn> = {}\n for (const colId of columnIds) {\n const arr = data[colId]\n if (!Array.isArray(arr)) continue\n const meta = colMeta.get(colId)\n columns[colId] = pickColumnMeta(meta)\n }\n return columns\n}\n\nfunction rowModeFromIncludeRows(includeRows: false | \"samples\" | \"full\"): GristDocumentMode {\n if (includeRows === false) return \"schema-only\"\n if (includeRows === \"samples\") return \"schema+samples\"\n return \"schema+data\"\n}\n\nexport type BuildReplicaDocumentFromDocApiOptions = {\n /** When false (default), skip fetching row data for `tableId` starting with `_grist`. */\n includeSystemTableData?: boolean\n /**\n * Row bodies: omit (`false`), first N (`samples`), or full decode (`full`).\n * Default `samples`.\n */\n includeRows?: false | \"samples\" | \"full\"\n /** Max rows per table when `includeRows` is `samples`. Default 10. */\n sampleRowLimit?: number\n /** Set on the replica as `source` for host logging / provenance. */\n source?: string\n}\n\n/**\n * Build {@link GristReplicaDocument} from a host `docApi`:\n * metadata from `_grist_Tables` / `_grist_Tables_column` when readable, plus optional decoded `rows`.\n *\n * Prefer {@link useGrist}'s `buildReplicaDocumentFromDocApi()` when you already use the primary hook.\n */\nexport async function buildReplicaDocumentFromDocApi(\n docApi: GristDocApi,\n options?: BuildReplicaDocumentFromDocApiOptions\n): Promise<GristReplicaDocument> {\n const includeSystemTableData = options?.includeSystemTableData ?? false\n const includeRows = options?.includeRows ?? \"samples\"\n const sampleRowLimit = options?.sampleRowLimit ?? 10\n const rowMode = rowModeFromIncludeRows(includeRows)\n\n const metaByTable = await loadColumnMetadataByTable(docApi)\n\n let docName: string | undefined\n try {\n docName = String(await Promise.resolve(docApi.getDocName()))\n } catch {\n docName = undefined\n }\n\n const tableIdsRaw = await Promise.resolve(docApi.listTables())\n const tableIds = Array.isArray(tableIdsRaw) ? [...tableIdsRaw] : []\n\n const tables: Record<string, GristReplicaTable> = {}\n\n for (const tableId of tableIds) {\n const omitData = !includeSystemTableData && tableId.startsWith(\"_grist\")\n if (omitData) {\n tables[tableId] = {\n rowCount: 0,\n dataOmitted: true,\n dataOmittedReason:\n \"Row scan skipped for tables whose id starts with `_grist` unless `includeSystemTableData` is true.\",\n columns: {},\n }\n continue\n }\n\n try {\n const data = (await docApi.fetchTable(tableId)) as GristColumnarTable\n const rowCount = computeRowCount(data)\n const colMeta = metaByTable.get(tableId) ?? new Map<string, ReplicaTableColumnMetaLite>()\n const columnIds = orderedColumnIds(data, colMeta)\n const columns = buildReplicaColumnsFromColumnar(data, colMeta)\n\n const table: GristReplicaTable = { columns, rowCount }\n if (includeRows === \"full\") {\n table.rows = decodeColumnarToReplicaRows(data, columnIds, columns)\n } else if (includeRows === \"samples\") {\n table.rows = decodeColumnarToReplicaRows(data, columnIds, columns, sampleRowLimit)\n }\n tables[tableId] = table\n } catch (err) {\n tables[tableId] = {\n rowCount: 0,\n error: err instanceof Error ? err.message : String(err),\n columns: {},\n }\n }\n }\n\n const out: GristReplicaDocument = {\n generatedAt: new Date().toISOString(),\n docName,\n mode: rowMode,\n tables,\n }\n if (options?.source !== undefined && options.source !== \"\") {\n out.source = options.source\n }\n return out\n}\n","import type { GristReplicaDocument, GristReplicaRow, GristReplicaTable } from \"../replica-document\"\n\n/**\n * Ensure `rows` is a concrete array for emulator / merge logic.\n * Call at host boundaries (`createDocument`, tests); JSON may still omit `rows` for schema-only.\n */\nexport function normalizeReplicaTableInput<T extends GristReplicaTable>(table: T): T & { rows: GristReplicaRow[] } {\n return { ...table, rows: table.rows ?? [] }\n}\n\n/** Apply {@link normalizeReplicaTableInput} to every table; shallow-copies the document shell. */\nexport function normalizeReplicaDocumentInput<T extends GristReplicaDocument>(doc: T): T {\n return {\n ...doc,\n tables: Object.fromEntries(\n Object.entries(doc.tables).map(([tableId, t]) => [tableId, normalizeReplicaTableInput(t)])\n ),\n } as T\n}\n\n/** How row arrays appear in serialized replica JSON from {@link buildReplicaJsonPayload}. */\nexport type ReplicaJsonIncludeRows = \"none\" | \"samples\" | \"full\"\n\n/**\n * Clone a replica document for JSON output: strip rows, cap to first N, or pass through.\n * Does not mutate the source document.\n */\nexport function buildReplicaJsonPayload(\n doc: GristReplicaDocument,\n options: { includeRows: ReplicaJsonIncludeRows; sampleRowLimit?: number }\n): GristReplicaDocument {\n const limit = options.sampleRowLimit ?? 10\n const tables = Object.fromEntries(\n Object.entries(doc.tables).map(([tid, t]) => {\n if (options.includeRows === \"none\") {\n const { rows: _r, ...rest } = t\n return [tid, rest]\n }\n if (options.includeRows === \"samples\") {\n const r = t.rows ?? []\n return [tid, { ...t, rows: r.slice(0, limit) }]\n }\n return [tid, { ...t, rows: t.rows }]\n })\n ) as GristReplicaDocument[\"tables\"]\n return { ...doc, tables }\n}\n","import type { GristColumnsToMap, GristColumnToMap, GristWidgetColumnMap } from \"../types\"\n\nexport type ValidateColumnMappingsResult = {\n ok: boolean\n /**\n * `true` while the host has not yet reported column mappings (e.g. between\n * `grist.ready()` resolving and the first `onRecord` / `onRecords` callback,\n * or before `sectionApi.mappings()` returns). Callers should not gate UI or\n * emit mapping alerts while pending.\n */\n pending?: boolean\n /** Logical names of required columns the user has not yet mapped. */\n missing: string[]\n /** Logical names of `allowMultiple` columns mapped to an empty list. */\n emptyMultiples: string[]\n}\n\n/**\n * Merges mapping payloads from `onRecord`, `onRecords`, and `sectionApi.mappings()`.\n * Later sources win; `undefined` sources are skipped; `null` means \"host reported\n * no mappings\" but still counts as a known (empty) payload.\n */\nexport function mergeWidgetColumnMaps(\n ...sources: (GristWidgetColumnMap | null | undefined)[]\n): GristWidgetColumnMap | null | undefined {\n let merged: GristWidgetColumnMap = {}\n let sawDefined = false\n for (const src of sources) {\n if (src === undefined) continue\n sawDefined = true\n if (src === null) continue\n merged = { ...merged, ...src }\n }\n if (!sawDefined) return undefined\n return merged\n}\n\nfunction asColumnSpec(entry: string | GristColumnToMap): GristColumnToMap {\n return typeof entry === \"string\" ? { name: entry } : entry\n}\n\n/**\n * Verifies that the current Grist mappings cover every required column declared\n * in `grist.ready({ columns })`.\n *\n * Use this before reading `mappedRecord` so you can render a \"please configure\n * the widget\" prompt instead of a confusing `null`.\n */\nexport function validateColumnMappings(\n spec: GristColumnsToMap | undefined | null,\n mappings: GristWidgetColumnMap | null | undefined\n): ValidateColumnMappingsResult {\n const missing: string[] = []\n const emptyMultiples: string[] = []\n if (!spec) return { ok: true, pending: false, missing, emptyMultiples }\n\n const m = mappings ?? {}\n for (const raw of spec) {\n const col = asColumnSpec(raw)\n if (col.optional) continue\n const value = m[col.name]\n if (col.allowMultiple) {\n if (value === undefined) {\n missing.push(col.name)\n } else if (!Array.isArray(value) || value.length === 0) {\n emptyMultiples.push(col.name)\n }\n } else {\n if (value === undefined || value === null || value === \"\") missing.push(col.name)\n }\n }\n return {\n ok: missing.length === 0 && emptyMultiples.length === 0,\n pending: false,\n missing,\n emptyMultiples,\n }\n}\n\n/** Status while waiting for the host to report mappings (see `pending`). */\nexport const pendingColumnMappingStatus: ValidateColumnMappingsResult = {\n ok: true,\n pending: true,\n missing: [],\n emptyMultiples: [],\n}\n","/**\n * Access-level helpers used by the handshake state machine.\n *\n * Kept in a tiny dedicated file because the same ranking is needed by the\n * reducer (`widened` flag, future re-negotiation logic) and potentially by\n * effects (decide whether to re-issue `grist.ready`).\n */\n\nimport type { GristRequiredAccess } from \"../../types\"\n\n/** Strictly-ordered ranking. Higher rank = stronger access. */\nexport const ACCESS_RANK: Record<GristRequiredAccess, number> = {\n none: 0,\n \"read table\": 1,\n full: 2,\n}\n\nconst GRIST_ACCESS_LEVELS: readonly GristRequiredAccess[] = [\"none\", \"read table\", \"full\"]\n\n/** Parse `interaction.access_level` / `accessLevel` from Grist `onOptions`. */\nexport function parseGristRequiredAccess(\n raw: string | undefined\n): GristRequiredAccess | null {\n if (!raw) return null\n return (GRIST_ACCESS_LEVELS as readonly string[]).includes(raw)\n ? (raw as GristRequiredAccess)\n : null\n}\n\n/** True when the host-granted level meets what the widget declared in `grist.ready`. */\nexport function isAccessSufficient(\n granted: GristRequiredAccess,\n required: GristRequiredAccess\n): boolean {\n return ACCESS_RANK[granted] >= ACCESS_RANK[required]\n}\n\n/** Creator-panel label for a Grist access level (for user-facing copy). */\nexport function gristAccessLevelLabel(level: GristRequiredAccess): string {\n switch (level) {\n case \"none\":\n return \"No document access\"\n case \"read table\":\n return \"Read selected table\"\n case \"full\":\n return \"Full document access\"\n }\n}\n\nexport function formatInsufficientAccessMessage(\n required: GristRequiredAccess,\n _granted: GristRequiredAccess\n): string {\n const need = gristAccessLevelLabel(required)\n return `Set Access level to at least \"${need}\" in the Custom widget settings.`\n}\n\nexport function isAccessWidening(\n previous: GristRequiredAccess | null,\n next: GristRequiredAccess\n): boolean {\n if (previous === null) return true\n return ACCESS_RANK[next] > ACCESS_RANK[previous]\n}\n","/**\n * Pure type contracts for the handshake / synchronization state machine.\n *\n * The machine models five orthogonal axes that together describe the widget's\n * relationship with the Grist host:\n *\n * 1. `LIFECYCLE` — protocol handshake (one-shot via `grist.ready`).\n * 2. `LINK` — RPC channel health (continuous, post-online).\n * 3. `AUTHZ` — effective access level granted by the host.\n * 4. `CONFIG` — column mapping contract with the end-user.\n * 5. `SYNC` — freshness of each event stream and ancillary RPCs.\n *\n * The legacy public `status` (\"booting\" / \"ready\" / \"unavailable\" / \"error\")\n * is a **pure projection** of the snapshot, computed in `./derive.ts`.\n *\n * No runtime side effects in this file — types only.\n */\n\nimport type { GristColumnsToMap, GristRequiredAccess, GristWidgetColumnMap } from \"../../types\"\n\n// ---------------------------------------------------------------------------\n// Branded primitives\n// ---------------------------------------------------------------------------\n\n/** Monotone counter bumped on reload / restart / link recovery / access widening. */\nexport type GristGeneration = number & { readonly __brand: \"GristGeneration\" }\n\nexport const ZERO_GENERATION = 0 as GristGeneration\n\nexport function nextGeneration(current: GristGeneration): GristGeneration {\n return (current + 1) as GristGeneration\n}\n\n// ---------------------------------------------------------------------------\n// 1. LIFECYCLE — handshake protocol\n// ---------------------------------------------------------------------------\n\nexport type GristLifecyclePhase =\n | \"idle\"\n | \"detecting\"\n | \"negotiating\"\n | \"online\"\n | \"terminated\"\n\nexport type GristTerminationReason =\n | { kind: \"script_timeout\"; attempts: number }\n | { kind: \"not_embedded\" }\n | { kind: \"ready_failed\"; message: string }\n | { kind: \"ready_timeout\"; afterMs: number }\n | { kind: \"host_rejected\"; message: string }\n | { kind: \"manual_terminate\" }\n\nexport type GristLifecycle =\n | { phase: \"idle\" }\n | { phase: \"detecting\"; attempts: number; startedAtMs: number }\n | { phase: \"negotiating\"; access: GristRequiredAccess; startedAtMs: number }\n | { phase: \"online\"; sinceMs: number; declaredAccess: GristRequiredAccess }\n | { phase: \"terminated\"; reason: GristTerminationReason; atMs: number }\n\n// ---------------------------------------------------------------------------\n// 2. LINK — RPC channel health\n// ---------------------------------------------------------------------------\n\nexport type GristLinkState = \"connected\" | \"stale\" | \"lost\"\n\nexport type GristLink = {\n state: GristLinkState\n /** ms timestamp of last successful RPC (or heartbeat). `null` before any. */\n lastSuccessMs: number | null\n /** Consecutive RPC failures since the last success. */\n missedPings: number\n}\n\n// ---------------------------------------------------------------------------\n// 3. AUTHZ — effective access\n// ---------------------------------------------------------------------------\n\nexport type GristAuthz =\n | { state: \"pending\"; declared: GristRequiredAccess }\n | {\n state: \"granted\"\n /** Effective level granted by the host. May differ from `declared`. */\n level: GristRequiredAccess\n declared: GristRequiredAccess\n /** True if granted level >= a previously granted level for the same widget. */\n widened: boolean\n }\n | { state: \"denied\"; declared: GristRequiredAccess; message?: string }\n\n// ---------------------------------------------------------------------------\n// 4. CONFIG — column-mapping contract\n// ---------------------------------------------------------------------------\n\n/**\n * Source that produced a mapping payload, used for deterministic merge by\n * {@link MappingResolver} (see `./mapping-resolver.ts`).\n */\nexport type GristMappingSource =\n | \"section_api\"\n | \"stream_record\"\n | \"stream_records\"\n | \"stream_new_record\"\n\n/**\n * Static priority order for mapping sources (lower index = higher priority).\n * `section_api` is the host's source-of-truth when available; stream payloads\n * are reactive fallbacks.\n */\nexport const MAPPING_SOURCE_PRIORITY: readonly GristMappingSource[] = [\n \"section_api\",\n \"stream_record\",\n \"stream_records\",\n \"stream_new_record\",\n] as const\n\nexport type GristMappingComplete = {\n state: \"complete\"\n declared: GristColumnsToMap\n mappings: GristWidgetColumnMap\n /** `\"merged\"` is used internally when multiple sources contributed. */\n source: GristMappingSource | \"merged\"\n reportedAtMs: number\n}\n\nexport type GristMappingIncomplete = {\n state: \"incomplete\"\n declared: GristColumnsToMap\n mappings: GristWidgetColumnMap\n missing: readonly string[]\n emptyMultiples: readonly string[]\n source: GristMappingSource | \"merged\"\n reportedAtMs: number\n}\n\nexport type GristMappingState =\n /** Widget did not declare any `columns` in `grist.ready`. */\n | { state: \"not_declared\" }\n /** Columns declared but no host report yet received. */\n | { state: \"pending\"; declared: GristColumnsToMap; declaredAtMs: number }\n | GristMappingIncomplete\n | GristMappingComplete\n /** User just modified the mapping; previous payload preserved to avoid UI flicker. */\n | {\n state: \"invalidating\"\n previous: GristMappingIncomplete | GristMappingComplete\n sinceMs: number\n }\n /** Declared but no host report after a timeout. Soft state — payload may still arrive. */\n | { state: \"unreported\"; declared: GristColumnsToMap; afterMs: number }\n\nexport type GristConfig = {\n mappings: GristMappingState\n}\n\n// ---------------------------------------------------------------------------\n// 5. SYNC — stream freshness\n// ---------------------------------------------------------------------------\n\nexport type GristStreamFreshness =\n | { state: \"cold\" }\n | { state: \"warming\"; sinceMs: number }\n | { state: \"hot\"; lastEventMs: number; generation: GristGeneration; payloadHash: string }\n | {\n state: \"stale\"\n lastEventMs: number\n reason: \"link_lost\" | \"tab_hidden\" | \"host_quiet\"\n }\n\nexport type GristCurrentTableState =\n | { state: \"unknown\" }\n | { state: \"known\"; tableId: string; refreshing: boolean }\n /** Local error (e.g. `selectedTable.getTableId()` rejected) — does NOT propagate to global status. */\n | { state: \"errored\"; message: string; sinceMs: number }\n\nexport type GristSync = {\n record: GristStreamFreshness\n records: GristStreamFreshness\n options: GristStreamFreshness\n newRecord: GristStreamFreshness\n currentTable: GristCurrentTableState\n}\n\n// ---------------------------------------------------------------------------\n// SNAPSHOT (aggregate)\n// ---------------------------------------------------------------------------\n\nexport type GristWidgetSnapshot = {\n generation: GristGeneration\n lifecycle: GristLifecycle\n link: GristLink\n authz: GristAuthz\n config: GristConfig\n sync: GristSync\n}\n\n// ---------------------------------------------------------------------------\n// PROJECTION — legacy 4-state status + capabilities\n// ---------------------------------------------------------------------------\n\n/** Mirrors the long-standing public type, kept for compat. */\nexport type GristWidgetStatus = \"booting\" | \"ready\" | \"unavailable\" | \"error\"\n\n/**\n * Pre-computed booleans that widget code should consume directly instead of\n * re-deriving from `status` + mapping flags + writes flags.\n *\n * Every field is a **pure function of the snapshot** and is referentially\n * stable across renders that don't change the snapshot's relevant slices.\n */\nexport type GristCapabilities = {\n /** `lifecycle.online` + `link != lost` + `authz.state === \"granted\"` with read or higher. */\n canRead: boolean\n /** `canRead` + (`mappings.state` is `complete` or `not_declared`). */\n canRender: boolean\n /** `canRender` + `authz.level === \"full\"`. Required before any write. */\n canWriteRecords: boolean\n /** `canWriteRecords` + `sync.currentTable.state === \"known\"`. */\n canWriteSchema: boolean\n /** `canRead` + `link === \"connected\"`. */\n canFetchTable: boolean\n /** `canRead` + `sync.record.state === \"hot\"` + mappings not invalidating. */\n hasFreshSelection: boolean\n /** `mappings.state === \"complete\" || \"not_declared\"`. */\n hasUsableMappings: boolean\n /** Logical column names still missing from user mapping (incomplete only). */\n missingMappings: readonly string[]\n /** `allowMultiple` columns mapped to `[]` (incomplete only). */\n emptyMultipleMappings: readonly string[]\n}\n\n// ---------------------------------------------------------------------------\n// Initial snapshot factory\n// ---------------------------------------------------------------------------\n\nexport function initialGristSnapshot(): GristWidgetSnapshot {\n return {\n generation: ZERO_GENERATION,\n lifecycle: { phase: \"idle\" },\n link: { state: \"connected\", lastSuccessMs: null, missedPings: 0 },\n authz: { state: \"pending\", declared: \"read table\" },\n config: { mappings: { state: \"not_declared\" } },\n sync: {\n record: { state: \"cold\" },\n records: { state: \"cold\" },\n options: { state: \"cold\" },\n newRecord: { state: \"cold\" },\n currentTable: { state: \"unknown\" },\n },\n }\n}\n","/**\n * Action union for the handshake state machine.\n *\n * Every action that can mutate the snapshot is listed here as a discriminated\n * union — exhaustiveness checks in the reducer rely on it.\n *\n * Actions either:\n * - target a single axis (e.g. `RPC_SUCCESS` → link), OR\n * - target multiple axes via a single transition (e.g. `NEGOTIATE_SUCCESS`\n * advances lifecycle AND authz at once).\n *\n * Generation-carrying actions can be **dropped** by the reducer if their\n * `generation` is older than the snapshot's current generation; this is the\n * primary defence against stale events arriving after a reload/restart.\n */\n\nimport type { GristColumnsToMap, GristRequiredAccess, GristWidgetColumnMap } from \"../../types\"\nimport type {\n GristGeneration,\n GristMappingSource,\n GristTerminationReason,\n} from \"./types\"\n\n// ---------------------------------------------------------------------------\n// Lifecycle actions\n// ---------------------------------------------------------------------------\n\nexport type GristLifecycleAction =\n | { type: \"DETECT_START\"; atMs: number }\n | { type: \"DETECT_TICK\"; attempts: number; atMs: number }\n | { type: \"DETECT_AVAILABLE\"; atMs: number }\n | { type: \"DETECT_TIMEOUT\"; attempts: number; atMs: number }\n | { type: \"NOT_EMBEDDED\"; atMs: number }\n | { type: \"NEGOTIATE_START\"; access: GristRequiredAccess; atMs: number }\n | {\n type: \"NEGOTIATE_SUCCESS\"\n access: GristRequiredAccess\n grantedLevel: GristRequiredAccess\n atMs: number\n }\n | { type: \"NEGOTIATE_FAIL\"; reason: GristTerminationReason; atMs: number }\n | { type: \"TERMINATE\"; reason: GristTerminationReason; atMs: number }\n\n// ---------------------------------------------------------------------------\n// Link actions\n// ---------------------------------------------------------------------------\n\nexport type GristLinkAction =\n | { type: \"RPC_SUCCESS\"; atMs: number }\n | { type: \"RPC_FAILURE\"; atMs: number; kind: \"timeout\" | \"rejected\" | \"other\" }\n | { type: \"HEARTBEAT_OK\"; atMs: number }\n | { type: \"HEARTBEAT_FAIL\"; atMs: number }\n\n// ---------------------------------------------------------------------------\n// Authz actions\n// ---------------------------------------------------------------------------\n\nexport type GristAuthzAction = {\n type: \"AUTHZ_REPORT\"\n /** Effective access level reported by Grist (`onOptions` / `interaction.access_level`). */\n level: GristRequiredAccess\n atMs: number\n generation: GristGeneration\n}\n\n// ---------------------------------------------------------------------------\n// Generation control\n// ---------------------------------------------------------------------------\n\nexport type GristGenerationAction = {\n type: \"BUMP_GENERATION\"\n atMs: number\n reason: \"reload\" | \"restart\" | \"link_recovery\" | \"widening\"\n}\n\n// ---------------------------------------------------------------------------\n// Config / mapping actions\n// ---------------------------------------------------------------------------\n\nexport type GristMappingAction =\n | {\n type: \"MAPPING_DECLARE\"\n declared: GristColumnsToMap\n atMs: number\n generation: GristGeneration\n }\n | {\n type: \"MAPPING_REPORT\"\n source: GristMappingSource\n payload: GristWidgetColumnMap | null\n atMs: number\n generation: GristGeneration\n }\n | { type: \"MAPPING_INVALIDATE\"; atMs: number; generation: GristGeneration }\n | { type: \"MAPPING_INVALIDATION_RESOLVE\"; atMs: number; generation: GristGeneration }\n | { type: \"MAPPING_TIMEOUT\"; atMs: number; generation: GristGeneration }\n\n// ---------------------------------------------------------------------------\n// Sync actions\n// ---------------------------------------------------------------------------\n\nexport type GristSyncStream = \"record\" | \"records\" | \"options\" | \"newRecord\"\n\nexport type GristSyncAction =\n | {\n type: \"STREAM_RECEIVED\"\n stream: GristSyncStream\n payloadHash: string\n atMs: number\n generation: GristGeneration\n }\n | { type: \"STREAM_WARMING\"; stream: GristSyncStream; atMs: number }\n | {\n type: \"STREAM_STALE\"\n stream: GristSyncStream\n atMs: number\n reason: \"link_lost\" | \"tab_hidden\" | \"host_quiet\"\n }\n | { type: \"CURRENT_TABLE_KNOWN\"; tableId: string; atMs: number }\n | { type: \"CURRENT_TABLE_REFRESH_START\"; atMs: number }\n | { type: \"CURRENT_TABLE_ERROR\"; message: string; atMs: number }\n\n// ---------------------------------------------------------------------------\n// Top-level union\n// ---------------------------------------------------------------------------\n\nexport type GristAction =\n | GristLifecycleAction\n | GristLinkAction\n | GristAuthzAction\n | GristGenerationAction\n | GristMappingAction\n | GristSyncAction\n\n/**\n * Type guard: actions that carry a `generation` field and can therefore be\n * dropped by the reducer if `action.generation < snapshot.generation`.\n */\nexport function hasGenerationStamp(\n action: GristAction\n): action is Extract<GristAction, { generation: GristGeneration }> {\n return \"generation\" in action && typeof action.generation === \"number\"\n}\n","/**\n * Deterministic merge of column-mapping payloads across multiple sources.\n *\n * Why this exists\n * ---------------\n * Grist reports column mappings from several places, possibly in different\n * orders depending on network timing and event scheduling:\n *\n * - `grist.sectionApi.mappings()` (one-shot promise),\n * - `grist.onRecord` (stream),\n * - `grist.onRecords` (stream, occasionally diverges from `onRecord`),\n * - `grist.onNewRecord` (stream, only on the \"new\" placeholder row).\n *\n * A \"later wins\" merge would let arrival order dictate the final mappings —\n * unstable and surprising. This resolver applies a fixed priority order\n * (see {@link MAPPING_SOURCE_PRIORITY}) so the resolution is a **pure function\n * of the set of received payloads**, independent of the order in which they\n * arrived.\n *\n * Generation safety\n * -----------------\n * Each payload is ingested with the {@link GristGeneration} that was active\n * when the source produced it. Payloads with `generation` strictly less than\n * the resolver's current generation are silently dropped — this is how the\n * machine recovers from reloads / restarts without ever applying a stale\n * mapping over a fresh one.\n */\n\nimport { validateColumnMappings } from \"../../helpers/grist-mappings\"\nimport type { GristColumnsToMap, GristWidgetColumnMap } from \"../../types\"\nimport {\n MAPPING_SOURCE_PRIORITY,\n type GristGeneration,\n type GristMappingComplete,\n type GristMappingIncomplete,\n type GristMappingSource,\n type GristMappingState,\n} from \"./types\"\n\nexport type MappingPayload = {\n source: GristMappingSource\n /** `null` is a known empty payload (host explicitly reported no mappings). */\n payload: GristWidgetColumnMap | null\n receivedAtMs: number\n generation: GristGeneration\n}\n\nexport type ResolveOutcome =\n | {\n kind: \"no_change\"\n reason: \"stale_generation\" | \"duplicate_payload\"\n }\n | {\n kind: \"resolved\"\n state: GristMappingComplete | GristMappingIncomplete\n }\n | { kind: \"still_pending\" }\n\n/**\n * Stateful resolver. One instance per declaration of `columns` (i.e. per\n * widget lifetime, modulo `reset()` on declare-change or restart).\n *\n * The resolver does NOT own the higher-level {@link GristMappingState} —\n * it returns concrete `complete` / `incomplete` payloads that the reducer\n * folds into the snapshot.\n */\nexport class MappingResolver {\n private declared: GristColumnsToMap\n private currentGeneration: GristGeneration\n /** Latest accepted payload per source. */\n private payloads = new Map<GristMappingSource, MappingPayload>()\n /** Last resolved state, used to detect duplicate ingests. */\n private lastResolvedHash: string | null = null\n\n constructor(declared: GristColumnsToMap, generation: GristGeneration) {\n this.declared = declared\n this.currentGeneration = generation\n }\n\n /**\n * Replace the declared columns (e.g. user passed a new `columns` array to\n * the provider). Clears accumulated payloads — they were validated against\n * the previous declaration.\n */\n redeclare(declared: GristColumnsToMap, atGeneration: GristGeneration): void {\n this.declared = declared\n this.currentGeneration = atGeneration\n this.payloads.clear()\n this.lastResolvedHash = null\n }\n\n /** Bump the active generation. Payloads from older generations are dropped. */\n bumpGeneration(next: GristGeneration): void {\n if (next <= this.currentGeneration) return\n this.currentGeneration = next\n // Drop any cached payloads from older generations.\n for (const [src, p] of this.payloads) {\n if (p.generation < next) this.payloads.delete(src)\n }\n this.lastResolvedHash = null\n }\n\n /** Forget every payload and reset the hash. The declaration is preserved. */\n reset(): void {\n this.payloads.clear()\n this.lastResolvedHash = null\n }\n\n /** Cheap, deterministic snapshot for tests/debug. */\n knownSources(): readonly GristMappingSource[] {\n return [...this.payloads.keys()]\n }\n\n /**\n * Ingest one payload. Returns a {@link ResolveOutcome}:\n * - `still_pending` — no payloads accepted yet.\n * - `no_change/stale_*` — input generation is older than current.\n * - `no_change/duplicate_payload` — input did not move the resolution.\n * - `resolved` — new resolution differs from the previous one.\n *\n * Call {@link current} to read the latest resolution without affecting\n * the duplicate-detection hash.\n */\n ingest(input: MappingPayload): ResolveOutcome {\n if (input.generation < this.currentGeneration) {\n return { kind: \"no_change\", reason: \"stale_generation\" }\n }\n if (input.generation > this.currentGeneration) {\n this.bumpGeneration(input.generation)\n }\n this.payloads.set(input.source, input)\n\n const computed = this.compute()\n if (computed === null) return { kind: \"still_pending\" }\n\n const hash = computeMappingHash(\n computed.mappings,\n computed.state === \"complete\",\n computed.source\n )\n if (hash === this.lastResolvedHash) {\n return { kind: \"no_change\", reason: \"duplicate_payload\" }\n }\n this.lastResolvedHash = hash\n return { kind: \"resolved\", state: computed }\n }\n\n /**\n * Return the resolver's current resolution (pure read). Equivalent to\n * `ingest(...)` without mutating any state — used by tests and by the\n * reducer when re-applying after `MAPPING_INVALIDATION_RESOLVE`.\n */\n current(): ResolveOutcome {\n const computed = this.compute()\n if (computed === null) return { kind: \"still_pending\" }\n return { kind: \"resolved\", state: computed }\n }\n\n /**\n * Compute the current best mapping from accumulated payloads (pure).\n *\n * Priority: higher-priority sources **override** specific keys from\n * lower-priority sources. Keys absent from a higher-priority source fall\n * back to lower-priority sources. This matches the production behaviour\n * where `sectionApi.mappings()` is authoritative for the keys it reports,\n * but stream payloads can fill in keys the section_api hasn't reported yet.\n */\n private compute(): GristMappingComplete | GristMappingIncomplete | null {\n if (this.payloads.size === 0) return null\n\n const merged: GristWidgetColumnMap = {}\n let latestReportedAt = 0\n const contributors: GristMappingSource[] = []\n\n for (const src of [...MAPPING_SOURCE_PRIORITY].reverse()) {\n const p = this.payloads.get(src)\n if (!p) continue\n contributors.push(src)\n if (p.receivedAtMs > latestReportedAt) latestReportedAt = p.receivedAtMs\n if (p.payload === null) continue\n for (const [k, v] of Object.entries(p.payload)) {\n merged[k] = v\n }\n }\n\n if (contributors.length === 0) return null\n\n const validation = validateColumnMappings(this.declared, merged)\n const source: GristMappingSource | \"merged\" =\n contributors.length === 1 ? (contributors[0] as GristMappingSource) : \"merged\"\n\n if (validation.ok) {\n return {\n state: \"complete\",\n declared: this.declared,\n mappings: merged,\n source,\n reportedAtMs: latestReportedAt,\n }\n }\n\n return {\n state: \"incomplete\",\n declared: this.declared,\n mappings: merged,\n missing: validation.missing,\n emptyMultiples: validation.emptyMultiples,\n source,\n reportedAtMs: latestReportedAt,\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Stable hash for a {complete|incomplete} mapping payload. Deterministic\n * across re-resolutions of identical inputs so the resolver can de-duplicate.\n */\nexport function computeMappingHash(\n mappings: GristWidgetColumnMap,\n ok: boolean,\n source: GristMappingSource | \"merged\"\n): string {\n const keys = Object.keys(mappings).sort()\n const body = keys.map((k) => {\n const v = mappings[k]\n if (Array.isArray(v)) return `${k}=[${v.join(\",\")}]`\n return `${k}=${v ?? \"\"}`\n }).join(\"|\")\n return `${ok ? \"OK\" : \"KO\"}::${source}::${body}`\n}\n\n/**\n * Decide whether to treat a newly arrived payload as a graceful invalidation\n * of the previous mapping (user just edited the section's mapping settings).\n *\n * Returns `true` if `previous` was `complete`/`incomplete` and `next` differs\n * by at least one key. Pure function, no side effects.\n */\nexport function shouldInvalidate(\n previous: GristMappingState,\n nextMappings: GristWidgetColumnMap\n): boolean {\n if (previous.state !== \"complete\" && previous.state !== \"incomplete\") return false\n const a = previous.mappings\n const aKeys = Object.keys(a)\n const bKeys = Object.keys(nextMappings)\n if (aKeys.length !== bKeys.length) return true\n for (const k of aKeys) {\n const av = a[k]\n const bv = nextMappings[k]\n if (Array.isArray(av) && Array.isArray(bv)) {\n if (av.length !== bv.length) return true\n for (let i = 0; i < av.length; i++) if (av[i] !== bv[i]) return true\n } else if (av !== bv) {\n return true\n }\n }\n return false\n}\n","/**\n * Pure reducer for the handshake state machine.\n *\n * Contract\n * --------\n * - **Pure**: `(snapshot, action, ctx) => nextSnapshot`. No I/O, no globals,\n * no Date.now() — callers pass timestamps via `action.atMs` and (optionally)\n * a context object for the {@link MappingResolver}.\n * - **Total**: every (snapshot.lifecycle.phase × action.type) pair returns\n * either an updated snapshot or the identity snapshot.\n * - **Idempotent for replays**: same generation-stamped action applied twice\n * leaves the snapshot unchanged (`payloadHash` short-circuit on streams,\n * resolver hash short-circuit on mappings).\n * - **Generation-safe**: any action carrying a `generation` lower than the\n * current snapshot generation is dropped silently — this is what makes\n * the SDK robust to late events after reload/restart.\n *\n * The reducer never throws. Invariant violations are surfaced via\n * `./invariants.ts` if the caller opts in.\n */\n\nimport {\n hasGenerationStamp,\n type GristAction,\n type GristMappingAction,\n type GristSyncAction,\n type GristSyncStream,\n} from \"./actions\"\nimport { MappingResolver } from \"./mapping-resolver\"\nimport {\n ZERO_GENERATION,\n nextGeneration,\n type GristGeneration,\n type GristLifecycle,\n type GristLink,\n type GristMappingComplete,\n type GristMappingIncomplete,\n type GristMappingState,\n type GristStreamFreshness,\n type GristSync,\n type GristTerminationReason,\n type GristWidgetSnapshot,\n} from \"./types\"\nimport {\n ACCESS_RANK,\n formatInsufficientAccessMessage,\n isAccessSufficient,\n} from \"./access\"\nimport type { GristRequiredAccess } from \"../../types\"\n\n/**\n * Per-machine mutable companion to the snapshot. The reducer reads from it\n * (and lets the resolver mutate it in-place) so the snapshot itself can stay\n * a deeply-frozen, immutable value.\n */\nexport type GristReducerContext = {\n resolver: MappingResolver | null\n}\n\nexport function createReducerContext(): GristReducerContext {\n return { resolver: null }\n}\n\n/**\n * Tuning knobs. Pass `Partial<ReducerConfig>` to override defaults; values\n * are read by the reducer at each step.\n */\nexport type ReducerConfig = {\n /** Stale-pings threshold before link transitions to `stale`. */\n staleAfterMissed: number\n /** Stale-pings threshold before link transitions to `lost`. */\n lostAfterMissed: number\n}\n\nexport const DEFAULT_REDUCER_CONFIG: ReducerConfig = {\n staleAfterMissed: 1,\n lostAfterMissed: 3,\n}\n\n// ---------------------------------------------------------------------------\n// Reducer entry point\n// ---------------------------------------------------------------------------\n\nexport function gristReducer(\n snapshot: GristWidgetSnapshot,\n action: GristAction,\n ctx: GristReducerContext,\n config: ReducerConfig = DEFAULT_REDUCER_CONFIG\n): GristWidgetSnapshot {\n // Generation gate — applied to every action that carries a generation.\n if (hasGenerationStamp(action) && action.generation < snapshot.generation) {\n return snapshot\n }\n\n switch (action.type) {\n // -- Lifecycle --------------------------------------------------------\n case \"DETECT_START\":\n return reduceDetectStart(snapshot, action.atMs)\n case \"DETECT_TICK\":\n return reduceDetectTick(snapshot, action.attempts)\n case \"DETECT_AVAILABLE\":\n return reduceDetectAvailable(snapshot, action.atMs)\n case \"DETECT_TIMEOUT\":\n return reduceTerminate(snapshot, {\n kind: \"script_timeout\",\n attempts: action.attempts,\n }, action.atMs)\n case \"NOT_EMBEDDED\":\n return reduceTerminate(snapshot, { kind: \"not_embedded\" }, action.atMs)\n case \"NEGOTIATE_START\":\n return reduceNegotiateStart(snapshot, action.access, action.atMs)\n case \"NEGOTIATE_SUCCESS\":\n return reduceNegotiateSuccess(snapshot, action.access, action.grantedLevel, action.atMs)\n case \"NEGOTIATE_FAIL\":\n return reduceTerminate(snapshot, action.reason, action.atMs)\n case \"TERMINATE\":\n return reduceTerminate(snapshot, action.reason, action.atMs)\n case \"AUTHZ_REPORT\":\n return reduceAuthzReport(snapshot, action.level, action.atMs)\n\n // -- Link -------------------------------------------------------------\n case \"RPC_SUCCESS\":\n case \"HEARTBEAT_OK\":\n return reduceLinkSuccess(snapshot, action.atMs)\n case \"RPC_FAILURE\":\n case \"HEARTBEAT_FAIL\":\n return reduceLinkFailure(snapshot, action.atMs, config)\n\n // -- Generation -------------------------------------------------------\n case \"BUMP_GENERATION\":\n return reduceBumpGeneration(snapshot, ctx)\n\n // -- Config / mappings -----------------------------------------------\n case \"MAPPING_DECLARE\":\n case \"MAPPING_REPORT\":\n case \"MAPPING_INVALIDATE\":\n case \"MAPPING_INVALIDATION_RESOLVE\":\n case \"MAPPING_TIMEOUT\":\n return reduceMapping(snapshot, action, ctx)\n\n // -- Sync -------------------------------------------------------------\n case \"STREAM_RECEIVED\":\n case \"STREAM_WARMING\":\n case \"STREAM_STALE\":\n return reduceStream(snapshot, action)\n case \"CURRENT_TABLE_KNOWN\":\n return updateSync(snapshot, {\n ...snapshot.sync,\n currentTable: { state: \"known\", tableId: action.tableId, refreshing: false },\n })\n case \"CURRENT_TABLE_REFRESH_START\":\n if (snapshot.sync.currentTable.state !== \"known\") return snapshot\n return updateSync(snapshot, {\n ...snapshot.sync,\n currentTable: { ...snapshot.sync.currentTable, refreshing: true },\n })\n case \"CURRENT_TABLE_ERROR\":\n return updateSync(snapshot, {\n ...snapshot.sync,\n currentTable: { state: \"errored\", message: action.message, sinceMs: action.atMs },\n })\n\n default: {\n // Exhaustiveness check — TypeScript guarantees this is `never`.\n const _exhaustive: never = action\n void _exhaustive\n return snapshot\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Lifecycle transitions\n// ---------------------------------------------------------------------------\n\nfunction reduceDetectStart(snapshot: GristWidgetSnapshot, atMs: number): GristWidgetSnapshot {\n if (snapshot.lifecycle.phase !== \"idle\") return snapshot\n return {\n ...snapshot,\n lifecycle: { phase: \"detecting\", attempts: 0, startedAtMs: atMs },\n }\n}\n\nfunction reduceDetectTick(snapshot: GristWidgetSnapshot, attempts: number): GristWidgetSnapshot {\n if (snapshot.lifecycle.phase !== \"detecting\") return snapshot\n if (attempts === snapshot.lifecycle.attempts) return snapshot\n return {\n ...snapshot,\n lifecycle: { ...snapshot.lifecycle, attempts },\n }\n}\n\nfunction reduceDetectAvailable(\n snapshot: GristWidgetSnapshot,\n atMs: number\n): GristWidgetSnapshot {\n if (snapshot.lifecycle.phase !== \"detecting\" && snapshot.lifecycle.phase !== \"idle\") {\n return snapshot\n }\n return {\n ...snapshot,\n lifecycle: {\n phase: \"negotiating\",\n access: snapshot.authz.declared,\n startedAtMs: atMs,\n },\n }\n}\n\nfunction reduceNegotiateStart(\n snapshot: GristWidgetSnapshot,\n access: GristWidgetSnapshot[\"authz\"][\"declared\"],\n atMs: number\n): GristWidgetSnapshot {\n // Allowed from `detecting` (first negotiate), `negotiating` (re-arm),\n // or `online` (access widening triggers re-negotiation in place).\n if (snapshot.lifecycle.phase === \"terminated\") return snapshot\n return {\n ...snapshot,\n authz: { state: \"pending\", declared: access },\n lifecycle:\n snapshot.lifecycle.phase === \"online\"\n ? snapshot.lifecycle\n : { phase: \"negotiating\", access, startedAtMs: atMs },\n }\n}\n\nfunction authzDeclared(snapshot: GristWidgetSnapshot): GristRequiredAccess {\n return snapshot.authz.declared\n}\n\nfunction reduceAuthzReport(\n snapshot: GristWidgetSnapshot,\n level: GristRequiredAccess,\n _atMs: number\n): GristWidgetSnapshot {\n if (snapshot.lifecycle.phase !== \"online\") return snapshot\n\n const declared = authzDeclared(snapshot)\n\n if (isAccessSufficient(level, declared)) {\n const previousLevel =\n snapshot.authz.state === \"granted\" ? snapshot.authz.level : null\n const widened =\n previousLevel !== null && ACCESS_RANK[level] > ACCESS_RANK[previousLevel]\n const nextAuthz = {\n state: \"granted\" as const,\n level,\n declared,\n widened,\n }\n if (\n snapshot.authz.state === \"granted\" &&\n snapshot.authz.level === nextAuthz.level &&\n snapshot.authz.declared === nextAuthz.declared &&\n snapshot.authz.widened === nextAuthz.widened\n ) {\n return snapshot\n }\n return { ...snapshot, authz: nextAuthz }\n }\n\n const message = formatInsufficientAccessMessage(declared, level)\n const nextAuthz = { state: \"denied\" as const, declared, message }\n if (\n snapshot.authz.state === \"denied\" &&\n snapshot.authz.declared === nextAuthz.declared &&\n snapshot.authz.message === nextAuthz.message\n ) {\n return snapshot\n }\n return { ...snapshot, authz: nextAuthz }\n}\n\nfunction reduceNegotiateSuccess(\n snapshot: GristWidgetSnapshot,\n access: GristWidgetSnapshot[\"authz\"][\"declared\"],\n grantedLevel: GristWidgetSnapshot[\"authz\"][\"declared\"],\n atMs: number\n): GristWidgetSnapshot {\n if (snapshot.lifecycle.phase === \"terminated\") return snapshot\n\n const previousLevel =\n snapshot.authz.state === \"granted\" ? snapshot.authz.level : null\n const widened =\n previousLevel !== null && ACCESS_RANK[grantedLevel] > ACCESS_RANK[previousLevel]\n\n return {\n ...snapshot,\n authz: {\n state: \"granted\",\n level: grantedLevel,\n declared: access,\n widened,\n },\n lifecycle:\n snapshot.lifecycle.phase === \"online\"\n ? snapshot.lifecycle\n : { phase: \"online\", sinceMs: atMs, declaredAccess: access },\n link: { state: \"connected\", lastSuccessMs: atMs, missedPings: 0 },\n }\n}\n\nfunction reduceTerminate(\n snapshot: GristWidgetSnapshot,\n reason: GristTerminationReason,\n atMs: number\n): GristWidgetSnapshot {\n if (snapshot.lifecycle.phase === \"terminated\") return snapshot\n const lifecycle: GristLifecycle = { phase: \"terminated\", reason, atMs }\n return { ...snapshot, lifecycle }\n}\n\n// ---------------------------------------------------------------------------\n// Link transitions\n// ---------------------------------------------------------------------------\n\nfunction reduceLinkSuccess(snapshot: GristWidgetSnapshot, atMs: number): GristWidgetSnapshot {\n if (snapshot.lifecycle.phase !== \"online\") return snapshot\n const link: GristLink = { state: \"connected\", lastSuccessMs: atMs, missedPings: 0 }\n if (\n snapshot.link.state === link.state &&\n snapshot.link.lastSuccessMs === link.lastSuccessMs &&\n snapshot.link.missedPings === link.missedPings\n ) {\n return snapshot\n }\n return { ...snapshot, link }\n}\n\nfunction reduceLinkFailure(\n snapshot: GristWidgetSnapshot,\n _atMs: number,\n config: ReducerConfig\n): GristWidgetSnapshot {\n if (snapshot.lifecycle.phase !== \"online\") return snapshot\n const missed = snapshot.link.missedPings + 1\n let state: GristLink[\"state\"] = snapshot.link.state\n if (missed >= config.lostAfterMissed) state = \"lost\"\n else if (missed >= config.staleAfterMissed) state = \"stale\"\n return {\n ...snapshot,\n link: { state, lastSuccessMs: snapshot.link.lastSuccessMs, missedPings: missed },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Generation\n// ---------------------------------------------------------------------------\n\nfunction reduceBumpGeneration(\n snapshot: GristWidgetSnapshot,\n ctx: GristReducerContext\n): GristWidgetSnapshot {\n const next = nextGeneration(snapshot.generation)\n ctx.resolver?.bumpGeneration(next)\n return {\n ...snapshot,\n generation: next,\n // Marking streams as warming again ensures hooks treat the data as\n // \"in transit\" until a fresh event arrives under the new generation.\n sync: {\n ...snapshot.sync,\n record: degradeForRefresh(snapshot.sync.record, snapshot.generation),\n records: degradeForRefresh(snapshot.sync.records, snapshot.generation),\n options: degradeForRefresh(snapshot.sync.options, snapshot.generation),\n newRecord: degradeForRefresh(snapshot.sync.newRecord, snapshot.generation),\n },\n }\n}\n\nfunction degradeForRefresh(\n freshness: GristStreamFreshness,\n prevGeneration: GristGeneration\n): GristStreamFreshness {\n if (freshness.state === \"hot\" && freshness.generation === prevGeneration) {\n return { state: \"stale\", lastEventMs: freshness.lastEventMs, reason: \"host_quiet\" }\n }\n return freshness\n}\n\n// ---------------------------------------------------------------------------\n// Mappings (config)\n// ---------------------------------------------------------------------------\n\nfunction reduceMapping(\n snapshot: GristWidgetSnapshot,\n action: GristMappingAction,\n ctx: GristReducerContext\n): GristWidgetSnapshot {\n switch (action.type) {\n case \"MAPPING_DECLARE\": {\n if (action.declared.length === 0) {\n // Empty declaration → revert to `not_declared`.\n if (snapshot.config.mappings.state === \"not_declared\") return snapshot\n ctx.resolver = null\n return {\n ...snapshot,\n config: { mappings: { state: \"not_declared\" } },\n }\n }\n if (!ctx.resolver) {\n ctx.resolver = new MappingResolver(action.declared, snapshot.generation)\n } else {\n ctx.resolver.redeclare(action.declared, snapshot.generation)\n }\n return {\n ...snapshot,\n config: {\n mappings: {\n state: \"pending\",\n declared: action.declared,\n declaredAtMs: action.atMs,\n },\n },\n }\n }\n case \"MAPPING_REPORT\": {\n if (!ctx.resolver) return snapshot\n const outcome = ctx.resolver.ingest({\n source: action.source,\n payload: action.payload,\n receivedAtMs: action.atMs,\n generation: action.generation,\n })\n if (outcome.kind !== \"resolved\") return snapshot\n return applyResolved(snapshot, outcome.state)\n }\n case \"MAPPING_INVALIDATE\": {\n const previous = snapshot.config.mappings\n if (previous.state !== \"complete\" && previous.state !== \"incomplete\") {\n return snapshot\n }\n return {\n ...snapshot,\n config: {\n mappings: {\n state: \"invalidating\",\n previous: previous as GristMappingComplete | GristMappingIncomplete,\n sinceMs: action.atMs,\n },\n },\n }\n }\n case \"MAPPING_INVALIDATION_RESOLVE\": {\n if (snapshot.config.mappings.state !== \"invalidating\") return snapshot\n if (!ctx.resolver) {\n // Resolver lost (e.g. declaration cleared) — fall back to `previous`.\n return {\n ...snapshot,\n config: { mappings: snapshot.config.mappings.previous },\n }\n }\n const outcome = ctx.resolver.current()\n if (outcome.kind !== \"resolved\") {\n return {\n ...snapshot,\n config: { mappings: snapshot.config.mappings.previous },\n }\n }\n return applyResolved(snapshot, outcome.state)\n }\n case \"MAPPING_TIMEOUT\": {\n const previous = snapshot.config.mappings\n if (previous.state !== \"pending\") return snapshot\n return {\n ...snapshot,\n config: {\n mappings: {\n state: \"unreported\",\n declared: previous.declared,\n afterMs: action.atMs - previous.declaredAtMs,\n },\n },\n }\n }\n }\n}\n\nfunction applyResolved(\n snapshot: GristWidgetSnapshot,\n resolved: GristMappingComplete | GristMappingIncomplete\n): GristWidgetSnapshot {\n const existing = snapshot.config.mappings\n if (\n (existing.state === \"complete\" || existing.state === \"incomplete\") &&\n sameResolved(existing, resolved)\n ) {\n return snapshot\n }\n return { ...snapshot, config: { mappings: resolved } }\n}\n\nfunction sameResolved(\n a: GristMappingState,\n b: GristMappingComplete | GristMappingIncomplete\n): boolean {\n if (a.state !== b.state) return false\n if (a.state !== \"complete\" && a.state !== \"incomplete\") return false\n if (a.source !== b.source) return false\n const ak = Object.keys(a.mappings)\n const bk = Object.keys(b.mappings)\n if (ak.length !== bk.length) return false\n for (const k of ak) {\n const av = a.mappings[k]\n const bv = b.mappings[k]\n if (Array.isArray(av) && Array.isArray(bv)) {\n if (av.length !== bv.length) return false\n for (let i = 0; i < av.length; i++) if (av[i] !== bv[i]) return false\n } else if (av !== bv) {\n return false\n }\n }\n return true\n}\n\n// ---------------------------------------------------------------------------\n// Streams (sync)\n// ---------------------------------------------------------------------------\n\nfunction reduceStream(snapshot: GristWidgetSnapshot, action: GristSyncAction): GristWidgetSnapshot {\n if (action.type === \"CURRENT_TABLE_KNOWN\" || action.type === \"CURRENT_TABLE_REFRESH_START\" || action.type === \"CURRENT_TABLE_ERROR\") {\n return snapshot\n }\n const stream = action.stream\n const current = snapshot.sync[stream]\n\n if (action.type === \"STREAM_WARMING\") {\n if (current.state === \"warming\" || current.state === \"hot\") return snapshot\n return updateStream(snapshot, stream, { state: \"warming\", sinceMs: action.atMs })\n }\n\n if (action.type === \"STREAM_STALE\") {\n if (current.state !== \"hot\") return snapshot\n return updateStream(snapshot, stream, {\n state: \"stale\",\n lastEventMs: current.lastEventMs,\n reason: action.reason,\n })\n }\n\n // STREAM_RECEIVED — idempotent on (generation, hash).\n if (\n current.state === \"hot\" &&\n current.generation === action.generation &&\n current.payloadHash === action.payloadHash\n ) {\n return snapshot\n }\n return updateStream(snapshot, stream, {\n state: \"hot\",\n lastEventMs: action.atMs,\n generation: action.generation,\n payloadHash: action.payloadHash,\n })\n}\n\nfunction updateStream(\n snapshot: GristWidgetSnapshot,\n stream: GristSyncStream,\n next: GristStreamFreshness\n): GristWidgetSnapshot {\n return {\n ...snapshot,\n sync: { ...snapshot.sync, [stream]: next },\n }\n}\n\nfunction updateSync(snapshot: GristWidgetSnapshot, sync: GristSync): GristWidgetSnapshot {\n return { ...snapshot, sync }\n}\n\n// ---------------------------------------------------------------------------\n// Re-exports (convenience)\n// ---------------------------------------------------------------------------\n\nexport { ZERO_GENERATION, nextGeneration }\n","/**\n * Pure projections from a {@link GristWidgetSnapshot}:\n *\n * - {@link deriveStatus} → legacy 4-state `status` (compat).\n * - {@link deriveCapabilities} → ready-to-bind booleans for widget UI.\n *\n * Both are deterministic and side-effect free. Callers (hooks, Boundary)\n * memoize them by reference equality of `snapshot`.\n */\n\nimport { ACCESS_RANK } from \"./access\"\nimport {\n pendingColumnMappingStatus,\n type ValidateColumnMappingsResult,\n} from \"../../helpers/grist-mappings\"\nimport type { GristColumnsToMap, GristWidgetColumnMap } from \"../../types\"\nimport type {\n GristCapabilities,\n GristMappingState,\n GristWidgetSnapshot,\n GristWidgetStatus,\n} from \"./types\"\n\n// ---------------------------------------------------------------------------\n// Status projection\n// ---------------------------------------------------------------------------\n\nexport function deriveStatus(snapshot: GristWidgetSnapshot): GristWidgetStatus {\n const { lifecycle, authz, link } = snapshot\n\n if (lifecycle.phase === \"idle\" || lifecycle.phase === \"detecting\") return \"booting\"\n\n if (lifecycle.phase === \"negotiating\") return \"booting\"\n\n if (lifecycle.phase === \"terminated\") {\n switch (lifecycle.reason.kind) {\n case \"script_timeout\":\n case \"not_embedded\":\n return \"unavailable\"\n case \"host_rejected\":\n case \"ready_failed\":\n case \"ready_timeout\":\n case \"manual_terminate\":\n return \"error\"\n }\n }\n\n // lifecycle.phase === \"online\"\n if (authz.state === \"denied\") return \"error\"\n if (link.state === \"lost\") return \"error\"\n return \"ready\"\n}\n\n/** Extract a single human-readable error message, if any, from the snapshot. */\nexport function deriveErrorMessage(snapshot: GristWidgetSnapshot): string | null {\n if (snapshot.lifecycle.phase === \"terminated\") {\n switch (snapshot.lifecycle.reason.kind) {\n case \"ready_failed\":\n return snapshot.lifecycle.reason.message\n case \"ready_timeout\":\n return `Grist handshake timed out after ${snapshot.lifecycle.reason.afterMs}ms`\n case \"host_rejected\":\n return snapshot.lifecycle.reason.message\n case \"script_timeout\":\n return `Grist plugin API never loaded (${snapshot.lifecycle.reason.attempts} attempts)`\n case \"not_embedded\":\n return \"This page is not embedded in a Grist iframe\"\n case \"manual_terminate\":\n return null\n }\n }\n if (snapshot.authz.state === \"denied\") {\n return (\n snapshot.authz.message ??\n `Grist denied requested access (${snapshot.authz.declared})`\n )\n }\n if (snapshot.lifecycle.phase === \"online\" && snapshot.link.state === \"lost\") {\n return `Grist link lost (${snapshot.link.missedPings} consecutive failures)`\n }\n return null\n}\n\n// ---------------------------------------------------------------------------\n// Capabilities derivation\n// ---------------------------------------------------------------------------\n\nexport function deriveCapabilities(snapshot: GristWidgetSnapshot): GristCapabilities {\n const { lifecycle, authz, link, config, sync } = snapshot\n const online = lifecycle.phase === \"online\"\n const granted = authz.state === \"granted\"\n const grantedReadOrMore =\n granted && ACCESS_RANK[authz.level] >= ACCESS_RANK[\"read table\"]\n const grantedFull = granted && authz.level === \"full\"\n const linkUsable = link.state !== \"lost\"\n\n const canRead = online && linkUsable && grantedReadOrMore\n const canFetchTable = canRead && link.state === \"connected\"\n\n const mappingsUsable = hasUsableMappings(config.mappings)\n const missing = mappingsMissing(config.mappings)\n const emptyMultiples = mappingsEmptyMultiples(config.mappings)\n\n const canRender = canRead && mappingsUsable\n const canWriteRecords = canRender && grantedFull\n const canWriteSchema =\n canWriteRecords && sync.currentTable.state === \"known\"\n\n const hasFreshSelection =\n canRead &&\n sync.record.state === \"hot\" &&\n config.mappings.state !== \"invalidating\"\n\n return {\n canRead,\n canRender,\n canWriteRecords,\n canWriteSchema,\n canFetchTable,\n hasFreshSelection,\n hasUsableMappings: mappingsUsable,\n missingMappings: missing,\n emptyMultipleMappings: emptyMultiples,\n }\n}\n\n// ---------------------------------------------------------------------------\n// Mapping helpers\n// ---------------------------------------------------------------------------\n\nfunction hasUsableMappings(state: GristMappingState): boolean {\n if (state.state === \"not_declared\") return true\n if (state.state === \"complete\") return true\n if (state.state === \"invalidating\") {\n return state.previous.state === \"complete\"\n }\n return false\n}\n\nfunction mappingsMissing(state: GristMappingState): readonly string[] {\n if (state.state === \"incomplete\") return state.missing\n if (state.state === \"invalidating\" && state.previous.state === \"incomplete\") {\n return state.previous.missing\n }\n return EMPTY\n}\n\nfunction mappingsEmptyMultiples(state: GristMappingState): readonly string[] {\n if (state.state === \"incomplete\") return state.emptyMultiples\n if (state.state === \"invalidating\" && state.previous.state === \"incomplete\") {\n return state.previous.emptyMultiples\n }\n return EMPTY\n}\n\nconst EMPTY: readonly string[] = Object.freeze([])\n\n// ---------------------------------------------------------------------------\n// Column-mapping projection (public `columnMappingStatus` shape)\n// ---------------------------------------------------------------------------\n\n/** Resolved mappings from the FSM config axis, if any. */\nexport function extractResolvedMappings(\n state: GristMappingState\n): GristWidgetColumnMap | null {\n switch (state.state) {\n case \"complete\":\n case \"incomplete\":\n return state.mappings\n case \"invalidating\":\n if (state.previous.state === \"complete\" || state.previous.state === \"incomplete\") {\n return state.previous.mappings\n }\n return null\n default:\n return null\n }\n}\n\n/**\n * Project {@link GristMappingState} into the legacy\n * {@link ValidateColumnMappingsResult} consumed by `useGrist().columnMappingStatus`.\n */\nexport function deriveColumnMappingStatus(\n mappingState: GristMappingState,\n columns?: GristColumnsToMap\n): ValidateColumnMappingsResult {\n if (!columns?.length) {\n return { ok: true, pending: false, missing: [], emptyMultiples: [] }\n }\n switch (mappingState.state) {\n case \"not_declared\":\n return { ok: true, pending: false, missing: [], emptyMultiples: [] }\n case \"pending\":\n return pendingColumnMappingStatus\n case \"unreported\":\n return pendingColumnMappingStatus\n case \"complete\":\n return { ok: true, pending: false, missing: [], emptyMultiples: [] }\n case \"incomplete\":\n return {\n ok: false,\n pending: false,\n missing: [...mappingState.missing],\n emptyMultiples: [...mappingState.emptyMultiples],\n }\n case \"invalidating\":\n return deriveColumnMappingStatus(mappingState.previous, columns)\n }\n}\n","/**\n * Pure projections from the handshake snapshot for boundary / shell UI.\n *\n * Blocking states (`booting`, `unavailable`, `error`) map to full-screen chrome\n * via `<GristBoundary>`. Non-blocking degradations stay on the alert path\n * ({@link getGristSdkAlertDescriptors}).\n */\n\nimport { gristAccessLevelLabel } from \"../internal/handshake/access\"\nimport { deriveErrorMessage, deriveStatus, type GristWidgetSnapshot } from \"../internal/handshake\"\nimport type { GristWidgetStatus } from \"../internal/hooks/use-grist-core\"\n\nexport type GristBoundaryBlockingKind = \"booting\" | \"unavailable\" | \"error\"\n\nexport type GristBoundaryBootPhase = \"idle\" | \"detecting\" | \"negotiating\" | \"generic\"\n\nexport type GristBoundaryView =\n | {\n mode: \"blocking\"\n kind: GristBoundaryBlockingKind\n bootPhase?: GristBoundaryBootPhase\n title: string\n message: string\n showRetry: boolean\n }\n | { mode: \"ready\" }\n\n/**\n * Human-readable boot label from lifecycle phase (for spinners / progress UI).\n */\nexport function deriveBoundaryBootLabel(snapshot: GristWidgetSnapshot): string {\n const { lifecycle } = snapshot\n switch (lifecycle.phase) {\n case \"idle\":\n return \"Starting…\"\n case \"detecting\":\n return lifecycle.attempts > 0\n ? `Looking for Grist… (attempt ${lifecycle.attempts})`\n : \"Looking for Grist…\"\n case \"negotiating\":\n return \"Asking Grist for the access this widget needs…\"\n case \"online\":\n return \"Connected\"\n case \"terminated\":\n return \"Connection ended\"\n }\n}\n\nexport function deriveBoundaryBootPhase(\n snapshot: GristWidgetSnapshot\n): GristBoundaryBootPhase {\n switch (snapshot.lifecycle.phase) {\n case \"idle\":\n return \"idle\"\n case \"detecting\":\n return \"detecting\"\n case \"negotiating\":\n return \"negotiating\"\n default:\n return \"generic\"\n }\n}\n\n/**\n * Turn internal handshake errors into short, actionable copy for `<GristBoundary>`.\n */\nexport function formatBoundaryUserMessage(\n raw: string | null,\n snapshot: GristWidgetSnapshot\n): string {\n if (snapshot.authz.state === \"denied\") {\n return (\n snapshot.authz.message ??\n `Set Access level to at least \"${gristAccessLevelLabel(snapshot.authz.declared)}\" in the Custom widget settings.`\n )\n }\n\n if (!raw?.trim()) {\n return \"Something went wrong connecting to Grist. Try reconnecting below, or reload the page.\"\n }\n\n const text = raw.trim()\n\n if (/timed out/i.test(text)) {\n return \"Grist took too long to respond. Check your network, then try reconnecting.\"\n }\n if (/link lost/i.test(text)) {\n return \"The link to Grist was interrupted. Try reconnecting to restore live data.\"\n }\n if (/not embedded|custom widget inside/i.test(text)) {\n return text\n }\n if (/plugin API did not load/i.test(text)) {\n return \"The Grist plugin did not load in time. Reload the page, or open this URL as a custom widget inside a Grist document.\"\n }\n if (/denied requested access/i.test(text)) {\n const declared =\n snapshot.authz.state === \"pending\"\n ? snapshot.authz.declared\n : snapshot.authz.state === \"granted\"\n ? snapshot.authz.declared\n : null\n if (declared) {\n return `Set Access level to at least \"${gristAccessLevelLabel(declared)}\" in the Custom widget settings.`\n }\n }\n\n return text\n}\n\nfunction blockingTitle(\n kind: GristBoundaryBlockingKind,\n bootPhase: GristBoundaryBootPhase,\n snapshot: GristWidgetSnapshot\n): string {\n if (kind === \"error\" && snapshot.authz.state === \"denied\") {\n return \"More access needed\"\n }\n if (kind === \"unavailable\") return \"Open inside Grist\"\n if (kind === \"error\") return \"Something went wrong\"\n switch (bootPhase) {\n case \"detecting\":\n return \"Connecting to Grist\"\n case \"negotiating\":\n return \"Setting up access\"\n case \"idle\":\n return \"Starting\"\n default:\n return \"Connecting to Grist\"\n }\n}\n\nfunction blockingMessage(\n snapshot: GristWidgetSnapshot,\n status: GristWidgetStatus,\n error: string | null\n): string {\n if (status === \"unavailable\") {\n if (snapshot.lifecycle.phase === \"terminated\") {\n if (snapshot.lifecycle.reason.kind === \"not_embedded\") {\n return \"Open this page as a custom widget inside a Grist document (it runs in an embedded panel, not on its own).\"\n }\n if (snapshot.lifecycle.reason.kind === \"script_timeout\") {\n return formatBoundaryUserMessage(\n error ?? \"The Grist plugin API did not load in time.\",\n snapshot\n )\n }\n }\n return \"This page must be opened from a Grist document as a custom widget.\"\n }\n if (status === \"error\") {\n return formatBoundaryUserMessage(error, snapshot)\n }\n return deriveBoundaryBootLabel(snapshot)\n}\n\n/**\n * Classify how `<GristBoundary>` should render: full-screen blocking vs children.\n */\nexport function deriveBoundaryView(snapshot: GristWidgetSnapshot): GristBoundaryView {\n const status = deriveStatus(snapshot)\n if (status === \"ready\") {\n return { mode: \"ready\" }\n }\n const kind: GristBoundaryBlockingKind =\n status === \"unavailable\" ? \"unavailable\" : status === \"error\" ? \"error\" : \"booting\"\n const bootPhase = kind === \"booting\" ? deriveBoundaryBootPhase(snapshot) : undefined\n const error = deriveErrorMessage(snapshot)\n return {\n mode: \"blocking\",\n kind,\n bootPhase,\n title: blockingTitle(kind, bootPhase ?? \"generic\", snapshot),\n message: blockingMessage(snapshot, status, error),\n showRetry: kind === \"unavailable\" || kind === \"error\",\n }\n}\n\n/** Copy for `gate=\"canRender\"` while column mappings are not yet usable. */\nexport const GRIST_BOUNDARY_PREPARING_COPY = {\n title: \"Map your columns\",\n message:\n \"Open the widget settings in Grist (Creator Panel → Custom widget) and connect each required column to your table.\",\n} as const\n","import type { GristWidgetInteraction, GristWidgetLinkingInfo } from \"../types\"\n\n/**\n * Parse `InteractionOptions.linking` from a Grist `onOptions` settings payload.\n */\nexport function parseGristWidgetLinkingInfo(raw: unknown): GristWidgetLinkingInfo | undefined {\n if (!raw || typeof raw !== \"object\" || !(\"asTarget\" in raw)) return undefined\n const linking = raw as { asTarget: unknown; asSource?: unknown }\n return {\n asTarget: linking.asTarget == null ? null : String(linking.asTarget),\n asSource: Boolean(linking.asSource),\n }\n}\n\n/**\n * Normalize the second argument to `grist.onOptions` (Grist `InteractionOptions`).\n * Hosts use `accessLevel` (camelCase); the emulator uses `access_level`.\n */\nexport function normalizeWidgetInteraction(\n interaction: GristWidgetInteraction | null\n): GristWidgetInteraction | null {\n if (!interaction || typeof interaction !== \"object\") return interaction\n const raw = interaction as Record<string, unknown>\n const access_level =\n typeof raw.access_level === \"string\"\n ? raw.access_level\n : typeof raw.accessLevel === \"string\"\n ? raw.accessLevel\n : undefined\n const linking = parseGristWidgetLinkingInfo(raw.linking)\n return {\n ...interaction,\n ...(access_level ? { access_level } : {}),\n ...(linking ? { linking } : {}),\n }\n}\n","import type { ValidateColumnMappingsResult } from \"./grist-mappings\"\nimport type { GristWidgetSnapshot } from \"../internal/handshake\"\nimport type { GristWidgetStatus } from \"../internal/hooks/use-grist-core\"\nimport type { GristWidgetMode } from \"../internal/hooks/use-grist-selection\"\nimport type { GristWidgetInteraction } from \"../types\"\nimport { parseGristWidgetLinkingInfo } from \"./grist-widget-interaction\"\n\n/**\n * Minimal widget slice for deriving non-fatal SDK callouts. Any\n * {@link import(\"../use-grist\").UseGristResult} satisfies this.\n */\nexport type GristSdkAlertsWidgetSlice = {\n status: GristWidgetStatus\n columnMappingStatus: ValidateColumnMappingsResult\n actionError: string | null\n /**\n * Last access-insufficient error from a read method (`fetchTable`, etc.).\n * When set and matching the access-error pattern, an \"access-insufficient\"\n * alert is emitted — same as for `actionError`.\n */\n readError?: string | null\n /**\n * Logical column names that the most recent `mapBack(...)` call could not\n * reverse-map (e.g. `allowMultiple` columns where one logical name resolves\n * to several real columns).\n */\n mapBackSkipped?: readonly string[]\n /** Selection mode from `useGrist()` — used for section-not-linked detection. */\n mode?: GristWidgetMode\n /** `onOptions` settings from Grist (`InteractionOptions`). */\n widgetInteraction?: GristWidgetInteraction | null\n /**\n * Alert kinds suppressed via `UseGristOptions.suppressAlerts`.\n * Consumed automatically by `useGristSdkAlertDescriptors`.\n */\n suppressAlerts?: readonly GristSdkAlertKind[]\n /**\n * Whether the widget declared `allowSelectBy: true` — used to distinguish\n * \"section-not-linked\" (expects incoming link) from \"source-not-wired\"\n * (expects to drive other sections).\n */\n allowSelectBy?: boolean\n}\n\nexport type GristSdkAlertKind =\n | \"column-mapping\"\n | \"mapping-pending\"\n | \"mapping-unreported\"\n | \"link-stale\"\n | \"section-not-linked\"\n | \"source-not-wired\"\n | \"current-table-error\"\n | \"action-error\"\n | \"access-insufficient\"\n | \"map-back-skip\"\n\n/** Classic callout level for host styling: info / warning / error. */\nexport type GristSdkAlertSeverity = \"info\" | \"warning\" | \"error\"\n\nexport type GristSdkAlertDescriptor = {\n id: string\n kind: GristSdkAlertKind\n severity: GristSdkAlertSeverity\n title: string\n /** Suggested WAI-ARIA role for the host shell. */\n ariaRole: \"status\" | \"alert\"\n message: string\n}\n\nexport type GetGristSdkAlertDescriptorsOptions = {\n /**\n * Handshake snapshot from `useGristHandshake()` / the provider manager.\n * Enables link-stale, mapping-unreported, and current-table alerts that are\n * not visible on the widget slice alone.\n */\n snapshot?: GristWidgetSnapshot\n /** Appended to {@link formatColumnMappingAlertMessage} when a mapping alert is emitted. */\n columnMappingHint?: string\n /** Appended to the map-back-skip message. */\n mapBackHint?: string\n /** Override copy for {@link formatMappingPendingAlertMessage}. */\n mappingPendingHint?: string\n /** Appended to {@link formatSectionNotLinkedAlertMessage}. */\n sectionNotLinkedHint?: string\n /** Appended to {@link formatSourceNotWiredAlertMessage}. */\n sourceNotWiredHint?: string\n /** Appended to {@link formatAccessInsufficientMessage}. */\n accessInsufficientHint?: string\n /**\n * Alert kinds to omit from the output. Useful for widgets that intentionally\n * operate without a link source (`[\"section-not-linked\"]`) or handle certain\n * conditions in their own UI.\n */\n suppressKinds?: readonly GristSdkAlertKind[]\n}\n\n/** Default alert title for shadcn / toast shells. */\nexport function getGristSdkAlertTitle(kind: GristSdkAlertKind): string {\n switch (kind) {\n case \"column-mapping\":\n return \"Column mapping\"\n case \"mapping-pending\":\n return \"Column mapping\"\n case \"mapping-unreported\":\n return \"Column mapping\"\n case \"link-stale\":\n return \"Grist connection\"\n case \"section-not-linked\":\n return \"Widget linking\"\n case \"source-not-wired\":\n return \"Widget linking\"\n case \"current-table-error\":\n return \"Current table\"\n case \"action-error\":\n return \"Action error\"\n case \"access-insufficient\":\n return \"Access level\"\n case \"map-back-skip\":\n return \"Write skipped\"\n }\n}\n\n/** Suggested severity for host styling (destructive vs muted). */\nexport function getGristSdkAlertSeverity(kind: GristSdkAlertKind): GristSdkAlertSeverity {\n switch (kind) {\n case \"action-error\":\n case \"current-table-error\":\n case \"access-insufficient\":\n return \"error\"\n case \"column-mapping\":\n case \"mapping-unreported\":\n case \"link-stale\":\n case \"section-not-linked\":\n case \"source-not-wired\":\n case \"map-back-skip\":\n return \"warning\"\n case \"mapping-pending\":\n return \"info\"\n }\n}\n\n/**\n * Human-readable text for an incomplete column mapping (when\n * `columnMappingStatus.ok` is false).\n */\nexport function formatColumnMappingAlertMessage(\n status: ValidateColumnMappingsResult,\n hint?: string\n): string {\n const parts: string[] = [\"Column mapping is incomplete.\"]\n if (status.missing.length > 0) {\n parts.push(`Required columns: ${status.missing.join(\", \")}.`)\n }\n if (status.emptyMultiples.length > 0) {\n parts.push(\n `Assign at least one sheet column for: ${status.emptyMultiples.join(\", \")}.`\n )\n }\n if (hint?.trim()) {\n parts.push(hint.trim())\n }\n return parts.join(\" \")\n}\n\nexport function formatMappingPendingAlertMessage(hint?: string): string {\n const base = \"Waiting for Grist to report column mappings.\"\n return hint?.trim() ? `${base} ${hint.trim()}` : base\n}\n\nexport function formatMappingUnreportedAlertMessage(hint?: string): string {\n const base =\n \"Grist has not reported column mappings yet. Open the widget panel to map columns.\"\n return hint?.trim() ? `${base} ${hint.trim()}` : base\n}\n\nexport function formatLinkStaleAlertMessage(snapshot: GristWidgetSnapshot): string {\n const missed = snapshot.link.missedPings\n const suffix = missed > 0 ? ` (${missed} missed heartbeat${missed === 1 ? \"\" : \"s\"})` : \"\"\n return `Connection to Grist is stale. Edits may fail until the link recovers.${suffix}`\n}\n\n/**\n * True when Grist reports this section is not a link target (no selector drives\n * the cursor / `onRecord` stream). Requires `linking` on `widgetInteraction` so\n * older hosts do not trigger false positives.\n */\nexport function isWidgetSectionNotLinked(\n interaction: GristWidgetInteraction | null | undefined\n): boolean {\n if (!interaction || typeof interaction !== \"object\") return false\n const linking = parseGristWidgetLinkingInfo(\n interaction.linking ?? (interaction as Record<string, unknown>).linking\n )\n if (!linking) return false\n return linking.asTarget == null\n}\n\nexport function formatSectionNotLinkedAlertMessage(hint?: string): string {\n const base =\n \"This widget section is not linked to a table or selector. Link it from the page settings so the selected row is sent to the widget.\"\n return hint?.trim() ? `${base} ${hint.trim()}` : base\n}\n\nexport function formatSourceNotWiredAlertMessage(hint?: string): string {\n const base =\n \"This widget is configured as a selector (allowSelectBy) but no other section is using it as a link source yet. Link another section to read from this widget.\"\n return hint?.trim() ? `${base} ${hint.trim()}` : base\n}\n\nfunction pushDescriptor(\n out: GristSdkAlertDescriptor[],\n partial: Omit<GristSdkAlertDescriptor, \"title\" | \"severity\"> & {\n title?: string\n severity?: GristSdkAlertSeverity\n }\n): void {\n out.push({\n title: partial.title ?? getGristSdkAlertTitle(partial.kind),\n severity: partial.severity ?? getGristSdkAlertSeverity(partial.kind),\n id: partial.id,\n kind: partial.kind,\n ariaRole: partial.ariaRole,\n message: partial.message,\n })\n}\n\nfunction appendSnapshotAlerts(\n snapshot: GristWidgetSnapshot,\n options: GetGristSdkAlertDescriptorsOptions | undefined,\n out: GristSdkAlertDescriptor[]\n): void {\n const { config, link, sync } = snapshot\n\n if (config.mappings.state === \"unreported\") {\n pushDescriptor(out, {\n id: \"mapping-unreported\",\n kind: \"mapping-unreported\",\n ariaRole: \"status\",\n message: formatMappingUnreportedAlertMessage(options?.columnMappingHint),\n })\n }\n\n if (link.state === \"stale\") {\n pushDescriptor(out, {\n id: \"link-stale\",\n kind: \"link-stale\",\n ariaRole: \"status\",\n message: formatLinkStaleAlertMessage(snapshot),\n })\n }\n\n if (sync.currentTable.state === \"errored\") {\n pushDescriptor(out, {\n id: \"current-table-error\",\n kind: \"current-table-error\",\n ariaRole: \"alert\",\n message: sync.currentTable.message,\n })\n }\n}\n\n/**\n * Non-fatal SDK messages to show while `status === \"ready\"` (e.g. incomplete\n * mappings, stale link, or `actionError` when not promoted to `status === \"error\"`).\n * Host apps map each descriptor to their own UI (shadcn Alert, toast, etc.).\n *\n * Pass `options.snapshot` (from `useGristHandshake()` or the provider manager)\n * for FSM-only signals: link stale, mapping unreported, current-table errors.\n */\nexport function getGristSdkAlertDescriptors(\n widget: GristSdkAlertsWidgetSlice,\n options?: GetGristSdkAlertDescriptorsOptions\n): GristSdkAlertDescriptor[] {\n const out: GristSdkAlertDescriptor[] = []\n\n if (widget.status !== \"ready\") {\n return out\n }\n\n if (widget.columnMappingStatus.pending) {\n pushDescriptor(out, {\n id: \"mapping-pending\",\n kind: \"mapping-pending\",\n ariaRole: \"status\",\n message: formatMappingPendingAlertMessage(options?.mappingPendingHint),\n })\n } else if (!widget.columnMappingStatus.ok) {\n pushDescriptor(out, {\n id: \"column-mapping\",\n kind: \"column-mapping\",\n ariaRole: \"status\",\n message: formatColumnMappingAlertMessage(\n widget.columnMappingStatus,\n options?.columnMappingHint\n ),\n })\n }\n\n const accessErrorSource = widget.actionError ?? widget.readError\n if (accessErrorSource && isAccessInsufficientError(accessErrorSource)) {\n pushDescriptor(out, {\n id: \"access-insufficient\",\n kind: \"access-insufficient\",\n ariaRole: \"alert\",\n message: formatAccessInsufficientMessage(options?.accessInsufficientHint),\n })\n } else if (widget.actionError) {\n pushDescriptor(out, {\n id: \"action-error\",\n kind: \"action-error\",\n ariaRole: \"alert\",\n message: widget.actionError,\n })\n } else if (widget.readError) {\n pushDescriptor(out, {\n id: \"action-error\",\n kind: \"action-error\",\n ariaRole: \"alert\",\n message: widget.readError,\n })\n }\n\n const skipped = widget.mapBackSkipped ?? []\n if (skipped.length > 0) {\n pushDescriptor(out, {\n id: \"map-back-skip\",\n kind: \"map-back-skip\",\n ariaRole: \"status\",\n message: formatMapBackSkipMessage(skipped, options?.mapBackHint),\n })\n }\n\n if (widget.allowSelectBy) {\n const linking = widget.widgetInteraction\n ? parseGristWidgetLinkingInfo(\n widget.widgetInteraction.linking ??\n (widget.widgetInteraction as Record<string, unknown>).linking\n )\n : undefined\n if (linking && !linking.asSource) {\n pushDescriptor(out, {\n id: \"source-not-wired\",\n kind: \"source-not-wired\",\n ariaRole: \"status\",\n message: formatSourceNotWiredAlertMessage(options?.sourceNotWiredHint),\n })\n }\n } else if (isWidgetSectionNotLinked(widget.widgetInteraction)) {\n pushDescriptor(out, {\n id: \"section-not-linked\",\n kind: \"section-not-linked\",\n ariaRole: \"status\",\n message: formatSectionNotLinkedAlertMessage(options?.sectionNotLinkedHint),\n })\n }\n\n if (options?.snapshot) {\n appendSnapshotAlerts(options.snapshot, options, out)\n }\n\n if (options?.suppressKinds?.length) {\n return out.filter((a) => !options.suppressKinds!.includes(a.kind))\n }\n return out\n}\n\n/**\n * Human-readable text when `mapBack(...)` had to skip allow-multiple columns.\n */\nexport function formatMapBackSkipMessage(\n skipped: readonly string[],\n hint?: string\n): string {\n const list = skipped.join(\", \")\n const base = `mapBack skipped multi-mapped column${\n skipped.length === 1 ? \"\" : \"s\"\n }: ${list}.`\n return hint?.trim() ? `${base} ${hint.trim()}` : base\n}\n\nconst ACCESS_ERROR_PATTERNS = [\n /access not granted/i,\n /need higher access level/i,\n /requires.*full.*access/i,\n /RPC_ONCALL_ERROR Access/i,\n]\n\n/**\n * Heuristic: returns `true` when `actionError` looks like it was caused by\n * insufficient access rights rather than a domain / schema error.\n */\nexport function isAccessInsufficientError(message: string): boolean {\n return ACCESS_ERROR_PATTERNS.some((re) => re.test(message))\n}\n\nexport function formatAccessInsufficientMessage(hint?: string): string {\n const base =\n 'This operation requires \"Full document access\". Set the Access level to \"Full document access\" in the Custom widget configuration panel.'\n return hint?.trim() ? `${base} ${hint.trim()}` : base\n}\n","import { useMemo, useSyncExternalStore } from \"react\"\n\nimport {\n getGristSdkAlertDescriptors,\n type GetGristSdkAlertDescriptorsOptions,\n type GristSdkAlertDescriptor,\n type GristSdkAlertsWidgetSlice,\n} from \"../helpers/grist-sdk-alerts\"\nimport { initialGristSnapshot } from \"../internal/handshake\"\nimport { useGristManagerOptional } from \"../internal/handshake-manager-context\"\nimport { useGristOptional } from \"../components/grist-widget-provider\"\nimport type { UseGristResult } from \"../use-grist-types\"\n\nfunction noopSubscribe() {\n return () => {}\n}\n\n/**\n * React hook: widget slice + optional handshake snapshot for\n * {@link getGristSdkAlertDescriptors}.\n */\nexport function useGristSdkAlertDescriptors(\n widget?: GristSdkAlertsWidgetSlice | UseGristResult,\n options?: GetGristSdkAlertDescriptorsOptions\n): GristSdkAlertDescriptor[] {\n const fromContext = useGristOptional()\n const w = widget ?? fromContext\n const manager = useGristManagerOptional()\n const snapshot = useSyncExternalStore(\n manager?.subscribe ?? noopSubscribe,\n manager?.getSnapshot ?? initialGristSnapshot,\n initialGristSnapshot\n )\n\n const resolvedSnapshot = options?.snapshot ?? (manager ? snapshot : undefined)\n\n const widgetInteraction = w?.widgetInteraction\n const readError = w && \"readError\" in w ? (w as { readError?: string | null }).readError : null\n const alertInputs = w\n ? [\n w.status,\n w.mode,\n widgetInteraction,\n w.columnMappingStatus,\n w.actionError,\n readError,\n w.mapBackSkipped,\n ]\n : null\n\n const suppressFromSlice = w?.suppressAlerts\n\n return useMemo(\n () =>\n w\n ? getGristSdkAlertDescriptors(w, {\n ...options,\n suppressKinds: options?.suppressKinds ?? suppressFromSlice,\n snapshot: resolvedSnapshot,\n })\n : [],\n [alertInputs, options, resolvedSnapshot, w, suppressFromSlice]\n )\n}\n","/**\n * Internal context that hosts the shared {@link GristHandshakeManager} for a\n * widget subtree.\n *\n * - `<GristWidgetProvider>` publishes the manager via\n * {@link GristHandshakeManagerContext}.\n * - Standalone `useGrist()` / mid-level hooks without a provider acquire the\n * page-level embedded manager ({@link acquireEmbeddedHandshakeManager}).\n *\n * All SDK hooks call {@link useGristManager} — there is no pre-FSM fallback.\n */\n\nimport { createContext, useContext, useEffect, useRef } from \"react\"\n\nimport { buildManagerOptionsFromGristOptions, type BuildManagerOptionsInput } from \"./build-manager-options\"\nimport {\n acquireEmbeddedHandshakeManager,\n releaseEmbeddedHandshakeManager,\n} from \"./embedded-handshake-manager\"\nimport type { ManagerControls } from \"./handshake/manager\"\n\nexport const GristHandshakeManagerContext = createContext<ManagerControls | null>(null)\n\n/** Read the manager from context. Returns `null` outside a provider. */\nexport function useGristManagerOptional(): ManagerControls | null {\n return useContext(GristHandshakeManagerContext)\n}\n\n/**\n * Returns the active handshake manager for this React tree.\n *\n * Inside `<GristWidgetProvider>` this is the provider's manager. Otherwise a\n * single ref-counted embedded manager is shared across all standalone hook\n * instances on the page.\n */\nexport function useGristManager(options?: BuildManagerOptionsInput): ManagerControls {\n const fromProvider = useContext(GristHandshakeManagerContext)\n const optionsRef = useRef(options)\n optionsRef.current = options\n\n const embeddedRef = useRef<ManagerControls | null>(null)\n const ownsEmbeddedRef = useRef(false)\n\n if (fromProvider) {\n return fromProvider\n }\n\n if (embeddedRef.current === null) {\n embeddedRef.current = acquireEmbeddedHandshakeManager(\n buildManagerOptionsFromGristOptions(optionsRef.current)\n )\n ownsEmbeddedRef.current = true\n }\n\n useEffect(() => {\n if (!ownsEmbeddedRef.current) return\n return () => {\n releaseEmbeddedHandshakeManager()\n embeddedRef.current = null\n ownsEmbeddedRef.current = false\n }\n }, [])\n\n return embeddedRef.current\n}\n","/**\n * Single-call wrapper around `grist.ready()`.\n *\n * Grist's contract is \"call ready once\". Multiple `useGristReady` calls (or\n * `useGristWidget` from sibling components) would otherwise race. We:\n *\n * - Coalesce concurrent calls into one in-flight promise.\n * - Re-call `grist.ready` only when `requiredAccess` widens (so an action-capable\n * hook can upgrade a previously read-only handshake).\n */\n\nimport type { GristReadyOptions, GristRequiredAccess } from \"../types\"\n\nconst ACCESS_RANK: Record<GristRequiredAccess, number> = {\n none: 0,\n \"read table\": 1,\n full: 2,\n}\n\nlet inFlight: Promise<void> | null = null\nlet lastAccess: GristRequiredAccess | null = null\n\nfunction shouldReinit(next: GristRequiredAccess): boolean {\n if (!lastAccess) return true\n return ACCESS_RANK[next] > ACCESS_RANK[lastAccess]\n}\n\n/**\n * Calls `grist.ready` at most once per page (re-called only if access widens).\n * Returns the same promise for all concurrent callers.\n */\nexport function ensureGristReady(payload: GristReadyOptions): Promise<void> {\n const access = payload.requiredAccess ?? \"read table\"\n if (inFlight && !shouldReinit(access)) return inFlight\n\n lastAccess = access\n const next = Promise.resolve().then(() => {\n const result = grist.ready(payload)\n return result instanceof Promise ? result : Promise.resolve()\n })\n\n inFlight = next.catch((err) => {\n inFlight = null\n lastAccess = null\n throw err\n })\n return inFlight\n}\n\n/**\n * Forget the cached ready state. Subsequent calls to {@link ensureGristReady}\n * will re-issue `grist.ready` even at the same access level.\n *\n * Production uses: the handshake manager's `reload()` clears the singleton so\n * a soft retry triggers a fresh `grist.ready` (otherwise the cached promise\n * would short-circuit and the user-visible reload would be a no-op).\n *\n * Tests use this between test cases when swapping `window.grist`.\n */\nexport function resetGristReadySingleton(): void {\n inFlight = null\n lastAccess = null\n}\n\n/** @deprecated Use {@link resetGristReadySingleton}. Kept for test back-compat. */\nexport const resetGristReadyCacheForTests = resetGristReadySingleton\n","import type { ManagerOptions } from \"./handshake/manager\"\nimport { ensureGristReady, resetGristReadySingleton } from \"./ready-singleton\"\nimport type { GristReadyOptions } from \"../types\"\n\nexport type BuildManagerOptionsInput = GristReadyOptions & {\n availabilityMaxAttempts?: number\n availabilityIntervalMs?: number\n logWhenNotEmbedded?: boolean\n}\n\n/**\n * Map public widget options to {@link ManagerOptions} for\n * {@link createGristHandshakeManager}.\n */\nexport function buildManagerOptionsFromGristOptions(\n options?: BuildManagerOptionsInput\n): ManagerOptions {\n const opts: ManagerOptions = {\n requiredAccess: options?.requiredAccess ?? \"read table\",\n columns: options?.columns ?? [],\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n negotiate: {\n readyImpl: (payload) => ensureGristReady(payload),\n },\n onBeforeReload: () => resetGristReadySingleton(),\n }\n if (\n options?.availabilityMaxAttempts !== undefined ||\n options?.availabilityIntervalMs !== undefined\n ) {\n const interval = options?.availabilityIntervalMs ?? 1000\n const max = options?.availabilityMaxAttempts ?? 10\n opts.detect = {\n pollSequenceMs: Array.from({ length: max }, () => interval),\n budgetMs: interval * max,\n }\n }\n return opts\n}\n","/**\n * Detect effect — poll for `window.grist` with exponential backoff inside a\n * finite, optionally adaptive budget.\n *\n * Outputs (dispatched to the manager):\n * - DETECT_START (once, at start)\n * - DETECT_TICK (each unsuccessful poll, with attempts count)\n * - DETECT_AVAILABLE (grist global present AND embedded)\n * - NOT_EMBEDDED (grist global present but `self === top`)\n * - DETECT_TIMEOUT (budget consumed without detection)\n *\n * The effect aborts on `signal.aborted` and clears its pending timer.\n *\n * Pure of `window`: relies on the {@link GristEnvironment} adapter so the\n * effect is fully unit-testable with a virtual clock.\n */\n\nimport type { GristEnvironment, TimerHandle } from \"../environment\"\nimport type { GristAction } from \"../actions\"\n\n/**\n * Default poll sequence (ms). Caps at 5 000 ms — most production widgets see\n * `grist-plugin-api.js` load in < 1 s, but slow 3G can stretch to 20–30 s.\n */\nexport const DEFAULT_POLL_SEQUENCE_MS: readonly number[] = [\n 200, 200, 400, 400, 800, 1600, 3200, 5000, 5000, 5000, 5000, 5000, 5000, 5000,\n] as const\n\n/** Effective budget, adaptive on `navigator.connection.effectiveType`. */\nexport function defaultBudgetMs(hint: ReturnType<GristEnvironment[\"effectiveTypeHint\"]>): number {\n if (hint === \"slow-2g\" || hint === \"2g\") return 120_000\n if (hint === \"3g\") return 60_000\n return 30_000\n}\n\nexport type DetectOptions = {\n /** Custom poll sequence in ms. Index past end uses last value. */\n pollSequenceMs?: readonly number[]\n /** Total wall-clock budget across all polls. */\n budgetMs?: number\n}\n\nexport type DetectHandle = {\n cancel(): void\n}\n\n/**\n * Start the detect effect. The manager owns the cancellation handle and is\n * responsible for calling `cancel()` on `restart()` / `stop()`.\n */\nexport function startDetectEffect(\n env: GristEnvironment,\n dispatch: (action: GristAction) => void,\n signal: AbortSignal,\n options: DetectOptions = {}\n): DetectHandle {\n const sequence = options.pollSequenceMs ?? DEFAULT_POLL_SEQUENCE_MS\n const budgetMs = options.budgetMs ?? defaultBudgetMs(env.effectiveTypeHint())\n\n const startedAt = env.now()\n let attempts = 0\n let timer: TimerHandle | null = null\n let cancelled = false\n\n signal.addEventListener(\"abort\", () => {\n cancelled = true\n if (timer !== null) env.clearTimeout(timer)\n })\n\n dispatch({ type: \"DETECT_START\", atMs: startedAt })\n\n const tick = () => {\n if (cancelled) return\n timer = null\n\n const probe = env.probeGrist()\n if (probe !== null) {\n if (probe.embedded) {\n dispatch({ type: \"DETECT_AVAILABLE\", atMs: env.now() })\n } else {\n dispatch({ type: \"NOT_EMBEDDED\", atMs: env.now() })\n }\n return\n }\n\n attempts += 1\n dispatch({ type: \"DETECT_TICK\", attempts, atMs: env.now() })\n\n const elapsed = env.now() - startedAt\n if (elapsed >= budgetMs) {\n dispatch({ type: \"DETECT_TIMEOUT\", attempts, atMs: env.now() })\n return\n }\n\n const next = sequence[Math.min(attempts - 1, sequence.length - 1)] ?? 1000\n const remaining = budgetMs - elapsed\n timer = env.setTimeout(tick, Math.max(0, Math.min(next, remaining)))\n }\n\n // Probe immediately at t=0 so widgets where grist is already global don't\n // wait for the first interval.\n tick()\n\n return {\n cancel() {\n cancelled = true\n if (timer !== null) {\n env.clearTimeout(timer)\n timer = null\n }\n },\n }\n}\n","/**\n * Negotiate effect — issue `grist.ready(payload)` race-d against a timeout\n * and an external `AbortSignal`.\n *\n * Dispatches:\n * - NEGOTIATE_START\n * - NEGOTIATE_SUCCESS (grist.ready resolved AND `docApi` is present)\n * - NEGOTIATE_FAIL (reason: ready_failed | ready_timeout | manual_terminate)\n *\n * The effect never throws to the caller. Aborts before resolution silently\n * stop dispatching.\n */\n\nimport type { GristEnvironment, GristLike } from \"../environment\"\nimport type { GristAction } from \"../actions\"\nimport type { GristReadyOptions, GristRequiredAccess } from \"../../../types\"\nimport type { GristTerminationReason } from \"../types\"\n\nexport type NegotiateOptions = {\n /** Max ms to wait for `grist.ready` to resolve. */\n timeoutMs?: number\n /**\n * Custom implementation of `grist.ready(payload)`. Defaults to calling\n * `grist.ready` directly via the env. Production callers (the provider)\n * inject a wrapper that routes through `ensureGristReady()` so the\n * page-level singleton dedupes concurrent ready calls.\n */\n readyImpl?: (payload: GristReadyOptions) => Promise<void> | void\n}\n\nexport const DEFAULT_NEGOTIATE_TIMEOUT_MS = 30_000\n\nexport type NegotiateHandle = {\n cancel(): void\n}\n\nexport function startNegotiateEffect(\n env: GristEnvironment,\n dispatch: (action: GristAction) => void,\n signal: AbortSignal,\n payload: GristReadyOptions,\n options: NegotiateOptions = {}\n): NegotiateHandle {\n const timeoutMs = options.timeoutMs ?? DEFAULT_NEGOTIATE_TIMEOUT_MS\n const access: GristRequiredAccess = payload.requiredAccess ?? \"read table\"\n let settled = false\n let timer: ReturnType<GristEnvironment[\"setTimeout\"]> | null = null\n\n const settle = (next: () => void) => {\n if (settled) return\n settled = true\n if (timer !== null) env.clearTimeout(timer)\n if (signal.aborted) return\n next()\n }\n\n dispatch({ type: \"NEGOTIATE_START\", access, atMs: env.now() })\n\n const grist = env.getGrist()\n if (!grist) {\n settle(() =>\n dispatch({\n type: \"NEGOTIATE_FAIL\",\n reason: { kind: \"ready_failed\", message: \"grist global missing at negotiate\" },\n atMs: env.now(),\n })\n )\n return { cancel: () => settle(() => {}) }\n }\n\n // Schedule timeout first; ready() may resolve synchronously and trigger\n // `settle` before this fires.\n timer = env.setTimeout(() => {\n if (settled) return\n settle(() =>\n dispatch({\n type: \"NEGOTIATE_FAIL\",\n reason: { kind: \"ready_timeout\", afterMs: timeoutMs },\n atMs: env.now(),\n })\n )\n }, timeoutMs)\n\n const handleSuccess = (g: GristLike) => {\n if (!g.docApi) {\n dispatch({\n type: \"NEGOTIATE_FAIL\",\n reason: { kind: \"ready_failed\", message: \"grist.docApi missing after ready\" },\n atMs: env.now(),\n })\n return\n }\n dispatch({\n type: \"NEGOTIATE_SUCCESS\",\n access,\n grantedLevel: access, // host doesn't report effective level; widen later via authz events\n atMs: env.now(),\n })\n }\n\n const handleFailure = (err: unknown) => {\n const message = err instanceof Error ? err.message : String(err)\n const reason: GristTerminationReason = { kind: \"ready_failed\", message }\n dispatch({ type: \"NEGOTIATE_FAIL\", reason, atMs: env.now() })\n }\n\n const readyImpl = options.readyImpl ?? ((p) => grist.ready(p))\n try {\n const result = readyImpl(payload)\n if (result && typeof (result as Promise<void>).then === \"function\") {\n ;(result as Promise<void>).then(\n () => settle(() => handleSuccess(env.getGrist() ?? grist)),\n (err) => settle(() => handleFailure(err))\n )\n } else {\n settle(() => handleSuccess(env.getGrist() ?? grist))\n }\n } catch (err) {\n settle(() => handleFailure(err))\n }\n\n signal.addEventListener(\"abort\", () => settle(() => {}))\n\n return { cancel: () => settle(() => {}) }\n}\n","/**\n * Module-level subscription manager for Grist's `on*` events.\n *\n * Why this exists: `grist.onRecord`, `onRecords`, `onOptions`, and `onNewRecord`\n * are add-only — there is no `off`. Subscribing in every hook instance leaks\n * handlers for the page lifetime. This module subscribes to each Grist event\n * **at most once** and fans out to React listeners with proper teardown.\n *\n * Last-known values are cached so late subscribers immediately receive the\n * current state (analogous to a BehaviorSubject).\n *\n * Fixed-defaults contract\n * -----------------------\n * The underlying `grist.onRecord` / `onRecords` calls accept a\n * `FetchSelectedOptions` parameter (e.g. `keepEncoded`, `format`), but\n * because we bind **once** at the first subscribe, those options would be\n * \"first-hook-wins\" across the page — a subtle footgun for agents.\n *\n * This module therefore binds with Grist's **public defaults** and does not\n * accept per-subscriber options:\n * - `onRecord` → decoded rows (`keepEncoded: false`)\n * - `onRecords` → decoded rows (`format: \"rows\"`, `keepEncoded: false`)\n *\n * If you need encoded values, use the one-shot readers\n * (`useGrist().fetchSelectedTable({ keepEncoded: true })`) instead of\n * a subscription — that call-site controls its own options.\n */\n\nimport { normalizeWidgetInteraction } from \"../helpers/grist-widget-interaction\"\nimport type { GristWidgetColumnMap, GristWidgetInteraction } from \"../types\"\n\ntype Listener<T> = (value: T) => void\n\nclass GristEvent<T> {\n private listeners = new Set<Listener<T>>()\n private hasValue = false\n private last: T | undefined\n private bind: (() => void) | null = null\n\n constructor(private readonly bindOnce: (emit: (value: T) => void) => void) {}\n\n subscribe(listener: Listener<T>): () => void {\n this.listeners.add(listener)\n if (!this.bind) {\n this.bind = () => {\n // Mark as bound regardless of throw, so we don't retry every render.\n this.bind = () => {}\n try {\n this.bindOnce((value) => {\n this.hasValue = true\n this.last = value\n for (const l of this.listeners) l(value)\n })\n } catch (err) {\n if (typeof console !== \"undefined\") {\n console.error(\"[lib/grist] failed to subscribe to Grist event:\", err)\n }\n }\n }\n this.bind()\n }\n if (this.hasValue && this.last !== undefined) {\n listener(this.last)\n }\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n /** Last cached value (or `undefined` if no event has fired yet). */\n peek(): T | undefined {\n return this.last\n }\n\n /** True once at least one event has fired. */\n get ready(): boolean {\n return this.hasValue\n }\n\n /**\n * Test helper: fan out a payload without calling `grist.on*`.\n * Used to simulate hosts that reuse one record object and mutate it in place.\n */\n deliverForTests(value: T): void {\n this.hasValue = true\n this.last = value\n for (const l of this.listeners) l(value)\n }\n\n /**\n * Test helper: forget the bound state and cached value. Lets a test swap\n * `window.grist` (e.g. via the emulator's `dispose()` + `createGristEmulator()`)\n * and re-bind cleanly on the next subscribe.\n */\n _resetForTests(): void {\n this.listeners.clear()\n this.hasValue = false\n this.last = undefined\n this.bind = null\n }\n}\n\nexport type GristRecordPayload = {\n record: Record<string, unknown> | null\n mappings: GristWidgetColumnMap | null\n}\n\nexport type GristRecordsPayload = {\n records: Record<string, unknown>[]\n mappings: GristWidgetColumnMap | null\n}\n\nexport type GristOptionsPayload = {\n options: Record<string, unknown> | null\n interaction: GristWidgetInteraction | null\n}\n\nexport type GristNewRecordPayload = {\n mappings: GristWidgetColumnMap | null\n}\n\n/**\n * The singletons. These are lazy: nothing is registered with `grist` until\n * the first `subscribe()` call.\n */\ntype GristHostMessage = {\n tableId?: string\n rowId?: number | \"new\"\n dataChange?: boolean\n mappingsChange?: boolean\n}\n\nexport const recordEvent = new GristEvent<GristRecordPayload>((emit) => {\n const deliver = (record: Record<string, unknown> | null, mappings: GristWidgetColumnMap | null) => {\n emit({ record, mappings })\n }\n\n // Pin `keepEncoded: false` so mapped records contain JS-native values for\n // widget code instead of raw cell tuples.\n grist.onRecord(\n (record, mappings) => {\n deliver(record, (mappings as GristWidgetColumnMap | null) ?? null)\n },\n { keepEncoded: false }\n )\n\n // Mirror grist-plugin-api's `onRecord` message handler: Grist's RecordNotifier\n // posts `{ rowId, dataChange: false }` on cursor moves. `onRecord` should\n // handle that, but refetch here when `rowId` changes so widgets never stick on\n // the first row if the callback path is skipped or reordered.\n const fetchSelectedRecord = grist.fetchSelectedRecord ?? grist.docApi?.fetchSelectedRecord\n if (typeof grist.on !== \"function\" || typeof fetchSelectedRecord !== \"function\") {\n return\n }\n let lastRowId: number | undefined\n grist.on(\"message\", async (msg: unknown) => {\n if (!msg || typeof msg !== \"object\") return\n const host = msg as GristHostMessage\n if (!host.tableId || typeof host.rowId !== \"number\") return\n if (host.rowId === lastRowId) return\n lastRowId = host.rowId\n try {\n const record = await fetchSelectedRecord(host.rowId, { keepEncoded: false })\n deliver(record, recordEvent.peek()?.mappings ?? null)\n } catch (err) {\n if (typeof console !== \"undefined\") {\n console.error(\"[grist-widget-sdk] fetchSelectedRecord on cursor message failed:\", err)\n }\n }\n })\n})\n\nexport const recordsEvent = new GristEvent<GristRecordsPayload>((emit) => {\n // Pin `format: \"rows\"` + `keepEncoded: false` so callers always receive\n // row-shaped decoded objects. (GristView would otherwise default to\n // `format: \"columns\"` + `keepEncoded: true`.)\n grist.onRecords(\n (records, mappings) => {\n emit({ records, mappings: (mappings as GristWidgetColumnMap | null) ?? null })\n },\n { keepEncoded: false, format: \"rows\" }\n )\n})\n\nexport const optionsEvent = new GristEvent<GristOptionsPayload>((emit) => {\n grist.onOptions((options, interaction) => {\n const normalized = normalizeWidgetInteraction(\n (interaction as GristWidgetInteraction | null) ?? null\n )\n emit({\n options: options ? { ...options } : null,\n interaction: normalized,\n })\n })\n})\n\nexport const newRecordEvent = new GristEvent<GristNewRecordPayload>((emit) => {\n if (typeof grist.onNewRecord !== \"function\") return\n grist.onNewRecord((mappings) => {\n emit({ mappings: (mappings as GristWidgetColumnMap | null) ?? null })\n })\n})\n\n/**\n * Test-only: reset every event singleton. Call between tests when swapping\n * `window.grist`. Production code never imports this.\n */\nexport function resetGristEventsForTests(): void {\n recordEvent._resetForTests()\n recordsEvent._resetForTests()\n optionsEvent._resetForTests()\n newRecordEvent._resetForTests()\n}\n\n/** Vitest-only: push a record payload through {@link recordEvent} subscribers. */\nexport function deliverRecordForTests(payload: GristRecordPayload): void {\n recordEvent.deliverForTests(payload)\n}\n","/**\n * Subscriptions effect — bind Grist event streams once and feed the handshake\n * machine with generation-stamped, hash-deduplicated dispatches.\n *\n * Why a dedicated effect\n * ----------------------\n * The SDK already has a {@link \"../../subscriptions\"} module that owns the\n * one-time binding to `grist.on*` and the BehaviorSubject-style cache. We do\n * NOT re-bind here — instead, we install a single listener per stream that\n * forwards into the handshake reducer.\n *\n * Generation discipline: every dispatched action carries the CURRENT manager\n * generation read at the moment the event arrives. The reducer enforces\n * `action.generation >= snapshot.generation`, so events arriving after a\n * `reload()` / `restart()` that bumped generation are dropped automatically.\n *\n * Hash: payloads are reduced to a compact, deterministic string so duplicates\n * (e.g. emulator triple-replay of initial state) become no-ops at the reducer.\n */\n\nimport type { GristAction, GristSyncStream } from \"../actions\"\nimport { parseGristRequiredAccess } from \"../access\"\nimport type { GristGeneration } from \"../types\"\nimport {\n newRecordEvent,\n optionsEvent,\n recordEvent,\n recordsEvent,\n} from \"../../subscriptions\"\n\nexport type SubscriptionsHandle = {\n cancel(): void\n}\n\n/**\n * Pluggable binder type. The default {@link defaultSubscriptionsBinder}\n * subscribes to the SDK's singleton {@link GristEvent} instances. Tests can\n * supply a stub that never touches the real `grist` global.\n */\nexport type SubscriptionsBinder = (ctx: SubscriptionsContext) => SubscriptionsHandle\n\nexport type SubscriptionsContext = {\n dispatch: (action: GristAction) => void\n /**\n * Snapshot generation provider. Must be read lazily (inside the callback)\n * because `generation` is monotone but mutates over the lifetime of the\n * subscription.\n */\n getGeneration: () => GristGeneration\n /** Hook for the mapping effect: receive payloads in arrival order. */\n onRecordPayload?: (mappings: Record<string, unknown> | null | undefined) => void\n onRecordsPayload?: (mappings: Record<string, unknown> | null | undefined) => void\n onOptionsPayload?: (options: Record<string, unknown> | null) => void\n onNewRecordPayload?: (mappings: Record<string, unknown> | null | undefined) => void\n}\n\nexport const bindSubscriptions: SubscriptionsBinder = defaultSubscriptionsBinder\n\nexport function defaultSubscriptionsBinder(ctx: SubscriptionsContext): SubscriptionsHandle {\n const offs: Array<() => void> = []\n\n offs.push(\n recordEvent.subscribe((payload) => {\n const hash = quickHash(\"record\", payload)\n dispatchStream(ctx, \"record\", hash)\n ctx.onRecordPayload?.(payload.mappings ?? null)\n })\n )\n\n offs.push(\n recordsEvent.subscribe((payload) => {\n const hash = quickHash(\"records\", payload)\n dispatchStream(ctx, \"records\", hash)\n ctx.onRecordsPayload?.(payload.mappings ?? null)\n })\n )\n\n offs.push(\n optionsEvent.subscribe((payload) => {\n const hash = quickHash(\"options\", payload)\n dispatchStream(ctx, \"options\", hash)\n const level = parseGristRequiredAccess(payload.interaction?.access_level)\n if (level !== null) {\n ctx.dispatch({\n type: \"AUTHZ_REPORT\",\n level,\n atMs: Date.now(),\n generation: ctx.getGeneration(),\n })\n }\n ctx.onOptionsPayload?.(payload.options ?? null)\n })\n )\n\n offs.push(\n newRecordEvent.subscribe((payload) => {\n const hash = quickHash(\"newRecord\", payload)\n dispatchStream(ctx, \"newRecord\", hash)\n ctx.onNewRecordPayload?.(payload.mappings ?? null)\n })\n )\n\n return {\n cancel() {\n for (const off of offs.splice(0)) off()\n },\n }\n}\n\n/**\n * No-op binder for tests that don't care about event streams. Returned handle's\n * `cancel()` is a no-op. Use {@link defaultSubscriptionsBinder} in production.\n */\nexport const noopSubscriptionsBinder: SubscriptionsBinder = () => ({\n cancel: () => {},\n})\n\nfunction dispatchStream(\n ctx: SubscriptionsContext,\n stream: GristSyncStream,\n payloadHash: string\n): void {\n ctx.dispatch({\n type: \"STREAM_RECEIVED\",\n stream,\n payloadHash,\n atMs: Date.now(),\n generation: ctx.getGeneration(),\n })\n}\n\n/**\n * Deterministic, low-cost hash of an event payload.\n *\n * We do NOT need cryptographic strength — only equality on identical inputs\n * for idempotence. A short, stable serialization is enough.\n */\nexport function quickHash(kind: string, payload: unknown): string {\n return `${kind}::${stableSerialize(payload)}`\n}\n\nfunction stableSerialize(value: unknown): string {\n if (value === null) return \"null\"\n if (value === undefined) return \"undefined\"\n const t = typeof value\n if (t === \"number\" || t === \"string\" || t === \"boolean\") return JSON.stringify(value)\n if (Array.isArray(value)) {\n return `[${value.map(stableSerialize).join(\",\")}]`\n }\n if (t === \"object\") {\n const obj = value as Record<string, unknown>\n const keys = Object.keys(obj).sort()\n const body = keys.map((k) => `${JSON.stringify(k)}:${stableSerialize(obj[k])}`).join(\",\")\n return `{${body}}`\n }\n return String(value)\n}\n","/**\n * Mappings effect — feed column-mapping payloads into the reducer from the\n * three Grist sources (`sectionApi.mappings()`, `onRecord`, `onRecords`,\n * `onNewRecord`) and trigger the mapping timeout if nothing arrives in time.\n *\n * Inputs:\n * - `declared` — `columns` from the provider options.\n * - `getGeneration()` — current snapshot generation (for stale-drop).\n * - `getGrist()` — environment accessor to `grist.sectionApi.mappings()`.\n *\n * Outputs:\n * - `MAPPING_DECLARE` (once at start when `declared.length > 0`)\n * - `MAPPING_REPORT` (one per source payload received)\n * - `MAPPING_TIMEOUT` (if no payload after `timeoutMs`)\n *\n * The effect does NOT subscribe to grist events directly — it consumes them\n * via the {@link SubscriptionsContext} payload callbacks. This keeps the\n * single-binding contract of `subscriptions.ts` intact (one `grist.onRecord`\n * binding per page).\n */\n\nimport type { GristEnvironment } from \"../environment\"\nimport type { GristAction } from \"../actions\"\nimport type { GristColumnsToMap, GristWidgetColumnMap } from \"../../../types\"\nimport type { GristGeneration } from \"../types\"\n\nexport type MappingsOptions = {\n /**\n * Time after `MAPPING_DECLARE` before falling back to `unreported` state.\n * Default 5 000 ms.\n */\n timeoutMs?: number\n /**\n * If true, dispatch `MAPPING_INVALIDATE` whenever a payload differs from\n * the last applied mappings. Default false — graceful invalidation requires\n * a `mappingsChange: true` envelope flag the SDK doesn't currently surface,\n * so we leave it opt-in for tests.\n */\n invalidateOnDiff?: boolean\n}\n\nexport const DEFAULT_MAPPING_TIMEOUT_MS = 5_000\n\nexport type MappingsHandle = {\n /** Ingest a payload from `onRecord` / `onRecords` / `onNewRecord`. */\n ingestStreamPayload(\n source: \"stream_record\" | \"stream_records\" | \"stream_new_record\",\n payload: unknown\n ): void\n /** Force a re-fetch of `sectionApi.mappings()` (e.g. on link recovery). */\n refetchSectionApi(): Promise<void>\n /** Cancel all pending timers. */\n cancel(): void\n}\n\n/**\n * Start the mapping effect. Returns a handle the manager wires into the\n * subscriptions effect's `on*Payload` callbacks.\n *\n * The effect is a no-op when `declared.length === 0` (the reducer's\n * `MAPPING_DECLARE` action turns it into `not_declared`).\n */\nexport function startMappingsEffect(\n env: GristEnvironment,\n dispatch: (action: GristAction) => void,\n signal: AbortSignal,\n declared: GristColumnsToMap,\n getGeneration: () => GristGeneration,\n options: MappingsOptions = {}\n): MappingsHandle {\n let timeoutHandle: ReturnType<GristEnvironment[\"setTimeout\"]> | null = null\n let cancelled = false\n\n const startMs = env.now()\n dispatch({ type: \"MAPPING_DECLARE\", declared, atMs: startMs, generation: getGeneration() })\n\n // No declaration → no timeout, no section_api fetch, no further work.\n if (declared.length === 0) {\n return {\n ingestStreamPayload: () => {},\n refetchSectionApi: async () => {},\n cancel: () => {},\n }\n }\n\n // Arm the unreported timeout.\n const timeoutMs = options.timeoutMs ?? DEFAULT_MAPPING_TIMEOUT_MS\n timeoutHandle = env.setTimeout(() => {\n if (cancelled || signal.aborted) return\n dispatch({ type: \"MAPPING_TIMEOUT\", atMs: env.now(), generation: getGeneration() })\n }, timeoutMs)\n\n signal.addEventListener(\"abort\", () => {\n cancelled = true\n if (timeoutHandle !== null) env.clearTimeout(timeoutHandle)\n })\n\n const ingestPayload = (\n source: \"section_api\" | \"stream_record\" | \"stream_records\" | \"stream_new_record\",\n raw: unknown\n ) => {\n if (cancelled || signal.aborted) return\n const payload = coerceMappingsPayload(raw)\n dispatch({\n type: \"MAPPING_REPORT\",\n source,\n payload,\n atMs: env.now(),\n generation: getGeneration(),\n })\n }\n\n // Kick off `sectionApi.mappings()` once.\n const refetchSectionApi = async () => {\n if (cancelled || signal.aborted) return\n const grist = env.getGrist()\n const api = grist?.sectionApi\n if (!api || typeof api.mappings !== \"function\") return\n try {\n const payload = await api.mappings()\n ingestPayload(\"section_api\", payload)\n } catch {\n ingestPayload(\"section_api\", null)\n }\n }\n void refetchSectionApi()\n\n return {\n ingestStreamPayload: (source, payload) => ingestPayload(source, payload),\n refetchSectionApi,\n cancel() {\n cancelled = true\n if (timeoutHandle !== null) env.clearTimeout(timeoutHandle)\n },\n }\n}\n\nfunction coerceMappingsPayload(raw: unknown): GristWidgetColumnMap | null {\n if (raw === null || raw === undefined) return null\n if (typeof raw !== \"object\") return null\n return raw as GristWidgetColumnMap\n}\n","/**\n * Heartbeat effect — periodically verify the RPC channel is alive.\n *\n * Strategy\n * --------\n * 1. Schedule a ping every `intervalMs` (default 30 s).\n * 2. The ping calls a cheap RPC (default `grist.docApi.getDocName()`).\n * 3. Success → `HEARTBEAT_OK`. Failure / timeout → `HEARTBEAT_FAIL`.\n * 4. Any externally-observed RPC success (the caller invokes\n * {@link HeartbeatHandle.recordRpcSuccess}) coalesces with the heartbeat\n * and reschedules the next ping — we don't burn a request when natural\n * traffic already proves the link.\n * 5. Tab hidden? Pause via `env.onVisibilityChange`. Resume on `visible`.\n *\n * The effect is **purely an observer**: it never mutates application state\n * directly — it only dispatches actions the reducer consumes.\n */\n\nimport type { GristEnvironment, TimerHandle } from \"../environment\"\nimport type { GristAction } from \"../actions\"\n\nexport type HeartbeatOptions = {\n /** How often to issue a probe when no natural RPC traffic occurred. */\n intervalMs?: number\n /** Max time to wait for the probe before counting it as a failure. */\n pingTimeoutMs?: number\n /** If true, pause the heartbeat when the document becomes hidden. */\n pauseWhenHidden?: boolean\n /**\n * Probe used when the interval elapses. Defaults to\n * `() => env.getGrist().docApi.getDocName()`. Tests pass a controlled stub.\n */\n probe?: () => Promise<unknown>\n}\n\nexport const DEFAULT_HEARTBEAT_INTERVAL_MS = 30_000\nexport const DEFAULT_HEARTBEAT_PING_TIMEOUT_MS = 10_000\n\nexport type HeartbeatHandle = {\n /** Stop scheduling and cancel any pending probe. Idempotent. */\n cancel(): void\n /**\n * Coalesce: tell the heartbeat that an unrelated RPC just succeeded. The\n * heartbeat treats it as a free `HEARTBEAT_OK` and pushes the next probe\n * out by a full interval.\n */\n recordRpcSuccess(): void\n /**\n * Coalesce: an unrelated RPC failed. The heartbeat dispatches\n * `HEARTBEAT_FAIL` without firing its own probe, so the link signal\n * degrades immediately rather than waiting for the interval.\n */\n recordRpcFailure(): void\n /** Force a probe now (e.g. on `online` event). */\n pingNow(): void\n}\n\nexport function startHeartbeatEffect(\n env: GristEnvironment,\n dispatch: (action: GristAction) => void,\n signal: AbortSignal,\n options: HeartbeatOptions = {}\n): HeartbeatHandle {\n const intervalMs = options.intervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS\n const pingTimeoutMs = options.pingTimeoutMs ?? DEFAULT_HEARTBEAT_PING_TIMEOUT_MS\n const pauseWhenHidden = options.pauseWhenHidden ?? true\n const probe = options.probe ?? defaultProbe(env)\n\n let cancelled = false\n let paused = false\n let intervalTimer: TimerHandle | null = null\n let inFlight = false\n let inFlightTimeoutTimer: TimerHandle | null = null\n\n const clearInterval = () => {\n if (intervalTimer !== null) {\n env.clearTimeout(intervalTimer)\n intervalTimer = null\n }\n }\n const clearInFlightTimeout = () => {\n if (inFlightTimeoutTimer !== null) {\n env.clearTimeout(inFlightTimeoutTimer)\n inFlightTimeoutTimer = null\n }\n }\n\n const scheduleNext = (delay = intervalMs) => {\n clearInterval()\n if (cancelled || paused) return\n intervalTimer = env.setTimeout(ping, delay)\n }\n\n const ping = () => {\n if (cancelled || paused) return\n intervalTimer = null\n if (inFlight) {\n // A previous probe still in flight; let it resolve before scheduling.\n return\n }\n inFlight = true\n\n // Timeout guard.\n inFlightTimeoutTimer = env.setTimeout(() => {\n if (!inFlight) return\n inFlight = false\n clearInFlightTimeout()\n if (!cancelled) {\n dispatch({ type: \"HEARTBEAT_FAIL\", atMs: env.now() })\n scheduleNext()\n }\n }, pingTimeoutMs)\n\n const handleOk = () => {\n if (!inFlight) return\n inFlight = false\n clearInFlightTimeout()\n if (cancelled) return\n dispatch({ type: \"HEARTBEAT_OK\", atMs: env.now() })\n scheduleNext()\n }\n const handleFail = () => {\n if (!inFlight) return\n inFlight = false\n clearInFlightTimeout()\n if (cancelled) return\n dispatch({ type: \"HEARTBEAT_FAIL\", atMs: env.now() })\n scheduleNext()\n }\n\n // Call probe synchronously so we collapse one microtask round. If it\n // throws synchronously or returns a non-thenable, settle immediately.\n let result: unknown\n try {\n result = probe()\n } catch {\n handleFail()\n return\n }\n if (\n result &&\n typeof (result as { then?: unknown }).then === \"function\"\n ) {\n ;(result as Promise<unknown>).then(handleOk, handleFail)\n } else {\n handleOk()\n }\n }\n\n // Visibility wiring.\n const offVisibility =\n pauseWhenHidden && env.onVisibilityChange\n ? env.onVisibilityChange((visible) => {\n if (cancelled) return\n if (visible) {\n if (paused) {\n paused = false\n // Refresh immediately on resume — a hidden tab might have\n // missed a long stale window.\n ping()\n }\n } else {\n paused = true\n clearInterval()\n // Note: an in-flight probe is allowed to settle naturally; we\n // just don't schedule another one.\n }\n })\n : null\n\n // Online recovery — when the network reports it's back, ping immediately.\n const offOnline =\n env.onOnline?.(() => {\n if (cancelled || paused) return\n ping()\n }) ?? null\n\n signal.addEventListener(\"abort\", () => {\n cancelled = true\n clearInterval()\n clearInFlightTimeout()\n inFlight = false\n offVisibility?.()\n offOnline?.()\n })\n\n // Boot: first probe after `intervalMs`. We don't ping at t=0 because the\n // very transition that started the heartbeat (e.g. NEGOTIATE_SUCCESS) just\n // proved the link is alive.\n scheduleNext()\n\n return {\n cancel() {\n cancelled = true\n clearInterval()\n clearInFlightTimeout()\n inFlight = false\n offVisibility?.()\n offOnline?.()\n },\n recordRpcSuccess() {\n if (cancelled || paused) return\n dispatch({ type: \"RPC_SUCCESS\", atMs: env.now() })\n scheduleNext()\n },\n recordRpcFailure() {\n if (cancelled || paused) return\n dispatch({ type: \"RPC_FAILURE\", atMs: env.now(), kind: \"other\" })\n // Don't reschedule — a real failure should keep the interval close so\n // we re-probe quickly to confirm.\n scheduleNext(Math.min(intervalMs, 1_000))\n },\n pingNow() {\n if (cancelled) return\n ping()\n },\n }\n}\n\nfunction defaultProbe(env: GristEnvironment): () => Promise<unknown> {\n return async () => {\n const g = env.getGrist()\n if (!g) throw new Error(\"grist global missing\")\n const docApi = g.docApi\n if (!docApi || typeof docApi.getDocName !== \"function\") {\n throw new Error(\"grist.docApi.getDocName unavailable\")\n }\n return docApi.getDocName()\n }\n}\n","/**\n * Re-apply the cached `grist.onOptions` interaction after `reload()`.\n *\n * `reload()` re-runs `grist.ready` (optimistic grant) but Grist often does not\n * send a fresh `onOptions`. The subscription singleton still holds the last\n * `access_level`, which must be checked once the handshake is `online` again.\n *\n * Only runs after `reload()` — not on the initial connect — so a stale\n * pre-`ready` cache cannot deny a first successful handshake.\n */\n\nimport { isAccessSufficient, parseGristRequiredAccess } from \"./access\"\nimport type { GristAction } from \"./actions\"\nimport type { GristEnvironment } from \"./environment\"\nimport type { GristWidgetSnapshot } from \"./types\"\nimport { optionsEvent } from \"../subscriptions\"\n\nexport function denyAuthzFromCachedOptionsIfInsufficient(\n snapshot: GristWidgetSnapshot,\n dispatch: (action: GristAction) => void,\n env: GristEnvironment\n): void {\n if (snapshot.lifecycle.phase !== \"online\") return\n if (snapshot.authz.state === \"denied\") return\n\n const payload = optionsEvent.peek()\n const level = parseGristRequiredAccess(payload?.interaction?.access_level)\n if (level === null) return\n\n const declared = snapshot.authz.declared\n if (isAccessSufficient(level, declared)) return\n\n dispatch({\n type: \"AUTHZ_REPORT\",\n level,\n atMs: env.now(),\n generation: snapshot.generation,\n })\n}\n","/**\n * Environment abstraction for the handshake effects layer.\n *\n * Why an abstraction\n * ------------------\n * The detect / negotiate / heartbeat effects need access to:\n * - the `grist` global (or absence thereof),\n * - `window.self !== window.top` to detect iframe embedding,\n * - timers (`setTimeout`, `clearTimeout`),\n * - the wall clock (`performance.now()` or `Date.now()`),\n * - `navigator.connection?.effectiveType` for adaptive policy.\n *\n * Putting these behind a small interface lets us test the manager and effects\n * **without touching `window`**, using deterministic fake timers and stubbed\n * detectors / negotiators.\n *\n * Production code calls {@link createBrowserEnvironment()} which returns an\n * adapter against `globalThis`. Tests pass {@link createTestEnvironment} or a\n * hand-rolled stub.\n */\n\nimport type { GristDocApi, GristReadyOptions, GristWidgetColumnMap } from \"../../types\"\n\n// ---------------------------------------------------------------------------\n// Public env interface\n// ---------------------------------------------------------------------------\n\nexport type GristEnvironment = {\n /** Wall-clock ms (monotonic preferred but not required). */\n now(): number\n /** Schedule a callback. */\n setTimeout(cb: () => void, ms: number): TimerHandle\n /** Cancel a timer. */\n clearTimeout(handle: TimerHandle): void\n\n /**\n * Probe whether the `grist` global is present in this realm.\n * Returns `{ embedded }` when the global exists; `null` otherwise.\n */\n probeGrist(): { embedded: boolean } | null\n\n /**\n * Snapshot of the `grist` global. Effects use this once detection has\n * succeeded; callers must NOT cache the result across `restart()`.\n */\n getGrist(): GristLike | null\n\n /** Adaptive detection budget hint (ms). `null` if unknown. */\n effectiveTypeHint(): EffectiveTypeHint | null\n\n /** Add a listener for `visibilitychange` / `online` / `focus`. Returns cleanup. */\n onVisibilityChange?(listener: (visible: boolean) => void): () => void\n onOnline?(listener: () => void): () => void\n}\n\nexport type TimerHandle = ReturnType<typeof setTimeout> | number | { __opaque: true }\n\nexport type EffectiveTypeHint = \"slow-2g\" | \"2g\" | \"3g\" | \"4g\" | \"5g\"\n\n/**\n * Subset of `window.grist` actually used by handshake effects. Mirrors the\n * declared shape in `grist-global.d.ts` but only the pieces we need.\n */\nexport type GristLike = {\n ready: (options?: GristReadyOptions) => Promise<void> | void\n docApi: GristDocApi | null | undefined\n onRecord?: (\n cb: (\n record: Record<string, unknown> | null,\n mappings?: GristWidgetColumnMap | null\n ) => void,\n options?: { keepEncoded?: boolean }\n ) => void\n onRecords?: (\n cb: (\n records: Record<string, unknown>[],\n mappings?: GristWidgetColumnMap | null\n ) => void,\n options?: { keepEncoded?: boolean; format?: string }\n ) => void\n onOptions?: (\n cb: (options: Record<string, unknown> | null, interaction: unknown) => void\n ) => void\n onNewRecord?: (cb: (mappings: GristWidgetColumnMap | null) => void) => void\n sectionApi?: {\n mappings: () => Promise<GristWidgetColumnMap | null>\n }\n}\n\n// ---------------------------------------------------------------------------\n// Browser environment factory\n// ---------------------------------------------------------------------------\n\nexport function createBrowserEnvironment(): GristEnvironment {\n return {\n now: () => (typeof performance !== \"undefined\" ? performance.now() : Date.now()),\n setTimeout: (cb, ms) => globalThis.setTimeout(cb, ms),\n clearTimeout: (h) => globalThis.clearTimeout(h as ReturnType<typeof setTimeout>),\n\n probeGrist() {\n if (typeof globalThis === \"undefined\") return null\n const g = (globalThis as { grist?: unknown }).grist\n if (typeof g === \"undefined\") return null\n const embedded =\n typeof window === \"undefined\" ? false : window.self !== window.top\n return { embedded }\n },\n\n getGrist() {\n const g = (globalThis as { grist?: GristLike }).grist\n return g ?? null\n },\n\n effectiveTypeHint() {\n if (typeof navigator === \"undefined\") return null\n const conn = (navigator as { connection?: { effectiveType?: string } }).connection\n const t = conn?.effectiveType\n if (t === \"slow-2g\" || t === \"2g\" || t === \"3g\" || t === \"4g\" || t === \"5g\") return t\n return null\n },\n\n onVisibilityChange(listener) {\n if (typeof document === \"undefined\") return () => {}\n const handler = () => listener(document.visibilityState === \"visible\")\n document.addEventListener(\"visibilitychange\", handler)\n return () => document.removeEventListener(\"visibilitychange\", handler)\n },\n\n onOnline(listener) {\n if (typeof window === \"undefined\") return () => {}\n const handler = () => listener()\n window.addEventListener(\"online\", handler)\n return () => window.removeEventListener(\"online\", handler)\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Test environment factory — fake timers, stubbed grist\n// ---------------------------------------------------------------------------\n\nexport type TestEnvironmentOptions = {\n /**\n * Provider for the `grist` stub. Called every `probeGrist()` / `getGrist()`.\n * Returning `null` simulates \"script not loaded yet\".\n */\n grist?: () => GristLike | null\n embedded?: () => boolean\n effectiveType?: EffectiveTypeHint\n}\n\nexport type TestEnvironment = GristEnvironment & {\n /** Manually advance virtual time. Fires due timers in order. */\n advance(ms: number): void\n /** Currently scheduled timers. */\n pendingTimers(): readonly { dueAt: number; cb: () => void }[]\n /** Trigger visibilitychange listeners. */\n emitVisibility(visible: boolean): void\n /** Trigger online listeners. */\n emitOnline(): void\n}\n\nexport function createTestEnvironment(opts: TestEnvironmentOptions = {}): TestEnvironment {\n let clock = 0\n const timers: Array<{ id: number; dueAt: number; cb: () => void }> = []\n let nextId = 1\n const visListeners = new Set<(v: boolean) => void>()\n const onlineListeners = new Set<() => void>()\n\n function advance(ms: number) {\n const target = clock + ms\n while (true) {\n timers.sort((a, b) => a.dueAt - b.dueAt)\n const due = timers.find((t) => t.dueAt <= target)\n if (!due) break\n timers.splice(timers.indexOf(due), 1)\n clock = due.dueAt\n due.cb()\n }\n clock = target\n }\n\n return {\n now: () => clock,\n setTimeout(cb, ms) {\n const id = nextId++\n timers.push({ id, dueAt: clock + ms, cb })\n return id as unknown as TimerHandle\n },\n clearTimeout(handle) {\n const id = handle as unknown as number\n const idx = timers.findIndex((t) => t.id === id)\n if (idx >= 0) timers.splice(idx, 1)\n },\n\n probeGrist() {\n const g = opts.grist?.() ?? null\n if (!g) return null\n const embedded = opts.embedded?.() ?? true\n return { embedded }\n },\n getGrist: () => opts.grist?.() ?? null,\n effectiveTypeHint: () => opts.effectiveType ?? null,\n\n onVisibilityChange(listener) {\n visListeners.add(listener)\n return () => visListeners.delete(listener)\n },\n onOnline(listener) {\n onlineListeners.add(listener)\n return () => onlineListeners.delete(listener)\n },\n\n advance,\n pendingTimers: () => timers.map((t) => ({ dueAt: t.dueAt, cb: t.cb })),\n emitVisibility(visible) {\n for (const l of visListeners) l(visible)\n },\n emitOnline() {\n for (const l of onlineListeners) l()\n },\n }\n}\n","/**\n * GristHandshakeManager — single owner of the handshake snapshot.\n *\n * Responsibilities\n * ----------------\n * 1. Hold the snapshot and the {@link GristReducerContext}.\n * 2. Run effects (detect → negotiate → subscriptions + mappings) in order.\n * 3. Bump generation on `reload()` / `restart()` and propagate cancellation\n * through a per-generation {@link AbortController}.\n * 4. Notify subscribers on each snapshot change (interface compatible with\n * React's `useSyncExternalStore`).\n *\n * The manager is a **class**, not a hook. React hooks subscribe to it via the\n * standard `subscribe` / `getSnapshot` pair so unit tests can drive the\n * manager directly with a virtual clock — no React needed.\n */\n\nimport {\n DEFAULT_REDUCER_CONFIG,\n createReducerContext,\n gristReducer,\n initialGristSnapshot,\n nextGeneration,\n type GristAction,\n type GristReducerContext,\n type GristWidgetSnapshot,\n type ReducerConfig,\n} from \"./index\"\nimport { startDetectEffect, type DetectHandle, type DetectOptions } from \"./effects/detect\"\nimport {\n startNegotiateEffect,\n type NegotiateHandle,\n type NegotiateOptions,\n} from \"./effects/negotiate\"\nimport {\n defaultSubscriptionsBinder,\n type SubscriptionsBinder,\n type SubscriptionsHandle,\n} from \"./effects/subscriptions\"\nimport {\n startMappingsEffect,\n type MappingsHandle,\n type MappingsOptions,\n} from \"./effects/mappings\"\nimport {\n startHeartbeatEffect,\n type HeartbeatHandle,\n type HeartbeatOptions,\n} from \"./effects/heartbeat\"\nimport { denyAuthzFromCachedOptionsIfInsufficient } from \"./authz-from-options-cache\"\nimport {\n createBrowserEnvironment,\n type GristEnvironment,\n} from \"./environment\"\nimport type { GristColumnsToMap, GristReadyOptions } from \"../../types\"\n\nexport type ManagerOptions = GristReadyOptions & {\n detect?: DetectOptions\n negotiate?: NegotiateOptions\n mappings?: MappingsOptions\n heartbeat?: HeartbeatOptions | false\n reducerConfig?: Partial<ReducerConfig>\n /**\n * Where to read `grist`, timers, and platform hints from. Defaults to a\n * browser adapter. Tests pass {@link createTestEnvironment}.\n */\n env?: GristEnvironment\n /**\n * Binder for grist event streams. Defaults to\n * {@link defaultSubscriptionsBinder} which wires the SDK's singleton\n * {@link \"../../subscriptions\"} module. Tests can pass `noopSubscriptionsBinder`\n * to avoid touching the real `grist` global.\n */\n subscriptionsBinder?: SubscriptionsBinder\n /**\n * Called when the manager catches an unexpected internal error.\n * Telemetry hook — does not affect reducer state.\n */\n onError?: (err: unknown, where: string) => void\n /**\n * Called from inside {@link ManagerControls.reload} BEFORE generation bump.\n * Production callers route `resetGristReadySingleton()` through here so\n * the page-level ready singleton is cleared and the next negotiate effect\n * issues a fresh `grist.ready` instead of re-using the cached promise.\n */\n onBeforeReload?: () => void\n}\n\nexport type ManagerControls = {\n /** Start the effects pipeline. Idempotent after `start()`. */\n start(): void\n /** Cancel all running effects and reset to `idle`. */\n stop(): void\n /**\n * Soft retry: bumps generation, cancels current effects, re-runs detect/\n * negotiate. Subscriptions are NOT re-bound — the underlying singletons\n * survive (and re-deliver cached values).\n */\n reload(): void\n /**\n * Hard reload of the host iframe. Browser-only — in the test env this is a\n * no-op. Production code may also call `window.location.reload()` directly.\n */\n restart(): void\n subscribe(listener: () => void): () => void\n getSnapshot(): GristWidgetSnapshot\n /**\n * Test/internal: inject an action directly. Used by integration tests that\n * want to simulate authz events, link failures, etc.\n */\n dispatch(action: GristAction): void\n /**\n * Coalesce: an external RPC succeeded — tell the heartbeat to skip the\n * next scheduled probe and reset the missed-pings counter. Returns\n * silently when the heartbeat is disabled.\n */\n recordRpcSuccess(): void\n /**\n * Coalesce: an external RPC failed — degrade the link signal immediately.\n * Returns silently when the heartbeat is disabled.\n */\n recordRpcFailure(): void\n}\n\nexport function createGristHandshakeManager(options: ManagerOptions = {}): ManagerControls {\n const env = options.env ?? createBrowserEnvironment()\n const reducerConfig: ReducerConfig = {\n ...DEFAULT_REDUCER_CONFIG,\n ...(options.reducerConfig ?? {}),\n }\n\n let snapshot = initialGristSnapshot()\n const ctx: GristReducerContext = createReducerContext()\n const listeners = new Set<() => void>()\n\n let started = false\n let abort: AbortController | null = null\n let detectHandle: DetectHandle | null = null\n let negotiateHandle: NegotiateHandle | null = null\n let subscriptionsHandle: SubscriptionsHandle | null = null\n let mappingsHandle: MappingsHandle | null = null\n let heartbeatHandle: HeartbeatHandle | null = null\n /** Set by `reload()`; cleared after one post-online cache check. */\n let recheckAuthzFromCacheAfterOnline = false\n\n const declared: GristColumnsToMap = options.columns ?? []\n const subscriptionsBinder = options.subscriptionsBinder ?? defaultSubscriptionsBinder\n\n const notify = () => {\n for (const l of listeners) {\n try {\n l()\n } catch (err) {\n options.onError?.(err, \"listener\")\n }\n }\n }\n\n const dispatch = (action: GristAction) => {\n const prev = snapshot\n const next = gristReducer(prev, action, ctx, reducerConfig)\n if (next !== prev) {\n snapshot = next\n // Run side-effects that depend on phase transitions BEFORE notifying.\n onTransition(prev, next)\n notify()\n }\n }\n\n /**\n * Effect-runner glue: react to lifecycle transitions inside the manager\n * (without polluting the pure reducer).\n *\n * Rationale: the reducer cannot start a `grist.ready()` because that's\n * impure. The reducer instead emits the transition (DETECT_AVAILABLE →\n * `lifecycle.phase === \"negotiating\"`) and the manager observes the\n * transition here to launch the next effect.\n */\n const onTransition = (prev: GristWidgetSnapshot, next: GristWidgetSnapshot) => {\n if (prev.lifecycle.phase !== \"negotiating\" && next.lifecycle.phase === \"negotiating\") {\n launchNegotiate()\n // Bind `grist.onRecord` before `grist.ready` resolves so the host's\n // post-ready cursor/data push is not dropped (iframe transport).\n launchSubscriptions()\n }\n if (prev.lifecycle.phase !== \"online\" && next.lifecycle.phase === \"online\") {\n launchMappings()\n launchHeartbeat()\n if (recheckAuthzFromCacheAfterOnline) {\n recheckAuthzFromCacheAfterOnline = false\n denyAuthzFromCachedOptionsIfInsufficient(next, dispatch, env)\n }\n }\n if (prev.lifecycle.phase === \"online\" && next.lifecycle.phase !== \"online\") {\n // Leaving the online phase — stop probing immediately.\n heartbeatHandle?.cancel()\n heartbeatHandle = null\n }\n }\n\n const launchDetect = () => {\n if (!abort) return\n detectHandle?.cancel()\n detectHandle = startDetectEffect(env, dispatch, abort.signal, options.detect)\n }\n\n const launchNegotiate = () => {\n if (!abort) return\n negotiateHandle?.cancel()\n negotiateHandle = startNegotiateEffect(\n env,\n dispatch,\n abort.signal,\n buildReadyPayload(options),\n options.negotiate\n )\n }\n\n const launchSubscriptions = () => {\n if (!abort) return\n if (subscriptionsHandle) return\n subscriptionsHandle = subscriptionsBinder({\n dispatch,\n getGeneration: () => snapshot.generation,\n onRecordPayload: (m) =>\n mappingsHandle?.ingestStreamPayload(\"stream_record\", m),\n onRecordsPayload: (m) =>\n mappingsHandle?.ingestStreamPayload(\"stream_records\", m),\n onNewRecordPayload: (m) =>\n mappingsHandle?.ingestStreamPayload(\"stream_new_record\", m),\n })\n }\n\n const launchMappings = () => {\n if (!abort) return\n launchSubscriptions()\n if (mappingsHandle) return\n mappingsHandle = startMappingsEffect(\n env,\n dispatch,\n abort.signal,\n declared,\n () => snapshot.generation,\n options.mappings\n )\n }\n\n const launchHeartbeat = () => {\n if (!abort) return\n if (options.heartbeat === false) return\n if (heartbeatHandle) return\n heartbeatHandle = startHeartbeatEffect(\n env,\n dispatch,\n abort.signal,\n options.heartbeat ?? {}\n )\n }\n\n const cancelAllEffects = () => {\n detectHandle?.cancel()\n detectHandle = null\n negotiateHandle?.cancel()\n negotiateHandle = null\n mappingsHandle?.cancel()\n mappingsHandle = null\n heartbeatHandle?.cancel()\n heartbeatHandle = null\n if (abort && !abort.signal.aborted) abort.abort()\n }\n\n const controls: ManagerControls = {\n start() {\n if (started) return\n started = true\n abort = new AbortController()\n launchDetect()\n },\n stop() {\n if (!started) return\n started = false\n cancelAllEffects()\n subscriptionsHandle?.cancel()\n subscriptionsHandle = null\n // Reset snapshot to `idle` so a subsequent `start()` is clean.\n snapshot = initialGristSnapshot()\n notify()\n },\n reload() {\n if (!started) {\n controls.start()\n return\n }\n recheckAuthzFromCacheAfterOnline = true\n try {\n options.onBeforeReload?.()\n } catch (err) {\n options.onError?.(err, \"onBeforeReload\")\n }\n cancelAllEffects()\n // Bump generation so any lingering microtasks / RPC resolutions get dropped.\n dispatch({ type: \"BUMP_GENERATION\", atMs: env.now(), reason: \"reload\" })\n // Reset snapshot to `idle` for the lifecycle restart.\n snapshot = {\n ...initialGristSnapshot(),\n generation: nextGeneration(snapshot.generation),\n }\n ctx.resolver = null\n abort = new AbortController()\n launchDetect()\n notify()\n },\n restart() {\n controls.reload()\n // Hard reload only makes sense in a real browser realm.\n if (typeof window !== \"undefined\" && typeof window.location?.reload === \"function\") {\n try {\n window.location.reload()\n } catch (err) {\n options.onError?.(err, \"restart\")\n }\n }\n },\n subscribe(listener) {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n getSnapshot: () => snapshot,\n dispatch,\n recordRpcSuccess() {\n heartbeatHandle?.recordRpcSuccess()\n },\n recordRpcFailure() {\n heartbeatHandle?.recordRpcFailure()\n },\n }\n\n return controls\n}\n\nfunction buildReadyPayload(options: ManagerOptions): GristReadyOptions {\n const payload: GristReadyOptions = {\n requiredAccess: options.requiredAccess ?? \"read table\",\n columns: options.columns ?? [],\n }\n if (options.allowSelectBy !== undefined) payload.allowSelectBy = options.allowSelectBy\n if (options.hasCustomOptions !== undefined) payload.hasCustomOptions = options.hasCustomOptions\n if (options.onEditOptions) payload.onEditOptions = options.onEditOptions\n return payload\n}\n","/**\n * Page-level embedded handshake manager for widgets that call `useGrist()` /\n * `useGristCore()` without mounting `<GristWidgetProvider>`.\n *\n * A single manager is shared across all hook instances on the page (ref-counted)\n * so mid-level hooks (`useGristActions`, `useGristRowsFromTable`, …) do not\n * spawn competing `grist.ready` handshakes.\n */\n\nimport {\n createGristHandshakeManager,\n type ManagerControls,\n type ManagerOptions,\n} from \"./handshake/manager\"\n\ntype EmbeddedSlot = {\n manager: ManagerControls\n refCount: number\n}\n\nlet embedded: EmbeddedSlot | null = null\n\nexport function acquireEmbeddedHandshakeManager(options: ManagerOptions): ManagerControls {\n if (!embedded) {\n embedded = {\n manager: createGristHandshakeManager(options),\n refCount: 0,\n }\n embedded.manager.start()\n }\n embedded.refCount += 1\n return embedded.manager\n}\n\nexport function releaseEmbeddedHandshakeManager(): void {\n if (!embedded) return\n embedded.refCount -= 1\n if (embedded.refCount <= 0) {\n embedded.manager.stop()\n embedded = null\n }\n}\n\n/** Test isolation — tear down the page-level embedded manager between cases. */\nexport function resetEmbeddedHandshakeManagerForTests(): void {\n if (embedded) {\n embedded.manager.stop()\n embedded = null\n }\n}\n","import {\n useContext,\n useEffect,\n useRef,\n type ReactNode,\n} from \"react\"\n\nimport { GristHandshakeManagerContext } from \"../internal/handshake-manager-context\"\nimport { buildManagerOptionsFromGristOptions } from \"../internal/build-manager-options\"\nimport { useGristFromProvider } from \"../internal/contexts\"\nimport { GristContext, GristWidgetContextTree } from \"../internal/grist-widget-context-tree\"\nimport {\n createGristHandshakeManager,\n type ManagerControls,\n} from \"../internal/handshake/manager\"\nimport type { UseGristOptions, UseGristResult } from \"../use-grist-types\"\n\nexport type GristWidgetProviderProps = {\n options?: UseGristOptions\n children: ReactNode\n}\n\n/**\n * Sets up Grist once at the app root. Prefer slice hooks (`useGristSelection`,\n * `useGristWrites`, …) in large widgets; use `useGristContext()` when you need everything.\n *\n * Owns a {@link GristHandshakeManager} and mounts the slice / full-result context\n * tree underneath it so `useRpcHeartbeatCoalesce()` in slice hooks sees the manager\n * (ordering required — see `tests/sdk/handshake-rpc-coalesce.test.tsx`).\n */\nexport function GristWidgetProvider({ options, children }: GristWidgetProviderProps) {\n // Allocate the handshake manager exactly once per provider instance. The\n // options snapshot is taken on the first mount — subsequent option changes\n // are intentionally ignored to keep the FSM lifecycle stable (matches the\n // prior behaviour: only re-runs `grist.ready` when requiredAccess widens via\n // the singleton).\n const managerRef = useRef<ManagerControls | null>(null)\n if (managerRef.current === null) {\n managerRef.current = createGristHandshakeManager(buildManagerOptionsFromGristOptions(options))\n }\n const manager = managerRef.current\n\n useEffect(() => {\n manager.start()\n return () => {\n manager.stop()\n }\n }, [manager])\n\n return (\n <GristHandshakeManagerContext.Provider value={manager}>\n <GristWidgetContextTree options={options}>{children}</GristWidgetContextTree>\n </GristHandshakeManagerContext.Provider>\n )\n}\n\n/**\n * Access the full `UseGristResult` from inside a `<GristWidgetProvider>`.\n *\n * The returned object updates whenever any Grist state changes (record selection,\n * widget options, etc.). Individual methods on the result (e.g. `w.fetchTable`,\n * `w.listTables`) are referentially stable and safe to use in `useEffect` deps.\n * See `UseGristResult` JSDoc for details.\n */\nexport function useGristContext<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>(): UseGristResult<\n TRow,\n TMapped\n> {\n const ctx = useContext(GristContext)\n if (!ctx) {\n throw new Error(\"useGristContext() must be used inside <GristWidgetProvider>\")\n }\n return useGristFromProvider<TRow, TMapped>()\n}\n\nexport function useGristOptional<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>():\n | UseGristResult<TRow, TMapped>\n | null {\n return useContext(GristContext) as UseGristResult<TRow, TMapped> | null\n}\n","import { createContext, useContext, useMemo, type Context } from \"react\"\n\nimport type { ComposedGristWidgetSlices } from \"./compose-grist-widget\"\nimport { mergeGristResultFromSlices } from \"./merge-grist-result\"\nimport type { UseGristResult } from \"../use-grist-types\"\nimport type { UseGristAttachmentsRestResult } from \"./hooks/use-grist-attachments-rest\"\nimport type { UseGristCoreResult } from \"./hooks/use-grist-core\"\nimport type { UseGristCurrentTableResult } from \"./hooks/use-grist-current-table\"\nimport type { UseGristLinkingResult } from \"./hooks/use-grist-linking\"\nimport type { UseGristReadsResult } from \"./hooks/use-grist-reads\"\nimport type { UseGristSectionApiResult } from \"./hooks/use-grist-section-api\"\nimport type { UseGristSelectionResult } from \"./hooks/use-grist-selection\"\nimport type { UseGristTableOpsBoundResult } from \"./hooks/use-grist-table-ops-bound\"\nimport type { UseGristThemeResult } from \"./hooks/use-grist-theme\"\nimport type { UseGristWidgetOptionsApiResult } from \"./hooks/use-grist-widget-options-api\"\n\nexport type GristCoreContextValue = UseGristCoreResult & {\n tableError: string | null\n}\n\nexport type GristStatusSliceValue = GristCoreContextValue & UseGristCurrentTableResult\n\nexport const GristCoreContext = createContext<GristCoreContextValue | null>(null)\nexport const GristSelectionContext = createContext<UseGristSelectionResult | null>(null)\nexport const GristCurrentTableContext = createContext<UseGristCurrentTableResult | null>(null)\nexport const GristWritesContext = createContext<UseGristTableOpsBoundResult | null>(null)\nexport const GristReadsContext = createContext<UseGristReadsResult | null>(null)\nexport const GristWidgetOptionsApiContext = createContext<UseGristWidgetOptionsApiResult | null>(null)\nexport const GristLinkingContext = createContext<UseGristLinkingResult | null>(null)\nexport const GristAttachmentsRestContext = createContext<UseGristAttachmentsRestResult | null>(null)\nexport const GristThemeContext = createContext<UseGristThemeResult | null>(null)\nexport const GristSectionApiContext = createContext<UseGristSectionApiResult | null>(null)\n\nfunction useRequiredContext<T>(ctx: Context<T | null>, name: string): T {\n const value = useContext(ctx)\n if (!value) {\n throw new Error(`${name} must be used inside <GristWidgetProvider>`)\n }\n return value\n}\n\nexport function useGristCoreContext(): GristCoreContextValue {\n return useRequiredContext(GristCoreContext, \"useGristCoreContext()\")\n}\n\nexport function useGristSelectionContext<\n TRow = Record<string, unknown>,\n TMapped = Record<string, unknown>,\n>(): UseGristSelectionResult<TRow, TMapped> {\n return useRequiredContext(GristSelectionContext, \"useGristSelectionContext()\") as UseGristSelectionResult<\n TRow,\n TMapped\n >\n}\n\nexport function useGristCurrentTableContext(): UseGristCurrentTableResult {\n return useRequiredContext(GristCurrentTableContext, \"useGristCurrentTableContext()\")\n}\n\nexport function useGristWritesContext(): UseGristTableOpsBoundResult {\n return useRequiredContext(GristWritesContext, \"useGristWritesContext()\")\n}\n\nexport function useGristReadsContext(): UseGristReadsResult {\n return useRequiredContext(GristReadsContext, \"useGristReadsContext()\")\n}\n\nexport function useGristWidgetOptionsApiContext(): UseGristWidgetOptionsApiResult {\n return useRequiredContext(GristWidgetOptionsApiContext, \"useGristWidgetOptionsApiContext()\")\n}\n\nexport function useGristLinkingContext(): UseGristLinkingResult {\n return useRequiredContext(GristLinkingContext, \"useGristLinkingContext()\")\n}\n\nexport function useGristAttachmentsRestContext(): UseGristAttachmentsRestResult {\n return useRequiredContext(GristAttachmentsRestContext, \"useGristAttachmentsRestContext()\")\n}\n\nexport function useGristThemeContext(): UseGristThemeResult {\n return useRequiredContext(GristThemeContext, \"useGristThemeContext()\")\n}\n\nexport function useGristSectionApiContext(): UseGristSectionApiResult {\n return useRequiredContext(GristSectionApiContext, \"useGristSectionApiContext()\")\n}\n\n/**\n * Live merge of all provider slices — used by `useGrist()` / `useGristContext()` so\n * cursor-driven `onRecord` updates are not lost behind a stale memoized snapshot.\n */\nexport function useGristFromProvider<\n TRow = Record<string, unknown>,\n TMapped = Record<string, unknown>,\n>(): UseGristResult<TRow, TMapped> {\n const core = useGristCoreContext()\n const selection = useGristSelectionContext<TRow, TMapped>()\n const currentTable = useGristCurrentTableContext()\n const writes = useGristWritesContext()\n const reads = useGristReadsContext()\n const widgetOptionsApi = useGristWidgetOptionsApiContext()\n const linking = useGristLinkingContext()\n const attachmentsRest = useGristAttachmentsRestContext()\n const theme = useGristThemeContext()\n const sectionApi = useGristSectionApiContext()\n\n return useMemo(\n () =>\n mergeGristResultFromSlices<TRow, TMapped>({\n core,\n selection,\n currentTable,\n writes,\n reads,\n widgetOptionsApi,\n linking,\n attachmentsRest,\n theme,\n sectionApi,\n } as ComposedGristWidgetSlices),\n [\n core,\n selection,\n currentTable,\n writes,\n reads,\n widgetOptionsApi,\n linking,\n attachmentsRest,\n theme,\n sectionApi,\n ]\n )\n}\n","import type { ComposedGristWidgetSlices } from \"./compose-grist-widget\"\nimport type { UseGristResult } from \"../use-grist-types\"\n\nexport function mergeGristResultFromSlices<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>(\n slices: ComposedGristWidgetSlices\n): UseGristResult<TRow, TMapped> {\n const { core, selection, currentTable, writes, reads, widgetOptionsApi, linking, attachmentsRest, theme, sectionApi, suppressAlerts, allowSelectBy } =\n slices\n return {\n status: core.status,\n isAvailable: core.isAvailable,\n isReady: core.isReady,\n error: core.error,\n capabilities: core.capabilities,\n record: selection.record as UseGristResult<TRow, TMapped>[\"record\"],\n records: selection.records as UseGristResult<TRow, TMapped>[\"records\"],\n mappedRecord: selection.mappedRecord as TMapped | null,\n mappings: selection.mappings,\n recordsMappings: selection.recordsMappings,\n columnMappingStatus: selection.columnMappingStatus,\n mode: selection.mode,\n resolveMappedColumnId: selection.resolveMappedColumnId,\n mapBack: selection.mapBack as (patch: Partial<TMapped>) => Record<string, unknown>,\n mapBackSkipped: selection.mapBackSkipped,\n isNewRecord: selection.isNewRecord,\n newRecordMappings: selection.newRecordMappings,\n currentTableId: currentTable.currentTableId,\n currentTableLoading: currentTable.currentTableLoading,\n refreshCurrentTable: currentTable.refreshCurrentTable,\n table: writes.table,\n getTable: writes.getTable,\n actionStatus: writes.actionStatus,\n actionError: writes.actionError,\n applyActions: writes.applyActions,\n reload: core.reload,\n fetchTable: reads.fetchTable,\n fetchTableRows: reads.fetchTableRows,\n fetchRow: reads.fetchRow,\n listTables: reads.listTables,\n listColumns: reads.listColumns,\n getDocName: reads.getDocName,\n buildReplicaDocumentFromDocApi: reads.buildReplicaDocumentFromDocApi,\n getAttachmentUrl: attachmentsRest.getAttachmentUrl,\n fetchAttachmentBase64: attachmentsRest.fetchAttachmentBase64,\n fetchAttachmentBlob: attachmentsRest.fetchAttachmentBlob,\n widgetOptions: selection.widgetOptions,\n widgetInteraction: selection.widgetInteraction,\n getWidgetOptions: widgetOptionsApi.getWidgetOptions,\n getWidgetOption: widgetOptionsApi.getWidgetOption,\n setWidgetOption: widgetOptionsApi.setWidgetOption,\n setWidgetOptions: widgetOptionsApi.setWidgetOptions,\n patchWidgetOptions: widgetOptionsApi.patchWidgetOptions,\n clearWidgetOptions: widgetOptionsApi.clearWidgetOptions,\n fetchSelectedTable: reads.fetchSelectedTable,\n fetchSelectedRecord: reads.fetchSelectedRecord,\n readError: reads.readError ?? attachmentsRest.readError,\n setCursorPosition: linking.setCursorPosition,\n setLinkedRowSelection: linking.setLinkedRowSelection,\n getAccessToken: attachmentsRest.getAccessToken,\n fetchWithAuth: attachmentsRest.fetchWithAuth,\n uploadAttachment: attachmentsRest.uploadAttachment,\n theme: theme.theme,\n configure: sectionApi.configure,\n refreshMappings: sectionApi.refreshMappings,\n suppressAlerts,\n allowSelectBy,\n }\n}\n","import { createContext, useMemo, type ReactNode } from \"react\"\n\nimport {\n GristAttachmentsRestContext,\n GristCoreContext,\n GristCurrentTableContext,\n GristLinkingContext,\n GristReadsContext,\n GristSectionApiContext,\n GristSelectionContext,\n GristThemeContext,\n GristWidgetOptionsApiContext,\n GristWritesContext,\n} from \"./contexts\"\nimport { useComposeGristWidgetSlices } from \"./compose-grist-widget\"\nimport { mergeGristResultFromSlices } from \"./merge-grist-result\"\nimport type { UseGristOptions, UseGristResult } from \"../use-grist-types\"\n\n/** Full {@link UseGristResult} for `useGristContext()` / in-tree `useGrist()`. */\nexport const GristContext = createContext<UseGristResult | null>(null)\n\nexport type GristWidgetContextTreeProps = {\n options?: UseGristOptions\n children: ReactNode\n}\n\n/**\n * Mounts per-slice React contexts for granular hooks (`useGristSelection`,\n * `useGristWrites`, …) and {@link GristContext} with the full\n * {@link UseGristResult} for `useGristContext()` / in-tree `useGrist()`.\n *\n * Must render as a child of {@link GristHandshakeManagerContext} so slice\n * hooks' `useRpcHeartbeatCoalesce()` sees the manager (see\n * `tests/sdk/handshake-rpc-coalesce.test.tsx`).\n */\nexport function GristWidgetContextTree({ options, children }: GristWidgetContextTreeProps) {\n const slices = useComposeGristWidgetSlices(options)\n const fullResult = useMemo(\n () => mergeGristResultFromSlices(slices),\n [\n slices.core,\n slices.selection,\n slices.currentTable,\n slices.writes,\n slices.reads,\n slices.widgetOptionsApi,\n slices.linking,\n slices.attachmentsRest,\n slices.theme,\n slices.sectionApi,\n ]\n )\n\n return (\n <GristCoreContext.Provider value={slices.core}>\n <GristSelectionContext.Provider value={slices.selection}>\n <GristCurrentTableContext.Provider value={slices.currentTable}>\n <GristWritesContext.Provider value={slices.writes}>\n <GristReadsContext.Provider value={slices.reads}>\n <GristWidgetOptionsApiContext.Provider value={slices.widgetOptionsApi}>\n <GristLinkingContext.Provider value={slices.linking}>\n <GristAttachmentsRestContext.Provider value={slices.attachmentsRest}>\n <GristThemeContext.Provider value={slices.theme}>\n <GristSectionApiContext.Provider value={slices.sectionApi}>\n <GristContext.Provider value={fullResult}>{children}</GristContext.Provider>\n </GristSectionApiContext.Provider>\n </GristThemeContext.Provider>\n </GristAttachmentsRestContext.Provider>\n </GristLinkingContext.Provider>\n </GristWidgetOptionsApiContext.Provider>\n </GristReadsContext.Provider>\n </GristWritesContext.Provider>\n </GristCurrentTableContext.Provider>\n </GristSelectionContext.Provider>\n </GristCoreContext.Provider>\n )\n}\n","import { useMemo } from \"react\"\n\nimport { useGristCore, type UseGristCoreOptions } from \"./hooks/use-grist-core\"\nimport { useGristCurrentTable } from \"./hooks/use-grist-current-table\"\nimport {\n useGristSelectionSubscription,\n type UseGristSelectionOptions,\n} from \"./hooks/use-grist-selection\"\nimport { useGristTableOpsBound } from \"./hooks/use-grist-table-ops-bound\"\nimport { useGristReads } from \"./hooks/use-grist-reads\"\nimport { useGristWidgetOptionsApi } from \"./hooks/use-grist-widget-options-api\"\nimport { useGristLinking } from \"./hooks/use-grist-linking\"\nimport { useGristAttachmentsRest } from \"./hooks/use-grist-attachments-rest\"\nimport { useGristTheme } from \"./hooks/use-grist-theme\"\nimport { useGristSectionApi } from \"./hooks/use-grist-section-api\"\nimport type { GristCoreContextValue } from \"./contexts\"\nimport type { UseGristAttachmentsRestResult } from \"./hooks/use-grist-attachments-rest\"\nimport type { UseGristCurrentTableResult } from \"./hooks/use-grist-current-table\"\nimport type { UseGristLinkingResult } from \"./hooks/use-grist-linking\"\nimport type { UseGristReadsResult } from \"./hooks/use-grist-reads\"\nimport type { UseGristSectionApiResult } from \"./hooks/use-grist-section-api\"\nimport type { UseGristSelectionResult } from \"./hooks/use-grist-selection\"\nimport type { UseGristTableOpsBoundResult } from \"./hooks/use-grist-table-ops-bound\"\nimport type { UseGristThemeResult } from \"./hooks/use-grist-theme\"\nimport type { UseGristWidgetOptionsApiResult } from \"./hooks/use-grist-widget-options-api\"\nimport type { GristSdkAlertKind } from \"../helpers/grist-sdk-alerts\"\n\nexport type ComposeGristWidgetOptions = UseGristCoreOptions & UseGristSelectionOptions & {\n /**\n * Alert kinds that should never be emitted for this widget.\n * E.g. `[\"section-not-linked\"]` for widgets that don't need a link source.\n */\n suppressAlerts?: GristSdkAlertKind[]\n}\n\nexport type ComposedGristWidgetSlices = {\n core: GristCoreContextValue\n selection: UseGristSelectionResult\n currentTable: UseGristCurrentTableResult\n writes: UseGristTableOpsBoundResult\n reads: UseGristReadsResult\n widgetOptionsApi: UseGristWidgetOptionsApiResult\n linking: UseGristLinkingResult\n attachmentsRest: UseGristAttachmentsRestResult\n theme: UseGristThemeResult\n sectionApi: UseGristSectionApiResult\n suppressAlerts?: readonly GristSdkAlertKind[]\n allowSelectBy?: boolean\n}\n\nexport function useComposeGristWidgetSlices(\n options?: ComposeGristWidgetOptions\n): ComposedGristWidgetSlices {\n const core = useGristCore(options)\n const currentTable = useGristCurrentTable(core.docApi)\n const selection = useGristSelectionSubscription(core.docApi, options)\n const writes = useGristTableOpsBound(core.docApi)\n const reads = useGristReads(core.docApi)\n const widgetOptionsApi = useGristWidgetOptionsApi()\n const linking = useGristLinking()\n const attachmentsRest = useGristAttachmentsRest(core.docApi)\n const theme = useGristTheme(core.docApi)\n const sectionApi = useGristSectionApi()\n\n const coreSlice: GristCoreContextValue = useMemo(\n () => ({\n ...core,\n tableError: currentTable.tableError,\n }),\n [core, currentTable.tableError]\n )\n\n const suppressAlerts = options?.suppressAlerts\n const allowSelectBy = options?.allowSelectBy\n\n return useMemo(\n () => ({\n core: coreSlice,\n selection,\n currentTable,\n writes,\n reads,\n widgetOptionsApi,\n linking,\n attachmentsRest,\n theme,\n sectionApi,\n suppressAlerts,\n allowSelectBy,\n }),\n [\n coreSlice,\n selection,\n currentTable,\n writes,\n reads,\n widgetOptionsApi,\n linking,\n attachmentsRest,\n theme,\n sectionApi,\n suppressAlerts,\n allowSelectBy,\n ]\n )\n}\n","import { useCallback, useMemo, useSyncExternalStore } from \"react\"\n\nimport type { GristDocApi, GristReadyOptions } from \"../../types\"\nimport {\n deriveCapabilities,\n deriveErrorMessage,\n deriveStatus,\n initialGristSnapshot,\n type GristCapabilities,\n type GristWidgetSnapshot,\n type GristWidgetStatus as HandshakeStatus,\n} from \"../handshake\"\nimport type { ManagerControls } from \"../handshake/manager\"\nimport { useGristManager } from \"../handshake-manager-context\"\n\n/** Canonical 4-state status — projected from the handshake snapshot. */\nexport type GristWidgetStatus = HandshakeStatus\n\nexport type UseGristCoreOptions = GristReadyOptions & {\n availabilityMaxAttempts?: number\n availabilityIntervalMs?: number\n logWhenNotEmbedded?: boolean\n}\n\nexport type UseGristCoreResult = {\n status: GristWidgetStatus\n isAvailable: boolean | null\n isReady: boolean\n error: string | null\n docApi: GristDocApi | null\n /** Derived from the handshake snapshot — same values as `useGristCapabilities()` on `/advanced`. */\n capabilities: GristCapabilities\n reload: () => Promise<void>\n}\n\n/** Project handshake availability for legacy `isAvailable` consumers. */\nexport function computeAvailabilityFromSnapshot(\n snapshot: GristWidgetSnapshot\n): boolean | null {\n const { phase } = snapshot.lifecycle\n if (phase === \"idle\" || phase === \"detecting\") return null\n if (phase === \"terminated\") {\n const reason = snapshot.lifecycle.reason.kind\n if (reason === \"not_embedded\" || reason === \"script_timeout\") return false\n return true\n }\n return true\n}\n\n/**\n * Core connectivity hook — always backed by {@link GristHandshakeManager}.\n */\nexport function useGristCore(options?: UseGristCoreOptions): UseGristCoreResult {\n const manager = useGristManager(options)\n return useGristCoreFromManager(manager)\n}\n\n/**\n * Subscribe to an existing manager and project its snapshot into\n * {@link UseGristCoreResult}.\n */\nexport function useGristCoreFromManager(manager: ManagerControls): UseGristCoreResult {\n const snapshot = useSyncExternalStore(\n manager.subscribe,\n manager.getSnapshot,\n initialGristSnapshot\n )\n const status = deriveStatus(snapshot)\n const error = deriveErrorMessage(snapshot)\n const docApi = useMemo<GristDocApi | null>(() => {\n if (snapshot.lifecycle.phase !== \"online\") return null\n if (typeof grist === \"undefined\") return null\n return grist.docApi ?? null\n }, [snapshot.lifecycle.phase, snapshot.generation])\n const isAvailable = computeAvailabilityFromSnapshot(snapshot)\n const reload = useCallback(async () => {\n manager.reload()\n }, [manager])\n const capabilities = useMemo(() => deriveCapabilities(snapshot), [snapshot])\n return useMemo(\n () => ({\n status,\n isAvailable,\n isReady: status === \"ready\",\n error,\n docApi,\n capabilities,\n reload,\n }),\n [status, isAvailable, error, docApi, capabilities, reload]\n )\n}\n","import { useCallback, useEffect, useMemo, useSyncExternalStore } from \"react\"\n\nimport { recordEvent } from \"../subscriptions\"\nimport type { GristDocApi } from \"../../types\"\nimport { initialGristSnapshot } from \"../handshake\"\nimport { useGristManager } from \"../handshake-manager-context\"\nimport { useRpcHeartbeatCoalesce } from \"./use-rpc-heartbeat-coalesce\"\n\nexport type UseGristCurrentTableResult = {\n currentTableId: string | null\n currentTableLoading: boolean\n refreshCurrentTable: () => Promise<void>\n tableError: string | null\n}\n\nexport function useGristCurrentTable(docApi: GristDocApi | null): UseGristCurrentTableResult {\n const manager = useGristManager()\n const coalesceRpc = useRpcHeartbeatCoalesce()\n const snapshot = useSyncExternalStore(\n manager.subscribe,\n manager.getSnapshot,\n initialGristSnapshot\n )\n\n const currentTable = snapshot.sync.currentTable\n const currentTableId =\n currentTable.state === \"known\" ? currentTable.tableId : null\n const currentTableLoading =\n currentTable.state === \"known\" ? currentTable.refreshing : false\n const tableError =\n currentTable.state === \"errored\" ? currentTable.message : null\n\n const refreshCurrentTable = useCallback(async () => {\n if (!docApi) return\n if (typeof grist === \"undefined\") return\n const atMs = Date.now()\n manager.dispatch({ type: \"CURRENT_TABLE_REFRESH_START\", atMs })\n try {\n const next = await coalesceRpc(() =>\n Promise.resolve(grist.selectedTable?.getTableId())\n )\n if (next) {\n manager.dispatch({ type: \"CURRENT_TABLE_KNOWN\", tableId: next, atMs: Date.now() })\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n manager.dispatch({ type: \"CURRENT_TABLE_ERROR\", message, atMs: Date.now() })\n }\n }, [docApi, coalesceRpc, manager])\n\n useEffect(() => {\n if (docApi) void refreshCurrentTable()\n }, [docApi, refreshCurrentTable])\n\n useEffect(() => {\n return recordEvent.subscribe(() => {\n if (!docApi) return\n void refreshCurrentTable()\n })\n }, [docApi, refreshCurrentTable])\n\n return useMemo(\n () => ({\n currentTableId,\n currentTableLoading,\n refreshCurrentTable,\n tableError,\n }),\n [currentTableId, currentTableLoading, refreshCurrentTable, tableError]\n )\n}\n","/**\n * `useRpcHeartbeatCoalesce()` — coalesce real RPC traffic with the handshake\n * heartbeat.\n *\n * When a {@link GristHandshakeManager} is mounted (via `<GristWidgetProvider>`\n * or `<GristHandshakeProvider>`), every successful Grist RPC call is treated\n * as a natural heartbeat: the manager's `recordRpcSuccess()` resets the\n * missed-ping counter and pushes the next probe out by a full interval, so\n * a chatty widget never burns dedicated heartbeat probes.\n *\n * Failures are NOT coalesced: semantic errors (validation, \"row not found\",\n * \"no such column\") would briefly flash a connection-degraded indicator even\n * though the channel is alive. Instead we let the regular heartbeat probe\n * detect real transport failures on its own schedule (~30 s). The user\n * already sees the action error immediately, so the heartbeat indicator\n * doesn't need to race.\n *\n * Outside a provider (no manager in context), the wrapper is a zero-cost\n * passthrough — every slice hook keeps working exactly like the pre-FSM\n * release.\n */\n\nimport { useCallback } from \"react\"\n\nimport { useGristManagerOptional } from \"../handshake-manager-context\"\n\nexport type RpcHeartbeatCoalesce = <T>(fn: () => Promise<T>) => Promise<T>\n\nexport function useRpcHeartbeatCoalesce(): RpcHeartbeatCoalesce {\n const manager = useGristManagerOptional()\n return useCallback<RpcHeartbeatCoalesce>(\n async (fn) => {\n try {\n const result = await fn()\n manager?.recordRpcSuccess()\n return result\n } catch (err) {\n throw err\n }\n },\n [manager]\n )\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\n\nimport {\n newRecordEvent,\n optionsEvent,\n recordEvent,\n recordsEvent,\n type GristRecordPayload,\n} from \"../subscriptions\"\nimport {\n deriveColumnMappingStatus,\n extractResolvedMappings,\n type GristMappingState,\n} from \"../handshake\"\nimport { useGristManager } from \"../handshake-manager-context\"\nimport type {\n GristColumnsToMap,\n GristDocApi,\n GristWidgetColumnMap,\n GristWidgetInteraction,\n GristRowRecord,\n} from \"../../types\"\nimport type { ValidateColumnMappingsResult } from \"../../helpers/grist-mappings\"\n\nconst EMPTY_MAPPINGS: GristWidgetColumnMap = Object.freeze({})\n\nfunction stableColumnMappingStatus(\n prev: ValidateColumnMappingsResult | undefined,\n mappingState: GristMappingState,\n columns?: GristColumnsToMap\n): ValidateColumnMappingsResult {\n const next = deriveColumnMappingStatus(mappingState, columns)\n if (\n prev &&\n prev.ok === next.ok &&\n prev.pending === next.pending &&\n prev.missing.length === next.missing.length &&\n prev.emptyMultiples.length === next.emptyMultiples.length &&\n prev.missing.every((m, i) => m === next.missing[i]) &&\n prev.emptyMultiples.every((m, i) => m === next.emptyMultiples[i])\n ) {\n return prev\n }\n return next\n}\n\nexport type GristWidgetMode = \"empty\" | \"row\" | \"new-row\"\n\nexport type UseGristSelectionOptions = {\n columns?: GristColumnsToMap\n subscribeToWidgetOptions?: boolean\n subscribeToNewRecord?: boolean\n}\n\nexport type UseGristSelectionResult<TRow = Record<string, unknown>, TMapped = Record<string, unknown>> = {\n record: GristRowRecord<TRow> | null\n records: GristRowRecord<TRow>[] | null\n mappedRecord: TMapped | null\n mappings: GristWidgetColumnMap\n recordsMappings: GristWidgetColumnMap | null\n columnMappingStatus: ValidateColumnMappingsResult\n mode: GristWidgetMode\n resolveMappedColumnId: (logicalFieldName: string) => string\n mapBack: (patch: Partial<TMapped>) => Record<string, unknown>\n mapBackSkipped: readonly string[]\n isNewRecord: boolean\n newRecordMappings: GristWidgetColumnMap | null\n widgetOptions: Record<string, unknown> | null\n widgetInteraction: GristWidgetInteraction | null\n}\n\n/**\n * Shallow copy so React state updates when the host reuses one record object\n * and mutates fields in place (Grist's `onRecord` can do this).\n */\nfunction copyRowRecord<T>(record: Record<string, unknown> | null): GristRowRecord<T> | null {\n if (!record) return null\n return { ...record } as GristRowRecord<T>\n}\n\nfunction copyRowRecords<T>(records: Record<string, unknown>[] | null): GristRowRecord<T>[] | null {\n if (!records) return null\n return records.map((row) => ({ ...row })) as GristRowRecord<T>[]\n}\n\nfunction copyMappedRecord<T>(mapped: unknown): T | null {\n if (mapped === null || mapped === undefined) return null\n if (typeof mapped !== \"object\") return mapped as T\n return { ...(mapped as Record<string, unknown>) } as T\n}\n\nfunction mappingStateKey(state: GristMappingState): string {\n return JSON.stringify(state)\n}\n\n/** Re-render only when the FSM mapping axis changes — not on link/heartbeat updates. */\nfunction useMappingProjection() {\n const manager = useGristManager()\n const [mappingState, setMappingState] = useState(\n () => manager.getSnapshot().config.mappings\n )\n useEffect(() => {\n let lastKey = mappingStateKey(manager.getSnapshot().config.mappings)\n return manager.subscribe(() => {\n const next = manager.getSnapshot().config.mappings\n const nextKey = mappingStateKey(next)\n if (nextKey !== lastKey) {\n lastKey = nextKey\n setMappingState(next)\n }\n })\n }, [manager])\n return mappingState\n}\n\nexport function useGristSelectionSubscription<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>(\n docApi: GristDocApi | null,\n options?: UseGristSelectionOptions\n): UseGristSelectionResult<TRow, TMapped> {\n const subscribeToWidgetOptions = options?.subscribeToWidgetOptions ?? true\n const subscribeToNewRecord = options?.subscribeToNewRecord ?? true\n const mappingState = useMappingProjection()\n\n const [record, setRecord] = useState<GristRowRecord<TRow> | null>(null)\n const [records, setRecords] = useState<GristRowRecord<TRow>[] | null>(null)\n const [mappedRecord, setMappedRecord] = useState<TMapped | null>(null)\n const [streamMappings, setStreamMappings] = useState<GristWidgetColumnMap | null>(null)\n const [recordsMappings, setRecordsMappings] = useState<GristWidgetColumnMap | null>(null)\n const [widgetOptions, setWidgetOptionsMirror] = useState<Record<string, unknown> | null>(null)\n const [widgetInteraction, setWidgetInteraction] = useState<GristWidgetInteraction | null>(null)\n const [isNewRecord, setIsNewRecord] = useState(false)\n const [newRecordMappings, setNewRecordMappings] = useState<GristWidgetColumnMap | null>(null)\n const [mapBackSkipped, setMapBackSkipped] = useState<readonly string[]>([])\n const mapBackSkippedRef = useRef<readonly string[]>([])\n\n const fsmMappings = extractResolvedMappings(mappingState)\n const mappings = useMemo(\n () => fsmMappings ?? streamMappings ?? EMPTY_MAPPINGS,\n [fsmMappings, streamMappings]\n )\n\n const columnMappingStatusRef = useRef<ValidateColumnMappingsResult | undefined>(undefined)\n const columnMappingStatus = useMemo(() => {\n const next = stableColumnMappingStatus(\n columnMappingStatusRef.current,\n mappingState,\n options?.columns\n )\n columnMappingStatusRef.current = next\n return next\n }, [mappingState, options?.columns])\n\n const applyRecordPayload = useCallback(\n ({ record: next, mappings: nextMappings }: GristRecordPayload) => {\n setStreamMappings(nextMappings)\n setRecord(copyRowRecord<TRow>(next))\n if (!next) {\n setMappedRecord(null)\n return\n }\n setIsNewRecord(false)\n if (typeof grist !== \"undefined\" && typeof grist.mapColumnNames === \"function\") {\n setMappedRecord(copyMappedRecord<TMapped>(grist.mapColumnNames(next)))\n } else {\n setMappedRecord(copyMappedRecord<TMapped>(next))\n }\n },\n []\n )\n\n // Bind `grist.on*` as soon as the widget mounts — not when `docApi` appears.\n // `docApi` is only available after `grist.ready` resolves (`lifecycle.phase ===\n // \"online\"`), but the host may push the initial cursor/record payload during\n // ready. Late binding missed that first `onRecord` in production iframe runs.\n useEffect(() => {\n if (typeof grist === \"undefined\") return\n return recordEvent.subscribe(applyRecordPayload)\n }, [applyRecordPayload])\n\n useEffect(() => {\n if (typeof grist === \"undefined\") return\n return recordsEvent.subscribe(({ records: next, mappings: nextMappings }) => {\n setRecords(copyRowRecords<TRow>(next))\n setRecordsMappings(nextMappings)\n })\n }, [])\n\n useEffect(() => {\n if (!subscribeToWidgetOptions || typeof grist === \"undefined\") return\n return optionsEvent.subscribe(({ options: next, interaction }) => {\n setWidgetOptionsMirror(next)\n setWidgetInteraction(interaction)\n })\n }, [subscribeToWidgetOptions])\n\n useEffect(() => {\n if (!subscribeToNewRecord || typeof grist === \"undefined\") return\n if (typeof grist.onNewRecord !== \"function\") return\n return newRecordEvent.subscribe(({ mappings: nextMappings }) => {\n setIsNewRecord(true)\n setNewRecordMappings(nextMappings)\n })\n }, [subscribeToNewRecord])\n\n const prevDocApiRef = useRef<GristDocApi | null>(null)\n\n // Re-apply cached `onRecord` when `docApi` becomes ready. Do not clear stream\n // state on the initial mount while `docApi` is still null — that ran after\n // `recordEvent.subscribe()` replay and wiped the first selected row.\n useEffect(() => {\n const hadDocApi = prevDocApiRef.current !== null\n prevDocApiRef.current = docApi\n\n if (docApi) {\n if (!hadDocApi && recordEvent.ready) {\n const cached = recordEvent.peek()\n if (cached !== undefined) applyRecordPayload(cached)\n }\n return\n }\n\n if (!hadDocApi) return\n\n setRecord(null)\n setRecords(null)\n setMappedRecord(null)\n setStreamMappings(null)\n setRecordsMappings(null)\n setIsNewRecord(false)\n setNewRecordMappings(null)\n setWidgetOptionsMirror(null)\n setWidgetInteraction(null)\n }, [docApi, applyRecordPayload])\n\n const resolveMappedColumnId = useCallback(\n (logicalFieldName: string): string => {\n const value = mappings[logicalFieldName]\n if (typeof value === \"string\") return value\n if (Array.isArray(value) && typeof value[0] === \"string\") return value[0]\n return logicalFieldName\n },\n [mappings]\n )\n\n const mapBack = useCallback(\n (patch: Partial<TMapped>): Record<string, unknown> => {\n const skipped: string[] = []\n for (const name of Object.keys(patch as Record<string, unknown>)) {\n if (Array.isArray(mappings[name])) skipped.push(name)\n }\n\n const computeResult = (): Record<string, unknown> => {\n if (typeof grist.mapColumnNamesBack === \"function\") {\n const out = grist.mapColumnNamesBack(patch as Record<string, unknown>)\n // grist-plugin-api.js's `mapColumnNamesBack` builds transformation\n // functions for ALL mapped columns and applies every one of them,\n // even when the corresponding logical key is absent from `patch`.\n // Absent keys produce `undefined` values which JSON-serialise to\n // `null` over RPC, causing Grist to erase those cells.\n // Strip all `undefined` entries — callers that intentionally clear\n // a field should pass `null`.\n for (const key of Object.keys(out)) {\n if (out[key] === undefined) {\n delete out[key]\n }\n }\n return out\n }\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)) continue\n out[target ?? name] = value\n }\n return out\n }\n\n const result = computeResult()\n\n const previous = mapBackSkippedRef.current\n const same =\n previous.length === skipped.length &&\n previous.every((name, i) => name === skipped[i])\n if (!same) {\n mapBackSkippedRef.current = skipped\n setMapBackSkipped(skipped)\n }\n\n return result\n },\n [mappings]\n )\n\n const mode: GristWidgetMode = isNewRecord ? \"new-row\" : record ? \"row\" : \"empty\"\n\n return useMemo(\n () => ({\n record,\n records,\n mappedRecord,\n mappings,\n recordsMappings,\n columnMappingStatus,\n mode,\n resolveMappedColumnId,\n mapBack,\n mapBackSkipped,\n isNewRecord,\n newRecordMappings,\n widgetOptions,\n widgetInteraction,\n }),\n [\n record,\n records,\n mappedRecord,\n mappings,\n recordsMappings,\n columnMappingStatus,\n mode,\n resolveMappedColumnId,\n mapBack,\n mapBackSkipped,\n isNewRecord,\n newRecordMappings,\n widgetOptions,\n widgetInteraction,\n ]\n )\n}\n","import { useCallback, useMemo, useRef, useState } from \"react\"\n\nimport type { GristUserActionTuple } from \"../../helpers/grist-user-actions\"\nimport type {\n GristApplyUserActionsOptions,\n GristDocApi,\n GristMinimalRecord,\n GristTableNewRecord,\n GristTableOpOptions,\n GristTableOperations,\n GristTableUpdateRecord,\n GristTableUpsertOptions,\n GristTableUpsertRecord,\n} from \"../../types\"\nimport { useRpcHeartbeatCoalesce } from \"./use-rpc-heartbeat-coalesce\"\n\nexport type GristWidgetActionStatus = \"idle\" | \"running\" | \"error\"\n\nexport type UseGristTableOpsBoundResult = {\n table: GristTableOperations\n getTable: (tableId: string) => GristTableOperations\n actionStatus: GristWidgetActionStatus\n actionError: string | null\n applyActions: (\n actions: GristUserActionTuple[],\n applyOptions?: GristApplyUserActionsOptions\n ) => Promise<unknown>\n}\n\nfunction resolveSelectedTableOps(): GristTableOperations {\n if (grist.selectedTable) return grist.selectedTable\n throw new Error(\"grist.selectedTable is not available in this Grist version\")\n}\n\nfunction resolveTableOps(tableId: string): GristTableOperations {\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\nexport function useGristTableOpsBound(docApi: GristDocApi | null): UseGristTableOpsBoundResult {\n const [actionStatus, setActionStatus] = useState<GristWidgetActionStatus>(\"idle\")\n const [actionError, setActionError] = useState<string | null>(null)\n const tableCacheRef = useRef(new Map<string, GristTableOperations>())\n const coalesceRpc = useRpcHeartbeatCoalesce()\n\n const trackOp = useCallback(\n async <T>(fn: () => Promise<T>): Promise<T> => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n setActionStatus(\"running\")\n setActionError(null)\n try {\n const out = await coalesceRpc(fn)\n setActionStatus(\"idle\")\n return out\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n setActionError(message)\n setActionStatus(\"error\")\n throw err\n }\n },\n [docApi, coalesceRpc]\n )\n\n const wrapTableOps = useCallback(\n (resolve: () => GristTableOperations): GristTableOperations => ({\n getTableId: () => trackOp(() => resolve().getTableId()),\n create: (\n records: GristTableNewRecord | GristTableNewRecord[],\n opOptions?: GristTableOpOptions\n ): Promise<GristMinimalRecord | GristMinimalRecord[]> =>\n trackOp(() => resolve().create(records, opOptions)),\n update: (\n records: GristTableUpdateRecord | GristTableUpdateRecord[],\n opOptions?: GristTableOpOptions\n ) => trackOp(() => resolve().update(records, opOptions)),\n upsert: (\n records: GristTableUpsertRecord | GristTableUpsertRecord[],\n opOptions?: GristTableUpsertOptions\n ) => trackOp(() => resolve().upsert(records, opOptions)),\n destroy: (recordIds: number | number[]) =>\n trackOp(() => resolve().destroy(recordIds)),\n }),\n [trackOp]\n )\n\n const table = useMemo(() => wrapTableOps(() => resolveSelectedTableOps()), [wrapTableOps])\n\n const getTable = useCallback(\n (tableId: string) => {\n const cached = tableCacheRef.current.get(tableId)\n if (cached) return cached\n const wrapped = wrapTableOps(() => resolveTableOps(tableId))\n tableCacheRef.current.set(tableId, wrapped)\n return wrapped\n },\n [wrapTableOps]\n )\n\n const applyActions = useCallback(\n async (actions: GristUserActionTuple[], applyOptions?: GristApplyUserActionsOptions): Promise<unknown> => {\n if (!docApi) throw new Error(\"Grist docApi is not ready\")\n setActionStatus(\"running\")\n setActionError(null)\n try {\n const out = await coalesceRpc(() => docApi.applyUserActions(actions, applyOptions))\n setActionStatus(\"idle\")\n return out\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n setActionError(message)\n setActionStatus(\"error\")\n throw err\n }\n },\n [docApi, coalesceRpc]\n )\n\n return useMemo(\n () => ({ table, getTable, actionStatus, actionError, applyActions }),\n [table, getTable, actionStatus, actionError, applyActions]\n )\n}\n","import { useCallback, useMemo, useRef, useState } from \"react\"\n\nimport {\n buildReplicaDocumentFromDocApi as buildReplicaDocumentFromDocApiImpl,\n type BuildReplicaDocumentFromDocApiOptions,\n loadColumnMetadataByTable,\n} from \"../../helpers/build-replica-document\"\nimport { isGristNoiseColumn, type GristNoiseColumnsOptions } from \"../../helpers/grist-columns-filters\"\nimport {\n fetchGristTableRows,\n fetchGristRow,\n type FetchGristTableRowsOptions,\n type GristColumnarTable,\n} from \"../../helpers/grist-table-data\"\nimport type { GristSafeParseCellResult, SafeParseGristTableDataOptions } from \"../../helpers/grist-safe-parse\"\nimport type {\n GristDocApi,\n GristFetchSelectedOptions,\n GristReplicaDocument,\n GristRowRecord,\n} from \"../../types\"\nimport { isAccessInsufficientError } from \"../../helpers/grist-sdk-alerts\"\nimport { useGristManagerOptional } from \"../handshake-manager-context\"\nimport { useRpcHeartbeatCoalesce } from \"./use-rpc-heartbeat-coalesce\"\n\nconst SELECTED_FETCH_DEFAULTS: GristFetchSelectedOptions = {\n keepEncoded: false,\n format: \"rows\",\n}\n\nexport type ListTablesOptions = {\n /** When true, include system tables (prefixed with `_grist` or `GristHidden_`). Default: false. */\n includeSystem?: boolean\n}\n\nexport type GristColumnInfo = {\n colId: string\n type?: string\n label?: string\n isFormula?: boolean\n formula?: string\n description?: string\n}\n\nexport type ListColumnsOptions = GristNoiseColumnsOptions & {\n /** When true, include system tables' columns. Default: false. */\n includeSystem?: boolean\n}\n\nexport type UseGristReadsResult = {\n fetchTable: (tableId: string) => Promise<GristColumnarTable>\n fetchTableRows: {\n <T extends Record<string, unknown> = Record<string, unknown>>(\n tableId: string,\n options: FetchGristTableRowsOptions & {\n safeParse: true | Omit<SafeParseGristTableDataOptions, \"columns\" | \"order\">\n }\n ): Promise<GristRowRecord<{ [K in keyof T]: GristSafeParseCellResult<T[K]> | null }>[]>\n <T extends Record<string, unknown> = Record<string, unknown>>(\n tableId: string,\n options?: FetchGristTableRowsOptions\n ): Promise<GristRowRecord<T>[]>\n }\n fetchRow: <T = Record<string, unknown>>(tableId: string, rowId: number) => Promise<GristRowRecord<T> | null>\n listTables: (options?: ListTablesOptions) => Promise<string[]>\n listColumns: (tableId: string, options?: ListColumnsOptions) => Promise<GristColumnInfo[]>\n getDocName: () => Promise<string>\n buildReplicaDocumentFromDocApi: (\n options?: BuildReplicaDocumentFromDocApiOptions\n ) => Promise<GristReplicaDocument>\n fetchSelectedTable: (fetchOptions?: GristFetchSelectedOptions) => Promise<GristColumnarTable>\n fetchSelectedRecord: (rowId: number, fetchOptions?: GristFetchSelectedOptions) => Promise<Record<string, unknown>>\n readError: string | null\n}\n\nexport function useGristReads(docApi: GristDocApi | null): UseGristReadsResult {\n const coalesceRpc = useRpcHeartbeatCoalesce()\n const manager = useGristManagerOptional()\n const [readError, setReadError] = useState<string | null>(null)\n const readErrorRef = useRef<string | null>(null)\n\n /**\n * Pre-flight check: reject immediately when the **confirmed** effective\n * access level is insufficient for full-document reads.\n *\n * Important: the effective level is only known after `onOptions` arrives\n * (`sync.options.state === \"hot\"` → `AUTHZ_REPORT` has been dispatched).\n * Before that the snapshot carries the *declared* level from `grist.ready`,\n * which is often lower than what the user actually set in Grist's panel.\n * Guarding too early would block widgets whose declared level is\n * `\"read table\"` even when the user granted `\"full\"`.\n */\n const requireFullAccess = useCallback(\n (label: string) => {\n const snap = manager?.getSnapshot()\n if (!snap) return\n const { authz, sync } = snap\n if (sync.options.state !== \"hot\") return\n if (authz.state === \"granted\" && authz.level !== \"full\") {\n const msg =\n `${label} requires \"Full document access\". ` +\n `Current access level is \"${authz.level}\". ` +\n 'Set Access level to \"Full document access\" in the Custom widget configuration panel.'\n if (readErrorRef.current !== msg) {\n readErrorRef.current = msg\n setReadError(msg)\n }\n throw new Error(msg)\n }\n },\n [manager]\n )\n\n /** Wrap an RPC call and capture access-insufficient errors as `readError`. */\n const guardedRpc = useCallback(\n async <T>(fn: () => Promise<T>): Promise<T> => {\n try {\n const result = await coalesceRpc(fn)\n if (readErrorRef.current !== null) {\n readErrorRef.current = null\n setReadError(null)\n }\n return result\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n if (isAccessInsufficientError(msg)) {\n if (readErrorRef.current !== msg) {\n readErrorRef.current = msg\n setReadError(msg)\n }\n }\n throw err\n }\n },\n [coalesceRpc]\n )\n\n const fetchTable = useCallback(\n async (tableId: string) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n requireFullAccess(\"fetchTable\")\n return guardedRpc(() => docApi.fetchTable(tableId) as Promise<GristColumnarTable>)\n },\n [docApi, requireFullAccess, guardedRpc]\n )\n\n const fetchRow = useCallback(\n async <T = Record<string, unknown>>(tableId: string, rowId: number) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n requireFullAccess(\"fetchRow\")\n return guardedRpc(() => fetchGristRow<T>(docApi, tableId, rowId))\n },\n [docApi, requireFullAccess, guardedRpc]\n )\n\n const fetchTableRows = useCallback(\n async <T extends Record<string, unknown> = Record<string, unknown>>(\n tableId: string,\n options?: FetchGristTableRowsOptions\n ) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n requireFullAccess(\"fetchTableRows\")\n if (options?.safeParse) {\n return guardedRpc(() =>\n fetchGristTableRows<T>(\n docApi,\n tableId,\n options as FetchGristTableRowsOptions & {\n safeParse: true | Omit<SafeParseGristTableDataOptions, \"columns\" | \"order\">\n }\n )\n )\n }\n if (options) {\n return guardedRpc(() => fetchGristTableRows<T>(docApi, tableId, options))\n }\n return guardedRpc(() => fetchGristTableRows<T>(docApi, tableId))\n },\n [docApi, requireFullAccess, guardedRpc]\n )\n\n const listTables = useCallback(\n async (options?: ListTablesOptions) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return guardedRpc(async () => {\n const out = await Promise.resolve(docApi.listTables())\n const tables = [...out]\n if (options?.includeSystem) return tables\n return tables.filter(\n (t) => !t.startsWith(\"_grist\") && !t.startsWith(\"GristHidden_\")\n )\n })\n },\n [docApi, guardedRpc]\n )\n\n const listColumns = useCallback(\n async (tableId: string, options?: ListColumnsOptions) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n requireFullAccess(\"listColumns\")\n return guardedRpc(async () => {\n const metaByTable = await loadColumnMetadataByTable(docApi)\n const colMeta = metaByTable.get(tableId)\n if (!colMeta) return []\n\n const noiseOpts: GristNoiseColumnsOptions = {\n excludeId: options?.excludeId ?? true,\n excludeGristHelpers: options?.excludeGristHelpers ?? true,\n excludeLoggingColumns: options?.excludeLoggingColumns ?? true,\n excludeManualSort: options?.excludeManualSort ?? true,\n }\n\n const result: GristColumnInfo[] = []\n for (const [colId, meta] of colMeta) {\n if (!options?.includeSystem && isGristNoiseColumn(colId, meta, noiseOpts)) {\n continue\n }\n result.push({\n colId,\n type: meta.type,\n label: meta.label,\n isFormula: meta.isFormula,\n formula: meta.formula,\n description: meta.description,\n })\n }\n return result\n })\n },\n [docApi, requireFullAccess, guardedRpc]\n )\n\n const getDocName = useCallback(async () => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return guardedRpc(async () => String(await Promise.resolve(docApi.getDocName())))\n }, [docApi, guardedRpc])\n\n const buildReplicaDocumentFromDocApi = useCallback(\n async (opts?: BuildReplicaDocumentFromDocApiOptions) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n requireFullAccess(\"buildReplicaDocumentFromDocApi\")\n return guardedRpc(() => buildReplicaDocumentFromDocApiImpl(docApi, opts))\n },\n [docApi, requireFullAccess, guardedRpc]\n )\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 = { ...SELECTED_FETCH_DEFAULTS, ...fetchOptions }\n return guardedRpc(async () => (await impl(merged)) as GristColumnarTable)\n },\n [docApi, guardedRpc]\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 = { ...SELECTED_FETCH_DEFAULTS, ...fetchOptions }\n return guardedRpc(async () => (await impl(rowId, merged)) as Record<string, unknown>)\n },\n [docApi, guardedRpc]\n )\n\n return useMemo(\n () => ({\n fetchTable,\n fetchTableRows,\n fetchRow,\n listTables,\n listColumns,\n getDocName,\n buildReplicaDocumentFromDocApi,\n fetchSelectedTable,\n fetchSelectedRecord,\n readError,\n }),\n [\n fetchTable,\n fetchTableRows,\n fetchRow,\n listTables,\n listColumns,\n getDocName,\n buildReplicaDocumentFromDocApi,\n fetchSelectedTable,\n fetchSelectedRecord,\n readError,\n ]\n )\n}\n","import { useCallback, useMemo } from \"react\"\n\nimport { useRpcHeartbeatCoalesce } from \"./use-rpc-heartbeat-coalesce\"\n\nexport type UseGristWidgetOptionsApiResult = {\n getWidgetOptions: () => Promise<Record<string, unknown> | null>\n getWidgetOption: (key: string) => Promise<unknown>\n setWidgetOption: (key: string, value: unknown) => Promise<void>\n setWidgetOptions: (next: Record<string, unknown>) => Promise<void>\n patchWidgetOptions: (patch: Record<string, unknown>) => Promise<void>\n clearWidgetOptions: () => Promise<void>\n}\n\nexport function useGristWidgetOptionsApi(): UseGristWidgetOptionsApiResult {\n const coalesceRpc = useRpcHeartbeatCoalesce()\n\n const getWidgetOptions = useCallback(\n async () =>\n coalesceRpc(async () => {\n const next = await grist.getOptions()\n return next as Record<string, unknown> | null\n }),\n [coalesceRpc]\n )\n\n const getWidgetOption = useCallback(\n async (key: string) => coalesceRpc(() => Promise.resolve(grist.getOption(key))),\n [coalesceRpc]\n )\n\n const setWidgetOption = useCallback(\n async (key: string, value: unknown) => {\n await coalesceRpc(() => Promise.resolve(grist.setOption(key, value)))\n },\n [coalesceRpc]\n )\n\n const setWidgetOptions = useCallback(\n async (next: Record<string, unknown>) => {\n await coalesceRpc(() => Promise.resolve(grist.setOptions(next)))\n },\n [coalesceRpc]\n )\n\n const patchWidgetOptions = useCallback(\n async (patch: Record<string, unknown>) => {\n await coalesceRpc(async () => {\n const current = (await grist.getOptions()) as Record<string, unknown> | null\n await grist.setOptions({ ...(current ?? {}), ...patch })\n })\n },\n [coalesceRpc]\n )\n\n const clearWidgetOptions = useCallback(\n async () => {\n await coalesceRpc(() => Promise.resolve(grist.clearOptions()))\n },\n [coalesceRpc]\n )\n\n return useMemo(\n () => ({\n getWidgetOptions,\n getWidgetOption,\n setWidgetOption,\n setWidgetOptions,\n patchWidgetOptions,\n clearWidgetOptions,\n }),\n [\n getWidgetOptions,\n getWidgetOption,\n setWidgetOption,\n setWidgetOptions,\n patchWidgetOptions,\n clearWidgetOptions,\n ]\n )\n}\n","import { useCallback, useMemo } from \"react\"\n\nimport type { GristCursorPos } from \"../../types\"\nimport { useRpcHeartbeatCoalesce } from \"./use-rpc-heartbeat-coalesce\"\n\nexport type UseGristLinkingResult = {\n setCursorPosition: (pos: GristCursorPos) => Promise<void>\n setLinkedRowSelection: (rowIds: null | number[]) => Promise<void>\n}\n\nexport function useGristLinking(): UseGristLinkingResult {\n const coalesceRpc = useRpcHeartbeatCoalesce()\n\n const setCursorPosition = useCallback(\n async (pos: GristCursorPos) => {\n if (!grist.setCursorPos) throw new Error(\"setCursorPos is not available in this Grist version\")\n await coalesceRpc(() => Promise.resolve(grist.setCursorPos!(pos)))\n },\n [coalesceRpc]\n )\n\n const setLinkedRowSelection = useCallback(\n async (rowIds: null | number[]) => {\n if (!grist.setSelectedRows) throw new Error(\"setSelectedRows is not available in this Grist version\")\n await coalesceRpc(() => Promise.resolve(grist.setSelectedRows!(rowIds)))\n },\n [coalesceRpc]\n )\n\n return useMemo(\n () => ({ setCursorPosition, setLinkedRowSelection }),\n [setCursorPosition, setLinkedRowSelection]\n )\n}\n","import { useCallback, useMemo, useRef, useState } from \"react\"\n\nimport {\n fetchAttachmentBase64 as fetchAttachmentBase64Core,\n fetchAttachmentBlob as fetchAttachmentBlobCore,\n getAttachmentDownloadUrl as getAttachmentDownloadUrlCore,\n type GristFetchedAttachment,\n type GristFetchedAttachmentBlob,\n} from \"../../helpers/grist-attachment-download\"\nimport {\n uploadGristAttachment as uploadGristAttachmentCore,\n type GristAttachmentUploadResult,\n} from \"../../helpers/grist-attachment-upload\"\nimport {\n fetchWithGristAuth as fetchWithGristAuthCore,\n getGristAccessToken,\n type GristAccessToken,\n} from \"../../helpers/grist-fetch-with-auth\"\nimport { isAccessInsufficientError } from \"../../helpers/grist-sdk-alerts\"\nimport type { GristDocApi } from \"../../types\"\nimport { useRpcHeartbeatCoalesce } from \"./use-rpc-heartbeat-coalesce\"\n\nexport type UseGristAttachmentsRestResult = {\n getAttachmentUrl: (attachmentId: string, options?: { readOnly?: boolean }) => Promise<string>\n fetchAttachmentBase64: (attachmentId: string, options?: { readOnly?: boolean }) => Promise<GristFetchedAttachment>\n fetchAttachmentBlob: (attachmentId: string, options?: { readOnly?: boolean }) => Promise<GristFetchedAttachmentBlob>\n getAccessToken: (options?: { readOnly?: boolean }) => Promise<GristAccessToken>\n fetchWithAuth: (path: string, init?: RequestInit & { readOnly?: boolean }) => Promise<Response>\n uploadAttachment: (\n file: Blob | File,\n options?: { fileName?: string }\n ) => Promise<GristAttachmentUploadResult>\n readError: string | null\n}\n\nexport function useGristAttachmentsRest(docApi: GristDocApi | null): UseGristAttachmentsRestResult {\n const coalesceRpc = useRpcHeartbeatCoalesce()\n const [readError, setReadError] = useState<string | null>(null)\n const readErrorRef = useRef<string | null>(null)\n\n const guardedRpc = useCallback(\n async <T>(fn: () => Promise<T>): Promise<T> => {\n try {\n const result = await coalesceRpc(fn)\n if (readErrorRef.current !== null) {\n readErrorRef.current = null\n setReadError(null)\n }\n return result\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n if (isAccessInsufficientError(msg)) {\n if (readErrorRef.current !== msg) {\n readErrorRef.current = msg\n setReadError(msg)\n }\n }\n throw err\n }\n },\n [coalesceRpc]\n )\n\n const getAttachmentUrl = useCallback(\n async (attachmentId: string, opts?: { readOnly?: boolean }) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return guardedRpc(() => getAttachmentDownloadUrlCore(docApi, attachmentId, opts))\n },\n [docApi, guardedRpc]\n )\n\n const fetchAttachmentBase64 = useCallback(\n async (attachmentId: string, opts?: { readOnly?: boolean }) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return guardedRpc(() => fetchAttachmentBase64Core(docApi, attachmentId, opts))\n },\n [docApi, guardedRpc]\n )\n\n const fetchAttachmentBlob = useCallback(\n async (attachmentId: string, opts?: { readOnly?: boolean }) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return guardedRpc(() => fetchAttachmentBlobCore(docApi, attachmentId, opts))\n },\n [docApi, guardedRpc]\n )\n\n const getAccessToken = useCallback(\n async (opts?: { readOnly?: boolean }) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return guardedRpc(() => getGristAccessToken(docApi, opts))\n },\n [docApi, guardedRpc]\n )\n\n const fetchWithAuth = useCallback(\n (path: string, init?: RequestInit & { readOnly?: boolean }) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return guardedRpc(() => fetchWithGristAuthCore(docApi, path, init))\n },\n [docApi, guardedRpc]\n )\n\n const uploadAttachment = useCallback(\n (file: Blob | File, opts?: { fileName?: string }) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return guardedRpc(() => uploadGristAttachmentCore(docApi, file, opts))\n },\n [docApi, guardedRpc]\n )\n\n return useMemo(\n () => ({\n getAttachmentUrl,\n fetchAttachmentBase64,\n fetchAttachmentBlob,\n getAccessToken,\n fetchWithAuth,\n uploadAttachment,\n readError,\n }),\n [\n getAttachmentUrl,\n fetchAttachmentBase64,\n fetchAttachmentBlob,\n getAccessToken,\n fetchWithAuth,\n uploadAttachment,\n readError,\n ]\n )\n}\n","import { useEffect, useMemo, useState } from \"react\"\n\nimport { parseGristThemePayload } from \"../../helpers/grist-theme-payload\"\nimport type { GristDocApi } from \"../../types\"\n\nexport type GristTheme = \"light\" | \"dark\"\n\nexport type UseGristThemeResult = {\n theme: GristTheme | null\n}\n\nexport function useGristTheme(_docApi: GristDocApi | null): UseGristThemeResult {\n const [theme, setTheme] = useState<GristTheme | null>(null)\n\n useEffect(() => {\n if (typeof grist === \"undefined\" || typeof grist.on !== \"function\") return\n\n const apply = (payload: unknown) => {\n const next = parseGristThemePayload(payload)\n if (next) setTheme(next)\n }\n\n grist.on(\"message\", (msg: unknown) => {\n if (!msg || typeof msg !== \"object\") return\n if (!(\"theme\" in msg)) return\n apply(msg)\n })\n }, [])\n\n return useMemo(() => ({ theme }), [theme])\n}\n","export type GristThemeName = \"light\" | \"dark\"\n\n/**\n * Normalize theme from `grist.on(\"message\")` host payloads (`msg.theme`).\n * Grist sends a theme object with `appearance`; some hosts may send a bare string.\n */\nexport function parseGristThemePayload(payload: unknown): GristThemeName | null {\n if (!payload || typeof payload !== \"object\") return null\n const raw = payload as Record<string, unknown>\n const top = raw.theme\n if (top === \"light\" || top === \"dark\") return top\n if (top && typeof top === \"object\") {\n const appearance = (top as Record<string, unknown>).appearance\n if (appearance === \"light\" || appearance === \"dark\") return appearance\n }\n return null\n}\n","import { useCallback, useMemo } from \"react\"\n\nimport type { GristReadyOptions } from \"../../types\"\nimport { useRpcHeartbeatCoalesce } from \"./use-rpc-heartbeat-coalesce\"\n\nexport type UseGristSectionApiResult = {\n configure: (options: GristReadyOptions) => Promise<void>\n refreshMappings: () => Promise<import(\"../../types\").GristWidgetColumnMap | null>\n}\n\nexport function useGristSectionApi(): UseGristSectionApiResult {\n const coalesceRpc = useRpcHeartbeatCoalesce()\n\n const configure = useCallback(\n 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 coalesceRpc(() => Promise.resolve(grist.sectionApi!.configure!(next)))\n },\n [coalesceRpc]\n )\n\n const refreshMappings = useCallback(\n async () => {\n if (!grist.sectionApi?.mappings) {\n throw new Error(\"grist.sectionApi.mappings is not available in this Grist version\")\n }\n return coalesceRpc(() => grist.sectionApi!.mappings!())\n },\n [coalesceRpc]\n )\n\n return useMemo(() => ({ configure, refreshMappings }), [configure, refreshMappings])\n}\n","import {\n useCallback,\n useEffect,\n useMemo,\n useState,\n useSyncExternalStore,\n type CSSProperties,\n type ReactNode,\n} from \"react\"\n\nimport {\n deriveBoundaryView,\n GRIST_BOUNDARY_PREPARING_COPY,\n type GristBoundaryView,\n} from \"../helpers/grist-boundary-view\"\nimport { deriveCapabilities, initialGristSnapshot } from \"../internal/handshake\"\nimport { useGristManagerOptional } from \"../internal/handshake-manager-context\"\nimport type { UseGristResult } from \"../use-grist\"\nimport { useGristOptional } from \"./grist-widget-provider\"\n\nexport type GristBoundaryGate = \"ready\" | \"canRender\"\n\nexport type GristBoundaryProps = {\n /**\n * Pass an explicit widget instance (e.g. when not using `<GristWidgetProvider>`).\n * Otherwise the boundary reads from the nearest provider.\n */\n widget?: UseGristResult\n /**\n * When `\"canRender\"`, children render only after mappings are usable\n * (`capabilities.canRender`). Use for widgets that require mapped columns.\n */\n gate?: GristBoundaryGate\n /** Rendered while `grist.ready` is in flight. */\n bootingFallback?: ReactNode\n /** Shown when `gate=\"canRender\"` and mappings are not yet usable. */\n preparingFallback?: ReactNode\n /** Rendered when the widget is not embedded in Grist (e.g. opened directly). */\n unavailableFallback?: ReactNode | ((actions: GristBoundaryActions) => ReactNode)\n /** Rendered on any error from `useGristReady`, subscriptions, or actions. */\n errorFallback?: (error: string, actions: GristBoundaryActions) => ReactNode\n /**\n * Delay before showing \"unavailable\" UI. Helps avoid false negatives on slow\n * networks where the plugin API handshake arrives late.\n */\n unavailableGraceMs?: number\n children: ReactNode\n}\n\nexport type GristBoundaryActions = {\n reload: () => Promise<void>\n isReloading: boolean\n}\n\nconst shellStyle: CSSProperties = {\n alignItems: \"center\",\n background: \"var(--background)\",\n boxSizing: \"border-box\",\n color: \"var(--foreground)\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n minHeight: \"100%\",\n padding: \"clamp(16px, 5vh, 32px)\",\n width: \"100%\",\n}\n\nconst cardStyle: CSSProperties = {\n background: \"var(--card)\",\n border: \"1px solid var(--border)\",\n borderRadius: 12,\n boxShadow: \"0 1px 3px rgb(0 0 0 / 0.12)\",\n maxWidth: 420,\n padding: \"20px 22px\",\n textAlign: \"center\",\n width: \"100%\",\n}\n\nconst titleStyle: CSSProperties = {\n color: \"var(--foreground)\",\n fontSize: 15,\n fontWeight: 600,\n lineHeight: 1.35,\n margin: 0,\n}\n\nconst messageStyle: CSSProperties = {\n color: \"var(--muted-foreground)\",\n fontSize: 14,\n lineHeight: 1.5,\n margin: \"10px 0 0\",\n}\n\nconst buttonStyle: CSSProperties = {\n background: \"var(--background)\",\n border: \"1px solid var(--border)\",\n borderRadius: 8,\n color: \"var(--foreground)\",\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 500,\n marginTop: 16,\n padding: \"8px 14px\",\n}\n\nfunction noopSubscribe() {\n return () => {}\n}\n\ntype GristBoundaryScreenProps = {\n title: string\n message: string\n /** Affects WAI-ARIA role only (`alert` vs `status`); copy uses the same neutral styles. */\n tone?: \"default\" | \"error\"\n showRetry?: boolean\n actions?: GristBoundaryActions\n retryLabel?: string\n retryBusyLabel?: string\n}\n\n/** Centered full-viewport chrome for booting / unavailable / error states. */\nexport function GristBoundaryScreen({\n title,\n message,\n tone = \"default\",\n showRetry = false,\n actions,\n retryLabel = \"Try reconnecting\",\n retryBusyLabel = \"Reconnecting…\",\n}: GristBoundaryScreenProps) {\n return (\n <div style={shellStyle} role={tone === \"error\" ? \"alert\" : \"status\"}>\n <div style={cardStyle}>\n <h2 style={titleStyle}>{title}</h2>\n <p style={messageStyle}>{message}</p>\n {showRetry && actions ? (\n <button\n disabled={actions.isReloading}\n onClick={() => void actions.reload()}\n style={{\n ...buttonStyle,\n cursor: actions.isReloading ? \"not-allowed\" : \"pointer\",\n opacity: actions.isReloading ? 0.7 : 1,\n }}\n type=\"button\"\n >\n {actions.isReloading ? retryBusyLabel : retryLabel}\n </button>\n ) : null}\n </div>\n </div>\n )\n}\n\nfunction BootingScreen({ message }: { message: string }) {\n return (\n <GristBoundaryScreen\n title=\"Connecting to Grist\"\n message={message}\n showRetry={false}\n />\n )\n}\n\nfunction blockingScreenFromView(\n view: Extract<GristBoundaryView, { mode: \"blocking\" }>,\n actions: GristBoundaryActions\n): ReactNode {\n return (\n <GristBoundaryScreen\n title={view.title}\n message={view.message}\n tone={view.kind === \"error\" ? \"error\" : \"default\"}\n showRetry={view.showRetry}\n actions={actions}\n retryLabel={view.kind === \"error\" ? \"Try again\" : \"Try reconnecting\"}\n retryBusyLabel={view.kind === \"error\" ? \"Retrying…\" : \"Reconnecting…\"}\n />\n )\n}\n\nfunction legacyBlockingFromWidget(\n w: UseGristResult,\n actions: GristBoundaryActions\n): ReactNode | null {\n if (w.status === \"unavailable\") {\n return (\n <GristBoundaryScreen\n title=\"Open inside Grist\"\n message=\"This page must be opened from a Grist document as a custom widget.\"\n showRetry\n actions={actions}\n />\n )\n }\n if (w.status === \"error\") {\n return (\n <GristBoundaryScreen\n title=\"Something went wrong\"\n message={\n w.error ??\n \"Something went wrong connecting to Grist. Try reconnecting below, or reload the page.\"\n }\n tone=\"error\"\n showRetry\n actions={actions}\n retryLabel=\"Try again\"\n retryBusyLabel=\"Retrying…\"\n />\n )\n }\n if (w.status !== \"ready\") {\n return <BootingScreen message=\"Connecting to Grist…\" />\n }\n return null\n}\n\n/**\n * Standardised loading / unavailable / error chrome for a Grist widget.\n *\n * ```tsx\n * <GristWidgetProvider options={{ requiredAccess: \"full\" }}>\n * <GristBoundary>\n * <MyWidget />\n * </GristBoundary>\n * </GristWidgetProvider>\n * ```\n */\nexport function GristBoundary({\n widget,\n gate = \"ready\",\n bootingFallback,\n preparingFallback,\n unavailableFallback,\n errorFallback,\n unavailableGraceMs = 5000,\n children,\n}: GristBoundaryProps) {\n const fromContext = useGristOptional()\n const w = widget ?? fromContext\n const manager = useGristManagerOptional()\n const snapshot = useSyncExternalStore(\n manager?.subscribe ?? noopSubscribe,\n manager?.getSnapshot ?? initialGristSnapshot,\n initialGristSnapshot\n )\n\n if (!w) {\n throw new Error(\n \"<GristBoundary> requires either a `widget` prop or a parent <GristWidgetProvider>\"\n )\n }\n\n const boundaryView = useMemo(\n () => (manager ? deriveBoundaryView(snapshot) : null),\n [manager, snapshot]\n )\n\n const [showUnavailable, setShowUnavailable] = useState(false)\n const [isReloading, setIsReloading] = useState(false)\n\n useEffect(() => {\n if (w.status !== \"unavailable\") {\n setShowUnavailable(false)\n return\n }\n const timer = window.setTimeout(() => setShowUnavailable(true), unavailableGraceMs)\n return () => window.clearTimeout(timer)\n }, [unavailableGraceMs, w.status])\n\n const reload = useCallback(async () => {\n const MIN_RELOAD_VISIBILITY_MS = 700\n const startedAt = Date.now()\n setIsReloading(true)\n try {\n await w.reload()\n } catch (error) {\n console.error(\"[grist-sdk] reload failed:\", error)\n } finally {\n const elapsed = Date.now() - startedAt\n const remaining = Math.max(0, MIN_RELOAD_VISIBILITY_MS - elapsed)\n if (remaining > 0) {\n await new Promise((resolve) => window.setTimeout(resolve, remaining))\n }\n setIsReloading(false)\n }\n }, [w])\n\n const actions = useMemo<GristBoundaryActions>(\n () => ({ reload, isReloading }),\n [isReloading, reload]\n )\n\n const canRender =\n gate !== \"canRender\" || !manager || deriveCapabilities(snapshot).canRender\n\n const defaultPreparing = (\n <GristBoundaryScreen\n title={GRIST_BOUNDARY_PREPARING_COPY.title}\n message={GRIST_BOUNDARY_PREPARING_COPY.message}\n showRetry={false}\n />\n )\n\n if (!manager) {\n const legacy = legacyBlockingFromWidget(w, actions)\n if (legacy) return <>{legacy}</>\n if (!canRender) return <>{preparingFallback ?? defaultPreparing}</>\n return <>{children}</>\n }\n\n if (w.status === \"unavailable\") {\n if (!showUnavailable) {\n const boot =\n boundaryView?.mode === \"blocking\" && boundaryView.kind === \"booting\"\n ? boundaryView.message\n : \"Connecting to Grist…\"\n return <>{bootingFallback ?? <BootingScreen message={boot} />}</>\n }\n if (typeof unavailableFallback === \"function\") {\n return <>{unavailableFallback(actions)}</>\n }\n if (unavailableFallback) return <>{unavailableFallback}</>\n if (boundaryView?.mode === \"blocking\") {\n return <>{blockingScreenFromView(boundaryView, actions)}</>\n }\n }\n\n if (w.status === \"error\") {\n if (errorFallback) {\n return <>{errorFallback(w.error ?? \"Grist connection error\", actions)}</>\n }\n if (boundaryView?.mode === \"blocking\") {\n return <>{blockingScreenFromView(boundaryView, actions)}</>\n }\n }\n\n if (w.status !== \"ready\") {\n if (boundaryView?.mode === \"blocking\" && boundaryView.kind === \"booting\") {\n return (\n <>\n {bootingFallback ?? <BootingScreen message={boundaryView.message} />}\n </>\n )\n }\n return <>{bootingFallback ?? <BootingScreen message=\"Connecting to Grist…\" />}</>\n }\n\n if (!canRender) {\n return <>{preparingFallback ?? defaultPreparing}</>\n }\n\n return <>{children}</>\n}\n","import { useMemo } from \"react\"\n\nimport { useContext } from \"react\"\n\nimport { useGristOptional } from \"./components/grist-widget-provider\"\nimport { useComposeGristWidgetSlices } from \"./internal/compose-grist-widget\"\nimport {\n GristCoreContext,\n useGristFromProvider,\n useGristCoreContext,\n useGristCurrentTableContext,\n useGristSelectionContext,\n useGristThemeContext,\n useGristWritesContext,\n type GristStatusSliceValue,\n} from \"./internal/contexts\"\nimport { mergeGristResultFromSlices } from \"./internal/merge-grist-result\"\n\nexport type {\n GristCapabilities,\n GristTheme,\n GristWidgetActionStatus,\n GristWidgetMode,\n GristWidgetStatus,\n UseGristOptions,\n UseGristResult,\n} from \"./use-grist-types\"\n\nimport type { UseGristOptions, UseGristResult } from \"./use-grist-types\"\n\nfunction useGristStandalone<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>(\n options?: UseGristOptions\n): UseGristResult<TRow, TMapped> {\n const slices = useComposeGristWidgetSlices(options)\n return useMemo(() => mergeGristResultFromSlices<TRow, TMapped>(slices), [slices])\n}\n\n/**\n * Primary Grist hook — use inside `<GristWidgetProvider>` via `useGristContext()`,\n * or standalone in a single-leaf widget.\n */\nexport function useGrist<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>(\n options?: UseGristOptions\n): UseGristResult<TRow, TMapped> {\n if (useContext(GristCoreContext)) {\n return useGristFromProvider<TRow, TMapped>()\n }\n return useGristStandalone<TRow, TMapped>(options)\n}\n\nexport { useGristContext, useGristOptional } from \"./components/grist-widget-provider\"\n\n/**\n * Slice subscriber: status + current-table info. Re-renders on status, error,\n * `currentTableId`, or `currentTableLoading` changes only.\n *\n * Must be called inside `<GristWidgetProvider>` — for standalone usage use\n * `useGrist()` directly.\n */\nexport function useGristStatus(): GristStatusSliceValue {\n const core = useGristCoreContext()\n const currentTable = useGristCurrentTableContext()\n return useMemo(() => ({ ...core, ...currentTable }), [core, currentTable])\n}\n\n/**\n * Slice subscriber for the selection / mappings / widget-options stream.\n * Must be called inside `<GristWidgetProvider>`.\n */\nexport function useGristSelection<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>() {\n return useGristSelectionContext<TRow, TMapped>()\n}\n\n/**\n * Slice subscriber for writes (`table`, `getTable`, `applyActions`, `actionStatus`).\n * Must be called inside `<GristWidgetProvider>`.\n */\nexport function useGristWrites() {\n return useGristWritesContext()\n}\n\n/**\n * Slice subscriber for the host theme. Must be called inside `<GristWidgetProvider>`.\n */\nexport function useGristTheme() {\n return useGristThemeContext()\n}\n","import { useCallback, useContext, useEffect, useMemo, useState } from \"react\"\n\nimport { buildReplicaDocumentFromDocApi } from \"./helpers/build-replica-document\"\nimport { isGristNoiseColumn, type GristNoiseColumnsOptions } from \"./helpers/grist-columns-filters\"\nimport {\n buildReplicaJsonPayload,\n type ReplicaJsonIncludeRows,\n} from \"./helpers/replica-normalize\"\nimport { GristReadsContext } from \"./internal/contexts\"\nimport { useGristReady } from \"./low-level-hooks/use-grist-ready\"\nimport type {\n GristDocumentMode,\n GristReadyOptions,\n GristReplicaColumn,\n GristReplicaDocument,\n GristReplicaTable,\n GristRequiredAccess,\n} from \"./types\"\n\ntype ColumnExcludeContext = {\n tableId: string\n colId: string\n col: GristReplicaColumn\n}\n\nexport type UseGristSchemaOptions = {\n requiredAccess?: GristRequiredAccess\n tableId?: string\n excludeSystemTableData?: boolean\n /**\n * How row bodies are included in the replica document.\n * Default `schema+samples`.\n */\n replicaRowMode?: GristDocumentMode\n /** When `replicaRowMode` is `schema+samples`, max rows per table. Default 10. */\n sampleRowLimit?: number\n /** Stored on the replica as `source` (e.g. for logging). */\n source?: string\n} & GristNoiseColumnsOptions & {\n extraExcludeColumn?: (ctx: ColumnExcludeContext) => boolean\n } & Pick<GristReadyOptions, \"columns\" | \"allowSelectBy\" | \"hasCustomOptions\" | \"onEditOptions\">\n\n/** Selected table slice with `tableId` for consumers that expect it on the object. */\nexport type GristSchemaTableView = GristReplicaTable & { tableId: string }\n\n/** Options for `getDocumentJson` / `buildDocumentJson` on the return value of {@link useGristSchema}. */\nexport type ReplicaDocumentJsonOptions = {\n /** How row arrays appear in JSON. Default `full` (all rows currently on the document). */\n includeRows?: ReplicaJsonIncludeRows\n /** Cap per table when `includeRows` is `samples`. Default 10. */\n sampleRowLimit?: number\n space?: number\n}\n\nexport type UseGristSchemaResult = {\n isAvailable: boolean | null\n /** Canonical replica document. */\n document: GristReplicaDocument | null\n /** Same reference as `document`. */\n replicaDocument: GristReplicaDocument | null\n table: GristSchemaTableView | null\n documentJson: string | null\n getDocumentJson: (options?: ReplicaDocumentJsonOptions) => string | null\n buildDocumentJson: (document: GristReplicaDocument, options?: ReplicaDocumentJsonOptions) => string\n tableJson: string | null\n getTableJson: (options?: ReplicaDocumentJsonOptions) => string | null\n buildTableJson: (table: GristSchemaTableView, options?: ReplicaDocumentJsonOptions) => string\n isNoiseColumnId: (colId: string, col?: GristReplicaColumn) => boolean\n sortColumnIds: (colIds: string[], columns: Record<string, GristReplicaColumn>) => string[]\n loading: boolean\n error: string | null\n reload: () => Promise<void>\n}\n\nfunction filterReplicaDocumentColumns(\n document: GristReplicaDocument,\n options?: GristNoiseColumnsOptions,\n extraExcludeColumn?: (ctx: ColumnExcludeContext) => boolean\n): GristReplicaDocument {\n return {\n ...document,\n tables: Object.fromEntries(\n Object.entries(document.tables).map(([tableId, table]) => [\n tableId,\n {\n ...table,\n columns: Object.fromEntries(\n Object.entries(table.columns ?? {}).filter(([colId, col]) => {\n if (isGristNoiseColumn(colId, col, options)) return false\n if (extraExcludeColumn?.({ tableId, colId, col })) return false\n return true\n })\n ),\n },\n ])\n ),\n }\n}\n\n/**\n * Grist replica-document hook: metadata + optional decoded `rows` per table.\n */\nexport function useGristSchema(options?: UseGristSchemaOptions): UseGristSchemaResult {\n const requiredAccess = options?.requiredAccess ?? \"read table\"\n const requestedTableId = options?.tableId\n const excludeSystemTableData = options?.excludeSystemTableData ?? true\n const replicaRowMode = options?.replicaRowMode ?? \"schema+samples\"\n const sampleRowLimit = options?.sampleRowLimit ?? 10\n const replicaSource = options?.source\n const excludeId = options?.excludeId ?? true\n const excludeGristHelpers = options?.excludeGristHelpers ?? true\n const excludeLoggingColumns = options?.excludeLoggingColumns ?? true\n const excludeManualSort = options?.excludeManualSort ?? false\n const extraExcludeColumn = options?.extraExcludeColumn\n\n const { isAvailable, 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 // buildReplicaDocumentFromDocApi so access-insufficient errors flow through\n // the provider's readError → SDK alert system (smooth alert).\n const providerBuildReplica = useContext(GristReadsContext)?.buildReplicaDocumentFromDocApi\n\n const [document, setDocument] = useState<GristReplicaDocument | null>(null)\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const includeRowsForBuild: false | \"samples\" | \"full\" =\n replicaRowMode === \"schema-only\" ? false : replicaRowMode === \"schema+data\" ? \"full\" : \"samples\"\n\n const load = useCallback(async () => {\n if (!docApi) return\n setLoading(true)\n setError(null)\n try {\n const buildOpts = {\n includeSystemTableData: !excludeSystemTableData,\n includeRows: includeRowsForBuild,\n sampleRowLimit,\n source: replicaSource,\n }\n const raw = providerBuildReplica\n ? await providerBuildReplica(buildOpts)\n : await buildReplicaDocumentFromDocApi(docApi, buildOpts)\n const filtered = filterReplicaDocumentColumns(\n raw,\n {\n excludeId,\n excludeGristHelpers,\n excludeLoggingColumns,\n excludeManualSort,\n },\n extraExcludeColumn\n )\n setDocument(filtered)\n } catch (err) {\n setDocument(null)\n setError(err instanceof Error ? err.message : String(err))\n } finally {\n setLoading(false)\n }\n }, [\n docApi,\n providerBuildReplica,\n excludeSystemTableData,\n replicaRowMode,\n sampleRowLimit,\n excludeId,\n excludeGristHelpers,\n excludeLoggingColumns,\n excludeManualSort,\n extraExcludeColumn,\n replicaSource,\n ])\n\n useEffect(() => {\n if (docApi) void load()\n }, [docApi, load])\n\n const buildDocumentJson = useCallback((target: GristReplicaDocument, options?: ReplicaDocumentJsonOptions): string => {\n const includeRows = options?.includeRows ?? \"full\"\n const space = options?.space ?? 2\n const payload = buildReplicaJsonPayload(target, {\n includeRows,\n sampleRowLimit: options?.sampleRowLimit ?? sampleRowLimit,\n })\n return JSON.stringify(payload, null, space)\n }, [sampleRowLimit])\n\n const getDocumentJson = useCallback(\n (options?: ReplicaDocumentJsonOptions): string | null => {\n if (!document) return null\n return buildDocumentJson(document, options)\n },\n [document, buildDocumentJson]\n )\n\n const table = useMemo((): GristSchemaTableView | null => {\n if (!document || !requestedTableId) return null\n const slice = document.tables[requestedTableId]\n if (!slice) return null\n return { tableId: requestedTableId, ...slice }\n }, [document, requestedTableId])\n\n const buildTableJson = useCallback(\n (target: GristSchemaTableView, options?: ReplicaDocumentJsonOptions): string => {\n const includeRows = options?.includeRows ?? \"full\"\n const limit = options?.sampleRowLimit ?? sampleRowLimit\n const space = options?.space ?? 2\n const { tableId, ...rest } = target\n let body: GristReplicaTable = { ...rest }\n if (includeRows === \"none\") {\n const { rows: _r, ...r } = body\n body = r\n } else if (includeRows === \"samples\") {\n const r = body.rows ?? []\n body = { ...body, rows: r.slice(0, limit) }\n }\n return JSON.stringify({ tableId, ...body }, null, space)\n },\n [sampleRowLimit]\n )\n\n const getTableJson = useCallback(\n (options?: ReplicaDocumentJsonOptions): string | null => {\n if (!table) return null\n return buildTableJson(table, options)\n },\n [table, buildTableJson]\n )\n\n const noiseColumnMatcher = useCallback(\n (colId: string, col?: GristReplicaColumn): boolean =>\n isGristNoiseColumn(colId, col, {\n excludeId,\n excludeGristHelpers,\n excludeLoggingColumns,\n excludeManualSort,\n }),\n [excludeId, excludeGristHelpers, excludeLoggingColumns, excludeManualSort]\n )\n\n const sortColumns = useCallback((colIds: string[], columns: Record<string, GristReplicaColumn>): string[] => {\n return [...colIds].sort((a, b) => {\n const la = (columns[a]?.label || a).toLowerCase()\n const lb = (columns[b]?.label || b).toLowerCase()\n if (la !== lb) return la.localeCompare(lb)\n return a.localeCompare(b)\n })\n }, [])\n\n return {\n isAvailable,\n document,\n replicaDocument: document,\n table,\n documentJson: document ? buildDocumentJson(document) : null,\n getDocumentJson,\n buildDocumentJson,\n tableJson: table ? buildTableJson(table) : null,\n getTableJson,\n buildTableJson,\n isNoiseColumnId: noiseColumnMatcher,\n sortColumnIds: sortColumns,\n loading,\n error: readyError ?? error,\n reload: load,\n }\n}\n","import { useGristCore, type UseGristCoreOptions } from \"../internal/hooks/use-grist-core\"\nimport type { GristDocApi, GristReadyOptions } from \"../types\"\n\nexport type UseGristReadyOptions = GristReadyOptions & {\n availabilityMaxAttempts?: number\n availabilityIntervalMs?: number\n logWhenNotEmbedded?: boolean\n}\n\nexport type UseGristReadyResult = {\n isAvailable: boolean | null\n docApi: GristDocApi | null\n error: string | null\n reload: () => Promise<void>\n}\n\n/**\n * Handshake-backed `grist.ready` — delegates to {@link useGristCore} (FSM).\n *\n * Prefer `<GristWidgetProvider>` + `useGrist()` for full widget state; use this\n * hook when you only need `docApi` and connection status.\n */\nexport function useGristReady(options?: UseGristReadyOptions): UseGristReadyResult {\n const { isAvailable, docApi, error, reload } = useGristCore(options)\n return { isAvailable, docApi, error, reload }\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\n\nimport {\n useGristSelectionContext,\n useGristWidgetOptionsApiContext,\n} from \"../internal/contexts\"\n\nexport type UseGristWidgetOptionsFromContextConfig<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 key. When set, this hook reads/writes\n * `options[namespace]` instead of the whole options blob.\n */\n namespace?: string\n}\n\nexport type UseGristWidgetOptionsFromContextResult<T> = {\n options: T\n /** True until Grist has responded with the initial `onOptions` payload. */\n loading: boolean\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 * Typed widget options hook designed for use **inside a `<GristWidgetProvider>`**.\n *\n * Unlike `useGristWidgetOptions()` (which calls `useGristReady()` and conflicts\n * with the provider), this hook reads from the provider's existing context —\n * `widgetOptions` for reactive reads, and `patchWidgetOptions` / `setWidgetOptions`\n * for writes.\n *\n * ```tsx\n * function MyConfigPanel() {\n * const { options, patchOptions } = useGristWidgetOptionsFromContext({\n * defaults: { color: '#FF0000', showLabels: true },\n * })\n * return <input value={options.color} onChange={e => patchOptions({ color: e.target.value })} />\n * }\n * ```\n */\nexport function useGristWidgetOptionsFromContext<T extends Record<string, unknown>>(\n config: UseGristWidgetOptionsFromContextConfig<T>\n): UseGristWidgetOptionsFromContextResult<T> {\n const debounceMs = config.debounceMs ?? 250\n const selection = useGristSelectionContext()\n const optionsApi = useGristWidgetOptionsApiContext()\n\n const defaultsRef = useRef(config.defaults)\n useEffect(() => {\n defaultsRef.current = config.defaults\n }, [config.defaults])\n\n const rawOptions = selection.widgetOptions\n const hasReceived = rawOptions !== null\n\n const merged = useMemo(\n () => mergeWithDefaults(defaultsRef.current, rawOptions, config.namespace),\n [rawOptions, config.namespace]\n )\n\n const [localOverride, setLocalOverride] = useState<T | null>(null)\n const options = localOverride ?? merged\n\n useEffect(() => {\n setLocalOverride(null)\n }, [rawOptions])\n\n const debounceRef = useRef<number | null>(null)\n\n const flushWrite = useCallback(\n async (value: T) => {\n if (config.namespace) {\n await optionsApi.setWidgetOption(config.namespace, value)\n } else {\n await optionsApi.setWidgetOptions({ ...value })\n }\n },\n [config.namespace, optionsApi]\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 setOptions = useCallback(\n (next: T) => {\n setLocalOverride(next)\n scheduleWrite(next)\n },\n [scheduleWrite]\n )\n\n const patchOptions = useCallback(\n (patch: Partial<T>) => {\n setLocalOverride((prev) => {\n const base = prev ?? merged\n const next = { ...base, ...patch }\n scheduleWrite(next)\n return next\n })\n },\n [merged, 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 setLocalOverride(null)\n await flushWrite(next)\n }, [flushWrite])\n\n return useMemo(\n () => ({\n options,\n loading: !hasReceived,\n setOptions,\n patchOptions,\n reset,\n }),\n [options, hasReceived, setOptions, patchOptions, reset]\n )\n}\n","import { useEffect } from \"react\"\n\nexport type UseWidgetMetadataInput = {\n title: string\n description: string\n syncToParent?: boolean\n}\n\nexport function useWidgetMetadata(input?: UseWidgetMetadataInput | null) {\n useEffect(() => {\n if (!input) return\n\n const { title, description, syncToParent = true } = input\n const canonicalUrl = window.location.href\n\n document.title = title\n setMetaTag(\"name\", \"title\", title)\n setMetaTag(\"name\", \"description\", description)\n setMetaTag(\"property\", \"og:title\", title)\n setMetaTag(\"property\", \"og:description\", description)\n setMetaTag(\"property\", \"og:type\", \"website\")\n setMetaTag(\"property\", \"og:url\", canonicalUrl)\n setMetaTag(\"name\", \"twitter:card\", \"summary\")\n setMetaTag(\"name\", \"twitter:title\", title)\n setMetaTag(\"name\", \"twitter:description\", description)\n\n if (!syncToParent) return\n window.parent?.postMessage(\n {\n source: \"grist-playground-widget\",\n type: \"metadata\",\n title,\n description,\n },\n \"*\"\n )\n }, [input])\n}\n\nfunction setMetaTag(key: \"name\" | \"property\", value: string, content: string) {\n let meta = document.head.querySelector<HTMLMetaElement>(\n `meta[${key}=\"${value}\"]`\n )\n if (!meta) {\n meta = document.createElement(\"meta\")\n meta.setAttribute(key, value)\n document.head.appendChild(meta)\n }\n meta.setAttribute(\"content\", content)\n}\n"],"mappings":"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","names":["computeRowCount","sortRowsByGristOrder","useGristTheme","computeRowCount","manualSortKey","sortRowsByGristOrder","computeRowCount","nextAuthz","import_react","ACCESS_RANK","inFlight","grist","grist","inFlight","embedded","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","out","import_react","import_react","buildReplicaDocumentFromDocApi","import_react","import_react","import_react","fetchAttachmentBase64","fetchAttachmentBlob","import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","noopSubscribe","import_react","useGristTheme","import_react","document","options","import_react","import_react"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/sdk/helpers/grist-attachment-download.ts","../src/sdk/helpers/grist-fetch-with-auth.ts","../src/sdk/helpers/grist-value-codec.ts","../src/sdk/helpers/grist-attachment-upload.ts","../src/sdk/helpers/grist-safe-parse.ts","../src/sdk/helpers/grist-widget-options.ts","../src/sdk/helpers/grist-table-data.ts","../src/sdk/helpers/grist-user-actions.ts","../src/sdk/helpers/grist-columns-filters.ts","../src/sdk/helpers/grist-schema-formula.ts","../src/sdk/helpers/build-replica-document.ts","../src/sdk/helpers/replica-normalize.ts","../src/sdk/helpers/grist-mappings.ts","../src/sdk/internal/handshake/access.ts","../src/sdk/internal/handshake/types.ts","../src/sdk/internal/handshake/actions.ts","../src/sdk/internal/handshake/mapping-resolver.ts","../src/sdk/internal/handshake/reducer.ts","../src/sdk/internal/handshake/derive.ts","../src/sdk/helpers/grist-boundary-view.ts","../src/sdk/helpers/grist-widget-interaction.ts","../src/sdk/helpers/grist-sdk-alerts.ts","../src/sdk/hooks/use-grist-sdk-alert-descriptors.ts","../src/sdk/internal/handshake-manager-context.ts","../src/sdk/internal/ready-singleton.ts","../src/sdk/internal/build-manager-options.ts","../src/sdk/internal/handshake/effects/detect.ts","../src/sdk/internal/handshake/effects/negotiate.ts","../src/sdk/internal/subscriptions.ts","../src/sdk/internal/handshake/effects/subscriptions.ts","../src/sdk/internal/handshake/effects/mappings.ts","../src/sdk/internal/handshake/effects/heartbeat.ts","../src/sdk/internal/handshake/authz-from-options-cache.ts","../src/sdk/internal/handshake/environment.ts","../src/sdk/internal/handshake/manager.ts","../src/sdk/internal/embedded-handshake-manager.ts","../src/sdk/components/grist-widget-provider.tsx","../src/sdk/internal/contexts.tsx","../src/sdk/internal/merge-grist-result.ts","../src/sdk/internal/grist-widget-context-tree.tsx","../src/sdk/internal/compose-grist-widget.ts","../src/sdk/internal/hooks/use-grist-core.ts","../src/sdk/internal/hooks/use-grist-current-table.ts","../src/sdk/internal/hooks/use-rpc-heartbeat-coalesce.ts","../src/sdk/internal/hooks/use-grist-selection.ts","../src/sdk/internal/hooks/use-grist-table-ops-bound.ts","../src/sdk/internal/hooks/use-grist-reads.ts","../src/sdk/internal/hooks/use-grist-widget-options-api.ts","../src/sdk/internal/hooks/use-grist-linking.ts","../src/sdk/internal/hooks/use-grist-attachments-rest.ts","../src/sdk/internal/hooks/use-grist-theme.ts","../src/sdk/helpers/grist-theme-payload.ts","../src/sdk/internal/hooks/use-grist-section-api.ts","../src/sdk/components/grist-boundary.tsx","../src/sdk/use-grist.ts","../src/sdk/use-grist-schema.ts","../src/sdk/low-level-hooks/use-grist-ready.ts","../src/sdk/mid-level-hooks/use-grist-widget-options-from-context.ts","../src/sdk/use-widget-metadata.ts","../src/sdk/index.ts"],"sourcesContent":["export * from \"./sdk\"","import type { GristDocApi } from \"../types\"\n\nexport type GristFetchedAttachment = {\n base64: string\n contentType: string\n}\n\nexport type GristFetchedAttachmentBlob = {\n blob: Blob\n contentType: string\n}\n\nfunction attachmentIdFromObjectRecord(record: Record<string, unknown>): string | undefined {\n for (const candidate of [record.id, record.attachmentId, record.fileId]) {\n if (candidate === undefined || candidate === null) continue\n return String(candidate)\n }\n return undefined\n}\n\n/**\n * All attachment ids found in a Grist attachment cell value (ordered, deduped).\n * Attachment columns are usually an **array** of file refs; a single id or one JSON object is also supported.\n */\nexport function extractGristAttachmentIdsFromCell(value: unknown): string[] {\n const out: string[] = []\n const seen = new Set<string>()\n const push = (id: string) => {\n if (seen.has(id)) return\n seen.add(id)\n out.push(id)\n }\n\n const walk = (v: unknown): void => {\n if (v === undefined || v === null) return\n if (typeof v === \"number\") {\n push(String(v))\n return\n }\n if (typeof v === \"string\") {\n const trimmed = v.trim()\n if (!trimmed) return\n if (/^\\d+$/.test(trimmed)) {\n push(trimmed)\n return\n }\n try {\n walk(JSON.parse(trimmed) as unknown)\n } catch {\n /* ignore */\n }\n return\n }\n if (Array.isArray(v)) {\n for (const item of v) walk(item)\n return\n }\n if (typeof v === \"object\") {\n const record = v as Record<string, unknown>\n const direct = attachmentIdFromObjectRecord(record)\n if (direct !== undefined) {\n push(direct)\n return\n }\n for (const nested of Object.values(record)) walk(nested)\n }\n }\n\n walk(value)\n return out\n}\n\n/** First attachment id in the cell, if any (see {@link extractGristAttachmentIdsFromCell}). */\nexport function extractGristAttachmentId(value: unknown): string | undefined {\n return extractGristAttachmentIdsFromCell(value)[0]\n}\n\n/**\n * Signed Grist download URL for a single attachment id (`getAccessToken` + query auth).\n */\nexport async function getAttachmentDownloadUrl(\n docApi: GristDocApi,\n attachmentId: string,\n options?: { readOnly?: boolean }\n): Promise<string> {\n const getAccessToken = docApi.getAccessToken\n if (!getAccessToken) {\n throw new Error(\"getAccessToken is not available on docApi\")\n }\n const { token, baseUrl } = await getAccessToken({ readOnly: options?.readOnly ?? false })\n return `${baseUrl}/attachments/${attachmentId}/download?auth=${token}`\n}\n\n/** URL for the `index`’th attachment in a cell value (0-based). */\nexport async function getAttachmentDownloadUrlForCell(\n docApi: GristDocApi,\n cellValue: unknown,\n index: number,\n options?: { readOnly?: boolean }\n): Promise<string | null> {\n const ids = extractGristAttachmentIdsFromCell(cellValue)\n const id = ids[index]\n if (!id) return null\n return getAttachmentDownloadUrl(docApi, id, options)\n}\n\nasync function fetchBytesFromSignedAttachmentUrl(url: string): Promise<{\n buffer: ArrayBuffer\n contentType: string\n}> {\n const response = await fetch(url)\n const contentType = response.headers.get(\"content-type\")?.trim() || \"application/octet-stream\"\n if (!response.ok) {\n throw new Error(`Attachment download failed (${response.status})`)\n }\n const buffer = await response.arrayBuffer()\n return { buffer, contentType }\n}\n\nfunction bufferToBase64(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer)\n let binary = \"\"\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i])\n return btoa(binary)\n}\n\n/** Token + URL + fetch for one attachment id. */\nexport async function fetchAttachmentBase64(\n docApi: GristDocApi,\n attachmentId: string,\n options?: { readOnly?: boolean }\n): Promise<GristFetchedAttachment> {\n const url = await getAttachmentDownloadUrl(docApi, attachmentId, options)\n const { buffer, contentType } = await fetchBytesFromSignedAttachmentUrl(url)\n return { base64: bufferToBase64(buffer), contentType }\n}\n\n/** Download attachment bytes as a `Blob` (preferred for large files). */\nexport async function fetchAttachmentBlob(\n docApi: GristDocApi,\n attachmentId: string,\n options?: { readOnly?: boolean }\n): Promise<GristFetchedAttachmentBlob> {\n const url = await getAttachmentDownloadUrl(docApi, attachmentId, options)\n const { buffer, contentType } = await fetchBytesFromSignedAttachmentUrl(url)\n return { blob: new Blob([buffer], { type: contentType }), contentType }\n}\n\n/** Download the `index`’th attachment in a cell (0-based). */\nexport async function fetchAttachmentBase64ForCell(\n docApi: GristDocApi,\n cellValue: unknown,\n index: number,\n options?: { readOnly?: boolean }\n): Promise<GristFetchedAttachment | null> {\n const url = await getAttachmentDownloadUrlForCell(docApi, cellValue, index, options)\n if (!url) return null\n const { buffer, contentType } = await fetchBytesFromSignedAttachmentUrl(url)\n return { base64: bufferToBase64(buffer), contentType }\n}\n","import type { GristDocApi } from \"../types\"\n\nexport type GristAccessToken = {\n token: string\n baseUrl: string\n}\n\ntype TokenCacheEntry = {\n token: GristAccessToken\n fetchedAt: number\n}\n\nconst TOKEN_TTL_MS = 45_000\nconst cache = new Map<string, TokenCacheEntry>()\nconst inFlight = new Map<string, Promise<GristAccessToken>>()\n\nfunction cacheKey(readOnly: boolean): string {\n return readOnly ? \"ro\" : \"rw\"\n}\n\n/**\n * Returns an access token suitable for calling Grist's REST API directly.\n * Tokens are short-lived; results are cached briefly and coalesced per readOnly flag.\n */\nexport async function getGristAccessToken(\n docApi: GristDocApi,\n options?: { readOnly?: boolean }\n): Promise<GristAccessToken> {\n if (!docApi.getAccessToken) {\n throw new Error(\"getAccessToken is not available on docApi (need higher access level)\")\n }\n\n const readOnly = options?.readOnly ?? false\n const key = cacheKey(readOnly)\n const now = Date.now()\n const hit = cache.get(key)\n if (hit && now - hit.fetchedAt < TOKEN_TTL_MS) {\n return hit.token\n }\n\n const pending = inFlight.get(key)\n if (pending) return pending\n\n const next = docApi.getAccessToken({ readOnly }).then((token) => {\n cache.set(key, { token, fetchedAt: Date.now() })\n inFlight.delete(key)\n return token\n })\n\n inFlight.set(key, next)\n return next\n}\n\n/** Clear cached tokens (tests or after auth errors). */\nexport function clearGristAccessTokenCache(): void {\n cache.clear()\n inFlight.clear()\n}\n\n/**\n * `fetch()` against Grist's REST API with the doc access token attached.\n */\nexport async function fetchWithGristAuth(\n docApi: GristDocApi,\n path: string,\n init?: RequestInit & { readOnly?: boolean }\n): Promise<Response> {\n const readOnly = init?.readOnly ?? false\n let token: GristAccessToken\n try {\n token = await getGristAccessToken(docApi, { readOnly })\n } catch (err) {\n clearGristAccessTokenCache()\n throw err\n }\n\n const isAbsolute = /^https?:\\/\\//i.test(path)\n const cleanPath = isAbsolute ? path : path.startsWith(\"/\") ? path : `/${path}`\n const method = (init?.method ?? \"GET\").toUpperCase()\n\n const url = isAbsolute\n ? new URL(path)\n : new URL(`${token.baseUrl.replace(/\\/$/, \"\")}${cleanPath}`)\n\n // Grist signs widget REST calls with a short-lived `auth` query parameter.\n // Do not send `Authorization: Bearer` from the browser: many Grist deployments\n // omit it from Access-Control-Allow-Headers, which breaks POST (e.g. attachment upload).\n if (!url.searchParams.has(\"auth\")) url.searchParams.set(\"auth\", token.token)\n\n const headers = new Headers(init?.headers ?? {})\n headers.delete(\"Authorization\")\n\n const response = await fetch(url.toString(), { ...init, headers })\n if (response.status === 401) {\n clearGristAccessTokenCache()\n const retryToken = await getGristAccessToken(docApi, { readOnly })\n url.searchParams.set(\"auth\", retryToken.token)\n return fetch(url.toString(), { ...init, headers })\n }\n return response\n}\n","/**\n * Encoding helpers for Grist cell values.\n *\n * Grist sends some types as marshalled tuples or numeric epochs. This file\n * exposes pure decode/encode functions so widget code never has to spelunk\n * Grist's wire format.\n *\n * References: Grist `grist/RowRecord` and `grist/DocActions` typings.\n */\n\nimport type { GristReplicaColumn } from \"../types\"\n\n/** `[\"E\", \"ErrorClass\", \"message\", traceback?]` — Grist error sentinel. */\nexport type GristEncodedError = [\"E\", string, string?, string?]\n/** `[\"L\", ...items]` — list (used for ChoiceList, RefList, Attachments). */\nexport type GristEncodedList = [\"L\", ...unknown[]]\n/** `[\"D\", epochSeconds, \"tz/Name\"]` — DateTime with timezone. */\nexport type GristEncodedDateTime = [\"D\", number, string]\n/** `[\"d\", epochSeconds]` — Date (no time). */\nexport type GristEncodedDate = [\"d\", number]\n/** `[\"R\", tableId, rowId]` — explicit reference. */\nexport type GristEncodedRef = [\"R\", string, number]\n/** `[\"r\", rowId]` — bare reference (when table is contextual). */\nexport type GristEncodedBareRef = [\"r\", number]\n/** `[\"P\", encoded]` — pending marker. */\nexport type GristEncodedPending = [\"P\"]\n\nexport type GristDecodedValue =\n | null\n | string\n | number\n | boolean\n | Date\n | GristDecodedValue[]\n | { __error: true; type: string; message?: string; traceback?: string }\n | { __ref: true; tableId?: string; rowId: number }\n\nconst MARSHALLED_TAGS = new Set([\"E\", \"L\", \"D\", \"d\", \"R\", \"r\", \"P\"])\n\nfunction isMarshalledTuple(value: unknown): value is unknown[] {\n return (\n Array.isArray(value) &&\n typeof value[0] === \"string\" &&\n value[0].length <= 2 &&\n MARSHALLED_TAGS.has(value[0])\n )\n}\n\n/**\n * Normalises a Grist `fetchTable` cell that points at a row in another table.\n * Most payloads use a bare numeric row id, but `Ref:*` values may appear as\n * `[\"R\", tableId, rowId]` or `[\"r\", rowId]` (same shape as {@link decodeGristValue}).\n */\nexport function coerceGristDocApiRefRowId(value: unknown): number | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) return value\n if (!Array.isArray(value) || value.length < 2) return undefined\n const tag = value[0]\n if (tag === \"R\" && typeof value[2] === \"number\" && Number.isFinite(value[2])) return value[2]\n if (tag === \"r\" && typeof value[1] === \"number\" && Number.isFinite(value[1])) return value[1]\n return undefined\n}\n\nfunction looksLikeAttachmentColumn(column?: GristReplicaColumn): boolean {\n return column?.type === \"Attachments\"\n}\n\nfunction looksLikeChoiceListColumn(column?: GristReplicaColumn): boolean {\n return column?.type === \"ChoiceList\"\n}\n\nfunction looksLikeRefListColumn(column?: GristReplicaColumn): boolean {\n return typeof column?.type === \"string\" && column.type.startsWith(\"RefList:\")\n}\n\nfunction looksLikeRefColumn(column?: GristReplicaColumn): boolean {\n return typeof column?.type === \"string\" && column.type.startsWith(\"Ref:\")\n}\n\nfunction looksLikeDateColumn(column?: GristReplicaColumn): boolean {\n return column?.type === \"Date\"\n}\n\nfunction looksLikeDateTimeColumn(column?: GristReplicaColumn): boolean {\n return typeof column?.type === \"string\" && column.type.startsWith(\"DateTime\")\n}\n\n/**\n * Decodes a Grist cell value into an idiomatic JS value.\n *\n * Pass the column's metadata (from `useGristSchema` or `_grist_Tables_column`)\n * for type-aware decoding (e.g. `Date` columns return `Date` even when stored as a number).\n */\nexport function decodeGristValue(value: unknown, column?: GristReplicaColumn): GristDecodedValue {\n if (value === null || value === undefined) return null\n\n if (isMarshalledTuple(value)) {\n const tag = value[0] as string\n switch (tag) {\n case \"E\":\n return {\n __error: true,\n type: typeof value[1] === \"string\" ? value[1] : \"Error\",\n message: typeof value[2] === \"string\" ? value[2] : undefined,\n traceback: typeof value[3] === \"string\" ? value[3] : undefined,\n }\n case \"L\":\n return value.slice(1).map((v) => decodeGristValue(v, undefined)) as GristDecodedValue[]\n case \"D\":\n if (typeof value[1] === \"number\") return new Date(value[1] * 1000)\n return null\n case \"d\":\n if (typeof value[1] === \"number\") return new Date(value[1] * 1000)\n return null\n case \"R\":\n return {\n __ref: true,\n tableId: typeof value[1] === \"string\" ? value[1] : undefined,\n rowId: typeof value[2] === \"number\" ? value[2] : 0,\n }\n case \"r\":\n return { __ref: true, rowId: typeof value[1] === \"number\" ? value[1] : 0 }\n case \"P\":\n return null\n default:\n return null\n }\n }\n\n if (looksLikeDateColumn(column) || looksLikeDateTimeColumn(column)) {\n if (typeof value === \"number\" && Number.isFinite(value)) return new Date(value * 1000)\n }\n\n if (looksLikeRefColumn(column) && typeof value === \"number\") {\n return { __ref: true, rowId: value }\n }\n\n if ((looksLikeRefListColumn(column) || looksLikeChoiceListColumn(column) || looksLikeAttachmentColumn(column)) && Array.isArray(value)) {\n return value.map((v) => decodeGristValue(v, undefined)) as GristDecodedValue[]\n }\n\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") return value\n if (Array.isArray(value)) return value.map((v) => decodeGristValue(v, undefined)) as GristDecodedValue[]\n return null\n}\n\n/** Convenience: true when the cell is a Grist error sentinel. */\nexport function isGristCellError(value: unknown): value is GristEncodedError {\n return Array.isArray(value) && value[0] === \"E\"\n}\n\n/**\n * Encodes a JS value into Grist's expected wire form for a given column type.\n *\n * Use before passing values to `applyUserActions` or `TableOperations.update`\n * for `Date`, `DateTime`, `Ref`, `RefList`, and `ChoiceList` columns.\n */\nexport function encodeGristValue(value: unknown, column?: GristReplicaColumn): unknown {\n if (value === null || value === undefined) return null\n\n if (looksLikeDateColumn(column) || looksLikeDateTimeColumn(column)) {\n if (value instanceof Date) return Math.floor(value.getTime() / 1000)\n if (typeof value === \"string\") {\n const parsed = Date.parse(value)\n if (!Number.isNaN(parsed)) return Math.floor(parsed / 1000)\n }\n if (typeof value === \"number\") return Math.floor(value)\n }\n\n if (looksLikeRefColumn(column)) {\n if (typeof value === \"number\") return value\n if (value && typeof value === \"object\" && \"rowId\" in value) {\n return (value as { rowId: number }).rowId\n }\n }\n\n if (looksLikeRefListColumn(column) || looksLikeChoiceListColumn(column) || looksLikeAttachmentColumn(column)) {\n if (Array.isArray(value)) {\n const items = value.map((v) => {\n if (v && typeof v === \"object\" && \"rowId\" in v) return (v as { rowId: number }).rowId\n return v\n })\n return [\"L\", ...items]\n }\n }\n\n return value\n}\n","import type { GristDocApi } from \"../types\"\nimport { extractGristAttachmentIdsFromCell } from \"./grist-attachment-download\"\nimport { fetchWithGristAuth } from \"./grist-fetch-with-auth\"\nimport { encodeGristValue } from \"./grist-value-codec\"\n\nconst ATTACHMENTS_COLUMN = { type: \"Attachments\" as const }\n\nexport type GristEncodedAttachmentList = [\"L\", ...(number | string)[]]\n\nexport type GristAttachmentUploadResult = {\n /** All attachment ids returned by `POST /attachments`. */\n ids: string[]\n /** First id in `ids` (convenience for single-file uploads). */\n firstId: string\n}\n\n/**\n * Parse the body of `POST /attachments` (widget or REST).\n * Grist returns a JSON array of attachment ids, e.g. `[42]` or `[101, 102]`.\n */\nexport function parseGristAttachmentUploadResponseIds(\n raw: string,\n options?: { strict?: boolean }\n): string[] {\n const trimmed = raw.trim()\n if (!trimmed) {\n throw new Error(\"Attachment upload returned an empty response.\")\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(trimmed) as unknown\n } catch {\n if (options?.strict) {\n throw new Error(\"Attachment upload returned non-JSON response.\")\n }\n parsed = trimmed\n }\n\n return extractAttachmentIdsFromUploadPayload(parsed, options)\n}\n\n/**\n * First attachment id from an upload response (see {@link parseGristAttachmentUploadResponseIds}).\n */\nexport function parseGristAttachmentUploadResponse(\n raw: string,\n options?: { strict?: boolean }\n): string {\n const ids = parseGristAttachmentUploadResponseIds(raw, options)\n return ids[0]!\n}\n\nexport function extractAttachmentIdsFromUploadPayload(\n parsed: unknown,\n options?: { strict?: boolean }\n): string[] {\n if (options?.strict) {\n return extractAttachmentIdsFromUploadPayloadStrict(parsed)\n }\n\n const first = extractFirstAttachmentIdFromUploadPayload(parsed)\n if (first !== undefined) {\n if (Array.isArray(parsed)) {\n const ids: string[] = []\n const seen = new Set<string>()\n for (const item of parsed) {\n const id = coerceAttachmentId(item)\n if (id && !seen.has(id)) {\n seen.add(id)\n ids.push(id)\n }\n }\n return ids.length > 0 ? ids : [first]\n }\n return [first]\n }\n\n throw new Error(\"Attachment upload returned an unexpected response shape.\")\n}\n\nfunction extractAttachmentIdsFromUploadPayloadStrict(parsed: unknown): string[] {\n if (typeof parsed === \"number\" && Number.isFinite(parsed)) {\n return [String(parsed)]\n }\n\n if (Array.isArray(parsed)) {\n const ids: string[] = []\n const seen = new Set<string>()\n for (const item of parsed) {\n if (typeof item !== \"number\" || !Number.isFinite(item)) {\n throw new Error(\"Attachment upload returned an unexpected response shape.\")\n }\n const id = String(item)\n if (!seen.has(id)) {\n seen.add(id)\n ids.push(id)\n }\n }\n if (ids.length === 0) {\n throw new Error(\"Attachment upload returned an empty id list.\")\n }\n return ids\n }\n\n throw new Error(\"Attachment upload returned an unexpected response shape.\")\n}\n\n/** @deprecated Prefer {@link extractAttachmentIdsFromUploadPayload}. */\nexport function extractFirstAttachmentIdFromUploadPayload(parsed: unknown): string | undefined {\n if (typeof parsed === \"number\" && Number.isFinite(parsed)) {\n return String(parsed)\n }\n\n if (typeof parsed === \"string\" && parsed.trim()) {\n return parsed.trim()\n }\n\n if (Array.isArray(parsed)) {\n for (const item of parsed) {\n const id = coerceAttachmentId(item)\n if (id) return id\n }\n return undefined\n }\n\n if (parsed && typeof parsed === \"object\") {\n const record = parsed as Record<string, unknown>\n for (const key of [\"id\", \"attachmentId\", \"fileId\"]) {\n const id = coerceAttachmentId(record[key])\n if (id) return id\n }\n }\n\n return undefined\n}\n\nfunction coerceAttachmentId(value: unknown): string | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return String(value)\n }\n if (typeof value === \"string\" && value.trim()) {\n return value.trim()\n }\n return undefined\n}\n\nfunction normalizeAttachmentIdForWire(id: string | number): number | string {\n const numeric = typeof id === \"number\" ? id : Number(id)\n if (Number.isFinite(numeric) && String(numeric) === String(id).trim()) {\n return numeric\n }\n return typeof id === \"number\" ? String(id) : id.trim()\n}\n\n/** Wire value for an Attachments cell (Grist list encoding). */\nexport function gristAttachmentCellValues(\n attachmentIds: (string | number)[]\n): GristEncodedAttachmentList {\n const items = attachmentIds.map(normalizeAttachmentIdForWire)\n const encoded = encodeGristValue(items, ATTACHMENTS_COLUMN)\n if (!Array.isArray(encoded) || encoded[0] !== \"L\") {\n return [\"L\", ...items]\n }\n return encoded as GristEncodedAttachmentList\n}\n\n/** Wire value for a single-file Attachments cell. */\nexport function gristAttachmentCellValue(attachmentId: string | number): GristEncodedAttachmentList {\n return gristAttachmentCellValues([attachmentId])\n}\n\n/**\n * Merge new attachment ids into an existing Attachments cell value (deduped, order preserved).\n */\nexport function mergeGristAttachmentCellValue(\n existingCell: unknown,\n newIds: (string | number)[]\n): GristEncodedAttachmentList {\n const existing = extractGristAttachmentIdsFromCell(existingCell)\n const merged: string[] = []\n const seen = new Set<string>()\n const push = (raw: string | number) => {\n const id = String(raw).trim()\n if (!id || seen.has(id)) return\n seen.add(id)\n merged.push(id)\n }\n for (const id of existing) push(id)\n for (const id of newIds) push(id)\n return gristAttachmentCellValues(merged)\n}\n\nconst UPLOAD_HEADERS = {\n \"X-Requested-With\": \"XMLHttpRequest\",\n Accept: \"application/json\",\n} as const\n\n/**\n * Upload a file to the current document via `POST /attachments`.\n *\n * Uses `getAccessToken({ readOnly: false })` and `?auth=` (see Grist widget docs).\n * Requires document **full** access in the widget.\n */\nexport async function uploadGristAttachment(\n docApi: GristDocApi,\n file: Blob | File,\n options?: { fileName?: string }\n): Promise<GristAttachmentUploadResult> {\n const form = new FormData()\n const fileName =\n options?.fileName ?? (file instanceof File && file.name ? file.name : \"upload\")\n form.append(\"upload\", file, fileName)\n\n let response: Response\n try {\n response = await fetchWithGristAuth(docApi, \"/attachments\", {\n method: \"POST\",\n body: form,\n readOnly: false,\n headers: UPLOAD_HEADERS,\n })\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n if (/failed to fetch/i.test(msg)) {\n const widgetOrigin =\n typeof globalThis.location !== \"undefined\"\n ? globalThis.location.origin\n : \"this widget origin\"\n throw new Error(\n `Attachment upload was blocked by the Grist host (CORS). The browser could not POST from ${widgetOrigin} to the document API. If upload worked from a dev URL (e.g. ngrok) but fails after deploy, add the new widget URL to your Grist server CORS allowlist (see grist-core#2040).`\n )\n }\n throw err\n }\n\n const raw = await response.text()\n if (!response.ok) {\n throw new Error(\n raw.trim()\n ? `Attachment upload failed (${response.status}): ${raw.slice(0, 200)}`\n : `Attachment upload failed (${response.status})`\n )\n }\n\n const ids = parseGristAttachmentUploadResponseIds(raw)\n return { ids, firstId: ids[0]! }\n}\n","import { z, type ZodType } from \"zod\"\n\nimport type { GristReplicaColumn, GristRowRecord } from \"../types\"\nimport type { GristColumnarTable } from \"./grist-table-data\"\nimport { normalizeGristChoiceListEntries, type GristChoiceListEntry } from \"./grist-widget-options\"\nimport { decodeGristValue, type GristDecodedValue } from \"./grist-value-codec\"\n\nexport type GristSafeParseIssueCode =\n | \"grist_error\"\n | \"invalid_format\"\n | \"type_mismatch\"\n | \"helper_mismatch\"\n | \"zod_error\"\n\nexport type GristSafeParseIssue = {\n code: GristSafeParseIssueCode\n message: string\n}\n\nexport type GristSafeRefValue = {\n rowId: number\n display?: string | null\n}\n\nexport type GristSafeRefListValue = {\n rowIds: number[]\n displays?: string[]\n}\n\nexport const gristSafeRefValueSchema = z.object({\n rowId: z.number(),\n display: z.string().nullable().optional(),\n})\n\nexport const gristSafeRefListValueSchema = z.object({\n rowIds: z.array(z.number()),\n displays: z.array(z.string()).optional(),\n})\n\nexport const gristCellValueSchema = z.union([\n z.null(),\n z.string(),\n z.number(),\n z.boolean(),\n z.date(),\n z.array(z.unknown()),\n gristSafeRefValueSchema,\n gristSafeRefListValueSchema,\n])\n\nexport type GristCellValue = z.infer<typeof gristCellValueSchema>\n\nexport type GristSafeParseCellResult<TValue = unknown> = {\n ok: boolean\n typedValue: TValue | null\n displayValue: unknown\n raw: unknown\n issues: GristSafeParseIssue[]\n}\n\ntype RefMode = \"id\" | \"detailed\"\n\nexport type SafeParseGristValuesOptions<TValue = unknown> = {\n values: readonly unknown[]\n column?: GristReplicaColumn\n helperValues?: readonly unknown[]\n schema?: ZodType<TValue>\n fallbackUntypedToString?: boolean\n refMode?: RefMode\n}\n\nexport type SafeParseGristTableDataOptions = {\n columns?: Record<string, GristReplicaColumn>\n displayHelpersByRef?: Record<string, string>\n order?: \"none\" | \"id\" | \"grist\"\n fallbackUntypedToString?: boolean\n refMode?: RefMode\n}\n\nexport type GristSafeTableCellIssue = GristSafeParseIssue & {\n rowIndex: number\n colId: string\n}\n\nexport type GristSafeChoiceTokenMeta = {\n value: string\n label: string\n fillColor?: string\n textColor?: string\n valid: boolean\n}\n\nexport type GristSafeTableCellMeta = {\n rowIndex: number\n colId: string\n ok: boolean\n issues: GristSafeParseIssue[]\n choiceTokens?: GristSafeChoiceTokenMeta[]\n}\n\nexport type SafeParseGristTableDataResult<TRow extends Record<string, unknown> = Record<string, unknown>> = {\n rows: GristRowRecord<TRow>[]\n cellIssues: GristSafeTableCellIssue[]\n cellMeta: GristSafeTableCellMeta[]\n cellMetaByKey: Record<string, GristSafeTableCellMeta>\n cellResultsByColumn: Record<string, GristSafeParseCellResult[]>\n}\n\n/** Maps `Ref:*` / `RefList:*` column ids to their paired `gristHelper_*` column id (same rules as safe-parse). */\nexport function inferDisplayHelpersByRef(\n columns: Record<string, GristReplicaColumn>\n): Record<string, string> {\n const out: Record<string, string> = {}\n const helperColumns = Object.entries(columns).filter(([colId]) =>\n colId.startsWith(\"gristHelper_\")\n )\n const usedHelpers = new Set<string>()\n const colRefToColId = new Map<number, string>()\n for (const [colId, col] of Object.entries(columns)) {\n if (typeof col?.colRef === \"number\" && Number.isFinite(col.colRef)) {\n colRefToColId.set(col.colRef, colId)\n }\n }\n for (const [colId, col] of Object.entries(columns)) {\n const type = col?.type\n if (typeof type !== \"string\" || (!type.startsWith(\"Ref:\") && !type.startsWith(\"RefList:\"))) {\n continue\n }\n if (typeof col.displayColRef === \"number\" && Number.isFinite(col.displayColRef)) {\n const helperColId = colRefToColId.get(col.displayColRef)\n if (helperColId) {\n out[colId] = helperColId\n usedHelpers.add(helperColId)\n continue\n }\n }\n const match = helperColumns.find(([, helper]) => {\n const formula = helper?.formula\n return typeof formula === \"string\" && (formula.includes(`$${colId}.`) || formula.includes(`$${colId}`))\n })\n if (match) {\n out[colId] = match[0]\n usedHelpers.add(match[0])\n }\n }\n\n // Secondary fallback for schemas where helper formulas are unavailable:\n // pair unresolved Ref/RefList columns with nearest following gristHelper_*.\n const unresolvedRefs = Object.entries(columns)\n .filter(([colId, col]) => {\n const type = col?.type\n return (\n !out[colId] &&\n typeof type === \"string\" &&\n (type.startsWith(\"Ref:\") || type.startsWith(\"RefList:\"))\n )\n })\n .sort((a, b) => (a[1]?.parentPos ?? Number.MAX_SAFE_INTEGER) - (b[1]?.parentPos ?? Number.MAX_SAFE_INTEGER))\n const helperByPos = helperColumns\n .filter(([helperId]) => !usedHelpers.has(helperId))\n .sort((a, b) => (a[1]?.parentPos ?? Number.MAX_SAFE_INTEGER) - (b[1]?.parentPos ?? Number.MAX_SAFE_INTEGER))\n for (const [refId, refCol] of unresolvedRefs) {\n const refPos = refCol?.parentPos ?? Number.MAX_SAFE_INTEGER\n const candidate = helperByPos.find(([, helperCol]) => {\n const helperPos = helperCol?.parentPos ?? Number.MAX_SAFE_INTEGER\n return helperPos > refPos\n })\n if (!candidate) continue\n out[refId] = candidate[0]\n usedHelpers.add(candidate[0])\n }\n // If multiple unresolved refs remain, greedily map by order.\n for (const [refId] of unresolvedRefs) {\n if (out[refId]) continue\n const candidate = helperByPos.find(([helperId]) => !usedHelpers.has(helperId))\n if (!candidate) continue\n out[refId] = candidate[0]\n usedHelpers.add(candidate[0])\n }\n return out\n}\n\nfunction computeRowCount(data: Record<string, unknown[]>): number {\n const idCol = data.id\n if (Array.isArray(idCol)) return idCol.length\n for (const key of Object.keys(data)) {\n const col = data[key]\n if (Array.isArray(col)) return col.length\n }\n return 0\n}\n\nfunction manualSortKey(row: Record<string, unknown>): number | null {\n const v = row.manualSort\n if (typeof v === \"number\" && !Number.isNaN(v)) return v\n if (typeof v === \"string\" && v.trim() !== \"\") {\n const n = Number(v)\n if (!Number.isNaN(n)) return n\n }\n return null\n}\n\nfunction sortRowsByGristOrder<T = Record<string, unknown>>(\n rows: readonly GristRowRecord<T>[]\n): GristRowRecord<T>[] {\n const hasManual = rows.some((r) => manualSortKey(r as Record<string, unknown>) !== null)\n if (!hasManual) {\n return [...rows].sort((a, b) => {\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n })\n }\n return [...rows].sort((a, b) => {\n const ma = manualSortKey(a as Record<string, unknown>)\n const mb = manualSortKey(b as Record<string, unknown>)\n if (ma !== null && mb !== null && ma !== mb) return ma - mb\n if (ma !== null && mb === null) return -1\n if (ma === null && mb !== null) return 1\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n })\n}\n\nfunction columnKind(column?: GristReplicaColumn):\n | \"text\"\n | \"numeric\"\n | \"int\"\n | \"bool\"\n | \"date\"\n | \"datetime\"\n | \"choice\"\n | \"choiceList\"\n | \"ref\"\n | \"refList\"\n | \"attachments\"\n | \"any\"\n | \"unknown\" {\n const type = column?.type\n if (!type) return \"unknown\"\n if (type === \"Text\") return \"text\"\n if (type === \"Numeric\") return \"numeric\"\n if (type === \"Int\") return \"int\"\n if (type === \"Bool\") return \"bool\"\n if (type === \"Date\") return \"date\"\n if (type === \"DateTime\" || type.startsWith(\"DateTime:\")) return \"datetime\"\n if (type === \"Choice\") return \"choice\"\n if (type === \"ChoiceList\") return \"choiceList\"\n if (type.startsWith(\"Ref:\")) return \"ref\"\n if (type.startsWith(\"RefList:\")) return \"refList\"\n if (type === \"Attachments\") return \"attachments\"\n if (type === \"Any\") return \"any\"\n return \"unknown\"\n}\n\nfunction primitiveToString(value: unknown): string | null {\n if (value === null || value === undefined) return null\n if (typeof value === \"string\") return value\n if (typeof value === \"number\" || typeof value === \"boolean\" || typeof value === \"bigint\") {\n return String(value)\n }\n return null\n}\n\nfunction normalizeRefDisplay(value: unknown): { value?: string | null; issue?: GristSafeParseIssue } {\n if (value === null || value === undefined) return { value: null }\n if (typeof value === \"string\") return { value }\n if (typeof value === \"number\" || typeof value === \"boolean\") return { value: String(value) }\n return {\n issue: {\n code: \"helper_mismatch\",\n message: \"Ref display helper value should be a scalar value.\",\n },\n }\n}\n\nfunction normalizeRefListDisplays(value: unknown): { values?: string[]; issue?: GristSafeParseIssue } {\n if (value === null || value === undefined) return { values: [] }\n if (typeof value === \"string\") {\n const s = value.trim()\n if (s === \"\") return { values: [] }\n if (s.startsWith(\"[\")) {\n try {\n const parsed = JSON.parse(s)\n if (Array.isArray(parsed)) {\n return normalizeRefListDisplays(parsed)\n }\n } catch {\n // Keep existing error below for non-array/non-JSON helper strings.\n }\n }\n }\n if (!Array.isArray(value)) {\n return {\n issue: {\n code: \"helper_mismatch\",\n message: \"RefList display helper value should be an array.\",\n },\n }\n }\n // Grist list wire format may leak through as [\"L\", ...items].\n // Treat a leading \"L\" marker as metadata, not a display label.\n const items =\n value.length > 0 && value[0] === \"L\"\n ? value.slice(1)\n : value\n const out: string[] = []\n for (const item of items) {\n const s = primitiveToString(item)\n if (s === null) {\n return {\n issue: {\n code: \"helper_mismatch\",\n message: \"RefList helper items should be scalar values.\",\n },\n }\n }\n out.push(s)\n }\n return { values: out }\n}\n\nfunction normalizeRefValue(\n decoded: GristDecodedValue,\n helperValue: unknown,\n refMode: RefMode\n): { value: number | GristSafeRefValue | null; issues: GristSafeParseIssue[] } {\n const issues: GristSafeParseIssue[] = []\n if (decoded === null) return { value: null, issues }\n\n const rowId =\n typeof decoded === \"number\" && Number.isFinite(decoded)\n ? decoded\n : decoded && typeof decoded === \"object\" && \"__ref\" in decoded\n ? (decoded as { rowId: number }).rowId\n : null\n\n // Grist empty refs can surface as 0; treat as empty cell.\n if (rowId === 0) return { value: null, issues }\n if (rowId === null || !Number.isFinite(rowId)) {\n issues.push({\n code: \"type_mismatch\",\n message: \"Expected a Ref row id.\",\n })\n return { value: null, issues }\n }\n\n if (refMode === \"id\") return { value: rowId, issues }\n\n const helper = normalizeRefDisplay(helperValue)\n if (helper.issue) issues.push(helper.issue)\n return {\n value: { rowId, display: helper.value },\n issues,\n }\n}\n\nfunction normalizeRefListValue(\n decoded: GristDecodedValue,\n helperValue: unknown,\n refMode: RefMode\n): { value: number[] | GristSafeRefListValue | null; issues: GristSafeParseIssue[] } {\n const issues: GristSafeParseIssue[] = []\n if (decoded === null) return { value: null, issues }\n if (!Array.isArray(decoded)) {\n issues.push({\n code: \"type_mismatch\",\n message: \"Expected an array for RefList.\",\n })\n return { value: null, issues }\n }\n\n const rowIds: number[] = []\n for (const item of decoded) {\n if (typeof item === \"number\" && Number.isFinite(item) && item !== 0) {\n rowIds.push(item)\n continue\n }\n if (item && typeof item === \"object\" && \"__ref\" in item) {\n const rowId = (item as { rowId: number }).rowId\n if (typeof rowId === \"number\" && Number.isFinite(rowId) && rowId !== 0) {\n rowIds.push(rowId)\n continue\n }\n }\n issues.push({\n code: \"type_mismatch\",\n message: \"RefList items should be row ids.\",\n })\n return { value: null, issues }\n }\n\n if (refMode === \"id\") return { value: rowIds, issues }\n\n const helper = normalizeRefListDisplays(helperValue)\n if (helper.issue) {\n issues.push(helper.issue)\n } else if (helper.values && helper.values.length > 0 && helper.values.length !== rowIds.length) {\n issues.push({\n code: \"helper_mismatch\",\n message: \"RefList helper labels count does not match row ids count.\",\n })\n }\n return {\n value: { rowIds, displays: helper.values },\n issues,\n }\n}\n\nfunction normalizeByColumnKind(\n decoded: GristDecodedValue,\n kind: ReturnType<typeof columnKind>,\n helperValue: unknown,\n fallbackUntypedToString: boolean,\n refMode: RefMode\n): { value: unknown; issues: GristSafeParseIssue[] } {\n const issues: GristSafeParseIssue[] = []\n if (decoded && typeof decoded === \"object\" && \"__error\" in decoded) {\n issues.push({\n code: \"grist_error\",\n message: (decoded as { message?: string }).message ?? \"Grist returned a cell error.\",\n })\n return { value: null, issues }\n }\n\n switch (kind) {\n case \"ref\":\n return normalizeRefValue(decoded, helperValue, refMode)\n case \"refList\":\n return normalizeRefListValue(decoded, helperValue, refMode)\n case \"date\":\n case \"datetime\":\n if (decoded === null || decoded instanceof Date) return { value: decoded, issues }\n issues.push({ code: \"type_mismatch\", message: \"Expected a Date value.\" })\n return { value: null, issues }\n case \"bool\":\n if (decoded === null || typeof decoded === \"boolean\") return { value: decoded, issues }\n issues.push({ code: \"type_mismatch\", message: \"Expected a boolean value.\" })\n return { value: null, issues }\n case \"numeric\":\n if (decoded === null || (typeof decoded === \"number\" && Number.isFinite(decoded))) {\n return { value: decoded, issues }\n }\n issues.push({ code: \"type_mismatch\", message: \"Expected a numeric value.\" })\n return {\n value:\n typeof decoded === \"string\" ||\n typeof decoded === \"number\" ||\n typeof decoded === \"boolean\"\n ? decoded\n : null,\n issues,\n }\n case \"int\":\n if (decoded === null || (typeof decoded === \"number\" && Number.isInteger(decoded))) {\n return { value: decoded, issues }\n }\n issues.push({ code: \"type_mismatch\", message: \"Expected an integer value.\" })\n return {\n value:\n typeof decoded === \"string\" ||\n typeof decoded === \"number\" ||\n typeof decoded === \"boolean\"\n ? decoded\n : null,\n issues,\n }\n case \"choice\":\n case \"text\":\n if (decoded === null || typeof decoded === \"string\") return { value: decoded, issues }\n issues.push({ code: \"type_mismatch\", message: \"Expected a string value.\" })\n return { value: null, issues }\n case \"choiceList\":\n case \"attachments\":\n if (decoded === null || Array.isArray(decoded)) return { value: decoded, issues }\n issues.push({ code: \"type_mismatch\", message: \"Expected a list value.\" })\n return { value: null, issues }\n case \"any\":\n case \"unknown\":\n // Heuristic fallback: when schema typing is missing but a helper column is\n // attached, infer Ref/RefList from the decoded shape.\n if (helperValue !== undefined) {\n if (typeof decoded === \"number\" || (decoded && typeof decoded === \"object\" && \"__ref\" in decoded)) {\n return normalizeRefValue(decoded, helperValue, refMode)\n }\n if (Array.isArray(decoded)) {\n return normalizeRefListValue(decoded, helperValue, refMode)\n }\n }\n if (!fallbackUntypedToString) return { value: decoded, issues }\n if (decoded === null) return { value: null, issues }\n if (typeof decoded === \"string\") return { value: decoded, issues }\n if (\n typeof decoded === \"number\" ||\n typeof decoded === \"boolean\" ||\n decoded instanceof Date\n ) {\n return {\n value: decoded instanceof Date ? decoded.toISOString() : String(decoded),\n issues,\n }\n }\n if (Array.isArray(decoded)) {\n try {\n return { value: JSON.stringify(decoded), issues }\n } catch {\n issues.push({\n code: \"invalid_format\",\n message: \"Unable to stringify list value.\",\n })\n return { value: null, issues }\n }\n }\n issues.push({\n code: \"type_mismatch\",\n message: \"Untyped value could not be represented as a string.\",\n })\n return { value: null, issues }\n }\n}\n\nfunction buildChoiceTokens(\n col: GristReplicaColumn | undefined,\n value: unknown\n): GristSafeChoiceTokenMeta[] | undefined {\n const type = col?.type\n if (type !== \"Choice\" && type !== \"ChoiceList\") return undefined\n const entries = normalizeGristChoiceListEntries(col?.widgetOptions)\n const byValue = new Map<string, GristChoiceListEntry>(entries.map((entry) => [entry.value, entry]))\n\n if (type === \"Choice\") {\n if (value == null || typeof value !== \"string\" || value.trim() === \"\") return []\n const meta = byValue.get(value)\n if (!meta) return [{ value, label: value, valid: false }]\n return [\n {\n value,\n label: meta.label,\n fillColor: meta.fillColor,\n textColor: meta.textColor,\n valid: true,\n },\n ]\n }\n\n if (!Array.isArray(value)) return []\n const out: GristSafeChoiceTokenMeta[] = []\n for (const item of value) {\n const v = typeof item === \"string\" ? item : String(item)\n const meta = byValue.get(v)\n if (!meta) {\n out.push({ value: v, label: v, valid: false })\n continue\n }\n out.push({\n value: v,\n label: meta.label,\n fillColor: meta.fillColor,\n textColor: meta.textColor,\n valid: true,\n })\n }\n return out\n}\n\nexport function safeParseGristValues<TValue = unknown>(\n options: SafeParseGristValuesOptions<TValue>\n): GristSafeParseCellResult<TValue>[] {\n const fallbackUntypedToString = options.fallbackUntypedToString ?? true\n const refMode = options.refMode ?? \"id\"\n const kind = columnKind(options.column)\n return options.values.map((raw, index) => {\n const decoded = decodeGristValue(raw, options.column)\n const helperValue = options.helperValues?.[index]\n const normalized = normalizeByColumnKind(\n decoded,\n kind,\n helperValue,\n fallbackUntypedToString,\n refMode\n )\n const issues = [...normalized.issues]\n\n if (options.schema) {\n const result = options.schema.safeParse(normalized.value)\n if (!result.success) {\n issues.push({\n code: \"zod_error\",\n message: result.error.issues.map((issue) => issue.message).join(\"; \"),\n })\n }\n }\n\n return {\n ok: issues.length === 0,\n typedValue: normalized.value as TValue | null,\n displayValue: normalized.value,\n raw,\n issues,\n }\n })\n}\n\nexport function safeParseGristTableData<TRow extends Record<string, unknown> = Record<string, unknown>>(\n data: GristColumnarTable,\n options?: SafeParseGristTableDataOptions\n): SafeParseGristTableDataResult<TRow> {\n const columns = options?.columns ?? {}\n const inferredDisplayHelpersByRef = inferDisplayHelpersByRef(columns)\n const displayHelpersByRef: Record<string, string> = {\n ...inferredDisplayHelpersByRef,\n ...(options?.displayHelpersByRef ?? {}),\n }\n // Fallback convention: if `owner` exists and `gristHelper_owner` is fetched,\n // use it as display helper even when formula metadata is unavailable.\n for (const [colId, col] of Object.entries(columns)) {\n const type = col?.type\n if (typeof type !== \"string\" || (!type.startsWith(\"Ref:\") && !type.startsWith(\"RefList:\"))) {\n continue\n }\n if (displayHelpersByRef[colId]) continue\n const byName = `gristHelper_${colId}`\n if (Array.isArray(data[byName])) {\n displayHelpersByRef[colId] = byName\n }\n }\n const fallbackUntypedToString = options?.fallbackUntypedToString ?? true\n const refMode = options?.refMode ?? \"id\"\n const colIds = Object.keys(data)\n const parsedByColumn: Record<string, GristSafeParseCellResult[]> = {}\n\n for (const colId of colIds) {\n const rawValues = Array.isArray(data[colId]) ? data[colId] : []\n const helperColId = displayHelpersByRef[colId]\n const helperValues = helperColId && Array.isArray(data[helperColId]) ? data[helperColId] : undefined\n parsedByColumn[colId] =\n colId === \"id\"\n ? rawValues.map((raw) => ({\n ok: typeof raw === \"number\" && Number.isFinite(raw),\n typedValue: typeof raw === \"number\" && Number.isFinite(raw) ? raw : null,\n displayValue: raw,\n raw,\n issues:\n typeof raw === \"number\" && Number.isFinite(raw)\n ? []\n : [{ code: \"type_mismatch\", message: \"Row id should be numeric.\" }],\n }))\n : safeParseGristValues({\n values: rawValues,\n column: columns[colId],\n helperValues,\n fallbackUntypedToString,\n refMode,\n })\n }\n\n const rowCount = computeRowCount(data)\n const rows: GristRowRecord<TRow>[] = []\n const cellIssues: GristSafeTableCellIssue[] = []\n const cellMeta: GristSafeTableCellMeta[] = []\n for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {\n const row: Record<string, unknown> = {}\n for (const colId of colIds) {\n const parsed = parsedByColumn[colId]?.[rowIndex]\n row[colId] = parsed?.typedValue ?? null\n const choiceTokens = buildChoiceTokens(columns[colId], parsed?.displayValue)\n if (parsed) {\n if (parsed.issues.length > 0 || (choiceTokens && choiceTokens.length > 0)) {\n cellMeta.push({\n rowIndex,\n colId,\n ok: parsed.ok,\n issues: parsed.issues,\n choiceTokens,\n })\n }\n }\n if (!parsed || parsed.issues.length === 0) continue\n for (const issue of parsed.issues) {\n cellIssues.push({ ...issue, rowIndex, colId })\n }\n }\n rows.push(row as GristRowRecord<TRow>)\n }\n\n const cellMetaByKey: Record<string, GristSafeTableCellMeta> = {}\n for (const meta of cellMeta) {\n const rowId = rows[meta.rowIndex]?.id\n if (typeof rowId !== \"number\") continue\n cellMetaByKey[`${rowId}:${meta.colId}`] = meta\n }\n\n const order = options?.order ?? \"grist\"\n if (order === \"none\") {\n return { rows, cellIssues, cellMeta, cellMetaByKey, cellResultsByColumn: parsedByColumn }\n }\n if (order === \"id\") {\n return {\n rows: [...rows].sort((a, b) => {\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n }),\n cellIssues,\n cellMeta,\n cellMetaByKey,\n cellResultsByColumn: parsedByColumn,\n }\n }\n return {\n rows: sortRowsByGristOrder(rows),\n cellIssues,\n cellMeta,\n cellMetaByKey,\n cellResultsByColumn: parsedByColumn,\n }\n}\n","/**\n * Grist stores column widget configuration in `_grist_Tables_column.widgetOptions`\n * as a JSON string. Choice fields use `choices: string[]` plus optional\n * `choiceOptions: Record<string, Style>` (e.g. `fillColor`, `textColor`).\n *\n * @see https://github.com/gristlabs/grist-core/blob/main/app/client/widgets/ChoiceEditor.js\n */\n\n/** One selectable choice for UI (value stored in the cell is `value`). */\nexport type GristChoiceListEntry = {\n value: string\n label: string\n fillColor?: string\n textColor?: string\n}\n\n/**\n * Parse a cell value from `_grist_Tables_column.widgetOptions` into a plain object.\n */\nexport function parseGristWidgetOptionsCell(raw: unknown): Record<string, unknown> | undefined {\n if (raw == null || raw === \"\") return undefined\n if (typeof raw === \"string\") {\n try {\n const parsed: unknown = JSON.parse(raw)\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>\n }\n } catch {\n return undefined\n }\n return undefined\n }\n if (typeof raw === \"object\" && !Array.isArray(raw)) {\n return raw as Record<string, unknown>\n }\n return undefined\n}\n\nfunction readStyleColor(style: Record<string, unknown>, key: string): string | undefined {\n const v = style[key]\n return typeof v === \"string\" ? v : undefined\n}\n\n/**\n * Normalizes Grist Choice / ChoiceList widgetOptions into a flat list for dropdowns.\n * `choices` entries are string labels (the stored cell value). Per-choice styling\n * lives in `choiceOptions[label]`.\n */\nexport function normalizeGristChoiceListEntries(\n widgetOptions: Record<string, unknown> | undefined\n): GristChoiceListEntry[] {\n if (!widgetOptions) return []\n const rawChoices = widgetOptions.choices\n if (!Array.isArray(rawChoices)) return []\n\n const choiceOptionsRaw = widgetOptions.choiceOptions\n const choiceOptions: Record<string, Record<string, unknown>> =\n choiceOptionsRaw &&\n typeof choiceOptionsRaw === \"object\" &&\n !Array.isArray(choiceOptionsRaw)\n ? (choiceOptionsRaw as Record<string, Record<string, unknown>>)\n : {}\n\n const out: GristChoiceListEntry[] = []\n for (const c of rawChoices) {\n const value = typeof c === \"string\" ? c : c != null ? String(c) : \"\"\n if (!value) continue\n const style = choiceOptions[value] ?? {}\n out.push({\n value,\n label: value,\n fillColor: readStyleColor(style, \"fillColor\"),\n textColor: readStyleColor(style, \"textColor\"),\n })\n }\n return out\n}\n","import type { GristDocApi, GristReplicaColumn, GristRowRecord } from \"../types\"\nimport { decodeGristValue } from \"./grist-value-codec\"\nimport {\n type GristSafeParseCellResult,\n type GristSafeTableCellMeta,\n safeParseGristTableData,\n type GristSafeTableCellIssue,\n type SafeParseGristTableDataOptions,\n} from \"./grist-safe-parse\"\n\n/**\n * Column-oriented table payload from `grist.docApi.fetchTable`.\n */\nexport type GristColumnarTable = Record<string, unknown[]>\nexport type GristTableRowsOrder = \"none\" | \"id\" | \"grist\"\nexport type FetchGristTableRowsOptions = {\n /** Optional schema metadata map to decode cells (except `id`) with `decodeGristValue`. */\n columns?: Record<string, GristReplicaColumn>\n /**\n * Row ordering strategy.\n * - `grist` (default): `manualSort` ascending when present, fallback `id`.\n * - `id`: numeric `id` ascending.\n * - `none`: preserve raw `fetchTable` row order.\n */\n order?: GristTableRowsOrder\n /**\n * Enable safe parsing with issue reporting.\n * - `true`: use safe parsing with defaults.\n * - object: pass safe-parse options (`displayHelpersByRef`, `refMode`, ...).\n */\n safeParse?: boolean | Omit<SafeParseGristTableDataOptions, \"columns\" | \"order\">\n /** Optional callback fired with per-cell parse issues when `safeParse` is enabled. */\n onSafeParseIssues?: (issues: GristSafeTableCellIssue[]) => void\n /** Optional callback fired with enriched per-cell safe-parse metadata. */\n onSafeParseCellMeta?: (meta: GristSafeTableCellMeta[]) => void\n /** Optional callback fired with keyed per-cell metadata (`${rowId}:${colId}`). */\n onSafeParseCellMetaByKey?: (metaByKey: Record<string, GristSafeTableCellMeta>) => void\n}\n\nfunction inferDisplayHelpersByNameFromData(data: GristColumnarTable): Record<string, string> {\n const out: Record<string, string> = {}\n for (const colId of Object.keys(data)) {\n if (!colId.startsWith(\"gristHelper_\")) continue\n const baseColId = colId.slice(\"gristHelper_\".length)\n if (!baseColId) continue\n if (!Array.isArray(data[baseColId])) continue\n out[baseColId] = colId\n }\n return out\n}\n\nfunction enrichSafeParseColumnsFromData(\n data: GristColumnarTable,\n columns?: Record<string, GristReplicaColumn>\n): Record<string, GristReplicaColumn> {\n const out: Record<string, GristReplicaColumn> = { ...(columns ?? {}) }\n const keys = Object.keys(data)\n const positionByColId = new Map<string, number>(keys.map((colId, index) => [colId, index + 1]))\n\n // Ensure helper columns exist in safe-parse metadata even when caller schema\n // excluded them (common for UI schemas). Parent positions are synthesized from\n // fetchTable key order so helper/ref fallback matching still works.\n for (const colId of keys) {\n if (!colId.startsWith(\"gristHelper_\")) continue\n if (out[colId]) continue\n out[colId] = {\n type: \"Any\",\n label: colId,\n parentPos: positionByColId.get(colId),\n }\n }\n return out\n}\n\nfunction rowsFromSafeCellResults(\n parsedByColumn: Record<string, GristSafeParseCellResult[]>\n): GristRowRecord<Record<string, unknown>>[] {\n const colIds = Object.keys(parsedByColumn)\n const rowCount = colIds.reduce((max, colId) => {\n const len = parsedByColumn[colId]?.length ?? 0\n return Math.max(max, len)\n }, 0)\n const rows: GristRowRecord<Record<string, unknown>>[] = []\n for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {\n const row: Record<string, unknown> = {}\n for (const colId of colIds) {\n row[colId] = parsedByColumn[colId]?.[rowIndex] ?? null\n }\n rows.push(row as GristRowRecord<Record<string, unknown>>)\n }\n return rows\n}\n\nfunction safeCellRowId(row: Record<string, unknown>): number | null {\n const idCell = row.id\n if (!idCell || typeof idCell !== \"object\" || !(\"typedValue\" in idCell)) return null\n const typed = (idCell as { typedValue?: unknown }).typedValue\n return typeof typed === \"number\" && Number.isFinite(typed) ? typed : null\n}\n\nfunction orderSafeCellRowsByParsedRows(\n rows: GristRowRecord<Record<string, unknown>>[],\n orderedParsedRows: ReadonlyArray<Record<string, unknown>>\n): GristRowRecord<Record<string, unknown>>[] {\n const byId = new Map<number, GristRowRecord<Record<string, unknown>>[]>()\n for (const row of rows) {\n const id = safeCellRowId(row)\n if (id === null) continue\n const bucket = byId.get(id)\n if (bucket) bucket.push(row)\n else byId.set(id, [row])\n }\n const out: GristRowRecord<Record<string, unknown>>[] = []\n for (const parsedRow of orderedParsedRows) {\n const id = typeof parsedRow.id === \"number\" ? parsedRow.id : null\n if (id === null) continue\n const bucket = byId.get(id)\n if (!bucket || bucket.length === 0) continue\n const next = bucket.shift()\n if (next) out.push(next)\n }\n // Preserve any unexpected leftovers (defensive).\n for (const bucket of byId.values()) {\n out.push(...bucket)\n }\n return out\n}\n\n/**\n * Project safe-parse rows to UI display rows by taking each cell's `displayValue`.\n * Useful for grids that render human-friendly values while keeping safe-cell\n * objects available for logic and metadata.\n */\nexport function safeParseRowsToDisplayRows(\n rows: ReadonlyArray<Record<string, unknown>>\n): GristRowRecord<Record<string, unknown>>[] {\n return rows.map((row) => {\n const out: Record<string, unknown> = {}\n for (const [colId, cell] of Object.entries(row)) {\n if (cell && typeof cell === \"object\" && \"displayValue\" in cell) {\n out[colId] = (cell as { displayValue: unknown }).displayValue\n } else {\n out[colId] = cell\n }\n }\n return out as GristRowRecord<Record<string, unknown>>\n })\n}\n\n/** Row count from columnar `fetchTable` data (prefers `id` column length). */\nexport function computeRowCount(data: Record<string, unknown[]>): number {\n const idCol = data.id\n if (Array.isArray(idCol)) return idCol.length\n for (const key of Object.keys(data)) {\n const col = data[key]\n if (Array.isArray(col)) return col.length\n }\n return 0\n}\n\n/**\n * Decode columnar `fetchTable` into replica row objects (same convention as the playground grid).\n */\nexport function decodeColumnarToReplicaRows(\n data: GristColumnarTable,\n columnIds: string[],\n columns: Record<string, GristReplicaColumn>,\n maxRows?: number\n): GristRowRecord[] {\n const nFull = computeRowCount(data)\n const n = maxRows !== undefined ? Math.min(nFull, maxRows) : nFull\n const out: GristRowRecord[] = []\n for (let i = 0; i < n; i++) {\n const row: Record<string, unknown> = {}\n for (const k of columnIds) {\n const arr = data[k]\n const raw = Array.isArray(arr) ? arr[i] : undefined\n if (k === \"id\") {\n row[k] = raw\n } else {\n row[k] = decodeGristValue(raw, columns[k]) as unknown\n }\n }\n out.push(row as GristRowRecord)\n }\n return out\n}\n\n/** Turn `fetchTable` output into row objects (order follows the `id` column). */\nexport function tableDataToRows<T = Record<string, unknown>>(\n data: GristColumnarTable\n): GristRowRecord<T>[] {\n const idCol = data.id\n if (!Array.isArray(idCol) || idCol.length === 0) return []\n const keys = Object.keys(data)\n const n = idCol.length\n const rows: GristRowRecord<T>[] = []\n for (let i = 0; i < n; i++) {\n const row: Record<string, unknown> = {}\n for (const k of keys) {\n const col = data[k]\n row[k] = Array.isArray(col) ? col[i] : undefined\n }\n rows.push(row as GristRowRecord<T>)\n }\n return rows\n}\n\nfunction manualSortKey(row: Record<string, unknown>): number | null {\n const v = row.manualSort\n if (typeof v === \"number\" && !Number.isNaN(v)) return v\n if (typeof v === \"string\" && v.trim() !== \"\") {\n const n = Number(v)\n if (!Number.isNaN(n)) return n\n }\n return null\n}\n\n/**\n * Sort rows by Grist's display order: `manualSort` ascending when present on\n * any row, otherwise numeric `id` ascending.\n */\nexport function sortRowsByGristOrder<T = Record<string, unknown>>(\n rows: readonly GristRowRecord<T>[]\n): GristRowRecord<T>[] {\n const hasManual = rows.some((r) => manualSortKey(r as Record<string, unknown>) !== null)\n if (!hasManual) {\n return [...rows].sort((a, b) => {\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n })\n }\n return [...rows].sort((a, b) => {\n const ma = manualSortKey(a as Record<string, unknown>)\n const mb = manualSortKey(b as Record<string, unknown>)\n if (ma !== null && mb !== null && ma !== mb) return ma - mb\n if (ma !== null && mb === null) return -1\n if (ma === null && mb !== null) return 1\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n })\n}\n\n/** Row index where `id` matches `rowId`, or `null`. */\nexport function findRowIndexById(data: GristColumnarTable, rowId: number | string): number | null {\n const idCol = data.id\n if (!Array.isArray(idCol)) return null\n const idx = idCol.findIndex((v) => v === rowId || (typeof v === \"number\" && v === Number(rowId)))\n return idx === -1 ? null : idx\n}\n\n/** Single row at `index`, or `null` if out of range. */\nexport function rowAtIndex<T = Record<string, unknown>>(\n data: GristColumnarTable,\n index: number\n): GristRowRecord<T> | null {\n const idCol = data.id\n if (!Array.isArray(idCol) || index < 0 || index >= idCol.length) return null\n const keys = Object.keys(data)\n const row: Record<string, unknown> = {}\n for (const k of keys) {\n const col = data[k]\n row[k] = Array.isArray(col) ? col[index] : undefined\n }\n return row as GristRowRecord<T>\n}\n\n/**\n * Fetch a single row from any table by id. Convenience around\n * `docApi.fetchTable` + {@link findRowIndexById} + {@link rowAtIndex}.\n */\nexport async function fetchGristRow<T = Record<string, unknown>>(\n docApi: GristDocApi,\n tableId: string,\n rowId: number\n): Promise<GristRowRecord<T> | null> {\n const data = (await docApi.fetchTable(tableId)) as GristColumnarTable\n const index = findRowIndexById(data, rowId)\n if (index === null) return null\n return rowAtIndex<T>(data, index)\n}\n\n/**\n * Same row materialization as {@link fetchGristTableRows} after `fetchTable`\n * returns columnar data. Hosts that already have columnar data (e.g. the\n * emulator building from in-memory rows) can use this and skip `docApi.fetchTable`.\n */\nexport function materializeGristRowsFromColumnar<T extends Record<string, unknown> = Record<string, unknown>>(\n data: GristColumnarTable,\n options?: FetchGristTableRowsOptions\n): GristRowRecord<T>[] {\n const order = options?.order ?? \"grist\"\n if (options?.safeParse) {\n const safeOptions = options.safeParse === true ? {} : options.safeParse\n const columnsForSafeParse = enrichSafeParseColumnsFromData(data, options?.columns)\n const displayHelpersByRef = {\n ...inferDisplayHelpersByNameFromData(data),\n ...(safeOptions.displayHelpersByRef ?? {}),\n }\n const parsed = safeParseGristTableData<T>(data, {\n ...safeOptions,\n columns: columnsForSafeParse,\n displayHelpersByRef,\n order,\n })\n options.onSafeParseIssues?.(parsed.cellIssues)\n options.onSafeParseCellMeta?.(parsed.cellMeta)\n options.onSafeParseCellMetaByKey?.(parsed.cellMetaByKey)\n const rawSafeRows = rowsFromSafeCellResults(parsed.cellResultsByColumn)\n const orderedSafeRows =\n order === \"none\"\n ? rawSafeRows\n : orderSafeCellRowsByParsedRows(rawSafeRows, parsed.rows as ReadonlyArray<Record<string, unknown>>)\n return orderedSafeRows as GristRowRecord<T>[]\n }\n\n let rows: GristRowRecord<T>[]\n if (options?.columns) {\n const columnIds = Object.keys(data)\n rows = decodeColumnarToReplicaRows(data, columnIds, options.columns) as GristRowRecord<T>[]\n } else {\n rows = tableDataToRows<T>(data)\n }\n\n if (order === \"none\") return rows\n if (order === \"id\") {\n return [...rows].sort((a, b) => {\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n })\n }\n return sortRowsByGristOrder(rows)\n}\n\n/**\n * Fetch a table and return rows as objects, optionally decoded from schema and sorted.\n */\nexport async function fetchGristTableRows<T extends Record<string, unknown> = Record<string, unknown>>(\n docApi: GristDocApi,\n tableId: string,\n options: FetchGristTableRowsOptions & { safeParse: true | Omit<SafeParseGristTableDataOptions, \"columns\" | \"order\"> }\n): Promise<GristRowRecord<{ [K in keyof T]: GristSafeParseCellResult<T[K]> | null }>[]>\nexport async function fetchGristTableRows<T extends Record<string, unknown> = Record<string, unknown>>(\n docApi: GristDocApi,\n tableId: string,\n options?: FetchGristTableRowsOptions\n): Promise<GristRowRecord<T>[]>\nexport async function fetchGristTableRows<T extends Record<string, unknown> = Record<string, unknown>>(\n docApi: GristDocApi,\n tableId: string,\n options?: FetchGristTableRowsOptions\n): Promise<GristRowRecord<T>[]> {\n const data = (await docApi.fetchTable(tableId)) as GristColumnarTable\n return materializeGristRowsFromColumnar<T>(data, options)\n}\n","/**\n * Grist `docApi.applyUserActions` payloads are arrays of user-action tuples.\n * @see https://support.getgrist.com/code/interfaces/grist_plugin_api.GristDocAPI/#applyuseractions\n */\n\nexport type GristUserActionTuple = unknown[]\n\n/** `[\"UpdateRecord\", tableId, rowId, { col: value, ... }]` */\nexport function gristUpdateRecordAction(\n tableId: string,\n rowId: number,\n patch: Record<string, unknown>\n): GristUserActionTuple {\n return [\"UpdateRecord\", tableId, rowId, patch]\n}\n\n/** `[\"AddRecord\", tableId, null, { col: value, ... }]` */\nexport function gristAddRecordAction(tableId: string, values: Record<string, unknown>): GristUserActionTuple {\n return [\"AddRecord\", tableId, null, values]\n}\n\n/** `[\"RemoveRecord\", tableId, rowId]` */\nexport function gristRemoveRecordAction(tableId: string, rowId: number): GristUserActionTuple {\n return [\"RemoveRecord\", tableId, rowId]\n}\n\n/** `[\"BulkUpdateRecord\", tableId, rowIds, { col: value[], ... }]` — column arrays must align with `rowIds`. */\nexport function gristBulkUpdateRecordAction(\n tableId: string,\n rowIds: number[],\n columnarPatch: Record<string, unknown[]>\n): GristUserActionTuple {\n return [\"BulkUpdateRecord\", tableId, rowIds, columnarPatch]\n}\n\n/**\n * `[\"BulkAddRecord\", tableId, rowIds | nullArray, { col: value[], ... }]`.\n * Pass `null` (or omit) for `rowIds` to let Grist allocate ids; in user-action\n * format Grist expects an array of nulls of the same length as the value arrays.\n */\nexport function gristBulkAddRecordAction(\n tableId: string,\n values: Record<string, unknown[]>,\n rowIds?: Array<number | null>\n): GristUserActionTuple {\n const length = inferBulkLength(values)\n const ids = rowIds ?? new Array<number | null>(length).fill(null)\n return [\"BulkAddRecord\", tableId, ids, values]\n}\n\n/** `[\"BulkRemoveRecord\", tableId, rowIds]` */\nexport function gristBulkRemoveRecordAction(tableId: string, rowIds: number[]): GristUserActionTuple {\n return [\"BulkRemoveRecord\", tableId, rowIds]\n}\n\n/** `[\"AddColumn\", tableId, colId, colInfo]` — `colInfo` shape depends on Grist version / column type. */\nexport function gristAddColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"AddVisibleColumn\", tableId, colId, colInfo]` — like `AddColumn` but also adds the column to the current view section. */\nexport function gristAddVisibleColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddVisibleColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"RenameColumn\", tableId, colId, newColId]` */\nexport function gristRenameColumnAction(tableId: string, colId: string, newColId: string): GristUserActionTuple {\n return [\"RenameColumn\", tableId, colId, newColId]\n}\n\n/** `[\"ModifyColumn\", tableId, colId, colInfo]` */\nexport function gristModifyColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"ModifyColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"RemoveColumn\", tableId, colId]` */\nexport function gristRemoveColumnAction(tableId: string, colId: string): GristUserActionTuple {\n return [\"RemoveColumn\", tableId, colId]\n}\n\n/** `[\"AddTable\", tableId, tableInfo]` */\nexport function gristAddTableAction(tableId: string, tableInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddTable\", tableId, tableInfo]\n}\n\n/** `[\"RenameTable\", tableId, newTableId]` */\nexport function gristRenameTableAction(tableId: string, newTableId: string): GristUserActionTuple {\n return [\"RenameTable\", tableId, newTableId]\n}\n\n/** `[\"RemoveTable\", tableId]` */\nexport function gristRemoveTableAction(tableId: string): GristUserActionTuple {\n return [\"RemoveTable\", tableId]\n}\n\n/** `[\"DuplicateTable\", tableId, newTableId, options?]` */\nexport function gristDuplicateTableAction(\n tableId: string,\n newTableId: string,\n options?: Record<string, unknown>\n): GristUserActionTuple {\n return options ? [\"DuplicateTable\", tableId, newTableId, options] : [\"DuplicateTable\", tableId, newTableId]\n}\n\n/** `[\"ReplaceTableData\", tableId, rowIds, columnarData]` */\nexport function gristReplaceTableDataAction(\n tableId: string,\n rowIds: Array<number | null>,\n columnarData: Record<string, unknown[]>\n): GristUserActionTuple {\n return [\"ReplaceTableData\", tableId, rowIds, columnarData]\n}\n\n/** `[\"SetDocumentInfo\", info]` */\nexport function gristSetDocumentInfoAction(info: Record<string, unknown>): GristUserActionTuple {\n return [\"SetDocumentInfo\", info]\n}\n\nfunction inferBulkLength(values: Record<string, unknown[]>): number {\n for (const arr of Object.values(values)) if (Array.isArray(arr)) return arr.length\n return 0\n}\n","export type GristColumnLike = {\n formula?: string\n}\n\nexport type GristNoiseColumnsOptions = {\n excludeId?: boolean\n excludeGristHelpers?: boolean\n excludeLoggingColumns?: boolean\n /**\n * When `true`, treat Grist's `manualSort` column as noise (omit from filtered replicas).\n * Default `false` — `manualSort` is kept unless you opt in.\n */\n excludeManualSort?: boolean\n}\n\nconst NOISE_COLUMN_FORMULAS = new Set([\"now()\"])\n\nfunction normalizeFormulaForComparison(formula: string): string {\n return formula.trim().toLowerCase().replace(/\\s+/g, \"\")\n}\n\n/**\n * Grist-centric \"technical column\" detection used by document hooks and widgets.\n *\n * - `id` (when {@link GristNoiseColumnsOptions.excludeId} is true — default)\n * - `manualSort` (only when {@link GristNoiseColumnsOptions.excludeManualSort} is true)\n * - `gristHelper_*` (when `excludeGristHelpers` is true — default)\n * - trigger/logging formulas (`NOW()`, `user.*`) (when `excludeLoggingColumns` is true — default)\n */\nexport function isGristNoiseColumn(\n colId: string,\n col?: GristColumnLike,\n options?: GristNoiseColumnsOptions\n): boolean {\n const excludeId = options?.excludeId ?? true\n const excludeGristHelpers = options?.excludeGristHelpers ?? true\n const excludeLoggingColumns = options?.excludeLoggingColumns ?? true\n const excludeManualSort = options?.excludeManualSort ?? false\n\n if (excludeId && colId === \"id\") return true\n if (excludeManualSort && colId === \"manualSort\") return true\n if (excludeGristHelpers && colId.startsWith(\"gristHelper_\")) return true\n\n if (excludeLoggingColumns) {\n const formula = typeof col?.formula === \"string\" ? normalizeFormulaForComparison(col.formula) : \"\"\n if (formula && NOISE_COLUMN_FORMULAS.has(formula)) return true\n if (formula.startsWith(\"user.\")) return true\n }\n\n return false\n}\n","import type { GristFormulaKind, GristReplicaColumn } from \"../types\"\n\nexport function inferGristFormulaKind(isFormula: boolean, formulaTrimmed: string): GristFormulaKind {\n if (formulaTrimmed.length > 0) return isFormula ? \"computed\" : \"trigger\"\n return isFormula ? \"empty_slot\" : \"none\"\n}\n\n/** Use when `formulaKind` may be missing (e.g. older document builds). */\nexport function resolveGristFormulaKind(col: GristReplicaColumn): GristFormulaKind {\n if (col.formulaKind) return col.formulaKind\n const f = col.formula?.trim() ?? \"\"\n if (f.length > 0) return col.isFormula === true ? \"computed\" : \"trigger\"\n return col.isFormula === true ? \"empty_slot\" : \"none\"\n}\n\n/** Serialize cell values for JSON output. */\nexport function serializeJsonFriendly(value: unknown): unknown {\n if (value === null || value === undefined) return null\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") return value\n try {\n return JSON.parse(JSON.stringify(value)) as unknown\n } catch {\n return String(value)\n }\n}\n","import type {\n GristDocApi,\n GristDocumentMode,\n GristReplicaColumn,\n GristReplicaDocument,\n GristReplicaTable,\n} from \"../types\"\nimport { computeRowCount, decodeColumnarToReplicaRows, type GristColumnarTable } from \"./grist-table-data\"\nimport { inferGristFormulaKind } from \"./grist-schema-formula\"\nimport { parseGristWidgetOptionsCell } from \"./grist-widget-options\"\nimport { coerceGristDocApiRefRowId } from \"./grist-value-codec\"\n\nexport type ReplicaTableColumnMetaLite = {\n colRef?: number\n type?: string\n label?: string\n parentPos?: number\n isFormula?: boolean\n formula?: string\n description?: string\n widgetOptions?: Record<string, unknown>\n displayColRef?: number\n visibleColRef?: number\n}\n\nconst FORMULA_PREVIEW_MAX = 500\n\nfunction readCellStr(table: Record<string, unknown[]>, key: string, rowIndex: number): string | undefined {\n const col = table[key]\n if (!Array.isArray(col)) return undefined\n const v = col[rowIndex]\n if (v === null || v === undefined) return undefined\n if (typeof v === \"string\") return v\n if (typeof v === \"number\" || typeof v === \"boolean\") return String(v)\n return undefined\n}\n\nfunction readCellNum(table: Record<string, unknown[]>, key: string, rowIndex: number): number | undefined {\n const col = table[key]\n if (!Array.isArray(col)) return undefined\n const v = col[rowIndex]\n if (typeof v === \"number\" && !Number.isNaN(v)) return v\n if (typeof v === \"string\" && v.trim() !== \"\") {\n const n = Number(v)\n if (!Number.isNaN(n)) return n\n }\n return undefined\n}\n\nfunction pickColumnMeta(meta: ReplicaTableColumnMetaLite | undefined): GristReplicaColumn {\n if (!meta) return {}\n const out: GristReplicaColumn = {}\n if (meta.colRef !== undefined) out.colRef = meta.colRef\n if (meta.type) out.type = meta.type\n if (meta.label) out.label = meta.label\n if (meta.parentPos !== undefined) out.parentPos = meta.parentPos\n if (meta.isFormula) out.isFormula = true\n const formulaRaw = meta.formula?.trim() ?? \"\"\n out.formulaKind = inferGristFormulaKind(Boolean(meta.isFormula), formulaRaw)\n if (formulaRaw) {\n out.formula =\n formulaRaw.length > FORMULA_PREVIEW_MAX ? `${formulaRaw.slice(0, FORMULA_PREVIEW_MAX)}...` : formulaRaw\n }\n if (meta.description) out.description = meta.description\n if (meta.widgetOptions && Object.keys(meta.widgetOptions).length > 0) {\n out.widgetOptions = meta.widgetOptions\n }\n if (meta.displayColRef !== undefined) out.displayColRef = meta.displayColRef\n if (meta.visibleColRef !== undefined) out.visibleColRef = meta.visibleColRef\n return out\n}\n\nexport async function loadColumnMetadataByTable(\n docApi: GristDocApi\n): Promise<Map<string, Map<string, ReplicaTableColumnMetaLite>>> {\n const byTable = new Map<string, Map<string, ReplicaTableColumnMetaLite>>()\n try {\n const tables = await docApi.fetchTable(\"_grist_Tables\")\n const columns = await docApi.fetchTable(\"_grist_Tables_column\")\n const tableIds = tables.tableId\n const tableInternalIds = tables.id\n if (!Array.isArray(tableIds) || !Array.isArray(tableInternalIds)) return byTable\n\n const internalIdToTableId = new Map<number, string>()\n for (let i = 0; i < tableInternalIds.length; i++) {\n const tid = tableIds[i]\n const iid = coerceGristDocApiRefRowId(tableInternalIds[i])\n if (typeof tid === \"string\" && iid !== undefined) internalIdToTableId.set(iid, tid)\n }\n\n const parentIds = columns.parentId\n const colIds = columns.colId\n const columnIds = columns.id\n if (\n !Array.isArray(parentIds) ||\n !Array.isArray(colIds) ||\n !Array.isArray(columnIds) ||\n parentIds.length !== colIds.length ||\n colIds.length !== columnIds.length\n ) {\n return byTable\n }\n\n const n = parentIds.length\n for (let i = 0; i < n; i++) {\n const parentRowId = coerceGristDocApiRefRowId(parentIds[i])\n const colRef = coerceGristDocApiRefRowId(columnIds[i])\n const colId = colIds[i]\n if (parentRowId === undefined || colRef === undefined || typeof colId !== \"string\") continue\n const tableId = internalIdToTableId.get(parentRowId)\n if (!tableId) continue\n\n let colMap = byTable.get(tableId)\n if (!colMap) {\n colMap = new Map()\n byTable.set(tableId, colMap)\n }\n\n const parentPos = readCellNum(columns, \"parentPos\", i)\n const isFormulaCol = columns.isFormula\n const isFormula = Array.isArray(isFormulaCol) ? Boolean(isFormulaCol[i]) : false\n\n const woCol = columns.widgetOptions\n const widgetOptions =\n Array.isArray(woCol) && i < woCol.length ? parseGristWidgetOptionsCell(woCol[i]) : undefined\n const displayColRef = coerceGristDocApiRefRowId(\n Array.isArray(columns.displayCol) ? columns.displayCol[i] : undefined\n )\n const visibleColRef = coerceGristDocApiRefRowId(\n Array.isArray(columns.visibleCol) ? columns.visibleCol[i] : undefined\n )\n\n colMap.set(colId, {\n colRef,\n type: readCellStr(columns, \"type\", i),\n label: readCellStr(columns, \"label\", i),\n parentPos: parentPos !== undefined ? parentPos : undefined,\n isFormula,\n formula: readCellStr(columns, \"formula\", i),\n description: readCellStr(columns, \"description\", i) ?? readCellStr(columns, \"descr\", i),\n widgetOptions,\n displayColRef,\n visibleColRef,\n })\n }\n } catch {\n // Metadata is best-effort; document build still works from cell data alone.\n }\n return byTable\n}\n\nexport function orderedColumnIds(\n data: Record<string, unknown[]>,\n metaByCol: Map<string, ReplicaTableColumnMetaLite>\n): string[] {\n const keys = Object.keys(data).filter((k) => Array.isArray(data[k]))\n keys.sort((a, b) => {\n const pa = metaByCol.get(a)?.parentPos\n const pb = metaByCol.get(b)?.parentPos\n if (pa !== undefined && pb !== undefined && pa !== pb) return pa - pb\n if (pa !== undefined && pb === undefined) return -1\n if (pa === undefined && pb !== undefined) return 1\n return a.localeCompare(b)\n })\n return keys\n}\n\n/** Build replica column metadata from columnar `fetchTable` + `_grist_Tables_column` maps. */\nexport function buildReplicaColumnsFromColumnar(\n data: Record<string, unknown[]>,\n colMeta: Map<string, ReplicaTableColumnMetaLite>\n): Record<string, GristReplicaColumn> {\n const columnIds = orderedColumnIds(data, colMeta)\n const columns: Record<string, GristReplicaColumn> = {}\n for (const colId of columnIds) {\n const arr = data[colId]\n if (!Array.isArray(arr)) continue\n const meta = colMeta.get(colId)\n columns[colId] = pickColumnMeta(meta)\n }\n return columns\n}\n\nfunction rowModeFromIncludeRows(includeRows: false | \"samples\" | \"full\"): GristDocumentMode {\n if (includeRows === false) return \"schema-only\"\n if (includeRows === \"samples\") return \"schema+samples\"\n return \"schema+data\"\n}\n\nexport type BuildReplicaDocumentFromDocApiOptions = {\n /** When false (default), skip fetching row data for `tableId` starting with `_grist`. */\n includeSystemTableData?: boolean\n /**\n * Row bodies: omit (`false`), first N (`samples`), or full decode (`full`).\n * Default `samples`.\n */\n includeRows?: false | \"samples\" | \"full\"\n /** Max rows per table when `includeRows` is `samples`. Default 10. */\n sampleRowLimit?: number\n /** Set on the replica as `source` for host logging / provenance. */\n source?: string\n}\n\n/**\n * Build {@link GristReplicaDocument} from a host `docApi`:\n * metadata from `_grist_Tables` / `_grist_Tables_column` when readable, plus optional decoded `rows`.\n *\n * Prefer {@link useGrist}'s `buildReplicaDocumentFromDocApi()` when you already use the primary hook.\n */\nexport async function buildReplicaDocumentFromDocApi(\n docApi: GristDocApi,\n options?: BuildReplicaDocumentFromDocApiOptions\n): Promise<GristReplicaDocument> {\n const includeSystemTableData = options?.includeSystemTableData ?? false\n const includeRows = options?.includeRows ?? \"samples\"\n const sampleRowLimit = options?.sampleRowLimit ?? 10\n const rowMode = rowModeFromIncludeRows(includeRows)\n\n const metaByTable = await loadColumnMetadataByTable(docApi)\n\n let docName: string | undefined\n try {\n docName = String(await Promise.resolve(docApi.getDocName()))\n } catch {\n docName = undefined\n }\n\n const tableIdsRaw = await Promise.resolve(docApi.listTables())\n const tableIds = Array.isArray(tableIdsRaw) ? [...tableIdsRaw] : []\n\n const tables: Record<string, GristReplicaTable> = {}\n\n for (const tableId of tableIds) {\n const omitData = !includeSystemTableData && tableId.startsWith(\"_grist\")\n if (omitData) {\n tables[tableId] = {\n rowCount: 0,\n dataOmitted: true,\n dataOmittedReason:\n \"Row scan skipped for tables whose id starts with `_grist` unless `includeSystemTableData` is true.\",\n columns: {},\n }\n continue\n }\n\n try {\n const data = (await docApi.fetchTable(tableId)) as GristColumnarTable\n const rowCount = computeRowCount(data)\n const colMeta = metaByTable.get(tableId) ?? new Map<string, ReplicaTableColumnMetaLite>()\n const columnIds = orderedColumnIds(data, colMeta)\n const columns = buildReplicaColumnsFromColumnar(data, colMeta)\n\n const table: GristReplicaTable = { columns, rowCount }\n if (includeRows === \"full\") {\n table.rows = decodeColumnarToReplicaRows(data, columnIds, columns)\n } else if (includeRows === \"samples\") {\n table.rows = decodeColumnarToReplicaRows(data, columnIds, columns, sampleRowLimit)\n }\n tables[tableId] = table\n } catch (err) {\n tables[tableId] = {\n rowCount: 0,\n error: err instanceof Error ? err.message : String(err),\n columns: {},\n }\n }\n }\n\n const out: GristReplicaDocument = {\n generatedAt: new Date().toISOString(),\n docName,\n mode: rowMode,\n tables,\n }\n if (options?.source !== undefined && options.source !== \"\") {\n out.source = options.source\n }\n return out\n}\n","import type { GristReplicaDocument, GristReplicaRow, GristReplicaTable } from \"../replica-document\"\n\n/**\n * Ensure `rows` is a concrete array for emulator / merge logic.\n * Call at host boundaries (`createDocument`, tests); JSON may still omit `rows` for schema-only.\n */\nexport function normalizeReplicaTableInput<T extends GristReplicaTable>(table: T): T & { rows: GristReplicaRow[] } {\n return { ...table, rows: table.rows ?? [] }\n}\n\n/** Apply {@link normalizeReplicaTableInput} to every table; shallow-copies the document shell. */\nexport function normalizeReplicaDocumentInput<T extends GristReplicaDocument>(doc: T): T {\n return {\n ...doc,\n tables: Object.fromEntries(\n Object.entries(doc.tables).map(([tableId, t]) => [tableId, normalizeReplicaTableInput(t)])\n ),\n } as T\n}\n\n/** How row arrays appear in serialized replica JSON from {@link buildReplicaJsonPayload}. */\nexport type ReplicaJsonIncludeRows = \"none\" | \"samples\" | \"full\"\n\n/**\n * Clone a replica document for JSON output: strip rows, cap to first N, or pass through.\n * Does not mutate the source document.\n */\nexport function buildReplicaJsonPayload(\n doc: GristReplicaDocument,\n options: { includeRows: ReplicaJsonIncludeRows; sampleRowLimit?: number }\n): GristReplicaDocument {\n const limit = options.sampleRowLimit ?? 10\n const tables = Object.fromEntries(\n Object.entries(doc.tables).map(([tid, t]) => {\n if (options.includeRows === \"none\") {\n const { rows: _r, ...rest } = t\n return [tid, rest]\n }\n if (options.includeRows === \"samples\") {\n const r = t.rows ?? []\n return [tid, { ...t, rows: r.slice(0, limit) }]\n }\n return [tid, { ...t, rows: t.rows }]\n })\n ) as GristReplicaDocument[\"tables\"]\n return { ...doc, tables }\n}\n","import type { GristColumnsToMap, GristColumnToMap, GristWidgetColumnMap } from \"../types\"\n\nexport type ValidateColumnMappingsResult = {\n ok: boolean\n /**\n * `true` while the host has not yet reported column mappings (e.g. between\n * `grist.ready()` resolving and the first `onRecord` / `onRecords` callback,\n * or before `sectionApi.mappings()` returns). Callers should not gate UI or\n * emit mapping alerts while pending.\n */\n pending?: boolean\n /** Logical names of required columns the user has not yet mapped. */\n missing: string[]\n /** Logical names of `allowMultiple` columns mapped to an empty list. */\n emptyMultiples: string[]\n}\n\n/**\n * Merges mapping payloads from `onRecord`, `onRecords`, and `sectionApi.mappings()`.\n * Later sources win; `undefined` sources are skipped; `null` means \"host reported\n * no mappings\" but still counts as a known (empty) payload.\n */\nexport function mergeWidgetColumnMaps(\n ...sources: (GristWidgetColumnMap | null | undefined)[]\n): GristWidgetColumnMap | null | undefined {\n let merged: GristWidgetColumnMap = {}\n let sawDefined = false\n for (const src of sources) {\n if (src === undefined) continue\n sawDefined = true\n if (src === null) continue\n merged = { ...merged, ...src }\n }\n if (!sawDefined) return undefined\n return merged\n}\n\nfunction asColumnSpec(entry: string | GristColumnToMap): GristColumnToMap {\n return typeof entry === \"string\" ? { name: entry } : entry\n}\n\n/**\n * Verifies that the current Grist mappings cover every required column declared\n * in `grist.ready({ columns })`.\n *\n * Use this before reading `mappedRecord` so you can render a \"please configure\n * the widget\" prompt instead of a confusing `null`.\n */\nexport function validateColumnMappings(\n spec: GristColumnsToMap | undefined | null,\n mappings: GristWidgetColumnMap | null | undefined\n): ValidateColumnMappingsResult {\n const missing: string[] = []\n const emptyMultiples: string[] = []\n if (!spec) return { ok: true, pending: false, missing, emptyMultiples }\n\n const m = mappings ?? {}\n for (const raw of spec) {\n const col = asColumnSpec(raw)\n if (col.optional) continue\n const value = m[col.name]\n if (col.allowMultiple) {\n if (value === undefined) {\n missing.push(col.name)\n } else if (!Array.isArray(value) || value.length === 0) {\n emptyMultiples.push(col.name)\n }\n } else {\n if (value === undefined || value === null || value === \"\") missing.push(col.name)\n }\n }\n return {\n ok: missing.length === 0 && emptyMultiples.length === 0,\n pending: false,\n missing,\n emptyMultiples,\n }\n}\n\n/** Status while waiting for the host to report mappings (see `pending`). */\nexport const pendingColumnMappingStatus: ValidateColumnMappingsResult = {\n ok: true,\n pending: true,\n missing: [],\n emptyMultiples: [],\n}\n","/**\n * Access-level helpers used by the handshake state machine.\n *\n * Kept in a tiny dedicated file because the same ranking is needed by the\n * reducer (`widened` flag, future re-negotiation logic) and potentially by\n * effects (decide whether to re-issue `grist.ready`).\n */\n\nimport type { GristRequiredAccess } from \"../../types\"\n\n/** Strictly-ordered ranking. Higher rank = stronger access. */\nexport const ACCESS_RANK: Record<GristRequiredAccess, number> = {\n none: 0,\n \"read table\": 1,\n full: 2,\n}\n\nconst GRIST_ACCESS_LEVELS: readonly GristRequiredAccess[] = [\"none\", \"read table\", \"full\"]\n\n/** Parse `interaction.access_level` / `accessLevel` from Grist `onOptions`. */\nexport function parseGristRequiredAccess(\n raw: string | undefined\n): GristRequiredAccess | null {\n if (!raw) return null\n return (GRIST_ACCESS_LEVELS as readonly string[]).includes(raw)\n ? (raw as GristRequiredAccess)\n : null\n}\n\n/** True when the host-granted level meets what the widget declared in `grist.ready`. */\nexport function isAccessSufficient(\n granted: GristRequiredAccess,\n required: GristRequiredAccess\n): boolean {\n return ACCESS_RANK[granted] >= ACCESS_RANK[required]\n}\n\n/** Creator-panel label for a Grist access level (for user-facing copy). */\nexport function gristAccessLevelLabel(level: GristRequiredAccess): string {\n switch (level) {\n case \"none\":\n return \"No document access\"\n case \"read table\":\n return \"Read selected table\"\n case \"full\":\n return \"Full document access\"\n }\n}\n\nexport function formatInsufficientAccessMessage(\n required: GristRequiredAccess,\n _granted: GristRequiredAccess\n): string {\n const need = gristAccessLevelLabel(required)\n return `Set Access level to at least \"${need}\" in the Custom widget settings.`\n}\n\nexport function isAccessWidening(\n previous: GristRequiredAccess | null,\n next: GristRequiredAccess\n): boolean {\n if (previous === null) return true\n return ACCESS_RANK[next] > ACCESS_RANK[previous]\n}\n","/**\n * Pure type contracts for the handshake / synchronization state machine.\n *\n * The machine models five orthogonal axes that together describe the widget's\n * relationship with the Grist host:\n *\n * 1. `LIFECYCLE` — protocol handshake (one-shot via `grist.ready`).\n * 2. `LINK` — RPC channel health (continuous, post-online).\n * 3. `AUTHZ` — effective access level granted by the host.\n * 4. `CONFIG` — column mapping contract with the end-user.\n * 5. `SYNC` — freshness of each event stream and ancillary RPCs.\n *\n * The legacy public `status` (\"booting\" / \"ready\" / \"unavailable\" / \"error\")\n * is a **pure projection** of the snapshot, computed in `./derive.ts`.\n *\n * No runtime side effects in this file — types only.\n */\n\nimport type { GristColumnsToMap, GristRequiredAccess, GristWidgetColumnMap } from \"../../types\"\n\n// ---------------------------------------------------------------------------\n// Branded primitives\n// ---------------------------------------------------------------------------\n\n/** Monotone counter bumped on reload / restart / link recovery / access widening. */\nexport type GristGeneration = number & { readonly __brand: \"GristGeneration\" }\n\nexport const ZERO_GENERATION = 0 as GristGeneration\n\nexport function nextGeneration(current: GristGeneration): GristGeneration {\n return (current + 1) as GristGeneration\n}\n\n// ---------------------------------------------------------------------------\n// 1. LIFECYCLE — handshake protocol\n// ---------------------------------------------------------------------------\n\nexport type GristLifecyclePhase =\n | \"idle\"\n | \"detecting\"\n | \"negotiating\"\n | \"online\"\n | \"terminated\"\n\nexport type GristTerminationReason =\n | { kind: \"script_timeout\"; attempts: number }\n | { kind: \"not_embedded\" }\n | { kind: \"ready_failed\"; message: string }\n | { kind: \"ready_timeout\"; afterMs: number }\n | { kind: \"host_rejected\"; message: string }\n | { kind: \"manual_terminate\" }\n\nexport type GristLifecycle =\n | { phase: \"idle\" }\n | { phase: \"detecting\"; attempts: number; startedAtMs: number }\n | { phase: \"negotiating\"; access: GristRequiredAccess; startedAtMs: number }\n | { phase: \"online\"; sinceMs: number; declaredAccess: GristRequiredAccess }\n | { phase: \"terminated\"; reason: GristTerminationReason; atMs: number }\n\n// ---------------------------------------------------------------------------\n// 2. LINK — RPC channel health\n// ---------------------------------------------------------------------------\n\nexport type GristLinkState = \"connected\" | \"stale\" | \"lost\"\n\nexport type GristLink = {\n state: GristLinkState\n /** ms timestamp of last successful RPC (or heartbeat). `null` before any. */\n lastSuccessMs: number | null\n /** Consecutive RPC failures since the last success. */\n missedPings: number\n}\n\n// ---------------------------------------------------------------------------\n// 3. AUTHZ — effective access\n// ---------------------------------------------------------------------------\n\nexport type GristAuthz =\n | { state: \"pending\"; declared: GristRequiredAccess }\n | {\n state: \"granted\"\n /** Effective level granted by the host. May differ from `declared`. */\n level: GristRequiredAccess\n declared: GristRequiredAccess\n /** True if granted level >= a previously granted level for the same widget. */\n widened: boolean\n }\n | { state: \"denied\"; declared: GristRequiredAccess; message?: string }\n\n// ---------------------------------------------------------------------------\n// 4. CONFIG — column-mapping contract\n// ---------------------------------------------------------------------------\n\n/**\n * Source that produced a mapping payload, used for deterministic merge by\n * {@link MappingResolver} (see `./mapping-resolver.ts`).\n */\nexport type GristMappingSource =\n | \"section_api\"\n | \"stream_record\"\n | \"stream_records\"\n | \"stream_new_record\"\n\n/**\n * Static priority order for mapping sources (lower index = higher priority).\n * `section_api` is the host's source-of-truth when available; stream payloads\n * are reactive fallbacks.\n */\nexport const MAPPING_SOURCE_PRIORITY: readonly GristMappingSource[] = [\n \"section_api\",\n \"stream_record\",\n \"stream_records\",\n \"stream_new_record\",\n] as const\n\nexport type GristMappingComplete = {\n state: \"complete\"\n declared: GristColumnsToMap\n mappings: GristWidgetColumnMap\n /** `\"merged\"` is used internally when multiple sources contributed. */\n source: GristMappingSource | \"merged\"\n reportedAtMs: number\n}\n\nexport type GristMappingIncomplete = {\n state: \"incomplete\"\n declared: GristColumnsToMap\n mappings: GristWidgetColumnMap\n missing: readonly string[]\n emptyMultiples: readonly string[]\n source: GristMappingSource | \"merged\"\n reportedAtMs: number\n}\n\nexport type GristMappingState =\n /** Widget did not declare any `columns` in `grist.ready`. */\n | { state: \"not_declared\" }\n /** Columns declared but no host report yet received. */\n | { state: \"pending\"; declared: GristColumnsToMap; declaredAtMs: number }\n | GristMappingIncomplete\n | GristMappingComplete\n /** User just modified the mapping; previous payload preserved to avoid UI flicker. */\n | {\n state: \"invalidating\"\n previous: GristMappingIncomplete | GristMappingComplete\n sinceMs: number\n }\n /** Declared but no host report after a timeout. Soft state — payload may still arrive. */\n | { state: \"unreported\"; declared: GristColumnsToMap; afterMs: number }\n\nexport type GristConfig = {\n mappings: GristMappingState\n}\n\n// ---------------------------------------------------------------------------\n// 5. SYNC — stream freshness\n// ---------------------------------------------------------------------------\n\nexport type GristStreamFreshness =\n | { state: \"cold\" }\n | { state: \"warming\"; sinceMs: number }\n | { state: \"hot\"; lastEventMs: number; generation: GristGeneration; payloadHash: string }\n | {\n state: \"stale\"\n lastEventMs: number\n reason: \"link_lost\" | \"tab_hidden\" | \"host_quiet\"\n }\n\nexport type GristCurrentTableState =\n | { state: \"unknown\" }\n | { state: \"known\"; tableId: string; refreshing: boolean }\n /** Local error (e.g. `selectedTable.getTableId()` rejected) — does NOT propagate to global status. */\n | { state: \"errored\"; message: string; sinceMs: number }\n\nexport type GristSync = {\n record: GristStreamFreshness\n records: GristStreamFreshness\n options: GristStreamFreshness\n newRecord: GristStreamFreshness\n currentTable: GristCurrentTableState\n}\n\n// ---------------------------------------------------------------------------\n// SNAPSHOT (aggregate)\n// ---------------------------------------------------------------------------\n\nexport type GristWidgetSnapshot = {\n generation: GristGeneration\n lifecycle: GristLifecycle\n link: GristLink\n authz: GristAuthz\n config: GristConfig\n sync: GristSync\n}\n\n// ---------------------------------------------------------------------------\n// PROJECTION — legacy 4-state status + capabilities\n// ---------------------------------------------------------------------------\n\n/** Mirrors the long-standing public type, kept for compat. */\nexport type GristWidgetStatus = \"booting\" | \"ready\" | \"unavailable\" | \"error\"\n\n/**\n * Pre-computed booleans that widget code should consume directly instead of\n * re-deriving from `status` + mapping flags + writes flags.\n *\n * Every field is a **pure function of the snapshot** and is referentially\n * stable across renders that don't change the snapshot's relevant slices.\n */\nexport type GristCapabilities = {\n /** `lifecycle.online` + `link != lost` + `authz.state === \"granted\"` with read or higher. */\n canRead: boolean\n /** `canRead` + (`mappings.state` is `complete` or `not_declared`). */\n canRender: boolean\n /** `canRender` + `authz.level === \"full\"`. Required before any write. */\n canWriteRecords: boolean\n /** `canWriteRecords` + `sync.currentTable.state === \"known\"`. */\n canWriteSchema: boolean\n /** `canRead` + `link === \"connected\"`. */\n canFetchTable: boolean\n /** `canRead` + `sync.record.state === \"hot\"` + mappings not invalidating. */\n hasFreshSelection: boolean\n /** `mappings.state === \"complete\" || \"not_declared\"`. */\n hasUsableMappings: boolean\n /** Logical column names still missing from user mapping (incomplete only). */\n missingMappings: readonly string[]\n /** `allowMultiple` columns mapped to `[]` (incomplete only). */\n emptyMultipleMappings: readonly string[]\n}\n\n// ---------------------------------------------------------------------------\n// Initial snapshot factory\n// ---------------------------------------------------------------------------\n\nexport function initialGristSnapshot(): GristWidgetSnapshot {\n return {\n generation: ZERO_GENERATION,\n lifecycle: { phase: \"idle\" },\n link: { state: \"connected\", lastSuccessMs: null, missedPings: 0 },\n authz: { state: \"pending\", declared: \"read table\" },\n config: { mappings: { state: \"not_declared\" } },\n sync: {\n record: { state: \"cold\" },\n records: { state: \"cold\" },\n options: { state: \"cold\" },\n newRecord: { state: \"cold\" },\n currentTable: { state: \"unknown\" },\n },\n }\n}\n","/**\n * Action union for the handshake state machine.\n *\n * Every action that can mutate the snapshot is listed here as a discriminated\n * union — exhaustiveness checks in the reducer rely on it.\n *\n * Actions either:\n * - target a single axis (e.g. `RPC_SUCCESS` → link), OR\n * - target multiple axes via a single transition (e.g. `NEGOTIATE_SUCCESS`\n * advances lifecycle AND authz at once).\n *\n * Generation-carrying actions can be **dropped** by the reducer if their\n * `generation` is older than the snapshot's current generation; this is the\n * primary defence against stale events arriving after a reload/restart.\n */\n\nimport type { GristColumnsToMap, GristRequiredAccess, GristWidgetColumnMap } from \"../../types\"\nimport type {\n GristGeneration,\n GristMappingSource,\n GristTerminationReason,\n} from \"./types\"\n\n// ---------------------------------------------------------------------------\n// Lifecycle actions\n// ---------------------------------------------------------------------------\n\nexport type GristLifecycleAction =\n | { type: \"DETECT_START\"; atMs: number }\n | { type: \"DETECT_TICK\"; attempts: number; atMs: number }\n | { type: \"DETECT_AVAILABLE\"; atMs: number }\n | { type: \"DETECT_TIMEOUT\"; attempts: number; atMs: number }\n | { type: \"NOT_EMBEDDED\"; atMs: number }\n | { type: \"NEGOTIATE_START\"; access: GristRequiredAccess; atMs: number }\n | {\n type: \"NEGOTIATE_SUCCESS\"\n access: GristRequiredAccess\n grantedLevel: GristRequiredAccess\n atMs: number\n }\n | { type: \"NEGOTIATE_FAIL\"; reason: GristTerminationReason; atMs: number }\n | { type: \"TERMINATE\"; reason: GristTerminationReason; atMs: number }\n\n// ---------------------------------------------------------------------------\n// Link actions\n// ---------------------------------------------------------------------------\n\nexport type GristLinkAction =\n | { type: \"RPC_SUCCESS\"; atMs: number }\n | { type: \"RPC_FAILURE\"; atMs: number; kind: \"timeout\" | \"rejected\" | \"other\" }\n | { type: \"HEARTBEAT_OK\"; atMs: number }\n | { type: \"HEARTBEAT_FAIL\"; atMs: number }\n\n// ---------------------------------------------------------------------------\n// Authz actions\n// ---------------------------------------------------------------------------\n\nexport type GristAuthzAction = {\n type: \"AUTHZ_REPORT\"\n /** Effective access level reported by Grist (`onOptions` / `interaction.access_level`). */\n level: GristRequiredAccess\n atMs: number\n generation: GristGeneration\n}\n\n// ---------------------------------------------------------------------------\n// Generation control\n// ---------------------------------------------------------------------------\n\nexport type GristGenerationAction = {\n type: \"BUMP_GENERATION\"\n atMs: number\n reason: \"reload\" | \"restart\" | \"link_recovery\" | \"widening\"\n}\n\n// ---------------------------------------------------------------------------\n// Config / mapping actions\n// ---------------------------------------------------------------------------\n\nexport type GristMappingAction =\n | {\n type: \"MAPPING_DECLARE\"\n declared: GristColumnsToMap\n atMs: number\n generation: GristGeneration\n }\n | {\n type: \"MAPPING_REPORT\"\n source: GristMappingSource\n payload: GristWidgetColumnMap | null\n atMs: number\n generation: GristGeneration\n }\n | { type: \"MAPPING_INVALIDATE\"; atMs: number; generation: GristGeneration }\n | { type: \"MAPPING_INVALIDATION_RESOLVE\"; atMs: number; generation: GristGeneration }\n | { type: \"MAPPING_TIMEOUT\"; atMs: number; generation: GristGeneration }\n\n// ---------------------------------------------------------------------------\n// Sync actions\n// ---------------------------------------------------------------------------\n\nexport type GristSyncStream = \"record\" | \"records\" | \"options\" | \"newRecord\"\n\nexport type GristSyncAction =\n | {\n type: \"STREAM_RECEIVED\"\n stream: GristSyncStream\n payloadHash: string\n atMs: number\n generation: GristGeneration\n }\n | { type: \"STREAM_WARMING\"; stream: GristSyncStream; atMs: number }\n | {\n type: \"STREAM_STALE\"\n stream: GristSyncStream\n atMs: number\n reason: \"link_lost\" | \"tab_hidden\" | \"host_quiet\"\n }\n | { type: \"CURRENT_TABLE_KNOWN\"; tableId: string; atMs: number }\n | { type: \"CURRENT_TABLE_REFRESH_START\"; atMs: number }\n | { type: \"CURRENT_TABLE_ERROR\"; message: string; atMs: number }\n\n// ---------------------------------------------------------------------------\n// Top-level union\n// ---------------------------------------------------------------------------\n\nexport type GristAction =\n | GristLifecycleAction\n | GristLinkAction\n | GristAuthzAction\n | GristGenerationAction\n | GristMappingAction\n | GristSyncAction\n\n/**\n * Type guard: actions that carry a `generation` field and can therefore be\n * dropped by the reducer if `action.generation < snapshot.generation`.\n */\nexport function hasGenerationStamp(\n action: GristAction\n): action is Extract<GristAction, { generation: GristGeneration }> {\n return \"generation\" in action && typeof action.generation === \"number\"\n}\n","/**\n * Deterministic merge of column-mapping payloads across multiple sources.\n *\n * Why this exists\n * ---------------\n * Grist reports column mappings from several places, possibly in different\n * orders depending on network timing and event scheduling:\n *\n * - `grist.sectionApi.mappings()` (one-shot promise),\n * - `grist.onRecord` (stream),\n * - `grist.onRecords` (stream, occasionally diverges from `onRecord`),\n * - `grist.onNewRecord` (stream, only on the \"new\" placeholder row).\n *\n * A \"later wins\" merge would let arrival order dictate the final mappings —\n * unstable and surprising. This resolver applies a fixed priority order\n * (see {@link MAPPING_SOURCE_PRIORITY}) so the resolution is a **pure function\n * of the set of received payloads**, independent of the order in which they\n * arrived.\n *\n * Generation safety\n * -----------------\n * Each payload is ingested with the {@link GristGeneration} that was active\n * when the source produced it. Payloads with `generation` strictly less than\n * the resolver's current generation are silently dropped — this is how the\n * machine recovers from reloads / restarts without ever applying a stale\n * mapping over a fresh one.\n */\n\nimport { validateColumnMappings } from \"../../helpers/grist-mappings\"\nimport type { GristColumnsToMap, GristWidgetColumnMap } from \"../../types\"\nimport {\n MAPPING_SOURCE_PRIORITY,\n type GristGeneration,\n type GristMappingComplete,\n type GristMappingIncomplete,\n type GristMappingSource,\n type GristMappingState,\n} from \"./types\"\n\nexport type MappingPayload = {\n source: GristMappingSource\n /** `null` is a known empty payload (host explicitly reported no mappings). */\n payload: GristWidgetColumnMap | null\n receivedAtMs: number\n generation: GristGeneration\n}\n\nexport type ResolveOutcome =\n | {\n kind: \"no_change\"\n reason: \"stale_generation\" | \"duplicate_payload\"\n }\n | {\n kind: \"resolved\"\n state: GristMappingComplete | GristMappingIncomplete\n }\n | { kind: \"still_pending\" }\n\n/**\n * Stateful resolver. One instance per declaration of `columns` (i.e. per\n * widget lifetime, modulo `reset()` on declare-change or restart).\n *\n * The resolver does NOT own the higher-level {@link GristMappingState} —\n * it returns concrete `complete` / `incomplete` payloads that the reducer\n * folds into the snapshot.\n */\nexport class MappingResolver {\n private declared: GristColumnsToMap\n private currentGeneration: GristGeneration\n /** Latest accepted payload per source. */\n private payloads = new Map<GristMappingSource, MappingPayload>()\n /** Last resolved state, used to detect duplicate ingests. */\n private lastResolvedHash: string | null = null\n\n constructor(declared: GristColumnsToMap, generation: GristGeneration) {\n this.declared = declared\n this.currentGeneration = generation\n }\n\n /**\n * Replace the declared columns (e.g. user passed a new `columns` array to\n * the provider). Clears accumulated payloads — they were validated against\n * the previous declaration.\n */\n redeclare(declared: GristColumnsToMap, atGeneration: GristGeneration): void {\n this.declared = declared\n this.currentGeneration = atGeneration\n this.payloads.clear()\n this.lastResolvedHash = null\n }\n\n /** Bump the active generation. Payloads from older generations are dropped. */\n bumpGeneration(next: GristGeneration): void {\n if (next <= this.currentGeneration) return\n this.currentGeneration = next\n // Drop any cached payloads from older generations.\n for (const [src, p] of this.payloads) {\n if (p.generation < next) this.payloads.delete(src)\n }\n this.lastResolvedHash = null\n }\n\n /** Forget every payload and reset the hash. The declaration is preserved. */\n reset(): void {\n this.payloads.clear()\n this.lastResolvedHash = null\n }\n\n /** Cheap, deterministic snapshot for tests/debug. */\n knownSources(): readonly GristMappingSource[] {\n return [...this.payloads.keys()]\n }\n\n /**\n * Ingest one payload. Returns a {@link ResolveOutcome}:\n * - `still_pending` — no payloads accepted yet.\n * - `no_change/stale_*` — input generation is older than current.\n * - `no_change/duplicate_payload` — input did not move the resolution.\n * - `resolved` — new resolution differs from the previous one.\n *\n * Call {@link current} to read the latest resolution without affecting\n * the duplicate-detection hash.\n */\n ingest(input: MappingPayload): ResolveOutcome {\n if (input.generation < this.currentGeneration) {\n return { kind: \"no_change\", reason: \"stale_generation\" }\n }\n if (input.generation > this.currentGeneration) {\n this.bumpGeneration(input.generation)\n }\n this.payloads.set(input.source, input)\n\n const computed = this.compute()\n if (computed === null) return { kind: \"still_pending\" }\n\n const hash = computeMappingHash(\n computed.mappings,\n computed.state === \"complete\",\n computed.source\n )\n if (hash === this.lastResolvedHash) {\n return { kind: \"no_change\", reason: \"duplicate_payload\" }\n }\n this.lastResolvedHash = hash\n return { kind: \"resolved\", state: computed }\n }\n\n /**\n * Return the resolver's current resolution (pure read). Equivalent to\n * `ingest(...)` without mutating any state — used by tests and by the\n * reducer when re-applying after `MAPPING_INVALIDATION_RESOLVE`.\n */\n current(): ResolveOutcome {\n const computed = this.compute()\n if (computed === null) return { kind: \"still_pending\" }\n return { kind: \"resolved\", state: computed }\n }\n\n /**\n * Compute the current best mapping from accumulated payloads (pure).\n *\n * Priority: higher-priority sources **override** specific keys from\n * lower-priority sources. Keys absent from a higher-priority source fall\n * back to lower-priority sources. This matches the production behaviour\n * where `sectionApi.mappings()` is authoritative for the keys it reports,\n * but stream payloads can fill in keys the section_api hasn't reported yet.\n */\n private compute(): GristMappingComplete | GristMappingIncomplete | null {\n if (this.payloads.size === 0) return null\n\n const merged: GristWidgetColumnMap = {}\n let latestReportedAt = 0\n const contributors: GristMappingSource[] = []\n\n for (const src of [...MAPPING_SOURCE_PRIORITY].reverse()) {\n const p = this.payloads.get(src)\n if (!p) continue\n contributors.push(src)\n if (p.receivedAtMs > latestReportedAt) latestReportedAt = p.receivedAtMs\n if (p.payload === null) continue\n for (const [k, v] of Object.entries(p.payload)) {\n merged[k] = v\n }\n }\n\n if (contributors.length === 0) return null\n\n const validation = validateColumnMappings(this.declared, merged)\n const source: GristMappingSource | \"merged\" =\n contributors.length === 1 ? (contributors[0] as GristMappingSource) : \"merged\"\n\n if (validation.ok) {\n return {\n state: \"complete\",\n declared: this.declared,\n mappings: merged,\n source,\n reportedAtMs: latestReportedAt,\n }\n }\n\n return {\n state: \"incomplete\",\n declared: this.declared,\n mappings: merged,\n missing: validation.missing,\n emptyMultiples: validation.emptyMultiples,\n source,\n reportedAtMs: latestReportedAt,\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Stable hash for a {complete|incomplete} mapping payload. Deterministic\n * across re-resolutions of identical inputs so the resolver can de-duplicate.\n */\nexport function computeMappingHash(\n mappings: GristWidgetColumnMap,\n ok: boolean,\n source: GristMappingSource | \"merged\"\n): string {\n const keys = Object.keys(mappings).sort()\n const body = keys.map((k) => {\n const v = mappings[k]\n if (Array.isArray(v)) return `${k}=[${v.join(\",\")}]`\n return `${k}=${v ?? \"\"}`\n }).join(\"|\")\n return `${ok ? \"OK\" : \"KO\"}::${source}::${body}`\n}\n\n/**\n * Decide whether to treat a newly arrived payload as a graceful invalidation\n * of the previous mapping (user just edited the section's mapping settings).\n *\n * Returns `true` if `previous` was `complete`/`incomplete` and `next` differs\n * by at least one key. Pure function, no side effects.\n */\nexport function shouldInvalidate(\n previous: GristMappingState,\n nextMappings: GristWidgetColumnMap\n): boolean {\n if (previous.state !== \"complete\" && previous.state !== \"incomplete\") return false\n const a = previous.mappings\n const aKeys = Object.keys(a)\n const bKeys = Object.keys(nextMappings)\n if (aKeys.length !== bKeys.length) return true\n for (const k of aKeys) {\n const av = a[k]\n const bv = nextMappings[k]\n if (Array.isArray(av) && Array.isArray(bv)) {\n if (av.length !== bv.length) return true\n for (let i = 0; i < av.length; i++) if (av[i] !== bv[i]) return true\n } else if (av !== bv) {\n return true\n }\n }\n return false\n}\n","/**\n * Pure reducer for the handshake state machine.\n *\n * Contract\n * --------\n * - **Pure**: `(snapshot, action, ctx) => nextSnapshot`. No I/O, no globals,\n * no Date.now() — callers pass timestamps via `action.atMs` and (optionally)\n * a context object for the {@link MappingResolver}.\n * - **Total**: every (snapshot.lifecycle.phase × action.type) pair returns\n * either an updated snapshot or the identity snapshot.\n * - **Idempotent for replays**: same generation-stamped action applied twice\n * leaves the snapshot unchanged (`payloadHash` short-circuit on streams,\n * resolver hash short-circuit on mappings).\n * - **Generation-safe**: any action carrying a `generation` lower than the\n * current snapshot generation is dropped silently — this is what makes\n * the SDK robust to late events after reload/restart.\n *\n * The reducer never throws. Invariant violations are surfaced via\n * `./invariants.ts` if the caller opts in.\n */\n\nimport {\n hasGenerationStamp,\n type GristAction,\n type GristMappingAction,\n type GristSyncAction,\n type GristSyncStream,\n} from \"./actions\"\nimport { MappingResolver } from \"./mapping-resolver\"\nimport {\n ZERO_GENERATION,\n nextGeneration,\n type GristGeneration,\n type GristLifecycle,\n type GristLink,\n type GristMappingComplete,\n type GristMappingIncomplete,\n type GristMappingState,\n type GristStreamFreshness,\n type GristSync,\n type GristTerminationReason,\n type GristWidgetSnapshot,\n} from \"./types\"\nimport {\n ACCESS_RANK,\n formatInsufficientAccessMessage,\n isAccessSufficient,\n} from \"./access\"\nimport type { GristRequiredAccess } from \"../../types\"\n\n/**\n * Per-machine mutable companion to the snapshot. The reducer reads from it\n * (and lets the resolver mutate it in-place) so the snapshot itself can stay\n * a deeply-frozen, immutable value.\n */\nexport type GristReducerContext = {\n resolver: MappingResolver | null\n}\n\nexport function createReducerContext(): GristReducerContext {\n return { resolver: null }\n}\n\n/**\n * Tuning knobs. Pass `Partial<ReducerConfig>` to override defaults; values\n * are read by the reducer at each step.\n */\nexport type ReducerConfig = {\n /** Stale-pings threshold before link transitions to `stale`. */\n staleAfterMissed: number\n /** Stale-pings threshold before link transitions to `lost`. */\n lostAfterMissed: number\n}\n\nexport const DEFAULT_REDUCER_CONFIG: ReducerConfig = {\n staleAfterMissed: 1,\n lostAfterMissed: 3,\n}\n\n// ---------------------------------------------------------------------------\n// Reducer entry point\n// ---------------------------------------------------------------------------\n\nexport function gristReducer(\n snapshot: GristWidgetSnapshot,\n action: GristAction,\n ctx: GristReducerContext,\n config: ReducerConfig = DEFAULT_REDUCER_CONFIG\n): GristWidgetSnapshot {\n // Generation gate — applied to every action that carries a generation.\n if (hasGenerationStamp(action) && action.generation < snapshot.generation) {\n return snapshot\n }\n\n switch (action.type) {\n // -- Lifecycle --------------------------------------------------------\n case \"DETECT_START\":\n return reduceDetectStart(snapshot, action.atMs)\n case \"DETECT_TICK\":\n return reduceDetectTick(snapshot, action.attempts)\n case \"DETECT_AVAILABLE\":\n return reduceDetectAvailable(snapshot, action.atMs)\n case \"DETECT_TIMEOUT\":\n return reduceTerminate(snapshot, {\n kind: \"script_timeout\",\n attempts: action.attempts,\n }, action.atMs)\n case \"NOT_EMBEDDED\":\n return reduceTerminate(snapshot, { kind: \"not_embedded\" }, action.atMs)\n case \"NEGOTIATE_START\":\n return reduceNegotiateStart(snapshot, action.access, action.atMs)\n case \"NEGOTIATE_SUCCESS\":\n return reduceNegotiateSuccess(snapshot, action.access, action.grantedLevel, action.atMs)\n case \"NEGOTIATE_FAIL\":\n return reduceTerminate(snapshot, action.reason, action.atMs)\n case \"TERMINATE\":\n return reduceTerminate(snapshot, action.reason, action.atMs)\n case \"AUTHZ_REPORT\":\n return reduceAuthzReport(snapshot, action.level, action.atMs)\n\n // -- Link -------------------------------------------------------------\n case \"RPC_SUCCESS\":\n case \"HEARTBEAT_OK\":\n return reduceLinkSuccess(snapshot, action.atMs)\n case \"RPC_FAILURE\":\n case \"HEARTBEAT_FAIL\":\n return reduceLinkFailure(snapshot, action.atMs, config)\n\n // -- Generation -------------------------------------------------------\n case \"BUMP_GENERATION\":\n return reduceBumpGeneration(snapshot, ctx)\n\n // -- Config / mappings -----------------------------------------------\n case \"MAPPING_DECLARE\":\n case \"MAPPING_REPORT\":\n case \"MAPPING_INVALIDATE\":\n case \"MAPPING_INVALIDATION_RESOLVE\":\n case \"MAPPING_TIMEOUT\":\n return reduceMapping(snapshot, action, ctx)\n\n // -- Sync -------------------------------------------------------------\n case \"STREAM_RECEIVED\":\n case \"STREAM_WARMING\":\n case \"STREAM_STALE\":\n return reduceStream(snapshot, action)\n case \"CURRENT_TABLE_KNOWN\":\n return updateSync(snapshot, {\n ...snapshot.sync,\n currentTable: { state: \"known\", tableId: action.tableId, refreshing: false },\n })\n case \"CURRENT_TABLE_REFRESH_START\":\n if (snapshot.sync.currentTable.state !== \"known\") return snapshot\n return updateSync(snapshot, {\n ...snapshot.sync,\n currentTable: { ...snapshot.sync.currentTable, refreshing: true },\n })\n case \"CURRENT_TABLE_ERROR\":\n return updateSync(snapshot, {\n ...snapshot.sync,\n currentTable: { state: \"errored\", message: action.message, sinceMs: action.atMs },\n })\n\n default: {\n // Exhaustiveness check — TypeScript guarantees this is `never`.\n const _exhaustive: never = action\n void _exhaustive\n return snapshot\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Lifecycle transitions\n// ---------------------------------------------------------------------------\n\nfunction reduceDetectStart(snapshot: GristWidgetSnapshot, atMs: number): GristWidgetSnapshot {\n if (snapshot.lifecycle.phase !== \"idle\") return snapshot\n return {\n ...snapshot,\n lifecycle: { phase: \"detecting\", attempts: 0, startedAtMs: atMs },\n }\n}\n\nfunction reduceDetectTick(snapshot: GristWidgetSnapshot, attempts: number): GristWidgetSnapshot {\n if (snapshot.lifecycle.phase !== \"detecting\") return snapshot\n if (attempts === snapshot.lifecycle.attempts) return snapshot\n return {\n ...snapshot,\n lifecycle: { ...snapshot.lifecycle, attempts },\n }\n}\n\nfunction reduceDetectAvailable(\n snapshot: GristWidgetSnapshot,\n atMs: number\n): GristWidgetSnapshot {\n if (snapshot.lifecycle.phase !== \"detecting\" && snapshot.lifecycle.phase !== \"idle\") {\n return snapshot\n }\n return {\n ...snapshot,\n lifecycle: {\n phase: \"negotiating\",\n access: snapshot.authz.declared,\n startedAtMs: atMs,\n },\n }\n}\n\nfunction reduceNegotiateStart(\n snapshot: GristWidgetSnapshot,\n access: GristWidgetSnapshot[\"authz\"][\"declared\"],\n atMs: number\n): GristWidgetSnapshot {\n // Allowed from `detecting` (first negotiate), `negotiating` (re-arm),\n // or `online` (access widening triggers re-negotiation in place).\n if (snapshot.lifecycle.phase === \"terminated\") return snapshot\n return {\n ...snapshot,\n authz: { state: \"pending\", declared: access },\n lifecycle:\n snapshot.lifecycle.phase === \"online\"\n ? snapshot.lifecycle\n : { phase: \"negotiating\", access, startedAtMs: atMs },\n }\n}\n\nfunction authzDeclared(snapshot: GristWidgetSnapshot): GristRequiredAccess {\n return snapshot.authz.declared\n}\n\nfunction reduceAuthzReport(\n snapshot: GristWidgetSnapshot,\n level: GristRequiredAccess,\n _atMs: number\n): GristWidgetSnapshot {\n if (snapshot.lifecycle.phase !== \"online\") return snapshot\n\n const declared = authzDeclared(snapshot)\n\n if (isAccessSufficient(level, declared)) {\n const previousLevel =\n snapshot.authz.state === \"granted\" ? snapshot.authz.level : null\n const widened =\n previousLevel !== null && ACCESS_RANK[level] > ACCESS_RANK[previousLevel]\n const nextAuthz = {\n state: \"granted\" as const,\n level,\n declared,\n widened,\n }\n if (\n snapshot.authz.state === \"granted\" &&\n snapshot.authz.level === nextAuthz.level &&\n snapshot.authz.declared === nextAuthz.declared &&\n snapshot.authz.widened === nextAuthz.widened\n ) {\n return snapshot\n }\n return { ...snapshot, authz: nextAuthz }\n }\n\n const message = formatInsufficientAccessMessage(declared, level)\n const nextAuthz = { state: \"denied\" as const, declared, message }\n if (\n snapshot.authz.state === \"denied\" &&\n snapshot.authz.declared === nextAuthz.declared &&\n snapshot.authz.message === nextAuthz.message\n ) {\n return snapshot\n }\n return { ...snapshot, authz: nextAuthz }\n}\n\nfunction reduceNegotiateSuccess(\n snapshot: GristWidgetSnapshot,\n access: GristWidgetSnapshot[\"authz\"][\"declared\"],\n grantedLevel: GristWidgetSnapshot[\"authz\"][\"declared\"],\n atMs: number\n): GristWidgetSnapshot {\n if (snapshot.lifecycle.phase === \"terminated\") return snapshot\n\n const previousLevel =\n snapshot.authz.state === \"granted\" ? snapshot.authz.level : null\n const widened =\n previousLevel !== null && ACCESS_RANK[grantedLevel] > ACCESS_RANK[previousLevel]\n\n return {\n ...snapshot,\n authz: {\n state: \"granted\",\n level: grantedLevel,\n declared: access,\n widened,\n },\n lifecycle:\n snapshot.lifecycle.phase === \"online\"\n ? snapshot.lifecycle\n : { phase: \"online\", sinceMs: atMs, declaredAccess: access },\n link: { state: \"connected\", lastSuccessMs: atMs, missedPings: 0 },\n }\n}\n\nfunction reduceTerminate(\n snapshot: GristWidgetSnapshot,\n reason: GristTerminationReason,\n atMs: number\n): GristWidgetSnapshot {\n if (snapshot.lifecycle.phase === \"terminated\") return snapshot\n const lifecycle: GristLifecycle = { phase: \"terminated\", reason, atMs }\n return { ...snapshot, lifecycle }\n}\n\n// ---------------------------------------------------------------------------\n// Link transitions\n// ---------------------------------------------------------------------------\n\nfunction reduceLinkSuccess(snapshot: GristWidgetSnapshot, atMs: number): GristWidgetSnapshot {\n if (snapshot.lifecycle.phase !== \"online\") return snapshot\n const link: GristLink = { state: \"connected\", lastSuccessMs: atMs, missedPings: 0 }\n if (\n snapshot.link.state === link.state &&\n snapshot.link.lastSuccessMs === link.lastSuccessMs &&\n snapshot.link.missedPings === link.missedPings\n ) {\n return snapshot\n }\n return { ...snapshot, link }\n}\n\nfunction reduceLinkFailure(\n snapshot: GristWidgetSnapshot,\n _atMs: number,\n config: ReducerConfig\n): GristWidgetSnapshot {\n if (snapshot.lifecycle.phase !== \"online\") return snapshot\n const missed = snapshot.link.missedPings + 1\n let state: GristLink[\"state\"] = snapshot.link.state\n if (missed >= config.lostAfterMissed) state = \"lost\"\n else if (missed >= config.staleAfterMissed) state = \"stale\"\n return {\n ...snapshot,\n link: { state, lastSuccessMs: snapshot.link.lastSuccessMs, missedPings: missed },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Generation\n// ---------------------------------------------------------------------------\n\nfunction reduceBumpGeneration(\n snapshot: GristWidgetSnapshot,\n ctx: GristReducerContext\n): GristWidgetSnapshot {\n const next = nextGeneration(snapshot.generation)\n ctx.resolver?.bumpGeneration(next)\n return {\n ...snapshot,\n generation: next,\n // Marking streams as warming again ensures hooks treat the data as\n // \"in transit\" until a fresh event arrives under the new generation.\n sync: {\n ...snapshot.sync,\n record: degradeForRefresh(snapshot.sync.record, snapshot.generation),\n records: degradeForRefresh(snapshot.sync.records, snapshot.generation),\n options: degradeForRefresh(snapshot.sync.options, snapshot.generation),\n newRecord: degradeForRefresh(snapshot.sync.newRecord, snapshot.generation),\n },\n }\n}\n\nfunction degradeForRefresh(\n freshness: GristStreamFreshness,\n prevGeneration: GristGeneration\n): GristStreamFreshness {\n if (freshness.state === \"hot\" && freshness.generation === prevGeneration) {\n return { state: \"stale\", lastEventMs: freshness.lastEventMs, reason: \"host_quiet\" }\n }\n return freshness\n}\n\n// ---------------------------------------------------------------------------\n// Mappings (config)\n// ---------------------------------------------------------------------------\n\nfunction reduceMapping(\n snapshot: GristWidgetSnapshot,\n action: GristMappingAction,\n ctx: GristReducerContext\n): GristWidgetSnapshot {\n switch (action.type) {\n case \"MAPPING_DECLARE\": {\n if (action.declared.length === 0) {\n // Empty declaration → revert to `not_declared`.\n if (snapshot.config.mappings.state === \"not_declared\") return snapshot\n ctx.resolver = null\n return {\n ...snapshot,\n config: { mappings: { state: \"not_declared\" } },\n }\n }\n if (!ctx.resolver) {\n ctx.resolver = new MappingResolver(action.declared, snapshot.generation)\n } else {\n ctx.resolver.redeclare(action.declared, snapshot.generation)\n }\n return {\n ...snapshot,\n config: {\n mappings: {\n state: \"pending\",\n declared: action.declared,\n declaredAtMs: action.atMs,\n },\n },\n }\n }\n case \"MAPPING_REPORT\": {\n if (!ctx.resolver) return snapshot\n const outcome = ctx.resolver.ingest({\n source: action.source,\n payload: action.payload,\n receivedAtMs: action.atMs,\n generation: action.generation,\n })\n if (outcome.kind !== \"resolved\") return snapshot\n return applyResolved(snapshot, outcome.state)\n }\n case \"MAPPING_INVALIDATE\": {\n const previous = snapshot.config.mappings\n if (previous.state !== \"complete\" && previous.state !== \"incomplete\") {\n return snapshot\n }\n return {\n ...snapshot,\n config: {\n mappings: {\n state: \"invalidating\",\n previous: previous as GristMappingComplete | GristMappingIncomplete,\n sinceMs: action.atMs,\n },\n },\n }\n }\n case \"MAPPING_INVALIDATION_RESOLVE\": {\n if (snapshot.config.mappings.state !== \"invalidating\") return snapshot\n if (!ctx.resolver) {\n // Resolver lost (e.g. declaration cleared) — fall back to `previous`.\n return {\n ...snapshot,\n config: { mappings: snapshot.config.mappings.previous },\n }\n }\n const outcome = ctx.resolver.current()\n if (outcome.kind !== \"resolved\") {\n return {\n ...snapshot,\n config: { mappings: snapshot.config.mappings.previous },\n }\n }\n return applyResolved(snapshot, outcome.state)\n }\n case \"MAPPING_TIMEOUT\": {\n const previous = snapshot.config.mappings\n if (previous.state !== \"pending\") return snapshot\n return {\n ...snapshot,\n config: {\n mappings: {\n state: \"unreported\",\n declared: previous.declared,\n afterMs: action.atMs - previous.declaredAtMs,\n },\n },\n }\n }\n }\n}\n\nfunction applyResolved(\n snapshot: GristWidgetSnapshot,\n resolved: GristMappingComplete | GristMappingIncomplete\n): GristWidgetSnapshot {\n const existing = snapshot.config.mappings\n if (\n (existing.state === \"complete\" || existing.state === \"incomplete\") &&\n sameResolved(existing, resolved)\n ) {\n return snapshot\n }\n return { ...snapshot, config: { mappings: resolved } }\n}\n\nfunction sameResolved(\n a: GristMappingState,\n b: GristMappingComplete | GristMappingIncomplete\n): boolean {\n if (a.state !== b.state) return false\n if (a.state !== \"complete\" && a.state !== \"incomplete\") return false\n if (a.source !== b.source) return false\n const ak = Object.keys(a.mappings)\n const bk = Object.keys(b.mappings)\n if (ak.length !== bk.length) return false\n for (const k of ak) {\n const av = a.mappings[k]\n const bv = b.mappings[k]\n if (Array.isArray(av) && Array.isArray(bv)) {\n if (av.length !== bv.length) return false\n for (let i = 0; i < av.length; i++) if (av[i] !== bv[i]) return false\n } else if (av !== bv) {\n return false\n }\n }\n return true\n}\n\n// ---------------------------------------------------------------------------\n// Streams (sync)\n// ---------------------------------------------------------------------------\n\nfunction reduceStream(snapshot: GristWidgetSnapshot, action: GristSyncAction): GristWidgetSnapshot {\n if (action.type === \"CURRENT_TABLE_KNOWN\" || action.type === \"CURRENT_TABLE_REFRESH_START\" || action.type === \"CURRENT_TABLE_ERROR\") {\n return snapshot\n }\n const stream = action.stream\n const current = snapshot.sync[stream]\n\n if (action.type === \"STREAM_WARMING\") {\n if (current.state === \"warming\" || current.state === \"hot\") return snapshot\n return updateStream(snapshot, stream, { state: \"warming\", sinceMs: action.atMs })\n }\n\n if (action.type === \"STREAM_STALE\") {\n if (current.state !== \"hot\") return snapshot\n return updateStream(snapshot, stream, {\n state: \"stale\",\n lastEventMs: current.lastEventMs,\n reason: action.reason,\n })\n }\n\n // STREAM_RECEIVED — idempotent on (generation, hash).\n if (\n current.state === \"hot\" &&\n current.generation === action.generation &&\n current.payloadHash === action.payloadHash\n ) {\n return snapshot\n }\n return updateStream(snapshot, stream, {\n state: \"hot\",\n lastEventMs: action.atMs,\n generation: action.generation,\n payloadHash: action.payloadHash,\n })\n}\n\nfunction updateStream(\n snapshot: GristWidgetSnapshot,\n stream: GristSyncStream,\n next: GristStreamFreshness\n): GristWidgetSnapshot {\n return {\n ...snapshot,\n sync: { ...snapshot.sync, [stream]: next },\n }\n}\n\nfunction updateSync(snapshot: GristWidgetSnapshot, sync: GristSync): GristWidgetSnapshot {\n return { ...snapshot, sync }\n}\n\n// ---------------------------------------------------------------------------\n// Re-exports (convenience)\n// ---------------------------------------------------------------------------\n\nexport { ZERO_GENERATION, nextGeneration }\n","/**\n * Pure projections from a {@link GristWidgetSnapshot}:\n *\n * - {@link deriveStatus} → legacy 4-state `status` (compat).\n * - {@link deriveCapabilities} → ready-to-bind booleans for widget UI.\n *\n * Both are deterministic and side-effect free. Callers (hooks, Boundary)\n * memoize them by reference equality of `snapshot`.\n */\n\nimport { ACCESS_RANK } from \"./access\"\nimport {\n pendingColumnMappingStatus,\n type ValidateColumnMappingsResult,\n} from \"../../helpers/grist-mappings\"\nimport type { GristColumnsToMap, GristWidgetColumnMap } from \"../../types\"\nimport type {\n GristCapabilities,\n GristMappingState,\n GristWidgetSnapshot,\n GristWidgetStatus,\n} from \"./types\"\n\n// ---------------------------------------------------------------------------\n// Status projection\n// ---------------------------------------------------------------------------\n\nexport function deriveStatus(snapshot: GristWidgetSnapshot): GristWidgetStatus {\n const { lifecycle, authz, link } = snapshot\n\n if (lifecycle.phase === \"idle\" || lifecycle.phase === \"detecting\") return \"booting\"\n\n if (lifecycle.phase === \"negotiating\") return \"booting\"\n\n if (lifecycle.phase === \"terminated\") {\n switch (lifecycle.reason.kind) {\n case \"script_timeout\":\n case \"not_embedded\":\n return \"unavailable\"\n case \"host_rejected\":\n case \"ready_failed\":\n case \"ready_timeout\":\n case \"manual_terminate\":\n return \"error\"\n }\n }\n\n // lifecycle.phase === \"online\"\n if (authz.state === \"denied\") return \"error\"\n if (link.state === \"lost\") return \"error\"\n return \"ready\"\n}\n\n/** Extract a single human-readable error message, if any, from the snapshot. */\nexport function deriveErrorMessage(snapshot: GristWidgetSnapshot): string | null {\n if (snapshot.lifecycle.phase === \"terminated\") {\n switch (snapshot.lifecycle.reason.kind) {\n case \"ready_failed\":\n return snapshot.lifecycle.reason.message\n case \"ready_timeout\":\n return `Grist handshake timed out after ${snapshot.lifecycle.reason.afterMs}ms`\n case \"host_rejected\":\n return snapshot.lifecycle.reason.message\n case \"script_timeout\":\n return `Grist plugin API never loaded (${snapshot.lifecycle.reason.attempts} attempts)`\n case \"not_embedded\":\n return \"This page is not embedded in a Grist iframe\"\n case \"manual_terminate\":\n return null\n }\n }\n if (snapshot.authz.state === \"denied\") {\n return (\n snapshot.authz.message ??\n `Grist denied requested access (${snapshot.authz.declared})`\n )\n }\n if (snapshot.lifecycle.phase === \"online\" && snapshot.link.state === \"lost\") {\n return `Grist link lost (${snapshot.link.missedPings} consecutive failures)`\n }\n return null\n}\n\n// ---------------------------------------------------------------------------\n// Capabilities derivation\n// ---------------------------------------------------------------------------\n\nexport function deriveCapabilities(snapshot: GristWidgetSnapshot): GristCapabilities {\n const { lifecycle, authz, link, config, sync } = snapshot\n const online = lifecycle.phase === \"online\"\n const granted = authz.state === \"granted\"\n const grantedReadOrMore =\n granted && ACCESS_RANK[authz.level] >= ACCESS_RANK[\"read table\"]\n const grantedFull = granted && authz.level === \"full\"\n const linkUsable = link.state !== \"lost\"\n\n const canRead = online && linkUsable && grantedReadOrMore\n const canFetchTable = canRead && link.state === \"connected\"\n\n const mappingsUsable = hasUsableMappings(config.mappings)\n const missing = mappingsMissing(config.mappings)\n const emptyMultiples = mappingsEmptyMultiples(config.mappings)\n\n const canRender = canRead && mappingsUsable\n const canWriteRecords = canRender && grantedFull\n const canWriteSchema =\n canWriteRecords && sync.currentTable.state === \"known\"\n\n const hasFreshSelection =\n canRead &&\n sync.record.state === \"hot\" &&\n config.mappings.state !== \"invalidating\"\n\n return {\n canRead,\n canRender,\n canWriteRecords,\n canWriteSchema,\n canFetchTable,\n hasFreshSelection,\n hasUsableMappings: mappingsUsable,\n missingMappings: missing,\n emptyMultipleMappings: emptyMultiples,\n }\n}\n\n// ---------------------------------------------------------------------------\n// Mapping helpers\n// ---------------------------------------------------------------------------\n\nfunction hasUsableMappings(state: GristMappingState): boolean {\n if (state.state === \"not_declared\") return true\n if (state.state === \"complete\") return true\n if (state.state === \"invalidating\") {\n return state.previous.state === \"complete\"\n }\n return false\n}\n\nfunction mappingsMissing(state: GristMappingState): readonly string[] {\n if (state.state === \"incomplete\") return state.missing\n if (state.state === \"invalidating\" && state.previous.state === \"incomplete\") {\n return state.previous.missing\n }\n return EMPTY\n}\n\nfunction mappingsEmptyMultiples(state: GristMappingState): readonly string[] {\n if (state.state === \"incomplete\") return state.emptyMultiples\n if (state.state === \"invalidating\" && state.previous.state === \"incomplete\") {\n return state.previous.emptyMultiples\n }\n return EMPTY\n}\n\nconst EMPTY: readonly string[] = Object.freeze([])\n\n// ---------------------------------------------------------------------------\n// Column-mapping projection (public `columnMappingStatus` shape)\n// ---------------------------------------------------------------------------\n\n/** Resolved mappings from the FSM config axis, if any. */\nexport function extractResolvedMappings(\n state: GristMappingState\n): GristWidgetColumnMap | null {\n switch (state.state) {\n case \"complete\":\n case \"incomplete\":\n return state.mappings\n case \"invalidating\":\n if (state.previous.state === \"complete\" || state.previous.state === \"incomplete\") {\n return state.previous.mappings\n }\n return null\n default:\n return null\n }\n}\n\n/**\n * Project {@link GristMappingState} into the legacy\n * {@link ValidateColumnMappingsResult} consumed by `useGrist().columnMappingStatus`.\n */\nexport function deriveColumnMappingStatus(\n mappingState: GristMappingState,\n columns?: GristColumnsToMap\n): ValidateColumnMappingsResult {\n if (!columns?.length) {\n return { ok: true, pending: false, missing: [], emptyMultiples: [] }\n }\n switch (mappingState.state) {\n case \"not_declared\":\n return { ok: true, pending: false, missing: [], emptyMultiples: [] }\n case \"pending\":\n return pendingColumnMappingStatus\n case \"unreported\":\n return pendingColumnMappingStatus\n case \"complete\":\n return { ok: true, pending: false, missing: [], emptyMultiples: [] }\n case \"incomplete\":\n return {\n ok: false,\n pending: false,\n missing: [...mappingState.missing],\n emptyMultiples: [...mappingState.emptyMultiples],\n }\n case \"invalidating\":\n return deriveColumnMappingStatus(mappingState.previous, columns)\n }\n}\n","/**\n * Pure projections from the handshake snapshot for boundary / shell UI.\n *\n * Blocking states (`booting`, `unavailable`, `error`) map to full-screen chrome\n * via `<GristBoundary>`. Non-blocking degradations stay on the alert path\n * ({@link getGristSdkAlertDescriptors}).\n */\n\nimport { gristAccessLevelLabel } from \"../internal/handshake/access\"\nimport { deriveErrorMessage, deriveStatus, type GristWidgetSnapshot } from \"../internal/handshake\"\nimport type { GristWidgetStatus } from \"../internal/hooks/use-grist-core\"\n\nexport type GristBoundaryBlockingKind = \"booting\" | \"unavailable\" | \"error\"\n\nexport type GristBoundaryBootPhase = \"idle\" | \"detecting\" | \"negotiating\" | \"generic\"\n\nexport type GristBoundaryView =\n | {\n mode: \"blocking\"\n kind: GristBoundaryBlockingKind\n bootPhase?: GristBoundaryBootPhase\n title: string\n message: string\n showRetry: boolean\n }\n | { mode: \"ready\" }\n\n/**\n * Human-readable boot label from lifecycle phase (for spinners / progress UI).\n */\nexport function deriveBoundaryBootLabel(snapshot: GristWidgetSnapshot): string {\n const { lifecycle } = snapshot\n switch (lifecycle.phase) {\n case \"idle\":\n return \"Starting…\"\n case \"detecting\":\n return lifecycle.attempts > 0\n ? `Looking for Grist… (attempt ${lifecycle.attempts})`\n : \"Looking for Grist…\"\n case \"negotiating\":\n return \"Asking Grist for the access this widget needs…\"\n case \"online\":\n return \"Connected\"\n case \"terminated\":\n return \"Connection ended\"\n }\n}\n\nexport function deriveBoundaryBootPhase(\n snapshot: GristWidgetSnapshot\n): GristBoundaryBootPhase {\n switch (snapshot.lifecycle.phase) {\n case \"idle\":\n return \"idle\"\n case \"detecting\":\n return \"detecting\"\n case \"negotiating\":\n return \"negotiating\"\n default:\n return \"generic\"\n }\n}\n\n/**\n * Turn internal handshake errors into short, actionable copy for `<GristBoundary>`.\n */\nexport function formatBoundaryUserMessage(\n raw: string | null,\n snapshot: GristWidgetSnapshot\n): string {\n if (snapshot.authz.state === \"denied\") {\n return (\n snapshot.authz.message ??\n `Set Access level to at least \"${gristAccessLevelLabel(snapshot.authz.declared)}\" in the Custom widget settings.`\n )\n }\n\n if (!raw?.trim()) {\n return \"Something went wrong connecting to Grist. Try reconnecting below, or reload the page.\"\n }\n\n const text = raw.trim()\n\n if (/timed out/i.test(text)) {\n return \"Grist took too long to respond. Check your network, then try reconnecting.\"\n }\n if (/link lost/i.test(text)) {\n return \"The link to Grist was interrupted. Try reconnecting to restore live data.\"\n }\n if (/not embedded|custom widget inside/i.test(text)) {\n return text\n }\n if (/plugin API did not load/i.test(text)) {\n return \"The Grist plugin did not load in time. Reload the page, or open this URL as a custom widget inside a Grist document.\"\n }\n if (/denied requested access/i.test(text)) {\n const declared =\n snapshot.authz.state === \"pending\"\n ? snapshot.authz.declared\n : snapshot.authz.state === \"granted\"\n ? snapshot.authz.declared\n : null\n if (declared) {\n return `Set Access level to at least \"${gristAccessLevelLabel(declared)}\" in the Custom widget settings.`\n }\n }\n\n return text\n}\n\nfunction blockingTitle(\n kind: GristBoundaryBlockingKind,\n bootPhase: GristBoundaryBootPhase,\n snapshot: GristWidgetSnapshot\n): string {\n if (kind === \"error\" && snapshot.authz.state === \"denied\") {\n return \"More access needed\"\n }\n if (kind === \"unavailable\") return \"Open inside Grist\"\n if (kind === \"error\") return \"Something went wrong\"\n switch (bootPhase) {\n case \"detecting\":\n return \"Connecting to Grist\"\n case \"negotiating\":\n return \"Setting up access\"\n case \"idle\":\n return \"Starting\"\n default:\n return \"Connecting to Grist\"\n }\n}\n\nfunction blockingMessage(\n snapshot: GristWidgetSnapshot,\n status: GristWidgetStatus,\n error: string | null\n): string {\n if (status === \"unavailable\") {\n if (snapshot.lifecycle.phase === \"terminated\") {\n if (snapshot.lifecycle.reason.kind === \"not_embedded\") {\n return \"Open this page as a custom widget inside a Grist document (it runs in an embedded panel, not on its own).\"\n }\n if (snapshot.lifecycle.reason.kind === \"script_timeout\") {\n return formatBoundaryUserMessage(\n error ?? \"The Grist plugin API did not load in time.\",\n snapshot\n )\n }\n }\n return \"This page must be opened from a Grist document as a custom widget.\"\n }\n if (status === \"error\") {\n return formatBoundaryUserMessage(error, snapshot)\n }\n return deriveBoundaryBootLabel(snapshot)\n}\n\n/**\n * Classify how `<GristBoundary>` should render: full-screen blocking vs children.\n */\nexport function deriveBoundaryView(snapshot: GristWidgetSnapshot): GristBoundaryView {\n const status = deriveStatus(snapshot)\n if (status === \"ready\") {\n return { mode: \"ready\" }\n }\n const kind: GristBoundaryBlockingKind =\n status === \"unavailable\" ? \"unavailable\" : status === \"error\" ? \"error\" : \"booting\"\n const bootPhase = kind === \"booting\" ? deriveBoundaryBootPhase(snapshot) : undefined\n const error = deriveErrorMessage(snapshot)\n return {\n mode: \"blocking\",\n kind,\n bootPhase,\n title: blockingTitle(kind, bootPhase ?? \"generic\", snapshot),\n message: blockingMessage(snapshot, status, error),\n showRetry: kind === \"unavailable\" || kind === \"error\",\n }\n}\n\n/** Copy for `gate=\"canRender\"` while column mappings are not yet usable. */\nexport const GRIST_BOUNDARY_PREPARING_COPY = {\n title: \"Map your columns\",\n message:\n \"Open the widget settings in Grist (Creator Panel → Custom widget) and connect each required column to your table.\",\n} as const\n","import type { GristWidgetInteraction, GristWidgetLinkingInfo } from \"../types\"\n\n/**\n * Parse `InteractionOptions.linking` from a Grist `onOptions` settings payload.\n */\nexport function parseGristWidgetLinkingInfo(raw: unknown): GristWidgetLinkingInfo | undefined {\n if (!raw || typeof raw !== \"object\" || !(\"asTarget\" in raw)) return undefined\n const linking = raw as { asTarget: unknown; asSource?: unknown }\n return {\n asTarget: linking.asTarget == null ? null : String(linking.asTarget),\n asSource: Boolean(linking.asSource),\n }\n}\n\n/**\n * Normalize the second argument to `grist.onOptions` (Grist `InteractionOptions`).\n * Hosts use `accessLevel` (camelCase); the emulator uses `access_level`.\n */\nexport function normalizeWidgetInteraction(\n interaction: GristWidgetInteraction | null\n): GristWidgetInteraction | null {\n if (!interaction || typeof interaction !== \"object\") return interaction\n const raw = interaction as Record<string, unknown>\n const access_level =\n typeof raw.access_level === \"string\"\n ? raw.access_level\n : typeof raw.accessLevel === \"string\"\n ? raw.accessLevel\n : undefined\n const linking = parseGristWidgetLinkingInfo(raw.linking)\n return {\n ...interaction,\n ...(access_level ? { access_level } : {}),\n ...(linking ? { linking } : {}),\n }\n}\n","import type { ValidateColumnMappingsResult } from \"./grist-mappings\"\nimport type { GristWidgetSnapshot } from \"../internal/handshake\"\nimport type { GristWidgetStatus } from \"../internal/hooks/use-grist-core\"\nimport type { GristWidgetMode } from \"../internal/hooks/use-grist-selection\"\nimport type { GristWidgetInteraction } from \"../types\"\nimport { parseGristWidgetLinkingInfo } from \"./grist-widget-interaction\"\n\n/**\n * Minimal widget slice for deriving non-fatal SDK callouts. Any\n * {@link import(\"../use-grist\").UseGristResult} satisfies this.\n */\nexport type GristSdkAlertsWidgetSlice = {\n status: GristWidgetStatus\n columnMappingStatus: ValidateColumnMappingsResult\n actionError: string | null\n /**\n * Last access-insufficient error from a read method (`fetchTable`, etc.).\n * When set and matching the access-error pattern, an \"access-insufficient\"\n * alert is emitted — same as for `actionError`.\n */\n readError?: string | null\n /**\n * Logical column names that the most recent `mapBack(...)` call could not\n * reverse-map (e.g. `allowMultiple` columns where one logical name resolves\n * to several real columns).\n */\n mapBackSkipped?: readonly string[]\n /** Selection mode from `useGrist()` — used for section-not-linked detection. */\n mode?: GristWidgetMode\n /** `onOptions` settings from Grist (`InteractionOptions`). */\n widgetInteraction?: GristWidgetInteraction | null\n /**\n * Alert kinds suppressed via `UseGristOptions.suppressAlerts`.\n * Consumed automatically by `useGristSdkAlertDescriptors`.\n */\n suppressAlerts?: readonly GristSdkAlertKind[]\n /**\n * Whether the widget declared `allowSelectBy: true` — used to distinguish\n * \"section-not-linked\" (expects incoming link) from \"source-not-wired\"\n * (expects to drive other sections).\n */\n allowSelectBy?: boolean\n}\n\nexport type GristSdkAlertKind =\n | \"column-mapping\"\n | \"mapping-pending\"\n | \"mapping-unreported\"\n | \"link-stale\"\n | \"section-not-linked\"\n | \"source-not-wired\"\n | \"current-table-error\"\n | \"action-error\"\n | \"access-insufficient\"\n | \"map-back-skip\"\n\n/** Classic callout level for host styling: info / warning / error. */\nexport type GristSdkAlertSeverity = \"info\" | \"warning\" | \"error\"\n\nexport type GristSdkAlertDescriptor = {\n id: string\n kind: GristSdkAlertKind\n severity: GristSdkAlertSeverity\n title: string\n /** Suggested WAI-ARIA role for the host shell. */\n ariaRole: \"status\" | \"alert\"\n message: string\n}\n\nexport type GetGristSdkAlertDescriptorsOptions = {\n /**\n * Handshake snapshot from `useGristHandshake()` / the provider manager.\n * Enables link-stale, mapping-unreported, and current-table alerts that are\n * not visible on the widget slice alone.\n */\n snapshot?: GristWidgetSnapshot\n /** Appended to {@link formatColumnMappingAlertMessage} when a mapping alert is emitted. */\n columnMappingHint?: string\n /** Appended to the map-back-skip message. */\n mapBackHint?: string\n /** Override copy for {@link formatMappingPendingAlertMessage}. */\n mappingPendingHint?: string\n /** Appended to {@link formatSectionNotLinkedAlertMessage}. */\n sectionNotLinkedHint?: string\n /** Appended to {@link formatSourceNotWiredAlertMessage}. */\n sourceNotWiredHint?: string\n /** Appended to {@link formatAccessInsufficientMessage}. */\n accessInsufficientHint?: string\n /**\n * Alert kinds to omit from the output. Useful for widgets that intentionally\n * operate without a link source (`[\"section-not-linked\"]`) or handle certain\n * conditions in their own UI.\n */\n suppressKinds?: readonly GristSdkAlertKind[]\n}\n\n/** Default alert title for shadcn / toast shells. */\nexport function getGristSdkAlertTitle(kind: GristSdkAlertKind): string {\n switch (kind) {\n case \"column-mapping\":\n return \"Column mapping\"\n case \"mapping-pending\":\n return \"Column mapping\"\n case \"mapping-unreported\":\n return \"Column mapping\"\n case \"link-stale\":\n return \"Grist connection\"\n case \"section-not-linked\":\n return \"Widget linking\"\n case \"source-not-wired\":\n return \"Widget linking\"\n case \"current-table-error\":\n return \"Current table\"\n case \"action-error\":\n return \"Action error\"\n case \"access-insufficient\":\n return \"Access level\"\n case \"map-back-skip\":\n return \"Write skipped\"\n }\n}\n\n/** Suggested severity for host styling (destructive vs muted). */\nexport function getGristSdkAlertSeverity(kind: GristSdkAlertKind): GristSdkAlertSeverity {\n switch (kind) {\n case \"action-error\":\n case \"current-table-error\":\n case \"access-insufficient\":\n return \"error\"\n case \"column-mapping\":\n case \"mapping-unreported\":\n case \"link-stale\":\n case \"section-not-linked\":\n case \"source-not-wired\":\n case \"map-back-skip\":\n return \"warning\"\n case \"mapping-pending\":\n return \"info\"\n }\n}\n\n/**\n * Human-readable text for an incomplete column mapping (when\n * `columnMappingStatus.ok` is false).\n */\nexport function formatColumnMappingAlertMessage(\n status: ValidateColumnMappingsResult,\n hint?: string\n): string {\n const parts: string[] = [\"Column mapping is incomplete.\"]\n if (status.missing.length > 0) {\n parts.push(`Required columns: ${status.missing.join(\", \")}.`)\n }\n if (status.emptyMultiples.length > 0) {\n parts.push(\n `Assign at least one sheet column for: ${status.emptyMultiples.join(\", \")}.`\n )\n }\n if (hint?.trim()) {\n parts.push(hint.trim())\n }\n return parts.join(\" \")\n}\n\nexport function formatMappingPendingAlertMessage(hint?: string): string {\n const base = \"Waiting for Grist to report column mappings.\"\n return hint?.trim() ? `${base} ${hint.trim()}` : base\n}\n\nexport function formatMappingUnreportedAlertMessage(hint?: string): string {\n const base =\n \"Grist has not reported column mappings yet. Open the widget panel to map columns.\"\n return hint?.trim() ? `${base} ${hint.trim()}` : base\n}\n\nexport function formatLinkStaleAlertMessage(snapshot: GristWidgetSnapshot): string {\n const missed = snapshot.link.missedPings\n const suffix = missed > 0 ? ` (${missed} missed heartbeat${missed === 1 ? \"\" : \"s\"})` : \"\"\n return `Connection to Grist is stale. Edits may fail until the link recovers.${suffix}`\n}\n\n/**\n * True when Grist reports this section is not a link target (no selector drives\n * the cursor / `onRecord` stream). Requires `linking` on `widgetInteraction` so\n * older hosts do not trigger false positives.\n */\nexport function isWidgetSectionNotLinked(\n interaction: GristWidgetInteraction | null | undefined\n): boolean {\n if (!interaction || typeof interaction !== \"object\") return false\n const linking = parseGristWidgetLinkingInfo(\n interaction.linking ?? (interaction as Record<string, unknown>).linking\n )\n if (!linking) return false\n return linking.asTarget == null\n}\n\nexport function formatSectionNotLinkedAlertMessage(hint?: string): string {\n const base =\n \"This widget section is not linked to a table or selector. Link it from the page settings so the selected row is sent to the widget.\"\n return hint?.trim() ? `${base} ${hint.trim()}` : base\n}\n\nexport function formatSourceNotWiredAlertMessage(hint?: string): string {\n const base =\n \"This widget is configured as a selector (allowSelectBy) but no other section is using it as a link source yet. Link another section to read from this widget.\"\n return hint?.trim() ? `${base} ${hint.trim()}` : base\n}\n\nfunction pushDescriptor(\n out: GristSdkAlertDescriptor[],\n partial: Omit<GristSdkAlertDescriptor, \"title\" | \"severity\"> & {\n title?: string\n severity?: GristSdkAlertSeverity\n }\n): void {\n out.push({\n title: partial.title ?? getGristSdkAlertTitle(partial.kind),\n severity: partial.severity ?? getGristSdkAlertSeverity(partial.kind),\n id: partial.id,\n kind: partial.kind,\n ariaRole: partial.ariaRole,\n message: partial.message,\n })\n}\n\nfunction appendSnapshotAlerts(\n snapshot: GristWidgetSnapshot,\n options: GetGristSdkAlertDescriptorsOptions | undefined,\n out: GristSdkAlertDescriptor[]\n): void {\n const { config, link, sync } = snapshot\n\n if (config.mappings.state === \"unreported\") {\n pushDescriptor(out, {\n id: \"mapping-unreported\",\n kind: \"mapping-unreported\",\n ariaRole: \"status\",\n message: formatMappingUnreportedAlertMessage(options?.columnMappingHint),\n })\n }\n\n if (link.state === \"stale\") {\n pushDescriptor(out, {\n id: \"link-stale\",\n kind: \"link-stale\",\n ariaRole: \"status\",\n message: formatLinkStaleAlertMessage(snapshot),\n })\n }\n\n if (sync.currentTable.state === \"errored\") {\n pushDescriptor(out, {\n id: \"current-table-error\",\n kind: \"current-table-error\",\n ariaRole: \"alert\",\n message: sync.currentTable.message,\n })\n }\n}\n\n/**\n * Non-fatal SDK messages to show while `status === \"ready\"` (e.g. incomplete\n * mappings, stale link, or `actionError` when not promoted to `status === \"error\"`).\n * Host apps map each descriptor to their own UI (shadcn Alert, toast, etc.).\n *\n * Pass `options.snapshot` (from `useGristHandshake()` or the provider manager)\n * for FSM-only signals: link stale, mapping unreported, current-table errors.\n */\nexport function getGristSdkAlertDescriptors(\n widget: GristSdkAlertsWidgetSlice,\n options?: GetGristSdkAlertDescriptorsOptions\n): GristSdkAlertDescriptor[] {\n const out: GristSdkAlertDescriptor[] = []\n\n if (widget.status !== \"ready\") {\n return out\n }\n\n if (widget.columnMappingStatus.pending) {\n pushDescriptor(out, {\n id: \"mapping-pending\",\n kind: \"mapping-pending\",\n ariaRole: \"status\",\n message: formatMappingPendingAlertMessage(options?.mappingPendingHint),\n })\n } else if (!widget.columnMappingStatus.ok) {\n pushDescriptor(out, {\n id: \"column-mapping\",\n kind: \"column-mapping\",\n ariaRole: \"status\",\n message: formatColumnMappingAlertMessage(\n widget.columnMappingStatus,\n options?.columnMappingHint\n ),\n })\n }\n\n const accessErrorSource = widget.actionError ?? widget.readError\n if (accessErrorSource && isAccessInsufficientError(accessErrorSource)) {\n pushDescriptor(out, {\n id: \"access-insufficient\",\n kind: \"access-insufficient\",\n ariaRole: \"alert\",\n message: formatAccessInsufficientMessage(options?.accessInsufficientHint),\n })\n } else if (widget.actionError) {\n pushDescriptor(out, {\n id: \"action-error\",\n kind: \"action-error\",\n ariaRole: \"alert\",\n message: widget.actionError,\n })\n } else if (widget.readError) {\n pushDescriptor(out, {\n id: \"action-error\",\n kind: \"action-error\",\n ariaRole: \"alert\",\n message: widget.readError,\n })\n }\n\n const skipped = widget.mapBackSkipped ?? []\n if (skipped.length > 0) {\n pushDescriptor(out, {\n id: \"map-back-skip\",\n kind: \"map-back-skip\",\n ariaRole: \"status\",\n message: formatMapBackSkipMessage(skipped, options?.mapBackHint),\n })\n }\n\n if (widget.allowSelectBy) {\n const linking = widget.widgetInteraction\n ? parseGristWidgetLinkingInfo(\n widget.widgetInteraction.linking ??\n (widget.widgetInteraction as Record<string, unknown>).linking\n )\n : undefined\n if (linking && !linking.asSource) {\n pushDescriptor(out, {\n id: \"source-not-wired\",\n kind: \"source-not-wired\",\n ariaRole: \"status\",\n message: formatSourceNotWiredAlertMessage(options?.sourceNotWiredHint),\n })\n }\n } else if (isWidgetSectionNotLinked(widget.widgetInteraction)) {\n pushDescriptor(out, {\n id: \"section-not-linked\",\n kind: \"section-not-linked\",\n ariaRole: \"status\",\n message: formatSectionNotLinkedAlertMessage(options?.sectionNotLinkedHint),\n })\n }\n\n if (options?.snapshot) {\n appendSnapshotAlerts(options.snapshot, options, out)\n }\n\n if (options?.suppressKinds?.length) {\n return out.filter((a) => !options.suppressKinds!.includes(a.kind))\n }\n return out\n}\n\n/**\n * Human-readable text when `mapBack(...)` had to skip allow-multiple columns.\n */\nexport function formatMapBackSkipMessage(\n skipped: readonly string[],\n hint?: string\n): string {\n const list = skipped.join(\", \")\n const base = `mapBack skipped multi-mapped column${\n skipped.length === 1 ? \"\" : \"s\"\n }: ${list}.`\n return hint?.trim() ? `${base} ${hint.trim()}` : base\n}\n\nconst ACCESS_ERROR_PATTERNS = [\n /access not granted/i,\n /need higher access level/i,\n /requires.*full.*access/i,\n /RPC_ONCALL_ERROR Access/i,\n]\n\n/**\n * Heuristic: returns `true` when `actionError` looks like it was caused by\n * insufficient access rights rather than a domain / schema error.\n */\nexport function isAccessInsufficientError(message: string): boolean {\n return ACCESS_ERROR_PATTERNS.some((re) => re.test(message))\n}\n\nexport function formatAccessInsufficientMessage(hint?: string): string {\n const base =\n 'This operation requires \"Full document access\". Set the Access level to \"Full document access\" in the Custom widget configuration panel.'\n return hint?.trim() ? `${base} ${hint.trim()}` : base\n}\n","import { useMemo, useSyncExternalStore } from \"react\"\n\nimport {\n getGristSdkAlertDescriptors,\n type GetGristSdkAlertDescriptorsOptions,\n type GristSdkAlertDescriptor,\n type GristSdkAlertsWidgetSlice,\n} from \"../helpers/grist-sdk-alerts\"\nimport { initialGristSnapshot } from \"../internal/handshake\"\nimport { useGristManagerOptional } from \"../internal/handshake-manager-context\"\nimport { useGristOptional } from \"../components/grist-widget-provider\"\nimport type { UseGristResult } from \"../use-grist-types\"\n\nfunction noopSubscribe() {\n return () => {}\n}\n\n/**\n * React hook: widget slice + optional handshake snapshot for\n * {@link getGristSdkAlertDescriptors}.\n */\nexport function useGristSdkAlertDescriptors(\n widget?: GristSdkAlertsWidgetSlice | UseGristResult,\n options?: GetGristSdkAlertDescriptorsOptions\n): GristSdkAlertDescriptor[] {\n const fromContext = useGristOptional()\n const w = widget ?? fromContext\n const manager = useGristManagerOptional()\n const snapshot = useSyncExternalStore(\n manager?.subscribe ?? noopSubscribe,\n manager?.getSnapshot ?? initialGristSnapshot,\n initialGristSnapshot\n )\n\n const resolvedSnapshot = options?.snapshot ?? (manager ? snapshot : undefined)\n\n const widgetInteraction = w?.widgetInteraction\n const readError = w && \"readError\" in w ? (w as { readError?: string | null }).readError : null\n const alertInputs = w\n ? [\n w.status,\n w.mode,\n widgetInteraction,\n w.columnMappingStatus,\n w.actionError,\n readError,\n w.mapBackSkipped,\n ]\n : null\n\n const suppressFromSlice = w?.suppressAlerts\n\n return useMemo(\n () =>\n w\n ? getGristSdkAlertDescriptors(w, {\n ...options,\n suppressKinds: options?.suppressKinds ?? suppressFromSlice,\n snapshot: resolvedSnapshot,\n })\n : [],\n [alertInputs, options, resolvedSnapshot, w, suppressFromSlice]\n )\n}\n","/**\n * Internal context that hosts the shared {@link GristHandshakeManager} for a\n * widget subtree.\n *\n * - `<GristWidgetProvider>` publishes the manager via\n * {@link GristHandshakeManagerContext}.\n * - Standalone `useGrist()` / mid-level hooks without a provider acquire the\n * page-level embedded manager ({@link acquireEmbeddedHandshakeManager}).\n *\n * All SDK hooks call {@link useGristManager} — there is no pre-FSM fallback.\n */\n\nimport { createContext, useContext, useEffect, useRef } from \"react\"\n\nimport { buildManagerOptionsFromGristOptions, type BuildManagerOptionsInput } from \"./build-manager-options\"\nimport {\n acquireEmbeddedHandshakeManager,\n releaseEmbeddedHandshakeManager,\n} from \"./embedded-handshake-manager\"\nimport type { ManagerControls } from \"./handshake/manager\"\n\nexport const GristHandshakeManagerContext = createContext<ManagerControls | null>(null)\n\n/** Read the manager from context. Returns `null` outside a provider. */\nexport function useGristManagerOptional(): ManagerControls | null {\n return useContext(GristHandshakeManagerContext)\n}\n\n/**\n * Returns the active handshake manager for this React tree.\n *\n * Inside `<GristWidgetProvider>` this is the provider's manager. Otherwise a\n * single ref-counted embedded manager is shared across all standalone hook\n * instances on the page.\n */\nexport function useGristManager(options?: BuildManagerOptionsInput): ManagerControls {\n const fromProvider = useContext(GristHandshakeManagerContext)\n const optionsRef = useRef(options)\n optionsRef.current = options\n\n const embeddedRef = useRef<ManagerControls | null>(null)\n const ownsEmbeddedRef = useRef(false)\n\n if (fromProvider) {\n return fromProvider\n }\n\n if (embeddedRef.current === null) {\n embeddedRef.current = acquireEmbeddedHandshakeManager(\n buildManagerOptionsFromGristOptions(optionsRef.current)\n )\n ownsEmbeddedRef.current = true\n }\n\n useEffect(() => {\n if (!ownsEmbeddedRef.current) return\n return () => {\n releaseEmbeddedHandshakeManager()\n embeddedRef.current = null\n ownsEmbeddedRef.current = false\n }\n }, [])\n\n return embeddedRef.current\n}\n","/**\n * Single-call wrapper around `grist.ready()`.\n *\n * Grist's contract is \"call ready once\". Multiple `useGristReady` calls (or\n * `useGristWidget` from sibling components) would otherwise race. We:\n *\n * - Coalesce concurrent calls into one in-flight promise.\n * - Re-call `grist.ready` only when `requiredAccess` widens (so an action-capable\n * hook can upgrade a previously read-only handshake).\n */\n\nimport type { GristReadyOptions, GristRequiredAccess } from \"../types\"\n\nconst ACCESS_RANK: Record<GristRequiredAccess, number> = {\n none: 0,\n \"read table\": 1,\n full: 2,\n}\n\nlet inFlight: Promise<void> | null = null\nlet lastAccess: GristRequiredAccess | null = null\n\nfunction shouldReinit(next: GristRequiredAccess): boolean {\n if (!lastAccess) return true\n return ACCESS_RANK[next] > ACCESS_RANK[lastAccess]\n}\n\n/**\n * Calls `grist.ready` at most once per page (re-called only if access widens).\n * Returns the same promise for all concurrent callers.\n */\nexport function ensureGristReady(payload: GristReadyOptions): Promise<void> {\n const access = payload.requiredAccess ?? \"read table\"\n if (inFlight && !shouldReinit(access)) return inFlight\n\n lastAccess = access\n const next = Promise.resolve().then(() => {\n const result = grist.ready(payload)\n return result instanceof Promise ? result : Promise.resolve()\n })\n\n inFlight = next.catch((err) => {\n inFlight = null\n lastAccess = null\n throw err\n })\n return inFlight\n}\n\n/**\n * Forget the cached ready state. Subsequent calls to {@link ensureGristReady}\n * will re-issue `grist.ready` even at the same access level.\n *\n * Production uses: the handshake manager's `reload()` clears the singleton so\n * a soft retry triggers a fresh `grist.ready` (otherwise the cached promise\n * would short-circuit and the user-visible reload would be a no-op).\n *\n * Tests use this between test cases when swapping `window.grist`.\n */\nexport function resetGristReadySingleton(): void {\n inFlight = null\n lastAccess = null\n}\n\n/** @deprecated Use {@link resetGristReadySingleton}. Kept for test back-compat. */\nexport const resetGristReadyCacheForTests = resetGristReadySingleton\n","import type { ManagerOptions } from \"./handshake/manager\"\nimport { ensureGristReady, resetGristReadySingleton } from \"./ready-singleton\"\nimport type { GristReadyOptions } from \"../types\"\n\nexport type BuildManagerOptionsInput = GristReadyOptions & {\n availabilityMaxAttempts?: number\n availabilityIntervalMs?: number\n logWhenNotEmbedded?: boolean\n}\n\n/**\n * Map public widget options to {@link ManagerOptions} for\n * {@link createGristHandshakeManager}.\n */\nexport function buildManagerOptionsFromGristOptions(\n options?: BuildManagerOptionsInput\n): ManagerOptions {\n const opts: ManagerOptions = {\n requiredAccess: options?.requiredAccess ?? \"read table\",\n columns: options?.columns ?? [],\n allowSelectBy: options?.allowSelectBy,\n hasCustomOptions: options?.hasCustomOptions,\n onEditOptions: options?.onEditOptions,\n negotiate: {\n readyImpl: (payload) => ensureGristReady(payload),\n },\n onBeforeReload: () => resetGristReadySingleton(),\n }\n if (\n options?.availabilityMaxAttempts !== undefined ||\n options?.availabilityIntervalMs !== undefined\n ) {\n const interval = options?.availabilityIntervalMs ?? 1000\n const max = options?.availabilityMaxAttempts ?? 10\n opts.detect = {\n pollSequenceMs: Array.from({ length: max }, () => interval),\n budgetMs: interval * max,\n }\n }\n return opts\n}\n","/**\n * Detect effect — poll for `window.grist` with exponential backoff inside a\n * finite, optionally adaptive budget.\n *\n * Outputs (dispatched to the manager):\n * - DETECT_START (once, at start)\n * - DETECT_TICK (each unsuccessful poll, with attempts count)\n * - DETECT_AVAILABLE (grist global present AND embedded)\n * - NOT_EMBEDDED (grist global present but `self === top`)\n * - DETECT_TIMEOUT (budget consumed without detection)\n *\n * The effect aborts on `signal.aborted` and clears its pending timer.\n *\n * Pure of `window`: relies on the {@link GristEnvironment} adapter so the\n * effect is fully unit-testable with a virtual clock.\n */\n\nimport type { GristEnvironment, TimerHandle } from \"../environment\"\nimport type { GristAction } from \"../actions\"\n\n/**\n * Default poll sequence (ms). Caps at 5 000 ms — most production widgets see\n * `grist-plugin-api.js` load in < 1 s, but slow 3G can stretch to 20–30 s.\n */\nexport const DEFAULT_POLL_SEQUENCE_MS: readonly number[] = [\n 200, 200, 400, 400, 800, 1600, 3200, 5000, 5000, 5000, 5000, 5000, 5000, 5000,\n] as const\n\n/** Effective budget, adaptive on `navigator.connection.effectiveType`. */\nexport function defaultBudgetMs(hint: ReturnType<GristEnvironment[\"effectiveTypeHint\"]>): number {\n if (hint === \"slow-2g\" || hint === \"2g\") return 120_000\n if (hint === \"3g\") return 60_000\n return 30_000\n}\n\nexport type DetectOptions = {\n /** Custom poll sequence in ms. Index past end uses last value. */\n pollSequenceMs?: readonly number[]\n /** Total wall-clock budget across all polls. */\n budgetMs?: number\n}\n\nexport type DetectHandle = {\n cancel(): void\n}\n\n/**\n * Start the detect effect. The manager owns the cancellation handle and is\n * responsible for calling `cancel()` on `restart()` / `stop()`.\n */\nexport function startDetectEffect(\n env: GristEnvironment,\n dispatch: (action: GristAction) => void,\n signal: AbortSignal,\n options: DetectOptions = {}\n): DetectHandle {\n const sequence = options.pollSequenceMs ?? DEFAULT_POLL_SEQUENCE_MS\n const budgetMs = options.budgetMs ?? defaultBudgetMs(env.effectiveTypeHint())\n\n const startedAt = env.now()\n let attempts = 0\n let timer: TimerHandle | null = null\n let cancelled = false\n\n signal.addEventListener(\"abort\", () => {\n cancelled = true\n if (timer !== null) env.clearTimeout(timer)\n })\n\n dispatch({ type: \"DETECT_START\", atMs: startedAt })\n\n const tick = () => {\n if (cancelled) return\n timer = null\n\n const probe = env.probeGrist()\n if (probe !== null) {\n if (probe.embedded) {\n dispatch({ type: \"DETECT_AVAILABLE\", atMs: env.now() })\n } else {\n dispatch({ type: \"NOT_EMBEDDED\", atMs: env.now() })\n }\n return\n }\n\n attempts += 1\n dispatch({ type: \"DETECT_TICK\", attempts, atMs: env.now() })\n\n const elapsed = env.now() - startedAt\n if (elapsed >= budgetMs) {\n dispatch({ type: \"DETECT_TIMEOUT\", attempts, atMs: env.now() })\n return\n }\n\n const next = sequence[Math.min(attempts - 1, sequence.length - 1)] ?? 1000\n const remaining = budgetMs - elapsed\n timer = env.setTimeout(tick, Math.max(0, Math.min(next, remaining)))\n }\n\n // Probe immediately at t=0 so widgets where grist is already global don't\n // wait for the first interval.\n tick()\n\n return {\n cancel() {\n cancelled = true\n if (timer !== null) {\n env.clearTimeout(timer)\n timer = null\n }\n },\n }\n}\n","/**\n * Negotiate effect — issue `grist.ready(payload)` race-d against a timeout\n * and an external `AbortSignal`.\n *\n * Dispatches:\n * - NEGOTIATE_START\n * - NEGOTIATE_SUCCESS (grist.ready resolved AND `docApi` is present)\n * - NEGOTIATE_FAIL (reason: ready_failed | ready_timeout | manual_terminate)\n *\n * The effect never throws to the caller. Aborts before resolution silently\n * stop dispatching.\n */\n\nimport type { GristEnvironment, GristLike } from \"../environment\"\nimport type { GristAction } from \"../actions\"\nimport type { GristReadyOptions, GristRequiredAccess } from \"../../../types\"\nimport type { GristTerminationReason } from \"../types\"\n\nexport type NegotiateOptions = {\n /** Max ms to wait for `grist.ready` to resolve. */\n timeoutMs?: number\n /**\n * Custom implementation of `grist.ready(payload)`. Defaults to calling\n * `grist.ready` directly via the env. Production callers (the provider)\n * inject a wrapper that routes through `ensureGristReady()` so the\n * page-level singleton dedupes concurrent ready calls.\n */\n readyImpl?: (payload: GristReadyOptions) => Promise<void> | void\n}\n\nexport const DEFAULT_NEGOTIATE_TIMEOUT_MS = 30_000\n\nexport type NegotiateHandle = {\n cancel(): void\n}\n\nexport function startNegotiateEffect(\n env: GristEnvironment,\n dispatch: (action: GristAction) => void,\n signal: AbortSignal,\n payload: GristReadyOptions,\n options: NegotiateOptions = {}\n): NegotiateHandle {\n const timeoutMs = options.timeoutMs ?? DEFAULT_NEGOTIATE_TIMEOUT_MS\n const access: GristRequiredAccess = payload.requiredAccess ?? \"read table\"\n let settled = false\n let timer: ReturnType<GristEnvironment[\"setTimeout\"]> | null = null\n\n const settle = (next: () => void) => {\n if (settled) return\n settled = true\n if (timer !== null) env.clearTimeout(timer)\n if (signal.aborted) return\n next()\n }\n\n dispatch({ type: \"NEGOTIATE_START\", access, atMs: env.now() })\n\n const grist = env.getGrist()\n if (!grist) {\n settle(() =>\n dispatch({\n type: \"NEGOTIATE_FAIL\",\n reason: { kind: \"ready_failed\", message: \"grist global missing at negotiate\" },\n atMs: env.now(),\n })\n )\n return { cancel: () => settle(() => {}) }\n }\n\n // Schedule timeout first; ready() may resolve synchronously and trigger\n // `settle` before this fires.\n timer = env.setTimeout(() => {\n if (settled) return\n settle(() =>\n dispatch({\n type: \"NEGOTIATE_FAIL\",\n reason: { kind: \"ready_timeout\", afterMs: timeoutMs },\n atMs: env.now(),\n })\n )\n }, timeoutMs)\n\n const handleSuccess = (g: GristLike) => {\n if (!g.docApi) {\n dispatch({\n type: \"NEGOTIATE_FAIL\",\n reason: { kind: \"ready_failed\", message: \"grist.docApi missing after ready\" },\n atMs: env.now(),\n })\n return\n }\n dispatch({\n type: \"NEGOTIATE_SUCCESS\",\n access,\n grantedLevel: access, // host doesn't report effective level; widen later via authz events\n atMs: env.now(),\n })\n }\n\n const handleFailure = (err: unknown) => {\n const message = err instanceof Error ? err.message : String(err)\n const reason: GristTerminationReason = { kind: \"ready_failed\", message }\n dispatch({ type: \"NEGOTIATE_FAIL\", reason, atMs: env.now() })\n }\n\n const readyImpl = options.readyImpl ?? ((p) => grist.ready(p))\n try {\n const result = readyImpl(payload)\n if (result && typeof (result as Promise<void>).then === \"function\") {\n ;(result as Promise<void>).then(\n () => settle(() => handleSuccess(env.getGrist() ?? grist)),\n (err) => settle(() => handleFailure(err))\n )\n } else {\n settle(() => handleSuccess(env.getGrist() ?? grist))\n }\n } catch (err) {\n settle(() => handleFailure(err))\n }\n\n signal.addEventListener(\"abort\", () => settle(() => {}))\n\n return { cancel: () => settle(() => {}) }\n}\n","/**\n * Module-level subscription manager for Grist's `on*` events.\n *\n * Why this exists: `grist.onRecord`, `onRecords`, `onOptions`, and `onNewRecord`\n * are add-only — there is no `off`. Subscribing in every hook instance leaks\n * handlers for the page lifetime. This module subscribes to each Grist event\n * **at most once** and fans out to React listeners with proper teardown.\n *\n * Last-known values are cached so late subscribers immediately receive the\n * current state (analogous to a BehaviorSubject).\n *\n * Fixed-defaults contract\n * -----------------------\n * The underlying `grist.onRecord` / `onRecords` calls accept a\n * `FetchSelectedOptions` parameter (e.g. `keepEncoded`, `format`), but\n * because we bind **once** at the first subscribe, those options would be\n * \"first-hook-wins\" across the page — a subtle footgun for agents.\n *\n * This module therefore binds with Grist's **public defaults** and does not\n * accept per-subscriber options:\n * - `onRecord` → decoded rows (`keepEncoded: false`)\n * - `onRecords` → decoded rows (`format: \"rows\"`, `keepEncoded: false`)\n *\n * If you need encoded values, use the one-shot readers\n * (`useGrist().fetchSelectedTable({ keepEncoded: true })`) instead of\n * a subscription — that call-site controls its own options.\n */\n\nimport { normalizeWidgetInteraction } from \"../helpers/grist-widget-interaction\"\nimport type { GristWidgetColumnMap, GristWidgetInteraction } from \"../types\"\n\ntype Listener<T> = (value: T) => void\n\nclass GristEvent<T> {\n private listeners = new Set<Listener<T>>()\n private hasValue = false\n private last: T | undefined\n private bind: (() => void) | null = null\n\n constructor(private readonly bindOnce: (emit: (value: T) => void) => void) {}\n\n subscribe(listener: Listener<T>): () => void {\n this.listeners.add(listener)\n if (!this.bind) {\n this.bind = () => {\n // Mark as bound regardless of throw, so we don't retry every render.\n this.bind = () => {}\n try {\n this.bindOnce((value) => {\n this.hasValue = true\n this.last = value\n for (const l of this.listeners) l(value)\n })\n } catch (err) {\n if (typeof console !== \"undefined\") {\n console.error(\"[lib/grist] failed to subscribe to Grist event:\", err)\n }\n }\n }\n this.bind()\n }\n if (this.hasValue && this.last !== undefined) {\n listener(this.last)\n }\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n /** Last cached value (or `undefined` if no event has fired yet). */\n peek(): T | undefined {\n return this.last\n }\n\n /** True once at least one event has fired. */\n get ready(): boolean {\n return this.hasValue\n }\n\n /**\n * Test helper: fan out a payload without calling `grist.on*`.\n * Used to simulate hosts that reuse one record object and mutate it in place.\n */\n deliverForTests(value: T): void {\n this.hasValue = true\n this.last = value\n for (const l of this.listeners) l(value)\n }\n\n /**\n * Test helper: forget the bound state and cached value. Lets a test swap\n * `window.grist` (e.g. via the emulator's `dispose()` + `createGristEmulator()`)\n * and re-bind cleanly on the next subscribe.\n */\n _resetForTests(): void {\n this.listeners.clear()\n this.hasValue = false\n this.last = undefined\n this.bind = null\n }\n}\n\nexport type GristRecordPayload = {\n record: Record<string, unknown> | null\n mappings: GristWidgetColumnMap | null\n}\n\nexport type GristRecordsPayload = {\n records: Record<string, unknown>[]\n mappings: GristWidgetColumnMap | null\n}\n\nexport type GristOptionsPayload = {\n options: Record<string, unknown> | null\n interaction: GristWidgetInteraction | null\n}\n\nexport type GristNewRecordPayload = {\n mappings: GristWidgetColumnMap | null\n}\n\n/**\n * The singletons. These are lazy: nothing is registered with `grist` until\n * the first `subscribe()` call.\n */\ntype GristHostMessage = {\n tableId?: string\n rowId?: number | \"new\"\n dataChange?: boolean\n mappingsChange?: boolean\n}\n\nexport const recordEvent = new GristEvent<GristRecordPayload>((emit) => {\n const deliver = (record: Record<string, unknown> | null, mappings: GristWidgetColumnMap | null) => {\n emit({ record, mappings })\n }\n\n // Pin `keepEncoded: false` so mapped records contain JS-native values for\n // widget code instead of raw cell tuples.\n grist.onRecord(\n (record, mappings) => {\n deliver(record, (mappings as GristWidgetColumnMap | null) ?? null)\n },\n { keepEncoded: false }\n )\n\n // Mirror grist-plugin-api's `onRecord` message handler: Grist's RecordNotifier\n // posts `{ rowId, dataChange: false }` on cursor moves. `onRecord` should\n // handle that, but refetch here when `rowId` changes so widgets never stick on\n // the first row if the callback path is skipped or reordered.\n const fetchSelectedRecord = grist.fetchSelectedRecord ?? grist.docApi?.fetchSelectedRecord\n if (typeof grist.on !== \"function\" || typeof fetchSelectedRecord !== \"function\") {\n return\n }\n let lastRowId: number | undefined\n grist.on(\"message\", async (msg: unknown) => {\n if (!msg || typeof msg !== \"object\") return\n const host = msg as GristHostMessage\n if (!host.tableId || typeof host.rowId !== \"number\") return\n if (host.rowId === lastRowId) return\n lastRowId = host.rowId\n try {\n const record = await fetchSelectedRecord(host.rowId, { keepEncoded: false })\n deliver(record, recordEvent.peek()?.mappings ?? null)\n } catch (err) {\n if (typeof console !== \"undefined\") {\n console.error(\"[grist-widget-sdk] fetchSelectedRecord on cursor message failed:\", err)\n }\n }\n })\n})\n\nexport const recordsEvent = new GristEvent<GristRecordsPayload>((emit) => {\n // Pin `format: \"rows\"` + `keepEncoded: false` so callers always receive\n // row-shaped decoded objects. (GristView would otherwise default to\n // `format: \"columns\"` + `keepEncoded: true`.)\n grist.onRecords(\n (records, mappings) => {\n emit({ records, mappings: (mappings as GristWidgetColumnMap | null) ?? null })\n },\n { keepEncoded: false, format: \"rows\" }\n )\n})\n\nexport const optionsEvent = new GristEvent<GristOptionsPayload>((emit) => {\n grist.onOptions((options, interaction) => {\n const normalized = normalizeWidgetInteraction(\n (interaction as GristWidgetInteraction | null) ?? null\n )\n emit({\n options: options ? { ...options } : null,\n interaction: normalized,\n })\n })\n})\n\nexport const newRecordEvent = new GristEvent<GristNewRecordPayload>((emit) => {\n if (typeof grist.onNewRecord !== \"function\") return\n grist.onNewRecord((mappings) => {\n emit({ mappings: (mappings as GristWidgetColumnMap | null) ?? null })\n })\n})\n\n/**\n * Test-only: reset every event singleton. Call between tests when swapping\n * `window.grist`. Production code never imports this.\n */\nexport function resetGristEventsForTests(): void {\n recordEvent._resetForTests()\n recordsEvent._resetForTests()\n optionsEvent._resetForTests()\n newRecordEvent._resetForTests()\n}\n\n/** Vitest-only: push a record payload through {@link recordEvent} subscribers. */\nexport function deliverRecordForTests(payload: GristRecordPayload): void {\n recordEvent.deliverForTests(payload)\n}\n","/**\n * Subscriptions effect — bind Grist event streams once and feed the handshake\n * machine with generation-stamped, hash-deduplicated dispatches.\n *\n * Why a dedicated effect\n * ----------------------\n * The SDK already has a {@link \"../../subscriptions\"} module that owns the\n * one-time binding to `grist.on*` and the BehaviorSubject-style cache. We do\n * NOT re-bind here — instead, we install a single listener per stream that\n * forwards into the handshake reducer.\n *\n * Generation discipline: every dispatched action carries the CURRENT manager\n * generation read at the moment the event arrives. The reducer enforces\n * `action.generation >= snapshot.generation`, so events arriving after a\n * `reload()` / `restart()` that bumped generation are dropped automatically.\n *\n * Hash: payloads are reduced to a compact, deterministic string so duplicates\n * (e.g. emulator triple-replay of initial state) become no-ops at the reducer.\n */\n\nimport type { GristAction, GristSyncStream } from \"../actions\"\nimport { parseGristRequiredAccess } from \"../access\"\nimport type { GristGeneration } from \"../types\"\nimport {\n newRecordEvent,\n optionsEvent,\n recordEvent,\n recordsEvent,\n} from \"../../subscriptions\"\n\nexport type SubscriptionsHandle = {\n cancel(): void\n}\n\n/**\n * Pluggable binder type. The default {@link defaultSubscriptionsBinder}\n * subscribes to the SDK's singleton {@link GristEvent} instances. Tests can\n * supply a stub that never touches the real `grist` global.\n */\nexport type SubscriptionsBinder = (ctx: SubscriptionsContext) => SubscriptionsHandle\n\nexport type SubscriptionsContext = {\n dispatch: (action: GristAction) => void\n /**\n * Snapshot generation provider. Must be read lazily (inside the callback)\n * because `generation` is monotone but mutates over the lifetime of the\n * subscription.\n */\n getGeneration: () => GristGeneration\n /** Hook for the mapping effect: receive payloads in arrival order. */\n onRecordPayload?: (mappings: Record<string, unknown> | null | undefined) => void\n onRecordsPayload?: (mappings: Record<string, unknown> | null | undefined) => void\n onOptionsPayload?: (options: Record<string, unknown> | null) => void\n onNewRecordPayload?: (mappings: Record<string, unknown> | null | undefined) => void\n}\n\nexport const bindSubscriptions: SubscriptionsBinder = defaultSubscriptionsBinder\n\nexport function defaultSubscriptionsBinder(ctx: SubscriptionsContext): SubscriptionsHandle {\n const offs: Array<() => void> = []\n\n offs.push(\n recordEvent.subscribe((payload) => {\n const hash = quickHash(\"record\", payload)\n dispatchStream(ctx, \"record\", hash)\n ctx.onRecordPayload?.(payload.mappings ?? null)\n })\n )\n\n offs.push(\n recordsEvent.subscribe((payload) => {\n const hash = quickHash(\"records\", payload)\n dispatchStream(ctx, \"records\", hash)\n ctx.onRecordsPayload?.(payload.mappings ?? null)\n })\n )\n\n offs.push(\n optionsEvent.subscribe((payload) => {\n const hash = quickHash(\"options\", payload)\n dispatchStream(ctx, \"options\", hash)\n const level = parseGristRequiredAccess(payload.interaction?.access_level)\n if (level !== null) {\n ctx.dispatch({\n type: \"AUTHZ_REPORT\",\n level,\n atMs: Date.now(),\n generation: ctx.getGeneration(),\n })\n }\n ctx.onOptionsPayload?.(payload.options ?? null)\n })\n )\n\n offs.push(\n newRecordEvent.subscribe((payload) => {\n const hash = quickHash(\"newRecord\", payload)\n dispatchStream(ctx, \"newRecord\", hash)\n ctx.onNewRecordPayload?.(payload.mappings ?? null)\n })\n )\n\n return {\n cancel() {\n for (const off of offs.splice(0)) off()\n },\n }\n}\n\n/**\n * No-op binder for tests that don't care about event streams. Returned handle's\n * `cancel()` is a no-op. Use {@link defaultSubscriptionsBinder} in production.\n */\nexport const noopSubscriptionsBinder: SubscriptionsBinder = () => ({\n cancel: () => {},\n})\n\nfunction dispatchStream(\n ctx: SubscriptionsContext,\n stream: GristSyncStream,\n payloadHash: string\n): void {\n ctx.dispatch({\n type: \"STREAM_RECEIVED\",\n stream,\n payloadHash,\n atMs: Date.now(),\n generation: ctx.getGeneration(),\n })\n}\n\n/**\n * Deterministic, low-cost hash of an event payload.\n *\n * We do NOT need cryptographic strength — only equality on identical inputs\n * for idempotence. A short, stable serialization is enough.\n */\nexport function quickHash(kind: string, payload: unknown): string {\n return `${kind}::${stableSerialize(payload)}`\n}\n\nfunction stableSerialize(value: unknown): string {\n if (value === null) return \"null\"\n if (value === undefined) return \"undefined\"\n const t = typeof value\n if (t === \"number\" || t === \"string\" || t === \"boolean\") return JSON.stringify(value)\n if (Array.isArray(value)) {\n return `[${value.map(stableSerialize).join(\",\")}]`\n }\n if (t === \"object\") {\n const obj = value as Record<string, unknown>\n const keys = Object.keys(obj).sort()\n const body = keys.map((k) => `${JSON.stringify(k)}:${stableSerialize(obj[k])}`).join(\",\")\n return `{${body}}`\n }\n return String(value)\n}\n","/**\n * Mappings effect — feed column-mapping payloads into the reducer from the\n * three Grist sources (`sectionApi.mappings()`, `onRecord`, `onRecords`,\n * `onNewRecord`) and trigger the mapping timeout if nothing arrives in time.\n *\n * Inputs:\n * - `declared` — `columns` from the provider options.\n * - `getGeneration()` — current snapshot generation (for stale-drop).\n * - `getGrist()` — environment accessor to `grist.sectionApi.mappings()`.\n *\n * Outputs:\n * - `MAPPING_DECLARE` (once at start when `declared.length > 0`)\n * - `MAPPING_REPORT` (one per source payload received)\n * - `MAPPING_TIMEOUT` (if no payload after `timeoutMs`)\n *\n * The effect does NOT subscribe to grist events directly — it consumes them\n * via the {@link SubscriptionsContext} payload callbacks. This keeps the\n * single-binding contract of `subscriptions.ts` intact (one `grist.onRecord`\n * binding per page).\n */\n\nimport type { GristEnvironment } from \"../environment\"\nimport type { GristAction } from \"../actions\"\nimport type { GristColumnsToMap, GristWidgetColumnMap } from \"../../../types\"\nimport type { GristGeneration } from \"../types\"\n\nexport type MappingsOptions = {\n /**\n * Time after `MAPPING_DECLARE` before falling back to `unreported` state.\n * Default 5 000 ms.\n */\n timeoutMs?: number\n /**\n * If true, dispatch `MAPPING_INVALIDATE` whenever a payload differs from\n * the last applied mappings. Default false — graceful invalidation requires\n * a `mappingsChange: true` envelope flag the SDK doesn't currently surface,\n * so we leave it opt-in for tests.\n */\n invalidateOnDiff?: boolean\n}\n\nexport const DEFAULT_MAPPING_TIMEOUT_MS = 5_000\n\nexport type MappingsHandle = {\n /** Ingest a payload from `onRecord` / `onRecords` / `onNewRecord`. */\n ingestStreamPayload(\n source: \"stream_record\" | \"stream_records\" | \"stream_new_record\",\n payload: unknown\n ): void\n /** Force a re-fetch of `sectionApi.mappings()` (e.g. on link recovery). */\n refetchSectionApi(): Promise<void>\n /** Cancel all pending timers. */\n cancel(): void\n}\n\n/**\n * Start the mapping effect. Returns a handle the manager wires into the\n * subscriptions effect's `on*Payload` callbacks.\n *\n * The effect is a no-op when `declared.length === 0` (the reducer's\n * `MAPPING_DECLARE` action turns it into `not_declared`).\n */\nexport function startMappingsEffect(\n env: GristEnvironment,\n dispatch: (action: GristAction) => void,\n signal: AbortSignal,\n declared: GristColumnsToMap,\n getGeneration: () => GristGeneration,\n options: MappingsOptions = {}\n): MappingsHandle {\n let timeoutHandle: ReturnType<GristEnvironment[\"setTimeout\"]> | null = null\n let cancelled = false\n\n const startMs = env.now()\n dispatch({ type: \"MAPPING_DECLARE\", declared, atMs: startMs, generation: getGeneration() })\n\n // No declaration → no timeout, no section_api fetch, no further work.\n if (declared.length === 0) {\n return {\n ingestStreamPayload: () => {},\n refetchSectionApi: async () => {},\n cancel: () => {},\n }\n }\n\n // Arm the unreported timeout.\n const timeoutMs = options.timeoutMs ?? DEFAULT_MAPPING_TIMEOUT_MS\n timeoutHandle = env.setTimeout(() => {\n if (cancelled || signal.aborted) return\n dispatch({ type: \"MAPPING_TIMEOUT\", atMs: env.now(), generation: getGeneration() })\n }, timeoutMs)\n\n signal.addEventListener(\"abort\", () => {\n cancelled = true\n if (timeoutHandle !== null) env.clearTimeout(timeoutHandle)\n })\n\n const ingestPayload = (\n source: \"section_api\" | \"stream_record\" | \"stream_records\" | \"stream_new_record\",\n raw: unknown\n ) => {\n if (cancelled || signal.aborted) return\n const payload = coerceMappingsPayload(raw)\n dispatch({\n type: \"MAPPING_REPORT\",\n source,\n payload,\n atMs: env.now(),\n generation: getGeneration(),\n })\n }\n\n // Kick off `sectionApi.mappings()` once.\n const refetchSectionApi = async () => {\n if (cancelled || signal.aborted) return\n const grist = env.getGrist()\n const api = grist?.sectionApi\n if (!api || typeof api.mappings !== \"function\") return\n try {\n const payload = await api.mappings()\n ingestPayload(\"section_api\", payload)\n } catch {\n ingestPayload(\"section_api\", null)\n }\n }\n void refetchSectionApi()\n\n return {\n ingestStreamPayload: (source, payload) => ingestPayload(source, payload),\n refetchSectionApi,\n cancel() {\n cancelled = true\n if (timeoutHandle !== null) env.clearTimeout(timeoutHandle)\n },\n }\n}\n\nfunction coerceMappingsPayload(raw: unknown): GristWidgetColumnMap | null {\n if (raw === null || raw === undefined) return null\n if (typeof raw !== \"object\") return null\n return raw as GristWidgetColumnMap\n}\n","/**\n * Heartbeat effect — periodically verify the RPC channel is alive.\n *\n * Strategy\n * --------\n * 1. Schedule a ping every `intervalMs` (default 30 s).\n * 2. The ping calls a cheap RPC (default `grist.docApi.getDocName()`).\n * 3. Success → `HEARTBEAT_OK`. Failure / timeout → `HEARTBEAT_FAIL`.\n * 4. Any externally-observed RPC success (the caller invokes\n * {@link HeartbeatHandle.recordRpcSuccess}) coalesces with the heartbeat\n * and reschedules the next ping — we don't burn a request when natural\n * traffic already proves the link.\n * 5. Tab hidden? Pause via `env.onVisibilityChange`. Resume on `visible`.\n *\n * The effect is **purely an observer**: it never mutates application state\n * directly — it only dispatches actions the reducer consumes.\n */\n\nimport type { GristEnvironment, TimerHandle } from \"../environment\"\nimport type { GristAction } from \"../actions\"\n\nexport type HeartbeatOptions = {\n /** How often to issue a probe when no natural RPC traffic occurred. */\n intervalMs?: number\n /** Max time to wait for the probe before counting it as a failure. */\n pingTimeoutMs?: number\n /** If true, pause the heartbeat when the document becomes hidden. */\n pauseWhenHidden?: boolean\n /**\n * Probe used when the interval elapses. Defaults to\n * `() => env.getGrist().docApi.getDocName()`. Tests pass a controlled stub.\n */\n probe?: () => Promise<unknown>\n}\n\nexport const DEFAULT_HEARTBEAT_INTERVAL_MS = 30_000\nexport const DEFAULT_HEARTBEAT_PING_TIMEOUT_MS = 10_000\n\nexport type HeartbeatHandle = {\n /** Stop scheduling and cancel any pending probe. Idempotent. */\n cancel(): void\n /**\n * Coalesce: tell the heartbeat that an unrelated RPC just succeeded. The\n * heartbeat treats it as a free `HEARTBEAT_OK` and pushes the next probe\n * out by a full interval.\n */\n recordRpcSuccess(): void\n /**\n * Coalesce: an unrelated RPC failed. The heartbeat dispatches\n * `HEARTBEAT_FAIL` without firing its own probe, so the link signal\n * degrades immediately rather than waiting for the interval.\n */\n recordRpcFailure(): void\n /** Force a probe now (e.g. on `online` event). */\n pingNow(): void\n}\n\nexport function startHeartbeatEffect(\n env: GristEnvironment,\n dispatch: (action: GristAction) => void,\n signal: AbortSignal,\n options: HeartbeatOptions = {}\n): HeartbeatHandle {\n const intervalMs = options.intervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS\n const pingTimeoutMs = options.pingTimeoutMs ?? DEFAULT_HEARTBEAT_PING_TIMEOUT_MS\n const pauseWhenHidden = options.pauseWhenHidden ?? true\n const probe = options.probe ?? defaultProbe(env)\n\n let cancelled = false\n let paused = false\n let intervalTimer: TimerHandle | null = null\n let inFlight = false\n let inFlightTimeoutTimer: TimerHandle | null = null\n\n const clearInterval = () => {\n if (intervalTimer !== null) {\n env.clearTimeout(intervalTimer)\n intervalTimer = null\n }\n }\n const clearInFlightTimeout = () => {\n if (inFlightTimeoutTimer !== null) {\n env.clearTimeout(inFlightTimeoutTimer)\n inFlightTimeoutTimer = null\n }\n }\n\n const scheduleNext = (delay = intervalMs) => {\n clearInterval()\n if (cancelled || paused) return\n intervalTimer = env.setTimeout(ping, delay)\n }\n\n const ping = () => {\n if (cancelled || paused) return\n intervalTimer = null\n if (inFlight) {\n // A previous probe still in flight; let it resolve before scheduling.\n return\n }\n inFlight = true\n\n // Timeout guard.\n inFlightTimeoutTimer = env.setTimeout(() => {\n if (!inFlight) return\n inFlight = false\n clearInFlightTimeout()\n if (!cancelled) {\n dispatch({ type: \"HEARTBEAT_FAIL\", atMs: env.now() })\n scheduleNext()\n }\n }, pingTimeoutMs)\n\n const handleOk = () => {\n if (!inFlight) return\n inFlight = false\n clearInFlightTimeout()\n if (cancelled) return\n dispatch({ type: \"HEARTBEAT_OK\", atMs: env.now() })\n scheduleNext()\n }\n const handleFail = () => {\n if (!inFlight) return\n inFlight = false\n clearInFlightTimeout()\n if (cancelled) return\n dispatch({ type: \"HEARTBEAT_FAIL\", atMs: env.now() })\n scheduleNext()\n }\n\n // Call probe synchronously so we collapse one microtask round. If it\n // throws synchronously or returns a non-thenable, settle immediately.\n let result: unknown\n try {\n result = probe()\n } catch {\n handleFail()\n return\n }\n if (\n result &&\n typeof (result as { then?: unknown }).then === \"function\"\n ) {\n ;(result as Promise<unknown>).then(handleOk, handleFail)\n } else {\n handleOk()\n }\n }\n\n // Visibility wiring.\n const offVisibility =\n pauseWhenHidden && env.onVisibilityChange\n ? env.onVisibilityChange((visible) => {\n if (cancelled) return\n if (visible) {\n if (paused) {\n paused = false\n // Refresh immediately on resume — a hidden tab might have\n // missed a long stale window.\n ping()\n }\n } else {\n paused = true\n clearInterval()\n // Note: an in-flight probe is allowed to settle naturally; we\n // just don't schedule another one.\n }\n })\n : null\n\n // Online recovery — when the network reports it's back, ping immediately.\n const offOnline =\n env.onOnline?.(() => {\n if (cancelled || paused) return\n ping()\n }) ?? null\n\n signal.addEventListener(\"abort\", () => {\n cancelled = true\n clearInterval()\n clearInFlightTimeout()\n inFlight = false\n offVisibility?.()\n offOnline?.()\n })\n\n // Boot: first probe after `intervalMs`. We don't ping at t=0 because the\n // very transition that started the heartbeat (e.g. NEGOTIATE_SUCCESS) just\n // proved the link is alive.\n scheduleNext()\n\n return {\n cancel() {\n cancelled = true\n clearInterval()\n clearInFlightTimeout()\n inFlight = false\n offVisibility?.()\n offOnline?.()\n },\n recordRpcSuccess() {\n if (cancelled || paused) return\n dispatch({ type: \"RPC_SUCCESS\", atMs: env.now() })\n scheduleNext()\n },\n recordRpcFailure() {\n if (cancelled || paused) return\n dispatch({ type: \"RPC_FAILURE\", atMs: env.now(), kind: \"other\" })\n // Don't reschedule — a real failure should keep the interval close so\n // we re-probe quickly to confirm.\n scheduleNext(Math.min(intervalMs, 1_000))\n },\n pingNow() {\n if (cancelled) return\n ping()\n },\n }\n}\n\nfunction defaultProbe(env: GristEnvironment): () => Promise<unknown> {\n return async () => {\n const g = env.getGrist()\n if (!g) throw new Error(\"grist global missing\")\n const docApi = g.docApi\n if (!docApi || typeof docApi.getDocName !== \"function\") {\n throw new Error(\"grist.docApi.getDocName unavailable\")\n }\n return docApi.getDocName()\n }\n}\n","/**\n * Re-apply the cached `grist.onOptions` interaction after `reload()`.\n *\n * `reload()` re-runs `grist.ready` (optimistic grant) but Grist often does not\n * send a fresh `onOptions`. The subscription singleton still holds the last\n * `access_level`, which must be checked once the handshake is `online` again.\n *\n * Only runs after `reload()` — not on the initial connect — so a stale\n * pre-`ready` cache cannot deny a first successful handshake.\n */\n\nimport { isAccessSufficient, parseGristRequiredAccess } from \"./access\"\nimport type { GristAction } from \"./actions\"\nimport type { GristEnvironment } from \"./environment\"\nimport type { GristWidgetSnapshot } from \"./types\"\nimport { optionsEvent } from \"../subscriptions\"\n\nexport function denyAuthzFromCachedOptionsIfInsufficient(\n snapshot: GristWidgetSnapshot,\n dispatch: (action: GristAction) => void,\n env: GristEnvironment\n): void {\n if (snapshot.lifecycle.phase !== \"online\") return\n if (snapshot.authz.state === \"denied\") return\n\n const payload = optionsEvent.peek()\n const level = parseGristRequiredAccess(payload?.interaction?.access_level)\n if (level === null) return\n\n const declared = snapshot.authz.declared\n if (isAccessSufficient(level, declared)) return\n\n dispatch({\n type: \"AUTHZ_REPORT\",\n level,\n atMs: env.now(),\n generation: snapshot.generation,\n })\n}\n","/**\n * Environment abstraction for the handshake effects layer.\n *\n * Why an abstraction\n * ------------------\n * The detect / negotiate / heartbeat effects need access to:\n * - the `grist` global (or absence thereof),\n * - `window.self !== window.top` to detect iframe embedding,\n * - timers (`setTimeout`, `clearTimeout`),\n * - the wall clock (`performance.now()` or `Date.now()`),\n * - `navigator.connection?.effectiveType` for adaptive policy.\n *\n * Putting these behind a small interface lets us test the manager and effects\n * **without touching `window`**, using deterministic fake timers and stubbed\n * detectors / negotiators.\n *\n * Production code calls {@link createBrowserEnvironment()} which returns an\n * adapter against `globalThis`. Tests pass {@link createTestEnvironment} or a\n * hand-rolled stub.\n */\n\nimport type { GristDocApi, GristReadyOptions, GristWidgetColumnMap } from \"../../types\"\n\n// ---------------------------------------------------------------------------\n// Public env interface\n// ---------------------------------------------------------------------------\n\nexport type GristEnvironment = {\n /** Wall-clock ms (monotonic preferred but not required). */\n now(): number\n /** Schedule a callback. */\n setTimeout(cb: () => void, ms: number): TimerHandle\n /** Cancel a timer. */\n clearTimeout(handle: TimerHandle): void\n\n /**\n * Probe whether the `grist` global is present in this realm.\n * Returns `{ embedded }` when the global exists; `null` otherwise.\n */\n probeGrist(): { embedded: boolean } | null\n\n /**\n * Snapshot of the `grist` global. Effects use this once detection has\n * succeeded; callers must NOT cache the result across `restart()`.\n */\n getGrist(): GristLike | null\n\n /** Adaptive detection budget hint (ms). `null` if unknown. */\n effectiveTypeHint(): EffectiveTypeHint | null\n\n /** Add a listener for `visibilitychange` / `online` / `focus`. Returns cleanup. */\n onVisibilityChange?(listener: (visible: boolean) => void): () => void\n onOnline?(listener: () => void): () => void\n}\n\nexport type TimerHandle = ReturnType<typeof setTimeout> | number | { __opaque: true }\n\nexport type EffectiveTypeHint = \"slow-2g\" | \"2g\" | \"3g\" | \"4g\" | \"5g\"\n\n/**\n * Subset of `window.grist` actually used by handshake effects. Mirrors the\n * declared shape in `grist-global.d.ts` but only the pieces we need.\n */\nexport type GristLike = {\n ready: (options?: GristReadyOptions) => Promise<void> | void\n docApi: GristDocApi | null | undefined\n onRecord?: (\n cb: (\n record: Record<string, unknown> | null,\n mappings?: GristWidgetColumnMap | null\n ) => void,\n options?: { keepEncoded?: boolean }\n ) => void\n onRecords?: (\n cb: (\n records: Record<string, unknown>[],\n mappings?: GristWidgetColumnMap | null\n ) => void,\n options?: { keepEncoded?: boolean; format?: string }\n ) => void\n onOptions?: (\n cb: (options: Record<string, unknown> | null, interaction: unknown) => void\n ) => void\n onNewRecord?: (cb: (mappings: GristWidgetColumnMap | null) => void) => void\n sectionApi?: {\n mappings: () => Promise<GristWidgetColumnMap | null>\n }\n}\n\n// ---------------------------------------------------------------------------\n// Browser environment factory\n// ---------------------------------------------------------------------------\n\nexport function createBrowserEnvironment(): GristEnvironment {\n return {\n now: () => (typeof performance !== \"undefined\" ? performance.now() : Date.now()),\n setTimeout: (cb, ms) => globalThis.setTimeout(cb, ms),\n clearTimeout: (h) => globalThis.clearTimeout(h as ReturnType<typeof setTimeout>),\n\n probeGrist() {\n if (typeof globalThis === \"undefined\") return null\n const g = (globalThis as { grist?: unknown }).grist\n if (typeof g === \"undefined\") return null\n const embedded =\n typeof window === \"undefined\" ? false : window.self !== window.top\n return { embedded }\n },\n\n getGrist() {\n const g = (globalThis as { grist?: GristLike }).grist\n return g ?? null\n },\n\n effectiveTypeHint() {\n if (typeof navigator === \"undefined\") return null\n const conn = (navigator as { connection?: { effectiveType?: string } }).connection\n const t = conn?.effectiveType\n if (t === \"slow-2g\" || t === \"2g\" || t === \"3g\" || t === \"4g\" || t === \"5g\") return t\n return null\n },\n\n onVisibilityChange(listener) {\n if (typeof document === \"undefined\") return () => {}\n const handler = () => listener(document.visibilityState === \"visible\")\n document.addEventListener(\"visibilitychange\", handler)\n return () => document.removeEventListener(\"visibilitychange\", handler)\n },\n\n onOnline(listener) {\n if (typeof window === \"undefined\") return () => {}\n const handler = () => listener()\n window.addEventListener(\"online\", handler)\n return () => window.removeEventListener(\"online\", handler)\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Test environment factory — fake timers, stubbed grist\n// ---------------------------------------------------------------------------\n\nexport type TestEnvironmentOptions = {\n /**\n * Provider for the `grist` stub. Called every `probeGrist()` / `getGrist()`.\n * Returning `null` simulates \"script not loaded yet\".\n */\n grist?: () => GristLike | null\n embedded?: () => boolean\n effectiveType?: EffectiveTypeHint\n}\n\nexport type TestEnvironment = GristEnvironment & {\n /** Manually advance virtual time. Fires due timers in order. */\n advance(ms: number): void\n /** Currently scheduled timers. */\n pendingTimers(): readonly { dueAt: number; cb: () => void }[]\n /** Trigger visibilitychange listeners. */\n emitVisibility(visible: boolean): void\n /** Trigger online listeners. */\n emitOnline(): void\n}\n\nexport function createTestEnvironment(opts: TestEnvironmentOptions = {}): TestEnvironment {\n let clock = 0\n const timers: Array<{ id: number; dueAt: number; cb: () => void }> = []\n let nextId = 1\n const visListeners = new Set<(v: boolean) => void>()\n const onlineListeners = new Set<() => void>()\n\n function advance(ms: number) {\n const target = clock + ms\n while (true) {\n timers.sort((a, b) => a.dueAt - b.dueAt)\n const due = timers.find((t) => t.dueAt <= target)\n if (!due) break\n timers.splice(timers.indexOf(due), 1)\n clock = due.dueAt\n due.cb()\n }\n clock = target\n }\n\n return {\n now: () => clock,\n setTimeout(cb, ms) {\n const id = nextId++\n timers.push({ id, dueAt: clock + ms, cb })\n return id as unknown as TimerHandle\n },\n clearTimeout(handle) {\n const id = handle as unknown as number\n const idx = timers.findIndex((t) => t.id === id)\n if (idx >= 0) timers.splice(idx, 1)\n },\n\n probeGrist() {\n const g = opts.grist?.() ?? null\n if (!g) return null\n const embedded = opts.embedded?.() ?? true\n return { embedded }\n },\n getGrist: () => opts.grist?.() ?? null,\n effectiveTypeHint: () => opts.effectiveType ?? null,\n\n onVisibilityChange(listener) {\n visListeners.add(listener)\n return () => visListeners.delete(listener)\n },\n onOnline(listener) {\n onlineListeners.add(listener)\n return () => onlineListeners.delete(listener)\n },\n\n advance,\n pendingTimers: () => timers.map((t) => ({ dueAt: t.dueAt, cb: t.cb })),\n emitVisibility(visible) {\n for (const l of visListeners) l(visible)\n },\n emitOnline() {\n for (const l of onlineListeners) l()\n },\n }\n}\n","/**\n * GristHandshakeManager — single owner of the handshake snapshot.\n *\n * Responsibilities\n * ----------------\n * 1. Hold the snapshot and the {@link GristReducerContext}.\n * 2. Run effects (detect → negotiate → subscriptions + mappings) in order.\n * 3. Bump generation on `reload()` / `restart()` and propagate cancellation\n * through a per-generation {@link AbortController}.\n * 4. Notify subscribers on each snapshot change (interface compatible with\n * React's `useSyncExternalStore`).\n *\n * The manager is a **class**, not a hook. React hooks subscribe to it via the\n * standard `subscribe` / `getSnapshot` pair so unit tests can drive the\n * manager directly with a virtual clock — no React needed.\n */\n\nimport {\n DEFAULT_REDUCER_CONFIG,\n createReducerContext,\n gristReducer,\n initialGristSnapshot,\n nextGeneration,\n type GristAction,\n type GristReducerContext,\n type GristWidgetSnapshot,\n type ReducerConfig,\n} from \"./index\"\nimport { startDetectEffect, type DetectHandle, type DetectOptions } from \"./effects/detect\"\nimport {\n startNegotiateEffect,\n type NegotiateHandle,\n type NegotiateOptions,\n} from \"./effects/negotiate\"\nimport {\n defaultSubscriptionsBinder,\n type SubscriptionsBinder,\n type SubscriptionsHandle,\n} from \"./effects/subscriptions\"\nimport {\n startMappingsEffect,\n type MappingsHandle,\n type MappingsOptions,\n} from \"./effects/mappings\"\nimport {\n startHeartbeatEffect,\n type HeartbeatHandle,\n type HeartbeatOptions,\n} from \"./effects/heartbeat\"\nimport { denyAuthzFromCachedOptionsIfInsufficient } from \"./authz-from-options-cache\"\nimport {\n createBrowserEnvironment,\n type GristEnvironment,\n} from \"./environment\"\nimport type { GristColumnsToMap, GristReadyOptions } from \"../../types\"\n\nexport type ManagerOptions = GristReadyOptions & {\n detect?: DetectOptions\n negotiate?: NegotiateOptions\n mappings?: MappingsOptions\n heartbeat?: HeartbeatOptions | false\n reducerConfig?: Partial<ReducerConfig>\n /**\n * Where to read `grist`, timers, and platform hints from. Defaults to a\n * browser adapter. Tests pass {@link createTestEnvironment}.\n */\n env?: GristEnvironment\n /**\n * Binder for grist event streams. Defaults to\n * {@link defaultSubscriptionsBinder} which wires the SDK's singleton\n * {@link \"../../subscriptions\"} module. Tests can pass `noopSubscriptionsBinder`\n * to avoid touching the real `grist` global.\n */\n subscriptionsBinder?: SubscriptionsBinder\n /**\n * Called when the manager catches an unexpected internal error.\n * Telemetry hook — does not affect reducer state.\n */\n onError?: (err: unknown, where: string) => void\n /**\n * Called from inside {@link ManagerControls.reload} BEFORE generation bump.\n * Production callers route `resetGristReadySingleton()` through here so\n * the page-level ready singleton is cleared and the next negotiate effect\n * issues a fresh `grist.ready` instead of re-using the cached promise.\n */\n onBeforeReload?: () => void\n}\n\nexport type ManagerControls = {\n /** Start the effects pipeline. Idempotent after `start()`. */\n start(): void\n /** Cancel all running effects and reset to `idle`. */\n stop(): void\n /**\n * Soft retry: bumps generation, cancels current effects, re-runs detect/\n * negotiate. Subscriptions are NOT re-bound — the underlying singletons\n * survive (and re-deliver cached values).\n */\n reload(): void\n /**\n * Hard reload of the host iframe. Browser-only — in the test env this is a\n * no-op. Production code may also call `window.location.reload()` directly.\n */\n restart(): void\n subscribe(listener: () => void): () => void\n getSnapshot(): GristWidgetSnapshot\n /**\n * Test/internal: inject an action directly. Used by integration tests that\n * want to simulate authz events, link failures, etc.\n */\n dispatch(action: GristAction): void\n /**\n * Coalesce: an external RPC succeeded — tell the heartbeat to skip the\n * next scheduled probe and reset the missed-pings counter. Returns\n * silently when the heartbeat is disabled.\n */\n recordRpcSuccess(): void\n /**\n * Coalesce: an external RPC failed — degrade the link signal immediately.\n * Returns silently when the heartbeat is disabled.\n */\n recordRpcFailure(): void\n}\n\nexport function createGristHandshakeManager(options: ManagerOptions = {}): ManagerControls {\n const env = options.env ?? createBrowserEnvironment()\n const reducerConfig: ReducerConfig = {\n ...DEFAULT_REDUCER_CONFIG,\n ...(options.reducerConfig ?? {}),\n }\n\n let snapshot = initialGristSnapshot()\n const ctx: GristReducerContext = createReducerContext()\n const listeners = new Set<() => void>()\n\n let started = false\n let abort: AbortController | null = null\n let detectHandle: DetectHandle | null = null\n let negotiateHandle: NegotiateHandle | null = null\n let subscriptionsHandle: SubscriptionsHandle | null = null\n let mappingsHandle: MappingsHandle | null = null\n let heartbeatHandle: HeartbeatHandle | null = null\n /** Set by `reload()`; cleared after one post-online cache check. */\n let recheckAuthzFromCacheAfterOnline = false\n\n const declared: GristColumnsToMap = options.columns ?? []\n const subscriptionsBinder = options.subscriptionsBinder ?? defaultSubscriptionsBinder\n\n const notify = () => {\n for (const l of listeners) {\n try {\n l()\n } catch (err) {\n options.onError?.(err, \"listener\")\n }\n }\n }\n\n const dispatch = (action: GristAction) => {\n const prev = snapshot\n const next = gristReducer(prev, action, ctx, reducerConfig)\n if (next !== prev) {\n snapshot = next\n // Run side-effects that depend on phase transitions BEFORE notifying.\n onTransition(prev, next)\n notify()\n }\n }\n\n /**\n * Effect-runner glue: react to lifecycle transitions inside the manager\n * (without polluting the pure reducer).\n *\n * Rationale: the reducer cannot start a `grist.ready()` because that's\n * impure. The reducer instead emits the transition (DETECT_AVAILABLE →\n * `lifecycle.phase === \"negotiating\"`) and the manager observes the\n * transition here to launch the next effect.\n */\n const onTransition = (prev: GristWidgetSnapshot, next: GristWidgetSnapshot) => {\n if (prev.lifecycle.phase !== \"negotiating\" && next.lifecycle.phase === \"negotiating\") {\n launchNegotiate()\n // Bind `grist.onRecord` before `grist.ready` resolves so the host's\n // post-ready cursor/data push is not dropped (iframe transport).\n launchSubscriptions()\n }\n if (prev.lifecycle.phase !== \"online\" && next.lifecycle.phase === \"online\") {\n launchMappings()\n launchHeartbeat()\n if (recheckAuthzFromCacheAfterOnline) {\n recheckAuthzFromCacheAfterOnline = false\n denyAuthzFromCachedOptionsIfInsufficient(next, dispatch, env)\n }\n }\n if (prev.lifecycle.phase === \"online\" && next.lifecycle.phase !== \"online\") {\n // Leaving the online phase — stop probing immediately.\n heartbeatHandle?.cancel()\n heartbeatHandle = null\n }\n }\n\n const launchDetect = () => {\n if (!abort) return\n detectHandle?.cancel()\n detectHandle = startDetectEffect(env, dispatch, abort.signal, options.detect)\n }\n\n const launchNegotiate = () => {\n if (!abort) return\n negotiateHandle?.cancel()\n negotiateHandle = startNegotiateEffect(\n env,\n dispatch,\n abort.signal,\n buildReadyPayload(options),\n options.negotiate\n )\n }\n\n const launchSubscriptions = () => {\n if (!abort) return\n if (subscriptionsHandle) return\n subscriptionsHandle = subscriptionsBinder({\n dispatch,\n getGeneration: () => snapshot.generation,\n onRecordPayload: (m) =>\n mappingsHandle?.ingestStreamPayload(\"stream_record\", m),\n onRecordsPayload: (m) =>\n mappingsHandle?.ingestStreamPayload(\"stream_records\", m),\n onNewRecordPayload: (m) =>\n mappingsHandle?.ingestStreamPayload(\"stream_new_record\", m),\n })\n }\n\n const launchMappings = () => {\n if (!abort) return\n launchSubscriptions()\n if (mappingsHandle) return\n mappingsHandle = startMappingsEffect(\n env,\n dispatch,\n abort.signal,\n declared,\n () => snapshot.generation,\n options.mappings\n )\n }\n\n const launchHeartbeat = () => {\n if (!abort) return\n if (options.heartbeat === false) return\n if (heartbeatHandle) return\n heartbeatHandle = startHeartbeatEffect(\n env,\n dispatch,\n abort.signal,\n options.heartbeat ?? {}\n )\n }\n\n const cancelAllEffects = () => {\n detectHandle?.cancel()\n detectHandle = null\n negotiateHandle?.cancel()\n negotiateHandle = null\n mappingsHandle?.cancel()\n mappingsHandle = null\n heartbeatHandle?.cancel()\n heartbeatHandle = null\n if (abort && !abort.signal.aborted) abort.abort()\n }\n\n const controls: ManagerControls = {\n start() {\n if (started) return\n started = true\n abort = new AbortController()\n launchDetect()\n },\n stop() {\n if (!started) return\n started = false\n cancelAllEffects()\n subscriptionsHandle?.cancel()\n subscriptionsHandle = null\n // Reset snapshot to `idle` so a subsequent `start()` is clean.\n snapshot = initialGristSnapshot()\n notify()\n },\n reload() {\n if (!started) {\n controls.start()\n return\n }\n recheckAuthzFromCacheAfterOnline = true\n try {\n options.onBeforeReload?.()\n } catch (err) {\n options.onError?.(err, \"onBeforeReload\")\n }\n cancelAllEffects()\n // Bump generation so any lingering microtasks / RPC resolutions get dropped.\n dispatch({ type: \"BUMP_GENERATION\", atMs: env.now(), reason: \"reload\" })\n // Reset snapshot to `idle` for the lifecycle restart.\n snapshot = {\n ...initialGristSnapshot(),\n generation: nextGeneration(snapshot.generation),\n }\n ctx.resolver = null\n abort = new AbortController()\n launchDetect()\n notify()\n },\n restart() {\n controls.reload()\n // Hard reload only makes sense in a real browser realm.\n if (typeof window !== \"undefined\" && typeof window.location?.reload === \"function\") {\n try {\n window.location.reload()\n } catch (err) {\n options.onError?.(err, \"restart\")\n }\n }\n },\n subscribe(listener) {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n getSnapshot: () => snapshot,\n dispatch,\n recordRpcSuccess() {\n heartbeatHandle?.recordRpcSuccess()\n },\n recordRpcFailure() {\n heartbeatHandle?.recordRpcFailure()\n },\n }\n\n return controls\n}\n\nfunction buildReadyPayload(options: ManagerOptions): GristReadyOptions {\n const payload: GristReadyOptions = {\n requiredAccess: options.requiredAccess ?? \"read table\",\n columns: options.columns ?? [],\n }\n if (options.allowSelectBy !== undefined) payload.allowSelectBy = options.allowSelectBy\n if (options.hasCustomOptions !== undefined) payload.hasCustomOptions = options.hasCustomOptions\n if (options.onEditOptions) payload.onEditOptions = options.onEditOptions\n return payload\n}\n","/**\n * Page-level embedded handshake manager for widgets that call `useGrist()` /\n * `useGristCore()` without mounting `<GristWidgetProvider>`.\n *\n * A single manager is shared across all hook instances on the page (ref-counted)\n * so mid-level hooks (`useGristActions`, `useGristRowsFromTable`, …) do not\n * spawn competing `grist.ready` handshakes.\n */\n\nimport {\n createGristHandshakeManager,\n type ManagerControls,\n type ManagerOptions,\n} from \"./handshake/manager\"\n\ntype EmbeddedSlot = {\n manager: ManagerControls\n refCount: number\n}\n\nlet embedded: EmbeddedSlot | null = null\n\nexport function acquireEmbeddedHandshakeManager(options: ManagerOptions): ManagerControls {\n if (!embedded) {\n embedded = {\n manager: createGristHandshakeManager(options),\n refCount: 0,\n }\n embedded.manager.start()\n }\n embedded.refCount += 1\n return embedded.manager\n}\n\nexport function releaseEmbeddedHandshakeManager(): void {\n if (!embedded) return\n embedded.refCount -= 1\n if (embedded.refCount <= 0) {\n embedded.manager.stop()\n embedded = null\n }\n}\n\n/** Test isolation — tear down the page-level embedded manager between cases. */\nexport function resetEmbeddedHandshakeManagerForTests(): void {\n if (embedded) {\n embedded.manager.stop()\n embedded = null\n }\n}\n","import {\n useContext,\n useEffect,\n useRef,\n type ReactNode,\n} from \"react\"\n\nimport { GristHandshakeManagerContext } from \"../internal/handshake-manager-context\"\nimport { buildManagerOptionsFromGristOptions } from \"../internal/build-manager-options\"\nimport { useGristFromProvider } from \"../internal/contexts\"\nimport { GristContext, GristWidgetContextTree } from \"../internal/grist-widget-context-tree\"\nimport {\n createGristHandshakeManager,\n type ManagerControls,\n} from \"../internal/handshake/manager\"\nimport type { UseGristOptions, UseGristResult } from \"../use-grist-types\"\n\nexport type GristWidgetProviderProps = {\n options?: UseGristOptions\n children: ReactNode\n}\n\n/**\n * Sets up Grist once at the app root. Prefer slice hooks (`useGristSelection`,\n * `useGristWrites`, …) in large widgets; use `useGristContext()` when you need everything.\n *\n * Owns a {@link GristHandshakeManager} and mounts the slice / full-result context\n * tree underneath it so `useRpcHeartbeatCoalesce()` in slice hooks sees the manager\n * (ordering required — see `tests/sdk/handshake-rpc-coalesce.test.tsx`).\n */\nexport function GristWidgetProvider({ options, children }: GristWidgetProviderProps) {\n // Allocate the handshake manager exactly once per provider instance. The\n // options snapshot is taken on the first mount — subsequent option changes\n // are intentionally ignored to keep the FSM lifecycle stable (matches the\n // prior behaviour: only re-runs `grist.ready` when requiredAccess widens via\n // the singleton).\n const managerRef = useRef<ManagerControls | null>(null)\n if (managerRef.current === null) {\n managerRef.current = createGristHandshakeManager(buildManagerOptionsFromGristOptions(options))\n }\n const manager = managerRef.current\n\n useEffect(() => {\n manager.start()\n return () => {\n manager.stop()\n }\n }, [manager])\n\n return (\n <GristHandshakeManagerContext.Provider value={manager}>\n <GristWidgetContextTree options={options}>{children}</GristWidgetContextTree>\n </GristHandshakeManagerContext.Provider>\n )\n}\n\n/**\n * Access the full `UseGristResult` from inside a `<GristWidgetProvider>`.\n *\n * The returned object updates whenever any Grist state changes (record selection,\n * widget options, etc.). Individual methods on the result (e.g. `w.fetchTable`,\n * `w.listTables`) are referentially stable and safe to use in `useEffect` deps.\n * See `UseGristResult` JSDoc for details.\n */\nexport function useGristContext<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>(): UseGristResult<\n TRow,\n TMapped\n> {\n const ctx = useContext(GristContext)\n if (!ctx) {\n throw new Error(\"useGristContext() must be used inside <GristWidgetProvider>\")\n }\n return useGristFromProvider<TRow, TMapped>()\n}\n\nexport function useGristOptional<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>():\n | UseGristResult<TRow, TMapped>\n | null {\n return useContext(GristContext) as UseGristResult<TRow, TMapped> | null\n}\n","import { createContext, useContext, useMemo, type Context } from \"react\"\n\nimport type { ComposedGristWidgetSlices } from \"./compose-grist-widget\"\nimport { mergeGristResultFromSlices } from \"./merge-grist-result\"\nimport type { UseGristResult } from \"../use-grist-types\"\nimport type { UseGristAttachmentsRestResult } from \"./hooks/use-grist-attachments-rest\"\nimport type { UseGristCoreResult } from \"./hooks/use-grist-core\"\nimport type { UseGristCurrentTableResult } from \"./hooks/use-grist-current-table\"\nimport type { UseGristLinkingResult } from \"./hooks/use-grist-linking\"\nimport type { UseGristReadsResult } from \"./hooks/use-grist-reads\"\nimport type { UseGristSectionApiResult } from \"./hooks/use-grist-section-api\"\nimport type { UseGristSelectionResult } from \"./hooks/use-grist-selection\"\nimport type { UseGristTableOpsBoundResult } from \"./hooks/use-grist-table-ops-bound\"\nimport type { UseGristThemeResult } from \"./hooks/use-grist-theme\"\nimport type { UseGristWidgetOptionsApiResult } from \"./hooks/use-grist-widget-options-api\"\n\nexport type GristCoreContextValue = UseGristCoreResult & {\n tableError: string | null\n}\n\nexport type GristStatusSliceValue = GristCoreContextValue & UseGristCurrentTableResult\n\nexport const GristCoreContext = createContext<GristCoreContextValue | null>(null)\nexport const GristSelectionContext = createContext<UseGristSelectionResult | null>(null)\nexport const GristCurrentTableContext = createContext<UseGristCurrentTableResult | null>(null)\nexport const GristWritesContext = createContext<UseGristTableOpsBoundResult | null>(null)\nexport const GristReadsContext = createContext<UseGristReadsResult | null>(null)\nexport const GristWidgetOptionsApiContext = createContext<UseGristWidgetOptionsApiResult | null>(null)\nexport const GristLinkingContext = createContext<UseGristLinkingResult | null>(null)\nexport const GristAttachmentsRestContext = createContext<UseGristAttachmentsRestResult | null>(null)\nexport const GristThemeContext = createContext<UseGristThemeResult | null>(null)\nexport const GristSectionApiContext = createContext<UseGristSectionApiResult | null>(null)\n\nfunction useRequiredContext<T>(ctx: Context<T | null>, name: string): T {\n const value = useContext(ctx)\n if (!value) {\n throw new Error(`${name} must be used inside <GristWidgetProvider>`)\n }\n return value\n}\n\nexport function useGristCoreContext(): GristCoreContextValue {\n return useRequiredContext(GristCoreContext, \"useGristCoreContext()\")\n}\n\nexport function useGristSelectionContext<\n TRow = Record<string, unknown>,\n TMapped = Record<string, unknown>,\n>(): UseGristSelectionResult<TRow, TMapped> {\n return useRequiredContext(GristSelectionContext, \"useGristSelectionContext()\") as UseGristSelectionResult<\n TRow,\n TMapped\n >\n}\n\nexport function useGristCurrentTableContext(): UseGristCurrentTableResult {\n return useRequiredContext(GristCurrentTableContext, \"useGristCurrentTableContext()\")\n}\n\nexport function useGristWritesContext(): UseGristTableOpsBoundResult {\n return useRequiredContext(GristWritesContext, \"useGristWritesContext()\")\n}\n\nexport function useGristReadsContext(): UseGristReadsResult {\n return useRequiredContext(GristReadsContext, \"useGristReadsContext()\")\n}\n\nexport function useGristWidgetOptionsApiContext(): UseGristWidgetOptionsApiResult {\n return useRequiredContext(GristWidgetOptionsApiContext, \"useGristWidgetOptionsApiContext()\")\n}\n\nexport function useGristLinkingContext(): UseGristLinkingResult {\n return useRequiredContext(GristLinkingContext, \"useGristLinkingContext()\")\n}\n\nexport function useGristAttachmentsRestContext(): UseGristAttachmentsRestResult {\n return useRequiredContext(GristAttachmentsRestContext, \"useGristAttachmentsRestContext()\")\n}\n\nexport function useGristThemeContext(): UseGristThemeResult {\n return useRequiredContext(GristThemeContext, \"useGristThemeContext()\")\n}\n\nexport function useGristSectionApiContext(): UseGristSectionApiResult {\n return useRequiredContext(GristSectionApiContext, \"useGristSectionApiContext()\")\n}\n\n/**\n * Live merge of all provider slices — used by `useGrist()` / `useGristContext()` so\n * cursor-driven `onRecord` updates are not lost behind a stale memoized snapshot.\n */\nexport function useGristFromProvider<\n TRow = Record<string, unknown>,\n TMapped = Record<string, unknown>,\n>(): UseGristResult<TRow, TMapped> {\n const core = useGristCoreContext()\n const selection = useGristSelectionContext<TRow, TMapped>()\n const currentTable = useGristCurrentTableContext()\n const writes = useGristWritesContext()\n const reads = useGristReadsContext()\n const widgetOptionsApi = useGristWidgetOptionsApiContext()\n const linking = useGristLinkingContext()\n const attachmentsRest = useGristAttachmentsRestContext()\n const theme = useGristThemeContext()\n const sectionApi = useGristSectionApiContext()\n\n return useMemo(\n () =>\n mergeGristResultFromSlices<TRow, TMapped>({\n core,\n selection,\n currentTable,\n writes,\n reads,\n widgetOptionsApi,\n linking,\n attachmentsRest,\n theme,\n sectionApi,\n } as ComposedGristWidgetSlices),\n [\n core,\n selection,\n currentTable,\n writes,\n reads,\n widgetOptionsApi,\n linking,\n attachmentsRest,\n theme,\n sectionApi,\n ]\n )\n}\n","import type { ComposedGristWidgetSlices } from \"./compose-grist-widget\"\nimport type { UseGristResult } from \"../use-grist-types\"\n\nexport function mergeGristResultFromSlices<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>(\n slices: ComposedGristWidgetSlices\n): UseGristResult<TRow, TMapped> {\n const { core, selection, currentTable, writes, reads, widgetOptionsApi, linking, attachmentsRest, theme, sectionApi, suppressAlerts, allowSelectBy } =\n slices\n return {\n status: core.status,\n isAvailable: core.isAvailable,\n isReady: core.isReady,\n error: core.error,\n capabilities: core.capabilities,\n record: selection.record as UseGristResult<TRow, TMapped>[\"record\"],\n records: selection.records as UseGristResult<TRow, TMapped>[\"records\"],\n mappedRecord: selection.mappedRecord as TMapped | null,\n mappings: selection.mappings,\n recordsMappings: selection.recordsMappings,\n columnMappingStatus: selection.columnMappingStatus,\n mode: selection.mode,\n resolveMappedColumnId: selection.resolveMappedColumnId,\n mapBack: selection.mapBack as (patch: Partial<TMapped>) => Record<string, unknown>,\n mapBackSkipped: selection.mapBackSkipped,\n isNewRecord: selection.isNewRecord,\n newRecordMappings: selection.newRecordMappings,\n currentTableId: currentTable.currentTableId,\n currentTableLoading: currentTable.currentTableLoading,\n refreshCurrentTable: currentTable.refreshCurrentTable,\n table: writes.table,\n getTable: writes.getTable,\n actionStatus: writes.actionStatus,\n actionError: writes.actionError,\n applyActions: writes.applyActions,\n reload: core.reload,\n fetchTable: reads.fetchTable,\n fetchTableRows: reads.fetchTableRows,\n fetchRow: reads.fetchRow,\n listTables: reads.listTables,\n listColumns: reads.listColumns,\n getDocName: reads.getDocName,\n buildReplicaDocumentFromDocApi: reads.buildReplicaDocumentFromDocApi,\n getAttachmentUrl: attachmentsRest.getAttachmentUrl,\n fetchAttachmentBase64: attachmentsRest.fetchAttachmentBase64,\n fetchAttachmentBlob: attachmentsRest.fetchAttachmentBlob,\n widgetOptions: selection.widgetOptions,\n widgetInteraction: selection.widgetInteraction,\n getWidgetOptions: widgetOptionsApi.getWidgetOptions,\n getWidgetOption: widgetOptionsApi.getWidgetOption,\n setWidgetOption: widgetOptionsApi.setWidgetOption,\n setWidgetOptions: widgetOptionsApi.setWidgetOptions,\n patchWidgetOptions: widgetOptionsApi.patchWidgetOptions,\n clearWidgetOptions: widgetOptionsApi.clearWidgetOptions,\n fetchSelectedTable: reads.fetchSelectedTable,\n fetchSelectedRecord: reads.fetchSelectedRecord,\n readError: reads.readError ?? attachmentsRest.readError,\n setCursorPosition: linking.setCursorPosition,\n setLinkedRowSelection: linking.setLinkedRowSelection,\n getAccessToken: attachmentsRest.getAccessToken,\n fetchWithAuth: attachmentsRest.fetchWithAuth,\n uploadAttachment: attachmentsRest.uploadAttachment,\n theme: theme.theme,\n configure: sectionApi.configure,\n refreshMappings: sectionApi.refreshMappings,\n suppressAlerts,\n allowSelectBy,\n }\n}\n","import { createContext, useMemo, type ReactNode } from \"react\"\n\nimport {\n GristAttachmentsRestContext,\n GristCoreContext,\n GristCurrentTableContext,\n GristLinkingContext,\n GristReadsContext,\n GristSectionApiContext,\n GristSelectionContext,\n GristThemeContext,\n GristWidgetOptionsApiContext,\n GristWritesContext,\n} from \"./contexts\"\nimport { useComposeGristWidgetSlices } from \"./compose-grist-widget\"\nimport { mergeGristResultFromSlices } from \"./merge-grist-result\"\nimport type { UseGristOptions, UseGristResult } from \"../use-grist-types\"\n\n/** Full {@link UseGristResult} for `useGristContext()` / in-tree `useGrist()`. */\nexport const GristContext = createContext<UseGristResult | null>(null)\n\nexport type GristWidgetContextTreeProps = {\n options?: UseGristOptions\n children: ReactNode\n}\n\n/**\n * Mounts per-slice React contexts for granular hooks (`useGristSelection`,\n * `useGristWrites`, …) and {@link GristContext} with the full\n * {@link UseGristResult} for `useGristContext()` / in-tree `useGrist()`.\n *\n * Must render as a child of {@link GristHandshakeManagerContext} so slice\n * hooks' `useRpcHeartbeatCoalesce()` sees the manager (see\n * `tests/sdk/handshake-rpc-coalesce.test.tsx`).\n */\nexport function GristWidgetContextTree({ options, children }: GristWidgetContextTreeProps) {\n const slices = useComposeGristWidgetSlices(options)\n const fullResult = useMemo(\n () => mergeGristResultFromSlices(slices),\n [\n slices.core,\n slices.selection,\n slices.currentTable,\n slices.writes,\n slices.reads,\n slices.widgetOptionsApi,\n slices.linking,\n slices.attachmentsRest,\n slices.theme,\n slices.sectionApi,\n ]\n )\n\n return (\n <GristCoreContext.Provider value={slices.core}>\n <GristSelectionContext.Provider value={slices.selection}>\n <GristCurrentTableContext.Provider value={slices.currentTable}>\n <GristWritesContext.Provider value={slices.writes}>\n <GristReadsContext.Provider value={slices.reads}>\n <GristWidgetOptionsApiContext.Provider value={slices.widgetOptionsApi}>\n <GristLinkingContext.Provider value={slices.linking}>\n <GristAttachmentsRestContext.Provider value={slices.attachmentsRest}>\n <GristThemeContext.Provider value={slices.theme}>\n <GristSectionApiContext.Provider value={slices.sectionApi}>\n <GristContext.Provider value={fullResult}>{children}</GristContext.Provider>\n </GristSectionApiContext.Provider>\n </GristThemeContext.Provider>\n </GristAttachmentsRestContext.Provider>\n </GristLinkingContext.Provider>\n </GristWidgetOptionsApiContext.Provider>\n </GristReadsContext.Provider>\n </GristWritesContext.Provider>\n </GristCurrentTableContext.Provider>\n </GristSelectionContext.Provider>\n </GristCoreContext.Provider>\n )\n}\n","import { useMemo } from \"react\"\n\nimport { useGristCore, type UseGristCoreOptions } from \"./hooks/use-grist-core\"\nimport { useGristCurrentTable } from \"./hooks/use-grist-current-table\"\nimport {\n useGristSelectionSubscription,\n type UseGristSelectionOptions,\n} from \"./hooks/use-grist-selection\"\nimport { useGristTableOpsBound } from \"./hooks/use-grist-table-ops-bound\"\nimport { useGristReads } from \"./hooks/use-grist-reads\"\nimport { useGristWidgetOptionsApi } from \"./hooks/use-grist-widget-options-api\"\nimport { useGristLinking } from \"./hooks/use-grist-linking\"\nimport { useGristAttachmentsRest } from \"./hooks/use-grist-attachments-rest\"\nimport { useGristTheme } from \"./hooks/use-grist-theme\"\nimport { useGristSectionApi } from \"./hooks/use-grist-section-api\"\nimport type { GristCoreContextValue } from \"./contexts\"\nimport type { UseGristAttachmentsRestResult } from \"./hooks/use-grist-attachments-rest\"\nimport type { UseGristCurrentTableResult } from \"./hooks/use-grist-current-table\"\nimport type { UseGristLinkingResult } from \"./hooks/use-grist-linking\"\nimport type { UseGristReadsResult } from \"./hooks/use-grist-reads\"\nimport type { UseGristSectionApiResult } from \"./hooks/use-grist-section-api\"\nimport type { UseGristSelectionResult } from \"./hooks/use-grist-selection\"\nimport type { UseGristTableOpsBoundResult } from \"./hooks/use-grist-table-ops-bound\"\nimport type { UseGristThemeResult } from \"./hooks/use-grist-theme\"\nimport type { UseGristWidgetOptionsApiResult } from \"./hooks/use-grist-widget-options-api\"\nimport type { GristSdkAlertKind } from \"../helpers/grist-sdk-alerts\"\n\nexport type ComposeGristWidgetOptions = UseGristCoreOptions & UseGristSelectionOptions & {\n /**\n * Alert kinds that should never be emitted for this widget.\n * E.g. `[\"section-not-linked\"]` for widgets that don't need a link source.\n */\n suppressAlerts?: GristSdkAlertKind[]\n}\n\nexport type ComposedGristWidgetSlices = {\n core: GristCoreContextValue\n selection: UseGristSelectionResult\n currentTable: UseGristCurrentTableResult\n writes: UseGristTableOpsBoundResult\n reads: UseGristReadsResult\n widgetOptionsApi: UseGristWidgetOptionsApiResult\n linking: UseGristLinkingResult\n attachmentsRest: UseGristAttachmentsRestResult\n theme: UseGristThemeResult\n sectionApi: UseGristSectionApiResult\n suppressAlerts?: readonly GristSdkAlertKind[]\n allowSelectBy?: boolean\n}\n\nexport function useComposeGristWidgetSlices(\n options?: ComposeGristWidgetOptions\n): ComposedGristWidgetSlices {\n const core = useGristCore(options)\n const currentTable = useGristCurrentTable(core.docApi)\n const selection = useGristSelectionSubscription(core.docApi, options)\n const writes = useGristTableOpsBound(core.docApi)\n const reads = useGristReads(core.docApi)\n const widgetOptionsApi = useGristWidgetOptionsApi()\n const linking = useGristLinking()\n const attachmentsRest = useGristAttachmentsRest(core.docApi)\n const theme = useGristTheme(core.docApi)\n const sectionApi = useGristSectionApi()\n\n const coreSlice: GristCoreContextValue = useMemo(\n () => ({\n ...core,\n tableError: currentTable.tableError,\n }),\n [core, currentTable.tableError]\n )\n\n const suppressAlerts = options?.suppressAlerts\n const allowSelectBy = options?.allowSelectBy\n\n return useMemo(\n () => ({\n core: coreSlice,\n selection,\n currentTable,\n writes,\n reads,\n widgetOptionsApi,\n linking,\n attachmentsRest,\n theme,\n sectionApi,\n suppressAlerts,\n allowSelectBy,\n }),\n [\n coreSlice,\n selection,\n currentTable,\n writes,\n reads,\n widgetOptionsApi,\n linking,\n attachmentsRest,\n theme,\n sectionApi,\n suppressAlerts,\n allowSelectBy,\n ]\n )\n}\n","import { useCallback, useMemo, useSyncExternalStore } from \"react\"\n\nimport type { GristDocApi, GristReadyOptions } from \"../../types\"\nimport {\n deriveCapabilities,\n deriveErrorMessage,\n deriveStatus,\n initialGristSnapshot,\n type GristCapabilities,\n type GristWidgetSnapshot,\n type GristWidgetStatus as HandshakeStatus,\n} from \"../handshake\"\nimport type { ManagerControls } from \"../handshake/manager\"\nimport { useGristManager } from \"../handshake-manager-context\"\n\n/** Canonical 4-state status — projected from the handshake snapshot. */\nexport type GristWidgetStatus = HandshakeStatus\n\nexport type UseGristCoreOptions = GristReadyOptions & {\n availabilityMaxAttempts?: number\n availabilityIntervalMs?: number\n logWhenNotEmbedded?: boolean\n}\n\nexport type UseGristCoreResult = {\n status: GristWidgetStatus\n isAvailable: boolean | null\n isReady: boolean\n error: string | null\n docApi: GristDocApi | null\n /** Derived from the handshake snapshot — same values as `useGristCapabilities()` on `/advanced`. */\n capabilities: GristCapabilities\n reload: () => Promise<void>\n}\n\n/** Project handshake availability for legacy `isAvailable` consumers. */\nexport function computeAvailabilityFromSnapshot(\n snapshot: GristWidgetSnapshot\n): boolean | null {\n const { phase } = snapshot.lifecycle\n if (phase === \"idle\" || phase === \"detecting\") return null\n if (phase === \"terminated\") {\n const reason = snapshot.lifecycle.reason.kind\n if (reason === \"not_embedded\" || reason === \"script_timeout\") return false\n return true\n }\n return true\n}\n\n/**\n * Core connectivity hook — always backed by {@link GristHandshakeManager}.\n */\nexport function useGristCore(options?: UseGristCoreOptions): UseGristCoreResult {\n const manager = useGristManager(options)\n return useGristCoreFromManager(manager)\n}\n\n/**\n * Subscribe to an existing manager and project its snapshot into\n * {@link UseGristCoreResult}.\n */\nexport function useGristCoreFromManager(manager: ManagerControls): UseGristCoreResult {\n const snapshot = useSyncExternalStore(\n manager.subscribe,\n manager.getSnapshot,\n initialGristSnapshot\n )\n const status = deriveStatus(snapshot)\n const error = deriveErrorMessage(snapshot)\n const docApi = useMemo<GristDocApi | null>(() => {\n if (snapshot.lifecycle.phase !== \"online\") return null\n if (typeof grist === \"undefined\") return null\n return grist.docApi ?? null\n }, [snapshot.lifecycle.phase, snapshot.generation])\n const isAvailable = computeAvailabilityFromSnapshot(snapshot)\n const reload = useCallback(async () => {\n manager.reload()\n }, [manager])\n const capabilities = useMemo(() => deriveCapabilities(snapshot), [snapshot])\n return useMemo(\n () => ({\n status,\n isAvailable,\n isReady: status === \"ready\",\n error,\n docApi,\n capabilities,\n reload,\n }),\n [status, isAvailable, error, docApi, capabilities, reload]\n )\n}\n","import { useCallback, useEffect, useMemo, useSyncExternalStore } from \"react\"\n\nimport { recordEvent } from \"../subscriptions\"\nimport type { GristDocApi } from \"../../types\"\nimport { initialGristSnapshot } from \"../handshake\"\nimport { useGristManager } from \"../handshake-manager-context\"\nimport { useRpcHeartbeatCoalesce } from \"./use-rpc-heartbeat-coalesce\"\n\nexport type UseGristCurrentTableResult = {\n currentTableId: string | null\n currentTableLoading: boolean\n refreshCurrentTable: () => Promise<void>\n tableError: string | null\n}\n\nexport function useGristCurrentTable(docApi: GristDocApi | null): UseGristCurrentTableResult {\n const manager = useGristManager()\n const coalesceRpc = useRpcHeartbeatCoalesce()\n const snapshot = useSyncExternalStore(\n manager.subscribe,\n manager.getSnapshot,\n initialGristSnapshot\n )\n\n const currentTable = snapshot.sync.currentTable\n const currentTableId =\n currentTable.state === \"known\" ? currentTable.tableId : null\n const currentTableLoading =\n currentTable.state === \"known\" ? currentTable.refreshing : false\n const tableError =\n currentTable.state === \"errored\" ? currentTable.message : null\n\n const refreshCurrentTable = useCallback(async () => {\n if (!docApi) return\n if (typeof grist === \"undefined\") return\n const atMs = Date.now()\n manager.dispatch({ type: \"CURRENT_TABLE_REFRESH_START\", atMs })\n try {\n const next = await coalesceRpc(() =>\n Promise.resolve(grist.selectedTable?.getTableId())\n )\n if (next) {\n manager.dispatch({ type: \"CURRENT_TABLE_KNOWN\", tableId: next, atMs: Date.now() })\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n manager.dispatch({ type: \"CURRENT_TABLE_ERROR\", message, atMs: Date.now() })\n }\n }, [docApi, coalesceRpc, manager])\n\n useEffect(() => {\n if (docApi) void refreshCurrentTable()\n }, [docApi, refreshCurrentTable])\n\n useEffect(() => {\n return recordEvent.subscribe(() => {\n if (!docApi) return\n void refreshCurrentTable()\n })\n }, [docApi, refreshCurrentTable])\n\n return useMemo(\n () => ({\n currentTableId,\n currentTableLoading,\n refreshCurrentTable,\n tableError,\n }),\n [currentTableId, currentTableLoading, refreshCurrentTable, tableError]\n )\n}\n","/**\n * `useRpcHeartbeatCoalesce()` — coalesce real RPC traffic with the handshake\n * heartbeat.\n *\n * When a {@link GristHandshakeManager} is mounted (via `<GristWidgetProvider>`\n * or `<GristHandshakeProvider>`), every successful Grist RPC call is treated\n * as a natural heartbeat: the manager's `recordRpcSuccess()` resets the\n * missed-ping counter and pushes the next probe out by a full interval, so\n * a chatty widget never burns dedicated heartbeat probes.\n *\n * Failures are NOT coalesced: semantic errors (validation, \"row not found\",\n * \"no such column\") would briefly flash a connection-degraded indicator even\n * though the channel is alive. Instead we let the regular heartbeat probe\n * detect real transport failures on its own schedule (~30 s). The user\n * already sees the action error immediately, so the heartbeat indicator\n * doesn't need to race.\n *\n * Outside a provider (no manager in context), the wrapper is a zero-cost\n * passthrough — every slice hook keeps working exactly like the pre-FSM\n * release.\n */\n\nimport { useCallback } from \"react\"\n\nimport { useGristManagerOptional } from \"../handshake-manager-context\"\n\nexport type RpcHeartbeatCoalesce = <T>(fn: () => Promise<T>) => Promise<T>\n\nexport function useRpcHeartbeatCoalesce(): RpcHeartbeatCoalesce {\n const manager = useGristManagerOptional()\n return useCallback<RpcHeartbeatCoalesce>(\n async (fn) => {\n try {\n const result = await fn()\n manager?.recordRpcSuccess()\n return result\n } catch (err) {\n throw err\n }\n },\n [manager]\n )\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\n\nimport {\n newRecordEvent,\n optionsEvent,\n recordEvent,\n recordsEvent,\n type GristRecordPayload,\n} from \"../subscriptions\"\nimport {\n deriveColumnMappingStatus,\n extractResolvedMappings,\n type GristMappingState,\n} from \"../handshake\"\nimport { useGristManager } from \"../handshake-manager-context\"\nimport type {\n GristColumnsToMap,\n GristDocApi,\n GristWidgetColumnMap,\n GristWidgetInteraction,\n GristRowRecord,\n} from \"../../types\"\nimport type { ValidateColumnMappingsResult } from \"../../helpers/grist-mappings\"\n\nconst EMPTY_MAPPINGS: GristWidgetColumnMap = Object.freeze({})\n\nfunction stableColumnMappingStatus(\n prev: ValidateColumnMappingsResult | undefined,\n mappingState: GristMappingState,\n columns?: GristColumnsToMap\n): ValidateColumnMappingsResult {\n const next = deriveColumnMappingStatus(mappingState, columns)\n if (\n prev &&\n prev.ok === next.ok &&\n prev.pending === next.pending &&\n prev.missing.length === next.missing.length &&\n prev.emptyMultiples.length === next.emptyMultiples.length &&\n prev.missing.every((m, i) => m === next.missing[i]) &&\n prev.emptyMultiples.every((m, i) => m === next.emptyMultiples[i])\n ) {\n return prev\n }\n return next\n}\n\nexport type GristWidgetMode = \"empty\" | \"row\" | \"new-row\"\n\nexport type UseGristSelectionOptions = {\n columns?: GristColumnsToMap\n subscribeToWidgetOptions?: boolean\n subscribeToNewRecord?: boolean\n}\n\nexport type UseGristSelectionResult<TRow = Record<string, unknown>, TMapped = Record<string, unknown>> = {\n record: GristRowRecord<TRow> | null\n records: GristRowRecord<TRow>[] | null\n mappedRecord: TMapped | null\n mappings: GristWidgetColumnMap\n recordsMappings: GristWidgetColumnMap | null\n columnMappingStatus: ValidateColumnMappingsResult\n mode: GristWidgetMode\n resolveMappedColumnId: (logicalFieldName: string) => string\n mapBack: (patch: Partial<TMapped>) => Record<string, unknown>\n mapBackSkipped: readonly string[]\n isNewRecord: boolean\n newRecordMappings: GristWidgetColumnMap | null\n widgetOptions: Record<string, unknown> | null\n widgetInteraction: GristWidgetInteraction | null\n}\n\n/**\n * Shallow copy so React state updates when the host reuses one record object\n * and mutates fields in place (Grist's `onRecord` can do this).\n */\nfunction copyRowRecord<T>(record: Record<string, unknown> | null): GristRowRecord<T> | null {\n if (!record) return null\n return { ...record } as GristRowRecord<T>\n}\n\nfunction copyRowRecords<T>(records: Record<string, unknown>[] | null): GristRowRecord<T>[] | null {\n if (!records) return null\n return records.map((row) => ({ ...row })) as GristRowRecord<T>[]\n}\n\nfunction copyMappedRecord<T>(mapped: unknown): T | null {\n if (mapped === null || mapped === undefined) return null\n if (typeof mapped !== \"object\") return mapped as T\n return { ...(mapped as Record<string, unknown>) } as T\n}\n\nfunction mappingStateKey(state: GristMappingState): string {\n return JSON.stringify(state)\n}\n\n/** Re-render only when the FSM mapping axis changes — not on link/heartbeat updates. */\nfunction useMappingProjection() {\n const manager = useGristManager()\n const [mappingState, setMappingState] = useState(\n () => manager.getSnapshot().config.mappings\n )\n useEffect(() => {\n let lastKey = mappingStateKey(manager.getSnapshot().config.mappings)\n return manager.subscribe(() => {\n const next = manager.getSnapshot().config.mappings\n const nextKey = mappingStateKey(next)\n if (nextKey !== lastKey) {\n lastKey = nextKey\n setMappingState(next)\n }\n })\n }, [manager])\n return mappingState\n}\n\nexport function useGristSelectionSubscription<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>(\n docApi: GristDocApi | null,\n options?: UseGristSelectionOptions\n): UseGristSelectionResult<TRow, TMapped> {\n const subscribeToWidgetOptions = options?.subscribeToWidgetOptions ?? true\n const subscribeToNewRecord = options?.subscribeToNewRecord ?? true\n const mappingState = useMappingProjection()\n\n const [record, setRecord] = useState<GristRowRecord<TRow> | null>(null)\n const [records, setRecords] = useState<GristRowRecord<TRow>[] | null>(null)\n const [mappedRecord, setMappedRecord] = useState<TMapped | null>(null)\n const [streamMappings, setStreamMappings] = useState<GristWidgetColumnMap | null>(null)\n const [recordsMappings, setRecordsMappings] = useState<GristWidgetColumnMap | null>(null)\n const [widgetOptions, setWidgetOptionsMirror] = useState<Record<string, unknown> | null>(null)\n const [widgetInteraction, setWidgetInteraction] = useState<GristWidgetInteraction | null>(null)\n const [isNewRecord, setIsNewRecord] = useState(false)\n const [newRecordMappings, setNewRecordMappings] = useState<GristWidgetColumnMap | null>(null)\n const [mapBackSkipped, setMapBackSkipped] = useState<readonly string[]>([])\n const mapBackSkippedRef = useRef<readonly string[]>([])\n\n const fsmMappings = extractResolvedMappings(mappingState)\n const mappings = useMemo(\n () => fsmMappings ?? streamMappings ?? EMPTY_MAPPINGS,\n [fsmMappings, streamMappings]\n )\n\n const columnMappingStatusRef = useRef<ValidateColumnMappingsResult | undefined>(undefined)\n const columnMappingStatus = useMemo(() => {\n const next = stableColumnMappingStatus(\n columnMappingStatusRef.current,\n mappingState,\n options?.columns\n )\n columnMappingStatusRef.current = next\n return next\n }, [mappingState, options?.columns])\n\n const applyRecordPayload = useCallback(\n ({ record: next, mappings: nextMappings }: GristRecordPayload) => {\n setStreamMappings(nextMappings)\n setRecord(copyRowRecord<TRow>(next))\n if (!next) {\n setMappedRecord(null)\n return\n }\n setIsNewRecord(false)\n if (typeof grist !== \"undefined\" && typeof grist.mapColumnNames === \"function\") {\n setMappedRecord(copyMappedRecord<TMapped>(grist.mapColumnNames(next)))\n } else {\n setMappedRecord(copyMappedRecord<TMapped>(next))\n }\n },\n []\n )\n\n // Bind `grist.on*` as soon as the widget mounts — not when `docApi` appears.\n // `docApi` is only available after `grist.ready` resolves (`lifecycle.phase ===\n // \"online\"`), but the host may push the initial cursor/record payload during\n // ready. Late binding missed that first `onRecord` in production iframe runs.\n useEffect(() => {\n if (typeof grist === \"undefined\") return\n return recordEvent.subscribe(applyRecordPayload)\n }, [applyRecordPayload])\n\n useEffect(() => {\n if (typeof grist === \"undefined\") return\n return recordsEvent.subscribe(({ records: next, mappings: nextMappings }) => {\n setRecords(copyRowRecords<TRow>(next))\n setRecordsMappings(nextMappings)\n })\n }, [])\n\n useEffect(() => {\n if (!subscribeToWidgetOptions || typeof grist === \"undefined\") return\n return optionsEvent.subscribe(({ options: next, interaction }) => {\n setWidgetOptionsMirror(next)\n setWidgetInteraction(interaction)\n })\n }, [subscribeToWidgetOptions])\n\n useEffect(() => {\n if (!subscribeToNewRecord || typeof grist === \"undefined\") return\n if (typeof grist.onNewRecord !== \"function\") return\n return newRecordEvent.subscribe(({ mappings: nextMappings }) => {\n setIsNewRecord(true)\n setNewRecordMappings(nextMappings)\n })\n }, [subscribeToNewRecord])\n\n const prevDocApiRef = useRef<GristDocApi | null>(null)\n\n // Re-apply cached `onRecord` when `docApi` becomes ready. Do not clear stream\n // state on the initial mount while `docApi` is still null — that ran after\n // `recordEvent.subscribe()` replay and wiped the first selected row.\n useEffect(() => {\n const hadDocApi = prevDocApiRef.current !== null\n prevDocApiRef.current = docApi\n\n if (docApi) {\n if (!hadDocApi && recordEvent.ready) {\n const cached = recordEvent.peek()\n if (cached !== undefined) applyRecordPayload(cached)\n }\n return\n }\n\n if (!hadDocApi) return\n\n setRecord(null)\n setRecords(null)\n setMappedRecord(null)\n setStreamMappings(null)\n setRecordsMappings(null)\n setIsNewRecord(false)\n setNewRecordMappings(null)\n setWidgetOptionsMirror(null)\n setWidgetInteraction(null)\n }, [docApi, applyRecordPayload])\n\n const resolveMappedColumnId = useCallback(\n (logicalFieldName: string): string => {\n const value = mappings[logicalFieldName]\n if (typeof value === \"string\") return value\n if (Array.isArray(value) && typeof value[0] === \"string\") return value[0]\n return logicalFieldName\n },\n [mappings]\n )\n\n const mapBack = useCallback(\n (patch: Partial<TMapped>): Record<string, unknown> => {\n const skipped: string[] = []\n for (const name of Object.keys(patch as Record<string, unknown>)) {\n if (Array.isArray(mappings[name])) skipped.push(name)\n }\n\n const computeResult = (): Record<string, unknown> => {\n if (typeof grist.mapColumnNamesBack === \"function\") {\n const out = grist.mapColumnNamesBack(patch as Record<string, unknown>)\n // grist-plugin-api.js's `mapColumnNamesBack` builds transformation\n // functions for ALL mapped columns and applies every one of them,\n // even when the corresponding logical key is absent from `patch`.\n // Absent keys produce `undefined` values which JSON-serialise to\n // `null` over RPC, causing Grist to erase those cells.\n // Strip all `undefined` entries — callers that intentionally clear\n // a field should pass `null`.\n for (const key of Object.keys(out)) {\n if (out[key] === undefined) {\n delete out[key]\n }\n }\n return out\n }\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)) continue\n out[target ?? name] = value\n }\n return out\n }\n\n const result = computeResult()\n\n const previous = mapBackSkippedRef.current\n const same =\n previous.length === skipped.length &&\n previous.every((name, i) => name === skipped[i])\n if (!same) {\n mapBackSkippedRef.current = skipped\n setMapBackSkipped(skipped)\n }\n\n return result\n },\n [mappings]\n )\n\n const mode: GristWidgetMode = isNewRecord ? \"new-row\" : record ? \"row\" : \"empty\"\n\n return useMemo(\n () => ({\n record,\n records,\n mappedRecord,\n mappings,\n recordsMappings,\n columnMappingStatus,\n mode,\n resolveMappedColumnId,\n mapBack,\n mapBackSkipped,\n isNewRecord,\n newRecordMappings,\n widgetOptions,\n widgetInteraction,\n }),\n [\n record,\n records,\n mappedRecord,\n mappings,\n recordsMappings,\n columnMappingStatus,\n mode,\n resolveMappedColumnId,\n mapBack,\n mapBackSkipped,\n isNewRecord,\n newRecordMappings,\n widgetOptions,\n widgetInteraction,\n ]\n )\n}\n","import { useCallback, useMemo, useRef, useState } from \"react\"\n\nimport type { GristUserActionTuple } from \"../../helpers/grist-user-actions\"\nimport type {\n GristApplyUserActionsOptions,\n GristDocApi,\n GristMinimalRecord,\n GristTableNewRecord,\n GristTableOpOptions,\n GristTableOperations,\n GristTableUpdateRecord,\n GristTableUpsertOptions,\n GristTableUpsertRecord,\n} from \"../../types\"\nimport { useRpcHeartbeatCoalesce } from \"./use-rpc-heartbeat-coalesce\"\n\nexport type GristWidgetActionStatus = \"idle\" | \"running\" | \"error\"\n\nexport type UseGristTableOpsBoundResult = {\n table: GristTableOperations\n getTable: (tableId: string) => GristTableOperations\n actionStatus: GristWidgetActionStatus\n actionError: string | null\n applyActions: (\n actions: GristUserActionTuple[],\n applyOptions?: GristApplyUserActionsOptions\n ) => Promise<unknown>\n}\n\nfunction resolveSelectedTableOps(): GristTableOperations {\n if (grist.selectedTable) return grist.selectedTable\n throw new Error(\"grist.selectedTable is not available in this Grist version\")\n}\n\nfunction resolveTableOps(tableId: string): GristTableOperations {\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\nexport function useGristTableOpsBound(docApi: GristDocApi | null): UseGristTableOpsBoundResult {\n const [actionStatus, setActionStatus] = useState<GristWidgetActionStatus>(\"idle\")\n const [actionError, setActionError] = useState<string | null>(null)\n const tableCacheRef = useRef(new Map<string, GristTableOperations>())\n const coalesceRpc = useRpcHeartbeatCoalesce()\n\n const trackOp = useCallback(\n async <T>(fn: () => Promise<T>): Promise<T> => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n setActionStatus(\"running\")\n setActionError(null)\n try {\n const out = await coalesceRpc(fn)\n setActionStatus(\"idle\")\n return out\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n setActionError(message)\n setActionStatus(\"error\")\n throw err\n }\n },\n [docApi, coalesceRpc]\n )\n\n const wrapTableOps = useCallback(\n (resolve: () => GristTableOperations): GristTableOperations => ({\n getTableId: () => trackOp(() => resolve().getTableId()),\n create: (\n records: GristTableNewRecord | GristTableNewRecord[],\n opOptions?: GristTableOpOptions\n ): Promise<GristMinimalRecord | GristMinimalRecord[]> =>\n trackOp(() => resolve().create(records, opOptions)),\n update: (\n records: GristTableUpdateRecord | GristTableUpdateRecord[],\n opOptions?: GristTableOpOptions\n ) => trackOp(() => resolve().update(records, opOptions)),\n upsert: (\n records: GristTableUpsertRecord | GristTableUpsertRecord[],\n opOptions?: GristTableUpsertOptions\n ) => trackOp(() => resolve().upsert(records, opOptions)),\n destroy: (recordIds: number | number[]) =>\n trackOp(() => resolve().destroy(recordIds)),\n }),\n [trackOp]\n )\n\n const table = useMemo(() => wrapTableOps(() => resolveSelectedTableOps()), [wrapTableOps])\n\n const getTable = useCallback(\n (tableId: string) => {\n const cached = tableCacheRef.current.get(tableId)\n if (cached) return cached\n const wrapped = wrapTableOps(() => resolveTableOps(tableId))\n tableCacheRef.current.set(tableId, wrapped)\n return wrapped\n },\n [wrapTableOps]\n )\n\n const applyActions = useCallback(\n async (actions: GristUserActionTuple[], applyOptions?: GristApplyUserActionsOptions): Promise<unknown> => {\n if (!docApi) throw new Error(\"Grist docApi is not ready\")\n setActionStatus(\"running\")\n setActionError(null)\n try {\n const out = await coalesceRpc(() => docApi.applyUserActions(actions, applyOptions))\n setActionStatus(\"idle\")\n return out\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n setActionError(message)\n setActionStatus(\"error\")\n throw err\n }\n },\n [docApi, coalesceRpc]\n )\n\n return useMemo(\n () => ({ table, getTable, actionStatus, actionError, applyActions }),\n [table, getTable, actionStatus, actionError, applyActions]\n )\n}\n","import { useCallback, useMemo, useRef, useState } from \"react\"\n\nimport {\n buildReplicaDocumentFromDocApi as buildReplicaDocumentFromDocApiImpl,\n type BuildReplicaDocumentFromDocApiOptions,\n loadColumnMetadataByTable,\n} from \"../../helpers/build-replica-document\"\nimport { isGristNoiseColumn, type GristNoiseColumnsOptions } from \"../../helpers/grist-columns-filters\"\nimport {\n fetchGristTableRows,\n fetchGristRow,\n type FetchGristTableRowsOptions,\n type GristColumnarTable,\n} from \"../../helpers/grist-table-data\"\nimport type { GristSafeParseCellResult, SafeParseGristTableDataOptions } from \"../../helpers/grist-safe-parse\"\nimport type {\n GristDocApi,\n GristFetchSelectedOptions,\n GristReplicaDocument,\n GristRowRecord,\n} from \"../../types\"\nimport { isAccessInsufficientError } from \"../../helpers/grist-sdk-alerts\"\nimport { useGristManagerOptional } from \"../handshake-manager-context\"\nimport { useRpcHeartbeatCoalesce } from \"./use-rpc-heartbeat-coalesce\"\n\nconst SELECTED_FETCH_DEFAULTS: GristFetchSelectedOptions = {\n keepEncoded: false,\n format: \"rows\",\n}\n\nexport type ListTablesOptions = {\n /** When true, include system tables (prefixed with `_grist` or `GristHidden_`). Default: false. */\n includeSystem?: boolean\n}\n\nexport type GristColumnInfo = {\n colId: string\n type?: string\n label?: string\n isFormula?: boolean\n formula?: string\n description?: string\n}\n\nexport type ListColumnsOptions = GristNoiseColumnsOptions & {\n /** When true, include system tables' columns. Default: false. */\n includeSystem?: boolean\n}\n\nexport type UseGristReadsResult = {\n fetchTable: (tableId: string) => Promise<GristColumnarTable>\n fetchTableRows: {\n <T extends Record<string, unknown> = Record<string, unknown>>(\n tableId: string,\n options: FetchGristTableRowsOptions & {\n safeParse: true | Omit<SafeParseGristTableDataOptions, \"columns\" | \"order\">\n }\n ): Promise<GristRowRecord<{ [K in keyof T]: GristSafeParseCellResult<T[K]> | null }>[]>\n <T extends Record<string, unknown> = Record<string, unknown>>(\n tableId: string,\n options?: FetchGristTableRowsOptions\n ): Promise<GristRowRecord<T>[]>\n }\n fetchRow: <T = Record<string, unknown>>(tableId: string, rowId: number) => Promise<GristRowRecord<T> | null>\n listTables: (options?: ListTablesOptions) => Promise<string[]>\n listColumns: (tableId: string, options?: ListColumnsOptions) => Promise<GristColumnInfo[]>\n getDocName: () => Promise<string>\n buildReplicaDocumentFromDocApi: (\n options?: BuildReplicaDocumentFromDocApiOptions\n ) => Promise<GristReplicaDocument>\n fetchSelectedTable: (fetchOptions?: GristFetchSelectedOptions) => Promise<GristColumnarTable>\n fetchSelectedRecord: (rowId: number, fetchOptions?: GristFetchSelectedOptions) => Promise<Record<string, unknown>>\n readError: string | null\n}\n\nexport function useGristReads(docApi: GristDocApi | null): UseGristReadsResult {\n const coalesceRpc = useRpcHeartbeatCoalesce()\n const manager = useGristManagerOptional()\n const [readError, setReadError] = useState<string | null>(null)\n const readErrorRef = useRef<string | null>(null)\n\n /**\n * Pre-flight check: reject immediately when the **confirmed** effective\n * access level is insufficient for full-document reads.\n *\n * Important: the effective level is only known after `onOptions` arrives\n * (`sync.options.state === \"hot\"` → `AUTHZ_REPORT` has been dispatched).\n * Before that the snapshot carries the *declared* level from `grist.ready`,\n * which is often lower than what the user actually set in Grist's panel.\n * Guarding too early would block widgets whose declared level is\n * `\"read table\"` even when the user granted `\"full\"`.\n */\n const requireFullAccess = useCallback(\n (label: string) => {\n const snap = manager?.getSnapshot()\n if (!snap) return\n const { authz, sync } = snap\n if (sync.options.state !== \"hot\") return\n if (authz.state === \"granted\" && authz.level !== \"full\") {\n const msg =\n `${label} requires \"Full document access\". ` +\n `Current access level is \"${authz.level}\". ` +\n 'Set Access level to \"Full document access\" in the Custom widget configuration panel.'\n if (readErrorRef.current !== msg) {\n readErrorRef.current = msg\n setReadError(msg)\n }\n throw new Error(msg)\n }\n },\n [manager]\n )\n\n /** Wrap an RPC call and capture access-insufficient errors as `readError`. */\n const guardedRpc = useCallback(\n async <T>(fn: () => Promise<T>): Promise<T> => {\n try {\n const result = await coalesceRpc(fn)\n if (readErrorRef.current !== null) {\n readErrorRef.current = null\n setReadError(null)\n }\n return result\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n if (isAccessInsufficientError(msg)) {\n if (readErrorRef.current !== msg) {\n readErrorRef.current = msg\n setReadError(msg)\n }\n }\n throw err\n }\n },\n [coalesceRpc]\n )\n\n const fetchTable = useCallback(\n async (tableId: string) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n requireFullAccess(\"fetchTable\")\n return guardedRpc(() => docApi.fetchTable(tableId) as Promise<GristColumnarTable>)\n },\n [docApi, requireFullAccess, guardedRpc]\n )\n\n const fetchRow = useCallback(\n async <T = Record<string, unknown>>(tableId: string, rowId: number) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n requireFullAccess(\"fetchRow\")\n return guardedRpc(() => fetchGristRow<T>(docApi, tableId, rowId))\n },\n [docApi, requireFullAccess, guardedRpc]\n )\n\n const fetchTableRows = useCallback(\n async <T extends Record<string, unknown> = Record<string, unknown>>(\n tableId: string,\n options?: FetchGristTableRowsOptions\n ) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n requireFullAccess(\"fetchTableRows\")\n if (options?.safeParse) {\n return guardedRpc(() =>\n fetchGristTableRows<T>(\n docApi,\n tableId,\n options as FetchGristTableRowsOptions & {\n safeParse: true | Omit<SafeParseGristTableDataOptions, \"columns\" | \"order\">\n }\n )\n )\n }\n if (options) {\n return guardedRpc(() => fetchGristTableRows<T>(docApi, tableId, options))\n }\n return guardedRpc(() => fetchGristTableRows<T>(docApi, tableId))\n },\n [docApi, requireFullAccess, guardedRpc]\n )\n\n const listTables = useCallback(\n async (options?: ListTablesOptions) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return guardedRpc(async () => {\n const out = await Promise.resolve(docApi.listTables())\n const tables = [...out]\n if (options?.includeSystem) return tables\n return tables.filter(\n (t) => !t.startsWith(\"_grist\") && !t.startsWith(\"GristHidden_\")\n )\n })\n },\n [docApi, guardedRpc]\n )\n\n const listColumns = useCallback(\n async (tableId: string, options?: ListColumnsOptions) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n requireFullAccess(\"listColumns\")\n return guardedRpc(async () => {\n const metaByTable = await loadColumnMetadataByTable(docApi)\n const colMeta = metaByTable.get(tableId)\n if (!colMeta) return []\n\n const noiseOpts: GristNoiseColumnsOptions = {\n excludeId: options?.excludeId ?? true,\n excludeGristHelpers: options?.excludeGristHelpers ?? true,\n excludeLoggingColumns: options?.excludeLoggingColumns ?? true,\n excludeManualSort: options?.excludeManualSort ?? true,\n }\n\n const result: GristColumnInfo[] = []\n for (const [colId, meta] of colMeta) {\n if (!options?.includeSystem && isGristNoiseColumn(colId, meta, noiseOpts)) {\n continue\n }\n result.push({\n colId,\n type: meta.type,\n label: meta.label,\n isFormula: meta.isFormula,\n formula: meta.formula,\n description: meta.description,\n })\n }\n return result\n })\n },\n [docApi, requireFullAccess, guardedRpc]\n )\n\n const getDocName = useCallback(async () => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return guardedRpc(async () => String(await Promise.resolve(docApi.getDocName())))\n }, [docApi, guardedRpc])\n\n const buildReplicaDocumentFromDocApi = useCallback(\n async (opts?: BuildReplicaDocumentFromDocApiOptions) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n requireFullAccess(\"buildReplicaDocumentFromDocApi\")\n return guardedRpc(() => buildReplicaDocumentFromDocApiImpl(docApi, opts))\n },\n [docApi, requireFullAccess, guardedRpc]\n )\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 = { ...SELECTED_FETCH_DEFAULTS, ...fetchOptions }\n return guardedRpc(async () => (await impl(merged)) as GristColumnarTable)\n },\n [docApi, guardedRpc]\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 = { ...SELECTED_FETCH_DEFAULTS, ...fetchOptions }\n return guardedRpc(async () => (await impl(rowId, merged)) as Record<string, unknown>)\n },\n [docApi, guardedRpc]\n )\n\n return useMemo(\n () => ({\n fetchTable,\n fetchTableRows,\n fetchRow,\n listTables,\n listColumns,\n getDocName,\n buildReplicaDocumentFromDocApi,\n fetchSelectedTable,\n fetchSelectedRecord,\n readError,\n }),\n [\n fetchTable,\n fetchTableRows,\n fetchRow,\n listTables,\n listColumns,\n getDocName,\n buildReplicaDocumentFromDocApi,\n fetchSelectedTable,\n fetchSelectedRecord,\n readError,\n ]\n )\n}\n","import { useCallback, useMemo } from \"react\"\n\nimport { useRpcHeartbeatCoalesce } from \"./use-rpc-heartbeat-coalesce\"\n\nexport type UseGristWidgetOptionsApiResult = {\n getWidgetOptions: () => Promise<Record<string, unknown> | null>\n getWidgetOption: (key: string) => Promise<unknown>\n setWidgetOption: (key: string, value: unknown) => Promise<void>\n setWidgetOptions: (next: Record<string, unknown>) => Promise<void>\n patchWidgetOptions: (patch: Record<string, unknown>) => Promise<void>\n clearWidgetOptions: () => Promise<void>\n}\n\nexport function useGristWidgetOptionsApi(): UseGristWidgetOptionsApiResult {\n const coalesceRpc = useRpcHeartbeatCoalesce()\n\n const getWidgetOptions = useCallback(\n async () =>\n coalesceRpc(async () => {\n const next = await grist.getOptions()\n return next as Record<string, unknown> | null\n }),\n [coalesceRpc]\n )\n\n const getWidgetOption = useCallback(\n async (key: string) => coalesceRpc(() => Promise.resolve(grist.getOption(key))),\n [coalesceRpc]\n )\n\n const setWidgetOption = useCallback(\n async (key: string, value: unknown) => {\n await coalesceRpc(() => Promise.resolve(grist.setOption(key, value)))\n },\n [coalesceRpc]\n )\n\n const setWidgetOptions = useCallback(\n async (next: Record<string, unknown>) => {\n await coalesceRpc(() => Promise.resolve(grist.setOptions(next)))\n },\n [coalesceRpc]\n )\n\n const patchWidgetOptions = useCallback(\n async (patch: Record<string, unknown>) => {\n await coalesceRpc(async () => {\n const current = (await grist.getOptions()) as Record<string, unknown> | null\n await grist.setOptions({ ...(current ?? {}), ...patch })\n })\n },\n [coalesceRpc]\n )\n\n const clearWidgetOptions = useCallback(\n async () => {\n await coalesceRpc(() => Promise.resolve(grist.clearOptions()))\n },\n [coalesceRpc]\n )\n\n return useMemo(\n () => ({\n getWidgetOptions,\n getWidgetOption,\n setWidgetOption,\n setWidgetOptions,\n patchWidgetOptions,\n clearWidgetOptions,\n }),\n [\n getWidgetOptions,\n getWidgetOption,\n setWidgetOption,\n setWidgetOptions,\n patchWidgetOptions,\n clearWidgetOptions,\n ]\n )\n}\n","import { useCallback, useMemo } from \"react\"\n\nimport type { GristCursorPos } from \"../../types\"\nimport { useRpcHeartbeatCoalesce } from \"./use-rpc-heartbeat-coalesce\"\n\nexport type UseGristLinkingResult = {\n setCursorPosition: (pos: GristCursorPos) => Promise<void>\n setLinkedRowSelection: (rowIds: null | number[]) => Promise<void>\n}\n\nexport function useGristLinking(): UseGristLinkingResult {\n const coalesceRpc = useRpcHeartbeatCoalesce()\n\n const setCursorPosition = useCallback(\n async (pos: GristCursorPos) => {\n if (!grist.setCursorPos) throw new Error(\"setCursorPos is not available in this Grist version\")\n await coalesceRpc(() => Promise.resolve(grist.setCursorPos!(pos)))\n },\n [coalesceRpc]\n )\n\n const setLinkedRowSelection = useCallback(\n async (rowIds: null | number[]) => {\n if (!grist.setSelectedRows) throw new Error(\"setSelectedRows is not available in this Grist version\")\n await coalesceRpc(() => Promise.resolve(grist.setSelectedRows!(rowIds)))\n },\n [coalesceRpc]\n )\n\n return useMemo(\n () => ({ setCursorPosition, setLinkedRowSelection }),\n [setCursorPosition, setLinkedRowSelection]\n )\n}\n","import { useCallback, useMemo, useRef, useState } from \"react\"\n\nimport {\n fetchAttachmentBase64 as fetchAttachmentBase64Core,\n fetchAttachmentBlob as fetchAttachmentBlobCore,\n getAttachmentDownloadUrl as getAttachmentDownloadUrlCore,\n type GristFetchedAttachment,\n type GristFetchedAttachmentBlob,\n} from \"../../helpers/grist-attachment-download\"\nimport {\n uploadGristAttachment as uploadGristAttachmentCore,\n type GristAttachmentUploadResult,\n} from \"../../helpers/grist-attachment-upload\"\nimport {\n fetchWithGristAuth as fetchWithGristAuthCore,\n getGristAccessToken,\n type GristAccessToken,\n} from \"../../helpers/grist-fetch-with-auth\"\nimport { isAccessInsufficientError } from \"../../helpers/grist-sdk-alerts\"\nimport type { GristDocApi } from \"../../types\"\nimport { useRpcHeartbeatCoalesce } from \"./use-rpc-heartbeat-coalesce\"\n\nexport type UseGristAttachmentsRestResult = {\n getAttachmentUrl: (attachmentId: string, options?: { readOnly?: boolean }) => Promise<string>\n fetchAttachmentBase64: (attachmentId: string, options?: { readOnly?: boolean }) => Promise<GristFetchedAttachment>\n fetchAttachmentBlob: (attachmentId: string, options?: { readOnly?: boolean }) => Promise<GristFetchedAttachmentBlob>\n getAccessToken: (options?: { readOnly?: boolean }) => Promise<GristAccessToken>\n fetchWithAuth: (path: string, init?: RequestInit & { readOnly?: boolean }) => Promise<Response>\n uploadAttachment: (\n file: Blob | File,\n options?: { fileName?: string }\n ) => Promise<GristAttachmentUploadResult>\n readError: string | null\n}\n\nexport function useGristAttachmentsRest(docApi: GristDocApi | null): UseGristAttachmentsRestResult {\n const coalesceRpc = useRpcHeartbeatCoalesce()\n const [readError, setReadError] = useState<string | null>(null)\n const readErrorRef = useRef<string | null>(null)\n\n const guardedRpc = useCallback(\n async <T>(fn: () => Promise<T>): Promise<T> => {\n try {\n const result = await coalesceRpc(fn)\n if (readErrorRef.current !== null) {\n readErrorRef.current = null\n setReadError(null)\n }\n return result\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n if (isAccessInsufficientError(msg)) {\n if (readErrorRef.current !== msg) {\n readErrorRef.current = msg\n setReadError(msg)\n }\n }\n throw err\n }\n },\n [coalesceRpc]\n )\n\n const getAttachmentUrl = useCallback(\n async (attachmentId: string, opts?: { readOnly?: boolean }) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return guardedRpc(() => getAttachmentDownloadUrlCore(docApi, attachmentId, opts))\n },\n [docApi, guardedRpc]\n )\n\n const fetchAttachmentBase64 = useCallback(\n async (attachmentId: string, opts?: { readOnly?: boolean }) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return guardedRpc(() => fetchAttachmentBase64Core(docApi, attachmentId, opts))\n },\n [docApi, guardedRpc]\n )\n\n const fetchAttachmentBlob = useCallback(\n async (attachmentId: string, opts?: { readOnly?: boolean }) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return guardedRpc(() => fetchAttachmentBlobCore(docApi, attachmentId, opts))\n },\n [docApi, guardedRpc]\n )\n\n const getAccessToken = useCallback(\n async (opts?: { readOnly?: boolean }) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return guardedRpc(() => getGristAccessToken(docApi, opts))\n },\n [docApi, guardedRpc]\n )\n\n const fetchWithAuth = useCallback(\n (path: string, init?: RequestInit & { readOnly?: boolean }) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return guardedRpc(() => fetchWithGristAuthCore(docApi, path, init))\n },\n [docApi, guardedRpc]\n )\n\n const uploadAttachment = useCallback(\n (file: Blob | File, opts?: { fileName?: string }) => {\n if (!docApi) throw new Error(\"Grist is not ready\")\n return guardedRpc(() => uploadGristAttachmentCore(docApi, file, opts))\n },\n [docApi, guardedRpc]\n )\n\n return useMemo(\n () => ({\n getAttachmentUrl,\n fetchAttachmentBase64,\n fetchAttachmentBlob,\n getAccessToken,\n fetchWithAuth,\n uploadAttachment,\n readError,\n }),\n [\n getAttachmentUrl,\n fetchAttachmentBase64,\n fetchAttachmentBlob,\n getAccessToken,\n fetchWithAuth,\n uploadAttachment,\n readError,\n ]\n )\n}\n","import { useEffect, useMemo, useState } from \"react\"\n\nimport { parseGristThemePayload } from \"../../helpers/grist-theme-payload\"\nimport type { GristDocApi } from \"../../types\"\n\nexport type GristTheme = \"light\" | \"dark\"\n\nexport type UseGristThemeResult = {\n theme: GristTheme | null\n}\n\nexport function useGristTheme(_docApi: GristDocApi | null): UseGristThemeResult {\n const [theme, setTheme] = useState<GristTheme | null>(null)\n\n useEffect(() => {\n if (typeof grist === \"undefined\" || typeof grist.on !== \"function\") return\n\n const apply = (payload: unknown) => {\n const next = parseGristThemePayload(payload)\n if (next) setTheme(next)\n }\n\n grist.on(\"message\", (msg: unknown) => {\n if (!msg || typeof msg !== \"object\") return\n if (!(\"theme\" in msg)) return\n apply(msg)\n })\n }, [])\n\n return useMemo(() => ({ theme }), [theme])\n}\n","export type GristThemeName = \"light\" | \"dark\"\n\n/**\n * Normalize theme from `grist.on(\"message\")` host payloads (`msg.theme`).\n * Grist sends a theme object with `appearance`; some hosts may send a bare string.\n */\nexport function parseGristThemePayload(payload: unknown): GristThemeName | null {\n if (!payload || typeof payload !== \"object\") return null\n const raw = payload as Record<string, unknown>\n const top = raw.theme\n if (top === \"light\" || top === \"dark\") return top\n if (top && typeof top === \"object\") {\n const appearance = (top as Record<string, unknown>).appearance\n if (appearance === \"light\" || appearance === \"dark\") return appearance\n }\n return null\n}\n","import { useCallback, useMemo } from \"react\"\n\nimport type { GristReadyOptions } from \"../../types\"\nimport { useRpcHeartbeatCoalesce } from \"./use-rpc-heartbeat-coalesce\"\n\nexport type UseGristSectionApiResult = {\n configure: (options: GristReadyOptions) => Promise<void>\n refreshMappings: () => Promise<import(\"../../types\").GristWidgetColumnMap | null>\n}\n\nexport function useGristSectionApi(): UseGristSectionApiResult {\n const coalesceRpc = useRpcHeartbeatCoalesce()\n\n const configure = useCallback(\n 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 coalesceRpc(() => Promise.resolve(grist.sectionApi!.configure!(next)))\n },\n [coalesceRpc]\n )\n\n const refreshMappings = useCallback(\n async () => {\n if (!grist.sectionApi?.mappings) {\n throw new Error(\"grist.sectionApi.mappings is not available in this Grist version\")\n }\n return coalesceRpc(() => grist.sectionApi!.mappings!())\n },\n [coalesceRpc]\n )\n\n return useMemo(() => ({ configure, refreshMappings }), [configure, refreshMappings])\n}\n","import {\n useCallback,\n useEffect,\n useMemo,\n useState,\n useSyncExternalStore,\n type CSSProperties,\n type ReactNode,\n} from \"react\"\n\nimport {\n deriveBoundaryView,\n GRIST_BOUNDARY_PREPARING_COPY,\n type GristBoundaryView,\n} from \"../helpers/grist-boundary-view\"\nimport { deriveCapabilities, initialGristSnapshot } from \"../internal/handshake\"\nimport { useGristManagerOptional } from \"../internal/handshake-manager-context\"\nimport type { UseGristResult } from \"../use-grist\"\nimport { useGristOptional } from \"./grist-widget-provider\"\n\nexport type GristBoundaryGate = \"ready\" | \"canRender\"\n\nexport type GristBoundaryProps = {\n /**\n * Pass an explicit widget instance (e.g. when not using `<GristWidgetProvider>`).\n * Otherwise the boundary reads from the nearest provider.\n */\n widget?: UseGristResult\n /**\n * When `\"canRender\"`, children render only after mappings are usable\n * (`capabilities.canRender`). Use for widgets that require mapped columns.\n */\n gate?: GristBoundaryGate\n /** Rendered while `grist.ready` is in flight. */\n bootingFallback?: ReactNode\n /** Shown when `gate=\"canRender\"` and mappings are not yet usable. */\n preparingFallback?: ReactNode\n /** Rendered when the widget is not embedded in Grist (e.g. opened directly). */\n unavailableFallback?: ReactNode | ((actions: GristBoundaryActions) => ReactNode)\n /** Rendered on any error from `useGristReady`, subscriptions, or actions. */\n errorFallback?: (error: string, actions: GristBoundaryActions) => ReactNode\n /**\n * Delay before showing \"unavailable\" UI. Helps avoid false negatives on slow\n * networks where the plugin API handshake arrives late.\n */\n unavailableGraceMs?: number\n children: ReactNode\n}\n\nexport type GristBoundaryActions = {\n reload: () => Promise<void>\n isReloading: boolean\n}\n\nconst shellStyle: CSSProperties = {\n alignItems: \"center\",\n background: \"var(--background)\",\n boxSizing: \"border-box\",\n color: \"var(--foreground)\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n minHeight: \"100%\",\n padding: \"clamp(16px, 5vh, 32px)\",\n width: \"100%\",\n}\n\nconst cardStyle: CSSProperties = {\n background: \"var(--card)\",\n border: \"1px solid var(--border)\",\n borderRadius: 12,\n boxShadow: \"0 1px 3px rgb(0 0 0 / 0.12)\",\n maxWidth: 420,\n padding: \"20px 22px\",\n textAlign: \"center\",\n width: \"100%\",\n}\n\nconst titleStyle: CSSProperties = {\n color: \"var(--foreground)\",\n fontSize: 15,\n fontWeight: 600,\n lineHeight: 1.35,\n margin: 0,\n}\n\nconst messageStyle: CSSProperties = {\n color: \"var(--muted-foreground)\",\n fontSize: 14,\n lineHeight: 1.5,\n margin: \"10px 0 0\",\n}\n\nconst buttonStyle: CSSProperties = {\n background: \"var(--background)\",\n border: \"1px solid var(--border)\",\n borderRadius: 8,\n color: \"var(--foreground)\",\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 500,\n marginTop: 16,\n padding: \"8px 14px\",\n}\n\nfunction noopSubscribe() {\n return () => {}\n}\n\ntype GristBoundaryScreenProps = {\n title: string\n message: string\n /** Affects WAI-ARIA role only (`alert` vs `status`); copy uses the same neutral styles. */\n tone?: \"default\" | \"error\"\n showRetry?: boolean\n actions?: GristBoundaryActions\n retryLabel?: string\n retryBusyLabel?: string\n}\n\n/** Centered full-viewport chrome for booting / unavailable / error states. */\nexport function GristBoundaryScreen({\n title,\n message,\n tone = \"default\",\n showRetry = false,\n actions,\n retryLabel = \"Try reconnecting\",\n retryBusyLabel = \"Reconnecting…\",\n}: GristBoundaryScreenProps) {\n return (\n <div style={shellStyle} role={tone === \"error\" ? \"alert\" : \"status\"}>\n <div style={cardStyle}>\n <h2 style={titleStyle}>{title}</h2>\n <p style={messageStyle}>{message}</p>\n {showRetry && actions ? (\n <button\n disabled={actions.isReloading}\n onClick={() => void actions.reload()}\n style={{\n ...buttonStyle,\n cursor: actions.isReloading ? \"not-allowed\" : \"pointer\",\n opacity: actions.isReloading ? 0.7 : 1,\n }}\n type=\"button\"\n >\n {actions.isReloading ? retryBusyLabel : retryLabel}\n </button>\n ) : null}\n </div>\n </div>\n )\n}\n\nfunction BootingScreen({ message }: { message: string }) {\n return (\n <GristBoundaryScreen\n title=\"Connecting to Grist\"\n message={message}\n showRetry={false}\n />\n )\n}\n\nfunction blockingScreenFromView(\n view: Extract<GristBoundaryView, { mode: \"blocking\" }>,\n actions: GristBoundaryActions\n): ReactNode {\n return (\n <GristBoundaryScreen\n title={view.title}\n message={view.message}\n tone={view.kind === \"error\" ? \"error\" : \"default\"}\n showRetry={view.showRetry}\n actions={actions}\n retryLabel={view.kind === \"error\" ? \"Try again\" : \"Try reconnecting\"}\n retryBusyLabel={view.kind === \"error\" ? \"Retrying…\" : \"Reconnecting…\"}\n />\n )\n}\n\nfunction legacyBlockingFromWidget(\n w: UseGristResult,\n actions: GristBoundaryActions\n): ReactNode | null {\n if (w.status === \"unavailable\") {\n return (\n <GristBoundaryScreen\n title=\"Open inside Grist\"\n message=\"This page must be opened from a Grist document as a custom widget.\"\n showRetry\n actions={actions}\n />\n )\n }\n if (w.status === \"error\") {\n return (\n <GristBoundaryScreen\n title=\"Something went wrong\"\n message={\n w.error ??\n \"Something went wrong connecting to Grist. Try reconnecting below, or reload the page.\"\n }\n tone=\"error\"\n showRetry\n actions={actions}\n retryLabel=\"Try again\"\n retryBusyLabel=\"Retrying…\"\n />\n )\n }\n if (w.status !== \"ready\") {\n return <BootingScreen message=\"Connecting to Grist…\" />\n }\n return null\n}\n\n/**\n * Standardised loading / unavailable / error chrome for a Grist widget.\n *\n * ```tsx\n * <GristWidgetProvider options={{ requiredAccess: \"full\" }}>\n * <GristBoundary>\n * <MyWidget />\n * </GristBoundary>\n * </GristWidgetProvider>\n * ```\n */\nexport function GristBoundary({\n widget,\n gate = \"ready\",\n bootingFallback,\n preparingFallback,\n unavailableFallback,\n errorFallback,\n unavailableGraceMs = 5000,\n children,\n}: GristBoundaryProps) {\n const fromContext = useGristOptional()\n const w = widget ?? fromContext\n const manager = useGristManagerOptional()\n const snapshot = useSyncExternalStore(\n manager?.subscribe ?? noopSubscribe,\n manager?.getSnapshot ?? initialGristSnapshot,\n initialGristSnapshot\n )\n\n if (!w) {\n throw new Error(\n \"<GristBoundary> requires either a `widget` prop or a parent <GristWidgetProvider>\"\n )\n }\n\n const boundaryView = useMemo(\n () => (manager ? deriveBoundaryView(snapshot) : null),\n [manager, snapshot]\n )\n\n const [showUnavailable, setShowUnavailable] = useState(false)\n const [isReloading, setIsReloading] = useState(false)\n\n useEffect(() => {\n if (w.status !== \"unavailable\") {\n setShowUnavailable(false)\n return\n }\n const timer = window.setTimeout(() => setShowUnavailable(true), unavailableGraceMs)\n return () => window.clearTimeout(timer)\n }, [unavailableGraceMs, w.status])\n\n const reload = useCallback(async () => {\n const MIN_RELOAD_VISIBILITY_MS = 700\n const startedAt = Date.now()\n setIsReloading(true)\n try {\n await w.reload()\n } catch (error) {\n console.error(\"[grist-sdk] reload failed:\", error)\n } finally {\n const elapsed = Date.now() - startedAt\n const remaining = Math.max(0, MIN_RELOAD_VISIBILITY_MS - elapsed)\n if (remaining > 0) {\n await new Promise((resolve) => window.setTimeout(resolve, remaining))\n }\n setIsReloading(false)\n }\n }, [w])\n\n const actions = useMemo<GristBoundaryActions>(\n () => ({ reload, isReloading }),\n [isReloading, reload]\n )\n\n const canRender =\n gate !== \"canRender\" || !manager || deriveCapabilities(snapshot).canRender\n\n const defaultPreparing = (\n <GristBoundaryScreen\n title={GRIST_BOUNDARY_PREPARING_COPY.title}\n message={GRIST_BOUNDARY_PREPARING_COPY.message}\n showRetry={false}\n />\n )\n\n if (!manager) {\n const legacy = legacyBlockingFromWidget(w, actions)\n if (legacy) return <>{legacy}</>\n if (!canRender) return <>{preparingFallback ?? defaultPreparing}</>\n return <>{children}</>\n }\n\n if (w.status === \"unavailable\") {\n if (!showUnavailable) {\n const boot =\n boundaryView?.mode === \"blocking\" && boundaryView.kind === \"booting\"\n ? boundaryView.message\n : \"Connecting to Grist…\"\n return <>{bootingFallback ?? <BootingScreen message={boot} />}</>\n }\n if (typeof unavailableFallback === \"function\") {\n return <>{unavailableFallback(actions)}</>\n }\n if (unavailableFallback) return <>{unavailableFallback}</>\n if (boundaryView?.mode === \"blocking\") {\n return <>{blockingScreenFromView(boundaryView, actions)}</>\n }\n }\n\n if (w.status === \"error\") {\n if (errorFallback) {\n return <>{errorFallback(w.error ?? \"Grist connection error\", actions)}</>\n }\n if (boundaryView?.mode === \"blocking\") {\n return <>{blockingScreenFromView(boundaryView, actions)}</>\n }\n }\n\n if (w.status !== \"ready\") {\n if (boundaryView?.mode === \"blocking\" && boundaryView.kind === \"booting\") {\n return (\n <>\n {bootingFallback ?? <BootingScreen message={boundaryView.message} />}\n </>\n )\n }\n return <>{bootingFallback ?? <BootingScreen message=\"Connecting to Grist…\" />}</>\n }\n\n if (!canRender) {\n return <>{preparingFallback ?? defaultPreparing}</>\n }\n\n return <>{children}</>\n}\n","import { useMemo } from \"react\"\n\nimport { useContext } from \"react\"\n\nimport { useGristOptional } from \"./components/grist-widget-provider\"\nimport { useComposeGristWidgetSlices } from \"./internal/compose-grist-widget\"\nimport {\n GristCoreContext,\n useGristFromProvider,\n useGristCoreContext,\n useGristCurrentTableContext,\n useGristSelectionContext,\n useGristThemeContext,\n useGristWritesContext,\n type GristStatusSliceValue,\n} from \"./internal/contexts\"\nimport { mergeGristResultFromSlices } from \"./internal/merge-grist-result\"\n\nexport type {\n GristCapabilities,\n GristTheme,\n GristWidgetActionStatus,\n GristWidgetMode,\n GristWidgetStatus,\n UseGristOptions,\n UseGristResult,\n} from \"./use-grist-types\"\n\nimport type { UseGristOptions, UseGristResult } from \"./use-grist-types\"\n\nfunction useGristStandalone<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>(\n options?: UseGristOptions\n): UseGristResult<TRow, TMapped> {\n const slices = useComposeGristWidgetSlices(options)\n return useMemo(() => mergeGristResultFromSlices<TRow, TMapped>(slices), [slices])\n}\n\n/**\n * Primary Grist hook — use inside `<GristWidgetProvider>` via `useGristContext()`,\n * or standalone in a single-leaf widget.\n */\nexport function useGrist<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>(\n options?: UseGristOptions\n): UseGristResult<TRow, TMapped> {\n if (useContext(GristCoreContext)) {\n return useGristFromProvider<TRow, TMapped>()\n }\n return useGristStandalone<TRow, TMapped>(options)\n}\n\nexport { useGristContext, useGristOptional } from \"./components/grist-widget-provider\"\n\n/**\n * Slice subscriber: status + current-table info. Re-renders on status, error,\n * `currentTableId`, or `currentTableLoading` changes only.\n *\n * Must be called inside `<GristWidgetProvider>` — for standalone usage use\n * `useGrist()` directly.\n */\nexport function useGristStatus(): GristStatusSliceValue {\n const core = useGristCoreContext()\n const currentTable = useGristCurrentTableContext()\n return useMemo(() => ({ ...core, ...currentTable }), [core, currentTable])\n}\n\n/**\n * Slice subscriber for the selection / mappings / widget-options stream.\n * Must be called inside `<GristWidgetProvider>`.\n */\nexport function useGristSelection<TRow = Record<string, unknown>, TMapped = Record<string, unknown>>() {\n return useGristSelectionContext<TRow, TMapped>()\n}\n\n/**\n * Slice subscriber for writes (`table`, `getTable`, `applyActions`, `actionStatus`).\n * Must be called inside `<GristWidgetProvider>`.\n */\nexport function useGristWrites() {\n return useGristWritesContext()\n}\n\n/**\n * Slice subscriber for the host theme. Must be called inside `<GristWidgetProvider>`.\n */\nexport function useGristTheme() {\n return useGristThemeContext()\n}\n","import { useCallback, useContext, useEffect, useMemo, useState } from \"react\"\n\nimport { buildReplicaDocumentFromDocApi } from \"./helpers/build-replica-document\"\nimport { isGristNoiseColumn, type GristNoiseColumnsOptions } from \"./helpers/grist-columns-filters\"\nimport {\n buildReplicaJsonPayload,\n type ReplicaJsonIncludeRows,\n} from \"./helpers/replica-normalize\"\nimport { GristReadsContext } from \"./internal/contexts\"\nimport { useGristReady } from \"./low-level-hooks/use-grist-ready\"\nimport type {\n GristDocumentMode,\n GristReadyOptions,\n GristReplicaColumn,\n GristReplicaDocument,\n GristReplicaTable,\n GristRequiredAccess,\n} from \"./types\"\n\ntype ColumnExcludeContext = {\n tableId: string\n colId: string\n col: GristReplicaColumn\n}\n\nexport type UseGristSchemaOptions = {\n requiredAccess?: GristRequiredAccess\n tableId?: string\n excludeSystemTableData?: boolean\n /**\n * How row bodies are included in the replica document.\n * Default `schema+samples`.\n */\n replicaRowMode?: GristDocumentMode\n /** When `replicaRowMode` is `schema+samples`, max rows per table. Default 10. */\n sampleRowLimit?: number\n /** Stored on the replica as `source` (e.g. for logging). */\n source?: string\n} & GristNoiseColumnsOptions & {\n extraExcludeColumn?: (ctx: ColumnExcludeContext) => boolean\n } & Pick<GristReadyOptions, \"columns\" | \"allowSelectBy\" | \"hasCustomOptions\" | \"onEditOptions\">\n\n/** Selected table slice with `tableId` for consumers that expect it on the object. */\nexport type GristSchemaTableView = GristReplicaTable & { tableId: string }\n\n/** Options for `getDocumentJson` / `buildDocumentJson` on the return value of {@link useGristSchema}. */\nexport type ReplicaDocumentJsonOptions = {\n /** How row arrays appear in JSON. Default `full` (all rows currently on the document). */\n includeRows?: ReplicaJsonIncludeRows\n /** Cap per table when `includeRows` is `samples`. Default 10. */\n sampleRowLimit?: number\n space?: number\n}\n\nexport type UseGristSchemaResult = {\n isAvailable: boolean | null\n /** Canonical replica document. */\n document: GristReplicaDocument | null\n /** Same reference as `document`. */\n replicaDocument: GristReplicaDocument | null\n table: GristSchemaTableView | null\n documentJson: string | null\n getDocumentJson: (options?: ReplicaDocumentJsonOptions) => string | null\n buildDocumentJson: (document: GristReplicaDocument, options?: ReplicaDocumentJsonOptions) => string\n tableJson: string | null\n getTableJson: (options?: ReplicaDocumentJsonOptions) => string | null\n buildTableJson: (table: GristSchemaTableView, options?: ReplicaDocumentJsonOptions) => string\n isNoiseColumnId: (colId: string, col?: GristReplicaColumn) => boolean\n sortColumnIds: (colIds: string[], columns: Record<string, GristReplicaColumn>) => string[]\n loading: boolean\n error: string | null\n reload: () => Promise<void>\n}\n\nfunction filterReplicaDocumentColumns(\n document: GristReplicaDocument,\n options?: GristNoiseColumnsOptions,\n extraExcludeColumn?: (ctx: ColumnExcludeContext) => boolean\n): GristReplicaDocument {\n return {\n ...document,\n tables: Object.fromEntries(\n Object.entries(document.tables).map(([tableId, table]) => [\n tableId,\n {\n ...table,\n columns: Object.fromEntries(\n Object.entries(table.columns ?? {}).filter(([colId, col]) => {\n if (isGristNoiseColumn(colId, col, options)) return false\n if (extraExcludeColumn?.({ tableId, colId, col })) return false\n return true\n })\n ),\n },\n ])\n ),\n }\n}\n\n/**\n * Grist replica-document hook: metadata + optional decoded `rows` per table.\n */\nexport function useGristSchema(options?: UseGristSchemaOptions): UseGristSchemaResult {\n const requiredAccess = options?.requiredAccess ?? \"read table\"\n const requestedTableId = options?.tableId\n const excludeSystemTableData = options?.excludeSystemTableData ?? true\n const replicaRowMode = options?.replicaRowMode ?? \"schema+samples\"\n const sampleRowLimit = options?.sampleRowLimit ?? 10\n const replicaSource = options?.source\n const excludeId = options?.excludeId ?? true\n const excludeGristHelpers = options?.excludeGristHelpers ?? true\n const excludeLoggingColumns = options?.excludeLoggingColumns ?? true\n const excludeManualSort = options?.excludeManualSort ?? false\n const extraExcludeColumn = options?.extraExcludeColumn\n\n const { isAvailable, 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 // buildReplicaDocumentFromDocApi so access-insufficient errors flow through\n // the provider's readError → SDK alert system (smooth alert).\n const providerBuildReplica = useContext(GristReadsContext)?.buildReplicaDocumentFromDocApi\n\n const [document, setDocument] = useState<GristReplicaDocument | null>(null)\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const includeRowsForBuild: false | \"samples\" | \"full\" =\n replicaRowMode === \"schema-only\" ? false : replicaRowMode === \"schema+data\" ? \"full\" : \"samples\"\n\n const load = useCallback(async () => {\n if (!docApi) return\n setLoading(true)\n setError(null)\n try {\n const buildOpts = {\n includeSystemTableData: !excludeSystemTableData,\n includeRows: includeRowsForBuild,\n sampleRowLimit,\n source: replicaSource,\n }\n const raw = providerBuildReplica\n ? await providerBuildReplica(buildOpts)\n : await buildReplicaDocumentFromDocApi(docApi, buildOpts)\n const filtered = filterReplicaDocumentColumns(\n raw,\n {\n excludeId,\n excludeGristHelpers,\n excludeLoggingColumns,\n excludeManualSort,\n },\n extraExcludeColumn\n )\n setDocument(filtered)\n } catch (err) {\n setDocument(null)\n setError(err instanceof Error ? err.message : String(err))\n } finally {\n setLoading(false)\n }\n }, [\n docApi,\n providerBuildReplica,\n excludeSystemTableData,\n replicaRowMode,\n sampleRowLimit,\n excludeId,\n excludeGristHelpers,\n excludeLoggingColumns,\n excludeManualSort,\n extraExcludeColumn,\n replicaSource,\n ])\n\n useEffect(() => {\n if (docApi) void load()\n }, [docApi, load])\n\n const buildDocumentJson = useCallback((target: GristReplicaDocument, options?: ReplicaDocumentJsonOptions): string => {\n const includeRows = options?.includeRows ?? \"full\"\n const space = options?.space ?? 2\n const payload = buildReplicaJsonPayload(target, {\n includeRows,\n sampleRowLimit: options?.sampleRowLimit ?? sampleRowLimit,\n })\n return JSON.stringify(payload, null, space)\n }, [sampleRowLimit])\n\n const getDocumentJson = useCallback(\n (options?: ReplicaDocumentJsonOptions): string | null => {\n if (!document) return null\n return buildDocumentJson(document, options)\n },\n [document, buildDocumentJson]\n )\n\n const table = useMemo((): GristSchemaTableView | null => {\n if (!document || !requestedTableId) return null\n const slice = document.tables[requestedTableId]\n if (!slice) return null\n return { tableId: requestedTableId, ...slice }\n }, [document, requestedTableId])\n\n const buildTableJson = useCallback(\n (target: GristSchemaTableView, options?: ReplicaDocumentJsonOptions): string => {\n const includeRows = options?.includeRows ?? \"full\"\n const limit = options?.sampleRowLimit ?? sampleRowLimit\n const space = options?.space ?? 2\n const { tableId, ...rest } = target\n let body: GristReplicaTable = { ...rest }\n if (includeRows === \"none\") {\n const { rows: _r, ...r } = body\n body = r\n } else if (includeRows === \"samples\") {\n const r = body.rows ?? []\n body = { ...body, rows: r.slice(0, limit) }\n }\n return JSON.stringify({ tableId, ...body }, null, space)\n },\n [sampleRowLimit]\n )\n\n const getTableJson = useCallback(\n (options?: ReplicaDocumentJsonOptions): string | null => {\n if (!table) return null\n return buildTableJson(table, options)\n },\n [table, buildTableJson]\n )\n\n const noiseColumnMatcher = useCallback(\n (colId: string, col?: GristReplicaColumn): boolean =>\n isGristNoiseColumn(colId, col, {\n excludeId,\n excludeGristHelpers,\n excludeLoggingColumns,\n excludeManualSort,\n }),\n [excludeId, excludeGristHelpers, excludeLoggingColumns, excludeManualSort]\n )\n\n const sortColumns = useCallback((colIds: string[], columns: Record<string, GristReplicaColumn>): string[] => {\n return [...colIds].sort((a, b) => {\n const la = (columns[a]?.label || a).toLowerCase()\n const lb = (columns[b]?.label || b).toLowerCase()\n if (la !== lb) return la.localeCompare(lb)\n return a.localeCompare(b)\n })\n }, [])\n\n return {\n isAvailable,\n document,\n replicaDocument: document,\n table,\n documentJson: document ? buildDocumentJson(document) : null,\n getDocumentJson,\n buildDocumentJson,\n tableJson: table ? buildTableJson(table) : null,\n getTableJson,\n buildTableJson,\n isNoiseColumnId: noiseColumnMatcher,\n sortColumnIds: sortColumns,\n loading,\n error: readyError ?? error,\n reload: load,\n }\n}\n","import { useGristCore, type UseGristCoreOptions } from \"../internal/hooks/use-grist-core\"\nimport type { GristDocApi, GristReadyOptions } from \"../types\"\n\nexport type UseGristReadyOptions = GristReadyOptions & {\n availabilityMaxAttempts?: number\n availabilityIntervalMs?: number\n logWhenNotEmbedded?: boolean\n}\n\nexport type UseGristReadyResult = {\n isAvailable: boolean | null\n docApi: GristDocApi | null\n error: string | null\n reload: () => Promise<void>\n}\n\n/**\n * Handshake-backed `grist.ready` — delegates to {@link useGristCore} (FSM).\n *\n * Prefer `<GristWidgetProvider>` + `useGrist()` for full widget state; use this\n * hook when you only need `docApi` and connection status.\n */\nexport function useGristReady(options?: UseGristReadyOptions): UseGristReadyResult {\n const { isAvailable, docApi, error, reload } = useGristCore(options)\n return { isAvailable, docApi, error, reload }\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\n\nimport {\n useGristSelectionContext,\n useGristWidgetOptionsApiContext,\n} from \"../internal/contexts\"\n\nexport type UseGristWidgetOptionsFromContextConfig<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 key. When set, this hook reads/writes\n * `options[namespace]` instead of the whole options blob.\n */\n namespace?: string\n}\n\nexport type UseGristWidgetOptionsFromContextResult<T> = {\n options: T\n /** True until Grist has responded with the initial `onOptions` payload. */\n loading: boolean\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 * Typed widget options hook designed for use **inside a `<GristWidgetProvider>`**.\n *\n * Unlike `useGristWidgetOptions()` (which calls `useGristReady()` and conflicts\n * with the provider), this hook reads from the provider's existing context —\n * `widgetOptions` for reactive reads, and `patchWidgetOptions` / `setWidgetOptions`\n * for writes.\n *\n * ```tsx\n * function MyConfigPanel() {\n * const { options, patchOptions } = useGristWidgetOptionsFromContext({\n * defaults: { color: '#FF0000', showLabels: true },\n * })\n * return <input value={options.color} onChange={e => patchOptions({ color: e.target.value })} />\n * }\n * ```\n */\nexport function useGristWidgetOptionsFromContext<T extends Record<string, unknown>>(\n config: UseGristWidgetOptionsFromContextConfig<T>\n): UseGristWidgetOptionsFromContextResult<T> {\n const debounceMs = config.debounceMs ?? 250\n const selection = useGristSelectionContext()\n const optionsApi = useGristWidgetOptionsApiContext()\n\n const defaultsRef = useRef(config.defaults)\n useEffect(() => {\n defaultsRef.current = config.defaults\n }, [config.defaults])\n\n const rawOptions = selection.widgetOptions\n const hasReceived = rawOptions !== null\n\n const merged = useMemo(\n () => mergeWithDefaults(defaultsRef.current, rawOptions, config.namespace),\n [rawOptions, config.namespace]\n )\n\n const [localOverride, setLocalOverride] = useState<T | null>(null)\n const options = localOverride ?? merged\n\n useEffect(() => {\n setLocalOverride(null)\n }, [rawOptions])\n\n const debounceRef = useRef<number | null>(null)\n\n const flushWrite = useCallback(\n async (value: T) => {\n if (config.namespace) {\n await optionsApi.setWidgetOption(config.namespace, value)\n } else {\n await optionsApi.setWidgetOptions({ ...value })\n }\n },\n [config.namespace, optionsApi]\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 setOptions = useCallback(\n (next: T) => {\n setLocalOverride(next)\n scheduleWrite(next)\n },\n [scheduleWrite]\n )\n\n const patchOptions = useCallback(\n (patch: Partial<T>) => {\n setLocalOverride((prev) => {\n const base = prev ?? merged\n const next = { ...base, ...patch }\n scheduleWrite(next)\n return next\n })\n },\n [merged, 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 setLocalOverride(null)\n await flushWrite(next)\n }, [flushWrite])\n\n return useMemo(\n () => ({\n options,\n loading: !hasReceived,\n setOptions,\n patchOptions,\n reset,\n }),\n [options, hasReceived, setOptions, patchOptions, reset]\n )\n}\n","import { useEffect } from \"react\"\n\nexport type UseWidgetMetadataInput = {\n title: string\n description: string\n syncToParent?: boolean\n}\n\nexport function useWidgetMetadata(input?: UseWidgetMetadataInput | null) {\n useEffect(() => {\n if (!input) return\n\n const { title, description, syncToParent = true } = input\n const canonicalUrl = window.location.href\n\n document.title = title\n setMetaTag(\"name\", \"title\", title)\n setMetaTag(\"name\", \"description\", description)\n setMetaTag(\"property\", \"og:title\", title)\n setMetaTag(\"property\", \"og:description\", description)\n setMetaTag(\"property\", \"og:type\", \"website\")\n setMetaTag(\"property\", \"og:url\", canonicalUrl)\n setMetaTag(\"name\", \"twitter:card\", \"summary\")\n setMetaTag(\"name\", \"twitter:title\", title)\n setMetaTag(\"name\", \"twitter:description\", description)\n\n if (!syncToParent) return\n window.parent?.postMessage(\n {\n source: \"grist-playground-widget\",\n type: \"metadata\",\n title,\n description,\n },\n \"*\"\n )\n }, [input])\n}\n\nfunction setMetaTag(key: \"name\" | \"property\", value: string, content: string) {\n let meta = document.head.querySelector<HTMLMetaElement>(\n `meta[${key}=\"${value}\"]`\n )\n if (!meta) {\n meta = document.createElement(\"meta\")\n meta.setAttribute(key, value)\n document.head.appendChild(meta)\n }\n meta.setAttribute(\"content\", content)\n}\n","/**\n * Standard React library for building Grist custom widgets.\n *\n * ---------------------------------------------------------------------------\n * Agent \"north star\" (use this pattern unless you have a specific reason not to)\n * ---------------------------------------------------------------------------\n *\n * ```tsx\n * import {\n * GristWidgetProvider,\n * GristBoundary,\n * useGrist,\n * } from \"grist-widget-sdk\"\n *\n * export default function Page() {\n * return (\n * <GristWidgetProvider options={{ requiredAccess: \"full\", columns: [...] }}>\n * <GristBoundary>\n * <MyWidget />\n * </GristBoundary>\n * </GristWidgetProvider>\n * )\n * }\n *\n * function MyWidget() {\n * const w = useGrist()\n * if (w.mode === \"empty\") return <p>Select a row.</p>\n * if (w.mode === \"new-row\") return <NewRowForm w={w} />\n * return (\n * <button onClick={() => w.table.update({ id: w.record!.id as number, fields: { Done: true } })}>\n * Mark done\n * </button>\n * )\n * }\n * ```\n *\n * Rules for robust widget code:\n *\n * 1. Consume Grist only through `useGrist()` / `useGristSchema()`. Never import\n * the `grist` or `docApi` globals in widget code — this is enforced by ESLint\n * in `app/widgets/**`.\n * 2. Writes:\n * - **Records (default):** `w.table.*` (selected table) or `w.getTable(id).*`.\n * These are `TableOperations` — they support single and bulk calls natively.\n * - **Schema:** `w.applyActions([...])` with the exported action builders\n * (`gristAddColumnAction`, `gristRenameColumnAction`, …).\n * 3. Reads of the current section use `w.fetchSelectedTable()` /\n * `w.fetchSelectedRecord()` — defaults are pinned to decoded `rows` format.\n * 4. Column mapping: declare `columns` on the provider, then use\n * `w.mappedRecord` / `w.resolveMappedColumnId()` / `w.mapBack()` on writes,\n * and `w.columnMappingStatus` to gate UI when required columns are not mapped.\n * Use {@link getGristSdkAlertDescriptors} / {@link formatColumnMappingAlertMessage}\n * in your host UI (e.g. shadcn Alert) for shared copy — the SDK does not ship\n * styled alert components.\n * `mappedRecord` is `null` when `grist.mapColumnNames` cannot build a logical\n * row (e.g. missing required mappings), not a disguised raw `record`.\n * 5. Need schema/sample context for an LLM? Use `useGristSchema()` — it returns\n * a replica document (`GristReplicaDocument`, exposed as `document` and `replicaDocument`) ready to feed a model.\n * For a **full-document** replica (all tables, same options as the standalone {@link buildReplicaDocumentFromDocApi}),\n * use **`w.buildReplicaDocumentFromDocApi({ … })`** from **`useGrist()`** / **`useGristContext()`** (no `docApi` argument).\n *\n * Load `https://docs.getgrist.com/grist-plugin-api.js` in your app shell before the widget bundle.\n */\n\n// ---------------------------------------------------------------------------\n// Types (data-shape contracts shared by all entry points)\n// ---------------------------------------------------------------------------\nexport type {\n GristApplyUserActionsOptions,\n GristColumnsToMap,\n GristColumnToMap,\n GristCursorPos,\n GristDocApi,\n GristDocumentMode,\n GristFetchSelectedOptions,\n GristFormulaKind,\n GristMinimalRecord,\n GristReadyOptions,\n GristReplicaColumn,\n GristReplicaDocument,\n GristReplicaSelection,\n GristReplicaTable,\n GristRequiredAccess,\n GristRowRecord,\n GristTableNewRecord,\n GristTableOpOptions,\n GristTableOperations,\n GristTableUpdateRecord,\n GristTableUpsertOptions,\n GristTableUpsertRecord,\n GristWidgetColumnMap,\n GristWidgetConfiguration,\n GristWidgetInteraction,\n GristWidgetLinkingInfo,\n GristReplicaRow,\n} from \"./types\"\n\n// ---------------------------------------------------------------------------\n// Pure helpers (no React / no globals)\n// ---------------------------------------------------------------------------\n\n// Attachments\nexport {\n extractGristAttachmentId,\n extractGristAttachmentIdsFromCell,\n fetchAttachmentBase64,\n fetchAttachmentBase64ForCell,\n fetchAttachmentBlob,\n getAttachmentDownloadUrl,\n getAttachmentDownloadUrlForCell,\n type GristFetchedAttachment,\n type GristFetchedAttachmentBlob,\n} from \"./helpers/grist-attachment-download\"\n\nexport {\n extractAttachmentIdsFromUploadPayload,\n extractFirstAttachmentIdFromUploadPayload,\n gristAttachmentCellValue,\n gristAttachmentCellValues,\n mergeGristAttachmentCellValue,\n parseGristAttachmentUploadResponse,\n parseGristAttachmentUploadResponseIds,\n uploadGristAttachment,\n type GristAttachmentUploadResult,\n type GristEncodedAttachmentList,\n} from \"./helpers/grist-attachment-upload\"\n\n// Table-data conversions\nexport {\n computeRowCount,\n decodeColumnarToReplicaRows,\n fetchGristTableRows,\n fetchGristRow,\n findRowIndexById,\n materializeGristRowsFromColumnar,\n rowAtIndex,\n safeParseRowsToDisplayRows,\n sortRowsByGristOrder,\n tableDataToRows,\n type FetchGristTableRowsOptions,\n type GristColumnarTable,\n type GristTableRowsOrder,\n} from \"./helpers/grist-table-data\"\n\n// User-action builders — primarily for SCHEMA mutations.\n// For record CRUD, prefer `useGrist().table.*` instead of hand-assembling actions.\nexport {\n gristAddColumnAction,\n gristAddRecordAction,\n gristAddTableAction,\n gristAddVisibleColumnAction,\n gristBulkAddRecordAction,\n gristBulkRemoveRecordAction,\n gristBulkUpdateRecordAction,\n gristDuplicateTableAction,\n gristModifyColumnAction,\n gristRemoveColumnAction,\n gristRemoveRecordAction,\n gristRemoveTableAction,\n gristRenameColumnAction,\n gristRenameTableAction,\n gristReplaceTableDataAction,\n gristSetDocumentInfoAction,\n gristUpdateRecordAction,\n type GristUserActionTuple,\n} from \"./helpers/grist-user-actions\"\n\n// Column filters / schema builder / value codec / REST helpers / mapping validation\nexport {\n isGristNoiseColumn,\n type GristColumnLike,\n type GristNoiseColumnsOptions,\n} from \"./helpers/grist-columns-filters\"\nexport {\n buildReplicaColumnsFromColumnar,\n buildReplicaDocumentFromDocApi,\n inferGristFormulaKind,\n resolveGristFormulaKind,\n serializeJsonFriendly,\n type BuildReplicaDocumentFromDocApiOptions,\n type ReplicaTableColumnMetaLite,\n loadColumnMetadataByTable,\n orderedColumnIds,\n} from \"./helpers/grist-schema-builder\"\nexport {\n buildReplicaJsonPayload,\n normalizeReplicaDocumentInput,\n normalizeReplicaTableInput,\n type ReplicaJsonIncludeRows,\n} from \"./helpers/replica-normalize\"\nexport {\n normalizeGristChoiceListEntries,\n parseGristWidgetOptionsCell,\n type GristChoiceListEntry,\n} from \"./helpers/grist-widget-options\"\nexport {\n inferDisplayHelpersByRef,\n safeParseGristTableData,\n safeParseGristValues,\n gristCellValueSchema,\n gristSafeRefListValueSchema,\n gristSafeRefValueSchema,\n type GristCellValue,\n type GristSafeParseCellResult,\n type GristSafeParseIssue,\n type GristSafeParseIssueCode,\n type GristSafeRefListValue,\n type GristSafeRefValue,\n type GristSafeTableCellMeta,\n type GristSafeTableCellIssue,\n type SafeParseGristTableDataOptions,\n type SafeParseGristTableDataResult,\n type SafeParseGristValuesOptions,\n} from \"./helpers/grist-safe-parse\"\nexport {\n coerceGristDocApiRefRowId,\n decodeGristValue,\n encodeGristValue,\n isGristCellError,\n type GristDecodedValue,\n type GristEncodedBareRef,\n type GristEncodedDate,\n type GristEncodedDateTime,\n type GristEncodedError,\n type GristEncodedList,\n type GristEncodedPending,\n type GristEncodedRef,\n} from \"./helpers/grist-value-codec\"\nexport {\n fetchWithGristAuth,\n getGristAccessToken,\n type GristAccessToken,\n} from \"./helpers/grist-fetch-with-auth\"\nexport {\n validateColumnMappings,\n type ValidateColumnMappingsResult,\n} from \"./helpers/grist-mappings\"\nexport {\n deriveBoundaryBootLabel,\n deriveBoundaryBootPhase,\n deriveBoundaryView,\n formatBoundaryUserMessage,\n GRIST_BOUNDARY_PREPARING_COPY,\n type GristBoundaryBlockingKind,\n type GristBoundaryBootPhase,\n type GristBoundaryView,\n} from \"./helpers/grist-boundary-view\"\nexport {\n formatColumnMappingAlertMessage,\n formatLinkStaleAlertMessage,\n formatMappingPendingAlertMessage,\n formatMappingUnreportedAlertMessage,\n formatSectionNotLinkedAlertMessage,\n formatSourceNotWiredAlertMessage,\n formatAccessInsufficientMessage,\n isAccessInsufficientError,\n getGristSdkAlertDescriptors,\n isWidgetSectionNotLinked,\n getGristSdkAlertSeverity,\n getGristSdkAlertTitle,\n type GetGristSdkAlertDescriptorsOptions,\n type GristSdkAlertDescriptor,\n type GristSdkAlertKind,\n type GristSdkAlertSeverity,\n type GristSdkAlertsWidgetSlice,\n} from \"./helpers/grist-sdk-alerts\"\nexport { useGristSdkAlertDescriptors } from \"./hooks/use-grist-sdk-alert-descriptors\"\n\n// ---------------------------------------------------------------------------\n// Primary React surface — the ONLY Grist entry points widgets should import.\n// ---------------------------------------------------------------------------\n\n// Provider + context hook + boundary (agent pattern)\nexport {\n GristBoundary,\n GristBoundaryScreen,\n GristWidgetProvider,\n useGristContext,\n useGristOptional,\n type GristBoundaryActions,\n type GristBoundaryGate,\n type GristBoundaryProps,\n type GristWidgetProviderProps,\n} from \"./components\"\n\n// Standalone primary hook (when a provider is overkill — single-leaf widgets)\nexport {\n useGrist,\n useGristSelection,\n useGristStatus,\n useGristTheme,\n useGristWrites,\n type GristCapabilities,\n type GristTheme,\n type GristWidgetActionStatus,\n type GristWidgetMode,\n type GristWidgetStatus,\n type UseGristOptions,\n type UseGristResult,\n} from \"./use-grist\"\n\nexport type {\n ListTablesOptions,\n ListColumnsOptions,\n GristColumnInfo,\n} from \"./internal/hooks/use-grist-reads\"\n\n// Schema + samples for LLM context (paired with `useGrist()`).\nexport {\n useGristSchema,\n type GristSchemaTableView,\n type ReplicaDocumentJsonOptions,\n type UseGristSchemaOptions,\n type UseGristSchemaResult,\n} from \"./use-grist-schema\"\n\n// Typed widget options inside a provider (no separate `grist.ready()` call)\nexport {\n useGristWidgetOptionsFromContext,\n type UseGristWidgetOptionsFromContextConfig,\n type UseGristWidgetOptionsFromContextResult,\n} from \"./mid-level-hooks/use-grist-widget-options-from-context\"\n\n// Widget metadata helper (document title/meta + optional parent sync)\nexport {\n useWidgetMetadata,\n type UseWidgetMetadataInput,\n} from \"./use-widget-metadata\"\n\n// TEMPORARY verification marker for the merged release.yml publish-staging\n// job (2026-07-12). Never merged to main; this branch is disposable.\nexport const __RC_PUBLISH_TEST_MARKER_2__ = \"rc-publish-verify-2-2026-07-12\"\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8BAAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACYA,SAAS,6BAA6B,QAAqD;AACzF,aAAW,aAAa,CAAC,OAAO,IAAI,OAAO,cAAc,OAAO,MAAM,GAAG;AACvE,QAAI,cAAc,UAAa,cAAc,KAAM;AACnD,WAAO,OAAO,SAAS;AAAA,EACzB;AACA,SAAO;AACT;AAMO,SAAS,kCAAkC,OAA0B;AAC1E,QAAM,MAAgB,CAAC;AACvB,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,OAAO,CAAC,OAAe;AAC3B,QAAI,KAAK,IAAI,EAAE,EAAG;AAClB,SAAK,IAAI,EAAE;AACX,QAAI,KAAK,EAAE;AAAA,EACb;AAEA,QAAM,OAAO,CAAC,MAAqB;AACjC,QAAI,MAAM,UAAa,MAAM,KAAM;AACnC,QAAI,OAAO,MAAM,UAAU;AACzB,WAAK,OAAO,CAAC,CAAC;AACd;AAAA,IACF;AACA,QAAI,OAAO,MAAM,UAAU;AACzB,YAAM,UAAU,EAAE,KAAK;AACvB,UAAI,CAAC,QAAS;AACd,UAAI,QAAQ,KAAK,OAAO,GAAG;AACzB,aAAK,OAAO;AACZ;AAAA,MACF;AACA,UAAI;AACF,aAAK,KAAK,MAAM,OAAO,CAAY;AAAA,MACrC,QAAQ;AAAA,MAER;AACA;AAAA,IACF;AACA,QAAI,MAAM,QAAQ,CAAC,GAAG;AACpB,iBAAW,QAAQ,EAAG,MAAK,IAAI;AAC/B;AAAA,IACF;AACA,QAAI,OAAO,MAAM,UAAU;AACzB,YAAM,SAAS;AACf,YAAM,SAAS,6BAA6B,MAAM;AAClD,UAAI,WAAW,QAAW;AACxB,aAAK,MAAM;AACX;AAAA,MACF;AACA,iBAAW,UAAU,OAAO,OAAO,MAAM,EAAG,MAAK,MAAM;AAAA,IACzD;AAAA,EACF;AAEA,OAAK,KAAK;AACV,SAAO;AACT;AAGO,SAAS,yBAAyB,OAAoC;AAC3E,SAAO,kCAAkC,KAAK,EAAE,CAAC;AACnD;AAKA,eAAsB,yBACpB,QACA,cACA,SACiB;AACjB,QAAM,iBAAiB,OAAO;AAC9B,MAAI,CAAC,gBAAgB;AACnB,UAAM,IAAI,MAAM,2CAA2C;AAAA,EAC7D;AACA,QAAM,EAAE,OAAO,QAAQ,IAAI,MAAM,eAAe,EAAE,UAAU,SAAS,YAAY,MAAM,CAAC;AACxF,SAAO,GAAG,OAAO,gBAAgB,YAAY,kBAAkB,KAAK;AACtE;AAGA,eAAsB,gCACpB,QACA,WACA,OACA,SACwB;AACxB,QAAM,MAAM,kCAAkC,SAAS;AACvD,QAAM,KAAK,IAAI,KAAK;AACpB,MAAI,CAAC,GAAI,QAAO;AAChB,SAAO,yBAAyB,QAAQ,IAAI,OAAO;AACrD;AAEA,eAAe,kCAAkC,KAG9C;AACD,QAAM,WAAW,MAAM,MAAM,GAAG;AAChC,QAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,GAAG,KAAK,KAAK;AACpE,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI,MAAM,+BAA+B,SAAS,MAAM,GAAG;AAAA,EACnE;AACA,QAAM,SAAS,MAAM,SAAS,YAAY;AAC1C,SAAO,EAAE,QAAQ,YAAY;AAC/B;AAEA,SAAS,eAAe,QAA6B;AACnD,QAAM,QAAQ,IAAI,WAAW,MAAM;AACnC,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAK,WAAU,OAAO,aAAa,MAAM,CAAC,CAAC;AAC7E,SAAO,KAAK,MAAM;AACpB;AAGA,eAAsB,sBACpB,QACA,cACA,SACiC;AACjC,QAAM,MAAM,MAAM,yBAAyB,QAAQ,cAAc,OAAO;AACxE,QAAM,EAAE,QAAQ,YAAY,IAAI,MAAM,kCAAkC,GAAG;AAC3E,SAAO,EAAE,QAAQ,eAAe,MAAM,GAAG,YAAY;AACvD;AAGA,eAAsB,oBACpB,QACA,cACA,SACqC;AACrC,QAAM,MAAM,MAAM,yBAAyB,QAAQ,cAAc,OAAO;AACxE,QAAM,EAAE,QAAQ,YAAY,IAAI,MAAM,kCAAkC,GAAG;AAC3E,SAAO,EAAE,MAAM,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,MAAM,YAAY,CAAC,GAAG,YAAY;AACxE;AAGA,eAAsB,6BACpB,QACA,WACA,OACA,SACwC;AACxC,QAAM,MAAM,MAAM,gCAAgC,QAAQ,WAAW,OAAO,OAAO;AACnF,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,EAAE,QAAQ,YAAY,IAAI,MAAM,kCAAkC,GAAG;AAC3E,SAAO,EAAE,QAAQ,eAAe,MAAM,GAAG,YAAY;AACvD;;;ACnJA,IAAM,eAAe;AACrB,IAAM,QAAQ,oBAAI,IAA6B;AAC/C,IAAM,WAAW,oBAAI,IAAuC;AAE5D,SAAS,SAAS,UAA2B;AAC3C,SAAO,WAAW,OAAO;AAC3B;AAMA,eAAsB,oBACpB,QACA,SAC2B;AAC3B,MAAI,CAAC,OAAO,gBAAgB;AAC1B,UAAM,IAAI,MAAM,sEAAsE;AAAA,EACxF;AAEA,QAAM,WAAW,SAAS,YAAY;AACtC,QAAM,MAAM,SAAS,QAAQ;AAC7B,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,MAAM,MAAM,IAAI,GAAG;AACzB,MAAI,OAAO,MAAM,IAAI,YAAY,cAAc;AAC7C,WAAO,IAAI;AAAA,EACb;AAEA,QAAM,UAAU,SAAS,IAAI,GAAG;AAChC,MAAI,QAAS,QAAO;AAEpB,QAAM,OAAO,OAAO,eAAe,EAAE,SAAS,CAAC,EAAE,KAAK,CAAC,UAAU;AAC/D,UAAM,IAAI,KAAK,EAAE,OAAO,WAAW,KAAK,IAAI,EAAE,CAAC;AAC/C,aAAS,OAAO,GAAG;AACnB,WAAO;AAAA,EACT,CAAC;AAED,WAAS,IAAI,KAAK,IAAI;AACtB,SAAO;AACT;AAGO,SAAS,6BAAmC;AACjD,QAAM,MAAM;AACZ,WAAS,MAAM;AACjB;AAKA,eAAsB,mBACpB,QACA,MACA,MACmB;AACnB,QAAM,WAAW,MAAM,YAAY;AACnC,MAAI;AACJ,MAAI;AACF,YAAQ,MAAM,oBAAoB,QAAQ,EAAE,SAAS,CAAC;AAAA,EACxD,SAAS,KAAK;AACZ,+BAA2B;AAC3B,UAAM;AAAA,EACR;AAEA,QAAM,aAAa,gBAAgB,KAAK,IAAI;AAC5C,QAAM,YAAY,aAAa,OAAO,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI;AAC5E,QAAM,UAAU,MAAM,UAAU,OAAO,YAAY;AAEnD,QAAM,MAAM,aACR,IAAI,IAAI,IAAI,IACZ,IAAI,IAAI,GAAG,MAAM,QAAQ,QAAQ,OAAO,EAAE,CAAC,GAAG,SAAS,EAAE;AAK7D,MAAI,CAAC,IAAI,aAAa,IAAI,MAAM,EAAG,KAAI,aAAa,IAAI,QAAQ,MAAM,KAAK;AAE3E,QAAM,UAAU,IAAI,QAAQ,MAAM,WAAW,CAAC,CAAC;AAC/C,UAAQ,OAAO,eAAe;AAE9B,QAAM,WAAW,MAAM,MAAM,IAAI,SAAS,GAAG,EAAE,GAAG,MAAM,QAAQ,CAAC;AACjE,MAAI,SAAS,WAAW,KAAK;AAC3B,+BAA2B;AAC3B,UAAM,aAAa,MAAM,oBAAoB,QAAQ,EAAE,SAAS,CAAC;AACjE,QAAI,aAAa,IAAI,QAAQ,WAAW,KAAK;AAC7C,WAAO,MAAM,IAAI,SAAS,GAAG,EAAE,GAAG,MAAM,QAAQ,CAAC;AAAA,EACnD;AACA,SAAO;AACT;;;AC/DA,IAAM,kBAAkB,oBAAI,IAAI,CAAC,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG,CAAC;AAEnE,SAAS,kBAAkB,OAAoC;AAC7D,SACE,MAAM,QAAQ,KAAK,KACnB,OAAO,MAAM,CAAC,MAAM,YACpB,MAAM,CAAC,EAAE,UAAU,KACnB,gBAAgB,IAAI,MAAM,CAAC,CAAC;AAEhC;AAOO,SAAS,0BAA0B,OAAoC;AAC5E,MAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,EAAG,QAAO;AAChE,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,EAAG,QAAO;AACtD,QAAM,MAAM,MAAM,CAAC;AACnB,MAAI,QAAQ,OAAO,OAAO,MAAM,CAAC,MAAM,YAAY,OAAO,SAAS,MAAM,CAAC,CAAC,EAAG,QAAO,MAAM,CAAC;AAC5F,MAAI,QAAQ,OAAO,OAAO,MAAM,CAAC,MAAM,YAAY,OAAO,SAAS,MAAM,CAAC,CAAC,EAAG,QAAO,MAAM,CAAC;AAC5F,SAAO;AACT;AAEA,SAAS,0BAA0B,QAAsC;AACvE,SAAO,QAAQ,SAAS;AAC1B;AAEA,SAAS,0BAA0B,QAAsC;AACvE,SAAO,QAAQ,SAAS;AAC1B;AAEA,SAAS,uBAAuB,QAAsC;AACpE,SAAO,OAAO,QAAQ,SAAS,YAAY,OAAO,KAAK,WAAW,UAAU;AAC9E;AAEA,SAAS,mBAAmB,QAAsC;AAChE,SAAO,OAAO,QAAQ,SAAS,YAAY,OAAO,KAAK,WAAW,MAAM;AAC1E;AAEA,SAAS,oBAAoB,QAAsC;AACjE,SAAO,QAAQ,SAAS;AAC1B;AAEA,SAAS,wBAAwB,QAAsC;AACrE,SAAO,OAAO,QAAQ,SAAS,YAAY,OAAO,KAAK,WAAW,UAAU;AAC9E;AAQO,SAAS,iBAAiB,OAAgB,QAAgD;AAC/F,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAElD,MAAI,kBAAkB,KAAK,GAAG;AAC5B,UAAM,MAAM,MAAM,CAAC;AACnB,YAAQ,KAAK;AAAA,MACX,KAAK;AACH,eAAO;AAAA,UACL,SAAS;AAAA,UACT,MAAM,OAAO,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,IAAI;AAAA,UAChD,SAAS,OAAO,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,IAAI;AAAA,UACnD,WAAW,OAAO,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,IAAI;AAAA,QACvD;AAAA,MACF,KAAK;AACH,eAAO,MAAM,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,iBAAiB,GAAG,MAAS,CAAC;AAAA,MACjE,KAAK;AACH,YAAI,OAAO,MAAM,CAAC,MAAM,SAAU,QAAO,IAAI,KAAK,MAAM,CAAC,IAAI,GAAI;AACjE,eAAO;AAAA,MACT,KAAK;AACH,YAAI,OAAO,MAAM,CAAC,MAAM,SAAU,QAAO,IAAI,KAAK,MAAM,CAAC,IAAI,GAAI;AACjE,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,UACL,OAAO;AAAA,UACP,SAAS,OAAO,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,IAAI;AAAA,UACnD,OAAO,OAAO,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,IAAI;AAAA,QACnD;AAAA,MACF,KAAK;AACH,eAAO,EAAE,OAAO,MAAM,OAAO,OAAO,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,IAAI,EAAE;AAAA,MAC3E,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAEA,MAAI,oBAAoB,MAAM,KAAK,wBAAwB,MAAM,GAAG;AAClE,QAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,EAAG,QAAO,IAAI,KAAK,QAAQ,GAAI;AAAA,EACvF;AAEA,MAAI,mBAAmB,MAAM,KAAK,OAAO,UAAU,UAAU;AAC3D,WAAO,EAAE,OAAO,MAAM,OAAO,MAAM;AAAA,EACrC;AAEA,OAAK,uBAAuB,MAAM,KAAK,0BAA0B,MAAM,KAAK,0BAA0B,MAAM,MAAM,MAAM,QAAQ,KAAK,GAAG;AACtI,WAAO,MAAM,IAAI,CAAC,MAAM,iBAAiB,GAAG,MAAS,CAAC;AAAA,EACxD;AAEA,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,YAAY,OAAO,UAAU,UAAW,QAAO;AACjG,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,CAAC,MAAM,iBAAiB,GAAG,MAAS,CAAC;AAChF,SAAO;AACT;AAGO,SAAS,iBAAiB,OAA4C;AAC3E,SAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,CAAC,MAAM;AAC9C;AAQO,SAAS,iBAAiB,OAAgB,QAAsC;AACrF,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAElD,MAAI,oBAAoB,MAAM,KAAK,wBAAwB,MAAM,GAAG;AAClE,QAAI,iBAAiB,KAAM,QAAO,KAAK,MAAM,MAAM,QAAQ,IAAI,GAAI;AACnE,QAAI,OAAO,UAAU,UAAU;AAC7B,YAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,UAAI,CAAC,OAAO,MAAM,MAAM,EAAG,QAAO,KAAK,MAAM,SAAS,GAAI;AAAA,IAC5D;AACA,QAAI,OAAO,UAAU,SAAU,QAAO,KAAK,MAAM,KAAK;AAAA,EACxD;AAEA,MAAI,mBAAmB,MAAM,GAAG;AAC9B,QAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAI,SAAS,OAAO,UAAU,YAAY,WAAW,OAAO;AAC1D,aAAQ,MAA4B;AAAA,IACtC;AAAA,EACF;AAEA,MAAI,uBAAuB,MAAM,KAAK,0BAA0B,MAAM,KAAK,0BAA0B,MAAM,GAAG;AAC5G,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,YAAM,QAAQ,MAAM,IAAI,CAAC,MAAM;AAC7B,YAAI,KAAK,OAAO,MAAM,YAAY,WAAW,EAAG,QAAQ,EAAwB;AAChF,eAAO;AAAA,MACT,CAAC;AACD,aAAO,CAAC,KAAK,GAAG,KAAK;AAAA,IACvB;AAAA,EACF;AAEA,SAAO;AACT;;;ACrLA,IAAM,qBAAqB,EAAE,MAAM,cAAuB;AAenD,SAAS,sCACd,KACA,SACU;AACV,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,+CAA+C;AAAA,EACjE;AAEA,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,OAAO;AAAA,EAC7B,QAAQ;AACN,QAAI,SAAS,QAAQ;AACnB,YAAM,IAAI,MAAM,+CAA+C;AAAA,IACjE;AACA,aAAS;AAAA,EACX;AAEA,SAAO,sCAAsC,QAAQ,OAAO;AAC9D;AAKO,SAAS,mCACd,KACA,SACQ;AACR,QAAM,MAAM,sCAAsC,KAAK,OAAO;AAC9D,SAAO,IAAI,CAAC;AACd;AAEO,SAAS,sCACd,QACA,SACU;AACV,MAAI,SAAS,QAAQ;AACnB,WAAO,4CAA4C,MAAM;AAAA,EAC3D;AAEA,QAAM,QAAQ,0CAA0C,MAAM;AAC9D,MAAI,UAAU,QAAW;AACvB,QAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,YAAM,MAAgB,CAAC;AACvB,YAAM,OAAO,oBAAI,IAAY;AAC7B,iBAAW,QAAQ,QAAQ;AACzB,cAAM,KAAK,mBAAmB,IAAI;AAClC,YAAI,MAAM,CAAC,KAAK,IAAI,EAAE,GAAG;AACvB,eAAK,IAAI,EAAE;AACX,cAAI,KAAK,EAAE;AAAA,QACb;AAAA,MACF;AACA,aAAO,IAAI,SAAS,IAAI,MAAM,CAAC,KAAK;AAAA,IACtC;AACA,WAAO,CAAC,KAAK;AAAA,EACf;AAEA,QAAM,IAAI,MAAM,0DAA0D;AAC5E;AAEA,SAAS,4CAA4C,QAA2B;AAC9E,MAAI,OAAO,WAAW,YAAY,OAAO,SAAS,MAAM,GAAG;AACzD,WAAO,CAAC,OAAO,MAAM,CAAC;AAAA,EACxB;AAEA,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,UAAM,MAAgB,CAAC;AACvB,UAAM,OAAO,oBAAI,IAAY;AAC7B,eAAW,QAAQ,QAAQ;AACzB,UAAI,OAAO,SAAS,YAAY,CAAC,OAAO,SAAS,IAAI,GAAG;AACtD,cAAM,IAAI,MAAM,0DAA0D;AAAA,MAC5E;AACA,YAAM,KAAK,OAAO,IAAI;AACtB,UAAI,CAAC,KAAK,IAAI,EAAE,GAAG;AACjB,aAAK,IAAI,EAAE;AACX,YAAI,KAAK,EAAE;AAAA,MACb;AAAA,IACF;AACA,QAAI,IAAI,WAAW,GAAG;AACpB,YAAM,IAAI,MAAM,8CAA8C;AAAA,IAChE;AACA,WAAO;AAAA,EACT;AAEA,QAAM,IAAI,MAAM,0DAA0D;AAC5E;AAGO,SAAS,0CAA0C,QAAqC;AAC7F,MAAI,OAAO,WAAW,YAAY,OAAO,SAAS,MAAM,GAAG;AACzD,WAAO,OAAO,MAAM;AAAA,EACtB;AAEA,MAAI,OAAO,WAAW,YAAY,OAAO,KAAK,GAAG;AAC/C,WAAO,OAAO,KAAK;AAAA,EACrB;AAEA,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,eAAW,QAAQ,QAAQ;AACzB,YAAM,KAAK,mBAAmB,IAAI;AAClC,UAAI,GAAI,QAAO;AAAA,IACjB;AACA,WAAO;AAAA,EACT;AAEA,MAAI,UAAU,OAAO,WAAW,UAAU;AACxC,UAAM,SAAS;AACf,eAAW,OAAO,CAAC,MAAM,gBAAgB,QAAQ,GAAG;AAClD,YAAM,KAAK,mBAAmB,OAAO,GAAG,CAAC;AACzC,UAAI,GAAI,QAAO;AAAA,IACjB;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,mBAAmB,OAAoC;AAC9D,MAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,GAAG;AACvD,WAAO,OAAO,KAAK;AAAA,EACrB;AACA,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,GAAG;AAC7C,WAAO,MAAM,KAAK;AAAA,EACpB;AACA,SAAO;AACT;AAEA,SAAS,6BAA6B,IAAsC;AAC1E,QAAM,UAAU,OAAO,OAAO,WAAW,KAAK,OAAO,EAAE;AACvD,MAAI,OAAO,SAAS,OAAO,KAAK,OAAO,OAAO,MAAM,OAAO,EAAE,EAAE,KAAK,GAAG;AACrE,WAAO;AAAA,EACT;AACA,SAAO,OAAO,OAAO,WAAW,OAAO,EAAE,IAAI,GAAG,KAAK;AACvD;AAGO,SAAS,0BACd,eAC4B;AAC5B,QAAM,QAAQ,cAAc,IAAI,4BAA4B;AAC5D,QAAM,UAAU,iBAAiB,OAAO,kBAAkB;AAC1D,MAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,QAAQ,CAAC,MAAM,KAAK;AACjD,WAAO,CAAC,KAAK,GAAG,KAAK;AAAA,EACvB;AACA,SAAO;AACT;AAGO,SAAS,yBAAyB,cAA2D;AAClG,SAAO,0BAA0B,CAAC,YAAY,CAAC;AACjD;AAKO,SAAS,8BACd,cACA,QAC4B;AAC5B,QAAM,WAAW,kCAAkC,YAAY;AAC/D,QAAM,SAAmB,CAAC;AAC1B,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,OAAO,CAAC,QAAyB;AACrC,UAAM,KAAK,OAAO,GAAG,EAAE,KAAK;AAC5B,QAAI,CAAC,MAAM,KAAK,IAAI,EAAE,EAAG;AACzB,SAAK,IAAI,EAAE;AACX,WAAO,KAAK,EAAE;AAAA,EAChB;AACA,aAAW,MAAM,SAAU,MAAK,EAAE;AAClC,aAAW,MAAM,OAAQ,MAAK,EAAE;AAChC,SAAO,0BAA0B,MAAM;AACzC;AAEA,IAAM,iBAAiB;AAAA,EACrB,oBAAoB;AAAA,EACpB,QAAQ;AACV;AAQA,eAAsB,sBACpB,QACA,MACA,SACsC;AACtC,QAAM,OAAO,IAAI,SAAS;AAC1B,QAAM,WACJ,SAAS,aAAa,gBAAgB,QAAQ,KAAK,OAAO,KAAK,OAAO;AACxE,OAAK,OAAO,UAAU,MAAM,QAAQ;AAEpC,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,mBAAmB,QAAQ,gBAAgB;AAAA,MAC1D,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,IACX,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,QAAI,mBAAmB,KAAK,GAAG,GAAG;AAChC,YAAM,eACJ,OAAO,WAAW,aAAa,cAC3B,WAAW,SAAS,SACpB;AACN,YAAM,IAAI;AAAA,QACR,2FAA2F,YAAY;AAAA,MACzG;AAAA,IACF;AACA,UAAM;AAAA,EACR;AAEA,QAAM,MAAM,MAAM,SAAS,KAAK;AAChC,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI;AAAA,MACR,IAAI,KAAK,IACL,6BAA6B,SAAS,MAAM,MAAM,IAAI,MAAM,GAAG,GAAG,CAAC,KACnE,6BAA6B,SAAS,MAAM;AAAA,IAClD;AAAA,EACF;AAEA,QAAM,MAAM,sCAAsC,GAAG;AACrD,SAAO,EAAE,KAAK,SAAS,IAAI,CAAC,EAAG;AACjC;;;ACvPA,iBAAgC;;;ACmBzB,SAAS,4BAA4B,KAAmD;AAC7F,MAAI,OAAO,QAAQ,QAAQ,GAAI,QAAO;AACtC,MAAI,OAAO,QAAQ,UAAU;AAC3B,QAAI;AACF,YAAM,SAAkB,KAAK,MAAM,GAAG;AACtC,UAAI,UAAU,OAAO,WAAW,YAAY,CAAC,MAAM,QAAQ,MAAM,GAAG;AAClE,eAAO;AAAA,MACT;AAAA,IACF,QAAQ;AACN,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AACA,MAAI,OAAO,QAAQ,YAAY,CAAC,MAAM,QAAQ,GAAG,GAAG;AAClD,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,eAAe,OAAgC,KAAiC;AACvF,QAAM,IAAI,MAAM,GAAG;AACnB,SAAO,OAAO,MAAM,WAAW,IAAI;AACrC;AAOO,SAAS,gCACd,eACwB;AACxB,MAAI,CAAC,cAAe,QAAO,CAAC;AAC5B,QAAM,aAAa,cAAc;AACjC,MAAI,CAAC,MAAM,QAAQ,UAAU,EAAG,QAAO,CAAC;AAExC,QAAM,mBAAmB,cAAc;AACvC,QAAM,gBACJ,oBACA,OAAO,qBAAqB,YAC5B,CAAC,MAAM,QAAQ,gBAAgB,IAC1B,mBACD,CAAC;AAEP,QAAM,MAA8B,CAAC;AACrC,aAAW,KAAK,YAAY;AAC1B,UAAM,QAAQ,OAAO,MAAM,WAAW,IAAI,KAAK,OAAO,OAAO,CAAC,IAAI;AAClE,QAAI,CAAC,MAAO;AACZ,UAAM,QAAQ,cAAc,KAAK,KAAK,CAAC;AACvC,QAAI,KAAK;AAAA,MACP;AAAA,MACA,OAAO;AAAA,MACP,WAAW,eAAe,OAAO,WAAW;AAAA,MAC5C,WAAW,eAAe,OAAO,WAAW;AAAA,IAC9C,CAAC;AAAA,EACH;AACA,SAAO;AACT;;;AD/CO,IAAM,0BAA0B,aAAE,OAAO;AAAA,EAC9C,OAAO,aAAE,OAAO;AAAA,EAChB,SAAS,aAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAC1C,CAAC;AAEM,IAAM,8BAA8B,aAAE,OAAO;AAAA,EAClD,QAAQ,aAAE,MAAM,aAAE,OAAO,CAAC;AAAA,EAC1B,UAAU,aAAE,MAAM,aAAE,OAAO,CAAC,EAAE,SAAS;AACzC,CAAC;AAEM,IAAM,uBAAuB,aAAE,MAAM;AAAA,EAC1C,aAAE,KAAK;AAAA,EACP,aAAE,OAAO;AAAA,EACT,aAAE,OAAO;AAAA,EACT,aAAE,QAAQ;AAAA,EACV,aAAE,KAAK;AAAA,EACP,aAAE,MAAM,aAAE,QAAQ,CAAC;AAAA,EACnB;AAAA,EACA;AACF,CAAC;AA6DM,SAAS,yBACd,SACwB;AACxB,QAAM,MAA8B,CAAC;AACrC,QAAM,gBAAgB,OAAO,QAAQ,OAAO,EAAE;AAAA,IAAO,CAAC,CAAC,KAAK,MAC1D,MAAM,WAAW,cAAc;AAAA,EACjC;AACA,QAAM,cAAc,oBAAI,IAAY;AACpC,QAAM,gBAAgB,oBAAI,IAAoB;AAC9C,aAAW,CAAC,OAAO,GAAG,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,QAAI,OAAO,KAAK,WAAW,YAAY,OAAO,SAAS,IAAI,MAAM,GAAG;AAClE,oBAAc,IAAI,IAAI,QAAQ,KAAK;AAAA,IACrC;AAAA,EACF;AACA,aAAW,CAAC,OAAO,GAAG,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,UAAM,OAAO,KAAK;AAClB,QAAI,OAAO,SAAS,YAAa,CAAC,KAAK,WAAW,MAAM,KAAK,CAAC,KAAK,WAAW,UAAU,GAAI;AAC1F;AAAA,IACF;AACA,QAAI,OAAO,IAAI,kBAAkB,YAAY,OAAO,SAAS,IAAI,aAAa,GAAG;AAC/E,YAAM,cAAc,cAAc,IAAI,IAAI,aAAa;AACvD,UAAI,aAAa;AACf,YAAI,KAAK,IAAI;AACb,oBAAY,IAAI,WAAW;AAC3B;AAAA,MACF;AAAA,IACF;AACA,UAAM,QAAQ,cAAc,KAAK,CAAC,CAAC,EAAE,MAAM,MAAM;AAC/C,YAAM,UAAU,QAAQ;AACxB,aAAO,OAAO,YAAY,aAAa,QAAQ,SAAS,IAAI,KAAK,GAAG,KAAK,QAAQ,SAAS,IAAI,KAAK,EAAE;AAAA,IACvG,CAAC;AACD,QAAI,OAAO;AACT,UAAI,KAAK,IAAI,MAAM,CAAC;AACpB,kBAAY,IAAI,MAAM,CAAC,CAAC;AAAA,IAC1B;AAAA,EACF;AAIA,QAAM,iBAAiB,OAAO,QAAQ,OAAO,EAC1C,OAAO,CAAC,CAAC,OAAO,GAAG,MAAM;AACxB,UAAM,OAAO,KAAK;AAClB,WACE,CAAC,IAAI,KAAK,KACV,OAAO,SAAS,aACf,KAAK,WAAW,MAAM,KAAK,KAAK,WAAW,UAAU;AAAA,EAE1D,CAAC,EACA,KAAK,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,aAAa,OAAO,qBAAqB,EAAE,CAAC,GAAG,aAAa,OAAO,iBAAiB;AAC7G,QAAM,cAAc,cACjB,OAAO,CAAC,CAAC,QAAQ,MAAM,CAAC,YAAY,IAAI,QAAQ,CAAC,EACjD,KAAK,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,aAAa,OAAO,qBAAqB,EAAE,CAAC,GAAG,aAAa,OAAO,iBAAiB;AAC7G,aAAW,CAAC,OAAO,MAAM,KAAK,gBAAgB;AAC5C,UAAM,SAAS,QAAQ,aAAa,OAAO;AAC3C,UAAM,YAAY,YAAY,KAAK,CAAC,CAAC,EAAE,SAAS,MAAM;AACpD,YAAM,YAAY,WAAW,aAAa,OAAO;AACjD,aAAO,YAAY;AAAA,IACrB,CAAC;AACD,QAAI,CAAC,UAAW;AAChB,QAAI,KAAK,IAAI,UAAU,CAAC;AACxB,gBAAY,IAAI,UAAU,CAAC,CAAC;AAAA,EAC9B;AAEA,aAAW,CAAC,KAAK,KAAK,gBAAgB;AACpC,QAAI,IAAI,KAAK,EAAG;AAChB,UAAM,YAAY,YAAY,KAAK,CAAC,CAAC,QAAQ,MAAM,CAAC,YAAY,IAAI,QAAQ,CAAC;AAC7E,QAAI,CAAC,UAAW;AAChB,QAAI,KAAK,IAAI,UAAU,CAAC;AACxB,gBAAY,IAAI,UAAU,CAAC,CAAC;AAAA,EAC9B;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,MAAyC;AAChE,QAAM,QAAQ,KAAK;AACnB,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM;AACvC,aAAW,OAAO,OAAO,KAAK,IAAI,GAAG;AACnC,UAAM,MAAM,KAAK,GAAG;AACpB,QAAI,MAAM,QAAQ,GAAG,EAAG,QAAO,IAAI;AAAA,EACrC;AACA,SAAO;AACT;AAEA,SAAS,cAAc,KAA6C;AAClE,QAAM,IAAI,IAAI;AACd,MAAI,OAAO,MAAM,YAAY,CAAC,OAAO,MAAM,CAAC,EAAG,QAAO;AACtD,MAAI,OAAO,MAAM,YAAY,EAAE,KAAK,MAAM,IAAI;AAC5C,UAAM,IAAI,OAAO,CAAC;AAClB,QAAI,CAAC,OAAO,MAAM,CAAC,EAAG,QAAO;AAAA,EAC/B;AACA,SAAO;AACT;AAEA,SAAS,qBACP,MACqB;AACrB,QAAM,YAAY,KAAK,KAAK,CAAC,MAAM,cAAc,CAA4B,MAAM,IAAI;AACvF,MAAI,CAAC,WAAW;AACd,WAAO,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM;AAC9B,YAAM,MAAM,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC9C,YAAM,MAAM,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC9C,aAAO,MAAM;AAAA,IACf,CAAC;AAAA,EACH;AACA,SAAO,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM;AAC9B,UAAM,KAAK,cAAc,CAA4B;AACrD,UAAM,KAAK,cAAc,CAA4B;AACrD,QAAI,OAAO,QAAQ,OAAO,QAAQ,OAAO,GAAI,QAAO,KAAK;AACzD,QAAI,OAAO,QAAQ,OAAO,KAAM,QAAO;AACvC,QAAI,OAAO,QAAQ,OAAO,KAAM,QAAO;AACvC,UAAM,MAAM,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC9C,UAAM,MAAM,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC9C,WAAO,MAAM;AAAA,EACf,CAAC;AACH;AAEA,SAAS,WAAW,QAaN;AACZ,QAAM,OAAO,QAAQ;AACrB,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,SAAS,OAAQ,QAAO;AAC5B,MAAI,SAAS,UAAW,QAAO;AAC/B,MAAI,SAAS,MAAO,QAAO;AAC3B,MAAI,SAAS,OAAQ,QAAO;AAC5B,MAAI,SAAS,OAAQ,QAAO;AAC5B,MAAI,SAAS,cAAc,KAAK,WAAW,WAAW,EAAG,QAAO;AAChE,MAAI,SAAS,SAAU,QAAO;AAC9B,MAAI,SAAS,aAAc,QAAO;AAClC,MAAI,KAAK,WAAW,MAAM,EAAG,QAAO;AACpC,MAAI,KAAK,WAAW,UAAU,EAAG,QAAO;AACxC,MAAI,SAAS,cAAe,QAAO;AACnC,MAAI,SAAS,MAAO,QAAO;AAC3B,SAAO;AACT;AAEA,SAAS,kBAAkB,OAA+B;AACxD,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,aAAa,OAAO,UAAU,UAAU;AACxF,WAAO,OAAO,KAAK;AAAA,EACrB;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,OAAwE;AACnG,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO,EAAE,OAAO,KAAK;AAChE,MAAI,OAAO,UAAU,SAAU,QAAO,EAAE,MAAM;AAC9C,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAW,QAAO,EAAE,OAAO,OAAO,KAAK,EAAE;AAC3F,SAAO;AAAA,IACL,OAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,EACF;AACF;AAEA,SAAS,yBAAyB,OAAoE;AACpG,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO,EAAE,QAAQ,CAAC,EAAE;AAC/D,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,IAAI,MAAM,KAAK;AACrB,QAAI,MAAM,GAAI,QAAO,EAAE,QAAQ,CAAC,EAAE;AAClC,QAAI,EAAE,WAAW,GAAG,GAAG;AACrB,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,CAAC;AAC3B,YAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,iBAAO,yBAAyB,MAAM;AAAA,QACxC;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACA,MAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,WAAO;AAAA,MACL,OAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAGA,QAAM,QACJ,MAAM,SAAS,KAAK,MAAM,CAAC,MAAM,MAC7B,MAAM,MAAM,CAAC,IACb;AACN,QAAM,MAAgB,CAAC;AACvB,aAAW,QAAQ,OAAO;AACxB,UAAM,IAAI,kBAAkB,IAAI;AAChC,QAAI,MAAM,MAAM;AACd,aAAO;AAAA,QACL,OAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF;AACA,QAAI,KAAK,CAAC;AAAA,EACZ;AACA,SAAO,EAAE,QAAQ,IAAI;AACvB;AAEA,SAAS,kBACP,SACA,aACA,SAC6E;AAC7E,QAAM,SAAgC,CAAC;AACvC,MAAI,YAAY,KAAM,QAAO,EAAE,OAAO,MAAM,OAAO;AAEnD,QAAM,QACJ,OAAO,YAAY,YAAY,OAAO,SAAS,OAAO,IAClD,UACA,WAAW,OAAO,YAAY,YAAY,WAAW,UAClD,QAA8B,QAC/B;AAGR,MAAI,UAAU,EAAG,QAAO,EAAE,OAAO,MAAM,OAAO;AAC9C,MAAI,UAAU,QAAQ,CAAC,OAAO,SAAS,KAAK,GAAG;AAC7C,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,IACX,CAAC;AACD,WAAO,EAAE,OAAO,MAAM,OAAO;AAAA,EAC/B;AAEA,MAAI,YAAY,KAAM,QAAO,EAAE,OAAO,OAAO,OAAO;AAEpD,QAAM,SAAS,oBAAoB,WAAW;AAC9C,MAAI,OAAO,MAAO,QAAO,KAAK,OAAO,KAAK;AAC1C,SAAO;AAAA,IACL,OAAO,EAAE,OAAO,SAAS,OAAO,MAAM;AAAA,IACtC;AAAA,EACF;AACF;AAEA,SAAS,sBACP,SACA,aACA,SACmF;AACnF,QAAM,SAAgC,CAAC;AACvC,MAAI,YAAY,KAAM,QAAO,EAAE,OAAO,MAAM,OAAO;AACnD,MAAI,CAAC,MAAM,QAAQ,OAAO,GAAG;AAC3B,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,IACX,CAAC;AACD,WAAO,EAAE,OAAO,MAAM,OAAO;AAAA,EAC/B;AAEA,QAAM,SAAmB,CAAC;AAC1B,aAAW,QAAQ,SAAS;AAC1B,QAAI,OAAO,SAAS,YAAY,OAAO,SAAS,IAAI,KAAK,SAAS,GAAG;AACnE,aAAO,KAAK,IAAI;AAChB;AAAA,IACF;AACA,QAAI,QAAQ,OAAO,SAAS,YAAY,WAAW,MAAM;AACvD,YAAM,QAAS,KAA2B;AAC1C,UAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,UAAU,GAAG;AACtE,eAAO,KAAK,KAAK;AACjB;AAAA,MACF;AAAA,IACF;AACA,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,IACX,CAAC;AACD,WAAO,EAAE,OAAO,MAAM,OAAO;AAAA,EAC/B;AAEA,MAAI,YAAY,KAAM,QAAO,EAAE,OAAO,QAAQ,OAAO;AAErD,QAAM,SAAS,yBAAyB,WAAW;AACnD,MAAI,OAAO,OAAO;AAChB,WAAO,KAAK,OAAO,KAAK;AAAA,EAC1B,WAAW,OAAO,UAAU,OAAO,OAAO,SAAS,KAAK,OAAO,OAAO,WAAW,OAAO,QAAQ;AAC9F,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACA,SAAO;AAAA,IACL,OAAO,EAAE,QAAQ,UAAU,OAAO,OAAO;AAAA,IACzC;AAAA,EACF;AACF;AAEA,SAAS,sBACP,SACA,MACA,aACA,yBACA,SACmD;AACnD,QAAM,SAAgC,CAAC;AACvC,MAAI,WAAW,OAAO,YAAY,YAAY,aAAa,SAAS;AAClE,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAU,QAAiC,WAAW;AAAA,IACxD,CAAC;AACD,WAAO,EAAE,OAAO,MAAM,OAAO;AAAA,EAC/B;AAEA,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,kBAAkB,SAAS,aAAa,OAAO;AAAA,IACxD,KAAK;AACH,aAAO,sBAAsB,SAAS,aAAa,OAAO;AAAA,IAC5D,KAAK;AAAA,IACL,KAAK;AACH,UAAI,YAAY,QAAQ,mBAAmB,KAAM,QAAO,EAAE,OAAO,SAAS,OAAO;AACjF,aAAO,KAAK,EAAE,MAAM,iBAAiB,SAAS,yBAAyB,CAAC;AACxE,aAAO,EAAE,OAAO,MAAM,OAAO;AAAA,IAC/B,KAAK;AACH,UAAI,YAAY,QAAQ,OAAO,YAAY,UAAW,QAAO,EAAE,OAAO,SAAS,OAAO;AACtF,aAAO,KAAK,EAAE,MAAM,iBAAiB,SAAS,4BAA4B,CAAC;AAC3E,aAAO,EAAE,OAAO,MAAM,OAAO;AAAA,IAC/B,KAAK;AACH,UAAI,YAAY,QAAS,OAAO,YAAY,YAAY,OAAO,SAAS,OAAO,GAAI;AACjF,eAAO,EAAE,OAAO,SAAS,OAAO;AAAA,MAClC;AACA,aAAO,KAAK,EAAE,MAAM,iBAAiB,SAAS,4BAA4B,CAAC;AAC3E,aAAO;AAAA,QACL,OACE,OAAO,YAAY,YACnB,OAAO,YAAY,YACnB,OAAO,YAAY,YACf,UACA;AAAA,QACN;AAAA,MACF;AAAA,IACF,KAAK;AACH,UAAI,YAAY,QAAS,OAAO,YAAY,YAAY,OAAO,UAAU,OAAO,GAAI;AAClF,eAAO,EAAE,OAAO,SAAS,OAAO;AAAA,MAClC;AACA,aAAO,KAAK,EAAE,MAAM,iBAAiB,SAAS,6BAA6B,CAAC;AAC5E,aAAO;AAAA,QACL,OACE,OAAO,YAAY,YACnB,OAAO,YAAY,YACnB,OAAO,YAAY,YACf,UACA;AAAA,QACN;AAAA,MACF;AAAA,IACF,KAAK;AAAA,IACL,KAAK;AACH,UAAI,YAAY,QAAQ,OAAO,YAAY,SAAU,QAAO,EAAE,OAAO,SAAS,OAAO;AACrF,aAAO,KAAK,EAAE,MAAM,iBAAiB,SAAS,2BAA2B,CAAC;AAC1E,aAAO,EAAE,OAAO,MAAM,OAAO;AAAA,IAC/B,KAAK;AAAA,IACL,KAAK;AACH,UAAI,YAAY,QAAQ,MAAM,QAAQ,OAAO,EAAG,QAAO,EAAE,OAAO,SAAS,OAAO;AAChF,aAAO,KAAK,EAAE,MAAM,iBAAiB,SAAS,yBAAyB,CAAC;AACxE,aAAO,EAAE,OAAO,MAAM,OAAO;AAAA,IAC/B,KAAK;AAAA,IACL,KAAK;AAGH,UAAI,gBAAgB,QAAW;AAC7B,YAAI,OAAO,YAAY,YAAa,WAAW,OAAO,YAAY,YAAY,WAAW,SAAU;AACjG,iBAAO,kBAAkB,SAAS,aAAa,OAAO;AAAA,QACxD;AACA,YAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,iBAAO,sBAAsB,SAAS,aAAa,OAAO;AAAA,QAC5D;AAAA,MACF;AACA,UAAI,CAAC,wBAAyB,QAAO,EAAE,OAAO,SAAS,OAAO;AAC9D,UAAI,YAAY,KAAM,QAAO,EAAE,OAAO,MAAM,OAAO;AACnD,UAAI,OAAO,YAAY,SAAU,QAAO,EAAE,OAAO,SAAS,OAAO;AACjE,UACE,OAAO,YAAY,YACnB,OAAO,YAAY,aACnB,mBAAmB,MACnB;AACA,eAAO;AAAA,UACL,OAAO,mBAAmB,OAAO,QAAQ,YAAY,IAAI,OAAO,OAAO;AAAA,UACvE;AAAA,QACF;AAAA,MACF;AACA,UAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,YAAI;AACF,iBAAO,EAAE,OAAO,KAAK,UAAU,OAAO,GAAG,OAAO;AAAA,QAClD,QAAQ;AACN,iBAAO,KAAK;AAAA,YACV,MAAM;AAAA,YACN,SAAS;AAAA,UACX,CAAC;AACD,iBAAO,EAAE,OAAO,MAAM,OAAO;AAAA,QAC/B;AAAA,MACF;AACA,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AACD,aAAO,EAAE,OAAO,MAAM,OAAO;AAAA,EACjC;AACF;AAEA,SAAS,kBACP,KACA,OACwC;AACxC,QAAM,OAAO,KAAK;AAClB,MAAI,SAAS,YAAY,SAAS,aAAc,QAAO;AACvD,QAAM,UAAU,gCAAgC,KAAK,aAAa;AAClE,QAAM,UAAU,IAAI,IAAkC,QAAQ,IAAI,CAAC,UAAU,CAAC,MAAM,OAAO,KAAK,CAAC,CAAC;AAElG,MAAI,SAAS,UAAU;AACrB,QAAI,SAAS,QAAQ,OAAO,UAAU,YAAY,MAAM,KAAK,MAAM,GAAI,QAAO,CAAC;AAC/E,UAAM,OAAO,QAAQ,IAAI,KAAK;AAC9B,QAAI,CAAC,KAAM,QAAO,CAAC,EAAE,OAAO,OAAO,OAAO,OAAO,MAAM,CAAC;AACxD,WAAO;AAAA,MACL;AAAA,QACE;AAAA,QACA,OAAO,KAAK;AAAA,QACZ,WAAW,KAAK;AAAA,QAChB,WAAW,KAAK;AAAA,QAChB,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACnC,QAAM,MAAkC,CAAC;AACzC,aAAW,QAAQ,OAAO;AACxB,UAAM,IAAI,OAAO,SAAS,WAAW,OAAO,OAAO,IAAI;AACvD,UAAM,OAAO,QAAQ,IAAI,CAAC;AAC1B,QAAI,CAAC,MAAM;AACT,UAAI,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,MAAM,CAAC;AAC7C;AAAA,IACF;AACA,QAAI,KAAK;AAAA,MACP,OAAO;AAAA,MACP,OAAO,KAAK;AAAA,MACZ,WAAW,KAAK;AAAA,MAChB,WAAW,KAAK;AAAA,MAChB,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEO,SAAS,qBACd,SACoC;AACpC,QAAM,0BAA0B,QAAQ,2BAA2B;AACnE,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,OAAO,WAAW,QAAQ,MAAM;AACtC,SAAO,QAAQ,OAAO,IAAI,CAAC,KAAK,UAAU;AACxC,UAAM,UAAU,iBAAiB,KAAK,QAAQ,MAAM;AACpD,UAAM,cAAc,QAAQ,eAAe,KAAK;AAChD,UAAM,aAAa;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,SAAS,CAAC,GAAG,WAAW,MAAM;AAEpC,QAAI,QAAQ,QAAQ;AAClB,YAAM,SAAS,QAAQ,OAAO,UAAU,WAAW,KAAK;AACxD,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,SAAS,OAAO,MAAM,OAAO,IAAI,CAAC,UAAU,MAAM,OAAO,EAAE,KAAK,IAAI;AAAA,QACtE,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,MACL,IAAI,OAAO,WAAW;AAAA,MACtB,YAAY,WAAW;AAAA,MACvB,cAAc,WAAW;AAAA,MACzB;AAAA,MACA;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEO,SAAS,wBACd,MACA,SACqC;AACrC,QAAM,UAAU,SAAS,WAAW,CAAC;AACrC,QAAM,8BAA8B,yBAAyB,OAAO;AACpE,QAAM,sBAA8C;AAAA,IAClD,GAAG;AAAA,IACH,GAAI,SAAS,uBAAuB,CAAC;AAAA,EACvC;AAGA,aAAW,CAAC,OAAO,GAAG,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,UAAM,OAAO,KAAK;AAClB,QAAI,OAAO,SAAS,YAAa,CAAC,KAAK,WAAW,MAAM,KAAK,CAAC,KAAK,WAAW,UAAU,GAAI;AAC1F;AAAA,IACF;AACA,QAAI,oBAAoB,KAAK,EAAG;AAChC,UAAM,SAAS,eAAe,KAAK;AACnC,QAAI,MAAM,QAAQ,KAAK,MAAM,CAAC,GAAG;AAC/B,0BAAoB,KAAK,IAAI;AAAA,IAC/B;AAAA,EACF;AACA,QAAM,0BAA0B,SAAS,2BAA2B;AACpE,QAAM,UAAU,SAAS,WAAW;AACpC,QAAM,SAAS,OAAO,KAAK,IAAI;AAC/B,QAAM,iBAA6D,CAAC;AAEpE,aAAW,SAAS,QAAQ;AAC1B,UAAM,YAAY,MAAM,QAAQ,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,IAAI,CAAC;AAC9D,UAAM,cAAc,oBAAoB,KAAK;AAC7C,UAAM,eAAe,eAAe,MAAM,QAAQ,KAAK,WAAW,CAAC,IAAI,KAAK,WAAW,IAAI;AAC3F,mBAAe,KAAK,IAClB,UAAU,OACN,UAAU,IAAI,CAAC,SAAS;AAAA,MACtB,IAAI,OAAO,QAAQ,YAAY,OAAO,SAAS,GAAG;AAAA,MAClD,YAAY,OAAO,QAAQ,YAAY,OAAO,SAAS,GAAG,IAAI,MAAM;AAAA,MACpE,cAAc;AAAA,MACd;AAAA,MACA,QACE,OAAO,QAAQ,YAAY,OAAO,SAAS,GAAG,IAC1C,CAAC,IACD,CAAC,EAAE,MAAM,iBAAiB,SAAS,4BAA4B,CAAC;AAAA,IACxE,EAAE,IACF,qBAAqB;AAAA,MACnB,QAAQ;AAAA,MACR,QAAQ,QAAQ,KAAK;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACT;AAEA,QAAM,WAAW,gBAAgB,IAAI;AACrC,QAAM,OAA+B,CAAC;AACtC,QAAM,aAAwC,CAAC;AAC/C,QAAM,WAAqC,CAAC;AAC5C,WAAS,WAAW,GAAG,WAAW,UAAU,YAAY;AACtD,UAAM,MAA+B,CAAC;AACtC,eAAW,SAAS,QAAQ;AAC1B,YAAM,SAAS,eAAe,KAAK,IAAI,QAAQ;AAC/C,UAAI,KAAK,IAAI,QAAQ,cAAc;AACnC,YAAM,eAAe,kBAAkB,QAAQ,KAAK,GAAG,QAAQ,YAAY;AAC3E,UAAI,QAAQ;AACV,YAAI,OAAO,OAAO,SAAS,KAAM,gBAAgB,aAAa,SAAS,GAAI;AACzE,mBAAS,KAAK;AAAA,YACZ;AAAA,YACA;AAAA,YACA,IAAI,OAAO;AAAA,YACX,QAAQ,OAAO;AAAA,YACf;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AACA,UAAI,CAAC,UAAU,OAAO,OAAO,WAAW,EAAG;AAC3C,iBAAW,SAAS,OAAO,QAAQ;AACjC,mBAAW,KAAK,EAAE,GAAG,OAAO,UAAU,MAAM,CAAC;AAAA,MAC/C;AAAA,IACF;AACA,SAAK,KAAK,GAA2B;AAAA,EACvC;AAEA,QAAM,gBAAwD,CAAC;AAC/D,aAAW,QAAQ,UAAU;AAC3B,UAAM,QAAQ,KAAK,KAAK,QAAQ,GAAG;AACnC,QAAI,OAAO,UAAU,SAAU;AAC/B,kBAAc,GAAG,KAAK,IAAI,KAAK,KAAK,EAAE,IAAI;AAAA,EAC5C;AAEA,QAAM,QAAQ,SAAS,SAAS;AAChC,MAAI,UAAU,QAAQ;AACpB,WAAO,EAAE,MAAM,YAAY,UAAU,eAAe,qBAAqB,eAAe;AAAA,EAC1F;AACA,MAAI,UAAU,MAAM;AAClB,WAAO;AAAA,MACL,MAAM,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM;AAC7B,cAAM,MAAM,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC9C,cAAM,MAAM,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC9C,eAAO,MAAM;AAAA,MACf,CAAC;AAAA,MACD;AAAA,MACA;AAAA,MACA;AAAA,MACA,qBAAqB;AAAA,IACvB;AAAA,EACF;AACA,SAAO;AAAA,IACL,MAAM,qBAAqB,IAAI;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,IACA,qBAAqB;AAAA,EACvB;AACF;;;AEtqBA,SAAS,kCAAkC,MAAkD;AAC3F,QAAM,MAA8B,CAAC;AACrC,aAAW,SAAS,OAAO,KAAK,IAAI,GAAG;AACrC,QAAI,CAAC,MAAM,WAAW,cAAc,EAAG;AACvC,UAAM,YAAY,MAAM,MAAM,eAAe,MAAM;AACnD,QAAI,CAAC,UAAW;AAChB,QAAI,CAAC,MAAM,QAAQ,KAAK,SAAS,CAAC,EAAG;AACrC,QAAI,SAAS,IAAI;AAAA,EACnB;AACA,SAAO;AACT;AAEA,SAAS,+BACP,MACA,SACoC;AACpC,QAAM,MAA0C,EAAE,GAAI,WAAW,CAAC,EAAG;AACrE,QAAM,OAAO,OAAO,KAAK,IAAI;AAC7B,QAAM,kBAAkB,IAAI,IAAoB,KAAK,IAAI,CAAC,OAAO,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC;AAK9F,aAAW,SAAS,MAAM;AACxB,QAAI,CAAC,MAAM,WAAW,cAAc,EAAG;AACvC,QAAI,IAAI,KAAK,EAAG;AAChB,QAAI,KAAK,IAAI;AAAA,MACX,MAAM;AAAA,MACN,OAAO;AAAA,MACP,WAAW,gBAAgB,IAAI,KAAK;AAAA,IACtC;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,wBACP,gBAC2C;AAC3C,QAAM,SAAS,OAAO,KAAK,cAAc;AACzC,QAAM,WAAW,OAAO,OAAO,CAAC,KAAK,UAAU;AAC7C,UAAM,MAAM,eAAe,KAAK,GAAG,UAAU;AAC7C,WAAO,KAAK,IAAI,KAAK,GAAG;AAAA,EAC1B,GAAG,CAAC;AACJ,QAAM,OAAkD,CAAC;AACzD,WAAS,WAAW,GAAG,WAAW,UAAU,YAAY;AACtD,UAAM,MAA+B,CAAC;AACtC,eAAW,SAAS,QAAQ;AAC1B,UAAI,KAAK,IAAI,eAAe,KAAK,IAAI,QAAQ,KAAK;AAAA,IACpD;AACA,SAAK,KAAK,GAA8C;AAAA,EAC1D;AACA,SAAO;AACT;AAEA,SAAS,cAAc,KAA6C;AAClE,QAAM,SAAS,IAAI;AACnB,MAAI,CAAC,UAAU,OAAO,WAAW,YAAY,EAAE,gBAAgB,QAAS,QAAO;AAC/E,QAAM,QAAS,OAAoC;AACnD,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,QAAQ;AACvE;AAEA,SAAS,8BACP,MACA,mBAC2C;AAC3C,QAAM,OAAO,oBAAI,IAAuD;AACxE,aAAW,OAAO,MAAM;AACtB,UAAM,KAAK,cAAc,GAAG;AAC5B,QAAI,OAAO,KAAM;AACjB,UAAM,SAAS,KAAK,IAAI,EAAE;AAC1B,QAAI,OAAQ,QAAO,KAAK,GAAG;AAAA,QACtB,MAAK,IAAI,IAAI,CAAC,GAAG,CAAC;AAAA,EACzB;AACA,QAAM,MAAiD,CAAC;AACxD,aAAW,aAAa,mBAAmB;AACzC,UAAM,KAAK,OAAO,UAAU,OAAO,WAAW,UAAU,KAAK;AAC7D,QAAI,OAAO,KAAM;AACjB,UAAM,SAAS,KAAK,IAAI,EAAE;AAC1B,QAAI,CAAC,UAAU,OAAO,WAAW,EAAG;AACpC,UAAM,OAAO,OAAO,MAAM;AAC1B,QAAI,KAAM,KAAI,KAAK,IAAI;AAAA,EACzB;AAEA,aAAW,UAAU,KAAK,OAAO,GAAG;AAClC,QAAI,KAAK,GAAG,MAAM;AAAA,EACpB;AACA,SAAO;AACT;AAOO,SAAS,2BACd,MAC2C;AAC3C,SAAO,KAAK,IAAI,CAAC,QAAQ;AACvB,UAAM,MAA+B,CAAC;AACtC,eAAW,CAAC,OAAO,IAAI,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC/C,UAAI,QAAQ,OAAO,SAAS,YAAY,kBAAkB,MAAM;AAC9D,YAAI,KAAK,IAAK,KAAmC;AAAA,MACnD,OAAO;AACL,YAAI,KAAK,IAAI;AAAA,MACf;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AACH;AAGO,SAASC,iBAAgB,MAAyC;AACvE,QAAM,QAAQ,KAAK;AACnB,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM;AACvC,aAAW,OAAO,OAAO,KAAK,IAAI,GAAG;AACnC,UAAM,MAAM,KAAK,GAAG;AACpB,QAAI,MAAM,QAAQ,GAAG,EAAG,QAAO,IAAI;AAAA,EACrC;AACA,SAAO;AACT;AAKO,SAAS,4BACd,MACA,WACA,SACA,SACkB;AAClB,QAAM,QAAQA,iBAAgB,IAAI;AAClC,QAAM,IAAI,YAAY,SAAY,KAAK,IAAI,OAAO,OAAO,IAAI;AAC7D,QAAM,MAAwB,CAAC;AAC/B,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,MAA+B,CAAC;AACtC,eAAW,KAAK,WAAW;AACzB,YAAM,MAAM,KAAK,CAAC;AAClB,YAAM,MAAM,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,IAAI;AAC1C,UAAI,MAAM,MAAM;AACd,YAAI,CAAC,IAAI;AAAA,MACX,OAAO;AACL,YAAI,CAAC,IAAI,iBAAiB,KAAK,QAAQ,CAAC,CAAC;AAAA,MAC3C;AAAA,IACF;AACA,QAAI,KAAK,GAAqB;AAAA,EAChC;AACA,SAAO;AACT;AAGO,SAAS,gBACd,MACqB;AACrB,QAAM,QAAQ,KAAK;AACnB,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW,EAAG,QAAO,CAAC;AACzD,QAAM,OAAO,OAAO,KAAK,IAAI;AAC7B,QAAM,IAAI,MAAM;AAChB,QAAM,OAA4B,CAAC;AACnC,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,MAA+B,CAAC;AACtC,eAAW,KAAK,MAAM;AACpB,YAAM,MAAM,KAAK,CAAC;AAClB,UAAI,CAAC,IAAI,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,IAAI;AAAA,IACzC;AACA,SAAK,KAAK,GAAwB;AAAA,EACpC;AACA,SAAO;AACT;AAEA,SAASC,eAAc,KAA6C;AAClE,QAAM,IAAI,IAAI;AACd,MAAI,OAAO,MAAM,YAAY,CAAC,OAAO,MAAM,CAAC,EAAG,QAAO;AACtD,MAAI,OAAO,MAAM,YAAY,EAAE,KAAK,MAAM,IAAI;AAC5C,UAAM,IAAI,OAAO,CAAC;AAClB,QAAI,CAAC,OAAO,MAAM,CAAC,EAAG,QAAO;AAAA,EAC/B;AACA,SAAO;AACT;AAMO,SAASC,sBACd,MACqB;AACrB,QAAM,YAAY,KAAK,KAAK,CAAC,MAAMD,eAAc,CAA4B,MAAM,IAAI;AACvF,MAAI,CAAC,WAAW;AACd,WAAO,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM;AAC9B,YAAM,MAAM,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC9C,YAAM,MAAM,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC9C,aAAO,MAAM;AAAA,IACf,CAAC;AAAA,EACH;AACA,SAAO,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM;AAC9B,UAAM,KAAKA,eAAc,CAA4B;AACrD,UAAM,KAAKA,eAAc,CAA4B;AACrD,QAAI,OAAO,QAAQ,OAAO,QAAQ,OAAO,GAAI,QAAO,KAAK;AACzD,QAAI,OAAO,QAAQ,OAAO,KAAM,QAAO;AACvC,QAAI,OAAO,QAAQ,OAAO,KAAM,QAAO;AACvC,UAAM,MAAM,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC9C,UAAM,MAAM,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC9C,WAAO,MAAM;AAAA,EACf,CAAC;AACH;AAGO,SAAS,iBAAiB,MAA0B,OAAuC;AAChG,QAAM,QAAQ,KAAK;AACnB,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO;AAClC,QAAM,MAAM,MAAM,UAAU,CAAC,MAAM,MAAM,SAAU,OAAO,MAAM,YAAY,MAAM,OAAO,KAAK,CAAE;AAChG,SAAO,QAAQ,KAAK,OAAO;AAC7B;AAGO,SAAS,WACd,MACA,OAC0B;AAC1B,QAAM,QAAQ,KAAK;AACnB,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,QAAQ,KAAK,SAAS,MAAM,OAAQ,QAAO;AACxE,QAAM,OAAO,OAAO,KAAK,IAAI;AAC7B,QAAM,MAA+B,CAAC;AACtC,aAAW,KAAK,MAAM;AACpB,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,CAAC,IAAI,MAAM,QAAQ,GAAG,IAAI,IAAI,KAAK,IAAI;AAAA,EAC7C;AACA,SAAO;AACT;AAMA,eAAsB,cACpB,QACA,SACA,OACmC;AACnC,QAAM,OAAQ,MAAM,OAAO,WAAW,OAAO;AAC7C,QAAM,QAAQ,iBAAiB,MAAM,KAAK;AAC1C,MAAI,UAAU,KAAM,QAAO;AAC3B,SAAO,WAAc,MAAM,KAAK;AAClC;AAOO,SAAS,iCACd,MACA,SACqB;AACrB,QAAM,QAAQ,SAAS,SAAS;AAChC,MAAI,SAAS,WAAW;AACtB,UAAM,cAAc,QAAQ,cAAc,OAAO,CAAC,IAAI,QAAQ;AAC9D,UAAM,sBAAsB,+BAA+B,MAAM,SAAS,OAAO;AACjF,UAAM,sBAAsB;AAAA,MAC1B,GAAG,kCAAkC,IAAI;AAAA,MACzC,GAAI,YAAY,uBAAuB,CAAC;AAAA,IAC1C;AACA,UAAM,SAAS,wBAA2B,MAAM;AAAA,MAC9C,GAAG;AAAA,MACH,SAAS;AAAA,MACT;AAAA,MACA;AAAA,IACF,CAAC;AACD,YAAQ,oBAAoB,OAAO,UAAU;AAC7C,YAAQ,sBAAsB,OAAO,QAAQ;AAC7C,YAAQ,2BAA2B,OAAO,aAAa;AACvD,UAAM,cAAc,wBAAwB,OAAO,mBAAmB;AACtE,UAAM,kBACJ,UAAU,SACN,cACA,8BAA8B,aAAa,OAAO,IAA8C;AACtG,WAAO;AAAA,EACT;AAEA,MAAI;AACJ,MAAI,SAAS,SAAS;AACpB,UAAM,YAAY,OAAO,KAAK,IAAI;AAClC,WAAO,4BAA4B,MAAM,WAAW,QAAQ,OAAO;AAAA,EACrE,OAAO;AACL,WAAO,gBAAmB,IAAI;AAAA,EAChC;AAEA,MAAI,UAAU,OAAQ,QAAO;AAC7B,MAAI,UAAU,MAAM;AAClB,WAAO,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM;AAC9B,YAAM,MAAM,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC9C,YAAM,MAAM,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC9C,aAAO,MAAM;AAAA,IACf,CAAC;AAAA,EACH;AACA,SAAOC,sBAAqB,IAAI;AAClC;AAeA,eAAsB,oBACpB,QACA,SACA,SAC8B;AAC9B,QAAM,OAAQ,MAAM,OAAO,WAAW,OAAO;AAC7C,SAAO,iCAAoC,MAAM,OAAO;AAC1D;;;AC7VO,SAAS,wBACd,SACA,OACA,OACsB;AACtB,SAAO,CAAC,gBAAgB,SAAS,OAAO,KAAK;AAC/C;AAGO,SAAS,qBAAqB,SAAiB,QAAuD;AAC3G,SAAO,CAAC,aAAa,SAAS,MAAM,MAAM;AAC5C;AAGO,SAAS,wBAAwB,SAAiB,OAAqC;AAC5F,SAAO,CAAC,gBAAgB,SAAS,KAAK;AACxC;AAGO,SAAS,4BACd,SACA,QACA,eACsB;AACtB,SAAO,CAAC,oBAAoB,SAAS,QAAQ,aAAa;AAC5D;AAOO,SAAS,yBACd,SACA,QACA,QACsB;AACtB,QAAM,SAAS,gBAAgB,MAAM;AACrC,QAAM,MAAM,UAAU,IAAI,MAAqB,MAAM,EAAE,KAAK,IAAI;AAChE,SAAO,CAAC,iBAAiB,SAAS,KAAK,MAAM;AAC/C;AAGO,SAAS,4BAA4B,SAAiB,QAAwC;AACnG,SAAO,CAAC,oBAAoB,SAAS,MAAM;AAC7C;AAGO,SAAS,qBAAqB,SAAiB,OAAe,SAAwD;AAC3H,SAAO,CAAC,aAAa,SAAS,OAAO,OAAO;AAC9C;AAGO,SAAS,4BAA4B,SAAiB,OAAe,SAAwD;AAClI,SAAO,CAAC,oBAAoB,SAAS,OAAO,OAAO;AACrD;AAGO,SAAS,wBAAwB,SAAiB,OAAe,UAAwC;AAC9G,SAAO,CAAC,gBAAgB,SAAS,OAAO,QAAQ;AAClD;AAGO,SAAS,wBAAwB,SAAiB,OAAe,SAAwD;AAC9H,SAAO,CAAC,gBAAgB,SAAS,OAAO,OAAO;AACjD;AAGO,SAAS,wBAAwB,SAAiB,OAAqC;AAC5F,SAAO,CAAC,gBAAgB,SAAS,KAAK;AACxC;AAGO,SAAS,oBAAoB,SAAiB,WAA0D;AAC7G,SAAO,CAAC,YAAY,SAAS,SAAS;AACxC;AAGO,SAAS,uBAAuB,SAAiB,YAA0C;AAChG,SAAO,CAAC,eAAe,SAAS,UAAU;AAC5C;AAGO,SAAS,uBAAuB,SAAuC;AAC5E,SAAO,CAAC,eAAe,OAAO;AAChC;AAGO,SAAS,0BACd,SACA,YACA,SACsB;AACtB,SAAO,UAAU,CAAC,kBAAkB,SAAS,YAAY,OAAO,IAAI,CAAC,kBAAkB,SAAS,UAAU;AAC5G;AAGO,SAAS,4BACd,SACA,QACA,cACsB;AACtB,SAAO,CAAC,oBAAoB,SAAS,QAAQ,YAAY;AAC3D;AAGO,SAAS,2BAA2B,MAAqD;AAC9F,SAAO,CAAC,mBAAmB,IAAI;AACjC;AAEA,SAAS,gBAAgB,QAA2C;AAClE,aAAW,OAAO,OAAO,OAAO,MAAM,EAAG,KAAI,MAAM,QAAQ,GAAG,EAAG,QAAO,IAAI;AAC5E,SAAO;AACT;;;AC1GA,IAAM,wBAAwB,oBAAI,IAAI,CAAC,OAAO,CAAC;AAE/C,SAAS,8BAA8B,SAAyB;AAC9D,SAAO,QAAQ,KAAK,EAAE,YAAY,EAAE,QAAQ,QAAQ,EAAE;AACxD;AAUO,SAAS,mBACd,OACA,KACA,SACS;AACT,QAAM,YAAY,SAAS,aAAa;AACxC,QAAM,sBAAsB,SAAS,uBAAuB;AAC5D,QAAM,wBAAwB,SAAS,yBAAyB;AAChE,QAAM,oBAAoB,SAAS,qBAAqB;AAExD,MAAI,aAAa,UAAU,KAAM,QAAO;AACxC,MAAI,qBAAqB,UAAU,aAAc,QAAO;AACxD,MAAI,uBAAuB,MAAM,WAAW,cAAc,EAAG,QAAO;AAEpE,MAAI,uBAAuB;AACzB,UAAM,UAAU,OAAO,KAAK,YAAY,WAAW,8BAA8B,IAAI,OAAO,IAAI;AAChG,QAAI,WAAW,sBAAsB,IAAI,OAAO,EAAG,QAAO;AAC1D,QAAI,QAAQ,WAAW,OAAO,EAAG,QAAO;AAAA,EAC1C;AAEA,SAAO;AACT;;;AChDO,SAAS,sBAAsB,WAAoB,gBAA0C;AAClG,MAAI,eAAe,SAAS,EAAG,QAAO,YAAY,aAAa;AAC/D,SAAO,YAAY,eAAe;AACpC;AAGO,SAAS,wBAAwB,KAA2C;AACjF,MAAI,IAAI,YAAa,QAAO,IAAI;AAChC,QAAM,IAAI,IAAI,SAAS,KAAK,KAAK;AACjC,MAAI,EAAE,SAAS,EAAG,QAAO,IAAI,cAAc,OAAO,aAAa;AAC/D,SAAO,IAAI,cAAc,OAAO,eAAe;AACjD;AAGO,SAAS,sBAAsB,OAAyB;AAC7D,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,YAAY,OAAO,UAAU,UAAW,QAAO;AACjG,MAAI;AACF,WAAO,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC;AAAA,EACzC,QAAQ;AACN,WAAO,OAAO,KAAK;AAAA,EACrB;AACF;;;ACCA,IAAM,sBAAsB;AAE5B,SAAS,YAAY,OAAkC,KAAa,UAAsC;AACxG,QAAM,MAAM,MAAM,GAAG;AACrB,MAAI,CAAC,MAAM,QAAQ,GAAG,EAAG,QAAO;AAChC,QAAM,IAAI,IAAI,QAAQ;AACtB,MAAI,MAAM,QAAQ,MAAM,OAAW,QAAO;AAC1C,MAAI,OAAO,MAAM,SAAU,QAAO;AAClC,MAAI,OAAO,MAAM,YAAY,OAAO,MAAM,UAAW,QAAO,OAAO,CAAC;AACpE,SAAO;AACT;AAEA,SAAS,YAAY,OAAkC,KAAa,UAAsC;AACxG,QAAM,MAAM,MAAM,GAAG;AACrB,MAAI,CAAC,MAAM,QAAQ,GAAG,EAAG,QAAO;AAChC,QAAM,IAAI,IAAI,QAAQ;AACtB,MAAI,OAAO,MAAM,YAAY,CAAC,OAAO,MAAM,CAAC,EAAG,QAAO;AACtD,MAAI,OAAO,MAAM,YAAY,EAAE,KAAK,MAAM,IAAI;AAC5C,UAAM,IAAI,OAAO,CAAC;AAClB,QAAI,CAAC,OAAO,MAAM,CAAC,EAAG,QAAO;AAAA,EAC/B;AACA,SAAO;AACT;AAEA,SAAS,eAAe,MAAkE;AACxF,MAAI,CAAC,KAAM,QAAO,CAAC;AACnB,QAAM,MAA0B,CAAC;AACjC,MAAI,KAAK,WAAW,OAAW,KAAI,SAAS,KAAK;AACjD,MAAI,KAAK,KAAM,KAAI,OAAO,KAAK;AAC/B,MAAI,KAAK,MAAO,KAAI,QAAQ,KAAK;AACjC,MAAI,KAAK,cAAc,OAAW,KAAI,YAAY,KAAK;AACvD,MAAI,KAAK,UAAW,KAAI,YAAY;AACpC,QAAM,aAAa,KAAK,SAAS,KAAK,KAAK;AAC3C,MAAI,cAAc,sBAAsB,QAAQ,KAAK,SAAS,GAAG,UAAU;AAC3E,MAAI,YAAY;AACd,QAAI,UACF,WAAW,SAAS,sBAAsB,GAAG,WAAW,MAAM,GAAG,mBAAmB,CAAC,QAAQ;AAAA,EACjG;AACA,MAAI,KAAK,YAAa,KAAI,cAAc,KAAK;AAC7C,MAAI,KAAK,iBAAiB,OAAO,KAAK,KAAK,aAAa,EAAE,SAAS,GAAG;AACpE,QAAI,gBAAgB,KAAK;AAAA,EAC3B;AACA,MAAI,KAAK,kBAAkB,OAAW,KAAI,gBAAgB,KAAK;AAC/D,MAAI,KAAK,kBAAkB,OAAW,KAAI,gBAAgB,KAAK;AAC/D,SAAO;AACT;AAEA,eAAsB,0BACpB,QAC+D;AAC/D,QAAM,UAAU,oBAAI,IAAqD;AACzE,MAAI;AACF,UAAM,SAAS,MAAM,OAAO,WAAW,eAAe;AACtD,UAAM,UAAU,MAAM,OAAO,WAAW,sBAAsB;AAC9D,UAAM,WAAW,OAAO;AACxB,UAAM,mBAAmB,OAAO;AAChC,QAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,CAAC,MAAM,QAAQ,gBAAgB,EAAG,QAAO;AAEzE,UAAM,sBAAsB,oBAAI,IAAoB;AACpD,aAAS,IAAI,GAAG,IAAI,iBAAiB,QAAQ,KAAK;AAChD,YAAM,MAAM,SAAS,CAAC;AACtB,YAAM,MAAM,0BAA0B,iBAAiB,CAAC,CAAC;AACzD,UAAI,OAAO,QAAQ,YAAY,QAAQ,OAAW,qBAAoB,IAAI,KAAK,GAAG;AAAA,IACpF;AAEA,UAAM,YAAY,QAAQ;AAC1B,UAAM,SAAS,QAAQ;AACvB,UAAM,YAAY,QAAQ;AAC1B,QACE,CAAC,MAAM,QAAQ,SAAS,KACxB,CAAC,MAAM,QAAQ,MAAM,KACrB,CAAC,MAAM,QAAQ,SAAS,KACxB,UAAU,WAAW,OAAO,UAC5B,OAAO,WAAW,UAAU,QAC5B;AACA,aAAO;AAAA,IACT;AAEA,UAAM,IAAI,UAAU;AACpB,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,YAAM,cAAc,0BAA0B,UAAU,CAAC,CAAC;AAC1D,YAAM,SAAS,0BAA0B,UAAU,CAAC,CAAC;AACrD,YAAM,QAAQ,OAAO,CAAC;AACtB,UAAI,gBAAgB,UAAa,WAAW,UAAa,OAAO,UAAU,SAAU;AACpF,YAAM,UAAU,oBAAoB,IAAI,WAAW;AACnD,UAAI,CAAC,QAAS;AAEd,UAAI,SAAS,QAAQ,IAAI,OAAO;AAChC,UAAI,CAAC,QAAQ;AACX,iBAAS,oBAAI,IAAI;AACjB,gBAAQ,IAAI,SAAS,MAAM;AAAA,MAC7B;AAEA,YAAM,YAAY,YAAY,SAAS,aAAa,CAAC;AACrD,YAAM,eAAe,QAAQ;AAC7B,YAAM,YAAY,MAAM,QAAQ,YAAY,IAAI,QAAQ,aAAa,CAAC,CAAC,IAAI;AAE3E,YAAM,QAAQ,QAAQ;AACtB,YAAM,gBACJ,MAAM,QAAQ,KAAK,KAAK,IAAI,MAAM,SAAS,4BAA4B,MAAM,CAAC,CAAC,IAAI;AACrF,YAAM,gBAAgB;AAAA,QACpB,MAAM,QAAQ,QAAQ,UAAU,IAAI,QAAQ,WAAW,CAAC,IAAI;AAAA,MAC9D;AACA,YAAM,gBAAgB;AAAA,QACpB,MAAM,QAAQ,QAAQ,UAAU,IAAI,QAAQ,WAAW,CAAC,IAAI;AAAA,MAC9D;AAEA,aAAO,IAAI,OAAO;AAAA,QAChB;AAAA,QACA,MAAM,YAAY,SAAS,QAAQ,CAAC;AAAA,QACpC,OAAO,YAAY,SAAS,SAAS,CAAC;AAAA,QACtC,WAAW,cAAc,SAAY,YAAY;AAAA,QACjD;AAAA,QACA,SAAS,YAAY,SAAS,WAAW,CAAC;AAAA,QAC1C,aAAa,YAAY,SAAS,eAAe,CAAC,KAAK,YAAY,SAAS,SAAS,CAAC;AAAA,QACtF;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAEO,SAAS,iBACd,MACA,WACU;AACV,QAAM,OAAO,OAAO,KAAK,IAAI,EAAE,OAAO,CAAC,MAAM,MAAM,QAAQ,KAAK,CAAC,CAAC,CAAC;AACnE,OAAK,KAAK,CAAC,GAAG,MAAM;AAClB,UAAM,KAAK,UAAU,IAAI,CAAC,GAAG;AAC7B,UAAM,KAAK,UAAU,IAAI,CAAC,GAAG;AAC7B,QAAI,OAAO,UAAa,OAAO,UAAa,OAAO,GAAI,QAAO,KAAK;AACnE,QAAI,OAAO,UAAa,OAAO,OAAW,QAAO;AACjD,QAAI,OAAO,UAAa,OAAO,OAAW,QAAO;AACjD,WAAO,EAAE,cAAc,CAAC;AAAA,EAC1B,CAAC;AACD,SAAO;AACT;AAGO,SAAS,gCACd,MACA,SACoC;AACpC,QAAM,YAAY,iBAAiB,MAAM,OAAO;AAChD,QAAM,UAA8C,CAAC;AACrD,aAAW,SAAS,WAAW;AAC7B,UAAM,MAAM,KAAK,KAAK;AACtB,QAAI,CAAC,MAAM,QAAQ,GAAG,EAAG;AACzB,UAAM,OAAO,QAAQ,IAAI,KAAK;AAC9B,YAAQ,KAAK,IAAI,eAAe,IAAI;AAAA,EACtC;AACA,SAAO;AACT;AAEA,SAAS,uBAAuB,aAA4D;AAC1F,MAAI,gBAAgB,MAAO,QAAO;AAClC,MAAI,gBAAgB,UAAW,QAAO;AACtC,SAAO;AACT;AAsBA,eAAsB,+BACpB,QACA,SAC+B;AAC/B,QAAM,yBAAyB,SAAS,0BAA0B;AAClE,QAAM,cAAc,SAAS,eAAe;AAC5C,QAAM,iBAAiB,SAAS,kBAAkB;AAClD,QAAM,UAAU,uBAAuB,WAAW;AAElD,QAAM,cAAc,MAAM,0BAA0B,MAAM;AAE1D,MAAI;AACJ,MAAI;AACF,cAAU,OAAO,MAAM,QAAQ,QAAQ,OAAO,WAAW,CAAC,CAAC;AAAA,EAC7D,QAAQ;AACN,cAAU;AAAA,EACZ;AAEA,QAAM,cAAc,MAAM,QAAQ,QAAQ,OAAO,WAAW,CAAC;AAC7D,QAAM,WAAW,MAAM,QAAQ,WAAW,IAAI,CAAC,GAAG,WAAW,IAAI,CAAC;AAElE,QAAM,SAA4C,CAAC;AAEnD,aAAW,WAAW,UAAU;AAC9B,UAAM,WAAW,CAAC,0BAA0B,QAAQ,WAAW,QAAQ;AACvE,QAAI,UAAU;AACZ,aAAO,OAAO,IAAI;AAAA,QAChB,UAAU;AAAA,QACV,aAAa;AAAA,QACb,mBACE;AAAA,QACF,SAAS,CAAC;AAAA,MACZ;AACA;AAAA,IACF;AAEA,QAAI;AACF,YAAM,OAAQ,MAAM,OAAO,WAAW,OAAO;AAC7C,YAAM,WAAWC,iBAAgB,IAAI;AACrC,YAAM,UAAU,YAAY,IAAI,OAAO,KAAK,oBAAI,IAAwC;AACxF,YAAM,YAAY,iBAAiB,MAAM,OAAO;AAChD,YAAM,UAAU,gCAAgC,MAAM,OAAO;AAE7D,YAAM,QAA2B,EAAE,SAAS,SAAS;AACrD,UAAI,gBAAgB,QAAQ;AAC1B,cAAM,OAAO,4BAA4B,MAAM,WAAW,OAAO;AAAA,MACnE,WAAW,gBAAgB,WAAW;AACpC,cAAM,OAAO,4BAA4B,MAAM,WAAW,SAAS,cAAc;AAAA,MACnF;AACA,aAAO,OAAO,IAAI;AAAA,IACpB,SAAS,KAAK;AACZ,aAAO,OAAO,IAAI;AAAA,QAChB,UAAU;AAAA,QACV,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,QACtD,SAAS,CAAC;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAEA,QAAM,MAA4B;AAAA,IAChC,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC;AAAA,IACA,MAAM;AAAA,IACN;AAAA,EACF;AACA,MAAI,SAAS,WAAW,UAAa,QAAQ,WAAW,IAAI;AAC1D,QAAI,SAAS,QAAQ;AAAA,EACvB;AACA,SAAO;AACT;;;AChRO,SAAS,2BAAwD,OAA2C;AACjH,SAAO,EAAE,GAAG,OAAO,MAAM,MAAM,QAAQ,CAAC,EAAE;AAC5C;AAGO,SAAS,8BAA8D,KAAW;AACvF,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QAAQ,OAAO;AAAA,MACb,OAAO,QAAQ,IAAI,MAAM,EAAE,IAAI,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,2BAA2B,CAAC,CAAC,CAAC;AAAA,IAC3F;AAAA,EACF;AACF;AASO,SAAS,wBACd,KACA,SACsB;AACtB,QAAM,QAAQ,QAAQ,kBAAkB;AACxC,QAAM,SAAS,OAAO;AAAA,IACpB,OAAO,QAAQ,IAAI,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM;AAC3C,UAAI,QAAQ,gBAAgB,QAAQ;AAClC,cAAM,EAAE,MAAM,IAAI,GAAG,KAAK,IAAI;AAC9B,eAAO,CAAC,KAAK,IAAI;AAAA,MACnB;AACA,UAAI,QAAQ,gBAAgB,WAAW;AACrC,cAAM,IAAI,EAAE,QAAQ,CAAC;AACrB,eAAO,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,CAAC;AAAA,MAChD;AACA,aAAO,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,EAAE,KAAK,CAAC;AAAA,IACrC,CAAC;AAAA,EACH;AACA,SAAO,EAAE,GAAG,KAAK,OAAO;AAC1B;;;ACTA,SAAS,aAAa,OAAoD;AACxE,SAAO,OAAO,UAAU,WAAW,EAAE,MAAM,MAAM,IAAI;AACvD;AASO,SAAS,uBACd,MACA,UAC8B;AAC9B,QAAM,UAAoB,CAAC;AAC3B,QAAM,iBAA2B,CAAC;AAClC,MAAI,CAAC,KAAM,QAAO,EAAE,IAAI,MAAM,SAAS,OAAO,SAAS,eAAe;AAEtE,QAAM,IAAI,YAAY,CAAC;AACvB,aAAW,OAAO,MAAM;AACtB,UAAM,MAAM,aAAa,GAAG;AAC5B,QAAI,IAAI,SAAU;AAClB,UAAM,QAAQ,EAAE,IAAI,IAAI;AACxB,QAAI,IAAI,eAAe;AACrB,UAAI,UAAU,QAAW;AACvB,gBAAQ,KAAK,IAAI,IAAI;AAAA,MACvB,WAAW,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW,GAAG;AACtD,uBAAe,KAAK,IAAI,IAAI;AAAA,MAC9B;AAAA,IACF,OAAO;AACL,UAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GAAI,SAAQ,KAAK,IAAI,IAAI;AAAA,IAClF;AAAA,EACF;AACA,SAAO;AAAA,IACL,IAAI,QAAQ,WAAW,KAAK,eAAe,WAAW;AAAA,IACtD,SAAS;AAAA,IACT;AAAA,IACA;AAAA,EACF;AACF;AAGO,IAAM,6BAA2D;AAAA,EACtE,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,SAAS,CAAC;AAAA,EACV,gBAAgB,CAAC;AACnB;;;AC1EO,IAAM,cAAmD;AAAA,EAC9D,MAAM;AAAA,EACN,cAAc;AAAA,EACd,MAAM;AACR;AAEA,IAAM,sBAAsD,CAAC,QAAQ,cAAc,MAAM;AAGlF,SAAS,yBACd,KAC4B;AAC5B,MAAI,CAAC,IAAK,QAAO;AACjB,SAAQ,oBAA0C,SAAS,GAAG,IACzD,MACD;AACN;AAGO,SAAS,mBACd,SACA,UACS;AACT,SAAO,YAAY,OAAO,KAAK,YAAY,QAAQ;AACrD;AAGO,SAAS,sBAAsB,OAAoC;AACxE,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;AAEO,SAAS,gCACd,UACA,UACQ;AACR,QAAM,OAAO,sBAAsB,QAAQ;AAC3C,SAAO,iCAAiC,IAAI;AAC9C;;;AC5BO,IAAM,kBAAkB;AAExB,SAAS,eAAe,SAA2C;AACxE,SAAQ,UAAU;AACpB;AA6EO,IAAM,0BAAyD;AAAA,EACpE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAyHO,SAAS,uBAA4C;AAC1D,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,WAAW,EAAE,OAAO,OAAO;AAAA,IAC3B,MAAM,EAAE,OAAO,aAAa,eAAe,MAAM,aAAa,EAAE;AAAA,IAChE,OAAO,EAAE,OAAO,WAAW,UAAU,aAAa;AAAA,IAClD,QAAQ,EAAE,UAAU,EAAE,OAAO,eAAe,EAAE;AAAA,IAC9C,MAAM;AAAA,MACJ,QAAQ,EAAE,OAAO,OAAO;AAAA,MACxB,SAAS,EAAE,OAAO,OAAO;AAAA,MACzB,SAAS,EAAE,OAAO,OAAO;AAAA,MACzB,WAAW,EAAE,OAAO,OAAO;AAAA,MAC3B,cAAc,EAAE,OAAO,UAAU;AAAA,IACnC;AAAA,EACF;AACF;;;AC/GO,SAAS,mBACd,QACiE;AACjE,SAAO,gBAAgB,UAAU,OAAO,OAAO,eAAe;AAChE;;;AC5EO,IAAM,kBAAN,MAAsB;AAAA,EAQ3B,YAAY,UAA6B,YAA6B;AAJtE;AAAA,SAAQ,WAAW,oBAAI,IAAwC;AAE/D;AAAA,SAAQ,mBAAkC;AAGxC,SAAK,WAAW;AAChB,SAAK,oBAAoB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAU,UAA6B,cAAqC;AAC1E,SAAK,WAAW;AAChB,SAAK,oBAAoB;AACzB,SAAK,SAAS,MAAM;AACpB,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA,EAGA,eAAe,MAA6B;AAC1C,QAAI,QAAQ,KAAK,kBAAmB;AACpC,SAAK,oBAAoB;AAEzB,eAAW,CAAC,KAAK,CAAC,KAAK,KAAK,UAAU;AACpC,UAAI,EAAE,aAAa,KAAM,MAAK,SAAS,OAAO,GAAG;AAAA,IACnD;AACA,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA,EAGA,QAAc;AACZ,SAAK,SAAS,MAAM;AACpB,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA,EAGA,eAA8C;AAC5C,WAAO,CAAC,GAAG,KAAK,SAAS,KAAK,CAAC;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,OAAO,OAAuC;AAC5C,QAAI,MAAM,aAAa,KAAK,mBAAmB;AAC7C,aAAO,EAAE,MAAM,aAAa,QAAQ,mBAAmB;AAAA,IACzD;AACA,QAAI,MAAM,aAAa,KAAK,mBAAmB;AAC7C,WAAK,eAAe,MAAM,UAAU;AAAA,IACtC;AACA,SAAK,SAAS,IAAI,MAAM,QAAQ,KAAK;AAErC,UAAM,WAAW,KAAK,QAAQ;AAC9B,QAAI,aAAa,KAAM,QAAO,EAAE,MAAM,gBAAgB;AAEtD,UAAM,OAAO;AAAA,MACX,SAAS;AAAA,MACT,SAAS,UAAU;AAAA,MACnB,SAAS;AAAA,IACX;AACA,QAAI,SAAS,KAAK,kBAAkB;AAClC,aAAO,EAAE,MAAM,aAAa,QAAQ,oBAAoB;AAAA,IAC1D;AACA,SAAK,mBAAmB;AACxB,WAAO,EAAE,MAAM,YAAY,OAAO,SAAS;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAA0B;AACxB,UAAM,WAAW,KAAK,QAAQ;AAC9B,QAAI,aAAa,KAAM,QAAO,EAAE,MAAM,gBAAgB;AACtD,WAAO,EAAE,MAAM,YAAY,OAAO,SAAS;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,UAAgE;AACtE,QAAI,KAAK,SAAS,SAAS,EAAG,QAAO;AAErC,UAAM,SAA+B,CAAC;AACtC,QAAI,mBAAmB;AACvB,UAAM,eAAqC,CAAC;AAE5C,eAAW,OAAO,CAAC,GAAG,uBAAuB,EAAE,QAAQ,GAAG;AACxD,YAAM,IAAI,KAAK,SAAS,IAAI,GAAG;AAC/B,UAAI,CAAC,EAAG;AACR,mBAAa,KAAK,GAAG;AACrB,UAAI,EAAE,eAAe,iBAAkB,oBAAmB,EAAE;AAC5D,UAAI,EAAE,YAAY,KAAM;AACxB,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,EAAE,OAAO,GAAG;AAC9C,eAAO,CAAC,IAAI;AAAA,MACd;AAAA,IACF;AAEA,QAAI,aAAa,WAAW,EAAG,QAAO;AAEtC,UAAM,aAAa,uBAAuB,KAAK,UAAU,MAAM;AAC/D,UAAM,SACJ,aAAa,WAAW,IAAK,aAAa,CAAC,IAA2B;AAExE,QAAI,WAAW,IAAI;AACjB,aAAO;AAAA,QACL,OAAO;AAAA,QACP,UAAU,KAAK;AAAA,QACf,UAAU;AAAA,QACV;AAAA,QACA,cAAc;AAAA,MAChB;AAAA,IACF;AAEA,WAAO;AAAA,MACL,OAAO;AAAA,MACP,UAAU,KAAK;AAAA,MACf,UAAU;AAAA,MACV,SAAS,WAAW;AAAA,MACpB,gBAAgB,WAAW;AAAA,MAC3B;AAAA,MACA,cAAc;AAAA,IAChB;AAAA,EACF;AACF;AAUO,SAAS,mBACd,UACA,IACA,QACQ;AACR,QAAM,OAAO,OAAO,KAAK,QAAQ,EAAE,KAAK;AACxC,QAAM,OAAO,KAAK,IAAI,CAAC,MAAM;AAC3B,UAAM,IAAI,SAAS,CAAC;AACpB,QAAI,MAAM,QAAQ,CAAC,EAAG,QAAO,GAAG,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC;AACjD,WAAO,GAAG,CAAC,IAAI,KAAK,EAAE;AAAA,EACxB,CAAC,EAAE,KAAK,GAAG;AACX,SAAO,GAAG,KAAK,OAAO,IAAI,KAAK,MAAM,KAAK,IAAI;AAChD;;;AC9KO,SAAS,uBAA4C;AAC1D,SAAO,EAAE,UAAU,KAAK;AAC1B;AAaO,IAAM,yBAAwC;AAAA,EACnD,kBAAkB;AAAA,EAClB,iBAAiB;AACnB;AAMO,SAAS,aACd,UACA,QACA,KACA,SAAwB,wBACH;AAErB,MAAI,mBAAmB,MAAM,KAAK,OAAO,aAAa,SAAS,YAAY;AACzE,WAAO;AAAA,EACT;AAEA,UAAQ,OAAO,MAAM;AAAA;AAAA,IAEnB,KAAK;AACH,aAAO,kBAAkB,UAAU,OAAO,IAAI;AAAA,IAChD,KAAK;AACH,aAAO,iBAAiB,UAAU,OAAO,QAAQ;AAAA,IACnD,KAAK;AACH,aAAO,sBAAsB,UAAU,OAAO,IAAI;AAAA,IACpD,KAAK;AACH,aAAO,gBAAgB,UAAU;AAAA,QAC/B,MAAM;AAAA,QACN,UAAU,OAAO;AAAA,MACnB,GAAG,OAAO,IAAI;AAAA,IAChB,KAAK;AACH,aAAO,gBAAgB,UAAU,EAAE,MAAM,eAAe,GAAG,OAAO,IAAI;AAAA,IACxE,KAAK;AACH,aAAO,qBAAqB,UAAU,OAAO,QAAQ,OAAO,IAAI;AAAA,IAClE,KAAK;AACH,aAAO,uBAAuB,UAAU,OAAO,QAAQ,OAAO,cAAc,OAAO,IAAI;AAAA,IACzF,KAAK;AACH,aAAO,gBAAgB,UAAU,OAAO,QAAQ,OAAO,IAAI;AAAA,IAC7D,KAAK;AACH,aAAO,gBAAgB,UAAU,OAAO,QAAQ,OAAO,IAAI;AAAA,IAC7D,KAAK;AACH,aAAO,kBAAkB,UAAU,OAAO,OAAO,OAAO,IAAI;AAAA;AAAA,IAG9D,KAAK;AAAA,IACL,KAAK;AACH,aAAO,kBAAkB,UAAU,OAAO,IAAI;AAAA,IAChD,KAAK;AAAA,IACL,KAAK;AACH,aAAO,kBAAkB,UAAU,OAAO,MAAM,MAAM;AAAA;AAAA,IAGxD,KAAK;AACH,aAAO,qBAAqB,UAAU,GAAG;AAAA;AAAA,IAG3C,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO,cAAc,UAAU,QAAQ,GAAG;AAAA;AAAA,IAG5C,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO,aAAa,UAAU,MAAM;AAAA,IACtC,KAAK;AACH,aAAO,WAAW,UAAU;AAAA,QAC1B,GAAG,SAAS;AAAA,QACZ,cAAc,EAAE,OAAO,SAAS,SAAS,OAAO,SAAS,YAAY,MAAM;AAAA,MAC7E,CAAC;AAAA,IACH,KAAK;AACH,UAAI,SAAS,KAAK,aAAa,UAAU,QAAS,QAAO;AACzD,aAAO,WAAW,UAAU;AAAA,QAC1B,GAAG,SAAS;AAAA,QACZ,cAAc,EAAE,GAAG,SAAS,KAAK,cAAc,YAAY,KAAK;AAAA,MAClE,CAAC;AAAA,IACH,KAAK;AACH,aAAO,WAAW,UAAU;AAAA,QAC1B,GAAG,SAAS;AAAA,QACZ,cAAc,EAAE,OAAO,WAAW,SAAS,OAAO,SAAS,SAAS,OAAO,KAAK;AAAA,MAClF,CAAC;AAAA,IAEH,SAAS;AAEP,YAAM,cAAqB;AAC3B,WAAK;AACL,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAMA,SAAS,kBAAkB,UAA+B,MAAmC;AAC3F,MAAI,SAAS,UAAU,UAAU,OAAQ,QAAO;AAChD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,WAAW,EAAE,OAAO,aAAa,UAAU,GAAG,aAAa,KAAK;AAAA,EAClE;AACF;AAEA,SAAS,iBAAiB,UAA+B,UAAuC;AAC9F,MAAI,SAAS,UAAU,UAAU,YAAa,QAAO;AACrD,MAAI,aAAa,SAAS,UAAU,SAAU,QAAO;AACrD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,WAAW,EAAE,GAAG,SAAS,WAAW,SAAS;AAAA,EAC/C;AACF;AAEA,SAAS,sBACP,UACA,MACqB;AACrB,MAAI,SAAS,UAAU,UAAU,eAAe,SAAS,UAAU,UAAU,QAAQ;AACnF,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,WAAW;AAAA,MACT,OAAO;AAAA,MACP,QAAQ,SAAS,MAAM;AAAA,MACvB,aAAa;AAAA,IACf;AAAA,EACF;AACF;AAEA,SAAS,qBACP,UACA,QACA,MACqB;AAGrB,MAAI,SAAS,UAAU,UAAU,aAAc,QAAO;AACtD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,OAAO,EAAE,OAAO,WAAW,UAAU,OAAO;AAAA,IAC5C,WACE,SAAS,UAAU,UAAU,WACzB,SAAS,YACT,EAAE,OAAO,eAAe,QAAQ,aAAa,KAAK;AAAA,EAC1D;AACF;AAEA,SAAS,cAAc,UAAoD;AACzE,SAAO,SAAS,MAAM;AACxB;AAEA,SAAS,kBACP,UACA,OACA,OACqB;AACrB,MAAI,SAAS,UAAU,UAAU,SAAU,QAAO;AAElD,QAAM,WAAW,cAAc,QAAQ;AAEvC,MAAI,mBAAmB,OAAO,QAAQ,GAAG;AACvC,UAAM,gBACJ,SAAS,MAAM,UAAU,YAAY,SAAS,MAAM,QAAQ;AAC9D,UAAM,UACJ,kBAAkB,QAAQ,YAAY,KAAK,IAAI,YAAY,aAAa;AAC1E,UAAMC,aAAY;AAAA,MAChB,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,QACE,SAAS,MAAM,UAAU,aACzB,SAAS,MAAM,UAAUA,WAAU,SACnC,SAAS,MAAM,aAAaA,WAAU,YACtC,SAAS,MAAM,YAAYA,WAAU,SACrC;AACA,aAAO;AAAA,IACT;AACA,WAAO,EAAE,GAAG,UAAU,OAAOA,WAAU;AAAA,EACzC;AAEA,QAAM,UAAU,gCAAgC,UAAU,KAAK;AAC/D,QAAM,YAAY,EAAE,OAAO,UAAmB,UAAU,QAAQ;AAChE,MACE,SAAS,MAAM,UAAU,YACzB,SAAS,MAAM,aAAa,UAAU,YACtC,SAAS,MAAM,YAAY,UAAU,SACrC;AACA,WAAO;AAAA,EACT;AACA,SAAO,EAAE,GAAG,UAAU,OAAO,UAAU;AACzC;AAEA,SAAS,uBACP,UACA,QACA,cACA,MACqB;AACrB,MAAI,SAAS,UAAU,UAAU,aAAc,QAAO;AAEtD,QAAM,gBACJ,SAAS,MAAM,UAAU,YAAY,SAAS,MAAM,QAAQ;AAC9D,QAAM,UACJ,kBAAkB,QAAQ,YAAY,YAAY,IAAI,YAAY,aAAa;AAEjF,SAAO;AAAA,IACL,GAAG;AAAA,IACH,OAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,MACP,UAAU;AAAA,MACV;AAAA,IACF;AAAA,IACA,WACE,SAAS,UAAU,UAAU,WACzB,SAAS,YACT,EAAE,OAAO,UAAU,SAAS,MAAM,gBAAgB,OAAO;AAAA,IAC/D,MAAM,EAAE,OAAO,aAAa,eAAe,MAAM,aAAa,EAAE;AAAA,EAClE;AACF;AAEA,SAAS,gBACP,UACA,QACA,MACqB;AACrB,MAAI,SAAS,UAAU,UAAU,aAAc,QAAO;AACtD,QAAM,YAA4B,EAAE,OAAO,cAAc,QAAQ,KAAK;AACtE,SAAO,EAAE,GAAG,UAAU,UAAU;AAClC;AAMA,SAAS,kBAAkB,UAA+B,MAAmC;AAC3F,MAAI,SAAS,UAAU,UAAU,SAAU,QAAO;AAClD,QAAM,OAAkB,EAAE,OAAO,aAAa,eAAe,MAAM,aAAa,EAAE;AAClF,MACE,SAAS,KAAK,UAAU,KAAK,SAC7B,SAAS,KAAK,kBAAkB,KAAK,iBACrC,SAAS,KAAK,gBAAgB,KAAK,aACnC;AACA,WAAO;AAAA,EACT;AACA,SAAO,EAAE,GAAG,UAAU,KAAK;AAC7B;AAEA,SAAS,kBACP,UACA,OACA,QACqB;AACrB,MAAI,SAAS,UAAU,UAAU,SAAU,QAAO;AAClD,QAAM,SAAS,SAAS,KAAK,cAAc;AAC3C,MAAI,QAA4B,SAAS,KAAK;AAC9C,MAAI,UAAU,OAAO,gBAAiB,SAAQ;AAAA,WACrC,UAAU,OAAO,iBAAkB,SAAQ;AACpD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,MAAM,EAAE,OAAO,eAAe,SAAS,KAAK,eAAe,aAAa,OAAO;AAAA,EACjF;AACF;AAMA,SAAS,qBACP,UACA,KACqB;AACrB,QAAM,OAAO,eAAe,SAAS,UAAU;AAC/C,MAAI,UAAU,eAAe,IAAI;AACjC,SAAO;AAAA,IACL,GAAG;AAAA,IACH,YAAY;AAAA;AAAA;AAAA,IAGZ,MAAM;AAAA,MACJ,GAAG,SAAS;AAAA,MACZ,QAAQ,kBAAkB,SAAS,KAAK,QAAQ,SAAS,UAAU;AAAA,MACnE,SAAS,kBAAkB,SAAS,KAAK,SAAS,SAAS,UAAU;AAAA,MACrE,SAAS,kBAAkB,SAAS,KAAK,SAAS,SAAS,UAAU;AAAA,MACrE,WAAW,kBAAkB,SAAS,KAAK,WAAW,SAAS,UAAU;AAAA,IAC3E;AAAA,EACF;AACF;AAEA,SAAS,kBACP,WACA,gBACsB;AACtB,MAAI,UAAU,UAAU,SAAS,UAAU,eAAe,gBAAgB;AACxE,WAAO,EAAE,OAAO,SAAS,aAAa,UAAU,aAAa,QAAQ,aAAa;AAAA,EACpF;AACA,SAAO;AACT;AAMA,SAAS,cACP,UACA,QACA,KACqB;AACrB,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK,mBAAmB;AACtB,UAAI,OAAO,SAAS,WAAW,GAAG;AAEhC,YAAI,SAAS,OAAO,SAAS,UAAU,eAAgB,QAAO;AAC9D,YAAI,WAAW;AACf,eAAO;AAAA,UACL,GAAG;AAAA,UACH,QAAQ,EAAE,UAAU,EAAE,OAAO,eAAe,EAAE;AAAA,QAChD;AAAA,MACF;AACA,UAAI,CAAC,IAAI,UAAU;AACjB,YAAI,WAAW,IAAI,gBAAgB,OAAO,UAAU,SAAS,UAAU;AAAA,MACzE,OAAO;AACL,YAAI,SAAS,UAAU,OAAO,UAAU,SAAS,UAAU;AAAA,MAC7D;AACA,aAAO;AAAA,QACL,GAAG;AAAA,QACH,QAAQ;AAAA,UACN,UAAU;AAAA,YACR,OAAO;AAAA,YACP,UAAU,OAAO;AAAA,YACjB,cAAc,OAAO;AAAA,UACvB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,KAAK,kBAAkB;AACrB,UAAI,CAAC,IAAI,SAAU,QAAO;AAC1B,YAAM,UAAU,IAAI,SAAS,OAAO;AAAA,QAClC,QAAQ,OAAO;AAAA,QACf,SAAS,OAAO;AAAA,QAChB,cAAc,OAAO;AAAA,QACrB,YAAY,OAAO;AAAA,MACrB,CAAC;AACD,UAAI,QAAQ,SAAS,WAAY,QAAO;AACxC,aAAO,cAAc,UAAU,QAAQ,KAAK;AAAA,IAC9C;AAAA,IACA,KAAK,sBAAsB;AACzB,YAAM,WAAW,SAAS,OAAO;AACjC,UAAI,SAAS,UAAU,cAAc,SAAS,UAAU,cAAc;AACpE,eAAO;AAAA,MACT;AACA,aAAO;AAAA,QACL,GAAG;AAAA,QACH,QAAQ;AAAA,UACN,UAAU;AAAA,YACR,OAAO;AAAA,YACP;AAAA,YACA,SAAS,OAAO;AAAA,UAClB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,KAAK,gCAAgC;AACnC,UAAI,SAAS,OAAO,SAAS,UAAU,eAAgB,QAAO;AAC9D,UAAI,CAAC,IAAI,UAAU;AAEjB,eAAO;AAAA,UACL,GAAG;AAAA,UACH,QAAQ,EAAE,UAAU,SAAS,OAAO,SAAS,SAAS;AAAA,QACxD;AAAA,MACF;AACA,YAAM,UAAU,IAAI,SAAS,QAAQ;AACrC,UAAI,QAAQ,SAAS,YAAY;AAC/B,eAAO;AAAA,UACL,GAAG;AAAA,UACH,QAAQ,EAAE,UAAU,SAAS,OAAO,SAAS,SAAS;AAAA,QACxD;AAAA,MACF;AACA,aAAO,cAAc,UAAU,QAAQ,KAAK;AAAA,IAC9C;AAAA,IACA,KAAK,mBAAmB;AACtB,YAAM,WAAW,SAAS,OAAO;AACjC,UAAI,SAAS,UAAU,UAAW,QAAO;AACzC,aAAO;AAAA,QACL,GAAG;AAAA,QACH,QAAQ;AAAA,UACN,UAAU;AAAA,YACR,OAAO;AAAA,YACP,UAAU,SAAS;AAAA,YACnB,SAAS,OAAO,OAAO,SAAS;AAAA,UAClC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,cACP,UACA,UACqB;AACrB,QAAM,WAAW,SAAS,OAAO;AACjC,OACG,SAAS,UAAU,cAAc,SAAS,UAAU,iBACrD,aAAa,UAAU,QAAQ,GAC/B;AACA,WAAO;AAAA,EACT;AACA,SAAO,EAAE,GAAG,UAAU,QAAQ,EAAE,UAAU,SAAS,EAAE;AACvD;AAEA,SAAS,aACP,GACA,GACS;AACT,MAAI,EAAE,UAAU,EAAE,MAAO,QAAO;AAChC,MAAI,EAAE,UAAU,cAAc,EAAE,UAAU,aAAc,QAAO;AAC/D,MAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAClC,QAAM,KAAK,OAAO,KAAK,EAAE,QAAQ;AACjC,QAAM,KAAK,OAAO,KAAK,EAAE,QAAQ;AACjC,MAAI,GAAG,WAAW,GAAG,OAAQ,QAAO;AACpC,aAAW,KAAK,IAAI;AAClB,UAAM,KAAK,EAAE,SAAS,CAAC;AACvB,UAAM,KAAK,EAAE,SAAS,CAAC;AACvB,QAAI,MAAM,QAAQ,EAAE,KAAK,MAAM,QAAQ,EAAE,GAAG;AAC1C,UAAI,GAAG,WAAW,GAAG,OAAQ,QAAO;AACpC,eAAS,IAAI,GAAG,IAAI,GAAG,QAAQ,IAAK,KAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAG,QAAO;AAAA,IAClE,WAAW,OAAO,IAAI;AACpB,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAMA,SAAS,aAAa,UAA+B,QAA8C;AACjG,MAAI,OAAO,SAAS,yBAAyB,OAAO,SAAS,iCAAiC,OAAO,SAAS,uBAAuB;AACnI,WAAO;AAAA,EACT;AACA,QAAM,SAAS,OAAO;AACtB,QAAM,UAAU,SAAS,KAAK,MAAM;AAEpC,MAAI,OAAO,SAAS,kBAAkB;AACpC,QAAI,QAAQ,UAAU,aAAa,QAAQ,UAAU,MAAO,QAAO;AACnE,WAAO,aAAa,UAAU,QAAQ,EAAE,OAAO,WAAW,SAAS,OAAO,KAAK,CAAC;AAAA,EAClF;AAEA,MAAI,OAAO,SAAS,gBAAgB;AAClC,QAAI,QAAQ,UAAU,MAAO,QAAO;AACpC,WAAO,aAAa,UAAU,QAAQ;AAAA,MACpC,OAAO;AAAA,MACP,aAAa,QAAQ;AAAA,MACrB,QAAQ,OAAO;AAAA,IACjB,CAAC;AAAA,EACH;AAGA,MACE,QAAQ,UAAU,SAClB,QAAQ,eAAe,OAAO,cAC9B,QAAQ,gBAAgB,OAAO,aAC/B;AACA,WAAO;AAAA,EACT;AACA,SAAO,aAAa,UAAU,QAAQ;AAAA,IACpC,OAAO;AAAA,IACP,aAAa,OAAO;AAAA,IACpB,YAAY,OAAO;AAAA,IACnB,aAAa,OAAO;AAAA,EACtB,CAAC;AACH;AAEA,SAAS,aACP,UACA,QACA,MACqB;AACrB,SAAO;AAAA,IACL,GAAG;AAAA,IACH,MAAM,EAAE,GAAG,SAAS,MAAM,CAAC,MAAM,GAAG,KAAK;AAAA,EAC3C;AACF;AAEA,SAAS,WAAW,UAA+B,MAAsC;AACvF,SAAO,EAAE,GAAG,UAAU,KAAK;AAC7B;;;AC/hBO,SAAS,aAAa,UAAkD;AAC7E,QAAM,EAAE,WAAW,OAAO,KAAK,IAAI;AAEnC,MAAI,UAAU,UAAU,UAAU,UAAU,UAAU,YAAa,QAAO;AAE1E,MAAI,UAAU,UAAU,cAAe,QAAO;AAE9C,MAAI,UAAU,UAAU,cAAc;AACpC,YAAQ,UAAU,OAAO,MAAM;AAAA,MAC7B,KAAK;AAAA,MACL,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACH,eAAO;AAAA,IACX;AAAA,EACF;AAGA,MAAI,MAAM,UAAU,SAAU,QAAO;AACrC,MAAI,KAAK,UAAU,OAAQ,QAAO;AAClC,SAAO;AACT;AAGO,SAAS,mBAAmB,UAA8C;AAC/E,MAAI,SAAS,UAAU,UAAU,cAAc;AAC7C,YAAQ,SAAS,UAAU,OAAO,MAAM;AAAA,MACtC,KAAK;AACH,eAAO,SAAS,UAAU,OAAO;AAAA,MACnC,KAAK;AACH,eAAO,mCAAmC,SAAS,UAAU,OAAO,OAAO;AAAA,MAC7E,KAAK;AACH,eAAO,SAAS,UAAU,OAAO;AAAA,MACnC,KAAK;AACH,eAAO,kCAAkC,SAAS,UAAU,OAAO,QAAQ;AAAA,MAC7E,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,IACX;AAAA,EACF;AACA,MAAI,SAAS,MAAM,UAAU,UAAU;AACrC,WACE,SAAS,MAAM,WACf,kCAAkC,SAAS,MAAM,QAAQ;AAAA,EAE7D;AACA,MAAI,SAAS,UAAU,UAAU,YAAY,SAAS,KAAK,UAAU,QAAQ;AAC3E,WAAO,oBAAoB,SAAS,KAAK,WAAW;AAAA,EACtD;AACA,SAAO;AACT;AAMO,SAAS,mBAAmB,UAAkD;AACnF,QAAM,EAAE,WAAW,OAAO,MAAM,QAAQ,KAAK,IAAI;AACjD,QAAM,SAAS,UAAU,UAAU;AACnC,QAAM,UAAU,MAAM,UAAU;AAChC,QAAM,oBACJ,WAAW,YAAY,MAAM,KAAK,KAAK,YAAY,YAAY;AACjE,QAAM,cAAc,WAAW,MAAM,UAAU;AAC/C,QAAM,aAAa,KAAK,UAAU;AAElC,QAAM,UAAU,UAAU,cAAc;AACxC,QAAM,gBAAgB,WAAW,KAAK,UAAU;AAEhD,QAAM,iBAAiB,kBAAkB,OAAO,QAAQ;AACxD,QAAM,UAAU,gBAAgB,OAAO,QAAQ;AAC/C,QAAM,iBAAiB,uBAAuB,OAAO,QAAQ;AAE7D,QAAM,YAAY,WAAW;AAC7B,QAAM,kBAAkB,aAAa;AACrC,QAAM,iBACJ,mBAAmB,KAAK,aAAa,UAAU;AAEjD,QAAM,oBACJ,WACA,KAAK,OAAO,UAAU,SACtB,OAAO,SAAS,UAAU;AAE5B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB;AAAA,IACnB,iBAAiB;AAAA,IACjB,uBAAuB;AAAA,EACzB;AACF;AAMA,SAAS,kBAAkB,OAAmC;AAC5D,MAAI,MAAM,UAAU,eAAgB,QAAO;AAC3C,MAAI,MAAM,UAAU,WAAY,QAAO;AACvC,MAAI,MAAM,UAAU,gBAAgB;AAClC,WAAO,MAAM,SAAS,UAAU;AAAA,EAClC;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,OAA6C;AACpE,MAAI,MAAM,UAAU,aAAc,QAAO,MAAM;AAC/C,MAAI,MAAM,UAAU,kBAAkB,MAAM,SAAS,UAAU,cAAc;AAC3E,WAAO,MAAM,SAAS;AAAA,EACxB;AACA,SAAO;AACT;AAEA,SAAS,uBAAuB,OAA6C;AAC3E,MAAI,MAAM,UAAU,aAAc,QAAO,MAAM;AAC/C,MAAI,MAAM,UAAU,kBAAkB,MAAM,SAAS,UAAU,cAAc;AAC3E,WAAO,MAAM,SAAS;AAAA,EACxB;AACA,SAAO;AACT;AAEA,IAAM,QAA2B,OAAO,OAAO,CAAC,CAAC;AAO1C,SAAS,wBACd,OAC6B;AAC7B,UAAQ,MAAM,OAAO;AAAA,IACnB,KAAK;AAAA,IACL,KAAK;AACH,aAAO,MAAM;AAAA,IACf,KAAK;AACH,UAAI,MAAM,SAAS,UAAU,cAAc,MAAM,SAAS,UAAU,cAAc;AAChF,eAAO,MAAM,SAAS;AAAA,MACxB;AACA,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAMO,SAAS,0BACd,cACA,SAC8B;AAC9B,MAAI,CAAC,SAAS,QAAQ;AACpB,WAAO,EAAE,IAAI,MAAM,SAAS,OAAO,SAAS,CAAC,GAAG,gBAAgB,CAAC,EAAE;AAAA,EACrE;AACA,UAAQ,aAAa,OAAO;AAAA,IAC1B,KAAK;AACH,aAAO,EAAE,IAAI,MAAM,SAAS,OAAO,SAAS,CAAC,GAAG,gBAAgB,CAAC,EAAE;AAAA,IACrE,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO,EAAE,IAAI,MAAM,SAAS,OAAO,SAAS,CAAC,GAAG,gBAAgB,CAAC,EAAE;AAAA,IACrE,KAAK;AACH,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,SAAS;AAAA,QACT,SAAS,CAAC,GAAG,aAAa,OAAO;AAAA,QACjC,gBAAgB,CAAC,GAAG,aAAa,cAAc;AAAA,MACjD;AAAA,IACF,KAAK;AACH,aAAO,0BAA0B,aAAa,UAAU,OAAO;AAAA,EACnE;AACF;;;ACnLO,SAAS,wBAAwB,UAAuC;AAC7E,QAAM,EAAE,UAAU,IAAI;AACtB,UAAQ,UAAU,OAAO;AAAA,IACvB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO,UAAU,WAAW,IACxB,oCAA+B,UAAU,QAAQ,MACjD;AAAA,IACN,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;AAEO,SAAS,wBACd,UACwB;AACxB,UAAQ,SAAS,UAAU,OAAO;AAAA,IAChC,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAKO,SAAS,0BACd,KACA,UACQ;AACR,MAAI,SAAS,MAAM,UAAU,UAAU;AACrC,WACE,SAAS,MAAM,WACf,iCAAiC,sBAAsB,SAAS,MAAM,QAAQ,CAAC;AAAA,EAEnF;AAEA,MAAI,CAAC,KAAK,KAAK,GAAG;AAChB,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,IAAI,KAAK;AAEtB,MAAI,aAAa,KAAK,IAAI,GAAG;AAC3B,WAAO;AAAA,EACT;AACA,MAAI,aAAa,KAAK,IAAI,GAAG;AAC3B,WAAO;AAAA,EACT;AACA,MAAI,qCAAqC,KAAK,IAAI,GAAG;AACnD,WAAO;AAAA,EACT;AACA,MAAI,2BAA2B,KAAK,IAAI,GAAG;AACzC,WAAO;AAAA,EACT;AACA,MAAI,2BAA2B,KAAK,IAAI,GAAG;AACzC,UAAM,WACJ,SAAS,MAAM,UAAU,YACrB,SAAS,MAAM,WACf,SAAS,MAAM,UAAU,YACvB,SAAS,MAAM,WACf;AACR,QAAI,UAAU;AACZ,aAAO,iCAAiC,sBAAsB,QAAQ,CAAC;AAAA,IACzE;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,cACP,MACA,WACA,UACQ;AACR,MAAI,SAAS,WAAW,SAAS,MAAM,UAAU,UAAU;AACzD,WAAO;AAAA,EACT;AACA,MAAI,SAAS,cAAe,QAAO;AACnC,MAAI,SAAS,QAAS,QAAO;AAC7B,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,gBACP,UACA,QACA,OACQ;AACR,MAAI,WAAW,eAAe;AAC5B,QAAI,SAAS,UAAU,UAAU,cAAc;AAC7C,UAAI,SAAS,UAAU,OAAO,SAAS,gBAAgB;AACrD,eAAO;AAAA,MACT;AACA,UAAI,SAAS,UAAU,OAAO,SAAS,kBAAkB;AACvD,eAAO;AAAA,UACL,SAAS;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,MAAI,WAAW,SAAS;AACtB,WAAO,0BAA0B,OAAO,QAAQ;AAAA,EAClD;AACA,SAAO,wBAAwB,QAAQ;AACzC;AAKO,SAAS,mBAAmB,UAAkD;AACnF,QAAM,SAAS,aAAa,QAAQ;AACpC,MAAI,WAAW,SAAS;AACtB,WAAO,EAAE,MAAM,QAAQ;AAAA,EACzB;AACA,QAAM,OACJ,WAAW,gBAAgB,gBAAgB,WAAW,UAAU,UAAU;AAC5E,QAAM,YAAY,SAAS,YAAY,wBAAwB,QAAQ,IAAI;AAC3E,QAAM,QAAQ,mBAAmB,QAAQ;AACzC,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA,OAAO,cAAc,MAAM,aAAa,WAAW,QAAQ;AAAA,IAC3D,SAAS,gBAAgB,UAAU,QAAQ,KAAK;AAAA,IAChD,WAAW,SAAS,iBAAiB,SAAS;AAAA,EAChD;AACF;AAGO,IAAM,gCAAgC;AAAA,EAC3C,OAAO;AAAA,EACP,SACE;AACJ;;;ACnLO,SAAS,4BAA4B,KAAkD;AAC5F,MAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,EAAE,cAAc,KAAM,QAAO;AACpE,QAAM,UAAU;AAChB,SAAO;AAAA,IACL,UAAU,QAAQ,YAAY,OAAO,OAAO,OAAO,QAAQ,QAAQ;AAAA,IACnE,UAAU,QAAQ,QAAQ,QAAQ;AAAA,EACpC;AACF;AAMO,SAAS,2BACd,aAC+B;AAC/B,MAAI,CAAC,eAAe,OAAO,gBAAgB,SAAU,QAAO;AAC5D,QAAM,MAAM;AACZ,QAAM,eACJ,OAAO,IAAI,iBAAiB,WACxB,IAAI,eACJ,OAAO,IAAI,gBAAgB,WACzB,IAAI,cACJ;AACR,QAAM,UAAU,4BAA4B,IAAI,OAAO;AACvD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,IACvC,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC/B;AACF;;;AC8DO,SAAS,sBAAsB,MAAiC;AACrE,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;AAGO,SAAS,yBAAyB,MAAgD;AACvF,UAAQ,MAAM;AAAA,IACZ,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;AAMO,SAAS,gCACd,QACA,MACQ;AACR,QAAM,QAAkB,CAAC,+BAA+B;AACxD,MAAI,OAAO,QAAQ,SAAS,GAAG;AAC7B,UAAM,KAAK,qBAAqB,OAAO,QAAQ,KAAK,IAAI,CAAC,GAAG;AAAA,EAC9D;AACA,MAAI,OAAO,eAAe,SAAS,GAAG;AACpC,UAAM;AAAA,MACJ,yCAAyC,OAAO,eAAe,KAAK,IAAI,CAAC;AAAA,IAC3E;AAAA,EACF;AACA,MAAI,MAAM,KAAK,GAAG;AAChB,UAAM,KAAK,KAAK,KAAK,CAAC;AAAA,EACxB;AACA,SAAO,MAAM,KAAK,GAAG;AACvB;AAEO,SAAS,iCAAiC,MAAuB;AACtE,QAAM,OAAO;AACb,SAAO,MAAM,KAAK,IAAI,GAAG,IAAI,IAAI,KAAK,KAAK,CAAC,KAAK;AACnD;AAEO,SAAS,oCAAoC,MAAuB;AACzE,QAAM,OACJ;AACF,SAAO,MAAM,KAAK,IAAI,GAAG,IAAI,IAAI,KAAK,KAAK,CAAC,KAAK;AACnD;AAEO,SAAS,4BAA4B,UAAuC;AACjF,QAAM,SAAS,SAAS,KAAK;AAC7B,QAAM,SAAS,SAAS,IAAI,KAAK,MAAM,oBAAoB,WAAW,IAAI,KAAK,GAAG,MAAM;AACxF,SAAO,wEAAwE,MAAM;AACvF;AAOO,SAAS,yBACd,aACS;AACT,MAAI,CAAC,eAAe,OAAO,gBAAgB,SAAU,QAAO;AAC5D,QAAM,UAAU;AAAA,IACd,YAAY,WAAY,YAAwC;AAAA,EAClE;AACA,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,QAAQ,YAAY;AAC7B;AAEO,SAAS,mCAAmC,MAAuB;AACxE,QAAM,OACJ;AACF,SAAO,MAAM,KAAK,IAAI,GAAG,IAAI,IAAI,KAAK,KAAK,CAAC,KAAK;AACnD;AAEO,SAAS,iCAAiC,MAAuB;AACtE,QAAM,OACJ;AACF,SAAO,MAAM,KAAK,IAAI,GAAG,IAAI,IAAI,KAAK,KAAK,CAAC,KAAK;AACnD;AAEA,SAAS,eACP,KACA,SAIM;AACN,MAAI,KAAK;AAAA,IACP,OAAO,QAAQ,SAAS,sBAAsB,QAAQ,IAAI;AAAA,IAC1D,UAAU,QAAQ,YAAY,yBAAyB,QAAQ,IAAI;AAAA,IACnE,IAAI,QAAQ;AAAA,IACZ,MAAM,QAAQ;AAAA,IACd,UAAU,QAAQ;AAAA,IAClB,SAAS,QAAQ;AAAA,EACnB,CAAC;AACH;AAEA,SAAS,qBACP,UACA,SACA,KACM;AACN,QAAM,EAAE,QAAQ,MAAM,KAAK,IAAI;AAE/B,MAAI,OAAO,SAAS,UAAU,cAAc;AAC1C,mBAAe,KAAK;AAAA,MAClB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,oCAAoC,SAAS,iBAAiB;AAAA,IACzE,CAAC;AAAA,EACH;AAEA,MAAI,KAAK,UAAU,SAAS;AAC1B,mBAAe,KAAK;AAAA,MAClB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,4BAA4B,QAAQ;AAAA,IAC/C,CAAC;AAAA,EACH;AAEA,MAAI,KAAK,aAAa,UAAU,WAAW;AACzC,mBAAe,KAAK;AAAA,MAClB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,KAAK,aAAa;AAAA,IAC7B,CAAC;AAAA,EACH;AACF;AAUO,SAAS,4BACd,QACA,SAC2B;AAC3B,QAAM,MAAiC,CAAC;AAExC,MAAI,OAAO,WAAW,SAAS;AAC7B,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,oBAAoB,SAAS;AACtC,mBAAe,KAAK;AAAA,MAClB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,iCAAiC,SAAS,kBAAkB;AAAA,IACvE,CAAC;AAAA,EACH,WAAW,CAAC,OAAO,oBAAoB,IAAI;AACzC,mBAAe,KAAK;AAAA,MAClB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,QACP,OAAO;AAAA,QACP,SAAS;AAAA,MACX;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,oBAAoB,OAAO,eAAe,OAAO;AACvD,MAAI,qBAAqB,0BAA0B,iBAAiB,GAAG;AACrE,mBAAe,KAAK;AAAA,MAClB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,gCAAgC,SAAS,sBAAsB;AAAA,IAC1E,CAAC;AAAA,EACH,WAAW,OAAO,aAAa;AAC7B,mBAAe,KAAK;AAAA,MAClB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,OAAO;AAAA,IAClB,CAAC;AAAA,EACH,WAAW,OAAO,WAAW;AAC3B,mBAAe,KAAK;AAAA,MAClB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,OAAO;AAAA,IAClB,CAAC;AAAA,EACH;AAEA,QAAM,UAAU,OAAO,kBAAkB,CAAC;AAC1C,MAAI,QAAQ,SAAS,GAAG;AACtB,mBAAe,KAAK;AAAA,MAClB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,yBAAyB,SAAS,SAAS,WAAW;AAAA,IACjE,CAAC;AAAA,EACH;AAEA,MAAI,OAAO,eAAe;AACxB,UAAM,UAAU,OAAO,oBACnB;AAAA,MACE,OAAO,kBAAkB,WACtB,OAAO,kBAA8C;AAAA,IAC1D,IACA;AACJ,QAAI,WAAW,CAAC,QAAQ,UAAU;AAChC,qBAAe,KAAK;AAAA,QAClB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,SAAS,iCAAiC,SAAS,kBAAkB;AAAA,MACvE,CAAC;AAAA,IACH;AAAA,EACF,WAAW,yBAAyB,OAAO,iBAAiB,GAAG;AAC7D,mBAAe,KAAK;AAAA,MAClB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS,mCAAmC,SAAS,oBAAoB;AAAA,IAC3E,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,UAAU;AACrB,yBAAqB,QAAQ,UAAU,SAAS,GAAG;AAAA,EACrD;AAEA,MAAI,SAAS,eAAe,QAAQ;AAClC,WAAO,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,cAAe,SAAS,EAAE,IAAI,CAAC;AAAA,EACnE;AACA,SAAO;AACT;AAKO,SAAS,yBACd,SACA,MACQ;AACR,QAAM,OAAO,QAAQ,KAAK,IAAI;AAC9B,QAAM,OAAO,sCACX,QAAQ,WAAW,IAAI,KAAK,GAC9B,KAAK,IAAI;AACT,SAAO,MAAM,KAAK,IAAI,GAAG,IAAI,IAAI,KAAK,KAAK,CAAC,KAAK;AACnD;AAEA,IAAM,wBAAwB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAMO,SAAS,0BAA0B,SAA0B;AAClE,SAAO,sBAAsB,KAAK,CAAC,OAAO,GAAG,KAAK,OAAO,CAAC;AAC5D;AAEO,SAAS,gCAAgC,MAAuB;AACrE,QAAM,OACJ;AACF,SAAO,MAAM,KAAK,IAAI,GAAG,IAAI,IAAI,KAAK,KAAK,CAAC,KAAK;AACnD;;;AC/YA,IAAAC,iBAA8C;;;ACY9C,mBAA6D;;;ACC7D,IAAMC,eAAmD;AAAA,EACvD,MAAM;AAAA,EACN,cAAc;AAAA,EACd,MAAM;AACR;AAEA,IAAIC,YAAiC;AACrC,IAAI,aAAyC;AAE7C,SAAS,aAAa,MAAoC;AACxD,MAAI,CAAC,WAAY,QAAO;AACxB,SAAOD,aAAY,IAAI,IAAIA,aAAY,UAAU;AACnD;AAMO,SAAS,iBAAiB,SAA2C;AAC1E,QAAM,SAAS,QAAQ,kBAAkB;AACzC,MAAIC,aAAY,CAAC,aAAa,MAAM,EAAG,QAAOA;AAE9C,eAAa;AACb,QAAM,OAAO,QAAQ,QAAQ,EAAE,KAAK,MAAM;AACxC,UAAM,SAAS,MAAM,MAAM,OAAO;AAClC,WAAO,kBAAkB,UAAU,SAAS,QAAQ,QAAQ;AAAA,EAC9D,CAAC;AAED,EAAAA,YAAW,KAAK,MAAM,CAAC,QAAQ;AAC7B,IAAAA,YAAW;AACX,iBAAa;AACb,UAAM;AAAA,EACR,CAAC;AACD,SAAOA;AACT;AAYO,SAAS,2BAAiC;AAC/C,EAAAA,YAAW;AACX,eAAa;AACf;;;AChDO,SAAS,oCACd,SACgB;AAChB,QAAM,OAAuB;AAAA,IAC3B,gBAAgB,SAAS,kBAAkB;AAAA,IAC3C,SAAS,SAAS,WAAW,CAAC;AAAA,IAC9B,eAAe,SAAS;AAAA,IACxB,kBAAkB,SAAS;AAAA,IAC3B,eAAe,SAAS;AAAA,IACxB,WAAW;AAAA,MACT,WAAW,CAAC,YAAY,iBAAiB,OAAO;AAAA,IAClD;AAAA,IACA,gBAAgB,MAAM,yBAAyB;AAAA,EACjD;AACA,MACE,SAAS,4BAA4B,UACrC,SAAS,2BAA2B,QACpC;AACA,UAAM,WAAW,SAAS,0BAA0B;AACpD,UAAM,MAAM,SAAS,2BAA2B;AAChD,SAAK,SAAS;AAAA,MACZ,gBAAgB,MAAM,KAAK,EAAE,QAAQ,IAAI,GAAG,MAAM,QAAQ;AAAA,MAC1D,UAAU,WAAW;AAAA,IACvB;AAAA,EACF;AACA,SAAO;AACT;;;AChBO,IAAM,2BAA8C;AAAA,EACzD;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAC3E;AAGO,SAAS,gBAAgB,MAAiE;AAC/F,MAAI,SAAS,aAAa,SAAS,KAAM,QAAO;AAChD,MAAI,SAAS,KAAM,QAAO;AAC1B,SAAO;AACT;AAiBO,SAAS,kBACd,KACA,UACA,QACA,UAAyB,CAAC,GACZ;AACd,QAAM,WAAW,QAAQ,kBAAkB;AAC3C,QAAM,WAAW,QAAQ,YAAY,gBAAgB,IAAI,kBAAkB,CAAC;AAE5E,QAAM,YAAY,IAAI,IAAI;AAC1B,MAAI,WAAW;AACf,MAAI,QAA4B;AAChC,MAAI,YAAY;AAEhB,SAAO,iBAAiB,SAAS,MAAM;AACrC,gBAAY;AACZ,QAAI,UAAU,KAAM,KAAI,aAAa,KAAK;AAAA,EAC5C,CAAC;AAED,WAAS,EAAE,MAAM,gBAAgB,MAAM,UAAU,CAAC;AAElD,QAAM,OAAO,MAAM;AACjB,QAAI,UAAW;AACf,YAAQ;AAER,UAAM,QAAQ,IAAI,WAAW;AAC7B,QAAI,UAAU,MAAM;AAClB,UAAI,MAAM,UAAU;AAClB,iBAAS,EAAE,MAAM,oBAAoB,MAAM,IAAI,IAAI,EAAE,CAAC;AAAA,MACxD,OAAO;AACL,iBAAS,EAAE,MAAM,gBAAgB,MAAM,IAAI,IAAI,EAAE,CAAC;AAAA,MACpD;AACA;AAAA,IACF;AAEA,gBAAY;AACZ,aAAS,EAAE,MAAM,eAAe,UAAU,MAAM,IAAI,IAAI,EAAE,CAAC;AAE3D,UAAM,UAAU,IAAI,IAAI,IAAI;AAC5B,QAAI,WAAW,UAAU;AACvB,eAAS,EAAE,MAAM,kBAAkB,UAAU,MAAM,IAAI,IAAI,EAAE,CAAC;AAC9D;AAAA,IACF;AAEA,UAAM,OAAO,SAAS,KAAK,IAAI,WAAW,GAAG,SAAS,SAAS,CAAC,CAAC,KAAK;AACtE,UAAM,YAAY,WAAW;AAC7B,YAAQ,IAAI,WAAW,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,SAAS,CAAC,CAAC;AAAA,EACrE;AAIA,OAAK;AAEL,SAAO;AAAA,IACL,SAAS;AACP,kBAAY;AACZ,UAAI,UAAU,MAAM;AAClB,YAAI,aAAa,KAAK;AACtB,gBAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AACF;;;AClFO,IAAM,+BAA+B;AAMrC,SAAS,qBACd,KACA,UACA,QACA,SACA,UAA4B,CAAC,GACZ;AACjB,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,SAA8B,QAAQ,kBAAkB;AAC9D,MAAI,UAAU;AACd,MAAI,QAA2D;AAE/D,QAAM,SAAS,CAAC,SAAqB;AACnC,QAAI,QAAS;AACb,cAAU;AACV,QAAI,UAAU,KAAM,KAAI,aAAa,KAAK;AAC1C,QAAI,OAAO,QAAS;AACpB,SAAK;AAAA,EACP;AAEA,WAAS,EAAE,MAAM,mBAAmB,QAAQ,MAAM,IAAI,IAAI,EAAE,CAAC;AAE7D,QAAMC,SAAQ,IAAI,SAAS;AAC3B,MAAI,CAACA,QAAO;AACV;AAAA,MAAO,MACL,SAAS;AAAA,QACP,MAAM;AAAA,QACN,QAAQ,EAAE,MAAM,gBAAgB,SAAS,oCAAoC;AAAA,QAC7E,MAAM,IAAI,IAAI;AAAA,MAChB,CAAC;AAAA,IACH;AACA,WAAO,EAAE,QAAQ,MAAM,OAAO,MAAM;AAAA,IAAC,CAAC,EAAE;AAAA,EAC1C;AAIA,UAAQ,IAAI,WAAW,MAAM;AAC3B,QAAI,QAAS;AACb;AAAA,MAAO,MACL,SAAS;AAAA,QACP,MAAM;AAAA,QACN,QAAQ,EAAE,MAAM,iBAAiB,SAAS,UAAU;AAAA,QACpD,MAAM,IAAI,IAAI;AAAA,MAChB,CAAC;AAAA,IACH;AAAA,EACF,GAAG,SAAS;AAEZ,QAAM,gBAAgB,CAAC,MAAiB;AACtC,QAAI,CAAC,EAAE,QAAQ;AACb,eAAS;AAAA,QACP,MAAM;AAAA,QACN,QAAQ,EAAE,MAAM,gBAAgB,SAAS,mCAAmC;AAAA,QAC5E,MAAM,IAAI,IAAI;AAAA,MAChB,CAAC;AACD;AAAA,IACF;AACA,aAAS;AAAA,MACP,MAAM;AAAA,MACN;AAAA,MACA,cAAc;AAAA;AAAA,MACd,MAAM,IAAI,IAAI;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,QAAM,gBAAgB,CAAC,QAAiB;AACtC,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,UAAM,SAAiC,EAAE,MAAM,gBAAgB,QAAQ;AACvE,aAAS,EAAE,MAAM,kBAAkB,QAAQ,MAAM,IAAI,IAAI,EAAE,CAAC;AAAA,EAC9D;AAEA,QAAM,YAAY,QAAQ,cAAc,CAAC,MAAMA,OAAM,MAAM,CAAC;AAC5D,MAAI;AACF,UAAM,SAAS,UAAU,OAAO;AAChC,QAAI,UAAU,OAAQ,OAAyB,SAAS,YAAY;AAClE;AAAC,MAAC,OAAyB;AAAA,QACzB,MAAM,OAAO,MAAM,cAAc,IAAI,SAAS,KAAKA,MAAK,CAAC;AAAA,QACzD,CAAC,QAAQ,OAAO,MAAM,cAAc,GAAG,CAAC;AAAA,MAC1C;AAAA,IACF,OAAO;AACL,aAAO,MAAM,cAAc,IAAI,SAAS,KAAKA,MAAK,CAAC;AAAA,IACrD;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,MAAM,cAAc,GAAG,CAAC;AAAA,EACjC;AAEA,SAAO,iBAAiB,SAAS,MAAM,OAAO,MAAM;AAAA,EAAC,CAAC,CAAC;AAEvD,SAAO,EAAE,QAAQ,MAAM,OAAO,MAAM;AAAA,EAAC,CAAC,EAAE;AAC1C;;;AC3FA,IAAM,aAAN,MAAoB;AAAA,EAMlB,YAA6B,UAA8C;AAA9C;AAL7B,SAAQ,YAAY,oBAAI,IAAiB;AACzC,SAAQ,WAAW;AAEnB,SAAQ,OAA4B;AAAA,EAEwC;AAAA,EAE5E,UAAU,UAAmC;AAC3C,SAAK,UAAU,IAAI,QAAQ;AAC3B,QAAI,CAAC,KAAK,MAAM;AACd,WAAK,OAAO,MAAM;AAEhB,aAAK,OAAO,MAAM;AAAA,QAAC;AACnB,YAAI;AACF,eAAK,SAAS,CAAC,UAAU;AACvB,iBAAK,WAAW;AAChB,iBAAK,OAAO;AACZ,uBAAW,KAAK,KAAK,UAAW,GAAE,KAAK;AAAA,UACzC,CAAC;AAAA,QACH,SAAS,KAAK;AACZ,cAAI,OAAO,YAAY,aAAa;AAClC,oBAAQ,MAAM,mDAAmD,GAAG;AAAA,UACtE;AAAA,QACF;AAAA,MACF;AACA,WAAK,KAAK;AAAA,IACZ;AACA,QAAI,KAAK,YAAY,KAAK,SAAS,QAAW;AAC5C,eAAS,KAAK,IAAI;AAAA,IACpB;AACA,WAAO,MAAM;AACX,WAAK,UAAU,OAAO,QAAQ;AAAA,IAChC;AAAA,EACF;AAAA;AAAA,EAGA,OAAsB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,QAAiB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB,OAAgB;AAC9B,SAAK,WAAW;AAChB,SAAK,OAAO;AACZ,eAAW,KAAK,KAAK,UAAW,GAAE,KAAK;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAuB;AACrB,SAAK,UAAU,MAAM;AACrB,SAAK,WAAW;AAChB,SAAK,OAAO;AACZ,SAAK,OAAO;AAAA,EACd;AACF;AAgCO,IAAM,cAAc,IAAI,WAA+B,CAAC,SAAS;AACtE,QAAM,UAAU,CAAC,QAAwC,aAA0C;AACjG,SAAK,EAAE,QAAQ,SAAS,CAAC;AAAA,EAC3B;AAIA,QAAM;AAAA,IACJ,CAAC,QAAQ,aAAa;AACpB,cAAQ,QAAS,YAA4C,IAAI;AAAA,IACnE;AAAA,IACA,EAAE,aAAa,MAAM;AAAA,EACvB;AAMA,QAAM,sBAAsB,MAAM,uBAAuB,MAAM,QAAQ;AACvE,MAAI,OAAO,MAAM,OAAO,cAAc,OAAO,wBAAwB,YAAY;AAC/E;AAAA,EACF;AACA,MAAI;AACJ,QAAM,GAAG,WAAW,OAAO,QAAiB;AAC1C,QAAI,CAAC,OAAO,OAAO,QAAQ,SAAU;AACrC,UAAM,OAAO;AACb,QAAI,CAAC,KAAK,WAAW,OAAO,KAAK,UAAU,SAAU;AACrD,QAAI,KAAK,UAAU,UAAW;AAC9B,gBAAY,KAAK;AACjB,QAAI;AACF,YAAM,SAAS,MAAM,oBAAoB,KAAK,OAAO,EAAE,aAAa,MAAM,CAAC;AAC3E,cAAQ,QAAQ,YAAY,KAAK,GAAG,YAAY,IAAI;AAAA,IACtD,SAAS,KAAK;AACZ,UAAI,OAAO,YAAY,aAAa;AAClC,gBAAQ,MAAM,oEAAoE,GAAG;AAAA,MACvF;AAAA,IACF;AAAA,EACF,CAAC;AACH,CAAC;AAEM,IAAM,eAAe,IAAI,WAAgC,CAAC,SAAS;AAIxE,QAAM;AAAA,IACJ,CAAC,SAAS,aAAa;AACrB,WAAK,EAAE,SAAS,UAAW,YAA4C,KAAK,CAAC;AAAA,IAC/E;AAAA,IACA,EAAE,aAAa,OAAO,QAAQ,OAAO;AAAA,EACvC;AACF,CAAC;AAEM,IAAM,eAAe,IAAI,WAAgC,CAAC,SAAS;AACxE,QAAM,UAAU,CAAC,SAAS,gBAAgB;AACxC,UAAM,aAAa;AAAA,MAChB,eAAiD;AAAA,IACpD;AACA,SAAK;AAAA,MACH,SAAS,UAAU,EAAE,GAAG,QAAQ,IAAI;AAAA,MACpC,aAAa;AAAA,IACf,CAAC;AAAA,EACH,CAAC;AACH,CAAC;AAEM,IAAM,iBAAiB,IAAI,WAAkC,CAAC,SAAS;AAC5E,MAAI,OAAO,MAAM,gBAAgB,WAAY;AAC7C,QAAM,YAAY,CAAC,aAAa;AAC9B,SAAK,EAAE,UAAW,YAA4C,KAAK,CAAC;AAAA,EACtE,CAAC;AACH,CAAC;;;AC/IM,SAAS,2BAA2B,KAAgD;AACzF,QAAM,OAA0B,CAAC;AAEjC,OAAK;AAAA,IACH,YAAY,UAAU,CAAC,YAAY;AACjC,YAAM,OAAO,UAAU,UAAU,OAAO;AACxC,qBAAe,KAAK,UAAU,IAAI;AAClC,UAAI,kBAAkB,QAAQ,YAAY,IAAI;AAAA,IAChD,CAAC;AAAA,EACH;AAEA,OAAK;AAAA,IACH,aAAa,UAAU,CAAC,YAAY;AAClC,YAAM,OAAO,UAAU,WAAW,OAAO;AACzC,qBAAe,KAAK,WAAW,IAAI;AACnC,UAAI,mBAAmB,QAAQ,YAAY,IAAI;AAAA,IACjD,CAAC;AAAA,EACH;AAEA,OAAK;AAAA,IACH,aAAa,UAAU,CAAC,YAAY;AAClC,YAAM,OAAO,UAAU,WAAW,OAAO;AACzC,qBAAe,KAAK,WAAW,IAAI;AACnC,YAAM,QAAQ,yBAAyB,QAAQ,aAAa,YAAY;AACxE,UAAI,UAAU,MAAM;AAClB,YAAI,SAAS;AAAA,UACX,MAAM;AAAA,UACN;AAAA,UACA,MAAM,KAAK,IAAI;AAAA,UACf,YAAY,IAAI,cAAc;AAAA,QAChC,CAAC;AAAA,MACH;AACA,UAAI,mBAAmB,QAAQ,WAAW,IAAI;AAAA,IAChD,CAAC;AAAA,EACH;AAEA,OAAK;AAAA,IACH,eAAe,UAAU,CAAC,YAAY;AACpC,YAAM,OAAO,UAAU,aAAa,OAAO;AAC3C,qBAAe,KAAK,aAAa,IAAI;AACrC,UAAI,qBAAqB,QAAQ,YAAY,IAAI;AAAA,IACnD,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,SAAS;AACP,iBAAW,OAAO,KAAK,OAAO,CAAC,EAAG,KAAI;AAAA,IACxC;AAAA,EACF;AACF;AAUA,SAAS,eACP,KACA,QACA,aACM;AACN,MAAI,SAAS;AAAA,IACX,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA,MAAM,KAAK,IAAI;AAAA,IACf,YAAY,IAAI,cAAc;AAAA,EAChC,CAAC;AACH;AAQO,SAAS,UAAU,MAAc,SAA0B;AAChE,SAAO,GAAG,IAAI,KAAK,gBAAgB,OAAO,CAAC;AAC7C;AAEA,SAAS,gBAAgB,OAAwB;AAC/C,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,IAAI,OAAO;AACjB,MAAI,MAAM,YAAY,MAAM,YAAY,MAAM,UAAW,QAAO,KAAK,UAAU,KAAK;AACpF,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,IAAI,MAAM,IAAI,eAAe,EAAE,KAAK,GAAG,CAAC;AAAA,EACjD;AACA,MAAI,MAAM,UAAU;AAClB,UAAM,MAAM;AACZ,UAAM,OAAO,OAAO,KAAK,GAAG,EAAE,KAAK;AACnC,UAAM,OAAO,KAAK,IAAI,CAAC,MAAM,GAAG,KAAK,UAAU,CAAC,CAAC,IAAI,gBAAgB,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,GAAG;AACxF,WAAO,IAAI,IAAI;AAAA,EACjB;AACA,SAAO,OAAO,KAAK;AACrB;;;ACnHO,IAAM,6BAA6B;AAqBnC,SAAS,oBACd,KACA,UACA,QACA,UACA,eACA,UAA2B,CAAC,GACZ;AAChB,MAAI,gBAAmE;AACvE,MAAI,YAAY;AAEhB,QAAM,UAAU,IAAI,IAAI;AACxB,WAAS,EAAE,MAAM,mBAAmB,UAAU,MAAM,SAAS,YAAY,cAAc,EAAE,CAAC;AAG1F,MAAI,SAAS,WAAW,GAAG;AACzB,WAAO;AAAA,MACL,qBAAqB,MAAM;AAAA,MAAC;AAAA,MAC5B,mBAAmB,YAAY;AAAA,MAAC;AAAA,MAChC,QAAQ,MAAM;AAAA,MAAC;AAAA,IACjB;AAAA,EACF;AAGA,QAAM,YAAY,QAAQ,aAAa;AACvC,kBAAgB,IAAI,WAAW,MAAM;AACnC,QAAI,aAAa,OAAO,QAAS;AACjC,aAAS,EAAE,MAAM,mBAAmB,MAAM,IAAI,IAAI,GAAG,YAAY,cAAc,EAAE,CAAC;AAAA,EACpF,GAAG,SAAS;AAEZ,SAAO,iBAAiB,SAAS,MAAM;AACrC,gBAAY;AACZ,QAAI,kBAAkB,KAAM,KAAI,aAAa,aAAa;AAAA,EAC5D,CAAC;AAED,QAAM,gBAAgB,CACpB,QACA,QACG;AACH,QAAI,aAAa,OAAO,QAAS;AACjC,UAAM,UAAU,sBAAsB,GAAG;AACzC,aAAS;AAAA,MACP,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,MAAM,IAAI,IAAI;AAAA,MACd,YAAY,cAAc;AAAA,IAC5B,CAAC;AAAA,EACH;AAGA,QAAM,oBAAoB,YAAY;AACpC,QAAI,aAAa,OAAO,QAAS;AACjC,UAAMC,SAAQ,IAAI,SAAS;AAC3B,UAAM,MAAMA,QAAO;AACnB,QAAI,CAAC,OAAO,OAAO,IAAI,aAAa,WAAY;AAChD,QAAI;AACF,YAAM,UAAU,MAAM,IAAI,SAAS;AACnC,oBAAc,eAAe,OAAO;AAAA,IACtC,QAAQ;AACN,oBAAc,eAAe,IAAI;AAAA,IACnC;AAAA,EACF;AACA,OAAK,kBAAkB;AAEvB,SAAO;AAAA,IACL,qBAAqB,CAAC,QAAQ,YAAY,cAAc,QAAQ,OAAO;AAAA,IACvE;AAAA,IACA,SAAS;AACP,kBAAY;AACZ,UAAI,kBAAkB,KAAM,KAAI,aAAa,aAAa;AAAA,IAC5D;AAAA,EACF;AACF;AAEA,SAAS,sBAAsB,KAA2C;AACxE,MAAI,QAAQ,QAAQ,QAAQ,OAAW,QAAO;AAC9C,MAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,SAAO;AACT;;;AC1GO,IAAM,gCAAgC;AACtC,IAAM,oCAAoC;AAqB1C,SAAS,qBACd,KACA,UACA,QACA,UAA4B,CAAC,GACZ;AACjB,QAAM,aAAa,QAAQ,cAAc;AACzC,QAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,QAAM,kBAAkB,QAAQ,mBAAmB;AACnD,QAAM,QAAQ,QAAQ,SAAS,aAAa,GAAG;AAE/C,MAAI,YAAY;AAChB,MAAI,SAAS;AACb,MAAI,gBAAoC;AACxC,MAAIC,YAAW;AACf,MAAI,uBAA2C;AAE/C,QAAM,gBAAgB,MAAM;AAC1B,QAAI,kBAAkB,MAAM;AAC1B,UAAI,aAAa,aAAa;AAC9B,sBAAgB;AAAA,IAClB;AAAA,EACF;AACA,QAAM,uBAAuB,MAAM;AACjC,QAAI,yBAAyB,MAAM;AACjC,UAAI,aAAa,oBAAoB;AACrC,6BAAuB;AAAA,IACzB;AAAA,EACF;AAEA,QAAM,eAAe,CAAC,QAAQ,eAAe;AAC3C,kBAAc;AACd,QAAI,aAAa,OAAQ;AACzB,oBAAgB,IAAI,WAAW,MAAM,KAAK;AAAA,EAC5C;AAEA,QAAM,OAAO,MAAM;AACjB,QAAI,aAAa,OAAQ;AACzB,oBAAgB;AAChB,QAAIA,WAAU;AAEZ;AAAA,IACF;AACA,IAAAA,YAAW;AAGX,2BAAuB,IAAI,WAAW,MAAM;AAC1C,UAAI,CAACA,UAAU;AACf,MAAAA,YAAW;AACX,2BAAqB;AACrB,UAAI,CAAC,WAAW;AACd,iBAAS,EAAE,MAAM,kBAAkB,MAAM,IAAI,IAAI,EAAE,CAAC;AACpD,qBAAa;AAAA,MACf;AAAA,IACF,GAAG,aAAa;AAEhB,UAAM,WAAW,MAAM;AACrB,UAAI,CAACA,UAAU;AACf,MAAAA,YAAW;AACX,2BAAqB;AACrB,UAAI,UAAW;AACf,eAAS,EAAE,MAAM,gBAAgB,MAAM,IAAI,IAAI,EAAE,CAAC;AAClD,mBAAa;AAAA,IACf;AACA,UAAM,aAAa,MAAM;AACvB,UAAI,CAACA,UAAU;AACf,MAAAA,YAAW;AACX,2BAAqB;AACrB,UAAI,UAAW;AACf,eAAS,EAAE,MAAM,kBAAkB,MAAM,IAAI,IAAI,EAAE,CAAC;AACpD,mBAAa;AAAA,IACf;AAIA,QAAI;AACJ,QAAI;AACF,eAAS,MAAM;AAAA,IACjB,QAAQ;AACN,iBAAW;AACX;AAAA,IACF;AACA,QACE,UACA,OAAQ,OAA8B,SAAS,YAC/C;AACA;AAAC,MAAC,OAA4B,KAAK,UAAU,UAAU;AAAA,IACzD,OAAO;AACL,eAAS;AAAA,IACX;AAAA,EACF;AAGA,QAAM,gBACJ,mBAAmB,IAAI,qBACnB,IAAI,mBAAmB,CAAC,YAAY;AAClC,QAAI,UAAW;AACf,QAAI,SAAS;AACX,UAAI,QAAQ;AACV,iBAAS;AAGT,aAAK;AAAA,MACP;AAAA,IACF,OAAO;AACL,eAAS;AACT,oBAAc;AAAA,IAGhB;AAAA,EACF,CAAC,IACD;AAGN,QAAM,YACJ,IAAI,WAAW,MAAM;AACnB,QAAI,aAAa,OAAQ;AACzB,SAAK;AAAA,EACP,CAAC,KAAK;AAER,SAAO,iBAAiB,SAAS,MAAM;AACrC,gBAAY;AACZ,kBAAc;AACd,yBAAqB;AACrB,IAAAA,YAAW;AACX,oBAAgB;AAChB,gBAAY;AAAA,EACd,CAAC;AAKD,eAAa;AAEb,SAAO;AAAA,IACL,SAAS;AACP,kBAAY;AACZ,oBAAc;AACd,2BAAqB;AACrB,MAAAA,YAAW;AACX,sBAAgB;AAChB,kBAAY;AAAA,IACd;AAAA,IACA,mBAAmB;AACjB,UAAI,aAAa,OAAQ;AACzB,eAAS,EAAE,MAAM,eAAe,MAAM,IAAI,IAAI,EAAE,CAAC;AACjD,mBAAa;AAAA,IACf;AAAA,IACA,mBAAmB;AACjB,UAAI,aAAa,OAAQ;AACzB,eAAS,EAAE,MAAM,eAAe,MAAM,IAAI,IAAI,GAAG,MAAM,QAAQ,CAAC;AAGhE,mBAAa,KAAK,IAAI,YAAY,GAAK,CAAC;AAAA,IAC1C;AAAA,IACA,UAAU;AACR,UAAI,UAAW;AACf,WAAK;AAAA,IACP;AAAA,EACF;AACF;AAEA,SAAS,aAAa,KAA+C;AACnE,SAAO,YAAY;AACjB,UAAM,IAAI,IAAI,SAAS;AACvB,QAAI,CAAC,EAAG,OAAM,IAAI,MAAM,sBAAsB;AAC9C,UAAM,SAAS,EAAE;AACjB,QAAI,CAAC,UAAU,OAAO,OAAO,eAAe,YAAY;AACtD,YAAM,IAAI,MAAM,qCAAqC;AAAA,IACvD;AACA,WAAO,OAAO,WAAW;AAAA,EAC3B;AACF;;;ACpNO,SAAS,yCACd,UACA,UACA,KACM;AACN,MAAI,SAAS,UAAU,UAAU,SAAU;AAC3C,MAAI,SAAS,MAAM,UAAU,SAAU;AAEvC,QAAM,UAAU,aAAa,KAAK;AAClC,QAAM,QAAQ,yBAAyB,SAAS,aAAa,YAAY;AACzE,MAAI,UAAU,KAAM;AAEpB,QAAM,WAAW,SAAS,MAAM;AAChC,MAAI,mBAAmB,OAAO,QAAQ,EAAG;AAEzC,WAAS;AAAA,IACP,MAAM;AAAA,IACN;AAAA,IACA,MAAM,IAAI,IAAI;AAAA,IACd,YAAY,SAAS;AAAA,EACvB,CAAC;AACH;;;ACuDO,SAAS,2BAA6C;AAC3D,SAAO;AAAA,IACL,KAAK,MAAO,OAAO,gBAAgB,cAAc,YAAY,IAAI,IAAI,KAAK,IAAI;AAAA,IAC9E,YAAY,CAAC,IAAI,OAAO,WAAW,WAAW,IAAI,EAAE;AAAA,IACpD,cAAc,CAAC,MAAM,WAAW,aAAa,CAAkC;AAAA,IAE/E,aAAa;AACX,UAAI,OAAO,eAAe,YAAa,QAAO;AAC9C,YAAM,IAAK,WAAmC;AAC9C,UAAI,OAAO,MAAM,YAAa,QAAO;AACrC,YAAMC,YACJ,OAAO,WAAW,cAAc,QAAQ,OAAO,SAAS,OAAO;AACjE,aAAO,EAAE,UAAAA,UAAS;AAAA,IACpB;AAAA,IAEA,WAAW;AACT,YAAM,IAAK,WAAqC;AAChD,aAAO,KAAK;AAAA,IACd;AAAA,IAEA,oBAAoB;AAClB,UAAI,OAAO,cAAc,YAAa,QAAO;AAC7C,YAAM,OAAQ,UAA0D;AACxE,YAAM,IAAI,MAAM;AAChB,UAAI,MAAM,aAAa,MAAM,QAAQ,MAAM,QAAQ,MAAM,QAAQ,MAAM,KAAM,QAAO;AACpF,aAAO;AAAA,IACT;AAAA,IAEA,mBAAmB,UAAU;AAC3B,UAAI,OAAO,aAAa,YAAa,QAAO,MAAM;AAAA,MAAC;AACnD,YAAM,UAAU,MAAM,SAAS,SAAS,oBAAoB,SAAS;AACrE,eAAS,iBAAiB,oBAAoB,OAAO;AACrD,aAAO,MAAM,SAAS,oBAAoB,oBAAoB,OAAO;AAAA,IACvE;AAAA,IAEA,SAAS,UAAU;AACjB,UAAI,OAAO,WAAW,YAAa,QAAO,MAAM;AAAA,MAAC;AACjD,YAAM,UAAU,MAAM,SAAS;AAC/B,aAAO,iBAAiB,UAAU,OAAO;AACzC,aAAO,MAAM,OAAO,oBAAoB,UAAU,OAAO;AAAA,IAC3D;AAAA,EACF;AACF;;;ACXO,SAAS,4BAA4B,UAA0B,CAAC,GAAoB;AACzF,QAAM,MAAM,QAAQ,OAAO,yBAAyB;AACpD,QAAM,gBAA+B;AAAA,IACnC,GAAG;AAAA,IACH,GAAI,QAAQ,iBAAiB,CAAC;AAAA,EAChC;AAEA,MAAI,WAAW,qBAAqB;AACpC,QAAM,MAA2B,qBAAqB;AACtD,QAAM,YAAY,oBAAI,IAAgB;AAEtC,MAAI,UAAU;AACd,MAAI,QAAgC;AACpC,MAAI,eAAoC;AACxC,MAAI,kBAA0C;AAC9C,MAAI,sBAAkD;AACtD,MAAI,iBAAwC;AAC5C,MAAI,kBAA0C;AAE9C,MAAI,mCAAmC;AAEvC,QAAM,WAA8B,QAAQ,WAAW,CAAC;AACxD,QAAM,sBAAsB,QAAQ,uBAAuB;AAE3D,QAAM,SAAS,MAAM;AACnB,eAAW,KAAK,WAAW;AACzB,UAAI;AACF,UAAE;AAAA,MACJ,SAAS,KAAK;AACZ,gBAAQ,UAAU,KAAK,UAAU;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW,CAAC,WAAwB;AACxC,UAAM,OAAO;AACb,UAAM,OAAO,aAAa,MAAM,QAAQ,KAAK,aAAa;AAC1D,QAAI,SAAS,MAAM;AACjB,iBAAW;AAEX,mBAAa,MAAM,IAAI;AACvB,aAAO;AAAA,IACT;AAAA,EACF;AAWA,QAAM,eAAe,CAAC,MAA2B,SAA8B;AAC7E,QAAI,KAAK,UAAU,UAAU,iBAAiB,KAAK,UAAU,UAAU,eAAe;AACpF,sBAAgB;AAGhB,0BAAoB;AAAA,IACtB;AACA,QAAI,KAAK,UAAU,UAAU,YAAY,KAAK,UAAU,UAAU,UAAU;AAC1E,qBAAe;AACf,sBAAgB;AAChB,UAAI,kCAAkC;AACpC,2CAAmC;AACnC,iDAAyC,MAAM,UAAU,GAAG;AAAA,MAC9D;AAAA,IACF;AACA,QAAI,KAAK,UAAU,UAAU,YAAY,KAAK,UAAU,UAAU,UAAU;AAE1E,uBAAiB,OAAO;AACxB,wBAAkB;AAAA,IACpB;AAAA,EACF;AAEA,QAAM,eAAe,MAAM;AACzB,QAAI,CAAC,MAAO;AACZ,kBAAc,OAAO;AACrB,mBAAe,kBAAkB,KAAK,UAAU,MAAM,QAAQ,QAAQ,MAAM;AAAA,EAC9E;AAEA,QAAM,kBAAkB,MAAM;AAC5B,QAAI,CAAC,MAAO;AACZ,qBAAiB,OAAO;AACxB,sBAAkB;AAAA,MAChB;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN,kBAAkB,OAAO;AAAA,MACzB,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,sBAAsB,MAAM;AAChC,QAAI,CAAC,MAAO;AACZ,QAAI,oBAAqB;AACzB,0BAAsB,oBAAoB;AAAA,MACxC;AAAA,MACA,eAAe,MAAM,SAAS;AAAA,MAC9B,iBAAiB,CAAC,MAChB,gBAAgB,oBAAoB,iBAAiB,CAAC;AAAA,MACxD,kBAAkB,CAAC,MACjB,gBAAgB,oBAAoB,kBAAkB,CAAC;AAAA,MACzD,oBAAoB,CAAC,MACnB,gBAAgB,oBAAoB,qBAAqB,CAAC;AAAA,IAC9D,CAAC;AAAA,EACH;AAEA,QAAM,iBAAiB,MAAM;AAC3B,QAAI,CAAC,MAAO;AACZ,wBAAoB;AACpB,QAAI,eAAgB;AACpB,qBAAiB;AAAA,MACf;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,MAAM,SAAS;AAAA,MACf,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,kBAAkB,MAAM;AAC5B,QAAI,CAAC,MAAO;AACZ,QAAI,QAAQ,cAAc,MAAO;AACjC,QAAI,gBAAiB;AACrB,sBAAkB;AAAA,MAChB;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN,QAAQ,aAAa,CAAC;AAAA,IACxB;AAAA,EACF;AAEA,QAAM,mBAAmB,MAAM;AAC7B,kBAAc,OAAO;AACrB,mBAAe;AACf,qBAAiB,OAAO;AACxB,sBAAkB;AAClB,oBAAgB,OAAO;AACvB,qBAAiB;AACjB,qBAAiB,OAAO;AACxB,sBAAkB;AAClB,QAAI,SAAS,CAAC,MAAM,OAAO,QAAS,OAAM,MAAM;AAAA,EAClD;AAEA,QAAM,WAA4B;AAAA,IAChC,QAAQ;AACN,UAAI,QAAS;AACb,gBAAU;AACV,cAAQ,IAAI,gBAAgB;AAC5B,mBAAa;AAAA,IACf;AAAA,IACA,OAAO;AACL,UAAI,CAAC,QAAS;AACd,gBAAU;AACV,uBAAiB;AACjB,2BAAqB,OAAO;AAC5B,4BAAsB;AAEtB,iBAAW,qBAAqB;AAChC,aAAO;AAAA,IACT;AAAA,IACA,SAAS;AACP,UAAI,CAAC,SAAS;AACZ,iBAAS,MAAM;AACf;AAAA,MACF;AACA,yCAAmC;AACnC,UAAI;AACF,gBAAQ,iBAAiB;AAAA,MAC3B,SAAS,KAAK;AACZ,gBAAQ,UAAU,KAAK,gBAAgB;AAAA,MACzC;AACA,uBAAiB;AAEjB,eAAS,EAAE,MAAM,mBAAmB,MAAM,IAAI,IAAI,GAAG,QAAQ,SAAS,CAAC;AAEvE,iBAAW;AAAA,QACT,GAAG,qBAAqB;AAAA,QACxB,YAAY,eAAe,SAAS,UAAU;AAAA,MAChD;AACA,UAAI,WAAW;AACf,cAAQ,IAAI,gBAAgB;AAC5B,mBAAa;AACb,aAAO;AAAA,IACT;AAAA,IACA,UAAU;AACR,eAAS,OAAO;AAEhB,UAAI,OAAO,WAAW,eAAe,OAAO,OAAO,UAAU,WAAW,YAAY;AAClF,YAAI;AACF,iBAAO,SAAS,OAAO;AAAA,QACzB,SAAS,KAAK;AACZ,kBAAQ,UAAU,KAAK,SAAS;AAAA,QAClC;AAAA,MACF;AAAA,IACF;AAAA,IACA,UAAU,UAAU;AAClB,gBAAU,IAAI,QAAQ;AACtB,aAAO,MAAM,UAAU,OAAO,QAAQ;AAAA,IACxC;AAAA,IACA,aAAa,MAAM;AAAA,IACnB;AAAA,IACA,mBAAmB;AACjB,uBAAiB,iBAAiB;AAAA,IACpC;AAAA,IACA,mBAAmB;AACjB,uBAAiB,iBAAiB;AAAA,IACpC;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,kBAAkB,SAA4C;AACrE,QAAM,UAA6B;AAAA,IACjC,gBAAgB,QAAQ,kBAAkB;AAAA,IAC1C,SAAS,QAAQ,WAAW,CAAC;AAAA,EAC/B;AACA,MAAI,QAAQ,kBAAkB,OAAW,SAAQ,gBAAgB,QAAQ;AACzE,MAAI,QAAQ,qBAAqB,OAAW,SAAQ,mBAAmB,QAAQ;AAC/E,MAAI,QAAQ,cAAe,SAAQ,gBAAgB,QAAQ;AAC3D,SAAO;AACT;;;ACzUA,IAAI,WAAgC;AAE7B,SAAS,gCAAgC,SAA0C;AACxF,MAAI,CAAC,UAAU;AACb,eAAW;AAAA,MACT,SAAS,4BAA4B,OAAO;AAAA,MAC5C,UAAU;AAAA,IACZ;AACA,aAAS,QAAQ,MAAM;AAAA,EACzB;AACA,WAAS,YAAY;AACrB,SAAO,SAAS;AAClB;AAEO,SAAS,kCAAwC;AACtD,MAAI,CAAC,SAAU;AACf,WAAS,YAAY;AACrB,MAAI,SAAS,YAAY,GAAG;AAC1B,aAAS,QAAQ,KAAK;AACtB,eAAW;AAAA,EACb;AACF;;;AZpBO,IAAM,mCAA+B,4BAAsC,IAAI;AAG/E,SAAS,0BAAkD;AAChE,aAAO,yBAAW,4BAA4B;AAChD;AASO,SAAS,gBAAgB,SAAqD;AACnF,QAAM,mBAAe,yBAAW,4BAA4B;AAC5D,QAAM,iBAAa,qBAAO,OAAO;AACjC,aAAW,UAAU;AAErB,QAAM,kBAAc,qBAA+B,IAAI;AACvD,QAAM,sBAAkB,qBAAO,KAAK;AAEpC,MAAI,cAAc;AAChB,WAAO;AAAA,EACT;AAEA,MAAI,YAAY,YAAY,MAAM;AAChC,gBAAY,UAAU;AAAA,MACpB,oCAAoC,WAAW,OAAO;AAAA,IACxD;AACA,oBAAgB,UAAU;AAAA,EAC5B;AAEA,8BAAU,MAAM;AACd,QAAI,CAAC,gBAAgB,QAAS;AAC9B,WAAO,MAAM;AACX,sCAAgC;AAChC,kBAAY,UAAU;AACtB,sBAAgB,UAAU;AAAA,IAC5B;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SAAO,YAAY;AACrB;;;AahEA,IAAAC,iBAKO;;;ACLP,IAAAC,gBAAiE;;;ACG1D,SAAS,2BACd,QAC+B;AAC/B,QAAM,EAAE,MAAM,WAAW,cAAc,QAAQ,OAAO,kBAAkB,SAAS,iBAAiB,OAAO,YAAY,gBAAgB,cAAc,IACjJ;AACF,SAAO;AAAA,IACL,QAAQ,KAAK;AAAA,IACb,aAAa,KAAK;AAAA,IAClB,SAAS,KAAK;AAAA,IACd,OAAO,KAAK;AAAA,IACZ,cAAc,KAAK;AAAA,IACnB,QAAQ,UAAU;AAAA,IAClB,SAAS,UAAU;AAAA,IACnB,cAAc,UAAU;AAAA,IACxB,UAAU,UAAU;AAAA,IACpB,iBAAiB,UAAU;AAAA,IAC3B,qBAAqB,UAAU;AAAA,IAC/B,MAAM,UAAU;AAAA,IAChB,uBAAuB,UAAU;AAAA,IACjC,SAAS,UAAU;AAAA,IACnB,gBAAgB,UAAU;AAAA,IAC1B,aAAa,UAAU;AAAA,IACvB,mBAAmB,UAAU;AAAA,IAC7B,gBAAgB,aAAa;AAAA,IAC7B,qBAAqB,aAAa;AAAA,IAClC,qBAAqB,aAAa;AAAA,IAClC,OAAO,OAAO;AAAA,IACd,UAAU,OAAO;AAAA,IACjB,cAAc,OAAO;AAAA,IACrB,aAAa,OAAO;AAAA,IACpB,cAAc,OAAO;AAAA,IACrB,QAAQ,KAAK;AAAA,IACb,YAAY,MAAM;AAAA,IAClB,gBAAgB,MAAM;AAAA,IACtB,UAAU,MAAM;AAAA,IAChB,YAAY,MAAM;AAAA,IAClB,aAAa,MAAM;AAAA,IACnB,YAAY,MAAM;AAAA,IAClB,gCAAgC,MAAM;AAAA,IACtC,kBAAkB,gBAAgB;AAAA,IAClC,uBAAuB,gBAAgB;AAAA,IACvC,qBAAqB,gBAAgB;AAAA,IACrC,eAAe,UAAU;AAAA,IACzB,mBAAmB,UAAU;AAAA,IAC7B,kBAAkB,iBAAiB;AAAA,IACnC,iBAAiB,iBAAiB;AAAA,IAClC,iBAAiB,iBAAiB;AAAA,IAClC,kBAAkB,iBAAiB;AAAA,IACnC,oBAAoB,iBAAiB;AAAA,IACrC,oBAAoB,iBAAiB;AAAA,IACrC,oBAAoB,MAAM;AAAA,IAC1B,qBAAqB,MAAM;AAAA,IAC3B,WAAW,MAAM,aAAa,gBAAgB;AAAA,IAC9C,mBAAmB,QAAQ;AAAA,IAC3B,uBAAuB,QAAQ;AAAA,IAC/B,gBAAgB,gBAAgB;AAAA,IAChC,eAAe,gBAAgB;AAAA,IAC/B,kBAAkB,gBAAgB;AAAA,IAClC,OAAO,MAAM;AAAA,IACb,WAAW,WAAW;AAAA,IACtB,iBAAiB,WAAW;AAAA,IAC5B;AAAA,IACA;AAAA,EACF;AACF;;;AD7CO,IAAM,uBAAmB,6BAA4C,IAAI;AACzE,IAAM,4BAAwB,6BAA8C,IAAI;AAChF,IAAM,+BAA2B,6BAAiD,IAAI;AACtF,IAAM,yBAAqB,6BAAkD,IAAI;AACjF,IAAM,wBAAoB,6BAA0C,IAAI;AACxE,IAAM,mCAA+B,6BAAqD,IAAI;AAC9F,IAAM,0BAAsB,6BAA4C,IAAI;AAC5E,IAAM,kCAA8B,6BAAoD,IAAI;AAC5F,IAAM,wBAAoB,6BAA0C,IAAI;AACxE,IAAM,6BAAyB,6BAA+C,IAAI;AAEzF,SAAS,mBAAsB,KAAwB,MAAiB;AACtE,QAAM,YAAQ,0BAAW,GAAG;AAC5B,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,GAAG,IAAI,4CAA4C;AAAA,EACrE;AACA,SAAO;AACT;AAEO,SAAS,sBAA6C;AAC3D,SAAO,mBAAmB,kBAAkB,uBAAuB;AACrE;AAEO,SAAS,2BAG4B;AAC1C,SAAO,mBAAmB,uBAAuB,4BAA4B;AAI/E;AAEO,SAAS,8BAA0D;AACxE,SAAO,mBAAmB,0BAA0B,+BAA+B;AACrF;AAEO,SAAS,wBAAqD;AACnE,SAAO,mBAAmB,oBAAoB,yBAAyB;AACzE;AAEO,SAAS,uBAA4C;AAC1D,SAAO,mBAAmB,mBAAmB,wBAAwB;AACvE;AAEO,SAAS,kCAAkE;AAChF,SAAO,mBAAmB,8BAA8B,mCAAmC;AAC7F;AAEO,SAAS,yBAAgD;AAC9D,SAAO,mBAAmB,qBAAqB,0BAA0B;AAC3E;AAEO,SAAS,iCAAgE;AAC9E,SAAO,mBAAmB,6BAA6B,kCAAkC;AAC3F;AAEO,SAAS,uBAA4C;AAC1D,SAAO,mBAAmB,mBAAmB,wBAAwB;AACvE;AAEO,SAAS,4BAAsD;AACpE,SAAO,mBAAmB,wBAAwB,6BAA6B;AACjF;AAMO,SAAS,uBAGmB;AACjC,QAAM,OAAO,oBAAoB;AACjC,QAAM,YAAY,yBAAwC;AAC1D,QAAM,eAAe,4BAA4B;AACjD,QAAM,SAAS,sBAAsB;AACrC,QAAM,QAAQ,qBAAqB;AACnC,QAAM,mBAAmB,gCAAgC;AACzD,QAAM,UAAU,uBAAuB;AACvC,QAAM,kBAAkB,+BAA+B;AACvD,QAAM,QAAQ,qBAAqB;AACnC,QAAM,aAAa,0BAA0B;AAE7C,aAAO;AAAA,IACL,MACE,2BAA0C;AAAA,MACxC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAA8B;AAAA,IAChC;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AErIA,IAAAC,iBAAuD;;;ACAvD,IAAAC,iBAAwB;;;ACAxB,IAAAC,gBAA2D;AAoCpD,SAAS,gCACd,UACgB;AAChB,QAAM,EAAE,MAAM,IAAI,SAAS;AAC3B,MAAI,UAAU,UAAU,UAAU,YAAa,QAAO;AACtD,MAAI,UAAU,cAAc;AAC1B,UAAM,SAAS,SAAS,UAAU,OAAO;AACzC,QAAI,WAAW,kBAAkB,WAAW,iBAAkB,QAAO;AACrE,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAKO,SAAS,aAAa,SAAmD;AAC9E,QAAM,UAAU,gBAAgB,OAAO;AACvC,SAAO,wBAAwB,OAAO;AACxC;AAMO,SAAS,wBAAwB,SAA8C;AACpF,QAAM,eAAW;AAAA,IACf,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR;AAAA,EACF;AACA,QAAM,SAAS,aAAa,QAAQ;AACpC,QAAM,QAAQ,mBAAmB,QAAQ;AACzC,QAAM,aAAS,uBAA4B,MAAM;AAC/C,QAAI,SAAS,UAAU,UAAU,SAAU,QAAO;AAClD,QAAI,OAAO,UAAU,YAAa,QAAO;AACzC,WAAO,MAAM,UAAU;AAAA,EACzB,GAAG,CAAC,SAAS,UAAU,OAAO,SAAS,UAAU,CAAC;AAClD,QAAM,cAAc,gCAAgC,QAAQ;AAC5D,QAAM,aAAS,2BAAY,YAAY;AACrC,YAAQ,OAAO;AAAA,EACjB,GAAG,CAAC,OAAO,CAAC;AACZ,QAAM,mBAAe,uBAAQ,MAAM,mBAAmB,QAAQ,GAAG,CAAC,QAAQ,CAAC;AAC3E,aAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,SAAS,WAAW;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,aAAa,OAAO,QAAQ,cAAc,MAAM;AAAA,EAC3D;AACF;;;AC3FA,IAAAC,gBAAsE;;;ACsBtE,IAAAC,gBAA4B;AAMrB,SAAS,0BAAgD;AAC9D,QAAM,UAAU,wBAAwB;AACxC,aAAO;AAAA,IACL,OAAO,OAAO;AACZ,UAAI;AACF,cAAM,SAAS,MAAM,GAAG;AACxB,iBAAS,iBAAiB;AAC1B,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AACF;;;AD3BO,SAAS,qBAAqB,QAAwD;AAC3F,QAAM,UAAU,gBAAgB;AAChC,QAAM,cAAc,wBAAwB;AAC5C,QAAM,eAAW;AAAA,IACf,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR;AAAA,EACF;AAEA,QAAM,eAAe,SAAS,KAAK;AACnC,QAAM,iBACJ,aAAa,UAAU,UAAU,aAAa,UAAU;AAC1D,QAAM,sBACJ,aAAa,UAAU,UAAU,aAAa,aAAa;AAC7D,QAAM,aACJ,aAAa,UAAU,YAAY,aAAa,UAAU;AAE5D,QAAM,0BAAsB,2BAAY,YAAY;AAClD,QAAI,CAAC,OAAQ;AACb,QAAI,OAAO,UAAU,YAAa;AAClC,UAAM,OAAO,KAAK,IAAI;AACtB,YAAQ,SAAS,EAAE,MAAM,+BAA+B,KAAK,CAAC;AAC9D,QAAI;AACF,YAAM,OAAO,MAAM;AAAA,QAAY,MAC7B,QAAQ,QAAQ,MAAM,eAAe,WAAW,CAAC;AAAA,MACnD;AACA,UAAI,MAAM;AACR,gBAAQ,SAAS,EAAE,MAAM,uBAAuB,SAAS,MAAM,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,MACnF;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,cAAQ,SAAS,EAAE,MAAM,uBAAuB,SAAS,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,IAC7E;AAAA,EACF,GAAG,CAAC,QAAQ,aAAa,OAAO,CAAC;AAEjC,+BAAU,MAAM;AACd,QAAI,OAAQ,MAAK,oBAAoB;AAAA,EACvC,GAAG,CAAC,QAAQ,mBAAmB,CAAC;AAEhC,+BAAU,MAAM;AACd,WAAO,YAAY,UAAU,MAAM;AACjC,UAAI,CAAC,OAAQ;AACb,WAAK,oBAAoB;AAAA,IAC3B,CAAC;AAAA,EACH,GAAG,CAAC,QAAQ,mBAAmB,CAAC;AAEhC,aAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,gBAAgB,qBAAqB,qBAAqB,UAAU;AAAA,EACvE;AACF;;;AEtEA,IAAAC,gBAAkE;AAwBlE,IAAM,iBAAuC,OAAO,OAAO,CAAC,CAAC;AAE7D,SAAS,0BACP,MACA,cACA,SAC8B;AAC9B,QAAM,OAAO,0BAA0B,cAAc,OAAO;AAC5D,MACE,QACA,KAAK,OAAO,KAAK,MACjB,KAAK,YAAY,KAAK,WACtB,KAAK,QAAQ,WAAW,KAAK,QAAQ,UACrC,KAAK,eAAe,WAAW,KAAK,eAAe,UACnD,KAAK,QAAQ,MAAM,CAAC,GAAG,MAAM,MAAM,KAAK,QAAQ,CAAC,CAAC,KAClD,KAAK,eAAe,MAAM,CAAC,GAAG,MAAM,MAAM,KAAK,eAAe,CAAC,CAAC,GAChE;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AA+BA,SAAS,cAAiB,QAAkE;AAC1F,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,EAAE,GAAG,OAAO;AACrB;AAEA,SAAS,eAAkB,SAAuE;AAChG,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,QAAQ,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,EAAE;AAC1C;AAEA,SAAS,iBAAoB,QAA2B;AACtD,MAAI,WAAW,QAAQ,WAAW,OAAW,QAAO;AACpD,MAAI,OAAO,WAAW,SAAU,QAAO;AACvC,SAAO,EAAE,GAAI,OAAmC;AAClD;AAEA,SAAS,gBAAgB,OAAkC;AACzD,SAAO,KAAK,UAAU,KAAK;AAC7B;AAGA,SAAS,uBAAuB;AAC9B,QAAM,UAAU,gBAAgB;AAChC,QAAM,CAAC,cAAc,eAAe,QAAI;AAAA,IACtC,MAAM,QAAQ,YAAY,EAAE,OAAO;AAAA,EACrC;AACA,+BAAU,MAAM;AACd,QAAI,UAAU,gBAAgB,QAAQ,YAAY,EAAE,OAAO,QAAQ;AACnE,WAAO,QAAQ,UAAU,MAAM;AAC7B,YAAM,OAAO,QAAQ,YAAY,EAAE,OAAO;AAC1C,YAAM,UAAU,gBAAgB,IAAI;AACpC,UAAI,YAAY,SAAS;AACvB,kBAAU;AACV,wBAAgB,IAAI;AAAA,MACtB;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAAC,OAAO,CAAC;AACZ,SAAO;AACT;AAEO,SAAS,8BACd,QACA,SACwC;AACxC,QAAM,2BAA2B,SAAS,4BAA4B;AACtE,QAAM,uBAAuB,SAAS,wBAAwB;AAC9D,QAAM,eAAe,qBAAqB;AAE1C,QAAM,CAAC,QAAQ,SAAS,QAAI,wBAAsC,IAAI;AACtE,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAwC,IAAI;AAC1E,QAAM,CAAC,cAAc,eAAe,QAAI,wBAAyB,IAAI;AACrE,QAAM,CAAC,gBAAgB,iBAAiB,QAAI,wBAAsC,IAAI;AACtF,QAAM,CAAC,iBAAiB,kBAAkB,QAAI,wBAAsC,IAAI;AACxF,QAAM,CAAC,eAAe,sBAAsB,QAAI,wBAAyC,IAAI;AAC7F,QAAM,CAAC,mBAAmB,oBAAoB,QAAI,wBAAwC,IAAI;AAC9F,QAAM,CAAC,aAAa,cAAc,QAAI,wBAAS,KAAK;AACpD,QAAM,CAAC,mBAAmB,oBAAoB,QAAI,wBAAsC,IAAI;AAC5F,QAAM,CAAC,gBAAgB,iBAAiB,QAAI,wBAA4B,CAAC,CAAC;AAC1E,QAAM,wBAAoB,sBAA0B,CAAC,CAAC;AAEtD,QAAM,cAAc,wBAAwB,YAAY;AACxD,QAAM,eAAW;AAAA,IACf,MAAM,eAAe,kBAAkB;AAAA,IACvC,CAAC,aAAa,cAAc;AAAA,EAC9B;AAEA,QAAM,6BAAyB,sBAAiD,MAAS;AACzF,QAAM,0BAAsB,uBAAQ,MAAM;AACxC,UAAM,OAAO;AAAA,MACX,uBAAuB;AAAA,MACvB;AAAA,MACA,SAAS;AAAA,IACX;AACA,2BAAuB,UAAU;AACjC,WAAO;AAAA,EACT,GAAG,CAAC,cAAc,SAAS,OAAO,CAAC;AAEnC,QAAM,yBAAqB;AAAA,IACzB,CAAC,EAAE,QAAQ,MAAM,UAAU,aAAa,MAA0B;AAChE,wBAAkB,YAAY;AAC9B,gBAAU,cAAoB,IAAI,CAAC;AACnC,UAAI,CAAC,MAAM;AACT,wBAAgB,IAAI;AACpB;AAAA,MACF;AACA,qBAAe,KAAK;AACpB,UAAI,OAAO,UAAU,eAAe,OAAO,MAAM,mBAAmB,YAAY;AAC9E,wBAAgB,iBAA0B,MAAM,eAAe,IAAI,CAAC,CAAC;AAAA,MACvE,OAAO;AACL,wBAAgB,iBAA0B,IAAI,CAAC;AAAA,MACjD;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACH;AAMA,+BAAU,MAAM;AACd,QAAI,OAAO,UAAU,YAAa;AAClC,WAAO,YAAY,UAAU,kBAAkB;AAAA,EACjD,GAAG,CAAC,kBAAkB,CAAC;AAEvB,+BAAU,MAAM;AACd,QAAI,OAAO,UAAU,YAAa;AAClC,WAAO,aAAa,UAAU,CAAC,EAAE,SAAS,MAAM,UAAU,aAAa,MAAM;AAC3E,iBAAW,eAAqB,IAAI,CAAC;AACrC,yBAAmB,YAAY;AAAA,IACjC,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,+BAAU,MAAM;AACd,QAAI,CAAC,4BAA4B,OAAO,UAAU,YAAa;AAC/D,WAAO,aAAa,UAAU,CAAC,EAAE,SAAS,MAAM,YAAY,MAAM;AAChE,6BAAuB,IAAI;AAC3B,2BAAqB,WAAW;AAAA,IAClC,CAAC;AAAA,EACH,GAAG,CAAC,wBAAwB,CAAC;AAE7B,+BAAU,MAAM;AACd,QAAI,CAAC,wBAAwB,OAAO,UAAU,YAAa;AAC3D,QAAI,OAAO,MAAM,gBAAgB,WAAY;AAC7C,WAAO,eAAe,UAAU,CAAC,EAAE,UAAU,aAAa,MAAM;AAC9D,qBAAe,IAAI;AACnB,2BAAqB,YAAY;AAAA,IACnC,CAAC;AAAA,EACH,GAAG,CAAC,oBAAoB,CAAC;AAEzB,QAAM,oBAAgB,sBAA2B,IAAI;AAKrD,+BAAU,MAAM;AACd,UAAM,YAAY,cAAc,YAAY;AAC5C,kBAAc,UAAU;AAExB,QAAI,QAAQ;AACV,UAAI,CAAC,aAAa,YAAY,OAAO;AACnC,cAAM,SAAS,YAAY,KAAK;AAChC,YAAI,WAAW,OAAW,oBAAmB,MAAM;AAAA,MACrD;AACA;AAAA,IACF;AAEA,QAAI,CAAC,UAAW;AAEhB,cAAU,IAAI;AACd,eAAW,IAAI;AACf,oBAAgB,IAAI;AACpB,sBAAkB,IAAI;AACtB,uBAAmB,IAAI;AACvB,mBAAe,KAAK;AACpB,yBAAqB,IAAI;AACzB,2BAAuB,IAAI;AAC3B,yBAAqB,IAAI;AAAA,EAC3B,GAAG,CAAC,QAAQ,kBAAkB,CAAC;AAE/B,QAAM,4BAAwB;AAAA,IAC5B,CAAC,qBAAqC;AACpC,YAAM,QAAQ,SAAS,gBAAgB;AACvC,UAAI,OAAO,UAAU,SAAU,QAAO;AACtC,UAAI,MAAM,QAAQ,KAAK,KAAK,OAAO,MAAM,CAAC,MAAM,SAAU,QAAO,MAAM,CAAC;AACxE,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,QAAM,cAAU;AAAA,IACd,CAAC,UAAqD;AACpD,YAAM,UAAoB,CAAC;AAC3B,iBAAW,QAAQ,OAAO,KAAK,KAAgC,GAAG;AAChE,YAAI,MAAM,QAAQ,SAAS,IAAI,CAAC,EAAG,SAAQ,KAAK,IAAI;AAAA,MACtD;AAEA,YAAM,gBAAgB,MAA+B;AACnD,YAAI,OAAO,MAAM,uBAAuB,YAAY;AAClD,gBAAMC,OAAM,MAAM,mBAAmB,KAAgC;AAQrE,qBAAW,OAAO,OAAO,KAAKA,IAAG,GAAG;AAClC,gBAAIA,KAAI,GAAG,MAAM,QAAW;AAC1B,qBAAOA,KAAI,GAAG;AAAA,YAChB;AAAA,UACF;AACA,iBAAOA;AAAA,QACT;AACA,cAAM,MAA+B,CAAC;AACtC,mBAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,KAAgC,GAAG;AAC5E,gBAAM,SAAS,SAAS,IAAI;AAC5B,cAAI,MAAM,QAAQ,MAAM,EAAG;AAC3B,cAAI,UAAU,IAAI,IAAI;AAAA,QACxB;AACA,eAAO;AAAA,MACT;AAEA,YAAM,SAAS,cAAc;AAE7B,YAAM,WAAW,kBAAkB;AACnC,YAAM,OACJ,SAAS,WAAW,QAAQ,UAC5B,SAAS,MAAM,CAAC,MAAM,MAAM,SAAS,QAAQ,CAAC,CAAC;AACjD,UAAI,CAAC,MAAM;AACT,0BAAkB,UAAU;AAC5B,0BAAkB,OAAO;AAAA,MAC3B;AAEA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,QAAM,OAAwB,cAAc,YAAY,SAAS,QAAQ;AAEzE,aAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;ACzUA,IAAAC,gBAAuD;AA6BvD,SAAS,0BAAgD;AACvD,MAAI,MAAM,cAAe,QAAO,MAAM;AACtC,QAAM,IAAI,MAAM,4DAA4D;AAC9E;AAEA,SAAS,gBAAgB,SAAuC;AAC9D,MAAI,OAAO,MAAM,aAAa,YAAY;AACxC,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AACA,SAAO,MAAM,SAAS,OAAO;AAC/B;AAEO,SAAS,sBAAsB,QAAyD;AAC7F,QAAM,CAAC,cAAc,eAAe,QAAI,wBAAkC,MAAM;AAChF,QAAM,CAAC,aAAa,cAAc,QAAI,wBAAwB,IAAI;AAClE,QAAM,oBAAgB,sBAAO,oBAAI,IAAkC,CAAC;AACpE,QAAM,cAAc,wBAAwB;AAE5C,QAAM,cAAU;AAAA,IACd,OAAU,OAAqC;AAC7C,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,sBAAgB,SAAS;AACzB,qBAAe,IAAI;AACnB,UAAI;AACF,cAAM,MAAM,MAAM,YAAY,EAAE;AAChC,wBAAgB,MAAM;AACtB,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,cAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,uBAAe,OAAO;AACtB,wBAAgB,OAAO;AACvB,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,WAAW;AAAA,EACtB;AAEA,QAAM,mBAAe;AAAA,IACnB,CAAC,aAA+D;AAAA,MAC9D,YAAY,MAAM,QAAQ,MAAM,QAAQ,EAAE,WAAW,CAAC;AAAA,MACtD,QAAQ,CACN,SACA,cAEA,QAAQ,MAAM,QAAQ,EAAE,OAAO,SAAS,SAAS,CAAC;AAAA,MACpD,QAAQ,CACN,SACA,cACG,QAAQ,MAAM,QAAQ,EAAE,OAAO,SAAS,SAAS,CAAC;AAAA,MACvD,QAAQ,CACN,SACA,cACG,QAAQ,MAAM,QAAQ,EAAE,OAAO,SAAS,SAAS,CAAC;AAAA,MACvD,SAAS,CAAC,cACR,QAAQ,MAAM,QAAQ,EAAE,QAAQ,SAAS,CAAC;AAAA,IAC9C;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAEA,QAAM,YAAQ,uBAAQ,MAAM,aAAa,MAAM,wBAAwB,CAAC,GAAG,CAAC,YAAY,CAAC;AAEzF,QAAM,eAAW;AAAA,IACf,CAAC,YAAoB;AACnB,YAAM,SAAS,cAAc,QAAQ,IAAI,OAAO;AAChD,UAAI,OAAQ,QAAO;AACnB,YAAM,UAAU,aAAa,MAAM,gBAAgB,OAAO,CAAC;AAC3D,oBAAc,QAAQ,IAAI,SAAS,OAAO;AAC1C,aAAO;AAAA,IACT;AAAA,IACA,CAAC,YAAY;AAAA,EACf;AAEA,QAAM,mBAAe;AAAA,IACnB,OAAO,SAAiC,iBAAkE;AACxG,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,2BAA2B;AACxD,sBAAgB,SAAS;AACzB,qBAAe,IAAI;AACnB,UAAI;AACF,cAAM,MAAM,MAAM,YAAY,MAAM,OAAO,iBAAiB,SAAS,YAAY,CAAC;AAClF,wBAAgB,MAAM;AACtB,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,cAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,uBAAe,OAAO;AACtB,wBAAgB,OAAO;AACvB,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,WAAW;AAAA,EACtB;AAEA,aAAO;AAAA,IACL,OAAO,EAAE,OAAO,UAAU,cAAc,aAAa,aAAa;AAAA,IAClE,CAAC,OAAO,UAAU,cAAc,aAAa,YAAY;AAAA,EAC3D;AACF;;;AC5HA,IAAAC,gBAAuD;AAyBvD,IAAM,0BAAqD;AAAA,EACzD,aAAa;AAAA,EACb,QAAQ;AACV;AA+CO,SAAS,cAAc,QAAiD;AAC7E,QAAM,cAAc,wBAAwB;AAC5C,QAAM,UAAU,wBAAwB;AACxC,QAAM,CAAC,WAAW,YAAY,QAAI,wBAAwB,IAAI;AAC9D,QAAM,mBAAe,sBAAsB,IAAI;AAa/C,QAAM,wBAAoB;AAAA,IACxB,CAAC,UAAkB;AACjB,YAAM,OAAO,SAAS,YAAY;AAClC,UAAI,CAAC,KAAM;AACX,YAAM,EAAE,OAAO,KAAK,IAAI;AACxB,UAAI,KAAK,QAAQ,UAAU,MAAO;AAClC,UAAI,MAAM,UAAU,aAAa,MAAM,UAAU,QAAQ;AACvD,cAAM,MACJ,GAAG,KAAK,8DACoB,MAAM,KAAK;AAEzC,YAAI,aAAa,YAAY,KAAK;AAChC,uBAAa,UAAU;AACvB,uBAAa,GAAG;AAAA,QAClB;AACA,cAAM,IAAI,MAAM,GAAG;AAAA,MACrB;AAAA,IACF;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAGA,QAAM,iBAAa;AAAA,IACjB,OAAU,OAAqC;AAC7C,UAAI;AACF,cAAM,SAAS,MAAM,YAAY,EAAE;AACnC,YAAI,aAAa,YAAY,MAAM;AACjC,uBAAa,UAAU;AACvB,uBAAa,IAAI;AAAA,QACnB;AACA,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,cAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,YAAI,0BAA0B,GAAG,GAAG;AAClC,cAAI,aAAa,YAAY,KAAK;AAChC,yBAAa,UAAU;AACvB,yBAAa,GAAG;AAAA,UAClB;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,iBAAa;AAAA,IACjB,OAAO,YAAoB;AACzB,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,wBAAkB,YAAY;AAC9B,aAAO,WAAW,MAAM,OAAO,WAAW,OAAO,CAAgC;AAAA,IACnF;AAAA,IACA,CAAC,QAAQ,mBAAmB,UAAU;AAAA,EACxC;AAEA,QAAM,eAAW;AAAA,IACf,OAAoC,SAAiB,UAAkB;AACrE,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,wBAAkB,UAAU;AAC5B,aAAO,WAAW,MAAM,cAAiB,QAAQ,SAAS,KAAK,CAAC;AAAA,IAClE;AAAA,IACA,CAAC,QAAQ,mBAAmB,UAAU;AAAA,EACxC;AAEA,QAAM,qBAAiB;AAAA,IACrB,OACE,SACA,YACG;AACH,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,wBAAkB,gBAAgB;AAClC,UAAI,SAAS,WAAW;AACtB,eAAO;AAAA,UAAW,MAChB;AAAA,YACE;AAAA,YACA;AAAA,YACA;AAAA,UAGF;AAAA,QACF;AAAA,MACF;AACA,UAAI,SAAS;AACX,eAAO,WAAW,MAAM,oBAAuB,QAAQ,SAAS,OAAO,CAAC;AAAA,MAC1E;AACA,aAAO,WAAW,MAAM,oBAAuB,QAAQ,OAAO,CAAC;AAAA,IACjE;AAAA,IACA,CAAC,QAAQ,mBAAmB,UAAU;AAAA,EACxC;AAEA,QAAM,iBAAa;AAAA,IACjB,OAAO,YAAgC;AACrC,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,aAAO,WAAW,YAAY;AAC5B,cAAM,MAAM,MAAM,QAAQ,QAAQ,OAAO,WAAW,CAAC;AACrD,cAAM,SAAS,CAAC,GAAG,GAAG;AACtB,YAAI,SAAS,cAAe,QAAO;AACnC,eAAO,OAAO;AAAA,UACZ,CAAC,MAAM,CAAC,EAAE,WAAW,QAAQ,KAAK,CAAC,EAAE,WAAW,cAAc;AAAA,QAChE;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA,CAAC,QAAQ,UAAU;AAAA,EACrB;AAEA,QAAM,kBAAc;AAAA,IAClB,OAAO,SAAiB,YAAiC;AACvD,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,wBAAkB,aAAa;AAC/B,aAAO,WAAW,YAAY;AAC5B,cAAM,cAAc,MAAM,0BAA0B,MAAM;AAC1D,cAAM,UAAU,YAAY,IAAI,OAAO;AACvC,YAAI,CAAC,QAAS,QAAO,CAAC;AAEtB,cAAM,YAAsC;AAAA,UAC1C,WAAW,SAAS,aAAa;AAAA,UACjC,qBAAqB,SAAS,uBAAuB;AAAA,UACrD,uBAAuB,SAAS,yBAAyB;AAAA,UACzD,mBAAmB,SAAS,qBAAqB;AAAA,QACnD;AAEA,cAAM,SAA4B,CAAC;AACnC,mBAAW,CAAC,OAAO,IAAI,KAAK,SAAS;AACnC,cAAI,CAAC,SAAS,iBAAiB,mBAAmB,OAAO,MAAM,SAAS,GAAG;AACzE;AAAA,UACF;AACA,iBAAO,KAAK;AAAA,YACV;AAAA,YACA,MAAM,KAAK;AAAA,YACX,OAAO,KAAK;AAAA,YACZ,WAAW,KAAK;AAAA,YAChB,SAAS,KAAK;AAAA,YACd,aAAa,KAAK;AAAA,UACpB,CAAC;AAAA,QACH;AACA,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,IACA,CAAC,QAAQ,mBAAmB,UAAU;AAAA,EACxC;AAEA,QAAM,iBAAa,2BAAY,YAAY;AACzC,QAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,WAAO,WAAW,YAAY,OAAO,MAAM,QAAQ,QAAQ,OAAO,WAAW,CAAC,CAAC,CAAC;AAAA,EAClF,GAAG,CAAC,QAAQ,UAAU,CAAC;AAEvB,QAAMC,sCAAiC;AAAA,IACrC,OAAO,SAAiD;AACtD,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,wBAAkB,gCAAgC;AAClD,aAAO,WAAW,MAAM,+BAAmC,QAAQ,IAAI,CAAC;AAAA,IAC1E;AAAA,IACA,CAAC,QAAQ,mBAAmB,UAAU;AAAA,EACxC;AAEA,QAAM,yBAAqB;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,GAAG,yBAAyB,GAAG,aAAa;AACxF,aAAO,WAAW,YAAa,MAAM,KAAK,MAAM,CAAwB;AAAA,IAC1E;AAAA,IACA,CAAC,QAAQ,UAAU;AAAA,EACrB;AAEA,QAAM,0BAAsB;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,GAAG,yBAAyB,GAAG,aAAa;AACxF,aAAO,WAAW,YAAa,MAAM,KAAK,OAAO,MAAM,CAA6B;AAAA,IACtF;AAAA,IACA,CAAC,QAAQ,UAAU;AAAA,EACrB;AAEA,aAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,gCAAAA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACAA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;ACtSA,IAAAC,gBAAqC;AAa9B,SAAS,2BAA2D;AACzE,QAAM,cAAc,wBAAwB;AAE5C,QAAM,uBAAmB;AAAA,IACvB,YACE,YAAY,YAAY;AACtB,YAAM,OAAO,MAAM,MAAM,WAAW;AACpC,aAAO;AAAA,IACT,CAAC;AAAA,IACH,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,sBAAkB;AAAA,IACtB,OAAO,QAAgB,YAAY,MAAM,QAAQ,QAAQ,MAAM,UAAU,GAAG,CAAC,CAAC;AAAA,IAC9E,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,sBAAkB;AAAA,IACtB,OAAO,KAAa,UAAmB;AACrC,YAAM,YAAY,MAAM,QAAQ,QAAQ,MAAM,UAAU,KAAK,KAAK,CAAC,CAAC;AAAA,IACtE;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,uBAAmB;AAAA,IACvB,OAAO,SAAkC;AACvC,YAAM,YAAY,MAAM,QAAQ,QAAQ,MAAM,WAAW,IAAI,CAAC,CAAC;AAAA,IACjE;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,yBAAqB;AAAA,IACzB,OAAO,UAAmC;AACxC,YAAM,YAAY,YAAY;AAC5B,cAAM,UAAW,MAAM,MAAM,WAAW;AACxC,cAAM,MAAM,WAAW,EAAE,GAAI,WAAW,CAAC,GAAI,GAAG,MAAM,CAAC;AAAA,MACzD,CAAC;AAAA,IACH;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,yBAAqB;AAAA,IACzB,YAAY;AACV,YAAM,YAAY,MAAM,QAAQ,QAAQ,MAAM,aAAa,CAAC,CAAC;AAAA,IAC/D;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,aAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AC/EA,IAAAC,iBAAqC;AAU9B,SAAS,kBAAyC;AACvD,QAAM,cAAc,wBAAwB;AAE5C,QAAM,wBAAoB;AAAA,IACxB,OAAO,QAAwB;AAC7B,UAAI,CAAC,MAAM,aAAc,OAAM,IAAI,MAAM,qDAAqD;AAC9F,YAAM,YAAY,MAAM,QAAQ,QAAQ,MAAM,aAAc,GAAG,CAAC,CAAC;AAAA,IACnE;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,4BAAwB;AAAA,IAC5B,OAAO,WAA4B;AACjC,UAAI,CAAC,MAAM,gBAAiB,OAAM,IAAI,MAAM,wDAAwD;AACpG,YAAM,YAAY,MAAM,QAAQ,QAAQ,MAAM,gBAAiB,MAAM,CAAC,CAAC;AAAA,IACzE;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,aAAO;AAAA,IACL,OAAO,EAAE,mBAAmB,sBAAsB;AAAA,IAClD,CAAC,mBAAmB,qBAAqB;AAAA,EAC3C;AACF;;;ACjCA,IAAAC,iBAAuD;AAmChD,SAAS,wBAAwB,QAA2D;AACjG,QAAM,cAAc,wBAAwB;AAC5C,QAAM,CAAC,WAAW,YAAY,QAAI,yBAAwB,IAAI;AAC9D,QAAM,mBAAe,uBAAsB,IAAI;AAE/C,QAAM,iBAAa;AAAA,IACjB,OAAU,OAAqC;AAC7C,UAAI;AACF,cAAM,SAAS,MAAM,YAAY,EAAE;AACnC,YAAI,aAAa,YAAY,MAAM;AACjC,uBAAa,UAAU;AACvB,uBAAa,IAAI;AAAA,QACnB;AACA,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,cAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,YAAI,0BAA0B,GAAG,GAAG;AAClC,cAAI,aAAa,YAAY,KAAK;AAChC,yBAAa,UAAU;AACvB,yBAAa,GAAG;AAAA,UAClB;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,uBAAmB;AAAA,IACvB,OAAO,cAAsB,SAAkC;AAC7D,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,aAAO,WAAW,MAAM,yBAA6B,QAAQ,cAAc,IAAI,CAAC;AAAA,IAClF;AAAA,IACA,CAAC,QAAQ,UAAU;AAAA,EACrB;AAEA,QAAMC,6BAAwB;AAAA,IAC5B,OAAO,cAAsB,SAAkC;AAC7D,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,aAAO,WAAW,MAAM,sBAA0B,QAAQ,cAAc,IAAI,CAAC;AAAA,IAC/E;AAAA,IACA,CAAC,QAAQ,UAAU;AAAA,EACrB;AAEA,QAAMC,2BAAsB;AAAA,IAC1B,OAAO,cAAsB,SAAkC;AAC7D,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,aAAO,WAAW,MAAM,oBAAwB,QAAQ,cAAc,IAAI,CAAC;AAAA,IAC7E;AAAA,IACA,CAAC,QAAQ,UAAU;AAAA,EACrB;AAEA,QAAM,qBAAiB;AAAA,IACrB,OAAO,SAAkC;AACvC,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,aAAO,WAAW,MAAM,oBAAoB,QAAQ,IAAI,CAAC;AAAA,IAC3D;AAAA,IACA,CAAC,QAAQ,UAAU;AAAA,EACrB;AAEA,QAAM,oBAAgB;AAAA,IACpB,CAAC,MAAc,SAAgD;AAC7D,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,aAAO,WAAW,MAAM,mBAAuB,QAAQ,MAAM,IAAI,CAAC;AAAA,IACpE;AAAA,IACA,CAAC,QAAQ,UAAU;AAAA,EACrB;AAEA,QAAM,uBAAmB;AAAA,IACvB,CAAC,MAAmB,SAAiC;AACnD,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oBAAoB;AACjD,aAAO,WAAW,MAAM,sBAA0B,QAAQ,MAAM,IAAI,CAAC;AAAA,IACvE;AAAA,IACA,CAAC,QAAQ,UAAU;AAAA,EACrB;AAEA,aAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA,uBAAAD;AAAA,MACA,qBAAAC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,MACAD;AAAA,MACAC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;ACnIA,IAAAC,iBAA6C;;;ACMtC,SAAS,uBAAuB,SAAyC;AAC9E,MAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAM,MAAM;AACZ,QAAM,MAAM,IAAI;AAChB,MAAI,QAAQ,WAAW,QAAQ,OAAQ,QAAO;AAC9C,MAAI,OAAO,OAAO,QAAQ,UAAU;AAClC,UAAM,aAAc,IAAgC;AACpD,QAAI,eAAe,WAAW,eAAe,OAAQ,QAAO;AAAA,EAC9D;AACA,SAAO;AACT;;;ADLO,SAAS,cAAc,SAAkD;AAC9E,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAA4B,IAAI;AAE1D,gCAAU,MAAM;AACd,QAAI,OAAO,UAAU,eAAe,OAAO,MAAM,OAAO,WAAY;AAEpE,UAAM,QAAQ,CAAC,YAAqB;AAClC,YAAM,OAAO,uBAAuB,OAAO;AAC3C,UAAI,KAAM,UAAS,IAAI;AAAA,IACzB;AAEA,UAAM,GAAG,WAAW,CAAC,QAAiB;AACpC,UAAI,CAAC,OAAO,OAAO,QAAQ,SAAU;AACrC,UAAI,EAAE,WAAW,KAAM;AACvB,YAAM,GAAG;AAAA,IACX,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,aAAO,wBAAQ,OAAO,EAAE,MAAM,IAAI,CAAC,KAAK,CAAC;AAC3C;;;AE9BA,IAAAC,iBAAqC;AAU9B,SAAS,qBAA+C;AAC7D,QAAM,cAAc,wBAAwB;AAE5C,QAAM,gBAAY;AAAA,IAChB,OAAO,SAA4B;AACjC,UAAI,CAAC,MAAM,YAAY,WAAW;AAChC,cAAM,IAAI,MAAM,mEAAmE;AAAA,MACrF;AACA,YAAM,YAAY,MAAM,QAAQ,QAAQ,MAAM,WAAY,UAAW,IAAI,CAAC,CAAC;AAAA,IAC7E;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,sBAAkB;AAAA,IACtB,YAAY;AACV,UAAI,CAAC,MAAM,YAAY,UAAU;AAC/B,cAAM,IAAI,MAAM,kEAAkE;AAAA,MACpF;AACA,aAAO,YAAY,MAAM,MAAM,WAAY,SAAU,CAAC;AAAA,IACxD;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,aAAO,wBAAQ,OAAO,EAAE,WAAW,gBAAgB,IAAI,CAAC,WAAW,eAAe,CAAC;AACrF;;;AZgBO,SAAS,4BACd,SAC2B;AAC3B,QAAM,OAAO,aAAa,OAAO;AACjC,QAAM,eAAe,qBAAqB,KAAK,MAAM;AACrD,QAAM,YAAY,8BAA8B,KAAK,QAAQ,OAAO;AACpE,QAAM,SAAS,sBAAsB,KAAK,MAAM;AAChD,QAAM,QAAQ,cAAc,KAAK,MAAM;AACvC,QAAM,mBAAmB,yBAAyB;AAClD,QAAM,UAAU,gBAAgB;AAChC,QAAM,kBAAkB,wBAAwB,KAAK,MAAM;AAC3D,QAAM,QAAQ,cAAc,KAAK,MAAM;AACvC,QAAM,aAAa,mBAAmB;AAEtC,QAAM,gBAAmC;AAAA,IACvC,OAAO;AAAA,MACL,GAAG;AAAA,MACH,YAAY,aAAa;AAAA,IAC3B;AAAA,IACA,CAAC,MAAM,aAAa,UAAU;AAAA,EAChC;AAEA,QAAM,iBAAiB,SAAS;AAChC,QAAM,gBAAgB,SAAS;AAE/B,aAAO;AAAA,IACL,OAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;ADzCwB;AA7CjB,IAAM,mBAAe,8BAAqC,IAAI;AAgB9D,SAAS,uBAAuB,EAAE,SAAS,SAAS,GAAgC;AACzF,QAAM,SAAS,4BAA4B,OAAO;AAClD,QAAM,iBAAa;AAAA,IACjB,MAAM,2BAA2B,MAAM;AAAA,IACvC;AAAA,MACE,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF;AAEA,SACE,4CAAC,iBAAiB,UAAjB,EAA0B,OAAO,OAAO,MACvC,sDAAC,sBAAsB,UAAtB,EAA+B,OAAO,OAAO,WAC5C,sDAAC,yBAAyB,UAAzB,EAAkC,OAAO,OAAO,cAC/C,sDAAC,mBAAmB,UAAnB,EAA4B,OAAO,OAAO,QACzC,sDAAC,kBAAkB,UAAlB,EAA2B,OAAO,OAAO,OACxC,sDAAC,6BAA6B,UAA7B,EAAsC,OAAO,OAAO,kBACnD,sDAAC,oBAAoB,UAApB,EAA6B,OAAO,OAAO,SAC1C,sDAAC,4BAA4B,UAA5B,EAAqC,OAAO,OAAO,iBAClD,sDAAC,kBAAkB,UAAlB,EAA2B,OAAO,OAAO,OACxC,sDAAC,uBAAuB,UAAvB,EAAgC,OAAO,OAAO,YAC7C,sDAAC,aAAa,UAAb,EAAsB,OAAO,YAAa,UAAS,GACtD,GACF,GACF,GACF,GACF,GACF,GACF,GACF,GACF,GACF;AAEJ;;;AHzBM,IAAAC,sBAAA;AArBC,SAAS,oBAAoB,EAAE,SAAS,SAAS,GAA6B;AAMnF,QAAM,iBAAa,uBAA+B,IAAI;AACtD,MAAI,WAAW,YAAY,MAAM;AAC/B,eAAW,UAAU,4BAA4B,oCAAoC,OAAO,CAAC;AAAA,EAC/F;AACA,QAAM,UAAU,WAAW;AAE3B,gCAAU,MAAM;AACd,YAAQ,MAAM;AACd,WAAO,MAAM;AACX,cAAQ,KAAK;AAAA,IACf;AAAA,EACF,GAAG,CAAC,OAAO,CAAC;AAEZ,SACE,6CAAC,6BAA6B,UAA7B,EAAsC,OAAO,SAC5C,uDAAC,0BAAuB,SAAmB,UAAS,GACtD;AAEJ;AAUO,SAAS,kBAGd;AACA,QAAM,UAAM,2BAAW,YAAY;AACnC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,MAAM,6DAA6D;AAAA,EAC/E;AACA,SAAO,qBAAoC;AAC7C;AAEO,SAAS,mBAEP;AACP,aAAO,2BAAW,YAAY;AAChC;;;AdlEA,SAAS,gBAAgB;AACvB,SAAO,MAAM;AAAA,EAAC;AAChB;AAMO,SAAS,4BACd,QACA,SAC2B;AAC3B,QAAM,cAAc,iBAAiB;AACrC,QAAM,IAAI,UAAU;AACpB,QAAM,UAAU,wBAAwB;AACxC,QAAM,eAAW;AAAA,IACf,SAAS,aAAa;AAAA,IACtB,SAAS,eAAe;AAAA,IACxB;AAAA,EACF;AAEA,QAAM,mBAAmB,SAAS,aAAa,UAAU,WAAW;AAEpE,QAAM,oBAAoB,GAAG;AAC7B,QAAM,YAAY,KAAK,eAAe,IAAK,EAAoC,YAAY;AAC3F,QAAM,cAAc,IAChB;AAAA,IACE,EAAE;AAAA,IACF,EAAE;AAAA,IACF;AAAA,IACA,EAAE;AAAA,IACF,EAAE;AAAA,IACF;AAAA,IACA,EAAE;AAAA,EACJ,IACA;AAEJ,QAAM,oBAAoB,GAAG;AAE7B,aAAO;AAAA,IACL,MACE,IACI,4BAA4B,GAAG;AAAA,MAC7B,GAAG;AAAA,MACH,eAAe,SAAS,iBAAiB;AAAA,MACzC,UAAU;AAAA,IACZ,CAAC,IACD,CAAC;AAAA,IACP,CAAC,aAAa,SAAS,kBAAkB,GAAG,iBAAiB;AAAA,EAC/D;AACF;;;A+B/DA,IAAAC,iBAQO;AA4HD,IAAAC,sBAAA;AA9EN,IAAM,aAA4B;AAAA,EAChC,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,OAAO;AAAA,EACP,SAAS;AAAA,EACT,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,SAAS;AAAA,EACT,OAAO;AACT;AAEA,IAAM,YAA2B;AAAA,EAC/B,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,WAAW;AAAA,EACX,UAAU;AAAA,EACV,SAAS;AAAA,EACT,WAAW;AAAA,EACX,OAAO;AACT;AAEA,IAAM,aAA4B;AAAA,EAChC,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,QAAQ;AACV;AAEA,IAAM,eAA8B;AAAA,EAClC,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,QAAQ;AACV;AAEA,IAAM,cAA6B;AAAA,EACjC,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,SAAS;AACX;AAEA,SAASC,iBAAgB;AACvB,SAAO,MAAM;AAAA,EAAC;AAChB;AAcO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,YAAY;AAAA,EACZ;AAAA,EACA,aAAa;AAAA,EACb,iBAAiB;AACnB,GAA6B;AAC3B,SACE,6CAAC,SAAI,OAAO,YAAY,MAAM,SAAS,UAAU,UAAU,UACzD,wDAAC,SAAI,OAAO,WACV;AAAA,iDAAC,QAAG,OAAO,YAAa,iBAAM;AAAA,IAC9B,6CAAC,OAAE,OAAO,cAAe,mBAAQ;AAAA,IAChC,aAAa,UACZ;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,QAAQ;AAAA,QAClB,SAAS,MAAM,KAAK,QAAQ,OAAO;AAAA,QACnC,OAAO;AAAA,UACL,GAAG;AAAA,UACH,QAAQ,QAAQ,cAAc,gBAAgB;AAAA,UAC9C,SAAS,QAAQ,cAAc,MAAM;AAAA,QACvC;AAAA,QACA,MAAK;AAAA,QAEJ,kBAAQ,cAAc,iBAAiB;AAAA;AAAA,IAC1C,IACE;AAAA,KACN,GACF;AAEJ;AAEA,SAAS,cAAc,EAAE,QAAQ,GAAwB;AACvD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA;AAAA,EACb;AAEJ;AAEA,SAAS,uBACP,MACA,SACW;AACX,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,KAAK;AAAA,MACZ,SAAS,KAAK;AAAA,MACd,MAAM,KAAK,SAAS,UAAU,UAAU;AAAA,MACxC,WAAW,KAAK;AAAA,MAChB;AAAA,MACA,YAAY,KAAK,SAAS,UAAU,cAAc;AAAA,MAClD,gBAAgB,KAAK,SAAS,UAAU,mBAAc;AAAA;AAAA,EACxD;AAEJ;AAEA,SAAS,yBACP,GACA,SACkB;AAClB,MAAI,EAAE,WAAW,eAAe;AAC9B,WACE;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,SAAQ;AAAA,QACR,WAAS;AAAA,QACT;AAAA;AAAA,IACF;AAAA,EAEJ;AACA,MAAI,EAAE,WAAW,SAAS;AACxB,WACE;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,SACE,EAAE,SACF;AAAA,QAEF,MAAK;AAAA,QACL,WAAS;AAAA,QACT;AAAA,QACA,YAAW;AAAA,QACX,gBAAe;AAAA;AAAA,IACjB;AAAA,EAEJ;AACA,MAAI,EAAE,WAAW,SAAS;AACxB,WAAO,6CAAC,iBAAc,SAAQ,6BAAuB;AAAA,EACvD;AACA,SAAO;AACT;AAaO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,qBAAqB;AAAA,EACrB;AACF,GAAuB;AACrB,QAAM,cAAc,iBAAiB;AACrC,QAAM,IAAI,UAAU;AACpB,QAAM,UAAU,wBAAwB;AACxC,QAAM,eAAW;AAAA,IACf,SAAS,aAAaA;AAAA,IACtB,SAAS,eAAe;AAAA,IACxB;AAAA,EACF;AAEA,MAAI,CAAC,GAAG;AACN,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,mBAAe;AAAA,IACnB,MAAO,UAAU,mBAAmB,QAAQ,IAAI;AAAA,IAChD,CAAC,SAAS,QAAQ;AAAA,EACpB;AAEA,QAAM,CAAC,iBAAiB,kBAAkB,QAAI,yBAAS,KAAK;AAC5D,QAAM,CAAC,aAAa,cAAc,QAAI,yBAAS,KAAK;AAEpD,gCAAU,MAAM;AACd,QAAI,EAAE,WAAW,eAAe;AAC9B,yBAAmB,KAAK;AACxB;AAAA,IACF;AACA,UAAM,QAAQ,OAAO,WAAW,MAAM,mBAAmB,IAAI,GAAG,kBAAkB;AAClF,WAAO,MAAM,OAAO,aAAa,KAAK;AAAA,EACxC,GAAG,CAAC,oBAAoB,EAAE,MAAM,CAAC;AAEjC,QAAM,aAAS,4BAAY,YAAY;AACrC,UAAM,2BAA2B;AACjC,UAAM,YAAY,KAAK,IAAI;AAC3B,mBAAe,IAAI;AACnB,QAAI;AACF,YAAM,EAAE,OAAO;AAAA,IACjB,SAAS,OAAO;AACd,cAAQ,MAAM,8BAA8B,KAAK;AAAA,IACnD,UAAE;AACA,YAAM,UAAU,KAAK,IAAI,IAAI;AAC7B,YAAM,YAAY,KAAK,IAAI,GAAG,2BAA2B,OAAO;AAChE,UAAI,YAAY,GAAG;AACjB,cAAM,IAAI,QAAQ,CAAC,YAAY,OAAO,WAAW,SAAS,SAAS,CAAC;AAAA,MACtE;AACA,qBAAe,KAAK;AAAA,IACtB;AAAA,EACF,GAAG,CAAC,CAAC,CAAC;AAEN,QAAM,cAAU;AAAA,IACd,OAAO,EAAE,QAAQ,YAAY;AAAA,IAC7B,CAAC,aAAa,MAAM;AAAA,EACtB;AAEA,QAAM,YACJ,SAAS,eAAe,CAAC,WAAW,mBAAmB,QAAQ,EAAE;AAEnE,QAAM,mBACJ;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,8BAA8B;AAAA,MACrC,SAAS,8BAA8B;AAAA,MACvC,WAAW;AAAA;AAAA,EACb;AAGF,MAAI,CAAC,SAAS;AACZ,UAAM,SAAS,yBAAyB,GAAG,OAAO;AAClD,QAAI,OAAQ,QAAO,6EAAG,kBAAO;AAC7B,QAAI,CAAC,UAAW,QAAO,6EAAG,+BAAqB,kBAAiB;AAChE,WAAO,6EAAG,UAAS;AAAA,EACrB;AAEA,MAAI,EAAE,WAAW,eAAe;AAC9B,QAAI,CAAC,iBAAiB;AACpB,YAAM,OACJ,cAAc,SAAS,cAAc,aAAa,SAAS,YACvD,aAAa,UACb;AACN,aAAO,6EAAG,6BAAmB,6CAAC,iBAAc,SAAS,MAAM,GAAG;AAAA,IAChE;AACA,QAAI,OAAO,wBAAwB,YAAY;AAC7C,aAAO,6EAAG,8BAAoB,OAAO,GAAE;AAAA,IACzC;AACA,QAAI,oBAAqB,QAAO,6EAAG,+BAAoB;AACvD,QAAI,cAAc,SAAS,YAAY;AACrC,aAAO,6EAAG,iCAAuB,cAAc,OAAO,GAAE;AAAA,IAC1D;AAAA,EACF;AAEA,MAAI,EAAE,WAAW,SAAS;AACxB,QAAI,eAAe;AACjB,aAAO,6EAAG,wBAAc,EAAE,SAAS,0BAA0B,OAAO,GAAE;AAAA,IACxE;AACA,QAAI,cAAc,SAAS,YAAY;AACrC,aAAO,6EAAG,iCAAuB,cAAc,OAAO,GAAE;AAAA,IAC1D;AAAA,EACF;AAEA,MAAI,EAAE,WAAW,SAAS;AACxB,QAAI,cAAc,SAAS,cAAc,aAAa,SAAS,WAAW;AACxE,aACE,6EACG,6BAAmB,6CAAC,iBAAc,SAAS,aAAa,SAAS,GACpE;AAAA,IAEJ;AACA,WAAO,6EAAG,6BAAmB,6CAAC,iBAAc,SAAQ,6BAAuB,GAAG;AAAA,EAChF;AAEA,MAAI,CAAC,WAAW;AACd,WAAO,6EAAG,+BAAqB,kBAAiB;AAAA,EAClD;AAEA,SAAO,6EAAG,UAAS;AACrB;;;ACjWA,IAAAC,iBAAwB;AAExB,IAAAA,iBAA2B;AA4B3B,SAAS,mBACP,SAC+B;AAC/B,QAAM,SAAS,4BAA4B,OAAO;AAClD,aAAO,wBAAQ,MAAM,2BAA0C,MAAM,GAAG,CAAC,MAAM,CAAC;AAClF;AAMO,SAAS,SACd,SAC+B;AAC/B,UAAI,2BAAW,gBAAgB,GAAG;AAChC,WAAO,qBAAoC;AAAA,EAC7C;AACA,SAAO,mBAAkC,OAAO;AAClD;AAWO,SAAS,iBAAwC;AACtD,QAAM,OAAO,oBAAoB;AACjC,QAAM,eAAe,4BAA4B;AACjD,aAAO,wBAAQ,OAAO,EAAE,GAAG,MAAM,GAAG,aAAa,IAAI,CAAC,MAAM,YAAY,CAAC;AAC3E;AAMO,SAAS,oBAAuF;AACrG,SAAO,yBAAwC;AACjD;AAMO,SAAS,iBAAiB;AAC/B,SAAO,sBAAsB;AAC/B;AAKO,SAASC,iBAAgB;AAC9B,SAAO,qBAAqB;AAC9B;;;ACtFA,IAAAC,iBAAsE;;;ACsB/D,SAAS,cAAc,SAAqD;AACjF,QAAM,EAAE,aAAa,QAAQ,OAAO,OAAO,IAAI,aAAa,OAAO;AACnE,SAAO,EAAE,aAAa,QAAQ,OAAO,OAAO;AAC9C;;;ADiDA,SAAS,6BACPC,WACA,SACA,oBACsB;AACtB,SAAO;AAAA,IACL,GAAGA;AAAA,IACH,QAAQ,OAAO;AAAA,MACb,OAAO,QAAQA,UAAS,MAAM,EAAE,IAAI,CAAC,CAAC,SAAS,KAAK,MAAM;AAAA,QACxD;AAAA,QACA;AAAA,UACE,GAAG;AAAA,UACH,SAAS,OAAO;AAAA,YACd,OAAO,QAAQ,MAAM,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,OAAO,GAAG,MAAM;AAC3D,kBAAI,mBAAmB,OAAO,KAAK,OAAO,EAAG,QAAO;AACpD,kBAAI,qBAAqB,EAAE,SAAS,OAAO,IAAI,CAAC,EAAG,QAAO;AAC1D,qBAAO;AAAA,YACT,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAKO,SAAS,eAAe,SAAuD;AACpF,QAAM,iBAAiB,SAAS,kBAAkB;AAClD,QAAM,mBAAmB,SAAS;AAClC,QAAM,yBAAyB,SAAS,0BAA0B;AAClE,QAAM,iBAAiB,SAAS,kBAAkB;AAClD,QAAM,iBAAiB,SAAS,kBAAkB;AAClD,QAAM,gBAAgB,SAAS;AAC/B,QAAM,YAAY,SAAS,aAAa;AACxC,QAAM,sBAAsB,SAAS,uBAAuB;AAC5D,QAAM,wBAAwB,SAAS,yBAAyB;AAChE,QAAM,oBAAoB,SAAS,qBAAqB;AACxD,QAAM,qBAAqB,SAAS;AAEpC,QAAM,EAAE,aAAa,QAAQ,OAAO,WAAW,IAAI,cAAc;AAAA,IAC/D;AAAA,IACA,SAAS,SAAS;AAAA,IAClB,eAAe,SAAS;AAAA,IACxB,kBAAkB,SAAS;AAAA,IAC3B,eAAe,SAAS;AAAA,EAC1B,CAAC;AAKD,QAAM,2BAAuB,2BAAW,iBAAiB,GAAG;AAE5D,QAAM,CAACA,WAAU,WAAW,QAAI,yBAAsC,IAAI;AAC1E,QAAM,CAAC,SAAS,UAAU,QAAI,yBAAS,KAAK;AAC5C,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAwB,IAAI;AAEtD,QAAM,sBACJ,mBAAmB,gBAAgB,QAAQ,mBAAmB,gBAAgB,SAAS;AAEzF,QAAM,WAAO,4BAAY,YAAY;AACnC,QAAI,CAAC,OAAQ;AACb,eAAW,IAAI;AACf,aAAS,IAAI;AACb,QAAI;AACF,YAAM,YAAY;AAAA,QAChB,wBAAwB,CAAC;AAAA,QACzB,aAAa;AAAA,QACb;AAAA,QACA,QAAQ;AAAA,MACV;AACA,YAAM,MAAM,uBACR,MAAM,qBAAqB,SAAS,IACpC,MAAM,+BAA+B,QAAQ,SAAS;AAC1D,YAAM,WAAW;AAAA,QACf;AAAA,QACA;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,MACF;AACA,kBAAY,QAAQ;AAAA,IACtB,SAAS,KAAK;AACZ,kBAAY,IAAI;AAChB,eAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAC3D,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,gCAAU,MAAM;AACd,QAAI,OAAQ,MAAK,KAAK;AAAA,EACxB,GAAG,CAAC,QAAQ,IAAI,CAAC;AAEjB,QAAM,wBAAoB,4BAAY,CAAC,QAA8BC,aAAiD;AACpH,UAAM,cAAcA,UAAS,eAAe;AAC5C,UAAM,QAAQA,UAAS,SAAS;AAChC,UAAM,UAAU,wBAAwB,QAAQ;AAAA,MAC9C;AAAA,MACA,gBAAgBA,UAAS,kBAAkB;AAAA,IAC7C,CAAC;AACD,WAAO,KAAK,UAAU,SAAS,MAAM,KAAK;AAAA,EAC5C,GAAG,CAAC,cAAc,CAAC;AAEnB,QAAM,sBAAkB;AAAA,IACtB,CAACA,aAAwD;AACvD,UAAI,CAACD,UAAU,QAAO;AACtB,aAAO,kBAAkBA,WAAUC,QAAO;AAAA,IAC5C;AAAA,IACA,CAACD,WAAU,iBAAiB;AAAA,EAC9B;AAEA,QAAM,YAAQ,wBAAQ,MAAmC;AACvD,QAAI,CAACA,aAAY,CAAC,iBAAkB,QAAO;AAC3C,UAAM,QAAQA,UAAS,OAAO,gBAAgB;AAC9C,QAAI,CAAC,MAAO,QAAO;AACnB,WAAO,EAAE,SAAS,kBAAkB,GAAG,MAAM;AAAA,EAC/C,GAAG,CAACA,WAAU,gBAAgB,CAAC;AAE/B,QAAM,qBAAiB;AAAA,IACrB,CAAC,QAA8BC,aAAiD;AAC9E,YAAM,cAAcA,UAAS,eAAe;AAC5C,YAAM,QAAQA,UAAS,kBAAkB;AACzC,YAAM,QAAQA,UAAS,SAAS;AAChC,YAAM,EAAE,SAAS,GAAG,KAAK,IAAI;AAC7B,UAAI,OAA0B,EAAE,GAAG,KAAK;AACxC,UAAI,gBAAgB,QAAQ;AAC1B,cAAM,EAAE,MAAM,IAAI,GAAG,EAAE,IAAI;AAC3B,eAAO;AAAA,MACT,WAAW,gBAAgB,WAAW;AACpC,cAAM,IAAI,KAAK,QAAQ,CAAC;AACxB,eAAO,EAAE,GAAG,MAAM,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE;AAAA,MAC5C;AACA,aAAO,KAAK,UAAU,EAAE,SAAS,GAAG,KAAK,GAAG,MAAM,KAAK;AAAA,IACzD;AAAA,IACA,CAAC,cAAc;AAAA,EACjB;AAEA,QAAM,mBAAe;AAAA,IACnB,CAACA,aAAwD;AACvD,UAAI,CAAC,MAAO,QAAO;AACnB,aAAO,eAAe,OAAOA,QAAO;AAAA,IACtC;AAAA,IACA,CAAC,OAAO,cAAc;AAAA,EACxB;AAEA,QAAM,yBAAqB;AAAA,IACzB,CAAC,OAAe,QACd,mBAAmB,OAAO,KAAK;AAAA,MAC7B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IACH,CAAC,WAAW,qBAAqB,uBAAuB,iBAAiB;AAAA,EAC3E;AAEA,QAAM,kBAAc,4BAAY,CAAC,QAAkB,YAA0D;AAC3G,WAAO,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM;AAChC,YAAM,MAAM,QAAQ,CAAC,GAAG,SAAS,GAAG,YAAY;AAChD,YAAM,MAAM,QAAQ,CAAC,GAAG,SAAS,GAAG,YAAY;AAChD,UAAI,OAAO,GAAI,QAAO,GAAG,cAAc,EAAE;AACzC,aAAO,EAAE,cAAc,CAAC;AAAA,IAC1B,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL;AAAA,IACA,UAAAD;AAAA,IACA,iBAAiBA;AAAA,IACjB;AAAA,IACA,cAAcA,YAAW,kBAAkBA,SAAQ,IAAI;AAAA,IACvD;AAAA,IACA;AAAA,IACA,WAAW,QAAQ,eAAe,KAAK,IAAI;AAAA,IAC3C;AAAA,IACA;AAAA,IACA,iBAAiB;AAAA,IACjB,eAAe;AAAA,IACf;AAAA,IACA,OAAO,cAAc;AAAA,IACrB,QAAQ;AAAA,EACV;AACF;;;AEjRA,IAAAE,iBAAkE;AA+BlE,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;AAmBO,SAAS,iCACd,QAC2C;AAC3C,QAAM,aAAa,OAAO,cAAc;AACxC,QAAM,YAAY,yBAAyB;AAC3C,QAAM,aAAa,gCAAgC;AAEnD,QAAM,kBAAc,uBAAO,OAAO,QAAQ;AAC1C,gCAAU,MAAM;AACd,gBAAY,UAAU,OAAO;AAAA,EAC/B,GAAG,CAAC,OAAO,QAAQ,CAAC;AAEpB,QAAM,aAAa,UAAU;AAC7B,QAAM,cAAc,eAAe;AAEnC,QAAM,aAAS;AAAA,IACb,MAAM,kBAAkB,YAAY,SAAS,YAAY,OAAO,SAAS;AAAA,IACzE,CAAC,YAAY,OAAO,SAAS;AAAA,EAC/B;AAEA,QAAM,CAAC,eAAe,gBAAgB,QAAI,yBAAmB,IAAI;AACjE,QAAM,UAAU,iBAAiB;AAEjC,gCAAU,MAAM;AACd,qBAAiB,IAAI;AAAA,EACvB,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,kBAAc,uBAAsB,IAAI;AAE9C,QAAM,iBAAa;AAAA,IACjB,OAAO,UAAa;AAClB,UAAI,OAAO,WAAW;AACpB,cAAM,WAAW,gBAAgB,OAAO,WAAW,KAAK;AAAA,MAC1D,OAAO;AACL,cAAM,WAAW,iBAAiB,EAAE,GAAG,MAAM,CAAC;AAAA,MAChD;AAAA,IACF;AAAA,IACA,CAAC,OAAO,WAAW,UAAU;AAAA,EAC/B;AAEA,QAAM,oBAAgB;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,gCAAU,MAAM;AACd,WAAO,MAAM;AACX,UAAI,YAAY,QAAS,QAAO,aAAa,YAAY,OAAO;AAAA,IAClE;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,iBAAa;AAAA,IACjB,CAAC,SAAY;AACX,uBAAiB,IAAI;AACrB,oBAAc,IAAI;AAAA,IACpB;AAAA,IACA,CAAC,aAAa;AAAA,EAChB;AAEA,QAAM,mBAAe;AAAA,IACnB,CAAC,UAAsB;AACrB,uBAAiB,CAAC,SAAS;AACzB,cAAM,OAAO,QAAQ;AACrB,cAAM,OAAO,EAAE,GAAG,MAAM,GAAG,MAAM;AACjC,sBAAc,IAAI;AAClB,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,IACA,CAAC,QAAQ,aAAa;AAAA,EACxB;AAEA,QAAM,YAAQ,4BAAY,YAAY;AACpC,QAAI,YAAY,SAAS;AACvB,aAAO,aAAa,YAAY,OAAO;AACvC,kBAAY,UAAU;AAAA,IACxB;AACA,UAAM,OAAO,EAAE,GAAG,YAAY,QAAQ;AACtC,qBAAiB,IAAI;AACrB,UAAM,WAAW,IAAI;AAAA,EACvB,GAAG,CAAC,UAAU,CAAC;AAEf,aAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA,SAAS,CAAC;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,SAAS,aAAa,YAAY,cAAc,KAAK;AAAA,EACxD;AACF;;;ACxJA,IAAAC,iBAA0B;AAQnB,SAAS,kBAAkB,OAAuC;AACvE,gCAAU,MAAM;AACd,QAAI,CAAC,MAAO;AAEZ,UAAM,EAAE,OAAO,aAAa,eAAe,KAAK,IAAI;AACpD,UAAM,eAAe,OAAO,SAAS;AAErC,aAAS,QAAQ;AACjB,eAAW,QAAQ,SAAS,KAAK;AACjC,eAAW,QAAQ,eAAe,WAAW;AAC7C,eAAW,YAAY,YAAY,KAAK;AACxC,eAAW,YAAY,kBAAkB,WAAW;AACpD,eAAW,YAAY,WAAW,SAAS;AAC3C,eAAW,YAAY,UAAU,YAAY;AAC7C,eAAW,QAAQ,gBAAgB,SAAS;AAC5C,eAAW,QAAQ,iBAAiB,KAAK;AACzC,eAAW,QAAQ,uBAAuB,WAAW;AAErD,QAAI,CAAC,aAAc;AACnB,WAAO,QAAQ;AAAA,MACb;AAAA,QACE,QAAQ;AAAA,QACR,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF,GAAG,CAAC,KAAK,CAAC;AACZ;AAEA,SAAS,WAAW,KAA0B,OAAe,SAAiB;AAC5E,MAAI,OAAO,SAAS,KAAK;AAAA,IACvB,QAAQ,GAAG,KAAK,KAAK;AAAA,EACvB;AACA,MAAI,CAAC,MAAM;AACT,WAAO,SAAS,cAAc,MAAM;AACpC,SAAK,aAAa,KAAK,KAAK;AAC5B,aAAS,KAAK,YAAY,IAAI;AAAA,EAChC;AACA,OAAK,aAAa,WAAW,OAAO;AACtC;;;AC0RO,IAAM,+BAA+B;","names":["computeRowCount","sortRowsByGristOrder","useGristTheme","computeRowCount","manualSortKey","sortRowsByGristOrder","computeRowCount","nextAuthz","import_react","ACCESS_RANK","inFlight","grist","grist","inFlight","embedded","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_react","out","import_react","import_react","buildReplicaDocumentFromDocApi","import_react","import_react","import_react","fetchAttachmentBase64","fetchAttachmentBlob","import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","noopSubscribe","import_react","useGristTheme","import_react","document","options","import_react","import_react"]}