grist-widget-sdk 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/CHANGELOG.md +730 -0
  2. package/LICENSE +15 -0
  3. package/README.md +249 -0
  4. package/dist/advanced.cjs +2749 -0
  5. package/dist/advanced.cjs.map +1 -0
  6. package/dist/advanced.d.cts +790 -0
  7. package/dist/advanced.d.ts +790 -0
  8. package/dist/advanced.js +825 -0
  9. package/dist/advanced.js.map +1 -0
  10. package/dist/chunk-64SVRWW7.js +758 -0
  11. package/dist/chunk-64SVRWW7.js.map +1 -0
  12. package/dist/chunk-BNBV24WM.js +479 -0
  13. package/dist/chunk-BNBV24WM.js.map +1 -0
  14. package/dist/chunk-ELGVOHFD.js +32 -0
  15. package/dist/chunk-ELGVOHFD.js.map +1 -0
  16. package/dist/chunk-GTTD5HPO.js +36 -0
  17. package/dist/chunk-GTTD5HPO.js.map +1 -0
  18. package/dist/chunk-JASMM2YC.js +243 -0
  19. package/dist/chunk-JASMM2YC.js.map +1 -0
  20. package/dist/chunk-PM3B4WYV.js +12 -0
  21. package/dist/chunk-PM3B4WYV.js.map +1 -0
  22. package/dist/chunk-QKXKZ27D.js +1189 -0
  23. package/dist/chunk-QKXKZ27D.js.map +1 -0
  24. package/dist/chunk-QZG7SNUG.js +463 -0
  25. package/dist/chunk-QZG7SNUG.js.map +1 -0
  26. package/dist/chunk-REV5AUXD.js +25 -0
  27. package/dist/chunk-REV5AUXD.js.map +1 -0
  28. package/dist/chunk-XE2SKNLH.js +1641 -0
  29. package/dist/chunk-XE2SKNLH.js.map +1 -0
  30. package/dist/create-grist-emulator-C_0I4wax.d.ts +80 -0
  31. package/dist/create-grist-emulator-DBS6gmiI.d.cts +80 -0
  32. package/dist/emulator/devtools.cjs +1367 -0
  33. package/dist/emulator/devtools.cjs.map +1 -0
  34. package/dist/emulator/devtools.d.cts +46 -0
  35. package/dist/emulator/devtools.d.ts +46 -0
  36. package/dist/emulator/devtools.js +480 -0
  37. package/dist/emulator/devtools.js.map +1 -0
  38. package/dist/emulator/testing.cjs +2061 -0
  39. package/dist/emulator/testing.cjs.map +1 -0
  40. package/dist/emulator/testing.d.cts +50 -0
  41. package/dist/emulator/testing.d.ts +50 -0
  42. package/dist/emulator/testing.js +124 -0
  43. package/dist/emulator/testing.js.map +1 -0
  44. package/dist/emulator/transports.cjs +1132 -0
  45. package/dist/emulator/transports.cjs.map +1 -0
  46. package/dist/emulator/transports.d.cts +37 -0
  47. package/dist/emulator/transports.d.ts +37 -0
  48. package/dist/emulator/transports.js +12 -0
  49. package/dist/emulator/transports.js.map +1 -0
  50. package/dist/emulator.cjs +1796 -0
  51. package/dist/emulator.cjs.map +1 -0
  52. package/dist/emulator.d.cts +107 -0
  53. package/dist/emulator.d.ts +107 -0
  54. package/dist/emulator.js +26 -0
  55. package/dist/emulator.js.map +1 -0
  56. package/dist/index.cjs +5511 -0
  57. package/dist/index.cjs.map +1 -0
  58. package/dist/index.d.cts +825 -0
  59. package/dist/index.d.ts +825 -0
  60. package/dist/index.js +2447 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/inline-CRwQQ-GW.d.cts +311 -0
  63. package/dist/inline-QitZwXKP.d.ts +311 -0
  64. package/dist/templates-BC7FoSdW.d.ts +24 -0
  65. package/dist/templates-DBq719O_.d.cts +24 -0
  66. package/dist/types-Fb2wplkv.d.cts +228 -0
  67. package/dist/types-Fb2wplkv.d.ts +228 -0
  68. package/dist/use-grist-widget-options-from-context-BFhQBGRY.d.ts +522 -0
  69. package/dist/use-grist-widget-options-from-context-qpFMdoBJ.d.cts +522 -0
  70. package/package.json +131 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sdk/helpers/grist-attachment-download.ts","../src/sdk/helpers/grist-attachment-upload.ts","../src/sdk/helpers/grist-schema-formula.ts","../src/sdk/helpers/build-replica-document.ts","../src/sdk/helpers/grist-boundary-view.ts","../src/sdk/helpers/grist-sdk-alerts.ts","../src/sdk/hooks/use-grist-sdk-alert-descriptors.ts","../src/sdk/components/grist-widget-provider.tsx","../src/sdk/internal/grist-widget-context-tree.tsx","../src/sdk/internal/compose-grist-widget.ts","../src/sdk/internal/hooks/use-grist-current-table.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/use-widget-metadata.ts"],"sourcesContent":["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\"\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 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","/**\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 { 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","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, 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, 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","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 { 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":["useMemo","useSyncExternalStore","useEffect","useRef","useMemo","useMemo","useCallback","useEffect","useMemo","useEffect","useMemo","useCallback","out","useCallback","useMemo","useRef","useState","useState","useRef","useCallback","useMemo","useCallback","useMemo","useRef","useState","useState","useRef","useCallback","buildReplicaDocumentFromDocApi","useMemo","useCallback","useMemo","useCallback","useMemo","useCallback","useMemo","useCallback","useMemo","useCallback","useMemo","useRef","useState","useState","useRef","useCallback","fetchAttachmentBase64","fetchAttachmentBlob","useMemo","useEffect","useMemo","useState","useState","useEffect","useMemo","useCallback","useMemo","useCallback","useMemo","useMemo","useMemo","jsx","useRef","useEffect","useSyncExternalStore","useMemo","useCallback","useEffect","useMemo","useState","useSyncExternalStore","jsx","noopSubscribe","useSyncExternalStore","useMemo","useState","useEffect","useCallback","useMemo","useContext","useMemo","useContext","useGristTheme","useCallback","useContext","useEffect","useMemo","useState","document","useContext","useState","useCallback","useEffect","options","useMemo","useEffect"]}